From 89ca28e45b2f99479e74018d3a990031cffb1466 Mon Sep 17 00:00:00 2001 From: Haled Odat <8566042+HalidOdat@users.noreply.github.com> Date: Sun, 15 Oct 2023 23:36:55 +0200 Subject: [PATCH] Implement WIP Ascii JsString --- boa_cli/src/debug/function.rs | 26 +- boa_cli/src/debug/gc.rs | 10 +- boa_cli/src/debug/limits.rs | 5 +- boa_cli/src/debug/mod.rs | 18 +- boa_cli/src/debug/object.rs | 2 +- boa_cli/src/debug/optimizer.rs | 5 +- boa_cli/src/debug/realm.rs | 6 +- boa_cli/src/debug/shape.rs | 6 +- boa_engine/src/builtins/array/mod.rs | 138 +-- boa_engine/src/builtins/array_buffer/mod.rs | 16 +- .../src/builtins/array_buffer/shared.rs | 14 +- .../src/builtins/async_generator/mod.rs | 7 +- boa_engine/src/builtins/bigint/mod.rs | 8 +- boa_engine/src/builtins/boolean/mod.rs | 4 +- boa_engine/src/builtins/dataview/mod.rs | 68 +- boa_engine/src/builtins/date/mod.rs | 148 +-- boa_engine/src/builtins/error/aggregate.rs | 10 +- boa_engine/src/builtins/error/eval.rs | 8 +- boa_engine/src/builtins/error/mod.rs | 22 +- boa_engine/src/builtins/error/range.rs | 8 +- boa_engine/src/builtins/error/reference.rs | 8 +- boa_engine/src/builtins/error/syntax.rs | 8 +- boa_engine/src/builtins/error/type.rs | 12 +- boa_engine/src/builtins/error/uri.rs | 8 +- boa_engine/src/builtins/escape/mod.rs | 8 +- boa_engine/src/builtins/function/mod.rs | 49 +- boa_engine/src/builtins/function/tests.rs | 2 +- boa_engine/src/builtins/generator/mod.rs | 7 +- boa_engine/src/builtins/intl/collator/mod.rs | 54 +- .../src/builtins/intl/date_time_format.rs | 27 +- .../src/builtins/intl/list_format/mod.rs | 34 +- boa_engine/src/builtins/intl/locale/mod.rs | 115 +-- boa_engine/src/builtins/intl/locale/utils.rs | 3 +- boa_engine/src/builtins/intl/mod.rs | 6 +- .../src/builtins/intl/number_format/utils.rs | 19 +- boa_engine/src/builtins/intl/options.rs | 2 +- .../src/builtins/intl/plural_rules/mod.rs | 20 +- .../src/builtins/intl/segmenter/iterator.rs | 31 +- boa_engine/src/builtins/intl/segmenter/mod.rs | 46 +- .../src/builtins/intl/segmenter/segments.rs | 3 +- .../iterable/async_from_sync_iterator.rs | 14 +- boa_engine/src/builtins/iterable/mod.rs | 9 +- boa_engine/src/builtins/json/mod.rs | 30 +- boa_engine/src/builtins/map/map_iterator.rs | 2 +- boa_engine/src/builtins/map/mod.rs | 36 +- boa_engine/src/builtins/math/mod.rs | 92 +- boa_engine/src/builtins/mod.rs | 39 +- boa_engine/src/builtins/number/globals.rs | 7 +- boa_engine/src/builtins/number/mod.rs | 52 +- .../src/builtins/object/for_in_iterator.rs | 3 +- boa_engine/src/builtins/object/mod.rs | 143 ++- boa_engine/src/builtins/options.rs | 2 +- boa_engine/src/builtins/promise/mod.rs | 59 +- boa_engine/src/builtins/proxy/mod.rs | 9 +- boa_engine/src/builtins/reflect/mod.rs | 27 +- boa_engine/src/builtins/regexp/mod.rs | 224 ++--- .../builtins/regexp/regexp_string_iterator.rs | 7 +- boa_engine/src/builtins/set/mod.rs | 34 +- boa_engine/src/builtins/set/set_iterator.rs | 2 +- boa_engine/src/builtins/string/mod.rs | 288 +++--- .../src/builtins/string/string_iterator.rs | 2 +- boa_engine/src/builtins/symbol/mod.rs | 66 +- .../src/builtins/temporal/calendar/iso.rs | 5 +- .../src/builtins/temporal/calendar/mod.rs | 142 ++- .../src/builtins/temporal/duration/mod.rs | 102 +- .../src/builtins/temporal/duration/record.rs | 26 +- boa_engine/src/builtins/temporal/fields.rs | 40 +- .../src/builtins/temporal/instant/mod.rs | 46 +- boa_engine/src/builtins/temporal/mod.rs | 37 +- boa_engine/src/builtins/temporal/now.rs | 17 +- boa_engine/src/builtins/temporal/options.rs | 6 +- .../src/builtins/temporal/plain_date/mod.rs | 84 +- .../builtins/temporal/plain_year_month/mod.rs | 46 +- .../src/builtins/temporal/time_zone/mod.rs | 45 +- .../src/builtins/typed_array/builtin.rs | 90 +- boa_engine/src/builtins/typed_array/mod.rs | 7 +- boa_engine/src/builtins/uri/mod.rs | 25 +- boa_engine/src/builtins/weak/weak_ref.rs | 2 +- boa_engine/src/builtins/weak_map/mod.rs | 13 +- boa_engine/src/builtins/weak_set/mod.rs | 11 +- boa_engine/src/bytecompiler/declarations.rs | 2 +- boa_engine/src/class.rs | 2 +- boa_engine/src/context/intrinsics.rs | 18 +- boa_engine/src/context/mod.rs | 12 +- boa_engine/src/error.rs | 21 +- boa_engine/src/module/mod.rs | 6 +- boa_engine/src/module/synthetic.rs | 4 +- boa_engine/src/object/builtins/jsmap.rs | 3 +- boa_engine/src/object/builtins/jsproxy.rs | 27 +- .../src/object/internal_methods/array.rs | 22 +- .../internal_methods/integer_indexed.rs | 4 +- .../src/object/internal_methods/proxy.rs | 27 +- .../src/object/internal_methods/string.rs | 2 +- boa_engine/src/object/jsobject.rs | 29 +- boa_engine/src/object/mod.rs | 16 +- boa_engine/src/object/operations.rs | 3 +- boa_engine/src/object/property_map.rs | 1 + .../src/optimizer/pass/constant_folding.rs | 6 +- boa_engine/src/property/mod.rs | 10 +- boa_engine/src/string/common.rs | 944 +++++++++--------- boa_engine/src/string/mod.rs | 627 +++++++++--- boa_engine/src/symbol.rs | 6 +- .../src/value/conversions/serde_json.rs | 19 +- boa_engine/src/value/display.rs | 10 +- boa_engine/src/value/tests.rs | 14 +- boa_engine/src/vm/code_block.rs | 5 +- boa_engine/src/vm/flowgraph/mod.rs | 3 +- boa_engine/src/vm/opcode/call/mod.rs | 4 +- boa_engine/src/vm/opcode/concat/mod.rs | 3 +- boa_engine/src/vm/opcode/generator/mod.rs | 9 +- boa_engine/src/vm/opcode/iteration/for_in.rs | 3 +- .../src/vm/opcode/iteration/iterator.rs | 6 +- boa_engine/src/vm/opcode/push/array.rs | 3 +- .../src/vm/opcode/push/class/private.rs | 5 +- boa_engine/src/vm/opcode/set/private.rs | 5 +- boa_engine/src/vm/opcode/set/property.rs | 4 +- boa_engine/src/vm/opcode/templates/mod.rs | 3 +- boa_examples/src/bin/classes.rs | 12 +- boa_examples/src/bin/closures.rs | 15 +- boa_examples/src/bin/jsarray.rs | 7 +- boa_examples/src/bin/jsarraybuffer.rs | 3 +- boa_examples/src/bin/modules.rs | 10 +- boa_examples/src/bin/synthetic.rs | 19 +- boa_runtime/src/console/mod.rs | 92 +- boa_tester/src/exec/js262.rs | 21 +- 125 files changed, 2422 insertions(+), 2527 deletions(-) diff --git a/boa_cli/src/debug/function.rs b/boa_cli/src/debug/function.rs index 9bb2c8ee0f0..6d2ecc25d02 100644 --- a/boa_cli/src/debug/function.rs +++ b/boa_cli/src/debug/function.rs @@ -68,10 +68,8 @@ fn flowgraph(_this: &JsValue, args: &[JsValue], context: &mut Context<'_>) -> Js let mut direction = Direction::LeftToRight; if let Some(arguments) = args.get(1) { if let Some(arguments) = arguments.as_object() { - format = flowgraph_parse_format_option(&arguments.get(js_string!("format"), context)?)?; - direction = flowgraph_parse_direction_option( - &arguments.get(js_string!("direction"), context)?, - )?; + format = flowgraph_parse_format_option(&arguments.get("format", context)?)?; + direction = flowgraph_parse_direction_option(&arguments.get("direction", context)?)?; } else if value.is_string() { format = flowgraph_parse_format_option(value)?; } else { @@ -173,21 +171,9 @@ fn traceable(_: &JsValue, args: &[JsValue], _: &mut Context<'_>) -> JsResult) -> JsObject { ObjectInitializer::new(context) - .function( - NativeFunction::from_fn_ptr(flowgraph), - js_string!("flowgraph"), - 1, - ) - .function( - NativeFunction::from_fn_ptr(bytecode), - js_string!("bytecode"), - 1, - ) - .function(NativeFunction::from_fn_ptr(trace), js_string!("trace"), 1) - .function( - NativeFunction::from_fn_ptr(traceable), - js_string!("traceable"), - 2, - ) + .function(NativeFunction::from_fn_ptr(flowgraph), "flowgraph", 1) + .function(NativeFunction::from_fn_ptr(bytecode), "bytecode", 1) + .function(NativeFunction::from_fn_ptr(trace), "trace", 1) + .function(NativeFunction::from_fn_ptr(traceable), "traceable", 2) .build() } diff --git a/boa_cli/src/debug/gc.rs b/boa_cli/src/debug/gc.rs index 69f3a08cdc7..93c4b625457 100644 --- a/boa_cli/src/debug/gc.rs +++ b/boa_cli/src/debug/gc.rs @@ -1,6 +1,4 @@ -use boa_engine::{ - js_string, object::ObjectInitializer, Context, JsObject, JsResult, JsValue, NativeFunction, -}; +use boa_engine::{object::ObjectInitializer, Context, JsObject, JsResult, JsValue, NativeFunction}; /// Trigger garbage collection. fn collect(_: &JsValue, _: &[JsValue], _: &mut Context<'_>) -> JsResult { @@ -10,10 +8,6 @@ fn collect(_: &JsValue, _: &[JsValue], _: &mut Context<'_>) -> JsResult pub(super) fn create_object(context: &mut Context<'_>) -> JsObject { ObjectInitializer::new(context) - .function( - NativeFunction::from_fn_ptr(collect), - js_string!("collect"), - 0, - ) + .function(NativeFunction::from_fn_ptr(collect), "collect", 0) .build() } diff --git a/boa_cli/src/debug/limits.rs b/boa_cli/src/debug/limits.rs index bfbdda4e613..dfd8f8237b7 100644 --- a/boa_cli/src/debug/limits.rs +++ b/boa_cli/src/debug/limits.rs @@ -1,5 +1,4 @@ use boa_engine::{ - js_string, object::{FunctionObjectBuilder, ObjectInitializer}, property::Attribute, Context, JsArgs, JsNativeError, JsObject, JsResult, JsValue, NativeFunction, @@ -56,13 +55,13 @@ pub(super) fn create_object(context: &mut Context<'_>) -> JsObject { .build(); ObjectInitializer::new(context) .accessor( - js_string!("loop"), + "loop", Some(get_loop), Some(set_loop), Attribute::WRITABLE | Attribute::CONFIGURABLE | Attribute::NON_ENUMERABLE, ) .accessor( - js_string!("recursion"), + "recursion", Some(get_recursion), Some(set_recursion), Attribute::WRITABLE | Attribute::CONFIGURABLE | Attribute::NON_ENUMERABLE, diff --git a/boa_cli/src/debug/mod.rs b/boa_cli/src/debug/mod.rs index 34e82a0ee0d..72a24a2d15a 100644 --- a/boa_cli/src/debug/mod.rs +++ b/boa_cli/src/debug/mod.rs @@ -1,7 +1,7 @@ // Allow lint so it, doesn't warn about `JsResult<>` unneeded return on functions. #![allow(clippy::unnecessary_wraps)] -use boa_engine::{js_string, object::ObjectInitializer, property::Attribute, Context, JsObject}; +use boa_engine::{object::ObjectInitializer, property::Attribute, Context, JsObject}; mod function; mod gc; @@ -22,37 +22,37 @@ fn create_boa_object(context: &mut Context<'_>) -> JsObject { ObjectInitializer::new(context) .property( - js_string!("function"), + "function", function_module, Attribute::WRITABLE | Attribute::NON_ENUMERABLE | Attribute::CONFIGURABLE, ) .property( - js_string!("object"), + "object", object_module, Attribute::WRITABLE | Attribute::NON_ENUMERABLE | Attribute::CONFIGURABLE, ) .property( - js_string!("shape"), + "shape", shape_module, Attribute::WRITABLE | Attribute::NON_ENUMERABLE | Attribute::CONFIGURABLE, ) .property( - js_string!("optimizer"), + "optimizer", optimizer_module, Attribute::WRITABLE | Attribute::NON_ENUMERABLE | Attribute::CONFIGURABLE, ) .property( - js_string!("gc"), + "gc", gc_module, Attribute::WRITABLE | Attribute::NON_ENUMERABLE | Attribute::CONFIGURABLE, ) .property( - js_string!("realm"), + "realm", realm_module, Attribute::WRITABLE | Attribute::NON_ENUMERABLE | Attribute::CONFIGURABLE, ) .property( - js_string!("limits"), + "limits", limits_module, Attribute::WRITABLE | Attribute::NON_ENUMERABLE | Attribute::CONFIGURABLE, ) @@ -64,7 +64,7 @@ pub(crate) fn init_boa_debug_object(context: &mut Context<'_>) { let boa_object = create_boa_object(context); context .register_global_property( - js_string!("$boa"), + "$boa", boa_object, Attribute::WRITABLE | Attribute::NON_ENUMERABLE | Attribute::CONFIGURABLE, ) diff --git a/boa_cli/src/debug/object.rs b/boa_cli/src/debug/object.rs index 441d89b5acb..71ebbccf756 100644 --- a/boa_cli/src/debug/object.rs +++ b/boa_cli/src/debug/object.rs @@ -23,6 +23,6 @@ fn id(_: &JsValue, args: &[JsValue], _: &mut Context<'_>) -> JsResult { pub(super) fn create_object(context: &mut Context<'_>) -> JsObject { ObjectInitializer::new(context) - .function(NativeFunction::from_fn_ptr(id), js_string!("id"), 1) + .function(NativeFunction::from_fn_ptr(id), "id", 1) .build() } diff --git a/boa_cli/src/debug/optimizer.rs b/boa_cli/src/debug/optimizer.rs index e7e2679c870..45c76993e65 100644 --- a/boa_cli/src/debug/optimizer.rs +++ b/boa_cli/src/debug/optimizer.rs @@ -1,5 +1,4 @@ use boa_engine::{ - js_string, object::{FunctionObjectBuilder, ObjectInitializer}, optimizer::OptimizerOptions, property::Attribute, @@ -72,13 +71,13 @@ pub(super) fn create_object(context: &mut Context<'_>) -> JsObject { .build(); ObjectInitializer::new(context) .accessor( - js_string!("constantFolding"), + "constantFolding", Some(get_constant_folding), Some(set_constant_folding), Attribute::WRITABLE | Attribute::CONFIGURABLE | Attribute::NON_ENUMERABLE, ) .accessor( - js_string!("statistics"), + "statistics", Some(get_statistics), Some(set_statistics), Attribute::WRITABLE | Attribute::CONFIGURABLE | Attribute::NON_ENUMERABLE, diff --git a/boa_cli/src/debug/realm.rs b/boa_cli/src/debug/realm.rs index efe5ccbbddb..7a1e6cff9d1 100644 --- a/boa_cli/src/debug/realm.rs +++ b/boa_cli/src/debug/realm.rs @@ -1,6 +1,4 @@ -use boa_engine::{ - js_string, object::ObjectInitializer, Context, JsObject, JsResult, JsValue, NativeFunction, -}; +use boa_engine::{object::ObjectInitializer, Context, JsObject, JsResult, JsValue, NativeFunction}; /// Creates a new ECMAScript Realm and returns the global object of the realm. fn create(_: &JsValue, _: &[JsValue], _: &mut Context<'_>) -> JsResult { @@ -11,6 +9,6 @@ fn create(_: &JsValue, _: &[JsValue], _: &mut Context<'_>) -> JsResult pub(super) fn create_object(context: &mut Context<'_>) -> JsObject { ObjectInitializer::new(context) - .function(NativeFunction::from_fn_ptr(create), js_string!("create"), 0) + .function(NativeFunction::from_fn_ptr(create), "create", 0) .build() } diff --git a/boa_cli/src/debug/shape.rs b/boa_cli/src/debug/shape.rs index 90844415a6a..becc64cc736 100644 --- a/boa_cli/src/debug/shape.rs +++ b/boa_cli/src/debug/shape.rs @@ -62,8 +62,8 @@ fn same(_: &JsValue, args: &[JsValue], _: &mut Context<'_>) -> JsResult pub(super) fn create_object(context: &mut Context<'_>) -> JsObject { ObjectInitializer::new(context) - .function(NativeFunction::from_fn_ptr(id), js_string!("id"), 1) - .function(NativeFunction::from_fn_ptr(r#type), js_string!("type"), 1) - .function(NativeFunction::from_fn_ptr(same), js_string!("same"), 2) + .function(NativeFunction::from_fn_ptr(id), "id", 1) + .function(NativeFunction::from_fn_ptr(r#type), "type", 1) + .function(NativeFunction::from_fn_ptr(same), "same", 2) .build() } diff --git a/boa_engine/src/builtins/array/mod.rs b/boa_engine/src/builtins/array/mod.rs index 9a2a0941307..ac3357a8daf 100644 --- a/boa_engine/src/builtins/array/mod.rs +++ b/boa_engine/src/builtins/array/mod.rs @@ -56,7 +56,7 @@ impl IntrinsicObject for Array { let symbol_unscopables = JsSymbol::unscopables(); let get_species = BuiltInBuilder::callable(realm, Self::get_species) - .name(js_string!("get [Symbol.species]")) + .name("get [Symbol.species]") .build(); let values_function = BuiltInBuilder::callable_with_object( @@ -64,7 +64,7 @@ impl IntrinsicObject for Array { realm.intrinsics().objects().array_prototype_values().into(), Self::values, ) - .name(js_string!("values")) + .name("values") .build(); let to_string_function = BuiltInBuilder::callable_with_object( @@ -76,7 +76,7 @@ impl IntrinsicObject for Array { .into(), Self::to_string, ) - .name(js_string!("toString")) + .name("toString") .build(); let unscopables_object = Self::unscopables_object(); @@ -89,12 +89,12 @@ impl IntrinsicObject for Array { Attribute::CONFIGURABLE, ) .property( - utf16!("length"), + "length", 0, Attribute::WRITABLE | Attribute::NON_ENUMERABLE | Attribute::PERMANENT, ) .property( - utf16!("values"), + "values", values_function.clone(), Attribute::WRITABLE | Attribute::NON_ENUMERABLE | Attribute::CONFIGURABLE, ) @@ -108,47 +108,47 @@ impl IntrinsicObject for Array { unscopables_object, Attribute::READONLY | Attribute::NON_ENUMERABLE | Attribute::CONFIGURABLE, ) - .method(Self::at, js_string!("at"), 1) - .method(Self::concat, js_string!("concat"), 1) - .method(Self::push, js_string!("push"), 1) - .method(Self::index_of, js_string!("indexOf"), 1) - .method(Self::last_index_of, js_string!("lastIndexOf"), 1) - .method(Self::includes_value, js_string!("includes"), 1) - .method(Self::map, js_string!("map"), 1) - .method(Self::fill, js_string!("fill"), 1) - .method(Self::for_each, js_string!("forEach"), 1) - .method(Self::filter, js_string!("filter"), 1) - .method(Self::pop, js_string!("pop"), 0) - .method(Self::join, js_string!("join"), 1) + .method(Self::at, "at", 1) + .method(Self::concat, "concat", 1) + .method(Self::push, "push", 1) + .method(Self::index_of, "indexOf", 1) + .method(Self::last_index_of, "lastIndexOf", 1) + .method(Self::includes_value, "includes", 1) + .method(Self::map, "map", 1) + .method(Self::fill, "fill", 1) + .method(Self::for_each, "forEach", 1) + .method(Self::filter, "filter", 1) + .method(Self::pop, "pop", 0) + .method(Self::join, "join", 1) .property( - utf16!("toString"), + "toString", to_string_function, Attribute::WRITABLE | Attribute::NON_ENUMERABLE | Attribute::CONFIGURABLE, ) - .method(Self::reverse, js_string!("reverse"), 0) - .method(Self::shift, js_string!("shift"), 0) - .method(Self::unshift, js_string!("unshift"), 1) - .method(Self::every, js_string!("every"), 1) - .method(Self::find, js_string!("find"), 1) - .method(Self::find_index, js_string!("findIndex"), 1) - .method(Self::find_last, js_string!("findLast"), 1) - .method(Self::find_last_index, js_string!("findLastIndex"), 1) - .method(Self::flat, js_string!("flat"), 0) - .method(Self::flat_map, js_string!("flatMap"), 1) - .method(Self::slice, js_string!("slice"), 2) - .method(Self::some, js_string!("some"), 1) - .method(Self::sort, js_string!("sort"), 1) - .method(Self::splice, js_string!("splice"), 2) - .method(Self::to_locale_string, js_string!("toLocaleString"), 0) - .method(Self::reduce, js_string!("reduce"), 1) - .method(Self::reduce_right, js_string!("reduceRight"), 1) - .method(Self::keys, js_string!("keys"), 0) - .method(Self::entries, js_string!("entries"), 0) - .method(Self::copy_within, js_string!("copyWithin"), 2) + .method(Self::reverse, "reverse", 0) + .method(Self::shift, "shift", 0) + .method(Self::unshift, "unshift", 1) + .method(Self::every, "every", 1) + .method(Self::find, "find", 1) + .method(Self::find_index, "findIndex", 1) + .method(Self::find_last, "findLast", 1) + .method(Self::find_last_index, "findLastIndex", 1) + .method(Self::flat, "flat", 0) + .method(Self::flat_map, "flatMap", 1) + .method(Self::slice, "slice", 2) + .method(Self::some, "some", 1) + .method(Self::sort, "sort", 1) + .method(Self::splice, "splice", 2) + .method(Self::to_locale_string, "toLocaleString", 0) + .method(Self::reduce, "reduce", 1) + .method(Self::reduce_right, "reduceRight", 1) + .method(Self::keys, "keys", 0) + .method(Self::entries, "entries", 0) + .method(Self::copy_within, "copyWithin", 2) // Static Methods - .static_method(Self::from, js_string!("from"), 1) - .static_method(Self::is_array, js_string!("isArray"), 1) - .static_method(Self::of, js_string!("of"), 0) + .static_method(Self::from, "from", 1) + .static_method(Self::is_array, "isArray", 1) + .static_method(Self::of, "of", 0) .build(); } @@ -227,7 +227,7 @@ impl BuiltInConstructor for Array { }; // e. Perform ! Set(array, "length", intLen, true). array - .set(utf16!("length"), int_len, true, context) + .set("length", int_len, true, context) .expect("this Set call must not fail"); // f. Return array. Ok(array.into()) @@ -276,7 +276,7 @@ impl Array { } } - o.set(utf16!("length"), len, true, context)?; + o.set("length", len, true, context)?; Ok(()) } @@ -338,7 +338,7 @@ impl Array { // 6. Perform ! OrdinaryDefineOwnProperty(A, "length", PropertyDescriptor { [[Value]]: 𝔽(length), [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false }). crate::object::internal_methods::ordinary_define_own_property( &array, - &utf16!("length").into(), + &"length".into(), PropertyDescriptor::builder() .value(length) .writable(true) @@ -565,7 +565,7 @@ impl Array { } // 13. Perform ? Set(A, "length", 𝔽(len), true). - a.set(utf16!("length"), len, true, context)?; + a.set("length", len, true, context)?; // 14. Return A. return Ok(a.into()); @@ -595,7 +595,7 @@ impl Array { // iii. Let next be ? IteratorStep(iteratorRecord). if iterator_record.step(context)? { // 1. Perform ? Set(A, "length", 𝔽(k), true). - a.set(utf16!("length"), k, true, context)?; + a.set("length", k, true, context)?; // 2. Return A. return Ok(a.into()); } @@ -996,7 +996,7 @@ impl Array { for k in 0..len { // a. If k > 0, set R to the string-concatenation of R and sep. if k > 0 { - r.extend_from_slice(&separator); + r.push(separator.clone()); } // b. Let element be ? Get(O, ! ToString(𝔽(k))). let element = o.get(k, context)?; @@ -1007,7 +1007,7 @@ impl Array { element.to_string(context)? }; // d. Set R to the string-concatenation of R and next. - r.extend_from_slice(&next); + r.push(next.clone()); // e. Set k to k + 1. } // 8. Return R. @@ -1035,7 +1035,7 @@ impl Array { // 1. Let array be ? ToObject(this value). let array = this.to_object(context)?; // 2. Let func be ? Get(array, "join"). - let func = array.get(utf16!("join"), context)?; + let func = array.get("join", context)?; // 3. If IsCallable(func) is false, set func to the intrinsic function %Object.prototype.toString%. // 4. Return ? Call(func, array). if let Some(func) = func.as_callable() { @@ -2133,7 +2133,7 @@ impl Array { // a. If k > 0, then if k > 0 { // i. Set R to the string-concatenation of R and separator. - r.extend_from_slice(separator); + r.extend(separator.iter()); } // b. Let nextElement be ? Get(array, ! ToString(k)). @@ -2143,16 +2143,16 @@ impl Array { if !next.is_null_or_undefined() { // i. Let S be ? ToString(? Invoke(nextElement, "toLocaleString", « locales, options »)). let s = next - .invoke(utf16!("toLocaleString"), args, context)? + .invoke("toLocaleString", args, context)? .to_string(context)?; // ii. Set R to the string-concatenation of R and S. - r.extend_from_slice(&s); + r.extend(s.iter()); } // d. Increase k by 1. } // 7. Return R. - Ok(js_string!(r).into()) + Ok(js_string!(&r[..]).into()) } /// `Array.prototype.splice ( start, [deleteCount[, ...items]] )` @@ -3011,37 +3011,37 @@ impl Array { { let mut obj = unscopable_list.borrow_mut(); // 2. Perform ! CreateDataPropertyOrThrow(unscopableList, "at", true). - obj.insert(utf16!("at"), true_prop.clone()); + obj.insert("at", true_prop.clone()); // 3. Perform ! CreateDataPropertyOrThrow(unscopableList, "copyWithin", true). - obj.insert(utf16!("copyWithin"), true_prop.clone()); + obj.insert("copyWithin", true_prop.clone()); // 4. Perform ! CreateDataPropertyOrThrow(unscopableList, "entries", true). - obj.insert(utf16!("entries"), true_prop.clone()); + obj.insert("entries", true_prop.clone()); // 5. Perform ! CreateDataPropertyOrThrow(unscopableList, "fill", true). - obj.insert(utf16!("fill"), true_prop.clone()); + obj.insert("fill", true_prop.clone()); // 6. Perform ! CreateDataPropertyOrThrow(unscopableList, "find", true). - obj.insert(utf16!("find"), true_prop.clone()); + obj.insert("find", true_prop.clone()); // 7. Perform ! CreateDataPropertyOrThrow(unscopableList, "findIndex", true). - obj.insert(utf16!("findIndex"), true_prop.clone()); + obj.insert("findIndex", true_prop.clone()); // 8. Perform ! CreateDataPropertyOrThrow(unscopableList, "findLast", true). - obj.insert(utf16!("findLast"), true_prop.clone()); + obj.insert("findLast", true_prop.clone()); // 9. Perform ! CreateDataPropertyOrThrow(unscopableList, "findLastIndex", true). - obj.insert(utf16!("findLastIndex"), true_prop.clone()); + obj.insert("findLastIndex", true_prop.clone()); // 10. Perform ! CreateDataPropertyOrThrow(unscopableList, "flat", true). - obj.insert(utf16!("flat"), true_prop.clone()); + obj.insert("flat", true_prop.clone()); // 11. Perform ! CreateDataPropertyOrThrow(unscopableList, "flatMap", true). - obj.insert(utf16!("flatMap"), true_prop.clone()); + obj.insert("flatMap", true_prop.clone()); // 12. Perform ! CreateDataPropertyOrThrow(unscopableList, "includes", true). - obj.insert(utf16!("includes"), true_prop.clone()); + obj.insert("includes", true_prop.clone()); // 13. Perform ! CreateDataPropertyOrThrow(unscopableList, "keys", true). - obj.insert(utf16!("keys"), true_prop.clone()); + obj.insert("keys", true_prop.clone()); // 14. Perform ! CreateDataPropertyOrThrow(unscopableList, "toReversed", true). - obj.insert(utf16!("toReversed"), true_prop.clone()); + obj.insert("toReversed", true_prop.clone()); // 15. Perform ! CreateDataPropertyOrThrow(unscopableList, "toSorted", true). - obj.insert(utf16!("toSorted"), true_prop.clone()); + obj.insert("toSorted", true_prop.clone()); // 16. Perform ! CreateDataPropertyOrThrow(unscopableList, "toSpliced", true). - obj.insert(utf16!("toSpliced"), true_prop.clone()); + obj.insert("toSpliced", true_prop.clone()); // 17. Perform ! CreateDataPropertyOrThrow(unscopableList, "values", true). - obj.insert(utf16!("values"), true_prop); + obj.insert("values", true_prop); } // 13. Return unscopableList. diff --git a/boa_engine/src/builtins/array_buffer/mod.rs b/boa_engine/src/builtins/array_buffer/mod.rs index ede5583529c..e36c4d98310 100644 --- a/boa_engine/src/builtins/array_buffer/mod.rs +++ b/boa_engine/src/builtins/array_buffer/mod.rs @@ -22,7 +22,6 @@ use crate::{ builtins::BuiltInObject, context::intrinsics::{Intrinsics, StandardConstructor, StandardConstructors}, error::JsNativeError, - js_string, object::{internal_methods::get_prototype_from_constructor, JsObject, ObjectData}, property::Attribute, realm::Realm, @@ -138,28 +137,23 @@ impl IntrinsicObject for ArrayBuffer { let flag_attributes = Attribute::CONFIGURABLE | Attribute::NON_ENUMERABLE; let get_species = BuiltInBuilder::callable(realm, Self::get_species) - .name(js_string!("get [Symbol.species]")) + .name("get [Symbol.species]") .build(); let get_byte_length = BuiltInBuilder::callable(realm, Self::get_byte_length) - .name(js_string!("get byteLength")) + .name("get byteLength") .build(); BuiltInBuilder::from_standard_constructor::(realm) - .accessor( - js_string!("byteLength"), - Some(get_byte_length), - None, - flag_attributes, - ) + .accessor("byteLength", Some(get_byte_length), None, flag_attributes) .static_accessor( JsSymbol::species(), Some(get_species), None, Attribute::CONFIGURABLE, ) - .static_method(Self::is_view, js_string!("isView"), 1) - .method(Self::slice, js_string!("slice"), 2) + .static_method(Self::is_view, "isView", 1) + .method(Self::slice, "slice", 2) .property( JsSymbol::to_string_tag(), Self::NAME, diff --git a/boa_engine/src/builtins/array_buffer/shared.rs b/boa_engine/src/builtins/array_buffer/shared.rs index dd44c175e0a..d744fcf74a2 100644 --- a/boa_engine/src/builtins/array_buffer/shared.rs +++ b/boa_engine/src/builtins/array_buffer/shared.rs @@ -11,7 +11,6 @@ use sptr::Strict; use crate::{ builtins::{BuiltInBuilder, BuiltInConstructor, BuiltInObject, IntrinsicObject}, context::intrinsics::{Intrinsics, StandardConstructor, StandardConstructors}, - js_string, object::{internal_methods::get_prototype_from_constructor, ObjectData}, property::Attribute, realm::Realm, @@ -52,27 +51,22 @@ impl IntrinsicObject for SharedArrayBuffer { let flag_attributes = Attribute::CONFIGURABLE | Attribute::NON_ENUMERABLE; let get_species = BuiltInBuilder::callable(realm, Self::get_species) - .name(js_string!("get [Symbol.species]")) + .name("get [Symbol.species]") .build(); let get_byte_length = BuiltInBuilder::callable(realm, Self::get_byte_length) - .name(js_string!("get byteLength")) + .name("get byteLength") .build(); BuiltInBuilder::from_standard_constructor::(realm) - .accessor( - js_string!("byteLength"), - Some(get_byte_length), - None, - flag_attributes, - ) + .accessor("byteLength", Some(get_byte_length), None, flag_attributes) .static_accessor( JsSymbol::species(), Some(get_species), None, Attribute::CONFIGURABLE, ) - .method(Self::slice, js_string!("slice"), 2) + .method(Self::slice, "slice", 2) .property( JsSymbol::to_string_tag(), Self::NAME, diff --git a/boa_engine/src/builtins/async_generator/mod.rs b/boa_engine/src/builtins/async_generator/mod.rs index 74af1438a48..e128ed978a1 100644 --- a/boa_engine/src/builtins/async_generator/mod.rs +++ b/boa_engine/src/builtins/async_generator/mod.rs @@ -12,7 +12,6 @@ use crate::{ }, context::intrinsics::Intrinsics, error::JsNativeError, - js_string, native_function::NativeFunction, object::{FunctionObjectBuilder, JsObject, CONSTRUCTOR}, property::Attribute, @@ -80,9 +79,9 @@ impl IntrinsicObject for AsyncGenerator { .iterator_prototypes() .async_iterator(), ) - .static_method(Self::next, js_string!("next"), 1) - .static_method(Self::r#return, js_string!("return"), 1) - .static_method(Self::throw, js_string!("throw"), 1) + .static_method(Self::next, "next", 1) + .static_method(Self::r#return, "return", 1) + .static_method(Self::throw, "throw", 1) .static_property( JsSymbol::to_string_tag(), Self::NAME, diff --git a/boa_engine/src/builtins/bigint/mod.rs b/boa_engine/src/builtins/bigint/mod.rs index 78d1b70a423..7d621c4395f 100644 --- a/boa_engine/src/builtins/bigint/mod.rs +++ b/boa_engine/src/builtins/bigint/mod.rs @@ -42,10 +42,10 @@ impl IntrinsicObject for BigInt { let _timer = Profiler::global().start_event(std::any::type_name::(), "init"); BuiltInBuilder::from_standard_constructor::(realm) - .method(Self::to_string, js_string!("toString"), 0) - .method(Self::value_of, js_string!("valueOf"), 0) - .static_method(Self::as_int_n, js_string!("asIntN"), 2) - .static_method(Self::as_uint_n, js_string!("asUintN"), 2) + .method(Self::to_string, "toString", 0) + .method(Self::value_of, "valueOf", 0) + .static_method(Self::as_int_n, "asIntN", 2) + .static_method(Self::as_uint_n, "asUintN", 2) .property( JsSymbol::to_string_tag(), Self::NAME, diff --git a/boa_engine/src/builtins/boolean/mod.rs b/boa_engine/src/builtins/boolean/mod.rs index fcae01bb373..efe13f3c0f4 100644 --- a/boa_engine/src/builtins/boolean/mod.rs +++ b/boa_engine/src/builtins/boolean/mod.rs @@ -35,8 +35,8 @@ impl IntrinsicObject for Boolean { let _timer = Profiler::global().start_event(std::any::type_name::(), "init"); BuiltInBuilder::from_standard_constructor::(realm) - .method(Self::to_string, js_string!("toString"), 0) - .method(Self::value_of, js_string!("valueOf"), 0) + .method(Self::to_string, "toString", 0) + .method(Self::value_of, "valueOf", 0) .build(); } diff --git a/boa_engine/src/builtins/dataview/mod.rs b/boa_engine/src/builtins/dataview/mod.rs index 92856fa2866..180df8e06ef 100644 --- a/boa_engine/src/builtins/dataview/mod.rs +++ b/boa_engine/src/builtins/dataview/mod.rs @@ -13,7 +13,6 @@ use crate::{ builtins::BuiltInObject, context::intrinsics::{Intrinsics, StandardConstructor, StandardConstructors}, error::JsNativeError, - js_string, object::{internal_methods::get_prototype_from_constructor, JsObject, ObjectData}, property::Attribute, realm::Realm, @@ -44,56 +43,41 @@ impl IntrinsicObject for DataView { let flag_attributes = Attribute::CONFIGURABLE | Attribute::NON_ENUMERABLE; let get_buffer = BuiltInBuilder::callable(realm, Self::get_buffer) - .name(js_string!("get buffer")) + .name("get buffer") .build(); let get_byte_length = BuiltInBuilder::callable(realm, Self::get_byte_length) - .name(js_string!("get byteLength")) + .name("get byteLength") .build(); let get_byte_offset = BuiltInBuilder::callable(realm, Self::get_byte_offset) - .name(js_string!("get byteOffset")) + .name("get byteOffset") .build(); BuiltInBuilder::from_standard_constructor::(realm) - .accessor( - js_string!("buffer"), - Some(get_buffer), - None, - flag_attributes, - ) - .accessor( - js_string!("byteLength"), - Some(get_byte_length), - None, - flag_attributes, - ) - .accessor( - js_string!("byteOffset"), - Some(get_byte_offset), - None, - flag_attributes, - ) - .method(Self::get_big_int64, js_string!("getBigInt64"), 1) - .method(Self::get_big_uint64, js_string!("getBigUint64"), 1) - .method(Self::get_float32, js_string!("getFloat32"), 1) - .method(Self::get_float64, js_string!("getFloat64"), 1) - .method(Self::get_int8, js_string!("getInt8"), 1) - .method(Self::get_int16, js_string!("getInt16"), 1) - .method(Self::get_int32, js_string!("getInt32"), 1) - .method(Self::get_uint8, js_string!("getUint8"), 1) - .method(Self::get_uint16, js_string!("getUint16"), 1) - .method(Self::get_uint32, js_string!("getUint32"), 1) - .method(Self::set_big_int64, js_string!("setBigInt64"), 2) - .method(Self::set_big_uint64, js_string!("setBigUint64"), 2) - .method(Self::set_float32, js_string!("setFloat32"), 2) - .method(Self::set_float64, js_string!("setFloat64"), 2) - .method(Self::set_int8, js_string!("setInt8"), 2) - .method(Self::set_int16, js_string!("setInt16"), 2) - .method(Self::set_int32, js_string!("setInt32"), 2) - .method(Self::set_uint8, js_string!("setUint8"), 2) - .method(Self::set_uint16, js_string!("setUint16"), 2) - .method(Self::set_uint32, js_string!("setUint32"), 2) + .accessor("buffer", Some(get_buffer), None, flag_attributes) + .accessor("byteLength", Some(get_byte_length), None, flag_attributes) + .accessor("byteOffset", Some(get_byte_offset), None, flag_attributes) + .method(Self::get_big_int64, "getBigInt64", 1) + .method(Self::get_big_uint64, "getBigUint64", 1) + .method(Self::get_float32, "getFloat32", 1) + .method(Self::get_float64, "getFloat64", 1) + .method(Self::get_int8, "getInt8", 1) + .method(Self::get_int16, "getInt16", 1) + .method(Self::get_int32, "getInt32", 1) + .method(Self::get_uint8, "getUint8", 1) + .method(Self::get_uint16, "getUint16", 1) + .method(Self::get_uint32, "getUint32", 1) + .method(Self::set_big_int64, "setBigInt64", 2) + .method(Self::set_big_uint64, "setBigUint64", 2) + .method(Self::set_float32, "setFloat32", 2) + .method(Self::set_float64, "setFloat64", 2) + .method(Self::set_int8, "setInt8", 2) + .method(Self::set_int16, "setInt16", 2) + .method(Self::set_int32, "setInt32", 2) + .method(Self::set_uint8, "setUint8", 2) + .method(Self::set_uint16, "setUint16", 2) + .method(Self::set_uint32, "setUint32", 2) .property( JsSymbol::to_string_tag(), Self::NAME, diff --git a/boa_engine/src/builtins/date/mod.rs b/boa_engine/src/builtins/date/mod.rs index b25ddcc2960..9aab7cc6dfb 100644 --- a/boa_engine/src/builtins/date/mod.rs +++ b/boa_engine/src/builtins/date/mod.rs @@ -24,7 +24,7 @@ use crate::{ object::{internal_methods::get_prototype_from_constructor, JsObject, ObjectData}, property::Attribute, realm::Realm, - string::{common::StaticJsStrings, utf16}, + string::common::StaticJsStrings, symbol::JsSymbol, value::{IntegerOrNan, JsValue, PreferredType}, Context, JsArgs, JsError, JsResult, JsString, @@ -97,106 +97,70 @@ impl IntrinsicObject for Date { let _timer = Profiler::global().start_event(std::any::type_name::(), "init"); let to_utc_string = BuiltInBuilder::callable(realm, Self::to_utc_string) - .name(js_string!("toUTCString")) + .name("toUTCString") .length(0) .build(); let to_primitive = BuiltInBuilder::callable(realm, Self::to_primitive) - .name(js_string!("[Symbol.toPrimitive]")) + .name("[Symbol.toPrimitive]") .length(1) .build(); BuiltInBuilder::from_standard_constructor::(realm) - .static_method(Self::now, js_string!("now"), 0) - .static_method(Self::parse, js_string!("parse"), 1) - .static_method(Self::utc, js_string!("UTC"), 7) - .method(Self::get_date::, js_string!("getDate"), 0) - .method(Self::get_day::, js_string!("getDay"), 0) - .method(Self::get_full_year::, js_string!("getFullYear"), 0) - .method(Self::get_hours::, js_string!("getHours"), 0) - .method( - Self::get_milliseconds::, - js_string!("getMilliseconds"), - 0, - ) - .method(Self::get_minutes::, js_string!("getMinutes"), 0) - .method(Self::get_month::, js_string!("getMonth"), 0) - .method(Self::get_seconds::, js_string!("getSeconds"), 0) - .method(Self::get_time, js_string!("getTime"), 0) - .method( - Self::get_timezone_offset, - js_string!("getTimezoneOffset"), - 0, - ) - .method(Self::get_date::, js_string!("getUTCDate"), 0) - .method(Self::get_day::, js_string!("getUTCDay"), 0) - .method( - Self::get_full_year::, - js_string!("getUTCFullYear"), - 0, - ) - .method(Self::get_hours::, js_string!("getUTCHours"), 0) - .method( - Self::get_milliseconds::, - js_string!("getUTCMilliseconds"), - 0, - ) - .method(Self::get_minutes::, js_string!("getUTCMinutes"), 0) - .method(Self::get_month::, js_string!("getUTCMonth"), 0) - .method(Self::get_seconds::, js_string!("getUTCSeconds"), 0) - .method(Self::get_year, js_string!("getYear"), 0) - .method(Self::set_date::, js_string!("setDate"), 1) - .method(Self::set_full_year::, js_string!("setFullYear"), 3) - .method(Self::set_hours::, js_string!("setHours"), 4) - .method( - Self::set_milliseconds::, - js_string!("setMilliseconds"), - 1, - ) - .method(Self::set_minutes::, js_string!("setMinutes"), 3) - .method(Self::set_month::, js_string!("setMonth"), 2) - .method(Self::set_seconds::, js_string!("setSeconds"), 2) - .method(Self::set_time, js_string!("setTime"), 1) - .method(Self::set_date::, js_string!("setUTCDate"), 1) - .method( - Self::set_full_year::, - js_string!("setUTCFullYear"), - 3, - ) - .method(Self::set_hours::, js_string!("setUTCHours"), 4) - .method( - Self::set_milliseconds::, - js_string!("setUTCMilliseconds"), - 1, - ) - .method(Self::set_minutes::, js_string!("setUTCMinutes"), 3) - .method(Self::set_month::, js_string!("setUTCMonth"), 2) - .method(Self::set_seconds::, js_string!("setUTCSeconds"), 2) - .method(Self::set_year, js_string!("setYear"), 1) - .method(Self::to_date_string, js_string!("toDateString"), 0) - .method(Self::to_iso_string, js_string!("toISOString"), 0) - .method(Self::to_json, js_string!("toJSON"), 1) - .method( - Self::to_locale_date_string, - js_string!("toLocaleDateString"), - 0, - ) - .method(Self::to_locale_string, js_string!("toLocaleString"), 0) - .method( - Self::to_locale_time_string, - js_string!("toLocaleTimeString"), - 0, - ) - .method(Self::to_string, js_string!("toString"), 0) - .method(Self::to_time_string, js_string!("toTimeString"), 0) - .method(Self::value_of, js_string!("valueOf"), 0) + .static_method(Self::now, "now", 0) + .static_method(Self::parse, "parse", 1) + .static_method(Self::utc, "UTC", 7) + .method(Self::get_date::, "getDate", 0) + .method(Self::get_day::, "getDay", 0) + .method(Self::get_full_year::, "getFullYear", 0) + .method(Self::get_hours::, "getHours", 0) + .method(Self::get_milliseconds::, "getMilliseconds", 0) + .method(Self::get_minutes::, "getMinutes", 0) + .method(Self::get_month::, "getMonth", 0) + .method(Self::get_seconds::, "getSeconds", 0) + .method(Self::get_time, "getTime", 0) + .method(Self::get_timezone_offset, "getTimezoneOffset", 0) + .method(Self::get_date::, "getUTCDate", 0) + .method(Self::get_day::, "getUTCDay", 0) + .method(Self::get_full_year::, "getUTCFullYear", 0) + .method(Self::get_hours::, "getUTCHours", 0) + .method(Self::get_milliseconds::, "getUTCMilliseconds", 0) + .method(Self::get_minutes::, "getUTCMinutes", 0) + .method(Self::get_month::, "getUTCMonth", 0) + .method(Self::get_seconds::, "getUTCSeconds", 0) + .method(Self::get_year, "getYear", 0) + .method(Self::set_date::, "setDate", 1) + .method(Self::set_full_year::, "setFullYear", 3) + .method(Self::set_hours::, "setHours", 4) + .method(Self::set_milliseconds::, "setMilliseconds", 1) + .method(Self::set_minutes::, "setMinutes", 3) + .method(Self::set_month::, "setMonth", 2) + .method(Self::set_seconds::, "setSeconds", 2) + .method(Self::set_time, "setTime", 1) + .method(Self::set_date::, "setUTCDate", 1) + .method(Self::set_full_year::, "setUTCFullYear", 3) + .method(Self::set_hours::, "setUTCHours", 4) + .method(Self::set_milliseconds::, "setUTCMilliseconds", 1) + .method(Self::set_minutes::, "setUTCMinutes", 3) + .method(Self::set_month::, "setUTCMonth", 2) + .method(Self::set_seconds::, "setUTCSeconds", 2) + .method(Self::set_year, "setYear", 1) + .method(Self::to_date_string, "toDateString", 0) + .method(Self::to_iso_string, "toISOString", 0) + .method(Self::to_json, "toJSON", 1) + .method(Self::to_locale_date_string, "toLocaleDateString", 0) + .method(Self::to_locale_string, "toLocaleString", 0) + .method(Self::to_locale_time_string, "toLocaleTimeString", 0) + .method(Self::to_string, "toString", 0) + .method(Self::to_time_string, "toTimeString", 0) + .method(Self::value_of, "valueOf", 0) .property( - js_string!("toGMTString"), + "toGMTString", to_utc_string.clone(), Attribute::WRITABLE | Attribute::NON_ENUMERABLE | Attribute::CONFIGURABLE, ) .property( - js_string!("toUTCString"), + "toUTCString", to_utc_string, Attribute::WRITABLE | Attribute::NON_ENUMERABLE | Attribute::CONFIGURABLE, ) @@ -1349,7 +1313,7 @@ impl Date { } // 4. Return ? Invoke(O, "toISOString"). - let func = o.get(utf16!("toISOString"), context)?; + let func = o.get("toISOString", context)?; func.call(this, &[], context) } @@ -1548,12 +1512,10 @@ impl Date { let try_first = match hint.as_string() { // 3. If hint is "string" or "default", then // a. Let tryFirst be string. - Some(string) if string == utf16!("string") || string == utf16!("default") => { - PreferredType::String - } + Some(string) if string == "string" || string == "default" => PreferredType::String, // 4. Else if hint is "number", then // a. Let tryFirst be number. - Some(number) if number == utf16!("number") => PreferredType::Number, + Some(number) if number == "number" => PreferredType::Number, // 5. Else, throw a TypeError exception. _ => { return Err(JsNativeError::typ() diff --git a/boa_engine/src/builtins/error/aggregate.rs b/boa_engine/src/builtins/error/aggregate.rs index 8daf6862246..b9295bebf10 100644 --- a/boa_engine/src/builtins/error/aggregate.rs +++ b/boa_engine/src/builtins/error/aggregate.rs @@ -17,7 +17,7 @@ use crate::{ object::{internal_methods::get_prototype_from_constructor, JsObject, ObjectData}, property::{Attribute, PropertyDescriptorBuilder}, realm::Realm, - string::{common::StaticJsStrings, utf16}, + string::common::StaticJsStrings, Context, JsArgs, JsResult, JsString, JsValue, }; use boa_profiler::Profiler; @@ -35,8 +35,8 @@ impl IntrinsicObject for AggregateError { BuiltInBuilder::from_standard_constructor::(realm) .prototype(realm.intrinsics().constructors().error().constructor()) .inherits(Some(realm.intrinsics().constructors().error().prototype())) - .property(utf16!("name"), Self::NAME, attribute) - .property(utf16!("message"), js_string!(), attribute) + .property("name", Self::NAME, attribute) + .property("message", js_string!(), attribute) .build(); } @@ -95,7 +95,7 @@ impl BuiltInConstructor for AggregateError { let msg = message.to_string(context)?; // b. Perform CreateNonEnumerableDataPropertyOrThrow(O, "message", msg). - o.create_non_enumerable_data_property_or_throw(utf16!("message"), msg, context); + o.create_non_enumerable_data_property_or_throw("message", msg, context); } // 4. Perform ? InstallErrorCause(O, options). @@ -112,7 +112,7 @@ impl BuiltInConstructor for AggregateError { // [[Value]]: CreateArrayFromList(errorsList) // }). o.define_property_or_throw( - utf16!("errors"), + "errors", PropertyDescriptorBuilder::new() .configurable(true) .enumerable(false) diff --git a/boa_engine/src/builtins/error/eval.rs b/boa_engine/src/builtins/error/eval.rs index fe8d417a84c..7d0caa7a5d4 100644 --- a/boa_engine/src/builtins/error/eval.rs +++ b/boa_engine/src/builtins/error/eval.rs @@ -18,7 +18,7 @@ use crate::{ object::{internal_methods::get_prototype_from_constructor, JsObject, ObjectData}, property::Attribute, realm::Realm, - string::{common::StaticJsStrings, utf16}, + string::common::StaticJsStrings, Context, JsArgs, JsResult, JsString, JsValue, }; use boa_profiler::Profiler; @@ -37,8 +37,8 @@ impl IntrinsicObject for EvalError { BuiltInBuilder::from_standard_constructor::(realm) .prototype(realm.intrinsics().constructors().error().constructor()) .inherits(Some(realm.intrinsics().constructors().error().prototype())) - .property(utf16!("name"), Self::NAME, attribute) - .property(utf16!("message"), js_string!(), attribute) + .property("name", Self::NAME, attribute) + .property("message", js_string!(), attribute) .build(); } @@ -94,7 +94,7 @@ impl BuiltInConstructor for EvalError { let msg = message.to_string(context)?; // b. Perform CreateNonEnumerableDataPropertyOrThrow(O, "message", msg). - o.create_non_enumerable_data_property_or_throw(utf16!("message"), msg, context); + o.create_non_enumerable_data_property_or_throw("message", msg, context); } // 4. Perform ? InstallErrorCause(O, options). diff --git a/boa_engine/src/builtins/error/mod.rs b/boa_engine/src/builtins/error/mod.rs index e28c4d6fbfc..9b49384f42c 100644 --- a/boa_engine/src/builtins/error/mod.rs +++ b/boa_engine/src/builtins/error/mod.rs @@ -18,7 +18,7 @@ use crate::{ object::{internal_methods::get_prototype_from_constructor, JsObject, ObjectData}, property::Attribute, realm::Realm, - string::{common::StaticJsStrings, utf16}, + string::common::StaticJsStrings, Context, JsArgs, JsResult, JsString, JsValue, }; use boa_profiler::Profiler; @@ -133,9 +133,9 @@ impl IntrinsicObject for Error { let attribute = Attribute::WRITABLE | Attribute::NON_ENUMERABLE | Attribute::CONFIGURABLE; BuiltInBuilder::from_standard_constructor::(realm) - .property(utf16!("name"), Self::NAME, attribute) - .property(utf16!("message"), js_string!(), attribute) - .method(Self::to_string, js_string!("toString"), 0) + .property("name", Self::NAME, attribute) + .property("message", js_string!(), attribute) + .method(Self::to_string, "toString", 0) .build(); } @@ -188,7 +188,7 @@ impl BuiltInConstructor for Error { let msg = message.to_string(context)?; // b. Perform CreateNonEnumerableDataPropertyOrThrow(O, "message", msg). - o.create_non_enumerable_data_property_or_throw(utf16!("message"), msg, context); + o.create_non_enumerable_data_property_or_throw("message", msg, context); } // 4. Perform ? InstallErrorCause(O, options). @@ -207,12 +207,12 @@ impl Error { ) -> JsResult<()> { // 1. If Type(options) is Object and ? HasProperty(options, "cause") is true, then if let Some(options) = options.as_object() { - if options.has_property(utf16!("cause"), context)? { + if options.has_property("cause", context)? { // a. Let cause be ? Get(options, "cause"). - let cause = options.get(utf16!("cause"), context)?; + let cause = options.get("cause", context)?; // b. Perform CreateNonEnumerableDataPropertyOrThrow(O, "cause", cause). - o.create_non_enumerable_data_property_or_throw(utf16!("cause"), cause, context); + o.create_non_enumerable_data_property_or_throw("cause", cause, context); } } @@ -243,7 +243,7 @@ impl Error { .ok_or_else(|| JsNativeError::typ().with_message("'this' is not an Object"))?; // 3. Let name be ? Get(O, "name"). - let name = o.get(js_string!("name"), context)?; + let name = o.get("name", context)?; // 4. If name is undefined, set name to "Error"; otherwise set name to ? ToString(name). let name = if name.is_undefined() { @@ -253,7 +253,7 @@ impl Error { }; // 5. Let msg be ? Get(O, "message"). - let msg = o.get(js_string!("message"), context)?; + let msg = o.get("message", context)?; // 6. If msg is undefined, set msg to the empty String; otherwise set msg to ? ToString(msg). let msg = if msg.is_undefined() { @@ -274,6 +274,6 @@ impl Error { // 9. Return the string-concatenation of name, the code unit 0x003A (COLON), // the code unit 0x0020 (SPACE), and msg. - Ok(js_string!(&name, utf16!(": "), &msg).into()) + Ok(js_string!(&name, ": ", &msg).into()) } } diff --git a/boa_engine/src/builtins/error/range.rs b/boa_engine/src/builtins/error/range.rs index 972392d0a2c..4ba0eaf9e55 100644 --- a/boa_engine/src/builtins/error/range.rs +++ b/boa_engine/src/builtins/error/range.rs @@ -16,7 +16,7 @@ use crate::{ object::{internal_methods::get_prototype_from_constructor, JsObject, ObjectData}, property::Attribute, realm::Realm, - string::{common::StaticJsStrings, utf16}, + string::common::StaticJsStrings, Context, JsArgs, JsResult, JsString, JsValue, }; use boa_profiler::Profiler; @@ -35,8 +35,8 @@ impl IntrinsicObject for RangeError { BuiltInBuilder::from_standard_constructor::(realm) .prototype(realm.intrinsics().constructors().error().constructor()) .inherits(Some(realm.intrinsics().constructors().error().prototype())) - .property(utf16!("name"), Self::NAME, attribute) - .property(utf16!("message"), js_string!(), attribute) + .property("name", Self::NAME, attribute) + .property("message", js_string!(), attribute) .build(); } @@ -92,7 +92,7 @@ impl BuiltInConstructor for RangeError { let msg = message.to_string(context)?; // b. Perform CreateNonEnumerableDataPropertyOrThrow(O, "message", msg). - o.create_non_enumerable_data_property_or_throw(utf16!("message"), msg, context); + o.create_non_enumerable_data_property_or_throw("message", msg, context); } // 4. Perform ? InstallErrorCause(O, options). diff --git a/boa_engine/src/builtins/error/reference.rs b/boa_engine/src/builtins/error/reference.rs index 4ddd5abd7d8..ea7ce71da3a 100644 --- a/boa_engine/src/builtins/error/reference.rs +++ b/boa_engine/src/builtins/error/reference.rs @@ -16,7 +16,7 @@ use crate::{ object::{internal_methods::get_prototype_from_constructor, JsObject, ObjectData}, property::Attribute, realm::Realm, - string::{common::StaticJsStrings, utf16}, + string::common::StaticJsStrings, Context, JsArgs, JsResult, JsString, JsValue, }; use boa_profiler::Profiler; @@ -34,8 +34,8 @@ impl IntrinsicObject for ReferenceError { BuiltInBuilder::from_standard_constructor::(realm) .prototype(realm.intrinsics().constructors().error().constructor()) .inherits(Some(realm.intrinsics().constructors().error().prototype())) - .property(js_string!("name"), Self::NAME, attribute) - .property(js_string!("message"), js_string!(), attribute) + .property("name", Self::NAME, attribute) + .property("message", js_string!(), attribute) .build(); } @@ -94,7 +94,7 @@ impl BuiltInConstructor for ReferenceError { let msg = message.to_string(context)?; // b. Perform CreateNonEnumerableDataPropertyOrThrow(O, "message", msg). - o.create_non_enumerable_data_property_or_throw(utf16!("message"), msg, context); + o.create_non_enumerable_data_property_or_throw("message", msg, context); } // 4. Perform ? InstallErrorCause(O, options). diff --git a/boa_engine/src/builtins/error/syntax.rs b/boa_engine/src/builtins/error/syntax.rs index 91b9f1a6380..62dc4f52bd5 100644 --- a/boa_engine/src/builtins/error/syntax.rs +++ b/boa_engine/src/builtins/error/syntax.rs @@ -18,7 +18,7 @@ use crate::{ object::{internal_methods::get_prototype_from_constructor, JsObject, ObjectData}, property::Attribute, realm::Realm, - string::{common::StaticJsStrings, utf16}, + string::common::StaticJsStrings, Context, JsArgs, JsResult, JsString, JsValue, }; use boa_profiler::Profiler; @@ -37,8 +37,8 @@ impl IntrinsicObject for SyntaxError { BuiltInBuilder::from_standard_constructor::(realm) .prototype(realm.intrinsics().constructors().error().constructor()) .inherits(Some(realm.intrinsics().constructors().error().prototype())) - .property(utf16!("name"), Self::NAME, attribute) - .property(utf16!("message"), js_string!(), attribute) + .property("name", Self::NAME, attribute) + .property("message", js_string!(), attribute) .build(); } @@ -97,7 +97,7 @@ impl BuiltInConstructor for SyntaxError { let msg = message.to_string(context)?; // b. Perform CreateNonEnumerableDataPropertyOrThrow(O, "message", msg). - o.create_non_enumerable_data_property_or_throw(utf16!("message"), msg, context); + o.create_non_enumerable_data_property_or_throw("message", msg, context); } // 4. Perform ? InstallErrorCause(O, options). diff --git a/boa_engine/src/builtins/error/type.rs b/boa_engine/src/builtins/error/type.rs index 9ebbed89ccb..0fae0c27776 100644 --- a/boa_engine/src/builtins/error/type.rs +++ b/boa_engine/src/builtins/error/type.rs @@ -23,7 +23,7 @@ use crate::{ object::{internal_methods::get_prototype_from_constructor, JsObject, ObjectData, ObjectKind}, property::Attribute, realm::Realm, - string::{common::StaticJsStrings, utf16}, + string::common::StaticJsStrings, Context, JsArgs, JsResult, JsString, JsValue, NativeFunction, }; use boa_profiler::Profiler; @@ -42,8 +42,8 @@ impl IntrinsicObject for TypeError { BuiltInBuilder::from_standard_constructor::(realm) .prototype(realm.intrinsics().constructors().error().constructor()) .inherits(Some(realm.intrinsics().constructors().error().prototype())) - .property(utf16!("name"), Self::NAME, attribute) - .property(utf16!("message"), js_string!(), attribute) + .property("name", Self::NAME, attribute) + .property("message", js_string!(), attribute) .build(); } @@ -99,7 +99,7 @@ impl BuiltInConstructor for TypeError { let msg = message.to_string(context)?; // b. Perform CreateNonEnumerableDataPropertyOrThrow(O, "message", msg). - o.create_non_enumerable_data_property_or_throw(utf16!("message"), msg, context); + o.create_non_enumerable_data_property_or_throw("message", msg, context); } // 4. Perform ? InstallErrorCause(O, options). @@ -126,8 +126,8 @@ impl IntrinsicObject for ThrowTypeError { let obj = BuiltInBuilder::with_intrinsic::(realm) .prototype(realm.intrinsics().constructors().function().prototype()) - .static_property(utf16!("length"), 0, Attribute::empty()) - .static_property(utf16!("name"), js_string!(), Attribute::empty()) + .static_property("length", 0, Attribute::empty()) + .static_property("name", js_string!(), Attribute::empty()) .build(); let mut obj = obj.borrow_mut(); diff --git a/boa_engine/src/builtins/error/uri.rs b/boa_engine/src/builtins/error/uri.rs index df27792f0d6..c383da2c6e3 100644 --- a/boa_engine/src/builtins/error/uri.rs +++ b/boa_engine/src/builtins/error/uri.rs @@ -17,7 +17,7 @@ use crate::{ object::{internal_methods::get_prototype_from_constructor, JsObject, ObjectData}, property::Attribute, realm::Realm, - string::{common::StaticJsStrings, utf16}, + string::common::StaticJsStrings, Context, JsArgs, JsResult, JsString, JsValue, }; use boa_profiler::Profiler; @@ -36,8 +36,8 @@ impl IntrinsicObject for UriError { BuiltInBuilder::from_standard_constructor::(realm) .prototype(realm.intrinsics().constructors().error().constructor()) .inherits(Some(realm.intrinsics().constructors().error().prototype())) - .property(utf16!("name"), Self::NAME, attribute) - .property(utf16!("message"), js_string!(), attribute) + .property("name", Self::NAME, attribute) + .property("message", js_string!(), attribute) .build(); } @@ -93,7 +93,7 @@ impl BuiltInConstructor for UriError { let msg = message.to_string(context)?; // b. Perform CreateNonEnumerableDataPropertyOrThrow(O, "message", msg). - o.create_non_enumerable_data_property_or_throw(utf16!("message"), msg, context); + o.create_non_enumerable_data_property_or_throw("message", msg, context); } // 4. Perform ? InstallErrorCause(O, options). diff --git a/boa_engine/src/builtins/escape/mod.rs b/boa_engine/src/builtins/escape/mod.rs index ea2c07f7bf5..c7b069ab3ab 100644 --- a/boa_engine/src/builtins/escape/mod.rs +++ b/boa_engine/src/builtins/escape/mod.rs @@ -59,7 +59,7 @@ fn escape(_: &JsValue, args: &[JsValue], context: &mut Context<'_>) -> JsResult< // 5. Let k be 0. // 6. Repeat, while k < len, // a. Let C be the code unit at index k within string. - for &cp in &*string { + for cp in string.iter() { // b. If unescapedSet contains C, then if is_unescaped(cp) { // i. Let S be C. @@ -86,7 +86,7 @@ fn escape(_: &JsValue, args: &[JsValue], context: &mut Context<'_>) -> JsResult< } // 7. Return R. - Ok(js_string!(vec).into()) + Ok(js_string!(&vec[..]).into()) } /// The `unescape` function @@ -124,7 +124,7 @@ fn unescape(_: &JsValue, args: &[JsValue], context: &mut Context<'_>) -> JsResul // 3. Let R be the empty String. let mut vec = Vec::with_capacity(string.len()); - let mut codepoints = >::new(string.iter().copied()); + let mut codepoints = >::new(string.iter()); // 2. Let len be the length of string. // 4. Let k be 0. @@ -192,7 +192,7 @@ fn unescape(_: &JsValue, args: &[JsValue], context: &mut Context<'_>) -> JsResul vec.push(unescaped_cp); } // 6. Return R. - Ok(js_string!(vec).into()) + Ok(js_string!(&vec[..]).into()) } /// An iterator that can peek `N` items. diff --git a/boa_engine/src/builtins/function/mod.rs b/boa_engine/src/builtins/function/mod.rs index 74e8ce61c2d..c7c391a07c9 100644 --- a/boa_engine/src/builtins/function/mod.rs +++ b/boa_engine/src/builtins/function/mod.rs @@ -345,26 +345,26 @@ impl IntrinsicObject for BuiltInFunctionObject { let _timer = Profiler::global().start_event(std::any::type_name::(), "init"); let has_instance = BuiltInBuilder::callable(realm, Self::has_instance) - .name(js_string!("[Symbol.hasInstance]")) + .name("[Symbol.hasInstance]") .length(1) .build(); let throw_type_error = realm.intrinsics().objects().throw_type_error(); BuiltInBuilder::from_standard_constructor::(realm) - .method(Self::apply, js_string!("apply"), 2) - .method(Self::bind, js_string!("bind"), 1) - .method(Self::call, js_string!("call"), 1) - .method(Self::to_string, js_string!("toString"), 0) + .method(Self::apply, "apply", 2) + .method(Self::bind, "bind", 1) + .method(Self::call, "call", 1) + .method(Self::to_string, "toString", 0) .property(JsSymbol::has_instance(), has_instance, Attribute::default()) .accessor( - utf16!("caller"), + "caller", Some(throw_type_error.clone()), Some(throw_type_error.clone()), Attribute::CONFIGURABLE, ) .accessor( - utf16!("arguments"), + "arguments", Some(throw_type_error.clone()), Some(throw_type_error), Attribute::CONFIGURABLE, @@ -492,7 +492,7 @@ impl BuiltInFunctionObject { } else { let mut parameters = Vec::with_capacity(args.len()); for arg in args { - parameters.push(arg.to_string(context)?); + parameters.push(arg.to_string(context)?.to_vec()); } let parameters = parameters.join(utf16!(",")); @@ -766,9 +766,9 @@ impl BuiltInFunctionObject { // 5. Let targetHasLength be ? HasOwnProperty(Target, "length"). // 6. If targetHasLength is true, then - if target.has_own_property(utf16!("length"), context)? { + if target.has_own_property("length", context)? { // a. Let targetLen be ? Get(Target, "length"). - let target_len = target.get(utf16!("length"), context)?; + let target_len = target.get("length", context)?; // b. If Type(targetLen) is Number, then if target_len.is_number() { // 1. Let targetLenAsInt be ! ToIntegerOrInfinity(targetLen). @@ -793,7 +793,7 @@ impl BuiltInFunctionObject { // 7. Perform ! SetFunctionLength(F, L). f.define_property_or_throw( - utf16!("length"), + "length", PropertyDescriptor::builder() .value(l) .writable(false) @@ -804,7 +804,7 @@ impl BuiltInFunctionObject { .expect("defining the `length` property for a new object should not fail"); // 8. Let targetName be ? Get(Target, "name"). - let target_name = target.get(utf16!("name"), context)?; + let target_name = target.get("name", context)?; // 9. If Type(targetName) is not String, set targetName to the empty String. let target_name = target_name @@ -880,18 +880,16 @@ impl BuiltInFunctionObject { let value = this .as_object() .expect("checked that `this` was an object above") - .get(utf16!("name"), &mut *context)?; + .get("name", &mut *context)?; if value.is_null_or_undefined() { js_string!() } else { value.to_string(context)? } }; - return Ok( - js_string!(utf16!("function "), &name, utf16!("() { [native code] }")).into(), - ); + return Ok(js_string!("function ", &name, "() { [native code] }").into()); } else if object.is_proxy() || object.is_bound_function() { - return Ok(js_string!(utf16!("function () { [native code] }")).into()); + return Ok(js_string!("function () { [native code] }").into()); } let function = object @@ -900,12 +898,7 @@ impl BuiltInFunctionObject { let code = function.codeblock(); - Ok(js_string!( - utf16!("function "), - code.name(), - utf16!("() { [native code] }") - ) - .into()) + Ok(js_string!("function ", code.name(), "() { [native code] }").into()) } /// `Function.prototype [ @@hasInstance ] ( V )` @@ -949,10 +942,8 @@ pub(crate) fn set_function_name( // a. Let description be name's [[Description]] value. // b. If description is undefined, set name to the empty String. // c. Else, set name to the string-concatenation of "[", description, and "]". - sym.description().map_or_else( - || js_string!(), - |desc| js_string!(utf16!("["), &desc, utf16!("]")), - ) + sym.description() + .map_or_else(|| js_string!(), |desc| js_string!("[", &desc, "]")) } PropertyKey::String(string) => string.clone(), PropertyKey::Index(index) => js_string!(format!("{}", index.get())), @@ -968,7 +959,7 @@ pub(crate) fn set_function_name( // 5. If prefix is present, then if let Some(prefix) = prefix { - name = js_string!(&prefix, utf16!(" "), &name); + name = js_string!(&prefix, " ", &name); // b. If F has an [[InitialName]] internal slot, then // i. Optionally, set F.[[InitialName]] to name. // todo: implement [[InitialName]] for builtins @@ -978,7 +969,7 @@ pub(crate) fn set_function_name( // [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }). function .define_property_or_throw( - utf16!("name"), + "name", PropertyDescriptor::builder() .value(name) .writable(false) diff --git a/boa_engine/src/builtins/function/tests.rs b/boa_engine/src/builtins/function/tests.rs index 7a4cf494fed..5bc02b9c7c4 100644 --- a/boa_engine/src/builtins/function/tests.rs +++ b/boa_engine/src/builtins/function/tests.rs @@ -153,7 +153,7 @@ fn closure_capture_clone() { let hw = js_string!( string, &object - .__get_own_property__(&js_string!("key").into(), context)? + .__get_own_property__(&"key".into(), context)? .and_then(|prop| prop.value().cloned()) .and_then(|val| val.as_string().cloned()) .ok_or_else( diff --git a/boa_engine/src/builtins/generator/mod.rs b/boa_engine/src/builtins/generator/mod.rs index fc063eaab85..efdb2ca420b 100644 --- a/boa_engine/src/builtins/generator/mod.rs +++ b/boa_engine/src/builtins/generator/mod.rs @@ -14,7 +14,6 @@ use crate::{ context::intrinsics::Intrinsics, environments::EnvironmentStack, error::JsNativeError, - js_string, object::{JsObject, CONSTRUCTOR}, property::Attribute, realm::Realm, @@ -148,9 +147,9 @@ impl IntrinsicObject for Generator { .iterator_prototypes() .iterator(), ) - .static_method(Self::next, js_string!("next"), 1) - .static_method(Self::r#return, js_string!("return"), 1) - .static_method(Self::throw, js_string!("throw"), 1) + .static_method(Self::next, "next", 1) + .static_method(Self::r#return, "return", 1) + .static_method(Self::throw, "throw", 1) .static_property( JsSymbol::to_string_tag(), Self::NAME, diff --git a/boa_engine/src/builtins/intl/collator/mod.rs b/boa_engine/src/builtins/intl/collator/mod.rs index 61f10b900b9..edd6140b3cc 100644 --- a/boa_engine/src/builtins/intl/collator/mod.rs +++ b/boa_engine/src/builtins/intl/collator/mod.rs @@ -27,7 +27,7 @@ use crate::{ }, property::Attribute, realm::Realm, - string::{common::StaticJsStrings, utf16}, + string::common::StaticJsStrings, symbol::JsSymbol, Context, JsArgs, JsNativeError, JsResult, JsString, JsValue, }; @@ -153,27 +153,18 @@ impl IntrinsicObject for Collator { let _timer = Profiler::global().start_event(std::any::type_name::(), "init"); let compare = BuiltInBuilder::callable(realm, Self::compare) - .name(js_string!("get compare")) + .name("get compare") .build(); BuiltInBuilder::from_standard_constructor::(realm) - .static_method( - Self::supported_locales_of, - js_string!("supportedLocalesOf"), - 1, - ) + .static_method(Self::supported_locales_of, "supportedLocalesOf", 1) .property( JsSymbol::to_string_tag(), js_string!("Intl.Collator"), Attribute::CONFIGURABLE, ) - .accessor( - js_string!("compare"), - Some(compare), - None, - Attribute::CONFIGURABLE, - ) - .method(Self::resolved_options, js_string!("resolvedOptions"), 0) + .accessor("compare", Some(compare), None, Attribute::CONFIGURABLE) + .method(Self::resolved_options, "resolvedOptions", 0) .build(); } @@ -241,28 +232,28 @@ impl BuiltInConstructor for Collator { // a. Let localeData be %Collator%.[[SortLocaleData]]. // 6. Else, // a. Let localeData be %Collator%.[[SearchLocaleData]]. - let usage = get_option(&options, utf16!("usage"), context)?.unwrap_or_default(); + let usage = get_option(&options, "usage", context)?.unwrap_or_default(); // 7. Let opt be a new Record. // 8. Let matcher be ? GetOption(options, "localeMatcher", string, « "lookup", "best fit" », "best fit"). // 9. Set opt.[[localeMatcher]] to matcher. - let matcher = get_option(&options, utf16!("localeMatcher"), context)?.unwrap_or_default(); + let matcher = get_option(&options, "localeMatcher", context)?.unwrap_or_default(); // 10. Let collation be ? GetOption(options, "collation", string, empty, undefined). // 11. If collation is not undefined, then // a. If collation does not match the Unicode Locale Identifier type nonterminal, throw a RangeError exception. // 12. Set opt.[[co]] to collation. - let collation = get_option(&options, utf16!("collation"), context)?; + let collation = get_option(&options, "collation", context)?; // 13. Let numeric be ? GetOption(options, "numeric", boolean, empty, undefined). // 14. If numeric is not undefined, then // a. Let numeric be ! ToString(numeric). // 15. Set opt.[[kn]] to numeric. - let numeric = get_option(&options, utf16!("numeric"), context)?; + let numeric = get_option(&options, "numeric", context)?; // 16. Let caseFirst be ? GetOption(options, "caseFirst", string, « "upper", "lower", "false" », undefined). // 17. Set opt.[[kf]] to caseFirst. - let case_first = get_option(&options, utf16!("caseFirst"), context)?; + let case_first = get_option(&options, "caseFirst", context)?; let mut intl_options = IntlOptions { matcher, @@ -311,7 +302,7 @@ impl BuiltInConstructor for Collator { // 26. Let sensitivity be ? GetOption(options, "sensitivity", string, « "base", "accent", "case", "variant" », undefined). // 28. Set collator.[[Sensitivity]] to sensitivity. - let sensitivity = get_option(&options, utf16!("sensitivity"), context)? + let sensitivity = get_option(&options, "sensitivity", context)? // 27. If sensitivity is undefined, then // a. If usage is "sort", then // i. Let sensitivity be "variant". @@ -324,7 +315,7 @@ impl BuiltInConstructor for Collator { // 29. Let ignorePunctuation be ? GetOption(options, "ignorePunctuation", boolean, empty, false). // 30. Set collator.[[IgnorePunctuation]] to ignorePunctuation. let ignore_punctuation: bool = - get_option(&options, utf16!("ignorePunctuation"), context)?.unwrap_or_default(); + get_option(&options, "ignorePunctuation", context)?.unwrap_or_default(); let (strength, case_level) = sensitivity.map(Sensitivity::to_collator_options).unzip(); @@ -441,13 +432,22 @@ impl Collator { // 3. If x is not provided, let x be undefined. // 5. Let X be ? ToString(x). - let x = args.get_or_undefined(0).to_string(context)?; + let x = args + .get_or_undefined(0) + .to_string(context)? + .iter() + .collect::>(); // 4. If y is not provided, let y be undefined. // 6. Let Y be ? ToString(y). - let y = args.get_or_undefined(1).to_string(context)?; + let y = args + .get_or_undefined(1) + .to_string(context)? + .iter() + .collect::>(); // 7. Return CompareStrings(collator, X, Y). + let result = collator.collator.compare_utf16(&x, &y) as i32; Ok(result.into()) @@ -511,14 +511,14 @@ impl Collator { // 5. Return options. options .create_data_property_or_throw( - utf16!("locale"), + "locale", js_string!(collator.locale.to_string()), context, ) .expect("operation must not fail per the spec"); options .create_data_property_or_throw( - utf16!("usage"), + "usage", match collator.usage { Usage::Search => js_string!("search"), Usage::Sort => js_string!("sort"), @@ -528,7 +528,7 @@ impl Collator { .expect("operation must not fail per the spec"); options .create_data_property_or_throw( - utf16!("sensitivity"), + "sensitivity", match collator.sensitivity { Sensitivity::Base => js_string!("base"), Sensitivity::Accent => js_string!("accent"), @@ -553,7 +553,7 @@ impl Collator { ) .expect("operation must not fail per the spec"); options - .create_data_property_or_throw(utf16!("numeric"), collator.numeric, context) + .create_data_property_or_throw("numeric", collator.numeric, context) .expect("operation must not fail per the spec"); if let Some(kf) = collator.case_first { options diff --git a/boa_engine/src/builtins/intl/date_time_format.rs b/boa_engine/src/builtins/intl/date_time_format.rs index 1cad2c007b0..ff324cc537e 100644 --- a/boa_engine/src/builtins/intl/date_time_format.rs +++ b/boa_engine/src/builtins/intl/date_time_format.rs @@ -16,7 +16,7 @@ use crate::{ js_string, object::{internal_methods::get_prototype_from_constructor, JsObject, ObjectData}, realm::Realm, - string::{common::StaticJsStrings, utf16}, + string::common::StaticJsStrings, Context, JsResult, JsString, JsValue, }; @@ -203,12 +203,7 @@ pub(crate) fn to_date_time_options( // 4. If required is "date" or "any", then if [DateTimeReqs::Date, DateTimeReqs::AnyAll].contains(required) { // a. For each property name prop of « "weekday", "year", "month", "day" », do - for property in [ - utf16!("weekday"), - utf16!("year"), - utf16!("month"), - utf16!("day"), - ] { + for property in ["weekday", "year", "month", "day"] { // i. Let value be ? Get(options, prop). let value = options.get(property, context)?; @@ -224,11 +219,11 @@ pub(crate) fn to_date_time_options( // a. For each property name prop of « "dayPeriod", "hour", "minute", "second", // "fractionalSecondDigits" », do for property in [ - utf16!("dayPeriod"), - utf16!("hour"), - utf16!("minute"), - utf16!("second"), - utf16!("fractionalSecondDigits"), + "dayPeriod", + "hour", + "minute", + "second", + "fractionalSecondDigits", ] { // i. Let value be ? Get(options, prop). let value = options.get(property, context)?; @@ -241,10 +236,10 @@ pub(crate) fn to_date_time_options( } // 6. Let dateStyle be ? Get(options, "dateStyle"). - let date_style = options.get(utf16!("dateStyle"), context)?; + let date_style = options.get("dateStyle", context)?; // 7. Let timeStyle be ? Get(options, "timeStyle"). - let time_style = options.get(utf16!("timeStyle"), context)?; + let time_style = options.get("timeStyle", context)?; // 8. If dateStyle is not undefined or timeStyle is not undefined, let needDefaults be false. if !date_style.is_undefined() || !time_style.is_undefined() { @@ -270,7 +265,7 @@ pub(crate) fn to_date_time_options( // 11. If needDefaults is true and defaults is either "date" or "all", then if need_defaults && [DateTimeReqs::Date, DateTimeReqs::AnyAll].contains(defaults) { // a. For each property name prop of « "year", "month", "day" », do - for property in [utf16!("year"), utf16!("month"), utf16!("day")] { + for property in ["year", "month", "day"] { // i. Perform ? CreateDataPropertyOrThrow(options, prop, "numeric"). options.create_data_property_or_throw(property, js_string!("numeric"), context)?; } @@ -279,7 +274,7 @@ pub(crate) fn to_date_time_options( // 12. If needDefaults is true and defaults is either "time" or "all", then if need_defaults && [DateTimeReqs::Time, DateTimeReqs::AnyAll].contains(defaults) { // a. For each property name prop of « "hour", "minute", "second" », do - for property in [utf16!("hour"), utf16!("minute"), utf16!("second")] { + for property in ["hour", "minute", "second"] { // i. Perform ? CreateDataPropertyOrThrow(options, prop, "numeric"). options.create_data_property_or_throw(property, js_string!("numeric"), context)?; } diff --git a/boa_engine/src/builtins/intl/list_format/mod.rs b/boa_engine/src/builtins/intl/list_format/mod.rs index 59e114ab3b9..3e5609c0bbb 100644 --- a/boa_engine/src/builtins/intl/list_format/mod.rs +++ b/boa_engine/src/builtins/intl/list_format/mod.rs @@ -15,7 +15,7 @@ use crate::{ object::{internal_methods::get_prototype_from_constructor, JsObject, ObjectData}, property::Attribute, realm::Realm, - string::{common::StaticJsStrings, utf16}, + string::common::StaticJsStrings, symbol::JsSymbol, Context, JsArgs, JsNativeError, JsResult, JsString, JsValue, }; @@ -48,19 +48,15 @@ impl IntrinsicObject for ListFormat { let _timer = Profiler::global().start_event(std::any::type_name::(), "init"); BuiltInBuilder::from_standard_constructor::(realm) - .static_method( - Self::supported_locales_of, - js_string!("supportedLocalesOf"), - 1, - ) + .static_method(Self::supported_locales_of, "supportedLocalesOf", 1) .property( JsSymbol::to_string_tag(), js_string!("Intl.ListFormat"), Attribute::CONFIGURABLE, ) - .method(Self::format, js_string!("format"), 1) - .method(Self::format_to_parts, js_string!("formatToParts"), 1) - .method(Self::resolved_options, js_string!("resolvedOptions"), 0) + .method(Self::format, "format", 1) + .method(Self::format_to_parts, "formatToParts", 1) + .method(Self::resolved_options, "resolvedOptions", 0) .build(); } @@ -111,7 +107,7 @@ impl BuiltInConstructor for ListFormat { // 5. Let opt be a new Record. // 6. Let matcher be ? GetOption(options, "localeMatcher", string, « "lookup", "best fit" », "best fit"). - let matcher = get_option(&options, utf16!("localeMatcher"), context)?.unwrap_or_default(); + let matcher = get_option(&options, "localeMatcher", context)?.unwrap_or_default(); // 7. Set opt.[[localeMatcher]] to matcher. // 8. Let localeData be %ListFormat%.[[LocaleData]]. @@ -128,11 +124,11 @@ impl BuiltInConstructor for ListFormat { // 11. Let type be ? GetOption(options, "type", string, « "conjunction", "disjunction", "unit" », "conjunction"). // 12. Set listFormat.[[Type]] to type. - let typ = get_option(&options, utf16!("type"), context)?.unwrap_or_default(); + let typ = get_option(&options, "type", context)?.unwrap_or_default(); // 13. Let style be ? GetOption(options, "style", string, « "long", "short", "narrow" », "long"). // 14. Set listFormat.[[Style]] to style. - let style = get_option(&options, utf16!("style"), context)?.unwrap_or(ListLength::Wide); + let style = get_option(&options, "style", context)?.unwrap_or(ListLength::Wide); // 15. Let dataLocale be r.[[dataLocale]]. // 16. Let dataLocaleData be localeData.[[]]. @@ -377,11 +373,11 @@ impl ListFormat { .create(ObjectData::ordinary(), vec![]); // b. Perform ! CreateDataPropertyOrThrow(O, "type", part.[[Type]]). - o.create_data_property_or_throw(utf16!("type"), js_string!(part.typ()), context) + o.create_data_property_or_throw("type", js_string!(part.typ()), context) .expect("operation must not fail per the spec"); // c. Perform ! CreateDataPropertyOrThrow(O, "value", part.[[Value]]). - o.create_data_property_or_throw(utf16!("value"), js_string!(part.value()), context) + o.create_data_property_or_throw("value", js_string!(part.value()), context) .expect("operation must not fail per the spec"); // d. Perform ! CreateDataPropertyOrThrow(result, ! ToString(n), O). @@ -435,15 +431,11 @@ impl ListFormat { // c. Assert: v is not undefined. // d. Perform ! CreateDataPropertyOrThrow(options, p, v). options - .create_data_property_or_throw( - utf16!("locale"), - js_string!(lf.locale.to_string()), - context, - ) + .create_data_property_or_throw("locale", js_string!(lf.locale.to_string()), context) .expect("operation must not fail per the spec"); options .create_data_property_or_throw( - js_string!("type"), + "type", match lf.typ { ListFormatType::Conjunction => js_string!("conjunction"), ListFormatType::Disjunction => js_string!("disjunction"), @@ -454,7 +446,7 @@ impl ListFormat { .expect("operation must not fail per the spec"); options .create_data_property_or_throw( - js_string!("style"), + "style", match lf.style { ListLength::Wide => js_string!("long"), ListLength::Short => js_string!("short"), diff --git a/boa_engine/src/builtins/intl/locale/mod.rs b/boa_engine/src/builtins/intl/locale/mod.rs index 3af04a84568..8584b2824d4 100644 --- a/boa_engine/src/builtins/intl/locale/mod.rs +++ b/boa_engine/src/builtins/intl/locale/mod.rs @@ -1,8 +1,4 @@ -use crate::{ - builtins::options::get_option, - realm::Realm, - string::{common::StaticJsStrings, utf16}, -}; +use crate::{builtins::options::get_option, realm::Realm, string::common::StaticJsStrings}; use boa_profiler::Profiler; use icu_collator::CaseFirst; use icu_datetime::options::preferences::HourCycle; @@ -38,43 +34,43 @@ impl IntrinsicObject for Locale { let _timer = Profiler::global().start_event(std::any::type_name::(), "init"); let base_name = BuiltInBuilder::callable(realm, Self::base_name) - .name(js_string!("get baseName")) + .name("get baseName") .build(); let calendar = BuiltInBuilder::callable(realm, Self::calendar) - .name(js_string!("get calendar")) + .name("get calendar") .build(); let case_first = BuiltInBuilder::callable(realm, Self::case_first) - .name(js_string!("get caseFirst")) + .name("get caseFirst") .build(); let collation = BuiltInBuilder::callable(realm, Self::collation) - .name(js_string!("get collation")) + .name("get collation") .build(); let hour_cycle = BuiltInBuilder::callable(realm, Self::hour_cycle) - .name(js_string!("get hourCycle")) + .name("get hourCycle") .build(); let numeric = BuiltInBuilder::callable(realm, Self::numeric) - .name(js_string!("get numeric")) + .name("get numeric") .build(); let numbering_system = BuiltInBuilder::callable(realm, Self::numbering_system) - .name(js_string!("get numberingSystem")) + .name("get numberingSystem") .build(); let language = BuiltInBuilder::callable(realm, Self::language) - .name(js_string!("get language")) + .name("get language") .build(); let script = BuiltInBuilder::callable(realm, Self::script) - .name(js_string!("get script")) + .name("get script") .build(); let region = BuiltInBuilder::callable(realm, Self::region) - .name(js_string!("get region")) + .name("get region") .build(); BuiltInBuilder::from_standard_constructor::(realm) @@ -83,69 +79,24 @@ impl IntrinsicObject for Locale { js_string!("Intl.Locale"), Attribute::CONFIGURABLE, ) - .method(Self::maximize, js_string!("maximize"), 0) - .method(Self::minimize, js_string!("minimize"), 0) - .method(Self::to_string, js_string!("toString"), 0) - .accessor( - js_string!("baseName"), - Some(base_name), - None, - Attribute::CONFIGURABLE, - ) - .accessor( - js_string!("calendar"), - Some(calendar), - None, - Attribute::CONFIGURABLE, - ) - .accessor( - js_string!("caseFirst"), - Some(case_first), - None, - Attribute::CONFIGURABLE, - ) - .accessor( - js_string!("collation"), - Some(collation), - None, - Attribute::CONFIGURABLE, - ) - .accessor( - js_string!("hourCycle"), - Some(hour_cycle), - None, - Attribute::CONFIGURABLE, - ) - .accessor( - js_string!("numeric"), - Some(numeric), - None, - Attribute::CONFIGURABLE, - ) + .method(Self::maximize, "maximize", 0) + .method(Self::minimize, "minimize", 0) + .method(Self::to_string, "toString", 0) + .accessor("baseName", Some(base_name), None, Attribute::CONFIGURABLE) + .accessor("calendar", Some(calendar), None, Attribute::CONFIGURABLE) + .accessor("caseFirst", Some(case_first), None, Attribute::CONFIGURABLE) + .accessor("collation", Some(collation), None, Attribute::CONFIGURABLE) + .accessor("hourCycle", Some(hour_cycle), None, Attribute::CONFIGURABLE) + .accessor("numeric", Some(numeric), None, Attribute::CONFIGURABLE) .accessor( - js_string!("numberingSystem"), + "numberingSystem", Some(numbering_system), None, Attribute::CONFIGURABLE, ) - .accessor( - js_string!("language"), - Some(language), - None, - Attribute::CONFIGURABLE, - ) - .accessor( - js_string!("script"), - Some(script), - None, - Attribute::CONFIGURABLE, - ) - .accessor( - js_string!("region"), - Some(region), - None, - Attribute::CONFIGURABLE, - ) + .accessor("language", Some(language), None, Attribute::CONFIGURABLE) + .accessor("script", Some(script), None, Attribute::CONFIGURABLE) + .accessor("region", Some(region), None, Attribute::CONFIGURABLE) .build(); } @@ -236,17 +187,17 @@ impl BuiltInConstructor for Locale { // 4. Let language be ? GetOption(options, "language", string, empty, undefined). // 5. If language is not undefined, then // a. If language does not match the unicode_language_subtag production, throw a RangeError exception. - let language = get_option(options, utf16!("language"), context)?; + let language = get_option(options, "language", context)?; // 6. Let script be ? GetOption(options, "script", string, empty, undefined). // 7. If script is not undefined, then // a. If script does not match the unicode_script_subtag production, throw a RangeError exception. - let script = get_option(options, utf16!("script"), context)?; + let script = get_option(options, "script", context)?; // 8. Let region be ? GetOption(options, "region", string, empty, undefined). // 9. If region is not undefined, then // a. If region does not match the unicode_region_subtag production, throw a RangeError exception. - let region = get_option(options, utf16!("region"), context)?; + let region = get_option(options, "region", context)?; // 10. Set tag to ! CanonicalizeUnicodeLocaleId(tag). context.icu().locale_canonicalizer().canonicalize(&mut tag); @@ -288,17 +239,17 @@ impl BuiltInConstructor for Locale { // 14. If calendar is not undefined, then // 15. Set opt.[[ca]] to calendar. // a. If calendar does not match the Unicode Locale Identifier type nonterminal, throw a RangeError exception. - let ca = get_option(options, utf16!("calendar"), context)?; + let ca = get_option(options, "calendar", context)?; // 16. Let collation be ? GetOption(options, "collation", string, empty, undefined). // 17. If collation is not undefined, then // 18. Set opt.[[co]] to collation. // a. If collation does not match the Unicode Locale Identifier type nonterminal, throw a RangeError exception. - let co = get_option(options, utf16!("collation"), context)?; + let co = get_option(options, "collation", context)?; // 19. Let hc be ? GetOption(options, "hourCycle", string, « "h11", "h12", "h23", "h24" », undefined). // 20. Set opt.[[hc]] to hc. - let hc = get_option(options, utf16!("hourCycle"), context)?.map(|hc| match hc { + let hc = get_option(options, "hourCycle", context)?.map(|hc| match hc { HourCycle::H24 => value!("h24"), HourCycle::H23 => value!("h23"), HourCycle::H12 => value!("h12"), @@ -307,7 +258,7 @@ impl BuiltInConstructor for Locale { // 21. Let kf be ? GetOption(options, "caseFirst", string, « "upper", "lower", "false" », undefined). // 22. Set opt.[[kf]] to kf. - let kf = get_option(options, utf16!("caseFirst"), context)?.map(|kf| match kf { + let kf = get_option(options, "caseFirst", context)?.map(|kf| match kf { CaseFirst::UpperFirst => value!("upper"), CaseFirst::LowerFirst => value!("lower"), CaseFirst::Off => value!("false"), @@ -317,7 +268,7 @@ impl BuiltInConstructor for Locale { // 23. Let kn be ? GetOption(options, "numeric", boolean, empty, undefined). // 24. If kn is not undefined, set kn to ! ToString(kn). // 25. Set opt.[[kn]] to kn. - let kn = get_option(options, utf16!("numeric"), context)?.map(|b| { + let kn = get_option(options, "numeric", context)?.map(|b| { if b { value!("true") } else { @@ -329,7 +280,7 @@ impl BuiltInConstructor for Locale { // 27. If numberingSystem is not undefined, then // 28. Set opt.[[nu]] to numberingSystem. // a. If numberingSystem does not match the Unicode Locale Identifier type nonterminal, throw a RangeError exception. - let nu = get_option(options, utf16!("numberingSystem"), context)?; + let nu = get_option(options, "numberingSystem", context)?; // 29. Let r be ! ApplyUnicodeExtensionToTag(tag, opt, relevantExtensionKeys). // 30. Set locale.[[Locale]] to r.[[locale]]. diff --git a/boa_engine/src/builtins/intl/locale/utils.rs b/boa_engine/src/builtins/intl/locale/utils.rs index 33d8766507e..ae84c7fef04 100644 --- a/boa_engine/src/builtins/intl/locale/utils.rs +++ b/boa_engine/src/builtins/intl/locale/utils.rs @@ -10,7 +10,6 @@ use crate::{ context::{icu::Icu, BoaProvider}, js_string, object::JsObject, - string::utf16, Context, JsNativeError, JsResult, JsValue, }; @@ -546,7 +545,7 @@ where let options = coerce_options_to_object(options, context)?; // 2. Let matcher be ? GetOption(options, "localeMatcher", string, « "lookup", "best fit" », "best fit"). - let matcher = get_option(&options, utf16!("localeMatcher"), context)?.unwrap_or_default(); + let matcher = get_option(&options, "localeMatcher", context)?.unwrap_or_default(); let elements = match matcher { // 4. Else, diff --git a/boa_engine/src/builtins/intl/mod.rs b/boa_engine/src/builtins/intl/mod.rs index 9592b6914a9..f09c077b7df 100644 --- a/boa_engine/src/builtins/intl/mod.rs +++ b/boa_engine/src/builtins/intl/mod.rs @@ -99,11 +99,7 @@ impl IntrinsicObject for Intl { .constructor(), DateTimeFormat::ATTRIBUTE, ) - .static_method( - Self::get_canonical_locales, - js_string!("getCanonicalLocales"), - 1, - ) + .static_method(Self::get_canonical_locales, "getCanonicalLocales", 1) .build(); } diff --git a/boa_engine/src/builtins/intl/number_format/utils.rs b/boa_engine/src/builtins/intl/number_format/utils.rs index ac6670bff95..c323c8ea0fa 100644 --- a/boa_engine/src/builtins/intl/number_format/utils.rs +++ b/boa_engine/src/builtins/intl/number_format/utils.rs @@ -1,4 +1,3 @@ -use boa_macros::utf16; use fixed_decimal::{FixedDecimal, FloatPrecision}; use crate::{ @@ -32,24 +31,24 @@ pub(crate) fn get_digit_format_options( // 1. Let mnid be ? GetNumberOption(options, "minimumIntegerDigits,", 1, 21, 1). let minimum_integer_digits = - get_number_option(options, utf16!("minimumIntegerDigits"), 1, 21, context)?.unwrap_or(1); + get_number_option(options, "minimumIntegerDigits", 1, 21, context)?.unwrap_or(1); // 2. Let mnfd be ? Get(options, "minimumFractionDigits"). - let min_float_digits = options.get(utf16!("minimumFractionDigits"), context)?; + let min_float_digits = options.get("minimumFractionDigits", context)?; // 3. Let mxfd be ? Get(options, "maximumFractionDigits"). - let max_float_digits = options.get(utf16!("maximumFractionDigits"), context)?; + let max_float_digits = options.get("maximumFractionDigits", context)?; // 4. Let mnsd be ? Get(options, "minimumSignificantDigits"). - let min_sig_digits = options.get(utf16!("minimumSignificantDigits"), context)?; + let min_sig_digits = options.get("minimumSignificantDigits", context)?; // 5. Let mxsd be ? Get(options, "maximumSignificantDigits"). - let max_sig_digits = options.get(utf16!("maximumSignificantDigits"), context)?; + let max_sig_digits = options.get("maximumSignificantDigits", context)?; // 7. Let roundingPriority be ? GetOption(options, "roundingPriority", string, « "auto", "morePrecision", "lessPrecision" », "auto"). let mut rounding_priority = - get_option(options, utf16!("roundingPriority"), context)?.unwrap_or_default(); + get_option(options, "roundingPriority", context)?.unwrap_or_default(); // 8. Let roundingIncrement be ? GetNumberOption(options, "roundingIncrement", 1, 5000, 1). // 9. If roundingIncrement is not in « 1, 2, 5, 10, 20, 25, 50, 100, 200, 250, 500, 1000, 2000, 2500, 5000 », throw a RangeError exception. let rounding_increment = - get_number_option(options, utf16!("roundingIncrement"), 1, 5000, context)?.unwrap_or(1); + get_number_option(options, "roundingIncrement", 1, 5000, context)?.unwrap_or(1); if !VALID_ROUNDING_INCREMENTS.contains(&rounding_increment) { return Err(JsNativeError::range() @@ -58,11 +57,11 @@ pub(crate) fn get_digit_format_options( } // 10. Let roundingMode be ? GetOption(options, "roundingMode", string, « "ceil", "floor", "expand", "trunc", "halfCeil", "halfFloor", "halfExpand", "halfTrunc", "halfEven" », "halfExpand"). - let rounding_mode = get_option(options, utf16!("roundingMode"), context)?.unwrap_or_default(); + let rounding_mode = get_option(options, "roundingMode", context)?.unwrap_or_default(); // 11. Let trailingZeroDisplay be ? GetOption(options, "trailingZeroDisplay", string, « "auto", "stripIfInteger" », "auto"). let trailing_zero_display = - get_option(options, utf16!("trailingZeroDisplay"), context)?.unwrap_or_default(); + get_option(options, "trailingZeroDisplay", context)?.unwrap_or_default(); // 12. NOTE: All fields required by SetNumberFormatDigitOptions have now been read from options. The remainder of this AO interprets the options and may throw exceptions. diff --git a/boa_engine/src/builtins/intl/options.rs b/boa_engine/src/builtins/intl/options.rs index 73168d4e888..377ece85fa8 100644 --- a/boa_engine/src/builtins/intl/options.rs +++ b/boa_engine/src/builtins/intl/options.rs @@ -60,7 +60,7 @@ impl ParsableOptionType for LocaleMatcher {} /// [spec]: https://tc39.es/ecma402/#sec-getnumberoption pub(super) fn get_number_option( options: &JsObject, - property: &[u16], + property: &str, minimum: T, maximum: T, context: &mut Context<'_>, diff --git a/boa_engine/src/builtins/intl/plural_rules/mod.rs b/boa_engine/src/builtins/intl/plural_rules/mod.rs index ac8bfae8ebf..8209d5d69a1 100644 --- a/boa_engine/src/builtins/intl/plural_rules/mod.rs +++ b/boa_engine/src/builtins/intl/plural_rules/mod.rs @@ -1,6 +1,5 @@ mod options; -use boa_macros::utf16; use boa_profiler::Profiler; use fixed_decimal::FixedDecimal; use icu_locid::Locale; @@ -52,18 +51,14 @@ impl IntrinsicObject for PluralRules { let _timer = Profiler::global().start_event(std::any::type_name::(), "init"); BuiltInBuilder::from_standard_constructor::(realm) - .static_method( - Self::supported_locales_of, - js_string!("supportedLocalesOf"), - 1, - ) + .static_method(Self::supported_locales_of, "supportedLocalesOf", 1) .property( JsSymbol::to_string_tag(), js_string!("Intl.PluralRules"), Attribute::CONFIGURABLE, ) - .method(Self::resolved_options, js_string!("resolvedOptions"), 0) - .method(Self::select, js_string!("select"), 1) + .method(Self::resolved_options, "resolvedOptions", 0) + .method(Self::select, "select", 1) .build(); } @@ -113,12 +108,11 @@ impl BuiltInConstructor for PluralRules { // 3. Let opt be a new Record. // 4. Let matcher be ? GetOption(options, "localeMatcher", string, « "lookup", "best fit" », "best fit"). // 5. Set opt.[[localeMatcher]] to matcher. - let matcher = get_option(&options, utf16!("localeMatcher"), context)?.unwrap_or_default(); + let matcher = get_option(&options, "localeMatcher", context)?.unwrap_or_default(); // 6. Let t be ? GetOption(options, "type", string, « "cardinal", "ordinal" », "cardinal"). // 7. Set pluralRules.[[Type]] to t. - let rule_type = - get_option(&options, utf16!("type"), context)?.unwrap_or(PluralRuleType::Cardinal); + let rule_type = get_option(&options, "type", context)?.unwrap_or(PluralRuleType::Cardinal); // 8. Perform ? SetNumberFormatDigitOptions(pluralRules, options, +0𝔽, 3𝔽, "standard"). let format_options = get_digit_format_options(&options, 0, 3, Notation::Standard, context)?; @@ -265,12 +259,12 @@ impl PluralRules { let mut options = ObjectInitializer::new(context); options .property( - js_string!("locale"), + "locale", js_string!(plural_rules.locale.to_string()), Attribute::all(), ) .property( - js_string!("type"), + "type", match plural_rules.rule_type { PluralRuleType::Cardinal => js_string!("cardinal"), PluralRuleType::Ordinal => js_string!("ordinal"), diff --git a/boa_engine/src/builtins/intl/segmenter/iterator.rs b/boa_engine/src/builtins/intl/segmenter/iterator.rs index 5045c911b5c..5595fb0e8db 100644 --- a/boa_engine/src/builtins/intl/segmenter/iterator.rs +++ b/boa_engine/src/builtins/intl/segmenter/iterator.rs @@ -1,7 +1,9 @@ use boa_gc::{Finalize, Trace}; use boa_profiler::Profiler; use icu_segmenter::{ - GraphemeClusterBreakIteratorUtf16, SentenceBreakIteratorUtf16, WordBreakIteratorUtf16, + GraphemeClusterBreakIteratorUtf16, GraphemeClusterBreakIteratorUtf8, + SentenceBreakIteratorUtf16, SentenceBreakIteratorUtf8, WordBreakIteratorUtf16, + WordBreakIteratorUtf8, }; use crate::{ @@ -17,9 +19,12 @@ use crate::{ use super::create_segment_data_object; pub(crate) enum NativeSegmentIterator<'l, 's> { - Grapheme(GraphemeClusterBreakIteratorUtf16<'l, 's>), - Word(WordBreakIteratorUtf16<'l, 's>), - Sentence(SentenceBreakIteratorUtf16<'l, 's>), + GraphemeU16(GraphemeClusterBreakIteratorUtf16<'l, 's>), + WordU16(WordBreakIteratorUtf16<'l, 's>), + SentenceU16(SentenceBreakIteratorUtf16<'l, 's>), + GraphemeUtf8(GraphemeClusterBreakIteratorUtf8<'l, 's>), + WordUtf8(WordBreakIteratorUtf8<'l, 's>), + SentenceUtf8(SentenceBreakIteratorUtf8<'l, 's>), } impl Iterator for NativeSegmentIterator<'_, '_> { @@ -27,9 +32,12 @@ impl Iterator for NativeSegmentIterator<'_, '_> { fn next(&mut self) -> Option { match self { - NativeSegmentIterator::Grapheme(g) => g.next(), - NativeSegmentIterator::Word(w) => w.next(), - NativeSegmentIterator::Sentence(s) => s.next(), + NativeSegmentIterator::GraphemeU16(g) => g.next(), + NativeSegmentIterator::WordU16(w) => w.next(), + NativeSegmentIterator::SentenceU16(s) => s.next(), + NativeSegmentIterator::GraphemeUtf8(g) => g.next(), + NativeSegmentIterator::WordUtf8(w) => w.next(), + NativeSegmentIterator::SentenceUtf8(s) => s.next(), } } } @@ -38,7 +46,7 @@ impl NativeSegmentIterator<'_, '_> { /// If the iterator is a word break iterator, returns `Some(true)` when the segment preceding /// the current boundary is word-like. pub(crate) fn is_word_like(&self) -> Option { - if let Self::Word(w) = self { + if let Self::WordU16(w) = self { Some(w.is_word_like()) } else { None @@ -63,7 +71,7 @@ impl IntrinsicObject for SegmentIterator { js_string!("Segmenter String Iterator"), Attribute::CONFIGURABLE, ) - .static_method(Self::next, js_string!("next"), 0) + .static_method(Self::next, "next", 0) .build(); } @@ -121,13 +129,14 @@ impl SegmentIterator { // 4. Let string be iterator.[[IteratedString]]. // 6. Let endIndex be ! FindBoundary(segmenter, string, startIndex, after). - let Some((end, is_word_like)) = iter.string.get(start..).and_then(|string| { + let Some((end, is_word_like)) = iter.string.to_vec().get(start..).and_then(|string| { // 3. Let segmenter be iterator.[[IteratingSegmenter]]. let segmenter = iter.segmenter.borrow(); let segmenter = segmenter .as_segmenter() .expect("segment iterator object should contain a segmenter"); - let mut segments = segmenter.native.segment(string); + let string = js_string!(string); + let mut segments = segmenter.native.segment(&string); // the first elem is always 0. segments.next(); segments diff --git a/boa_engine/src/builtins/intl/segmenter/mod.rs b/boa_engine/src/builtins/intl/segmenter/mod.rs index c70741dafce..a24d21ebd32 100644 --- a/boa_engine/src/builtins/intl/segmenter/mod.rs +++ b/boa_engine/src/builtins/intl/segmenter/mod.rs @@ -1,6 +1,5 @@ use std::ops::Range; -use boa_macros::utf16; use boa_profiler::Profiler; use icu_locid::Locale; use icu_segmenter::{ @@ -61,11 +60,18 @@ impl NativeSegmenter { /// Segment the passed string, returning an iterator with the index boundaries /// of the segments. - pub(crate) fn segment<'l, 's>(&'l self, input: &'s [u16]) -> NativeSegmentIterator<'l, 's> { - match self { - Self::Grapheme(g) => NativeSegmentIterator::Grapheme(g.segment_utf16(input)), - Self::Word(w) => NativeSegmentIterator::Word(w.segment_utf16(input)), - Self::Sentence(s) => NativeSegmentIterator::Sentence(s.segment_utf16(input)), + pub(crate) fn segment<'l, 's>(&'l self, input: &'s JsString) -> NativeSegmentIterator<'l, 's> { + match input.as_slice() { + crate::string::JsStr::Ascii(input) => match self { + Self::Grapheme(g) => NativeSegmentIterator::GraphemeUtf8(g.segment_str(input)), + Self::Word(w) => NativeSegmentIterator::WordUtf8(w.segment_str(input)), + Self::Sentence(s) => NativeSegmentIterator::SentenceUtf8(s.segment_str(input)), + }, + crate::string::JsStr::U16(input) => match self { + Self::Grapheme(g) => NativeSegmentIterator::GraphemeU16(g.segment_utf16(input)), + Self::Word(w) => NativeSegmentIterator::WordU16(w.segment_utf16(input)), + Self::Sentence(s) => NativeSegmentIterator::SentenceU16(s.segment_utf16(input)), + }, } } } @@ -81,18 +87,14 @@ impl IntrinsicObject for Segmenter { let _timer = Profiler::global().start_event(std::any::type_name::(), "init"); BuiltInBuilder::from_standard_constructor::(realm) - .static_method( - Self::supported_locales_of, - js_string!("supportedLocalesOf"), - 1, - ) + .static_method(Self::supported_locales_of, "supportedLocalesOf", 1) .property( JsSymbol::to_string_tag(), js_string!("Intl.Segmenter"), Attribute::CONFIGURABLE, ) - .method(Self::resolved_options, js_string!("resolvedOptions"), 0) - .method(Self::segment, js_string!("segment"), 1) + .method(Self::resolved_options, "resolvedOptions", 0) + .method(Self::segment, "segment", 1) .build(); } @@ -133,7 +135,7 @@ impl BuiltInConstructor for Segmenter { // 6. Let opt be a new Record. // 7. Let matcher be ? GetOption(options, "localeMatcher", string, « "lookup", "best fit" », "best fit"). - let matcher = get_option(&options, utf16!("localeMatcher"), context)?.unwrap_or_default(); + let matcher = get_option(&options, "localeMatcher", context)?.unwrap_or_default(); // 8. Set opt.[[localeMatcher]] to matcher. // 9. Let localeData be %Segmenter%.[[LocaleData]]. @@ -149,7 +151,7 @@ impl BuiltInConstructor for Segmenter { ); // 12. Let granularity be ? GetOption(options, "granularity", string, « "grapheme", "word", "sentence" », "grapheme"). - let granularity = get_option(&options, utf16!("granularity"), context)?.unwrap_or_default(); + let granularity = get_option(&options, "granularity", context)?.unwrap_or_default(); // 13. Set segmenter.[[SegmenterGranularity]] to granularity. let native = match granularity { @@ -247,12 +249,12 @@ impl Segmenter { // d. Perform ! CreateDataPropertyOrThrow(options, p, v). let options = ObjectInitializer::new(context) .property( - js_string!("locale"), + "locale", js_string!(segmenter.locale.to_string()), Attribute::all(), ) .property( - js_string!("granularity"), + "granularity", js_string!(segmenter.native.granularity().to_string()), Attribute::all(), ) @@ -307,25 +309,25 @@ fn create_segment_data_object( let start = range.start; // 6. Let segment be the substring of string from startIndex to endIndex. - let segment = js_string!(&string[range]); + let segment = js_string!(&string.to_vec()[range]); // 5. Let result be OrdinaryObjectCreate(%Object.prototype%). let object = &mut ObjectInitializer::new(context); object // 7. Perform ! CreateDataPropertyOrThrow(result, "segment", segment). - .property(js_string!("segment"), segment, Attribute::all()) + .property("segment", segment, Attribute::all()) // 8. Perform ! CreateDataPropertyOrThrow(result, "index", 𝔽(startIndex)). - .property(js_string!("index"), start, Attribute::all()) + .property("index", start, Attribute::all()) // 9. Perform ! CreateDataPropertyOrThrow(result, "input", string). - .property(js_string!("input"), string, Attribute::all()); + .property("input", string, Attribute::all()); // 10. Let granularity be segmenter.[[SegmenterGranularity]]. // 11. If granularity is "word", then if let Some(is_word_like) = is_word_like { // a. Let isWordLike be a Boolean value indicating whether the segment in string is "word-like" according to locale segmenter.[[Locale]]. // b. Perform ! CreateDataPropertyOrThrow(result, "isWordLike", isWordLike). - object.property(js_string!("isWordLike"), is_word_like, Attribute::all()); + object.property("isWordLike", is_word_like, Attribute::all()); } // 12. Return result. diff --git a/boa_engine/src/builtins/intl/segmenter/segments.rs b/boa_engine/src/builtins/intl/segmenter/segments.rs index e7fb671f775..437742ce14d 100644 --- a/boa_engine/src/builtins/intl/segmenter/segments.rs +++ b/boa_engine/src/builtins/intl/segmenter/segments.rs @@ -5,7 +5,6 @@ use itertools::Itertools; use crate::{ builtins::{BuiltInBuilder, IntrinsicObject}, context::intrinsics::Intrinsics, - js_string, object::ObjectData, realm::Realm, Context, JsArgs, JsNativeError, JsObject, JsResult, JsString, JsSymbol, JsValue, @@ -24,7 +23,7 @@ impl IntrinsicObject for Segments { let _timer = Profiler::global().start_event("%SegmentsPrototype%", "init"); BuiltInBuilder::with_intrinsic::(realm) - .static_method(Self::containing, js_string!("containing"), 1) + .static_method(Self::containing, "containing", 1) .static_method(Self::iterator, JsSymbol::iterator(), 0) .build(); } diff --git a/boa_engine/src/builtins/iterable/async_from_sync_iterator.rs b/boa_engine/src/builtins/iterable/async_from_sync_iterator.rs index 4bf413e78f7..b928513bbe6 100644 --- a/boa_engine/src/builtins/iterable/async_from_sync_iterator.rs +++ b/boa_engine/src/builtins/iterable/async_from_sync_iterator.rs @@ -5,11 +5,9 @@ use crate::{ BuiltInBuilder, IntrinsicObject, Promise, }, context::intrinsics::Intrinsics, - js_string, native_function::NativeFunction, object::{FunctionObjectBuilder, JsObject, ObjectData}, realm::Realm, - string::utf16, Context, JsArgs, JsResult, JsValue, }; use boa_gc::{Finalize, Trace}; @@ -39,9 +37,9 @@ impl IntrinsicObject for AsyncFromSyncIterator { .iterator_prototypes() .async_iterator(), ) - .static_method(Self::next, js_string!("next"), 1) - .static_method(Self::r#return, js_string!("return"), 1) - .static_method(Self::throw, js_string!("throw"), 1) + .static_method(Self::next, "next", 1) + .static_method(Self::r#return, "return", 1) + .static_method(Self::throw, "throw", 1) .build(); } @@ -80,7 +78,7 @@ impl AsyncFromSyncIterator { // 3. Let nextMethod be ! Get(asyncIterator, "next"). let next_method = async_iterator - .get(utf16!("next"), context) + .get("next", context) .expect("async from sync iterator prototype must have next method"); // 4. Let iteratorRecord be the Iterator Record { [[Iterator]]: asyncIterator, [[NextMethod]]: nextMethod, [[Done]]: false }. @@ -163,7 +161,7 @@ impl AsyncFromSyncIterator { .expect("cannot fail with promise constructor"); // 5. Let return be Completion(GetMethod(syncIterator, "return")). - let r#return = sync_iterator.get_method(utf16!("return"), context); + let r#return = sync_iterator.get_method("return", context); // 6. IfAbruptRejectPromise(return, promiseCapability). if_abrupt_reject_promise!(r#return, promise_capability, context); @@ -235,7 +233,7 @@ impl AsyncFromSyncIterator { .expect("cannot fail with promise constructor"); // 5. Let throw be Completion(GetMethod(syncIterator, "throw")). - let throw = sync_iterator.get_method(utf16!("throw"), context); + let throw = sync_iterator.get_method("throw", context); // 6. IfAbruptRejectPromise(throw, promiseCapability). if_abrupt_reject_promise!(throw, promise_capability, context); diff --git a/boa_engine/src/builtins/iterable/mod.rs b/boa_engine/src/builtins/iterable/mod.rs index 0074ea2db14..a8589304b60 100644 --- a/boa_engine/src/builtins/iterable/mod.rs +++ b/boa_engine/src/builtins/iterable/mod.rs @@ -4,7 +4,6 @@ use crate::{ builtins::{BuiltInBuilder, IntrinsicObject}, context::intrinsics::Intrinsics, error::JsNativeError, - js_string, object::{JsObject, ObjectData}, realm::Realm, symbol::JsSymbol, @@ -280,7 +279,7 @@ impl JsValue { })?; // 5. Let nextMethod be ? GetV(iterator, "next"). - let next_method = iterator.get_v(js_string!("next"), context)?; + let next_method = iterator.get_v("next", context)?; // 6. Let iteratorRecord be the Record { [[Iterator]]: iterator, [[NextMethod]]: nextMethod, [[Done]]: false }. // 7. Return iteratorRecord. @@ -324,7 +323,7 @@ impl IteratorResult { #[inline] pub fn complete(&self, context: &mut Context<'_>) -> JsResult { // 1. Return ToBoolean(? Get(iterResult, "done")). - Ok(self.object.get(js_string!("done"), context)?.to_boolean()) + Ok(self.object.get("done", context)?.to_boolean()) } /// `IteratorValue ( iterResult )` @@ -340,7 +339,7 @@ impl IteratorResult { #[inline] pub fn value(&self, context: &mut Context<'_>) -> JsResult { // 1. Return ? Get(iterResult, "value"). - self.object.get(js_string!("value"), context) + self.object.get("value", context) } } @@ -526,7 +525,7 @@ impl IteratorRecord { let iterator = &self.iterator; // 3. Let innerResult be Completion(GetMethod(iterator, "return")). - let inner_result = iterator.get_method(js_string!("return"), context); + let inner_result = iterator.get_method("return", context); // 4. If innerResult.[[Type]] is normal, then let inner_result = match inner_result { diff --git a/boa_engine/src/builtins/json/mod.rs b/boa_engine/src/builtins/json/mod.rs index 6b94df63d64..0187bd664d7 100644 --- a/boa_engine/src/builtins/json/mod.rs +++ b/boa_engine/src/builtins/json/mod.rs @@ -54,8 +54,8 @@ impl IntrinsicObject for Json { let attribute = Attribute::READONLY | Attribute::NON_ENUMERABLE | Attribute::CONFIGURABLE; BuiltInBuilder::with_intrinsic::(realm) - .static_method(Self::parse, js_string!("parse"), 2) - .static_method(Self::stringify, js_string!("stringify"), 3) + .static_method(Self::parse, "parse", 2) + .static_method(Self::stringify, "stringify", 3) .static_property(to_string_tag, Self::NAME, attribute) .build(); } @@ -146,7 +146,7 @@ impl Json { // b. Let rootName be the empty String. // c. Perform ! CreateDataPropertyOrThrow(root, rootName, unfiltered). - root.create_data_property_or_throw(utf16!(""), unfiltered, context) + root.create_data_property_or_throw("", unfiltered, context) .expect("CreateDataPropertyOrThrow should never throw here"); // d. Return ? InternalizeJSONProperty(root, rootName, reviver). @@ -366,7 +366,7 @@ impl Json { // 7. Else if Type(space) is String, then } else if let Some(s) = space.as_string() { // a. If the length of space is 10 or less, let gap be space; otherwise let gap be the substring of space from 0 to 10. - js_string!(s.get(..10).unwrap_or(s)) + js_string!(s.to_vec().get(..10).unwrap_or(&s.to_vec())) // 8. Else, } else { // a. Let gap be the empty String. @@ -378,7 +378,7 @@ impl Json { // 10. Perform ! CreateDataPropertyOrThrow(wrapper, the empty String, value). wrapper - .create_data_property_or_throw(utf16!(""), args.get_or_undefined(0).clone(), context) + .create_data_property_or_throw("", args.get_or_undefined(0).clone(), context) .expect("CreateDataPropertyOrThrow should never fail here"); // 11. Let state be the Record { [[ReplacerFunction]]: ReplacerFunction, [[Stack]]: stack, [[Indent]]: indent, [[Gap]]: gap, [[PropertyList]]: PropertyList }. @@ -416,7 +416,7 @@ impl Json { // 2. If Type(value) is Object or BigInt, then if value.is_object() || value.is_bigint() { // a. Let toJSON be ? GetV(value, "toJSON"). - let to_json = value.get_v(utf16!("toJSON"), context)?; + let to_json = value.get_v("toJSON", context)?; // b. If IsCallable(toJSON) is true, then if let Some(obj) = to_json.as_object() { @@ -625,7 +625,7 @@ impl Json { // b. If strP is not undefined, then if let Some(str_p) = str_p { // i. Let member be QuoteJSONString(P). - let mut member = Self::quote_json_string(p).to_vec(); + let mut member = Self::quote_json_string(p).iter().collect::>(); // ii. Set member to the string-concatenation of member and ":". member.push(':' as u16); @@ -637,7 +637,7 @@ impl Json { } // iv. Set member to the string-concatenation of member and strP. - member.extend_from_slice(&str_p); + member.extend(str_p.iter()); // v. Append member to partial. partial.push(member); @@ -672,20 +672,20 @@ impl Json { // i. Let separator be the string-concatenation of the code unit 0x002C (COMMA), // the code unit 0x000A (LINE FEED), and state.[[Indent]]. let mut separator = utf16!(",\n").to_vec(); - separator.extend_from_slice(&state.indent); + separator.extend(state.indent.iter()); // ii. Let properties be the String value formed by concatenating all the element Strings of partial // with each adjacent pair of Strings separated with separator. // The separator String is not inserted either before the first String or after the last String. // iii. Let final be the string-concatenation of "{", the code // unit 0x000A (LINE FEED), state.[[Indent]], properties, // the code unit 0x000A (LINE FEED), stepback, and "}". - let result = [utf16!("{\n"), &state.indent[..]] + let result = [utf16!("{\n"), &state.indent.to_vec()[..]] .into_iter() .chain(Itertools::intersperse( partial.iter().map(Vec::as_slice), &separator, )) - .chain([utf16!("\n"), &stepback[..], utf16!("}")]) + .chain([utf16!("\n"), &stepback.to_vec()[..], utf16!("}")]) .flatten() .copied() .collect::>(); @@ -748,7 +748,7 @@ impl Json { // b. If strP is undefined, then if let Some(str_p) = str_p { // i. Append strP to partial. - partial.push(Cow::Owned(str_p.to_vec())); + partial.push(Cow::Owned(str_p.iter().collect::<_>())); // c. Else, } else { // i. Append "null" to partial. @@ -787,18 +787,18 @@ impl Json { // i. Let separator be the string-concatenation of the code unit 0x002C (COMMA), // the code unit 0x000A (LINE FEED), and state.[[Indent]]. let mut separator = utf16!(",\n").to_vec(); - separator.extend_from_slice(&state.indent); + separator.extend(state.indent.iter()); // ii. Let properties be the String value formed by concatenating all the element Strings of partial // with each adjacent pair of Strings separated with separator. // The separator String is not inserted either before the first String or after the last String. // iii. Let final be the string-concatenation of "[", the code unit 0x000A (LINE FEED), state.[[Indent]], properties, the code unit 0x000A (LINE FEED), stepback, and "]". - let result = [utf16!("[\n"), &state.indent[..]] + let result = [utf16!("[\n"), &state.indent.to_vec()[..]] .into_iter() .chain(Itertools::intersperse( partial.iter().map(Cow::as_ref), &separator, )) - .chain([utf16!("\n"), &stepback[..], utf16!("]")]) + .chain([utf16!("\n"), &stepback.to_vec()[..], utf16!("]")]) .flatten() .copied() .collect::>(); diff --git a/boa_engine/src/builtins/map/map_iterator.rs b/boa_engine/src/builtins/map/map_iterator.rs index 0eeb58ea308..7d2567c24c4 100644 --- a/boa_engine/src/builtins/map/map_iterator.rs +++ b/boa_engine/src/builtins/map/map_iterator.rs @@ -49,7 +49,7 @@ impl IntrinsicObject for MapIterator { .iterator_prototypes() .iterator(), ) - .static_method(Self::next, js_string!("next"), 0) + .static_method(Self::next, "next", 0) .static_property( JsSymbol::to_string_tag(), js_string!("Map Iterator"), diff --git a/boa_engine/src/builtins/map/mod.rs b/boa_engine/src/builtins/map/mod.rs index fcb71dd201b..787f8fbde5b 100644 --- a/boa_engine/src/builtins/map/mod.rs +++ b/boa_engine/src/builtins/map/mod.rs @@ -14,11 +14,10 @@ use crate::{ builtins::BuiltInObject, context::intrinsics::{Intrinsics, StandardConstructor, StandardConstructors}, error::JsNativeError, - js_string, object::{internal_methods::get_prototype_from_constructor, JsObject, ObjectData}, property::{Attribute, PropertyNameKind}, realm::Realm, - string::{common::StaticJsStrings, utf16}, + string::common::StaticJsStrings, symbol::JsSymbol, Context, JsArgs, JsResult, JsString, JsValue, }; @@ -43,15 +42,15 @@ impl IntrinsicObject for Map { let _timer = Profiler::global().start_event(std::any::type_name::(), "init"); let get_species = BuiltInBuilder::callable(realm, Self::get_species) - .name(js_string!("get [Symbol.species]")) + .name("get [Symbol.species]") .build(); let get_size = BuiltInBuilder::callable(realm, Self::get_size) - .name(js_string!("get size")) + .name("get size") .build(); let entries_function = BuiltInBuilder::callable(realm, Self::entries) - .name(js_string!("entries")) + .name("entries") .build(); BuiltInBuilder::from_standard_constructor::(realm) @@ -62,7 +61,7 @@ impl IntrinsicObject for Map { Attribute::CONFIGURABLE, ) .property( - utf16!("entries"), + "entries", entries_function.clone(), Attribute::WRITABLE | Attribute::NON_ENUMERABLE | Attribute::CONFIGURABLE, ) @@ -76,20 +75,15 @@ impl IntrinsicObject for Map { Self::NAME, Attribute::READONLY | Attribute::NON_ENUMERABLE | Attribute::CONFIGURABLE, ) - .method(Self::clear, js_string!("clear"), 0) - .method(Self::delete, js_string!("delete"), 1) - .method(Self::for_each, js_string!("forEach"), 1) - .method(Self::get, js_string!("get"), 1) - .method(Self::has, js_string!("has"), 1) - .method(Self::keys, js_string!("keys"), 0) - .method(Self::set, js_string!("set"), 2) - .method(Self::values, js_string!("values"), 0) - .accessor( - js_string!("size"), - Some(get_size), - None, - Attribute::CONFIGURABLE, - ) + .method(Self::clear, "clear", 0) + .method(Self::delete, "delete", 1) + .method(Self::for_each, "forEach", 1) + .method(Self::get, "get", 1) + .method(Self::has, "has", 1) + .method(Self::keys, "keys", 0) + .method(Self::set, "set", 2) + .method(Self::values, "values", 0) + .accessor("size", Some(get_size), None, Attribute::CONFIGURABLE) .build(); } @@ -147,7 +141,7 @@ impl BuiltInConstructor for Map { }; // 5. Let adder be ? Get(map, "set"). - let adder = map.get(utf16!("set"), context)?; + let adder = map.get("set", context)?; // 6. Return ? AddEntriesFromIterable(map, iterable, adder). add_entries_from_iterable(&map, iterable, &adder, context) diff --git a/boa_engine/src/builtins/math/mod.rs b/boa_engine/src/builtins/math/mod.rs index 6d0693b2ac5..f710c63ddda 100644 --- a/boa_engine/src/builtins/math/mod.rs +++ b/boa_engine/src/builtins/math/mod.rs @@ -12,7 +12,7 @@ //! [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math use crate::{ - builtins::BuiltInObject, context::intrinsics::Intrinsics, js_string, object::JsObject, + builtins::BuiltInObject, context::intrinsics::Intrinsics, object::JsObject, property::Attribute, realm::Realm, string::common::StaticJsStrings, symbol::JsSymbol, Context, JsArgs, JsResult, JsString, JsValue, }; @@ -33,53 +33,49 @@ impl IntrinsicObject for Math { let attribute = Attribute::READONLY | Attribute::NON_ENUMERABLE | Attribute::PERMANENT; BuiltInBuilder::with_intrinsic::(realm) - .static_property(js_string!("E"), std::f64::consts::E, attribute) - .static_property(js_string!("LN10"), std::f64::consts::LN_10, attribute) - .static_property(js_string!("LN2"), std::f64::consts::LN_2, attribute) - .static_property(js_string!("LOG10E"), std::f64::consts::LOG10_E, attribute) - .static_property(js_string!("LOG2E"), std::f64::consts::LOG2_E, attribute) - .static_property(js_string!("PI"), std::f64::consts::PI, attribute) - .static_property( - js_string!("SQRT1_2"), - std::f64::consts::FRAC_1_SQRT_2, - attribute, - ) - .static_property(js_string!("SQRT2"), std::f64::consts::SQRT_2, attribute) - .static_method(Self::abs, js_string!("abs"), 1) - .static_method(Self::acos, js_string!("acos"), 1) - .static_method(Self::acosh, js_string!("acosh"), 1) - .static_method(Self::asin, js_string!("asin"), 1) - .static_method(Self::asinh, js_string!("asinh"), 1) - .static_method(Self::atan, js_string!("atan"), 1) - .static_method(Self::atanh, js_string!("atanh"), 1) - .static_method(Self::atan2, js_string!("atan2"), 2) - .static_method(Self::cbrt, js_string!("cbrt"), 1) - .static_method(Self::ceil, js_string!("ceil"), 1) - .static_method(Self::clz32, js_string!("clz32"), 1) - .static_method(Self::cos, js_string!("cos"), 1) - .static_method(Self::cosh, js_string!("cosh"), 1) - .static_method(Self::exp, js_string!("exp"), 1) - .static_method(Self::expm1, js_string!("expm1"), 1) - .static_method(Self::floor, js_string!("floor"), 1) - .static_method(Self::fround, js_string!("fround"), 1) - .static_method(Self::hypot, js_string!("hypot"), 2) - .static_method(Self::imul, js_string!("imul"), 2) - .static_method(Self::log, js_string!("log"), 1) - .static_method(Self::log1p, js_string!("log1p"), 1) - .static_method(Self::log10, js_string!("log10"), 1) - .static_method(Self::log2, js_string!("log2"), 1) - .static_method(Self::max, js_string!("max"), 2) - .static_method(Self::min, js_string!("min"), 2) - .static_method(Self::pow, js_string!("pow"), 2) - .static_method(Self::random, js_string!("random"), 0) - .static_method(Self::round, js_string!("round"), 1) - .static_method(Self::sign, js_string!("sign"), 1) - .static_method(Self::sin, js_string!("sin"), 1) - .static_method(Self::sinh, js_string!("sinh"), 1) - .static_method(Self::sqrt, js_string!("sqrt"), 1) - .static_method(Self::tan, js_string!("tan"), 1) - .static_method(Self::tanh, js_string!("tanh"), 1) - .static_method(Self::trunc, js_string!("trunc"), 1) + .static_property("E", std::f64::consts::E, attribute) + .static_property("LN10", std::f64::consts::LN_10, attribute) + .static_property("LN2", std::f64::consts::LN_2, attribute) + .static_property("LOG10E", std::f64::consts::LOG10_E, attribute) + .static_property("LOG2E", std::f64::consts::LOG2_E, attribute) + .static_property("PI", std::f64::consts::PI, attribute) + .static_property("SQRT1_2", std::f64::consts::FRAC_1_SQRT_2, attribute) + .static_property("SQRT2", std::f64::consts::SQRT_2, attribute) + .static_method(Self::abs, "abs", 1) + .static_method(Self::acos, "acos", 1) + .static_method(Self::acosh, "acosh", 1) + .static_method(Self::asin, "asin", 1) + .static_method(Self::asinh, "asinh", 1) + .static_method(Self::atan, "atan", 1) + .static_method(Self::atanh, "atanh", 1) + .static_method(Self::atan2, "atan2", 2) + .static_method(Self::cbrt, "cbrt", 1) + .static_method(Self::ceil, "ceil", 1) + .static_method(Self::clz32, "clz32", 1) + .static_method(Self::cos, "cos", 1) + .static_method(Self::cosh, "cosh", 1) + .static_method(Self::exp, "exp", 1) + .static_method(Self::expm1, "expm1", 1) + .static_method(Self::floor, "floor", 1) + .static_method(Self::fround, "fround", 1) + .static_method(Self::hypot, "hypot", 2) + .static_method(Self::imul, "imul", 2) + .static_method(Self::log, "log", 1) + .static_method(Self::log1p, "log1p", 1) + .static_method(Self::log10, "log10", 1) + .static_method(Self::log2, "log2", 1) + .static_method(Self::max, "max", 2) + .static_method(Self::min, "min", 2) + .static_method(Self::pow, "pow", 2) + .static_method(Self::random, "random", 0) + .static_method(Self::round, "round", 1) + .static_method(Self::sign, "sign", 1) + .static_method(Self::sin, "sin", 1) + .static_method(Self::sinh, "sinh", 1) + .static_method(Self::sqrt, "sqrt", 1) + .static_method(Self::tan, "tan", 1) + .static_method(Self::tanh, "tanh", 1) + .static_method(Self::trunc, "trunc", 1) .static_property( JsSymbol::to_string_tag(), Self::NAME, diff --git a/boa_engine/src/builtins/mod.rs b/boa_engine/src/builtins/mod.rs index e150d22000a..256e4b1fb1b 100644 --- a/boa_engine/src/builtins/mod.rs +++ b/boa_engine/src/builtins/mod.rs @@ -108,7 +108,6 @@ use crate::{ }, property::{Attribute, PropertyDescriptor, PropertyKey}, realm::Realm, - string::utf16, Context, JsResult, JsString, JsValue, }; @@ -305,7 +304,7 @@ pub(crate) fn set_default_global_bindings(context: &mut Context<'_>) -> JsResult let global_object = context.global_object(); global_object.define_property_or_throw( - utf16!("globalThis"), + "globalThis", PropertyDescriptor::builder() .value(context.realm().global_this().clone()) .writable(true) @@ -318,17 +317,13 @@ pub(crate) fn set_default_global_bindings(context: &mut Context<'_>) -> JsResult .enumerable(false) .configurable(false); global_object.define_property_or_throw( - utf16!("Infinity"), + "Infinity", restricted.clone().value(f64::INFINITY), context, )?; + global_object.define_property_or_throw("NaN", restricted.clone().value(f64::NAN), context)?; global_object.define_property_or_throw( - utf16!("NaN"), - restricted.clone().value(f64::NAN), - context, - )?; - global_object.define_property_or_throw( - utf16!("undefined"), + "undefined", restricted.value(JsValue::undefined()), context, )?; @@ -576,7 +571,7 @@ impl ApplyToObject for Callable { ); object.set_data(function); object.insert( - utf16!("length"), + "length", PropertyDescriptor::builder() .value(self.length) .writable(false) @@ -584,7 +579,7 @@ impl ApplyToObject for Callable { .configurable(true), ); object.insert( - utf16!("name"), + "name", PropertyDescriptor::builder() .value(self.name) .writable(false) @@ -845,8 +840,8 @@ impl BuiltInConstructorWithPrototype<'_> { let length = self.length; let name = self.name.clone(); let prototype = self.prototype.clone(); - self = self.static_property(js_string!("length"), length, Attribute::CONFIGURABLE); - self = self.static_property(js_string!("name"), name, Attribute::CONFIGURABLE); + self = self.static_property("length", length, Attribute::CONFIGURABLE); + self = self.static_property("name", name, Attribute::CONFIGURABLE); self = self.static_property(PROTOTYPE, prototype, Attribute::empty()); let attributes = self.attributes; @@ -894,8 +889,8 @@ impl BuiltInConstructorWithPrototype<'_> { let length = self.length; let name = self.name.clone(); - self = self.static_property(js_string!("length"), length, Attribute::CONFIGURABLE); - self = self.static_property(js_string!("name"), name, Attribute::CONFIGURABLE); + self = self.static_property("length", length, Attribute::CONFIGURABLE); + self = self.static_property("name", name, Attribute::CONFIGURABLE); let mut object = self.object.borrow_mut(); *object.kind_mut() = function; @@ -933,8 +928,11 @@ impl BuiltInCallable<'_> { /// Specify the name of the constructor function. /// /// Default is `""` - fn name(mut self, name: JsString) -> Self { - self.name = name; + fn name(mut self, name: N) -> Self + where + N: Into, + { + self.name = name.into(); self } @@ -1088,8 +1086,11 @@ impl BuiltInBuilder<'_, Callable> { /// Specify the name of the constructor function. /// /// Default is `""` - fn name(mut self, name: JsString) -> Self { - self.kind.name = name; + fn name(mut self, name: N) -> Self + where + N: Into, + { + self.kind.name = name.into(); self } } diff --git a/boa_engine/src/builtins/number/globals.rs b/boa_engine/src/builtins/number/globals.rs index 62ac94104ce..8ba393de6a2 100644 --- a/boa_engine/src/builtins/number/globals.rs +++ b/boa_engine/src/builtins/number/globals.rs @@ -1,14 +1,13 @@ -use boa_macros::utf16; - use crate::{ builtins::{string::is_trimmable_whitespace, BuiltInBuilder, BuiltInObject, IntrinsicObject}, context::intrinsics::Intrinsics, object::JsObject, realm::Realm, - string::{common::StaticJsStrings, Utf16Trim}, + string::common::StaticJsStrings, Context, JsArgs, JsResult, JsString, JsValue, }; +use boa_macros::utf16; use num_traits::Num; /// Builtin javascript 'isFinite(number)' function. @@ -123,7 +122,7 @@ pub(crate) fn parse_int( let input_string = val.to_string(context)?; // 2. Let S be ! TrimString(inputString, start). - let mut var_s = input_string.trim_start(); + let mut var_s = &input_string.trim_start().iter().collect::>()[..]; // 3. Let sign be 1. // 4. If S is not empty and the first code unit of S is the code unit 0x002D (HYPHEN-MINUS), diff --git a/boa_engine/src/builtins/number/mod.rs b/boa_engine/src/builtins/number/mod.rs index 4598df87958..4c41c66e565 100644 --- a/boa_engine/src/builtins/number/mod.rs +++ b/boa_engine/src/builtins/number/mod.rs @@ -53,46 +53,34 @@ impl IntrinsicObject for Number { let attribute = Attribute::READONLY | Attribute::NON_ENUMERABLE | Attribute::PERMANENT; BuiltInBuilder::from_standard_constructor::(realm) - .static_property(js_string!("EPSILON"), f64::EPSILON, attribute) + .static_property("EPSILON", f64::EPSILON, attribute) + .static_property("MAX_SAFE_INTEGER", Self::MAX_SAFE_INTEGER, attribute) + .static_property("MIN_SAFE_INTEGER", Self::MIN_SAFE_INTEGER, attribute) + .static_property("MAX_VALUE", Self::MAX_VALUE, attribute) + .static_property("MIN_VALUE", Self::MIN_VALUE, attribute) + .static_property("NEGATIVE_INFINITY", f64::NEG_INFINITY, attribute) + .static_property("POSITIVE_INFINITY", f64::INFINITY, attribute) + .static_property("NaN", f64::NAN, attribute) .static_property( - js_string!("MAX_SAFE_INTEGER"), - Self::MAX_SAFE_INTEGER, - attribute, - ) - .static_property( - js_string!("MIN_SAFE_INTEGER"), - Self::MIN_SAFE_INTEGER, - attribute, - ) - .static_property(js_string!("MAX_VALUE"), Self::MAX_VALUE, attribute) - .static_property(js_string!("MIN_VALUE"), Self::MIN_VALUE, attribute) - .static_property( - js_string!("NEGATIVE_INFINITY"), - f64::NEG_INFINITY, - attribute, - ) - .static_property(js_string!("POSITIVE_INFINITY"), f64::INFINITY, attribute) - .static_property(js_string!("NaN"), f64::NAN, attribute) - .static_property( - js_string!("parseInt"), + "parseInt", realm.intrinsics().objects().parse_int(), Attribute::WRITABLE | Attribute::NON_ENUMERABLE | Attribute::CONFIGURABLE, ) .static_property( - js_string!("parseFloat"), + "parseFloat", realm.intrinsics().objects().parse_float(), Attribute::WRITABLE | Attribute::NON_ENUMERABLE | Attribute::CONFIGURABLE, ) - .static_method(Self::number_is_finite, js_string!("isFinite"), 1) - .static_method(Self::number_is_nan, js_string!("isNaN"), 1) - .static_method(Self::is_safe_integer, js_string!("isSafeInteger"), 1) - .static_method(Self::number_is_integer, js_string!("isInteger"), 1) - .method(Self::to_exponential, js_string!("toExponential"), 1) - .method(Self::to_fixed, js_string!("toFixed"), 1) - .method(Self::to_locale_string, js_string!("toLocaleString"), 0) - .method(Self::to_precision, js_string!("toPrecision"), 1) - .method(Self::to_string, js_string!("toString"), 1) - .method(Self::value_of, js_string!("valueOf"), 0) + .static_method(Self::number_is_finite, "isFinite", 1) + .static_method(Self::number_is_nan, "isNaN", 1) + .static_method(Self::is_safe_integer, "isSafeInteger", 1) + .static_method(Self::number_is_integer, "isInteger", 1) + .method(Self::to_exponential, "toExponential", 1) + .method(Self::to_fixed, "toFixed", 1) + .method(Self::to_locale_string, "toLocaleString", 0) + .method(Self::to_precision, "toPrecision", 1) + .method(Self::to_string, "toString", 1) + .method(Self::value_of, "valueOf", 0) .build(); } diff --git a/boa_engine/src/builtins/object/for_in_iterator.rs b/boa_engine/src/builtins/object/for_in_iterator.rs index 95cb76b71cb..0f07f86fef5 100644 --- a/boa_engine/src/builtins/object/for_in_iterator.rs +++ b/boa_engine/src/builtins/object/for_in_iterator.rs @@ -12,7 +12,6 @@ use crate::{ builtins::{iterable::create_iter_result_object, BuiltInBuilder, IntrinsicObject}, context::intrinsics::Intrinsics, error::JsNativeError, - js_string, object::{JsObject, ObjectData}, property::PropertyKey, realm::Realm, @@ -50,7 +49,7 @@ impl IntrinsicObject for ForInIterator { .iterator_prototypes() .iterator(), ) - .static_method(Self::next, js_string!("next"), 0) + .static_method(Self::next, "next", 0) .build(); } diff --git a/boa_engine/src/builtins/object/mod.rs b/boa_engine/src/builtins/object/mod.rs index e1222cd4479..85b51f38a0f 100644 --- a/boa_engine/src/builtins/object/mod.rs +++ b/boa_engine/src/builtins/object/mod.rs @@ -13,8 +13,6 @@ //! [spec]: https://tc39.es/ecma262/#sec-objects //! [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object -use std::ops::Deref; - use super::{Array, BuiltInBuilder, BuiltInConstructor, IntrinsicObject}; use crate::{ builtins::{map, BuiltInObject}, @@ -28,7 +26,7 @@ use crate::{ }, property::{Attribute, PropertyDescriptor, PropertyKey, PropertyNameKind}, realm::Realm, - string::{common::StaticJsStrings, utf16}, + string::{common::StaticJsStrings, CowJsString}, symbol::JsSymbol, value::JsValue, Context, JsArgs, JsResult, JsString, @@ -49,89 +47,61 @@ impl IntrinsicObject for Object { let _timer = Profiler::global().start_event(std::any::type_name::(), "init"); let legacy_proto_getter = BuiltInBuilder::callable(realm, Self::legacy_proto_getter) - .name(js_string!("get __proto__")) + .name("get __proto__") .build(); let legacy_setter_proto = BuiltInBuilder::callable(realm, Self::legacy_proto_setter) - .name(js_string!("set __proto__")) + .name("set __proto__") .build(); BuiltInBuilder::from_standard_constructor::(realm) .inherits(None) .accessor( - utf16!("__proto__"), + "__proto__", Some(legacy_proto_getter), Some(legacy_setter_proto), Attribute::NON_ENUMERABLE | Attribute::CONFIGURABLE, ) - .method(Self::has_own_property, js_string!("hasOwnProperty"), 1) - .method( - Self::property_is_enumerable, - js_string!("propertyIsEnumerable"), - 1, - ) - .method(Self::to_string, js_string!("toString"), 0) - .method(Self::to_locale_string, js_string!("toLocaleString"), 0) - .method(Self::value_of, js_string!("valueOf"), 0) - .method(Self::is_prototype_of, js_string!("isPrototypeOf"), 1) - .method( - Self::legacy_define_getter, - js_string!("__defineGetter__"), - 2, - ) - .method( - Self::legacy_define_setter, - js_string!("__defineSetter__"), - 2, - ) - .method( - Self::legacy_lookup_getter, - js_string!("__lookupGetter__"), - 1, - ) - .method( - Self::legacy_lookup_setter, - js_string!("__lookupSetter__"), - 1, - ) - .static_method(Self::create, js_string!("create"), 2) - .static_method(Self::set_prototype_of, js_string!("setPrototypeOf"), 2) - .static_method(Self::get_prototype_of, js_string!("getPrototypeOf"), 1) - .static_method(Self::define_property, js_string!("defineProperty"), 3) - .static_method(Self::define_properties, js_string!("defineProperties"), 2) - .static_method(Self::assign, js_string!("assign"), 2) - .static_method(Self::is, js_string!("is"), 2) - .static_method(Self::keys, js_string!("keys"), 1) - .static_method(Self::values, js_string!("values"), 1) - .static_method(Self::entries, js_string!("entries"), 1) - .static_method(Self::seal, js_string!("seal"), 1) - .static_method(Self::is_sealed, js_string!("isSealed"), 1) - .static_method(Self::freeze, js_string!("freeze"), 1) - .static_method(Self::is_frozen, js_string!("isFrozen"), 1) - .static_method(Self::prevent_extensions, js_string!("preventExtensions"), 1) - .static_method(Self::is_extensible, js_string!("isExtensible"), 1) + .method(Self::has_own_property, "hasOwnProperty", 1) + .method(Self::property_is_enumerable, "propertyIsEnumerable", 1) + .method(Self::to_string, "toString", 0) + .method(Self::to_locale_string, "toLocaleString", 0) + .method(Self::value_of, "valueOf", 0) + .method(Self::is_prototype_of, "isPrototypeOf", 1) + .method(Self::legacy_define_getter, "__defineGetter__", 2) + .method(Self::legacy_define_setter, "__defineSetter__", 2) + .method(Self::legacy_lookup_getter, "__lookupGetter__", 1) + .method(Self::legacy_lookup_setter, "__lookupSetter__", 1) + .static_method(Self::create, "create", 2) + .static_method(Self::set_prototype_of, "setPrototypeOf", 2) + .static_method(Self::get_prototype_of, "getPrototypeOf", 1) + .static_method(Self::define_property, "defineProperty", 3) + .static_method(Self::define_properties, "defineProperties", 2) + .static_method(Self::assign, "assign", 2) + .static_method(Self::is, "is", 2) + .static_method(Self::keys, "keys", 1) + .static_method(Self::values, "values", 1) + .static_method(Self::entries, "entries", 1) + .static_method(Self::seal, "seal", 1) + .static_method(Self::is_sealed, "isSealed", 1) + .static_method(Self::freeze, "freeze", 1) + .static_method(Self::is_frozen, "isFrozen", 1) + .static_method(Self::prevent_extensions, "preventExtensions", 1) + .static_method(Self::is_extensible, "isExtensible", 1) .static_method( Self::get_own_property_descriptor, - js_string!("getOwnPropertyDescriptor"), + "getOwnPropertyDescriptor", 2, ) .static_method( Self::get_own_property_descriptors, - js_string!("getOwnPropertyDescriptors"), - 1, - ) - .static_method( - Self::get_own_property_names, - js_string!("getOwnPropertyNames"), - 1, - ) - .static_method( - Self::get_own_property_symbols, - js_string!("getOwnPropertySymbols"), + "getOwnPropertyDescriptors", 1, ) - .static_method(Self::has_own, js_string!("hasOwn"), 2) - .static_method(Self::from_entries, js_string!("fromEntries"), 1) + .static_method(Self::get_own_property_names, "getOwnPropertyNames", 1) + .static_method(Self::get_own_property_symbols, "getOwnPropertySymbols", 1) + .static_method(Self::has_own, "hasOwn", 2) + .static_method(Self::from_entries, "fromEntries", 1) .build(); } @@ -564,42 +534,42 @@ impl Object { // 4. If Desc has a [[Value]] field, then if let Some(value) = desc.value() { // a. Perform ! CreateDataPropertyOrThrow(obj, "value", Desc.[[Value]]). - obj.create_data_property_or_throw(utf16!("value"), value.clone(), context) + obj.create_data_property_or_throw("value", value.clone(), context) .expect("CreateDataPropertyOrThrow cannot fail here"); } // 5. If Desc has a [[Writable]] field, then if let Some(writable) = desc.writable() { // a. Perform ! CreateDataPropertyOrThrow(obj, "writable", Desc.[[Writable]]). - obj.create_data_property_or_throw(utf16!("writable"), writable, context) + obj.create_data_property_or_throw("writable", writable, context) .expect("CreateDataPropertyOrThrow cannot fail here"); } // 6. If Desc has a [[Get]] field, then if let Some(get) = desc.get() { // a. Perform ! CreateDataPropertyOrThrow(obj, "get", Desc.[[Get]]). - obj.create_data_property_or_throw(utf16!("get"), get.clone(), context) + obj.create_data_property_or_throw("get", get.clone(), context) .expect("CreateDataPropertyOrThrow cannot fail here"); } // 7. If Desc has a [[Set]] field, then if let Some(set) = desc.set() { // a. Perform ! CreateDataPropertyOrThrow(obj, "set", Desc.[[Set]]). - obj.create_data_property_or_throw(utf16!("set"), set.clone(), context) + obj.create_data_property_or_throw("set", set.clone(), context) .expect("CreateDataPropertyOrThrow cannot fail here"); } // 8. If Desc has an [[Enumerable]] field, then if let Some(enumerable) = desc.enumerable() { // a. Perform ! CreateDataPropertyOrThrow(obj, "enumerable", Desc.[[Enumerable]]). - obj.create_data_property_or_throw(utf16!("enumerable"), enumerable, context) + obj.create_data_property_or_throw("enumerable", enumerable, context) .expect("CreateDataPropertyOrThrow cannot fail here"); } // 9. If Desc has a [[Configurable]] field, then if let Some(configurable) = desc.configurable() { // a. Perform ! CreateDataPropertyOrThrow(obj, "configurable", Desc.[[Configurable]]). - obj.create_data_property_or_throw(utf16!("configurable"), configurable, context) + obj.create_data_property_or_throw("configurable", configurable, context) .expect("CreateDataPropertyOrThrow cannot fail here"); } @@ -831,7 +801,7 @@ impl Object { // 4. Let isArray be ? IsArray(O). // 5. If isArray is true, let builtinTag be "Array". let builtin_tag = if o.is_array_abstract()? { - utf16!("Array") + "Array" } else { // 6. Else if O has a [[ParameterMap]] internal slot, let builtinTag be "Arguments". // 7. Else if O has a [[Call]] internal method, let builtinTag be "Function". @@ -843,15 +813,15 @@ impl Object { // 13. Else if O has a [[RegExpMatcher]] internal slot, let builtinTag be "RegExp". // 14. Else, let builtinTag be "Object". match o.borrow().kind() { - ObjectKind::Arguments(_) => utf16!("Arguments"), - _ if o.is_callable() => utf16!("Function"), - ObjectKind::Error(_) => utf16!("Error"), - ObjectKind::Boolean(_) => utf16!("Boolean"), - ObjectKind::Number(_) => utf16!("Number"), - ObjectKind::String(_) => utf16!("String"), - ObjectKind::Date(_) => utf16!("Date"), - ObjectKind::RegExp(_) => utf16!("RegExp"), - _ => utf16!("Object"), + ObjectKind::Arguments(_) => "Arguments", + _ if o.is_callable() => "Function", + ObjectKind::Error(_) => "Error", + ObjectKind::Boolean(_) => "Boolean", + ObjectKind::Number(_) => "Number", + ObjectKind::String(_) => "String", + ObjectKind::Date(_) => "Date", + ObjectKind::RegExp(_) => "RegExp", + _ => "Object", } }; @@ -859,10 +829,13 @@ impl Object { let tag = o.get(JsSymbol::to_string_tag(), context)?; // 16. If Type(tag) is not String, set tag to builtinTag. - let tag_str = tag.as_string().map_or(builtin_tag, JsString::deref); + let tag_str = tag + .as_string() + .map(JsString::as_slice) + .map_or(CowJsString::from(builtin_tag), Into::into); // 17. Return the string-concatenation of "[object ", tag, and "]". - Ok(js_string!(utf16!("[object "), tag_str, utf16!("]")).into()) + Ok(js_string!("[object ", tag_str, "]").into()) } /// `Object.prototype.toLocaleString( [ reserved1 [ , reserved2 ] ] )` @@ -881,7 +854,7 @@ impl Object { ) -> JsResult { // 1. Let O be the this value. // 2. Return ? Invoke(O, "toString"). - this.invoke(utf16!("toString"), &[], context) + this.invoke("toString", &[], context) } /// `Object.prototype.hasOwnProperty( property )` diff --git a/boa_engine/src/builtins/options.rs b/boa_engine/src/builtins/options.rs index 004682246ec..c9dd9311e0a 100644 --- a/boa_engine/src/builtins/options.rs +++ b/boa_engine/src/builtins/options.rs @@ -50,7 +50,7 @@ where /// [spec]: https://tc39.es/ecma402/#sec-getoption pub(crate) fn get_option( options: &JsObject, - property: &[u16], + property: &str, context: &mut Context<'_>, ) -> JsResult> { // 1. Let value be ? Get(options, property). diff --git a/boa_engine/src/builtins/promise/mod.rs b/boa_engine/src/builtins/promise/mod.rs index 01cb74f4d70..d9fa005feb0 100644 --- a/boa_engine/src/builtins/promise/mod.rs +++ b/boa_engine/src/builtins/promise/mod.rs @@ -17,7 +17,7 @@ use crate::{ }, property::Attribute, realm::Realm, - string::{common::StaticJsStrings, utf16}, + string::common::StaticJsStrings, symbol::JsSymbol, value::JsValue, Context, JsArgs, JsError, JsResult, JsString, @@ -336,25 +336,25 @@ impl IntrinsicObject for Promise { let _timer = Profiler::global().start_event(std::any::type_name::(), "init"); let get_species = BuiltInBuilder::callable(realm, Self::get_species) - .name(js_string!("get [Symbol.species]")) + .name("get [Symbol.species]") .build(); let builder = BuiltInBuilder::from_standard_constructor::(realm) - .static_method(Self::all, js_string!("all"), 1) - .static_method(Self::all_settled, js_string!("allSettled"), 1) - .static_method(Self::any, js_string!("any"), 1) - .static_method(Self::race, js_string!("race"), 1) - .static_method(Self::reject, js_string!("reject"), 1) - .static_method(Self::resolve, js_string!("resolve"), 1) + .static_method(Self::all, "all", 1) + .static_method(Self::all_settled, "allSettled", 1) + .static_method(Self::any, "any", 1) + .static_method(Self::race, "race", 1) + .static_method(Self::reject, "reject", 1) + .static_method(Self::resolve, "resolve", 1) .static_accessor( JsSymbol::species(), Some(get_species), None, Attribute::CONFIGURABLE, ) - .method(Self::then, js_string!("then"), 2) - .method(Self::catch, js_string!("catch"), 1) - .method(Self::finally, js_string!("finally"), 1) + .method(Self::then, "then", 2) + .method(Self::catch, "catch", 1) + .method(Self::finally, "finally", 1) // .property( JsSymbol::to_string_tag(), @@ -363,8 +363,7 @@ impl IntrinsicObject for Promise { ); #[cfg(feature = "experimental")] - let builder = - builder.static_method(Self::with_resolvers, crate::js_string!("withResolvers"), 0); + let builder = builder.static_method(Self::with_resolvers, "withResolvers", 0); builder.build(); } @@ -715,7 +714,7 @@ impl Promise { // s. Perform ? Invoke(nextPromise, "then", « onFulfilled, resultCapability.[[Reject]] »). next_promise.invoke( - utf16!("then"), + "then", &[ on_fulfilled.into(), result_capability.functions.reject.clone().into(), @@ -903,7 +902,7 @@ impl Promise { // 10. Perform ! CreateDataPropertyOrThrow(obj, "status", "fulfilled"). obj.create_data_property_or_throw( - utf16!("status"), + "status", js_string!("fulfilled"), context, ) @@ -911,7 +910,7 @@ impl Promise { // 11. Perform ! CreateDataPropertyOrThrow(obj, "value", x). obj.create_data_property_or_throw( - utf16!("value"), + "value", args.get_or_undefined(0).clone(), context, ) @@ -993,7 +992,7 @@ impl Promise { // 10. Perform ! CreateDataPropertyOrThrow(obj, "status", "rejected"). obj.create_data_property_or_throw( - utf16!("status"), + "status", js_string!("rejected"), context, ) @@ -1001,7 +1000,7 @@ impl Promise { // 11. Perform ! CreateDataPropertyOrThrow(obj, "reason", x). obj.create_data_property_or_throw( - utf16!("reason"), + "reason", args.get_or_undefined(0).clone(), context, ) @@ -1052,11 +1051,7 @@ impl Promise { remaining_elements_count.set(remaining_elements_count.get() + 1); // ab. Perform ? Invoke(nextPromise, "then", « onFulfilled, onRejected »). - next_promise.invoke( - utf16!("then"), - &[on_fulfilled.into(), on_rejected.into()], - context, - )?; + next_promise.invoke("then", &[on_fulfilled.into(), on_rejected.into()], context)?; // ac. Set index to index + 1. index += 1; @@ -1288,7 +1283,7 @@ impl Promise { // s. Perform ? Invoke(nextPromise, "then", « resultCapability.[[Resolve]], onRejected »). next_promise.invoke( - utf16!("then"), + "then", &[ result_capability.functions.resolve.clone().into(), on_rejected.into(), @@ -1410,7 +1405,7 @@ impl Promise { // i. Perform ? Invoke(nextPromise, "then", « resultCapability.[[Resolve]], resultCapability.[[Reject]] »). next_promise.invoke( - utf16!("then"), + "then", &[ result_capability.functions.resolve.clone().into(), result_capability.functions.reject.clone().into(), @@ -1565,7 +1560,7 @@ impl Promise { let promise = this; // 2. Return ? Invoke(promise, "then", « undefined, onRejected »). promise.invoke( - utf16!("then"), + "then", &[JsValue::undefined(), on_rejected.clone()], context, ) @@ -1611,7 +1606,7 @@ impl Promise { // a. Let thenFinally be onFinally. // b. Let catchFinally be onFinally. // 7. Return ? Invoke(promise, "then", « thenFinally, catchFinally »). - let then = promise.get(utf16!("then"), context)?; + let then = promise.get("then", context)?; return then.call(this, &[on_finally.clone(), on_finally.clone()], context); }; @@ -1619,7 +1614,7 @@ impl Promise { Self::then_catch_finally_closures(c, on_finally, context); // 7. Return ? Invoke(promise, "then", « thenFinally, catchFinally »). - let then = promise.get(utf16!("then"), context)?; + let then = promise.get("then", context)?; then.call(this, &[then_finally.into(), catch_finally.into()], context) } @@ -1674,7 +1669,7 @@ impl Promise { let value_thunk = return_value.length(0).name("").build(); // v. Return ? Invoke(promise, "then", « valueThunk »). - promise.invoke(utf16!("then"), &[value_thunk.into()], context) + promise.invoke("then", &[value_thunk.into()], context) }, FinallyCaptures { on_finally: on_finally.clone(), @@ -1725,7 +1720,7 @@ impl Promise { let thrower = throw_reason.length(0).name("").build(); // v. Return ? Invoke(promise, "then", « thrower »). - promise.invoke(utf16!("then"), &[thrower.into()], context) + promise.invoke("then", &[thrower.into()], context) }, FinallyCaptures { on_finally, c }, ), @@ -1931,7 +1926,7 @@ impl Promise { context: &mut Context<'_>, ) -> JsResult { // 1. Let promiseResolve be ? Get(promiseConstructor, "resolve"). - let promise_resolve = promise_constructor.get(utf16!("resolve"), context)?; + let promise_resolve = promise_constructor.get("resolve", context)?; // 2. If IsCallable(promiseResolve) is false, throw a TypeError exception. promise_resolve.as_callable().cloned().ok_or_else(|| { @@ -2131,7 +2126,7 @@ impl Promise { }; // 9. Let then be Completion(Get(resolution, "then")). - let then_action = match then.get(utf16!("then"), context) { + let then_action = match then.get("then", context) { // 10. If then is an abrupt completion, then Err(e) => { // a. Perform RejectPromise(promise, then.[[Value]]). diff --git a/boa_engine/src/builtins/proxy/mod.rs b/boa_engine/src/builtins/proxy/mod.rs index cffdc4d84e7..48b486d3630 100644 --- a/boa_engine/src/builtins/proxy/mod.rs +++ b/boa_engine/src/builtins/proxy/mod.rs @@ -14,11 +14,10 @@ use crate::{ builtins::BuiltInObject, context::intrinsics::{Intrinsics, StandardConstructor, StandardConstructors}, error::JsNativeError, - js_string, native_function::NativeFunction, object::{FunctionObjectBuilder, JsFunction, JsObject, ObjectData}, realm::Realm, - string::{common::StaticJsStrings, utf16}, + string::common::StaticJsStrings, Context, JsArgs, JsResult, JsString, JsValue, }; use boa_gc::{Finalize, GcRefCell, Trace}; @@ -37,7 +36,7 @@ impl IntrinsicObject for Proxy { let _timer = Profiler::global().start_event(std::any::type_name::(), "init"); BuiltInBuilder::from_standard_constructor::(realm) - .static_method(Self::revocable, js_string!("revocable"), 2) + .static_method(Self::revocable, "revocable", 2) .build_without_prototype(); } @@ -188,12 +187,12 @@ impl Proxy { // 6. Perform ! CreateDataPropertyOrThrow(result, "proxy", p). result - .create_data_property_or_throw(utf16!("proxy"), p, context) + .create_data_property_or_throw("proxy", p, context) .expect("CreateDataPropertyOrThrow cannot fail here"); // 7. Perform ! CreateDataPropertyOrThrow(result, "revoke", revoker). result - .create_data_property_or_throw(utf16!("revoke"), revoker, context) + .create_data_property_or_throw("revoke", revoker, context) .expect("CreateDataPropertyOrThrow cannot fail here"); // 8. Return result. diff --git a/boa_engine/src/builtins/reflect/mod.rs b/boa_engine/src/builtins/reflect/mod.rs index 761573d8d07..3db90bfcda2 100644 --- a/boa_engine/src/builtins/reflect/mod.rs +++ b/boa_engine/src/builtins/reflect/mod.rs @@ -15,7 +15,6 @@ use crate::{ builtins::{self, BuiltInObject}, context::intrinsics::Intrinsics, error::JsNativeError, - js_string, object::JsObject, property::Attribute, realm::Realm, @@ -39,23 +38,23 @@ impl IntrinsicObject for Reflect { let to_string_tag = JsSymbol::to_string_tag(); BuiltInBuilder::with_intrinsic::(realm) - .static_method(Self::apply, js_string!("apply"), 3) - .static_method(Self::construct, js_string!("construct"), 2) - .static_method(Self::define_property, js_string!("defineProperty"), 3) - .static_method(Self::delete_property, js_string!("deleteProperty"), 2) - .static_method(Self::get, js_string!("get"), 2) + .static_method(Self::apply, "apply", 3) + .static_method(Self::construct, "construct", 2) + .static_method(Self::define_property, "defineProperty", 3) + .static_method(Self::delete_property, "deleteProperty", 2) + .static_method(Self::get, "get", 2) .static_method( Self::get_own_property_descriptor, - js_string!("getOwnPropertyDescriptor"), + "getOwnPropertyDescriptor", 2, ) - .static_method(Self::get_prototype_of, js_string!("getPrototypeOf"), 1) - .static_method(Self::has, js_string!("has"), 2) - .static_method(Self::is_extensible, js_string!("isExtensible"), 1) - .static_method(Self::own_keys, js_string!("ownKeys"), 1) - .static_method(Self::prevent_extensions, js_string!("preventExtensions"), 1) - .static_method(Self::set, js_string!("set"), 3) - .static_method(Self::set_prototype_of, js_string!("setPrototypeOf"), 2) + .static_method(Self::get_prototype_of, "getPrototypeOf", 1) + .static_method(Self::has, "has", 2) + .static_method(Self::is_extensible, "isExtensible", 1) + .static_method(Self::own_keys, "ownKeys", 1) + .static_method(Self::prevent_extensions, "preventExtensions", 1) + .static_method(Self::set, "set", 3) + .static_method(Self::set_prototype_of, "setPrototypeOf", 2) .static_property( to_string_tag, Self::NAME, diff --git a/boa_engine/src/builtins/regexp/mod.rs b/boa_engine/src/builtins/regexp/mod.rs index 9ca6a727e3f..8b21421d811 100644 --- a/boa_engine/src/builtins/regexp/mod.rs +++ b/boa_engine/src/builtins/regexp/mod.rs @@ -52,37 +52,37 @@ impl IntrinsicObject for RegExp { let _timer = Profiler::global().start_event(std::any::type_name::(), "init"); let get_species = BuiltInBuilder::callable(realm, Self::get_species) - .name(js_string!("get [Symbol.species]")) + .name("get [Symbol.species]") .build(); let flag_attributes = Attribute::CONFIGURABLE | Attribute::NON_ENUMERABLE; let get_has_indices = BuiltInBuilder::callable(realm, Self::get_has_indices) - .name(js_string!("get hasIndices")) + .name("get hasIndices") .build(); let get_global = BuiltInBuilder::callable(realm, Self::get_global) - .name(js_string!("get global")) + .name("get global") .build(); let get_ignore_case = BuiltInBuilder::callable(realm, Self::get_ignore_case) - .name(js_string!("get ignoreCase")) + .name("get ignoreCase") .build(); let get_multiline = BuiltInBuilder::callable(realm, Self::get_multiline) - .name(js_string!("get multiline")) + .name("get multiline") .build(); let get_dot_all = BuiltInBuilder::callable(realm, Self::get_dot_all) - .name(js_string!("get dotAll")) + .name("get dotAll") .build(); let get_unicode = BuiltInBuilder::callable(realm, Self::get_unicode) - .name(js_string!("get unicode")) + .name("get unicode") .build(); let get_sticky = BuiltInBuilder::callable(realm, Self::get_sticky) - .name(js_string!("get sticky")) + .name("get sticky") .build(); let get_flags = BuiltInBuilder::callable(realm, Self::get_flags) - .name(js_string!("get flags")) + .name("get flags") .build(); let get_source = BuiltInBuilder::callable(realm, Self::get_source) - .name(js_string!("get source")) + .name("get source") .build(); let regexp = BuiltInBuilder::from_standard_constructor::(realm) .static_accessor( @@ -91,67 +91,27 @@ impl IntrinsicObject for RegExp { None, Attribute::CONFIGURABLE, ) - .property(js_string!("lastIndex"), 0, Attribute::all()) - .method(Self::test, js_string!("test"), 1) - .method(Self::exec, js_string!("exec"), 1) - .method(Self::to_string, js_string!("toString"), 0) + .property("lastIndex", 0, Attribute::all()) + .method(Self::test, "test", 1) + .method(Self::exec, "exec", 1) + .method(Self::to_string, "toString", 0) .method(Self::r#match, JsSymbol::r#match(), 1) .method(Self::match_all, JsSymbol::match_all(), 1) .method(Self::replace, JsSymbol::replace(), 2) .method(Self::search, JsSymbol::search(), 1) .method(Self::split, JsSymbol::split(), 2) - .accessor( - js_string!("hasIndices"), - Some(get_has_indices), - None, - flag_attributes, - ) - .accessor( - js_string!("global"), - Some(get_global), - None, - flag_attributes, - ) - .accessor( - js_string!("ignoreCase"), - Some(get_ignore_case), - None, - flag_attributes, - ) - .accessor( - js_string!("multiline"), - Some(get_multiline), - None, - flag_attributes, - ) - .accessor( - js_string!("dotAll"), - Some(get_dot_all), - None, - flag_attributes, - ) - .accessor( - js_string!("unicode"), - Some(get_unicode), - None, - flag_attributes, - ) - .accessor( - js_string!("sticky"), - Some(get_sticky), - None, - flag_attributes, - ) - .accessor(js_string!("flags"), Some(get_flags), None, flag_attributes) - .accessor( - js_string!("source"), - Some(get_source), - None, - flag_attributes, - ); + .accessor("hasIndices", Some(get_has_indices), None, flag_attributes) + .accessor("global", Some(get_global), None, flag_attributes) + .accessor("ignoreCase", Some(get_ignore_case), None, flag_attributes) + .accessor("multiline", Some(get_multiline), None, flag_attributes) + .accessor("dotAll", Some(get_dot_all), None, flag_attributes) + .accessor("unicode", Some(get_unicode), None, flag_attributes) + .accessor("sticky", Some(get_sticky), None, flag_attributes) + .accessor("flags", Some(get_flags), None, flag_attributes) + .accessor("source", Some(get_source), None, flag_attributes); #[cfg(feature = "annex-b")] - let regexp = regexp.method(Self::compile, js_string!("compile"), 2); + let regexp = regexp.method(Self::compile, "compile", 2); regexp.build(); } @@ -231,12 +191,12 @@ impl BuiltInConstructor for RegExp { (p, f) } else if let Some(pattern) = pattern_is_regexp { // a. Let P be ? Get(pattern, "source"). - let p = pattern.get(js_string!("source"), context)?; + let p = pattern.get("source", context)?; // b. If flags is undefined, then let f = if flags.is_undefined() { // i. Let F be ? Get(pattern, "flags"). - pattern.get(js_string!("flags"), context)? + pattern.get("flags", context)? // c. Else, } else { // i. Let F be flags. @@ -312,7 +272,7 @@ impl RegExp { // 2. Perform ! DefinePropertyOrThrow(obj, "lastIndex", PropertyDescriptor { [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false }). obj.define_property_or_throw( - utf16!("lastIndex"), + "lastIndex", PropertyDescriptorBuilder::new() .writable(true) .enumerable(false) @@ -396,7 +356,7 @@ impl RegExp { *obj.borrow_mut().kind_mut() = ObjectKind::RegExp(Box::new(regexp)); // 16. Perform ? Set(obj, "lastIndex", +0𝔽, true). - obj.set(utf16!("lastIndex"), 0, true, context)?; + obj.set("lastIndex", 0, true, context)?; // 16. Return obj. Ok(obj.into()) @@ -623,41 +583,41 @@ impl RegExp { // 4. Let hasIndices be ToBoolean(? Get(R, "hasIndices")). // 5. If hasIndices is true, append the code unit 0x0064 (LATIN SMALL LETTER D) as the last code unit of result. - if object.get(utf16!("hasIndices"), context)?.to_boolean() { + if object.get("hasIndices", context)?.to_boolean() { result.push('d'); } // 6. Let global be ! ToBoolean(? Get(R, "global")). // 7. If global is true, append the code unit 0x0067 (LATIN SMALL LETTER G) as the last code unit of result. - if object.get(utf16!("global"), context)?.to_boolean() { + if object.get("global", context)?.to_boolean() { result.push('g'); } // 8. Let ignoreCase be ! ToBoolean(? Get(R, "ignoreCase")). // 9. If ignoreCase is true, append the code unit 0x0069 (LATIN SMALL LETTER I) as the last code unit of result. - if object.get(utf16!("ignoreCase"), context)?.to_boolean() { + if object.get("ignoreCase", context)?.to_boolean() { result.push('i'); } // 10. Let multiline be ! ToBoolean(? Get(R, "multiline")). // 11. If multiline is true, append the code unit 0x006D (LATIN SMALL LETTER M) as the last code unit of result. - if object.get(utf16!("multiline"), context)?.to_boolean() { + if object.get("multiline", context)?.to_boolean() { result.push('m'); } // 12. Let dotAll be ! ToBoolean(? Get(R, "dotAll")). // 13. If dotAll is true, append the code unit 0x0073 (LATIN SMALL LETTER S) as the last code unit of result. - if object.get(utf16!("dotAll"), context)?.to_boolean() { + if object.get("dotAll", context)?.to_boolean() { result.push('s'); } // 14. Let unicode be ! ToBoolean(? Get(R, "unicode")). // 15. If unicode is true, append the code unit 0x0075 (LATIN SMALL LETTER U) as the last code unit of result. - if object.get(utf16!("unicode"), context)?.to_boolean() { + if object.get("unicode", context)?.to_boolean() { result.push('u'); } // 16. Let sticky be ! ToBoolean(? Get(R, "sticky")). // 17. If sticky is true, append the code unit 0x0079 (LATIN SMALL LETTER Y) as the last code unit of result. - if object.get(utf16!("sticky"), context)?.to_boolean() { + if object.get("sticky", context)?.to_boolean() { result.push('y'); } @@ -842,7 +802,7 @@ impl RegExp { // 2. Assert: Type(S) is String. // 3. Let exec be ? Get(R, "exec"). - let exec = this.get(utf16!("exec"), context)?; + let exec = this.get("exec", context)?; // 4. If IsCallable(exec) is true, then if let Some(exec) = exec.as_callable() { @@ -897,19 +857,19 @@ impl RegExp { let length = input.len() as u64; // 2. Let lastIndex be ℝ(? ToLength(? Get(R, "lastIndex"))). - let mut last_index = this.get(utf16!("lastIndex"), context)?.to_length(context)?; + let mut last_index = this.get("lastIndex", context)?.to_length(context)?; // 3. Let flags be R.[[OriginalFlags]]. let flags = &rx.original_flags; // 4. If flags contains "g", let global be true; else let global be false. - let global = flags.contains(&('g' as u16)); + let global = flags.contains(b'g'); // 5. If flags contains "y", let sticky be true; else let sticky be false. - let sticky = flags.contains(&('y' as u16)); + let sticky = flags.contains(b'y'); // 6. If flags contains "d", let hasIndices be true; else let hasIndices be false. - let has_indices = flags.contains(&('d' as u16)); + let has_indices = flags.contains(b'd'); // 7. If global is false and sticky is false, set lastIndex to 0. if !global && !sticky { @@ -920,7 +880,7 @@ impl RegExp { let matcher = &rx.matcher; // 9. If flags contains "u" or flags contains "v", let fullUnicode be true; else let fullUnicode be false. - let full_unicode = flags.contains(&('u' as u16)) || flags.contains(&('v' as u16)); + let full_unicode = flags.contains(b'u') || flags.contains(b'v'); // TODO: // 11. If fullUnicode is true, let input be StringToCodePoints(S). Otherwise, let input be a List whose elements are the code units that are the elements of S. @@ -935,7 +895,7 @@ impl RegExp { // i. If global is true or sticky is true, then if global || sticky { // 1. Perform ? Set(R, "lastIndex", +0𝔽, true). - this.set(utf16!("lastIndex"), 0, true, context)?; + this.set("lastIndex", 0, true, context)?; } // ii. Return null. @@ -945,7 +905,7 @@ impl RegExp { // b. Let inputIndex be the index into input of the character that was obtained from element lastIndex of S. // Check if last_index is a valid utf8 index into input. // TODO: avoid converting to String - let last_byte_index = match String::from_utf16(&input[..last_index as usize]) { + let last_byte_index = match String::from_utf16(&input.to_vec()[..last_index as usize]) { Ok(s) => s.len(), Err(_) => { return Err(JsNativeError::typ() @@ -962,7 +922,7 @@ impl RegExp { // i. If sticky is true, then if sticky { // 1. Perform ? Set(R, "lastIndex", +0𝔽, true). - this.set(utf16!("lastIndex"), 0, true, context)?; + this.set("lastIndex", 0, true, context)?; // 2. Return null. return Ok(None); @@ -979,7 +939,7 @@ impl RegExp { // i. If sticky is true, then if sticky { // 1. Perform ? Set(R, "lastIndex", +0𝔽, true). - this.set(utf16!("lastIndex"), 0, true, context)?; + this.set("lastIndex", 0, true, context)?; // 2. Return null. return Ok(None); @@ -1007,14 +967,17 @@ impl RegExp { // Let eUTF be the smallest index into S that corresponds to the character at element e of Input. // If e is greater than or equal to the number of elements in Input, then eUTF is the number of code units in S. // b. Set e to eUTF. - e = input.get(..e).map_or_else(|| input.len(), <[u16]>::len); + e = input + .to_vec() + .get(..e) + .map_or_else(|| input.len(), <[u16]>::len); } // 16. If global is true or sticky is true, then if global || sticky { // a. Perform ? Set(R, "lastIndex", 𝔽(e), true). this.set( - utf16!("lastIndex"), + "lastIndex", lossy_input[..e].encode_utf16().count(), true, context, @@ -1032,11 +995,11 @@ impl RegExp { let a = Array::array_create(n + 1, None, context)?; // 22. Perform ! CreateDataPropertyOrThrow(A, "index", 𝔽(lastIndex)). - a.create_data_property_or_throw(utf16!("index"), last_index, context) + a.create_data_property_or_throw("index", last_index, context) .expect("this CreateDataPropertyOrThrow call must not fail"); // 23. Perform ! CreateDataPropertyOrThrow(A, "input", S). - a.create_data_property_or_throw(utf16!("input"), input.clone(), context) + a.create_data_property_or_throw("input", input.clone(), context) .expect("this CreateDataPropertyOrThrow call must not fail"); // 24. Let match be the Match Record { [[StartIndex]]: lastIndex, [[EndIndex]]: e }. @@ -1133,11 +1096,11 @@ impl RegExp { // 22.2.7.8 MakeMatchIndicesIndexPairArray ( S, indices, groupNames, hasGroups ) // 8. Perform ! CreateDataPropertyOrThrow(A, "groups", groups). indices - .create_data_property_or_throw(utf16!("groups"), group_names, context) + .create_data_property_or_throw("groups", group_names, context) .expect("this CreateDataPropertyOrThrow call must not fail"); // 32. Perform ! CreateDataPropertyOrThrow(A, "groups", groups). - a.create_data_property_or_throw(utf16!("groups"), groups, context) + a.create_data_property_or_throw("groups", groups, context) .expect("this CreateDataPropertyOrThrow call must not fail"); // 27. For each integer i such that i ≥ 1 and i ≤ n, in ascending order, do @@ -1179,7 +1142,7 @@ impl RegExp { // a. Let indicesArray be MakeMatchIndicesIndexPairArray(S, indices, groupNames, hasGroups). // b. Perform ! CreateDataPropertyOrThrow(A, "indices", indicesArray). if has_indices { - a.create_data_property_or_throw(utf16!("indices"), indices, context) + a.create_data_property_or_throw("indices", indices, context) .expect("this CreateDataPropertyOrThrow call must not fail"); } @@ -1213,7 +1176,7 @@ impl RegExp { let arg_str = args.get_or_undefined(0).to_string(context)?; // 4. Let global be ! ToBoolean(? Get(rx, "global")). - let global = rx.get(utf16!("global"), context)?.to_boolean(); + let global = rx.get("global", context)?.to_boolean(); // 5. If global is false, then #[allow(clippy::if_not_else)] @@ -1226,10 +1189,10 @@ impl RegExp { // a. Assert: global is true. // b. Let fullUnicode be ! ToBoolean(? Get(rx, "unicode")). - let unicode = rx.get(utf16!("unicode"), context)?.to_boolean(); + let unicode = rx.get("unicode", context)?.to_boolean(); // c. Perform ? Set(rx, "lastIndex", +0𝔽, true). - rx.set(utf16!("lastIndex"), 0, true, context)?; + rx.set("lastIndex", 0, true, context)?; // d. Let A be ! ArrayCreate(0). let a = @@ -1256,14 +1219,13 @@ impl RegExp { // 3. If matchStr is the empty String, then if match_str.is_empty() { // a. Let thisIndex be ℝ(? ToLength(? Get(rx, "lastIndex"))). - let this_index = - rx.get(utf16!("lastIndex"), context)?.to_length(context)?; + let this_index = rx.get("lastIndex", context)?.to_length(context)?; // b. Let nextIndex be AdvanceStringIndex(S, thisIndex, fullUnicode). let next_index = advance_string_index(&arg_str, this_index, unicode); // c. Perform ? Set(rx, "lastIndex", 𝔽(nextIndex), true). - rx.set(utf16!("lastIndex"), JsValue::new(next_index), true, context)?; + rx.set("lastIndex", JsValue::new(next_index), true, context)?; } // 4. Set n to n + 1. @@ -1313,7 +1275,7 @@ impl RegExp { )) .into()); }; - Ok(js_string!(utf16!("/"), &body, utf16!("/"), &flags).into()) + Ok(js_string!("/", &body, "/", &flags).into()) } /// `RegExp.prototype[ @@matchAll ]( string )` @@ -1345,26 +1307,24 @@ impl RegExp { let c = regexp.species_constructor(StandardConstructors::regexp, context)?; // 5. Let flags be ? ToString(? Get(R, "flags")). - let flags = regexp.get(utf16!("flags"), context)?.to_string(context)?; + let flags = regexp.get("flags", context)?.to_string(context)?; // 6. Let matcher be ? Construct(C, « R, flags »). let matcher = c.construct(&[this.clone(), flags.clone().into()], Some(&c), context)?; // 7. Let lastIndex be ? ToLength(? Get(R, "lastIndex")). - let last_index = regexp - .get(utf16!("lastIndex"), context)? - .to_length(context)?; + let last_index = regexp.get("lastIndex", context)?.to_length(context)?; // 8. Perform ? Set(matcher, "lastIndex", lastIndex, true). - matcher.set(utf16!("lastIndex"), last_index, true, context)?; + matcher.set("lastIndex", last_index, true, context)?; // 9. If flags contains "g", let global be true. // 10. Else, let global be false. - let global = flags.contains(&('g' as u16)); + let global = flags.contains(b'g'); // 11. If flags contains "u", let fullUnicode be true. // 12. Else, let fullUnicode be false. - let unicode = flags.contains(&('u' as u16)); + let unicode = flags.contains(b'u'); // 13. Return ! CreateRegExpStringIterator(matcher, S, global, fullUnicode). Ok(RegExpStringIterator::create_regexp_string_iterator( @@ -1427,18 +1387,18 @@ impl RegExp { }; // 7. Let flags be ? ToString(? Get(rx, "flags")). - let flags = rx.get(utf16!("flags"), context)?.to_string(context)?; + let flags = rx.get("flags", context)?.to_string(context)?; // 8. If flags contains "g", let global be true. Otherwise, let global be false. - let global = flags.as_slice().contains(&u16::from(b'g')); + let global = flags.contains(b'g'); // 9. If global is true, then let full_unicode = if global { // a. If flags contains "u", let fullUnicode be true. Otherwise, let fullUnicode be false. - let full_unicode = flags.contains(&u16::from(b'u')); + let full_unicode = flags.contains(b'u'); // b. Perform ? Set(rx, "lastIndex", +0𝔽, true). - rx.set(utf16!("lastIndex"), 0, true, context)?; + rx.set("lastIndex", 0, true, context)?; full_unicode } else { @@ -1480,13 +1440,13 @@ impl RegExp { // 2. If matchStr is the empty String, then if match_str.is_empty() { // a. Let thisIndex be ℝ(? ToLength(? Get(rx, "lastIndex"))). - let this_index = rx.get(utf16!("lastIndex"), context)?.to_length(context)?; + let this_index = rx.get("lastIndex", context)?.to_length(context)?; // b. Let nextIndex be AdvanceStringIndex(S, thisIndex, fullUnicode). let next_index = advance_string_index(&s, this_index, full_unicode); // c. Perform ? Set(rx, "lastIndex", 𝔽(nextIndex), true). - rx.set(utf16!("lastIndex"), JsValue::new(next_index), true, context)?; + rx.set("lastIndex", JsValue::new(next_index), true, context)?; } } @@ -1515,7 +1475,7 @@ impl RegExp { // e. Let position be ? ToIntegerOrInfinity(? Get(result, "index")). let position = result - .get(utf16!("index"), context)? + .get("index", context)? .to_integer_or_infinity(context)?; // f. Set position to the result of clamping position between 0 and lengthS. @@ -1547,7 +1507,7 @@ impl RegExp { } // j. Let namedCaptures be ? Get(result, "groups"). - let mut named_captures = result.get(utf16!("groups"), context)?; + let mut named_captures = result.get("groups", context)?; let replacement = match replace_value { // k. If functionalReplace is true, then @@ -1600,8 +1560,8 @@ impl RegExp { // In such cases, the corresponding substitution is ignored. // ii. Set accumulatedResult to the string-concatenation of accumulatedResult, the substring of S from nextSourcePosition to position, and replacement. - accumulated_result.extend_from_slice(&s[next_source_position..position]); - accumulated_result.extend_from_slice(&replacement); + accumulated_result.extend_from_slice(&s.to_vec()[next_source_position..position]); + accumulated_result.extend(replacement.iter()); // iii. Set nextSourcePosition to position + matchLength. next_source_position = position + match_length; @@ -1610,11 +1570,11 @@ impl RegExp { // 16. If nextSourcePosition ≥ lengthS, return accumulatedResult. if next_source_position >= length_s { - return Ok(js_string!(accumulated_result).into()); + return Ok(js_string!(&accumulated_result[..]).into()); } // 17. Return the string-concatenation of accumulatedResult and the substring of S from nextSourcePosition. - Ok(js_string!(&accumulated_result[..], &s[next_source_position..]).into()) + Ok(js_string!(&accumulated_result[..], &s.to_vec()[next_source_position..]).into()) } /// `RegExp.prototype[ @@search ]( string )` @@ -1643,31 +1603,31 @@ impl RegExp { let arg_str = args.get_or_undefined(0).to_string(context)?; // 4. Let previousLastIndex be ? Get(rx, "lastIndex"). - let previous_last_index = rx.get(utf16!("lastIndex"), context)?; + let previous_last_index = rx.get("lastIndex", context)?; // 5. If SameValue(previousLastIndex, +0𝔽) is false, then if !JsValue::same_value(&previous_last_index, &JsValue::new(0)) { // a. Perform ? Set(rx, "lastIndex", +0𝔽, true). - rx.set(utf16!("lastIndex"), 0, true, context)?; + rx.set("lastIndex", 0, true, context)?; } // 6. Let result be ? RegExpExec(rx, S). let result = Self::abstract_exec(rx, arg_str, context)?; // 7. Let currentLastIndex be ? Get(rx, "lastIndex"). - let current_last_index = rx.get(utf16!("lastIndex"), context)?; + let current_last_index = rx.get("lastIndex", context)?; // 8. If SameValue(currentLastIndex, previousLastIndex) is false, then if !JsValue::same_value(¤t_last_index, &previous_last_index) { // a. Perform ? Set(rx, "lastIndex", previousLastIndex, true). - rx.set(utf16!("lastIndex"), previous_last_index, true, context)?; + rx.set("lastIndex", previous_last_index, true, context)?; } // 9. If result is null, return -1𝔽. // 10. Return ? Get(result, "index"). result.map_or_else( || Ok(JsValue::new(-1)), - |result| result.get(utf16!("index"), context), + |result| result.get("index", context), ) } @@ -1700,18 +1660,18 @@ impl RegExp { let constructor = rx.species_constructor(StandardConstructors::regexp, context)?; // 5. Let flags be ? ToString(? Get(rx, "flags")). - let flags = rx.get(utf16!("flags"), context)?.to_string(context)?; + let flags = rx.get("flags", context)?.to_string(context)?; // 6. If flags contains "u", let unicodeMatching be true. // 7. Else, let unicodeMatching be false. - let unicode = flags.contains(&('u' as u16)); + let unicode = flags.contains(b'u'); // 8. If flags contains "y", let newFlags be flags. // 9. Else, let newFlags be the string-concatenation of flags and "y". - let new_flags = if flags.contains(&('y' as u16)) { + let new_flags = if flags.contains(b'y') { flags } else { - js_string!(&flags, utf16!("y")) + js_string!(&flags, "y") }; // 10. Let splitter be ? Construct(C, « rx, newFlags »). @@ -1769,7 +1729,7 @@ impl RegExp { // 19. Repeat, while q < size, while q < size { // a. Perform ? Set(splitter, "lastIndex", 𝔽(q), true). - splitter.set(utf16!("lastIndex"), JsValue::new(q), true, context)?; + splitter.set("lastIndex", JsValue::new(q), true, context)?; // b. Let z be ? RegExpExec(splitter, S). let result = Self::abstract_exec(&splitter, arg_str.clone(), context)?; @@ -1778,9 +1738,7 @@ impl RegExp { // d. Else, if let Some(result) = result { // i. Let e be ℝ(? ToLength(? Get(splitter, "lastIndex"))). - let mut e = splitter - .get(utf16!("lastIndex"), context)? - .to_length(context)?; + let mut e = splitter.get("lastIndex", context)?.to_length(context)?; // ii. Set e to min(e, size). e = std::cmp::min(e, size); @@ -1791,7 +1749,7 @@ impl RegExp { q = advance_string_index(&arg_str, q, unicode); } else { // 1. Let T be the substring of S from p to q. - let arg_str_substring = js_string!(&arg_str[p as usize..q as usize]); + let arg_str_substring = js_string!(&arg_str.to_vec()[p as usize..q as usize]); // 2. Perform ! CreateDataPropertyOrThrow(A, ! ToString(𝔽(lengthA)), T). a.create_data_property_or_throw(length_a, arg_str_substring, context) @@ -1842,7 +1800,7 @@ impl RegExp { } // 20. Let T be the substring of S from p to size. - let arg_str_substring = js_string!(&arg_str[p as usize..size as usize]); + let arg_str_substring = js_string!(&arg_str.to_vec()[p as usize..size as usize]); // 21. Perform ! CreateDataPropertyOrThrow(A, ! ToString(𝔽(lengthA)), T). a.create_data_property_or_throw(length_a, arg_str_substring, context) diff --git a/boa_engine/src/builtins/regexp/regexp_string_iterator.rs b/boa_engine/src/builtins/regexp/regexp_string_iterator.rs index 10d668acba6..8f76564b0b7 100644 --- a/boa_engine/src/builtins/regexp/regexp_string_iterator.rs +++ b/boa_engine/src/builtins/regexp/regexp_string_iterator.rs @@ -18,7 +18,6 @@ use crate::{ object::{JsObject, ObjectData}, property::Attribute, realm::Realm, - string::utf16, symbol::JsSymbol, Context, JsResult, JsString, JsValue, }; @@ -53,7 +52,7 @@ impl IntrinsicObject for RegExpStringIterator { .iterator_prototypes() .iterator(), ) - .static_method(Self::next, js_string!("next"), 0) + .static_method(Self::next, "next", 0) .static_property( JsSymbol::to_string_tag(), js_string!("RegExp String Iterator"), @@ -161,7 +160,7 @@ impl RegExpStringIterator { // 1. Let thisIndex be ℝ(? ToLength(? Get(R, "lastIndex"))). let this_index = iterator .matcher - .get(utf16!("lastIndex"), context)? + .get("lastIndex", context)? .to_length(context)?; // 2. Let nextIndex be ! AdvanceStringIndex(S, thisIndex, fullUnicode). @@ -171,7 +170,7 @@ impl RegExpStringIterator { // 3. Perform ? Set(R, "lastIndex", 𝔽(nextIndex), true). iterator .matcher - .set(utf16!("lastIndex"), next_index, true, context)?; + .set("lastIndex", next_index, true, context)?; } // vi. Perform ? Yield(match). diff --git a/boa_engine/src/builtins/set/mod.rs b/boa_engine/src/builtins/set/mod.rs index 908cd668219..df59c47ff1d 100644 --- a/boa_engine/src/builtins/set/mod.rs +++ b/boa_engine/src/builtins/set/mod.rs @@ -22,11 +22,10 @@ use crate::{ builtins::{BuiltInBuilder, BuiltInConstructor, BuiltInObject, IntrinsicObject}, context::intrinsics::{Intrinsics, StandardConstructor, StandardConstructors}, error::JsNativeError, - js_string, object::{internal_methods::get_prototype_from_constructor, JsObject, ObjectData}, property::{Attribute, PropertyNameKind}, realm::Realm, - string::{common::StaticJsStrings, utf16}, + string::common::StaticJsStrings, symbol::JsSymbol, Context, JsArgs, JsResult, JsString, JsValue, }; @@ -46,15 +45,15 @@ impl IntrinsicObject for Set { let _timer = Profiler::global().start_event(std::any::type_name::(), "init"); let get_species = BuiltInBuilder::callable(realm, Self::get_species) - .name(js_string!("get [Symbol.species]")) + .name("get [Symbol.species]") .build(); let size_getter = BuiltInBuilder::callable(realm, Self::size_getter) - .name(js_string!("get size")) + .name("get size") .build(); let values_function = BuiltInBuilder::callable(realm, Self::values) - .name(js_string!("values")) + .name("values") .build(); BuiltInBuilder::from_standard_constructor::(realm) @@ -64,25 +63,20 @@ impl IntrinsicObject for Set { None, Attribute::CONFIGURABLE, ) - .method(Self::add, js_string!("add"), 1) - .method(Self::clear, js_string!("clear"), 0) - .method(Self::delete, js_string!("delete"), 1) - .method(Self::entries, js_string!("entries"), 0) - .method(Self::for_each, js_string!("forEach"), 1) - .method(Self::has, js_string!("has"), 1) + .method(Self::add, "add", 1) + .method(Self::clear, "clear", 0) + .method(Self::delete, "delete", 1) + .method(Self::entries, "entries", 0) + .method(Self::for_each, "forEach", 1) + .method(Self::has, "has", 1) .property( - utf16!("keys"), + "keys", values_function.clone(), Attribute::WRITABLE | Attribute::NON_ENUMERABLE | Attribute::CONFIGURABLE, ) - .accessor( - utf16!("size"), - Some(size_getter), - None, - Attribute::CONFIGURABLE, - ) + .accessor("size", Some(size_getter), None, Attribute::CONFIGURABLE) .property( - utf16!("values"), + "values", values_function.clone(), Attribute::WRITABLE | Attribute::NON_ENUMERABLE | Attribute::CONFIGURABLE, ) @@ -138,7 +132,7 @@ impl BuiltInConstructor for Set { } // 5. Let adder be ? Get(set, "add"). - let adder = set.get(utf16!("add"), context)?; + let adder = set.get("add", context)?; // 6. If IsCallable(adder) is false, throw a TypeError exception. let adder = adder.as_callable().ok_or_else(|| { diff --git a/boa_engine/src/builtins/set/set_iterator.rs b/boa_engine/src/builtins/set/set_iterator.rs index 30de1cfe029..c4e0fb2ca25 100644 --- a/boa_engine/src/builtins/set/set_iterator.rs +++ b/boa_engine/src/builtins/set/set_iterator.rs @@ -49,7 +49,7 @@ impl IntrinsicObject for SetIterator { .iterator_prototypes() .iterator(), ) - .static_method(Self::next, js_string!("next"), 0) + .static_method(Self::next, "next", 0) .static_property( JsSymbol::to_string_tag(), js_string!("Set Iterator"), diff --git a/boa_engine/src/builtins/string/mod.rs b/boa_engine/src/builtins/string/mod.rs index 6f476b2b125..249df0257d7 100644 --- a/boa_engine/src/builtins/string/mod.rs +++ b/boa_engine/src/builtins/string/mod.rs @@ -17,8 +17,8 @@ use crate::{ object::{internal_methods::get_prototype_from_constructor, JsObject, ObjectData}, property::{Attribute, PropertyDescriptor}, realm::Realm, + string::CodePoint, string::{common::StaticJsStrings, utf16}, - string::{CodePoint, Utf16Trim}, symbol::JsSymbol, value::IntegerOrInfinity, Context, JsArgs, JsResult, JsString, JsValue, @@ -80,12 +80,12 @@ impl IntrinsicObject for String { let trim_start = BuiltInBuilder::callable(realm, Self::trim_start) .length(0) - .name(js_string!("trimStart")) + .name("trimStart") .build(); let trim_end = BuiltInBuilder::callable(realm, Self::trim_end) .length(0) - .name(js_string!("trimEnd")) + .name("trimEnd") .build(); #[cfg(feature = "annex-b")] @@ -96,89 +96,81 @@ impl IntrinsicObject for String { let attribute = Attribute::READONLY | Attribute::NON_ENUMERABLE | Attribute::PERMANENT; let builder = BuiltInBuilder::from_standard_constructor::(realm) - .property(js_string!("length"), 0, attribute) + .property("length", 0, attribute) .property( - js_string!("trimStart"), + "trimStart", trim_start, Attribute::WRITABLE | Attribute::NON_ENUMERABLE | Attribute::CONFIGURABLE, ) .property( - js_string!("trimEnd"), + "trimEnd", trim_end, Attribute::WRITABLE | Attribute::NON_ENUMERABLE | Attribute::CONFIGURABLE, ) - .static_method(Self::raw, js_string!("raw"), 1) - .static_method(Self::from_char_code, js_string!("fromCharCode"), 1) - .static_method(Self::from_code_point, js_string!("fromCodePoint"), 1) - .method(Self::char_at, js_string!("charAt"), 1) - .method(Self::char_code_at, js_string!("charCodeAt"), 1) - .method(Self::code_point_at, js_string!("codePointAt"), 1) - .method(Self::to_string, js_string!("toString"), 0) - .method(Self::concat, js_string!("concat"), 1) - .method(Self::repeat, js_string!("repeat"), 1) - .method(Self::slice, js_string!("slice"), 2) - .method(Self::starts_with, js_string!("startsWith"), 1) - .method(Self::ends_with, js_string!("endsWith"), 1) - .method(Self::includes, js_string!("includes"), 1) - .method(Self::index_of, js_string!("indexOf"), 1) - .method(Self::is_well_formed, js_string!("isWellFormed"), 0) - .method(Self::last_index_of, js_string!("lastIndexOf"), 1) - .method(Self::locale_compare, js_string!("localeCompare"), 1) - .method(Self::r#match, js_string!("match"), 1) - .method(Self::normalize, js_string!("normalize"), 0) - .method(Self::pad_end, js_string!("padEnd"), 1) - .method(Self::pad_start, js_string!("padStart"), 1) - .method(Self::trim, js_string!("trim"), 0) - .method(Self::to_case::, js_string!("toLowerCase"), 0) - .method(Self::to_case::, js_string!("toUpperCase"), 0) - .method(Self::to_well_formed, js_string!("toWellFormed"), 0) - .method( - Self::to_locale_case::, - js_string!("toLocaleLowerCase"), - 0, - ) - .method( - Self::to_locale_case::, - js_string!("toLocaleUpperCase"), - 0, - ) - .method(Self::substring, js_string!("substring"), 2) - .method(Self::split, js_string!("split"), 2) - .method(Self::value_of, js_string!("valueOf"), 0) - .method(Self::match_all, js_string!("matchAll"), 1) - .method(Self::replace, js_string!("replace"), 2) - .method(Self::replace_all, js_string!("replaceAll"), 2) + .static_method(Self::raw, "raw", 1) + .static_method(Self::from_char_code, "fromCharCode", 1) + .static_method(Self::from_code_point, "fromCodePoint", 1) + .method(Self::char_at, "charAt", 1) + .method(Self::char_code_at, "charCodeAt", 1) + .method(Self::code_point_at, "codePointAt", 1) + .method(Self::to_string, "toString", 0) + .method(Self::concat, "concat", 1) + .method(Self::repeat, "repeat", 1) + .method(Self::slice, "slice", 2) + .method(Self::starts_with, "startsWith", 1) + .method(Self::ends_with, "endsWith", 1) + .method(Self::includes, "includes", 1) + .method(Self::index_of, "indexOf", 1) + .method(Self::is_well_formed, "isWellFormed", 0) + .method(Self::last_index_of, "lastIndexOf", 1) + .method(Self::locale_compare, "localeCompare", 1) + .method(Self::r#match, "match", 1) + .method(Self::normalize, "normalize", 0) + .method(Self::pad_end, "padEnd", 1) + .method(Self::pad_start, "padStart", 1) + .method(Self::trim, "trim", 0) + .method(Self::to_case::, "toLowerCase", 0) + .method(Self::to_case::, "toUpperCase", 0) + .method(Self::to_well_formed, "toWellFormed", 0) + .method(Self::to_locale_case::, "toLocaleLowerCase", 0) + .method(Self::to_locale_case::, "toLocaleUpperCase", 0) + .method(Self::substring, "substring", 2) + .method(Self::split, "split", 2) + .method(Self::value_of, "valueOf", 0) + .method(Self::match_all, "matchAll", 1) + .method(Self::replace, "replace", 2) + .method(Self::replace_all, "replaceAll", 2) .method(Self::iterator, JsSymbol::iterator(), 0) - .method(Self::search, js_string!("search"), 1) - .method(Self::at, js_string!("at"), 1); + .method(Self::search, "search", 1) + .method(Self::at, "at", 1); #[cfg(feature = "annex-b")] let builder = { builder .property( - js_string!("trimLeft"), + "trimLeft", trim_left, Attribute::WRITABLE | Attribute::NON_ENUMERABLE | Attribute::CONFIGURABLE, ) .property( - js_string!("trimRight"), + "trimRight", trim_right, Attribute::WRITABLE | Attribute::NON_ENUMERABLE | Attribute::CONFIGURABLE, ) - .method(Self::substr, js_string!("substr"), 2) - .method(Self::anchor, js_string!("anchor"), 1) - .method(Self::big, js_string!("big"), 0) - .method(Self::blink, js_string!("blink"), 0) - .method(Self::bold, js_string!("bold"), 0) - .method(Self::fixed, js_string!("fixed"), 0) - .method(Self::fontcolor, js_string!("fontcolor"), 1) - .method(Self::fontsize, js_string!("fontsize"), 1) - .method(Self::italics, js_string!("italics"), 0) - .method(Self::link, js_string!("link"), 1) - .method(Self::small, js_string!("small"), 0) - .method(Self::strike, js_string!("strike"), 0) - .method(Self::sub, js_string!("sub"), 0) - .method(Self::sup, js_string!("sup"), 0) + .method(Self::substr, "substr", 2) + .method(Self::anchor, "anchor", 1) + .method(Self::big, "big", 0) + .method(Self::blink, "blink", 0) + .method(Self::bold, "bold", 0) + .method(Self::fixed, "fixed", 0) + .method(Self::fontcolor, "fontcolor", 1) + .method(Self::fontsize, "fontsize", 1) + .method(Self::italics, "italics", 0) + .method(Self::link, "link", 1) + .method(Self::small, "small", 0) + .method(Self::strike, "strike", 0) + .method(Self::sub, "sub", 0) + .method(Self::sup, "sup", 0) }; builder.build(); @@ -268,7 +260,7 @@ impl String { // 8. Perform ! DefinePropertyOrThrow(S, "length", PropertyDescriptor { [[Value]]: 𝔽(length), // [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }). s.define_property_or_throw( - utf16!("length"), + "length", PropertyDescriptor::builder() .value(len) .writable(false) @@ -386,7 +378,7 @@ impl String { let cooked = args.get_or_undefined(0).to_object(context)?; // 3. Let raw be ? ToObject(? Get(cooked, "raw")). - let raw = cooked.get(utf16!("raw"), context)?.to_object(context)?; + let raw = cooked.get("raw", context)?.to_object(context)?; // 4. Let literalSegments be ? LengthOfArrayLike(raw). let literal_segments = raw.length_of_array_like(context)?; @@ -411,13 +403,13 @@ impl String { let next_seg = raw.get(next_key, context)?.to_string(context)?; // c. Append the code unit elements of nextSeg to the end of stringElements. - string_elements.extend(next_seg.iter().copied()); + string_elements.extend(next_seg.iter()); // d. If nextIndex + 1 = literalSegments, then if next_index + 1 == literal_segments { // i. Return the String value whose code units are the elements in the List stringElements. // If stringElements has no elements, the empty String is returned. - return Ok(js_string!(string_elements).into()); + return Ok(js_string!(&string_elements[..]).into()); } // e. If nextIndex < numberOfSubstitutions, let next be substitutions[nextIndex]. @@ -433,7 +425,7 @@ impl String { let next_sub = next.to_string(context)?; // h. Append the code unit elements of nextSub to the end of stringElements. - string_elements.extend(next_sub.iter().copied()); + string_elements.extend(next_sub.iter()); // i. Set nextIndex to nextIndex + 1. next_index += 1; @@ -465,7 +457,7 @@ impl String { } // 3. Return result. - Ok(js_string!(result).into()) + Ok(js_string!(&result[..]).into()) } /// `String.prototype.toString ( )` @@ -519,7 +511,7 @@ impl String { // 6. Return the substring of S from position to position + 1. IntegerOrInfinity::Integer(i) if i >= 0 && i < string.len() as i64 => { let i = i as usize; - Ok(js_string!(&string[i..=i]).into()) + Ok(js_string!(&string.to_vec()[i..=i]).into()) } // 5. If position < 0 or position ≥ size, return the empty String. _ => Ok(js_string!().into()), @@ -565,7 +557,7 @@ impl String { }; // 8. Return the substring of S from k to k + 1. - Ok(js_string!(&s[k..=k]).into()) + Ok(js_string!(&s.to_vec()[k..=k]).into()) } /// `String.prototype.codePointAt( index )` @@ -643,7 +635,7 @@ impl String { // 4. Let size be the length of S. IntegerOrInfinity::Integer(i) if i >= 0 && i < string.len() as i64 => { // 6. Return the Number value for the numeric value of the code unit at index position within the String S. - Ok(u32::from(string[i as usize]).into()) + Ok(u32::from(string.to_vec()[i as usize]).into()) } // 5. If position < 0 or position ≥ size, return NaN. _ => Ok(JsValue::nan()), @@ -722,12 +714,12 @@ impl String { let n = n as usize; let mut result = Vec::with_capacity(n * len); - std::iter::repeat(&string[..]) + std::iter::repeat(&string.to_vec()[..]) .take(n) .for_each(|s| result.extend_from_slice(s)); // 6. Return the String value that is made from n copies of S appended together. - Ok(js_string!(result).into()) + Ok(js_string!(&result[..]).into()) } // 5. If n is 0, return the empty String. IntegerOrInfinity::Integer(0) => Ok(js_string!().into()), @@ -802,7 +794,7 @@ impl String { Ok(js_string!().into()) } else { // 13. Return the substring of S from from to to. - Ok(js_string!(&string[from..to]).into()) + Ok(js_string!(&string.to_vec()[from..to]).into()) } } @@ -871,7 +863,7 @@ impl String { // 14. Return ! SameValueNonNumeric(substring, searchStr). // `SameValueNonNumeric` forwards to `==`, so directly check // equality to avoid converting to `JsValue` - Ok(JsValue::new(search_string == string[start..end])) + Ok(JsValue::new(search_string == string.to_vec()[start..end])) } } @@ -934,7 +926,7 @@ impl String { // 14. Return ! SameValueNonNumeric(substring, searchStr). // `SameValueNonNumeric` forwards to `==`, so directly check // equality to avoid converting to `JsValue` - Ok(JsValue::new(search_str == string[start..end])) + Ok(JsValue::new(search_str == string.to_vec()[start..end])) } else { // 12. If start < 0, return false. Ok(false.into()) @@ -985,7 +977,10 @@ impl String { // 10. Let index be ! StringIndexOf(S, searchStr, start). // 11. If index is not -1, return true. // 12. Return false. - Ok(string.index_of(&search_str, start).is_some().into()) + Ok(string + .index_of(&search_str.as_slice(), start) + .is_some() + .into()) } /// `String.prototype.replace( regexp|substr, newSubstr|function )` @@ -1054,12 +1049,12 @@ impl String { // 8. Let position be ! StringIndexOf(string, searchString, 0). // 9. If position is -1, return string. - let Some(position) = string.index_of(&search_string, 0) else { + let Some(position) = string.index_of(&search_string.as_slice(), 0) else { return Ok(string.into()); }; // 10. Let preserved be the substring of string from 0 to position. - let preserved = &string[..position]; + let preserved = &string.to_vec()[..position]; let replacement = match replace_value { // 11. If functionalReplace is true, then @@ -1093,7 +1088,12 @@ impl String { }; // 13. Return the string-concatenation of preserved, replacement, and the substring of string from position + searchLength. - Ok(js_string!(preserved, &replacement, &string[position + search_length..]).into()) + Ok(js_string!( + preserved, + &replacement, + &string.to_vec()[position + search_length..] + ) + .into()) } /// `22.1.3.18 String.prototype.replaceAll ( searchValue, replaceValue )` @@ -1129,13 +1129,13 @@ impl String { // b. If isRegExp is true, then if let Some(obj) = RegExp::is_reg_exp(search_value, context)? { // i. Let flags be ? Get(searchValue, "flags"). - let flags = obj.get(utf16!("flags"), context)?; + let flags = obj.get("flags", context)?; // ii. Perform ? RequireObjectCoercible(flags). flags.require_object_coercible()?; // iii. If ? ToString(flags) does not contain "g", throw a TypeError exception. - if !flags.to_string(context)?.contains(&u16::from(b'g')) { + if !flags.to_string(context)?.contains(b'g') { return Err(JsNativeError::typ() .with_message( "String.prototype.replaceAll called with a non-global RegExp argument", @@ -1179,7 +1179,7 @@ impl String { let mut match_positions = Vec::new(); // 10. Let position be ! StringIndexOf(string, searchString, 0). - let mut position = string.index_of(&search_string, 0); + let mut position = string.index_of(&search_string.as_slice(), 0); // 11. Repeat, while position is not -1, while let Some(p) = position { @@ -1187,7 +1187,7 @@ impl String { match_positions.push(p); // b. Set position to ! StringIndexOf(string, searchString, position + advanceBy). - position = string.index_of(&search_string, p + advance_by); + position = string.index_of(&search_string.as_slice(), p + advance_by); } // 12. Let endOfLastMatch be 0. @@ -1199,7 +1199,7 @@ impl String { // 14. For each element p of matchPositions, do for p in match_positions { // a. Let preserved be the substring of string from endOfLastMatch to p. - let preserved = &string[end_of_last_match..p]; + let preserved = &string.to_vec()[end_of_last_match..p]; // c. Else, let replacement = match replace { @@ -1234,8 +1234,8 @@ impl String { }; // d. Set result to the string-concatenation of result, preserved, and replacement. - result.extend_from_slice(preserved); - result.extend_from_slice(&replacement); + result.extend(preserved.iter()); + result.extend(replacement.iter()); // e. Set endOfLastMatch to p + searchLength. end_of_last_match = p + search_length; @@ -1244,11 +1244,11 @@ impl String { // 15. If endOfLastMatch < the length of string, then if end_of_last_match < string.len() { // a. Set result to the string-concatenation of result and the substring of string from endOfLastMatch. - result.extend_from_slice(&string[end_of_last_match..]); + result.extend_from_slice(&string.to_vec()[end_of_last_match..]); } // 16. Return result. - Ok(js_string!(result).into()) + Ok(js_string!(&result[..]).into()) } /// `String.prototype.indexOf( searchValue[, fromIndex] )` @@ -1290,7 +1290,7 @@ impl String { // 8. Return 𝔽(! StringIndexOf(S, searchStr, start)). Ok(string - .index_of(&search_str, start) + .index_of(&search_str.as_slice(), start) .map_or(-1, |i| i as i64) .into()) } @@ -1380,7 +1380,7 @@ impl String { // 11. For each non-negative integer i starting with start such that i ≤ len - searchLen, in descending order, do for i in (0..=min(start, end)).rev() { // a. Let candidate be the substring of S from i to i + searchLen. - let candidate = &string[i..i + search_len]; + let candidate = &string.to_vec()[i..i + search_len]; // b. If candidate is the same sequence of code units as searchStr, return 𝔽(i). if candidate == &search_str { @@ -1441,6 +1441,9 @@ impl String { .expect("constructor must return a `Collator` object") .collator(); + let s = s.iter().collect::>(); + let that_value = that_value.iter().collect::>(); + collator.compare_utf16(&s, &that_value) as i8 } @@ -1554,7 +1557,7 @@ impl String { } }; - let truncated_string_filler = filler.repeat(repetitions as usize); + let truncated_string_filler = filler.to_vec().repeat(repetitions as usize); let truncated_string_filler = &truncated_string_filler[..fill_len as usize]; // 10. If placement is start, return the string-concatenation of truncatedStringFiller and S. @@ -1890,7 +1893,7 @@ impl String { let to = max(final_start, final_end); // 10. Return the substring of S from from to to. - Ok(js_string!(&string[from..to]).into()) + Ok(js_string!(&string.to_vec()[from..to]).into()) } /// `String.prototype.split ( separator, limit )` @@ -1958,6 +1961,7 @@ impl String { if separator_length == 0 { // a. Let head be the substring of S from 0 to lim. // b. Let codeUnits be a List consisting of the sequence of code units that are the elements of head. + let this_str = this_str.to_vec(); let head = this_str .get(..lim) .unwrap_or(&this_str[..]) @@ -1979,13 +1983,13 @@ impl String { let mut i = 0; // 13. Let j be ! StringIndexOf(S, R, 0). - let mut j = this_str.index_of(&separator_str, 0); + let mut j = this_str.index_of(&separator_str.as_slice(), 0); // 14. Repeat, while j is not -1 while let Some(index) = j { // a. Let T be the substring of S from i to j. // b. Append T as the last element of substrings. - substrings.push(js_string!(&this_str[i..index])); + substrings.push(js_string!(&this_str.to_vec()[i..index])); // c. If the number of elements of substrings is lim, return ! CreateArrayFromList(substrings). if substrings.len() == lim { @@ -1999,12 +2003,12 @@ impl String { i = index + separator_length; // e. Set j to ! StringIndexOf(S, R, i). - j = this_str.index_of(&separator_str, i); + j = this_str.index_of(&separator_str.as_slice(), i); } // 15. Let T be the substring of S from i. // 16. Append T to substrings. - substrings.push(js_string!(&this_str[i..])); + substrings.push(js_string!(&this_str.to_vec()[i..])); // 17. Return ! CreateArrayFromList(substrings). Ok( @@ -2059,13 +2063,13 @@ impl String { // b. If isRegExp is true, then if let Some(regexp) = RegExp::is_reg_exp(regexp, context)? { // i. Let flags be ? Get(regexp, "flags"). - let flags = regexp.get(utf16!("flags"), context)?; + let flags = regexp.get("flags", context)?; // ii. Perform ? RequireObjectCoercible(flags). flags.require_object_coercible()?; // iii. If ? ToString(flags) does not contain "g", throw a TypeError exception. - if !flags.to_string(context)?.contains(&u16::from(b'g')) { + if !flags.to_string(context)?.contains(b'g') { return Err(JsNativeError::typ() .with_message( "String.prototype.matchAll called with a non-global RegExp argument", @@ -2129,10 +2133,10 @@ impl String { &JsValue::Undefined => Normalization::Nfc, // 4. Else, let f be ? ToString(form). f => match f.to_string(context)? { - ntype if &ntype == utf16!("NFC") => Normalization::Nfc, - ntype if &ntype == utf16!("NFD") => Normalization::Nfd, - ntype if &ntype == utf16!("NFKC") => Normalization::Nfkc, - ntype if &ntype == utf16!("NFKD") => Normalization::Nfkd, + ntype if &ntype == "NFC" => Normalization::Nfc, + ntype if &ntype == "NFD" => Normalization::Nfd, + ntype if &ntype == "NFKC" => Normalization::Nfkc, + ntype if &ntype == "NFKD" => Normalization::Nfkd, // 5. If f is not one of "NFC", "NFD", "NFKC", or "NFKD", throw a RangeError exception. _ => { return Err(JsNativeError::range() @@ -2161,6 +2165,8 @@ impl String { } }; + let s = s.iter().collect::>(); + let result = match normalization { Normalization::Nfc => normalizers.nfc.normalize_utf16(&s), Normalization::Nfd => normalizers.nfd.normalize_utf16(&s), @@ -2169,7 +2175,7 @@ impl String { }; // 7. Return ns. - Ok(js_string!(result).into()) + Ok(js_string!(&result[..]).into()) } /// `String.prototype.search( regexp )` @@ -2289,7 +2295,7 @@ impl String { let int_end = min(int_start + int_length, size as usize); // 11. Return the substring of S from intStart to intEnd. - if let Some(substr) = s.get(int_start..int_end) { + if let Some(substr) = s.to_vec().get(int_start..int_end) { Ok(js_string!(substr).into()) } else { Ok(js_string!().into()) @@ -2304,8 +2310,8 @@ impl String { /// [spec]: https://tc39.es/ecma262/#sec-createhtml pub(crate) fn create_html( string: &JsValue, - tag: &[u16], - attribute_and_value: Option<(&[u16], &JsValue)>, + tag: &str, + attribute_and_value: Option<(&str, &JsValue)>, context: &mut Context<'_>, ) -> JsResult { // 1. Let str be ? RequireObjectCoercible(string). @@ -2315,7 +2321,7 @@ impl String { let s = str.to_string(context)?; // 3. Let p1 be the string-concatenation of "<" and tag. - let mut p1 = JsString::concat_array(&[utf16!("<"), tag]); + let mut p1 = js_string!("<", tag); // 4. If attribute is not the empty String, then if let Some((attribute, value)) = attribute_and_value { @@ -2326,7 +2332,7 @@ impl String { // of the code unit 0x0022 (QUOTATION MARK) in V has been replaced with the six // code unit sequence """. let mut escaped_v = Vec::with_capacity(v.len()); - for c in v.as_slice().iter().copied() { + for c in v.iter() { if c == 0x0022 { escaped_v.extend(utf16!(""")); continue; @@ -2342,27 +2348,13 @@ impl String { // the code unit 0x0022 (QUOTATION MARK) // escapedV // the code unit 0x0022 (QUOTATION MARK) - p1 = JsString::concat_array(&[ - p1.as_slice(), - utf16!(" "), - attribute, - utf16!("=\""), - escaped_v.as_slice(), - utf16!("\""), - ]); + p1 = js_string!(p1, " ", attribute, "=\"", &escaped_v[..], "\""); } // 5. Let p2 be the string-concatenation of p1 and ">". // 6. Let p3 be the string-concatenation of p2 and S. // 7. Let p4 be the string-concatenation of p3, "". - let p4 = JsString::concat_array(&[ - p1.as_slice(), - utf16!(">"), - s.as_slice(), - utf16!(""), - ]); + let p4 = js_string!(p1, ">", s, ""); // 8. Return p4. Ok(p4.into()) @@ -2386,7 +2378,7 @@ impl String { // 1. Let S be the this value. let s = this; // 2. Return ? CreateHTML(S, "a", "name", name). - Self::create_html(s, utf16!("a"), Some((utf16!("name"), name)), context) + Self::create_html(s, "a", Some(("name", name)), context) } /// `String.prototype.big( )` @@ -2405,7 +2397,7 @@ impl String { // 1. Let S be the this value. let s = this; // 2. Return ? CreateHTML(S, "big", "", ""). - Self::create_html(s, utf16!("big"), None, context) + Self::create_html(s, "big", None, context) } /// `String.prototype.blink( )` @@ -2424,7 +2416,7 @@ impl String { // 1. Let S be the this value. let s = this; // 2. Return ? CreateHTML(S, "blink", "", ""). - Self::create_html(s, utf16!("blink"), None, context) + Self::create_html(s, "blink", None, context) } /// `String.prototype.bold( )` @@ -2443,7 +2435,7 @@ impl String { // 1. Let S be the this value. let s = this; // 2. Return ? CreateHTML(S, "b", "", ""). - Self::create_html(s, utf16!("b"), None, context) + Self::create_html(s, "b", None, context) } /// `String.prototype.fixed( )` @@ -2462,7 +2454,7 @@ impl String { // 1. Let S be the this value. let s = this; // 2. Return ? CreateHTML(S, "big", "", ""). - Self::create_html(s, utf16!("tt"), None, context) + Self::create_html(s, "tt", None, context) } /// `String.prototype.fontcolor( color )` @@ -2483,7 +2475,7 @@ impl String { // 1. Let S be the this value. let s = this; // 2. Return ? CreateHTML(S, "font", "color", color). - Self::create_html(s, utf16!("font"), Some((utf16!("color"), color)), context) + Self::create_html(s, "font", Some(("color", color)), context) } /// `String.prototype.fontsize( size )` @@ -2504,7 +2496,7 @@ impl String { // 1. Let S be the this value. let s = this; // 2. Return ? CreateHTML(S, "font", "size", size). - Self::create_html(s, utf16!("font"), Some((utf16!("size"), size)), context) + Self::create_html(s, "font", Some(("size", size)), context) } /// `String.prototype.italics( )` @@ -2523,7 +2515,7 @@ impl String { // 1. Let S be the this value. let s = this; // 2. Return ? CreateHTML(S, "i", "", ""). - Self::create_html(s, utf16!("i"), None, context) + Self::create_html(s, "i", None, context) } /// `String.prototype.link( url )` @@ -2544,7 +2536,7 @@ impl String { // 1. Let S be the this value. let s = this; // 2. Return ? CreateHTML(S, "a", "href", url). - Self::create_html(s, utf16!("a"), Some((utf16!("href"), url)), context) + Self::create_html(s, "a", Some(("href", url)), context) } /// `String.prototype.small( )` @@ -2563,7 +2555,7 @@ impl String { // 1. Let S be the this value. let s = this; // 2. Return ? CreateHTML(S, "small", "", ""). - Self::create_html(s, utf16!("small"), None, context) + Self::create_html(s, "small", None, context) } /// `String.prototype.strike( )` @@ -2582,7 +2574,7 @@ impl String { // 1. Let S be the this value. let s = this; // 2. Return ? CreateHTML(S, "strike", "", ""). - Self::create_html(s, utf16!("strike"), None, context) + Self::create_html(s, "strike", None, context) } /// `String.prototype.sub( )` @@ -2601,7 +2593,7 @@ impl String { // 1. Let S be the this value. let s = this; // 2. Return ? CreateHTML(S, "sub", "", ""). - Self::create_html(s, utf16!("sub"), None, context) + Self::create_html(s, "sub", None, context) } /// `String.prototype.sup( )` @@ -2620,7 +2612,7 @@ impl String { // 1. Let S be the this value. let s = this; // 2. Return ? CreateHTML(S, "sup", "", ""). - Self::create_html(s, utf16!("sup"), None, context) + Self::create_html(s, "sup", None, context) } } @@ -2681,19 +2673,19 @@ pub(crate) fn get_substitution( // $& Some(CodePoint::Unicode('&')) => { // matched - result.extend_from_slice(matched); + result.extend(matched.iter()); } // $` Some(CodePoint::Unicode('`')) => { // The replacement is the substring of str from 0 to position. - result.extend_from_slice(&str[..position]); + result.extend_from_slice(&str.to_vec()[..position]); } // $' Some(CodePoint::Unicode('\'')) => { // If tailPos ≥ stringLength, the replacement is the empty String. // Otherwise the replacement is the substring of str from tailPos. if tail_pos < str_length { - result.extend_from_slice(&str[tail_pos..]); + result.extend(&str.to_vec()[tail_pos..]); } } // $nn @@ -2740,7 +2732,7 @@ pub(crate) fn get_substitution( // a. Let refReplacement be capture. if let Some(capture) = captures.get(index - 1) { if let Some(s) = capture.as_string() { - result.extend_from_slice(s); + result.extend(s.iter()); } } @@ -2784,14 +2776,14 @@ pub(crate) fn get_substitution( // d. Else, } else { // i. Let groupName be the enclosed substring. - let group_name = js_string!(group_name); + let group_name = js_string!(&group_name[..]); // ii. Let capture be ? Get(namedCaptures, groupName). let capture = named_captures.get(group_name, context)?; // iii. If capture is undefined, replace the text through > with the empty String. // iv. Otherwise, replace the text through > with ? ToString(capture). if !capture.is_undefined() { - result.extend_from_slice(&capture.to_string(context)?); + result.extend(capture.to_string(context)?.iter()); } } } @@ -2810,5 +2802,5 @@ pub(crate) fn get_substitution( } // 11. Return result. - Ok(js_string!(result)) + Ok(js_string!(&result[..])) } diff --git a/boa_engine/src/builtins/string/string_iterator.rs b/boa_engine/src/builtins/string/string_iterator.rs index 129e60257d1..11b4fa93e73 100644 --- a/boa_engine/src/builtins/string/string_iterator.rs +++ b/boa_engine/src/builtins/string/string_iterator.rs @@ -43,7 +43,7 @@ impl IntrinsicObject for StringIterator { .iterator_prototypes() .iterator(), ) - .static_method(Self::next, js_string!("next"), 0) + .static_method(Self::next, "next", 0) .static_property( JsSymbol::to_string_tag(), js_string!("String Iterator"), diff --git a/boa_engine/src/builtins/symbol/mod.rs b/boa_engine/src/builtins/symbol/mod.rs index ebc5efe9b80..60d8a34fc39 100644 --- a/boa_engine/src/builtins/symbol/mod.rs +++ b/boa_engine/src/builtins/symbol/mod.rs @@ -64,8 +64,8 @@ impl GlobalSymbolRegistry { } fn get_or_create_symbol(&self, key: &JsString) -> JsResult { - let slice = &**key; - if let Some(symbol) = self.keys.get(slice) { + let slice = key.iter().collect::>(); + if let Some(symbol) = self.keys.get(&slice[..]) { return Ok(symbol.clone()); } @@ -73,8 +73,10 @@ impl GlobalSymbolRegistry { JsNativeError::range() .with_message("reached the maximum number of symbols that can be created") })?; - self.keys.insert(slice.into(), symbol.clone()); - self.symbols.insert(symbol.clone(), slice.into()); + self.keys + .insert(slice.clone().into_boxed_slice(), symbol.clone()); + self.symbols + .insert(symbol.clone(), slice.into_boxed_slice()); Ok(symbol) } @@ -112,50 +114,34 @@ impl IntrinsicObject for Symbol { let attribute = Attribute::READONLY | Attribute::NON_ENUMERABLE | Attribute::PERMANENT; let to_primitive = BuiltInBuilder::callable(realm, Self::to_primitive) - .name(js_string!("[Symbol.toPrimitive]")) + .name("[Symbol.toPrimitive]") .length(1) .build(); let get_description = BuiltInBuilder::callable(realm, Self::get_description) - .name(js_string!("get description")) + .name("get description") .build(); BuiltInBuilder::from_standard_constructor::(realm) - .static_method(Self::for_, js_string!("for"), 1) - .static_method(Self::key_for, js_string!("keyFor"), 1) - .static_property( - js_string!("asyncIterator"), - symbol_async_iterator, - attribute, - ) - .static_property(js_string!("hasInstance"), symbol_has_instance, attribute) - .static_property( - js_string!("isConcatSpreadable"), - symbol_is_concat_spreadable, - attribute, - ) - .static_property(js_string!("iterator"), symbol_iterator, attribute) - .static_property(js_string!("match"), symbol_match, attribute) - .static_property(js_string!("matchAll"), symbol_match_all, attribute) - .static_property(js_string!("replace"), symbol_replace, attribute) - .static_property(js_string!("search"), symbol_search, attribute) - .static_property(js_string!("species"), symbol_species, attribute) - .static_property(js_string!("split"), symbol_split, attribute) - .static_property( - js_string!("toPrimitive"), - symbol_to_primitive.clone(), - attribute, - ) - .static_property( - js_string!("toStringTag"), - symbol_to_string_tag.clone(), - attribute, - ) - .static_property(js_string!("unscopables"), symbol_unscopables, attribute) - .method(Self::to_string, js_string!("toString"), 0) - .method(Self::value_of, js_string!("valueOf"), 0) + .static_method(Self::for_, "for", 1) + .static_method(Self::key_for, "keyFor", 1) + .static_property("asyncIterator", symbol_async_iterator, attribute) + .static_property("hasInstance", symbol_has_instance, attribute) + .static_property("isConcatSpreadable", symbol_is_concat_spreadable, attribute) + .static_property("iterator", symbol_iterator, attribute) + .static_property("match", symbol_match, attribute) + .static_property("matchAll", symbol_match_all, attribute) + .static_property("replace", symbol_replace, attribute) + .static_property("search", symbol_search, attribute) + .static_property("species", symbol_species, attribute) + .static_property("split", symbol_split, attribute) + .static_property("toPrimitive", symbol_to_primitive.clone(), attribute) + .static_property("toStringTag", symbol_to_string_tag.clone(), attribute) + .static_property("unscopables", symbol_unscopables, attribute) + .method(Self::to_string, "toString", 0) + .method(Self::value_of, "valueOf", 0) .accessor( - js_string!("description"), + "description", Some(get_description), None, Attribute::CONFIGURABLE | Attribute::NON_ENUMERABLE, diff --git a/boa_engine/src/builtins/temporal/calendar/iso.rs b/boa_engine/src/builtins/temporal/calendar/iso.rs index 4074aa3fa97..4de0398df7e 100644 --- a/boa_engine/src/builtins/temporal/calendar/iso.rs +++ b/boa_engine/src/builtins/temporal/calendar/iso.rs @@ -9,7 +9,6 @@ use crate::{ }, js_string, property::PropertyKey, - string::utf16, Context, JsNativeError, JsResult, JsString, JsValue, }; @@ -350,9 +349,9 @@ impl BuiltinCalendar for IsoCalendar { let key_string = key.to_string(); result.push(key); if key_string.as_str() == "month" { - result.push(utf16!("monthCode").into()); + result.push("monthCode".into()); } else if key_string.as_str() == "monthCode" { - result.push(utf16!("month").into()); + result.push("month".into()); } } result diff --git a/boa_engine/src/builtins/temporal/calendar/mod.rs b/boa_engine/src/builtins/temporal/calendar/mod.rs index d58f35f6807..30f67c935b8 100644 --- a/boa_engine/src/builtins/temporal/calendar/mod.rs +++ b/boa_engine/src/builtins/temporal/calendar/mod.rs @@ -18,7 +18,7 @@ use crate::{ object::{internal_methods::get_prototype_from_constructor, ObjectData}, property::{Attribute, PropertyKey}, realm::Realm, - string::{common::StaticJsStrings, utf16}, + string::common::StaticJsStrings, Context, JsArgs, JsNativeError, JsObject, JsResult, JsString, JsSymbol, JsValue, }; use boa_profiler::Profiler; @@ -159,15 +159,15 @@ impl core::fmt::Debug for dyn BuiltinCalendar { // ==== Calendar Abstractions ==== -const ISO: &[u16] = utf16!("iso8601"); +const ISO: &str = "iso8601"; // NOTE: potentially move these to `Realm`, so that there can be // host defined calendars. // Returns a map of all available calendars. -fn available_calendars() -> FxHashMap<&'static [u16], Box> { +fn available_calendars() -> FxHashMap> { let mut map = FxHashMap::default(); let iso: Box = Box::new(IsoCalendar); - map.insert(ISO, iso); + map.insert(js_string!(ISO), iso); map } @@ -176,7 +176,7 @@ fn available_calendars() -> FxHashMap<&'static [u16], Box> pub(crate) fn is_builtin_calendar(identifier: &JsString) -> bool { let calendars = available_calendars(); // TODO: Potentially implement `to_ascii_lowercase`. - calendars.contains_key(identifier.as_slice()) + calendars.contains_key(identifier) } /// The `Temporal.Calendar` object. @@ -194,7 +194,7 @@ impl IntrinsicObject for Calendar { let _timer = Profiler::global().start_event(std::any::type_name::(), "init"); let get_id = BuiltInBuilder::callable(realm, Self::get_id) - .name(js_string!("get Id")) + .name("get Id") .build(); BuiltInBuilder::from_standard_constructor::(realm) @@ -203,39 +203,31 @@ impl IntrinsicObject for Calendar { Self::NAME, Attribute::CONFIGURABLE, ) - .accessor(utf16!("id"), Some(get_id), None, Attribute::default()) - .method(Self::date_from_fields, js_string!("dateFromFields"), 2) - .method( - Self::year_month_from_fields, - js_string!("yearMonthFromFields"), - 2, - ) - .method( - Self::month_day_from_fields, - js_string!("monthDayFromFields"), - 2, - ) - .method(Self::date_add, js_string!("dateAdd"), 3) - .method(Self::date_until, js_string!("dateUntil"), 3) - .method(Self::era, js_string!("era"), 1) - .method(Self::era_year, js_string!("eraYear"), 1) - .method(Self::year, js_string!("year"), 1) - .method(Self::month, js_string!("month"), 1) - .method(Self::month_code, js_string!("monthCode"), 1) - .method(Self::day, js_string!("day"), 1) - .method(Self::day_of_week, js_string!("dayOfWeek"), 1) - .method(Self::day_of_year, js_string!("dayOfYear"), 1) - .method(Self::week_of_year, js_string!("weekOfYear"), 1) - .method(Self::year_of_week, js_string!("yearOfWeek"), 1) - .method(Self::days_in_week, js_string!("daysInWeek"), 1) - .method(Self::days_in_month, js_string!("daysInMonth"), 1) - .method(Self::days_in_year, js_string!("daysInYear"), 1) - .method(Self::months_in_year, js_string!("monthsInYear"), 1) - .method(Self::in_leap_year, js_string!("inLeapYear"), 1) - .method(Self::fields, js_string!("fields"), 1) - .method(Self::merge_fields, js_string!("mergeFields"), 2) - .method(Self::get_id, js_string!("toString"), 0) - .method(Self::get_id, js_string!("toJSON"), 0) + .accessor("id", Some(get_id), None, Attribute::default()) + .method(Self::date_from_fields, "dateFromFields", 2) + .method(Self::year_month_from_fields, "yearMonthFromFields", 2) + .method(Self::month_day_from_fields, "monthDayFromFields", 2) + .method(Self::date_add, "dateAdd", 3) + .method(Self::date_until, "dateUntil", 3) + .method(Self::era, "era", 1) + .method(Self::era_year, "eraYear", 1) + .method(Self::year, "year", 1) + .method(Self::month, "month", 1) + .method(Self::month_code, "monthCode", 1) + .method(Self::day, "day", 1) + .method(Self::day_of_week, "dayOfWeek", 1) + .method(Self::day_of_year, "dayOfYear", 1) + .method(Self::week_of_year, "weekOfYear", 1) + .method(Self::year_of_week, "yearOfWeek", 1) + .method(Self::days_in_week, "daysInWeek", 1) + .method(Self::days_in_month, "daysInMonth", 1) + .method(Self::days_in_year, "daysInYear", 1) + .method(Self::months_in_year, "monthsInYear", 1) + .method(Self::in_leap_year, "inLeapYear", 1) + .method(Self::fields, "fields", 1) + .method(Self::merge_fields, "mergeFields", 2) + .method(Self::get_id, "toString", 0) + .method(Self::get_id, "toJSON", 0) .build(); } @@ -320,7 +312,7 @@ impl Calendar { // Retrieve the current CalendarProtocol. let available_calendars = available_calendars(); let this_calendar = available_calendars - .get(calendar.identifier.as_slice()) + .get(&calendar.identifier) .expect("builtin must exist"); // 3. If Type(fields) is not Object, throw a TypeError exception. @@ -341,7 +333,7 @@ impl Calendar { ]); // 6. If calendar.[[Identifier]] is "iso8601", then - let mut fields = if calendar.identifier.as_slice() == ISO { + let mut fields = if &calendar.identifier == ISO { // a. Set fields to ? PrepareTemporalFields(fields, relevantFieldNames, « "year", "day" »). let mut required_fields = Vec::from(["year".to_owned(), "day".to_owned()]); temporal::TemporalFields::from_js_object( @@ -370,8 +362,8 @@ impl Calendar { }; // 8. Let overflow be ? ToTemporalOverflow(options). - let overflow = get_option(&options, utf16!("overflow"), context)? - .unwrap_or(ArithmeticOverflow::Constrain); + let overflow = + get_option(&options, "overflow", context)?.unwrap_or(ArithmeticOverflow::Constrain); // NOTE: implement the below on the calenar itself // 9. If calendar.[[Identifier]] is "iso8601", then @@ -401,7 +393,7 @@ impl Calendar { let available_calendars = available_calendars(); let this_calendar = available_calendars - .get(calendar.identifier.as_slice()) + .get(&calendar.identifier) .expect("builtin must exist"); let fields = args.get_or_undefined(0); let fields_obj = fields.as_object().ok_or_else(|| { @@ -418,7 +410,7 @@ impl Calendar { ]); // 6. Set fields to ? PrepareTemporalFields(fields, « "month", "monthCode", "year" », « "year" »). - let mut fields = if calendar.identifier.as_slice() == ISO { + let mut fields = if &calendar.identifier == ISO { // a. Set fields to ? PrepareTemporalFields(fields, relevantFieldNames, « "year" »). let mut required_fields = Vec::from(["year".to_owned()]); temporal::TemporalFields::from_js_object( @@ -451,7 +443,7 @@ impl Calendar { }; // 7. Let overflow be ? ToTemporalOverflow(options). - let overflow = get_option::(&options, utf16!("overflow"), context)? + let overflow = get_option::(&options, "overflow", context)? .unwrap_or(ArithmeticOverflow::Constrain); this_calendar.year_month_from_fields(&mut fields, overflow, context) @@ -476,7 +468,7 @@ impl Calendar { let available_calendars = available_calendars(); let this_calendar = available_calendars - .get(calendar.identifier.as_slice()) + .get(&calendar.identifier) .expect("builtin must exist"); // 3. If Type(fields) is not Object, throw a TypeError exception. @@ -497,7 +489,7 @@ impl Calendar { ]); // 6. If calendar.[[Identifier]] is "iso8601", then - let mut fields = if calendar.identifier.as_slice() == ISO { + let mut fields = if &calendar.identifier == ISO { // a. Set fields to ? PrepareTemporalFields(fields, relevantFieldNames, « "day" »). let mut required_fields = Vec::from(["day".to_owned()]); temporal::TemporalFields::from_js_object( @@ -527,8 +519,8 @@ impl Calendar { }; // 8. Let overflow be ? ToTemporalOverflow(options). - let overflow = get_option(&options, utf16!("overflow"), context)? - .unwrap_or(ArithmeticOverflow::Constrain); + let overflow = + get_option(&options, "overflow", context)?.unwrap_or(ArithmeticOverflow::Constrain); this_calendar.month_day_from_fields(&mut fields, overflow, context) } @@ -549,7 +541,7 @@ impl Calendar { let available_calendars = available_calendars(); let this_calendar = available_calendars - .get(calendar.identifier.as_slice()) + .get(&calendar.identifier) .expect("builtin must exist"); // 4. Set date to ? ToTemporalDate(date). @@ -565,8 +557,8 @@ impl Calendar { let options_obj = get_options_object(options)?; // 7. Let overflow be ? ToTemporalOverflow(options). - let overflow = get_option(&options_obj, utf16!("overflow"), context)? - .unwrap_or(ArithmeticOverflow::Constrain); + let overflow = + get_option(&options_obj, "overflow", context)?.unwrap_or(ArithmeticOverflow::Constrain); // 8. Let balanceResult be ? BalanceTimeDuration(duration.[[Days]], duration.[[Hours]], duration.[[Minutes]], duration.[[Seconds]], duration.[[Milliseconds]], duration.[[Microseconds]], duration.[[Nanoseconds]], "day"). duration.balance_time_duration(TemporalUnit::Day, None)?; @@ -594,7 +586,7 @@ impl Calendar { let available_calendars = available_calendars(); let this_calendar = available_calendars - .get(calendar.identifier.as_slice()) + .get(&calendar.identifier) .expect("builtin must exist"); // 4. Set one to ? ToTemporalDate(one). @@ -609,7 +601,7 @@ impl Calendar { // 8. If largestUnit is "auto", set largestUnit to "day". let largest_unit = super::options::get_temporal_unit( &options, - utf16!("largestUnit"), + "largestUnit", TemporalUnitGroup::Date, None, context, @@ -632,7 +624,7 @@ impl Calendar { let available_calendars = available_calendars(); let this_calendar = available_calendars - .get(calendar.identifier.as_slice()) + .get(&calendar.identifier) .expect("builtin must exist"); let date_like = args.get_or_undefined(0); @@ -678,7 +670,7 @@ impl Calendar { let available_calendars = available_calendars(); let this_calendar = available_calendars - .get(calendar.identifier.as_slice()) + .get(&calendar.identifier) .expect("builtin must exist"); let date_like = args.get_or_undefined(0); @@ -724,7 +716,7 @@ impl Calendar { let available_calendars = available_calendars(); let this_calendar = available_calendars - .get(calendar.identifier.as_slice()) + .get(&calendar.identifier) .expect("builtin must exist"); let date_like = args.get_or_undefined(0); @@ -770,7 +762,7 @@ impl Calendar { let available_calendars = available_calendars(); let this_calendar = available_calendars - .get(calendar.identifier.as_slice()) + .get(&calendar.identifier) .expect("builtin must exist"); let date_like = args.get_or_undefined(0); @@ -829,7 +821,7 @@ impl Calendar { let available_calendars = available_calendars(); let this_calendar = available_calendars - .get(calendar.identifier.as_slice()) + .get(&calendar.identifier) .expect("builtin must exist"); let date_like = args.get_or_undefined(0); @@ -881,7 +873,7 @@ impl Calendar { let available_calendars = available_calendars(); let this_calendar = available_calendars - .get(calendar.identifier.as_slice()) + .get(&calendar.identifier) .expect("builtin must exist"); let date_like = args.get_or_undefined(0); @@ -933,7 +925,7 @@ impl Calendar { let available_calendars = available_calendars(); let this_calendar = available_calendars - .get(calendar.identifier.as_slice()) + .get(&calendar.identifier) .expect("builtin must exist"); // 3. Let temporalDate be ? ToTemporalDate(temporalDateLike). @@ -960,7 +952,7 @@ impl Calendar { let available_calendars = available_calendars(); let this_calendar = available_calendars - .get(calendar.identifier.as_slice()) + .get(&calendar.identifier) .expect("builtin must exist"); // 3. Let temporalDate be ? ToTemporalDate(temporalDateLike). @@ -986,7 +978,7 @@ impl Calendar { let available_calendars = available_calendars(); let this_calendar = available_calendars - .get(calendar.identifier.as_slice()) + .get(&calendar.identifier) .expect("builtin must exist"); // 3. Let temporalDate be ? ToTemporalDate(temporalDateLike). @@ -1012,7 +1004,7 @@ impl Calendar { let available_calendars = available_calendars(); let this_calendar = available_calendars - .get(calendar.identifier.as_slice()) + .get(&calendar.identifier) .expect("builtin must exist"); // 3. Let temporalDate be ? ToTemporalDate(temporalDateLike). @@ -1038,7 +1030,7 @@ impl Calendar { let available_calendars = available_calendars(); let this_calendar = available_calendars - .get(calendar.identifier.as_slice()) + .get(&calendar.identifier) .expect("builtin must exist"); // 3. Let temporalDate be ? ToTemporalDate(temporalDateLike). @@ -1064,7 +1056,7 @@ impl Calendar { let available_calendars = available_calendars(); let this_calendar = available_calendars - .get(calendar.identifier.as_slice()) + .get(&calendar.identifier) .expect("builtin must exist"); let date_like = args.get_or_undefined(0); @@ -1114,7 +1106,7 @@ impl Calendar { let available_calendars = available_calendars(); let this_calendar = available_calendars - .get(calendar.identifier.as_slice()) + .get(&calendar.identifier) .expect("builtin must exist"); let date_like = args.get_or_undefined(0); @@ -1164,7 +1156,7 @@ impl Calendar { let available_calendars = available_calendars(); let this_calendar = available_calendars - .get(calendar.identifier.as_slice()) + .get(&calendar.identifier) .expect("builtin must exist"); let date_like = args.get_or_undefined(0); @@ -1214,7 +1206,7 @@ impl Calendar { let available_calendars = available_calendars(); let this_calendar = available_calendars - .get(calendar.identifier.as_slice()) + .get(&calendar.identifier) .expect("builtin must exist"); let date_like = args.get_or_undefined(0); @@ -1262,7 +1254,7 @@ impl Calendar { let available_calendars = available_calendars(); let this_calendar = available_calendars - .get(calendar.identifier.as_slice()) + .get(&calendar.identifier) .expect("builtin must exist"); // 3. Let iteratorRecord be ? GetIterator(fields, sync). @@ -1316,7 +1308,7 @@ impl Calendar { // 7. Let result be fieldNames. // 8. If calendar.[[Identifier]] is not "iso8601", then - if calendar.identifier.as_slice() != ISO { + if &calendar.identifier != ISO { // a. NOTE: Every built-in calendar preserves all input field names in output. // b. Let extraFieldDescriptors be CalendarFieldDescriptors(calendar.[[Identifier]], fieldNames). let extended_fields = this_calendar.field_descriptors(&fields_names); @@ -1356,7 +1348,7 @@ impl Calendar { let available_calendars = available_calendars(); let this_calendar = available_calendars - .get(calendar.identifier.as_slice()) + .get(&calendar.identifier) .expect("builtin must exist"); let fields = args.get_or_undefined(0).to_object(context)?; @@ -1512,7 +1504,7 @@ pub(crate) fn get_temporal_calendar_slot_value_with_default( } // 2. Let calendarLike be ? Get(item, "calendar"). - let calendar_like = item.get(utf16!("calendar"), context)?; + let calendar_like = item.get("calendar", context)?; // 3. Return ? ToTemporalCalendarSlotValue(calendarLike, "iso8601"). to_temporal_calendar_slot_value(&calendar_like, Some(ISO.into())) @@ -1619,7 +1611,7 @@ fn call_method_on_abstract_calendar( _ => unreachable!(), }; - let method = this_calendar.get(method.as_ref(), context)?; + let method = this_calendar.get(method.clone(), context)?; method.call(&this_calendar.into(), args, context) } diff --git a/boa_engine/src/builtins/temporal/duration/mod.rs b/boa_engine/src/builtins/temporal/duration/mod.rs index 5319b96c078..705d43512f5 100644 --- a/boa_engine/src/builtins/temporal/duration/mod.rs +++ b/boa_engine/src/builtins/temporal/duration/mod.rs @@ -7,11 +7,10 @@ use crate::{ BuiltInBuilder, BuiltInConstructor, BuiltInObject, IntrinsicObject, }, context::intrinsics::{Intrinsics, StandardConstructor, StandardConstructors}, - js_string, object::{internal_methods::get_prototype_from_constructor, ObjectData}, property::Attribute, realm::Realm, - string::{common::StaticJsStrings, utf16}, + string::common::StaticJsStrings, Context, JsArgs, JsNativeError, JsObject, JsResult, JsString, JsSymbol, JsValue, }; use boa_profiler::Profiler; @@ -50,51 +49,51 @@ impl IntrinsicObject for Duration { let _timer = Profiler::global().start_event(std::any::type_name::(), "init"); let get_years = BuiltInBuilder::callable(realm, Self::get_years) - .name(js_string!("get Years")) + .name("get Years") .build(); let get_months = BuiltInBuilder::callable(realm, Self::get_months) - .name(js_string!("get Months")) + .name("get Months") .build(); let get_weeks = BuiltInBuilder::callable(realm, Self::get_weeks) - .name(js_string!("get Weeks")) + .name("get Weeks") .build(); let get_days = BuiltInBuilder::callable(realm, Self::get_days) - .name(js_string!("get Days")) + .name("get Days") .build(); let get_hours = BuiltInBuilder::callable(realm, Self::get_hours) - .name(js_string!("get Hours")) + .name("get Hours") .build(); let get_minutes = BuiltInBuilder::callable(realm, Self::get_minutes) - .name(js_string!("get Minutes")) + .name("get Minutes") .build(); let get_seconds = BuiltInBuilder::callable(realm, Self::get_seconds) - .name(js_string!("get Seconds")) + .name("get Seconds") .build(); let get_milliseconds = BuiltInBuilder::callable(realm, Self::get_milliseconds) - .name(js_string!("get Milliseconds")) + .name("get Milliseconds") .build(); let get_microseconds = BuiltInBuilder::callable(realm, Self::get_microseconds) - .name(js_string!("get Microseconds")) + .name("get Microseconds") .build(); let get_nanoseconds = BuiltInBuilder::callable(realm, Self::get_nanoseconds) - .name(js_string!("get Nanoseconds")) + .name("get Nanoseconds") .build(); let get_sign = BuiltInBuilder::callable(realm, Self::get_sign) - .name(js_string!("get Sign")) + .name("get Sign") .build(); let is_blank = BuiltInBuilder::callable(realm, Self::get_blank) - .name(js_string!("get blank")) + .name("get blank") .build(); BuiltInBuilder::from_standard_constructor::(realm) @@ -103,57 +102,42 @@ impl IntrinsicObject for Duration { Self::NAME, Attribute::READONLY | Attribute::NON_ENUMERABLE | Attribute::CONFIGURABLE, ) - .accessor(utf16!("years"), Some(get_years), None, Attribute::default()) + .accessor("years", Some(get_years), None, Attribute::default()) + .accessor("months", Some(get_months), None, Attribute::default()) + .accessor("weeks", Some(get_weeks), None, Attribute::default()) + .accessor("days", Some(get_days), None, Attribute::default()) + .accessor("hours", Some(get_hours), None, Attribute::default()) + .accessor("minutes", Some(get_minutes), None, Attribute::default()) + .accessor("seconds", Some(get_seconds), None, Attribute::default()) .accessor( - utf16!("months"), - Some(get_months), - None, - Attribute::default(), - ) - .accessor(utf16!("weeks"), Some(get_weeks), None, Attribute::default()) - .accessor(utf16!("days"), Some(get_days), None, Attribute::default()) - .accessor(utf16!("hours"), Some(get_hours), None, Attribute::default()) - .accessor( - utf16!("minutes"), - Some(get_minutes), - None, - Attribute::default(), - ) - .accessor( - utf16!("seconds"), - Some(get_seconds), - None, - Attribute::default(), - ) - .accessor( - utf16!("milliseconds"), + "milliseconds", Some(get_milliseconds), None, Attribute::default(), ) .accessor( - utf16!("microseconds"), + "microseconds", Some(get_microseconds), None, Attribute::default(), ) .accessor( - utf16!("nanoseconds"), + "nanoseconds", Some(get_nanoseconds), None, Attribute::default(), ) - .accessor(utf16!("sign"), Some(get_sign), None, Attribute::default()) - .accessor(utf16!("blank"), Some(is_blank), None, Attribute::default()) - .method(Self::with, js_string!("with"), 1) - .method(Self::negated, js_string!("negated"), 0) - .method(Self::abs, js_string!("abs"), 0) - .method(Self::add, js_string!("add"), 2) - .method(Self::subtract, js_string!("subtract"), 2) - .method(Self::round, js_string!("round"), 1) - .method(Self::total, js_string!("total"), 1) - .method(Self::to_string, js_string!("toString"), 1) - .method(Self::to_json, js_string!("toJSON"), 0) + .accessor("sign", Some(get_sign), None, Attribute::default()) + .accessor("blank", Some(is_blank), None, Attribute::default()) + .method(Self::with, "with", 1) + .method(Self::negated, "negated", 0) + .method(Self::abs, "abs", 0) + .method(Self::add, "add", 2) + .method(Self::subtract, "subtract", 2) + .method(Self::round, "round", 1) + .method(Self::total, "total", 1) + .method(Self::to_string, "toString", 1) + .method(Self::to_json, "toJSON", 0) .build(); } @@ -596,7 +580,7 @@ impl Duration { let new_round_to = JsObject::with_null_proto(); // c. Perform ! CreateDataPropertyOrThrow(roundTo, "smallestUnit", paramString). new_round_to.create_data_property_or_throw( - utf16!("smallestUnit"), + "smallestUnit", param_string, context, )?; @@ -619,7 +603,7 @@ impl Duration { // 9. Let largestUnit be ? GetTemporalUnit(roundTo, "largestUnit", datetime, undefined, « "auto" »). let largest_unit = get_temporal_unit( &round_to, - utf16!("largestUnit"), + "largestUnit", TemporalUnitGroup::DateTime, Some([TemporalUnit::Auto].into()), context, @@ -632,13 +616,13 @@ impl Duration { let rounding_increment = get_temporal_rounding_increment(&round_to, context)?; // 12. Let roundingMode be ? ToTemporalRoundingMode(roundTo, "halfExpand"). - let rounding_mode = get_option(&round_to, utf16!("roundingMode"), context)? - .unwrap_or(RoundingMode::HalfExpand); + let rounding_mode = + get_option(&round_to, "roundingMode", context)?.unwrap_or(RoundingMode::HalfExpand); // 13. Let smallestUnit be ? GetTemporalUnit(roundTo, "smallestUnit", datetime, undefined). let smallest_unit = get_temporal_unit( &round_to, - utf16!("smallestUnit"), + "smallestUnit", TemporalUnitGroup::DateTime, None, context, @@ -768,11 +752,7 @@ impl Duration { // b. Set totalOf to OrdinaryObjectCreate(null). let total_of = JsObject::with_null_proto(); // c. Perform ! CreateDataPropertyOrThrow(totalOf, "unit", paramString). - total_of.create_data_property_or_throw( - utf16!("unit"), - param_string.clone(), - context, - )?; + total_of.create_data_property_or_throw("unit", param_string.clone(), context)?; total_of } // 5. Else, @@ -790,7 +770,7 @@ impl Duration { // 8. Let unit be ? GetTemporalUnit(totalOf, "unit", datetime, required). let unit = get_temporal_unit( &total_of, - utf16!("unit"), + "unit", TemporalUnitGroup::DateTime, None, context, diff --git a/boa_engine/src/builtins/temporal/duration/record.rs b/boa_engine/src/builtins/temporal/duration/record.rs index d05f07aecb1..014e55c549d 100644 --- a/boa_engine/src/builtins/temporal/duration/record.rs +++ b/boa_engine/src/builtins/temporal/duration/record.rs @@ -3,9 +3,7 @@ use crate::{ options::RoundingMode, temporal::{self, create_temporal_date, options::TemporalUnit, to_temporal_date}, }, - js_string, - string::utf16, - Context, JsNativeError, JsObject, JsResult, JsValue, + js_string, Context, JsNativeError, JsObject, JsResult, JsValue, }; use super::super::{calendar, to_integer_if_integral, zoned_date_time}; @@ -219,70 +217,70 @@ impl DurationRecord { // 3. NOTE: The following steps read properties and perform independent validation in alphabetical order. // 4. Let days be ? Get(temporalDurationLike, "days"). - let days = unknown_object.get(utf16!("days"), context)?; + let days = unknown_object.get("days", context)?; if !days.is_undefined() { // 5. If days is not undefined, set result.[[Days]] to ? ToIntegerIfIntegral(days). result.set_days(f64::from(to_integer_if_integral(&days, context)?)); } // 6. Let hours be ? Get(temporalDurationLike, "hours"). - let hours = unknown_object.get(utf16!("hours"), context)?; + let hours = unknown_object.get("hours", context)?; // 7. If hours is not undefined, set result.[[Hours]] to ? ToIntegerIfIntegral(hours). if !hours.is_undefined() { result.set_days(f64::from(to_integer_if_integral(&hours, context)?)); } // 8. Let microseconds be ? Get(temporalDurationLike, "microseconds"). - let microseconds = unknown_object.get(utf16!("microseconds"), context)?; + let microseconds = unknown_object.get("microseconds", context)?; // 9. If microseconds is not undefined, set result.[[Microseconds]] to ? ToIntegerIfIntegral(microseconds). if !microseconds.is_undefined() { result.set_days(f64::from(to_integer_if_integral(µseconds, context)?)); } // 10. Let milliseconds be ? Get(temporalDurationLike, "milliseconds"). - let milliseconds = unknown_object.get(utf16!("milliseconds"), context)?; + let milliseconds = unknown_object.get("milliseconds", context)?; // 11. If milliseconds is not undefined, set result.[[Milliseconds]] to ? ToIntegerIfIntegral(milliseconds). if !milliseconds.is_undefined() { result.set_days(f64::from(to_integer_if_integral(&milliseconds, context)?)); } // 12. Let minutes be ? Get(temporalDurationLike, "minutes"). - let minutes = unknown_object.get(utf16!("minutes"), context)?; + let minutes = unknown_object.get("minutes", context)?; // 13. If minutes is not undefined, set result.[[Minutes]] to ? ToIntegerIfIntegral(minutes). if !minutes.is_undefined() { result.set_days(f64::from(to_integer_if_integral(&minutes, context)?)); } // 14. Let months be ? Get(temporalDurationLike, "months"). - let months = unknown_object.get(utf16!("months"), context)?; + let months = unknown_object.get("months", context)?; // 15. If months is not undefined, set result.[[Months]] to ? ToIntegerIfIntegral(months). if !months.is_undefined() { result.set_days(f64::from(to_integer_if_integral(&months, context)?)); } // 16. Let nanoseconds be ? Get(temporalDurationLike, "nanoseconds"). - let nanoseconds = unknown_object.get(utf16!("nanoseconds"), context)?; + let nanoseconds = unknown_object.get("nanoseconds", context)?; // 17. If nanoseconds is not undefined, set result.[[Nanoseconds]] to ? ToIntegerIfIntegral(nanoseconds). if !nanoseconds.is_undefined() { result.set_days(f64::from(to_integer_if_integral(&nanoseconds, context)?)); } // 18. Let seconds be ? Get(temporalDurationLike, "seconds"). - let seconds = unknown_object.get(utf16!("seconds"), context)?; + let seconds = unknown_object.get("seconds", context)?; // 19. If seconds is not undefined, set result.[[Seconds]] to ? ToIntegerIfIntegral(seconds). if !seconds.is_undefined() { result.set_days(f64::from(to_integer_if_integral(&seconds, context)?)); } // 20. Let weeks be ? Get(temporalDurationLike, "weeks"). - let weeks = unknown_object.get(utf16!("weeks"), context)?; + let weeks = unknown_object.get("weeks", context)?; // 21. If weeks is not undefined, set result.[[Weeks]] to ? ToIntegerIfIntegral(weeks). if !weeks.is_undefined() { result.set_days(f64::from(to_integer_if_integral(&weeks, context)?)); } // 22. Let years be ? Get(temporalDurationLike, "years"). - let years = unknown_object.get(utf16!("years"), context)?; + let years = unknown_object.get("years", context)?; // 23. If years is not undefined, set result.[[Years]] to ? ToIntegerIfIntegral(years). if !years.is_undefined() { result.set_days(f64::from(to_integer_if_integral(&years, context)?)); @@ -1363,7 +1361,7 @@ impl DurationRecord { let until_options = JsObject::with_null_proto(); // m. Perform ! CreateDataPropertyOrThrow(untilOptions, "largestUnit", "year"). until_options.create_data_property_or_throw( - utf16!("largestUnit"), + "largestUnit", js_string!("year"), context, )?; diff --git a/boa_engine/src/builtins/temporal/fields.rs b/boa_engine/src/builtins/temporal/fields.rs index 39c60911ab4..15771ab35de 100644 --- a/boa_engine/src/builtins/temporal/fields.rs +++ b/boa_engine/src/builtins/temporal/fields.rs @@ -398,21 +398,21 @@ impl TemporalFields { match bit { FieldMap::YEAR => { obj.create_data_property_or_throw( - js_string!("year"), + "year", self.year.map_or(JsValue::undefined(), JsValue::from), context, )?; } FieldMap::MONTH => { obj.create_data_property_or_throw( - js_string!("month"), + "month", self.month.map_or(JsValue::undefined(), JsValue::from), context, )?; } FieldMap::MONTH_CODE => { obj.create_data_property_or_throw( - js_string!("monthCode"), + "monthCode", self.month_code .as_ref() .map_or(JsValue::undefined(), |f| f.clone().into()), @@ -421,44 +421,32 @@ impl TemporalFields { } FieldMap::DAY => { obj.create_data_property( - js_string!("day"), + "day", self.day().map_or(JsValue::undefined(), JsValue::from), context, )?; } FieldMap::HOUR => { - obj.create_data_property(js_string!("hour"), self.hour, context)?; + obj.create_data_property("hour", self.hour, context)?; } FieldMap::MINUTE => { - obj.create_data_property(js_string!("minute"), self.minute, context)?; + obj.create_data_property("minute", self.minute, context)?; } FieldMap::SECOND => { - obj.create_data_property_or_throw(js_string!("second"), self.second, context)?; + obj.create_data_property_or_throw("second", self.second, context)?; } FieldMap::MILLISECOND => { - obj.create_data_property_or_throw( - js_string!("millisecond"), - self.millisecond, - context, - )?; + obj.create_data_property_or_throw("millisecond", self.millisecond, context)?; } FieldMap::MICROSECOND => { - obj.create_data_property_or_throw( - js_string!("microsecond"), - self.microsecond, - context, - )?; + obj.create_data_property_or_throw("microsecond", self.microsecond, context)?; } FieldMap::NANOSECOND => { - obj.create_data_property_or_throw( - js_string!("nanosecond"), - self.nanosecond, - context, - )?; + obj.create_data_property_or_throw("nanosecond", self.nanosecond, context)?; } FieldMap::OFFSET => { obj.create_data_property_or_throw( - js_string!("offset"), + "offset", self.offset .as_ref() .map_or(JsValue::undefined(), |s| s.clone().into()), @@ -467,7 +455,7 @@ impl TemporalFields { } FieldMap::ERA => { obj.create_data_property_or_throw( - js_string!("era"), + "era", self.era .as_ref() .map_or(JsValue::undefined(), |s| s.clone().into()), @@ -476,14 +464,14 @@ impl TemporalFields { } FieldMap::ERA_YEAR => { obj.create_data_property_or_throw( - js_string!("eraYear"), + "eraYear", self.era_year.map_or(JsValue::undefined(), JsValue::from), context, )?; } FieldMap::TIME_ZONE => { obj.create_data_property_or_throw( - js_string!("timeZone"), + "timeZone", self.time_zone .as_ref() .map_or(JsValue::undefined(), |s| s.clone().into()), diff --git a/boa_engine/src/builtins/temporal/instant/mod.rs b/boa_engine/src/builtins/temporal/instant/mod.rs index 00a1b01a376..9de2eaf285b 100644 --- a/boa_engine/src/builtins/temporal/instant/mod.rs +++ b/boa_engine/src/builtins/temporal/instant/mod.rs @@ -13,11 +13,10 @@ use crate::{ BuiltInBuilder, BuiltInConstructor, BuiltInObject, IntrinsicObject, }, context::intrinsics::{Intrinsics, StandardConstructor, StandardConstructors}, - js_string, object::{internal_methods::get_prototype_from_constructor, ObjectData}, property::Attribute, realm::Realm, - string::{common::StaticJsStrings, utf16}, + string::common::StaticJsStrings, Context, JsArgs, JsBigInt, JsNativeError, JsObject, JsResult, JsString, JsSymbol, JsValue, }; use boa_profiler::Profiler; @@ -43,19 +42,19 @@ impl IntrinsicObject for Instant { let _timer = Profiler::global().start_event(std::any::type_name::(), "init"); let get_seconds = BuiltInBuilder::callable(realm, Self::get_epoc_seconds) - .name(js_string!("get epochSeconds")) + .name("get epochSeconds") .build(); let get_millis = BuiltInBuilder::callable(realm, Self::get_epoc_milliseconds) - .name(js_string!("get epochMilliseconds")) + .name("get epochMilliseconds") .build(); let get_micros = BuiltInBuilder::callable(realm, Self::get_epoc_microseconds) - .name(js_string!("get epochMicroseconds")) + .name("get epochMicroseconds") .build(); let get_nanos = BuiltInBuilder::callable(realm, Self::get_epoc_nanoseconds) - .name(js_string!("get epochNanoseconds")) + .name("get epochNanoseconds") .build(); BuiltInBuilder::from_standard_constructor::(realm) @@ -65,41 +64,37 @@ impl IntrinsicObject for Instant { Attribute::CONFIGURABLE, ) .accessor( - utf16!("epochSeconds"), + "epochSeconds", Some(get_seconds), None, Attribute::default(), ) .accessor( - utf16!("epochMilliseconds"), + "epochMilliseconds", Some(get_millis), None, Attribute::default(), ) .accessor( - utf16!("epochMicroseconds"), + "epochMicroseconds", Some(get_micros), None, Attribute::default(), ) .accessor( - utf16!("epochNanoseconds"), + "epochNanoseconds", Some(get_nanos), None, Attribute::default(), ) - .method(Self::add, js_string!("add"), 1) - .method(Self::subtract, js_string!("subtract"), 1) - .method(Self::until, js_string!("until"), 2) - .method(Self::since, js_string!("since"), 2) - .method(Self::round, js_string!("round"), 1) - .method(Self::equals, js_string!("equals"), 1) - .method(Self::to_zoned_date_time, js_string!("toZonedDateTime"), 1) - .method( - Self::to_zoned_date_time_iso, - js_string!("toZonedDateTimeISO"), - 1, - ) + .method(Self::add, "add", 1) + .method(Self::subtract, "subtract", 1) + .method(Self::until, "until", 2) + .method(Self::since, "since", 2) + .method(Self::round, "round", 1) + .method(Self::equals, "equals", 1) + .method(Self::to_zoned_date_time, "toZonedDateTime", 1) + .method(Self::to_zoned_date_time_iso, "toZonedDateTimeISO", 1) .build(); } @@ -348,7 +343,7 @@ impl Instant { let new_round_to = JsObject::with_null_proto(); // c. Perform ! CreateDataPropertyOrThrow(roundTo, "smallestUnit"), paramString). new_round_to.create_data_property_or_throw( - utf16!("smallestUnit"), + "smallestUnit", param_string.clone(), context, )?; @@ -365,13 +360,12 @@ impl Instant { let rounding_increment = get_temporal_rounding_increment(&round_to, context)?; // 8. Let roundingMode be ? ToTemporalRoundingMode(roundTo, "halfExpand"). - let rounding_mode = - get_option(&round_to, utf16!("roundingMode"), context)?.unwrap_or_default(); + let rounding_mode = get_option(&round_to, "roundingMode", context)?.unwrap_or_default(); // 9. Let smallestUnit be ? GetTemporalUnit(roundTo, "smallestUnit"), time, required). let smallest_unit = get_temporal_unit( &round_to, - utf16!("smallestUnit"), + "smallestUnit", TemporalUnitGroup::Time, None, context, diff --git a/boa_engine/src/builtins/temporal/mod.rs b/boa_engine/src/builtins/temporal/mod.rs index 133b35cb7c9..4d25d5d6fb9 100644 --- a/boa_engine/src/builtins/temporal/mod.rs +++ b/boa_engine/src/builtins/temporal/mod.rs @@ -39,10 +39,9 @@ use crate::{ BuiltInBuilder, BuiltInObject, IntrinsicObject, }, context::intrinsics::Intrinsics, - js_string, property::Attribute, realm::Realm, - string::{common::StaticJsStrings, utf16}, + string::common::StaticJsStrings, value::Type, Context, JsBigInt, JsNativeError, JsObject, JsResult, JsString, JsSymbol, JsValue, }; @@ -101,32 +100,32 @@ impl IntrinsicObject for Temporal { Attribute::READONLY | Attribute::NON_ENUMERABLE | Attribute::CONFIGURABLE, ) .static_property( - js_string!("Now"), + "Now", realm.intrinsics().objects().now(), Attribute::READONLY | Attribute::NON_ENUMERABLE | Attribute::CONFIGURABLE, ) .static_property( - js_string!("Calendar"), + "Calendar", realm.intrinsics().constructors().calendar().constructor(), Attribute::READONLY | Attribute::NON_ENUMERABLE | Attribute::CONFIGURABLE, ) .static_property( - js_string!("Duration"), + "Duration", realm.intrinsics().constructors().duration().constructor(), Attribute::READONLY | Attribute::NON_ENUMERABLE | Attribute::CONFIGURABLE, ) .static_property( - js_string!("Instant"), + "Instant", realm.intrinsics().constructors().instant().constructor(), Attribute::READONLY | Attribute::NON_ENUMERABLE | Attribute::CONFIGURABLE, ) .static_property( - js_string!("PlainDate"), + "PlainDate", realm.intrinsics().constructors().plain_date().constructor(), Attribute::READONLY | Attribute::NON_ENUMERABLE | Attribute::CONFIGURABLE, ) .static_property( - js_string!("PlainDateTime"), + "PlainDateTime", realm .intrinsics() .constructors() @@ -135,7 +134,7 @@ impl IntrinsicObject for Temporal { Attribute::READONLY | Attribute::NON_ENUMERABLE | Attribute::CONFIGURABLE, ) .static_property( - js_string!("PlainMonthDay"), + "PlainMonthDay", realm .intrinsics() .constructors() @@ -144,12 +143,12 @@ impl IntrinsicObject for Temporal { Attribute::READONLY | Attribute::NON_ENUMERABLE | Attribute::CONFIGURABLE, ) .static_property( - js_string!("PlainTime"), + "PlainTime", realm.intrinsics().constructors().plain_time().constructor(), Attribute::READONLY | Attribute::NON_ENUMERABLE | Attribute::CONFIGURABLE, ) .static_property( - js_string!("PlainYearMonth"), + "PlainYearMonth", realm .intrinsics() .constructors() @@ -158,12 +157,12 @@ impl IntrinsicObject for Temporal { Attribute::READONLY | Attribute::NON_ENUMERABLE | Attribute::CONFIGURABLE, ) .static_property( - js_string!("TimeZone"), + "TimeZone", realm.intrinsics().constructors().time_zone().constructor(), Attribute::READONLY | Attribute::NON_ENUMERABLE | Attribute::CONFIGURABLE, ) .static_property( - js_string!("ZonedDateTime"), + "ZonedDateTime", realm .intrinsics() .constructors() @@ -499,9 +498,8 @@ pub(crate) fn get_diff_settings( ) -> JsResult<(TemporalUnit, TemporalUnit, RoundingMode, f64)> { // 1. NOTE: The following steps read options and perform independent validation in alphabetical order (ToTemporalRoundingIncrement reads "roundingIncrement" and ToTemporalRoundingMode reads "roundingMode"). // 2. Let largestUnit be ? GetTemporalUnit(options, "largestUnit", unitGroup, "auto"). - let mut largest_unit = - get_temporal_unit(options, utf16!("largestUnit"), unit_group, None, context)? - .unwrap_or(TemporalUnit::Auto); + let mut largest_unit = get_temporal_unit(options, "largestUnit", unit_group, None, context)? + .unwrap_or(TemporalUnit::Auto); // 3. If disallowedUnits contains largestUnit, throw a RangeError exception. if disallowed_units.contains(&largest_unit) { @@ -515,7 +513,7 @@ pub(crate) fn get_diff_settings( // 5. Let roundingMode be ? ToTemporalRoundingMode(options, "trunc"). let mut rounding_mode = - get_option(options, utf16!("roundingMode"), context)?.unwrap_or(RoundingMode::Trunc); + get_option(options, "roundingMode", context)?.unwrap_or(RoundingMode::Trunc); // 6. If operation is since, then if !op { @@ -524,9 +522,8 @@ pub(crate) fn get_diff_settings( } // 7. Let smallestUnit be ? GetTemporalUnit(options, "smallestUnit", unitGroup, fallbackSmallestUnit). - let smallest_unit = - get_temporal_unit(options, utf16!("smallestUnit"), unit_group, None, context)? - .unwrap_or(fallback_smallest_unit); + let smallest_unit = get_temporal_unit(options, "smallestUnit", unit_group, None, context)? + .unwrap_or(fallback_smallest_unit); // 8. If disallowedUnits contains smallestUnit, throw a RangeError exception. if disallowed_units.contains(&smallest_unit) { diff --git a/boa_engine/src/builtins/temporal/now.rs b/boa_engine/src/builtins/temporal/now.rs index a67023a8d5f..409283bbd75 100644 --- a/boa_engine/src/builtins/temporal/now.rs +++ b/boa_engine/src/builtins/temporal/now.rs @@ -6,7 +6,6 @@ use crate::{ BuiltInBuilder, BuiltInObject, IntrinsicObject, }, context::intrinsics::Intrinsics, - js_string, property::Attribute, realm::Realm, string::common::StaticJsStrings, @@ -37,14 +36,14 @@ impl IntrinsicObject for Now { Self::NAME, Attribute::READONLY | Attribute::NON_ENUMERABLE | Attribute::CONFIGURABLE, ) - .static_method(Self::time_zone_id, js_string!("timeZoneId"), 0) - .static_method(Self::instant, js_string!("instant"), 0) - .static_method(Self::plain_date_time, js_string!("plainDateTime"), 2) - .static_method(Self::plain_date_time_iso, js_string!("plainDateTimeISO"), 1) - .static_method(Self::zoned_date_time, js_string!("zonedDateTime"), 2) - .static_method(Self::zoned_date_time_iso, js_string!("zonedDateTimeISO"), 1) - .static_method(Self::plain_date, js_string!("plainDate"), 2) - .static_method(Self::plain_date_iso, js_string!("plainDateISO"), 1) + .static_method(Self::time_zone_id, "timeZoneId", 0) + .static_method(Self::instant, "instant", 0) + .static_method(Self::plain_date_time, "plainDateTime", 2) + .static_method(Self::plain_date_time_iso, "plainDateTimeISO", 1) + .static_method(Self::zoned_date_time, "zonedDateTime", 2) + .static_method(Self::zoned_date_time_iso, "zonedDateTimeISO", 1) + .static_method(Self::plain_date, "plainDate", 2) + .static_method(Self::plain_date_iso, "plainDateISO", 1) .build(); } diff --git a/boa_engine/src/builtins/temporal/options.rs b/boa_engine/src/builtins/temporal/options.rs index 17b88ce94e4..20208c88c14 100644 --- a/boa_engine/src/builtins/temporal/options.rs +++ b/boa_engine/src/builtins/temporal/options.rs @@ -10,7 +10,7 @@ use crate::{ builtins::options::{get_option, ParsableOptionType}, - js_string, Context, JsNativeError, JsObject, JsResult, + Context, JsNativeError, JsObject, JsResult, }; use std::{fmt, str::FromStr}; @@ -22,7 +22,7 @@ pub(crate) fn get_temporal_rounding_increment( context: &mut Context<'_>, ) -> JsResult { // 1. Let increment be ? GetOption(normalizedOptions, "roundingIncrement", "number", undefined, 1𝔽). - let value = options.get(js_string!("roundingIncrement"), context)?; + let value = options.get("roundingIncrement", context)?; let increment = if value.is_undefined() { 1.0 @@ -55,7 +55,7 @@ pub(crate) fn get_temporal_rounding_increment( #[inline] pub(crate) fn get_temporal_unit( options: &JsObject, - key: &[u16], + key: &str, unit_group: TemporalUnitGroup, extra_values: Option>, context: &mut Context<'_>, diff --git a/boa_engine/src/builtins/temporal/plain_date/mod.rs b/boa_engine/src/builtins/temporal/plain_date/mod.rs index 5fe1de68473..5eedde3d01b 100644 --- a/boa_engine/src/builtins/temporal/plain_date/mod.rs +++ b/boa_engine/src/builtins/temporal/plain_date/mod.rs @@ -11,7 +11,7 @@ use crate::{ object::{internal_methods::get_prototype_from_constructor, ObjectData}, property::Attribute, realm::Realm, - string::{common::StaticJsStrings, utf16}, + string::common::StaticJsStrings, Context, JsArgs, JsNativeError, JsObject, JsResult, JsString, JsSymbol, JsValue, }; use boa_parser::temporal::{IsoCursor, TemporalDateTimeString}; @@ -37,59 +37,59 @@ impl IntrinsicObject for PlainDate { let _timer = Profiler::global().start_event(std::any::type_name::(), "init"); let get_calendar_id = BuiltInBuilder::callable(realm, Self::get_calendar_id) - .name(js_string!("get calendarId")) + .name("get calendarId") .build(); let get_year = BuiltInBuilder::callable(realm, Self::get_year) - .name(js_string!("get year")) + .name("get year") .build(); let get_month = BuiltInBuilder::callable(realm, Self::get_month) - .name(js_string!("get month")) + .name("get month") .build(); let get_month_code = BuiltInBuilder::callable(realm, Self::get_month_code) - .name(js_string!("get monthCode")) + .name("get monthCode") .build(); let get_day = BuiltInBuilder::callable(realm, Self::get_day) - .name(js_string!("get day")) + .name("get day") .build(); let get_day_of_week = BuiltInBuilder::callable(realm, Self::get_day_of_week) - .name(js_string!("get dayOfWeek")) + .name("get dayOfWeek") .build(); let get_day_of_year = BuiltInBuilder::callable(realm, Self::get_day_of_year) - .name(js_string!("get dayOfYear")) + .name("get dayOfYear") .build(); let get_week_of_year = BuiltInBuilder::callable(realm, Self::get_week_of_year) - .name(js_string!("get weekOfYear")) + .name("get weekOfYear") .build(); let get_year_of_week = BuiltInBuilder::callable(realm, Self::get_year_of_week) - .name(js_string!("get yearOfWeek")) + .name("get yearOfWeek") .build(); let get_days_in_week = BuiltInBuilder::callable(realm, Self::get_days_in_week) - .name(js_string!("get daysInWeek")) + .name("get daysInWeek") .build(); let get_days_in_month = BuiltInBuilder::callable(realm, Self::get_days_in_month) - .name(js_string!("get daysInMonth")) + .name("get daysInMonth") .build(); let get_days_in_year = BuiltInBuilder::callable(realm, Self::get_days_in_year) - .name(js_string!("get daysInYear")) + .name("get daysInYear") .build(); let get_months_in_year = BuiltInBuilder::callable(realm, Self::get_months_in_year) - .name(js_string!("get monthsInYear")) + .name("get monthsInYear") .build(); let get_in_leap_year = BuiltInBuilder::callable(realm, Self::get_in_leap_year) - .name(js_string!("get inLeapYear")) + .name("get inLeapYear") .build(); BuiltInBuilder::from_standard_constructor::(realm) @@ -99,85 +99,85 @@ impl IntrinsicObject for PlainDate { Attribute::CONFIGURABLE, ) .accessor( - utf16!("calendarId"), + "calendarId", Some(get_calendar_id), None, Attribute::default(), ) - .accessor(utf16!("year"), Some(get_year), None, Attribute::default()) - .accessor(utf16!("month"), Some(get_month), None, Attribute::default()) + .accessor("year", Some(get_year), None, Attribute::default()) + .accessor("month", Some(get_month), None, Attribute::default()) .accessor( - utf16!("monthCode"), + "monthCode", Some(get_month_code), None, Attribute::default(), ) - .accessor(utf16!("day"), Some(get_day), None, Attribute::default()) + .accessor("day", Some(get_day), None, Attribute::default()) .accessor( - utf16!("dayOfWeek"), + "dayOfWeek", Some(get_day_of_week), None, Attribute::default(), ) .accessor( - utf16!("dayOfYear"), + "dayOfYear", Some(get_day_of_year), None, Attribute::default(), ) .accessor( - utf16!("weekOfYear"), + "weekOfYear", Some(get_week_of_year), None, Attribute::default(), ) .accessor( - utf16!("yearOfWeek"), + "yearOfWeek", Some(get_year_of_week), None, Attribute::default(), ) .accessor( - utf16!("daysInWeek"), + "daysInWeek", Some(get_days_in_week), None, Attribute::default(), ) .accessor( - utf16!("daysInMonth"), + "daysInMonth", Some(get_days_in_month), None, Attribute::default(), ) .accessor( - utf16!("daysInYear"), + "daysInYear", Some(get_days_in_year), None, Attribute::default(), ) .accessor( - utf16!("monthsInYear"), + "monthsInYear", Some(get_months_in_year), None, Attribute::default(), ) .accessor( - utf16!("inLeapYear"), + "inLeapYear", Some(get_in_leap_year), None, Attribute::default(), ) - .method(Self::to_plain_year_month, js_string!("toPlainYearMonth"), 0) - .method(Self::to_plain_month_day, js_string!("toPlainMonthDay"), 0) - .method(Self::get_iso_fields, js_string!("getISOFields"), 0) - .method(Self::get_calendar, js_string!("getCalendar"), 0) - .method(Self::add, js_string!("add"), 2) - .method(Self::subtract, js_string!("subtract"), 2) - .method(Self::with, js_string!("with"), 2) - .method(Self::with_calendar, js_string!("withCalendar"), 1) - .method(Self::until, js_string!("until"), 2) - .method(Self::since, js_string!("since"), 2) - .method(Self::equals, js_string!("equals"), 1) + .method(Self::to_plain_year_month, "toPlainYearMonth", 0) + .method(Self::to_plain_month_day, "toPlainMonthDay", 0) + .method(Self::get_iso_fields, "getISOFields", 0) + .method(Self::get_calendar, "getCalendar", 0) + .method(Self::add, "add", 2) + .method(Self::subtract, "subtract", 2) + .method(Self::with, "with", 2) + .method(Self::with_calendar, "withCalendar", 1) + .method(Self::until, "until", 2) + .method(Self::since, "since", 2) + .method(Self::equals, "equals", 1) .build(); } @@ -478,7 +478,7 @@ pub(crate) fn to_temporal_date( // c. If item has an [[InitializedTemporalDateTime]] internal slot, then } else if object.is_plain_date_time() { // i. Perform ? ToTemporalOverflow(options). - let _o = get_option(&options_obj, utf16!("overflow"), context)? + let _o = get_option(&options_obj, "overflow", context)? .unwrap_or(ArithmeticOverflow::Constrain); let obj = object.borrow(); @@ -536,7 +536,7 @@ pub(crate) fn to_temporal_date( // 11. Set calendar to the ASCII-lowercase of calendar. // 12. Perform ? ToTemporalOverflow(options). - let _result = get_option(&options_obj, utf16!("overflow"), context)? + let _result = get_option(&options_obj, "overflow", context)? .unwrap_or(ArithmeticOverflow::Constrain); // 13. Return ? CreateTemporalDate(result.[[Year]], result.[[Month]], result.[[Day]], calendar). diff --git a/boa_engine/src/builtins/temporal/plain_year_month/mod.rs b/boa_engine/src/builtins/temporal/plain_year_month/mod.rs index d5c6ead7bdf..4cc772c6338 100644 --- a/boa_engine/src/builtins/temporal/plain_year_month/mod.rs +++ b/boa_engine/src/builtins/temporal/plain_year_month/mod.rs @@ -7,7 +7,7 @@ use crate::{ object::{internal_methods::get_prototype_from_constructor, ObjectData}, property::Attribute, realm::Realm, - string::{common::StaticJsStrings, utf16}, + string::common::StaticJsStrings, Context, JsArgs, JsNativeError, JsObject, JsResult, JsString, JsSymbol, JsValue, }; use boa_profiler::Profiler; @@ -30,35 +30,35 @@ impl IntrinsicObject for PlainYearMonth { let _timer = Profiler::global().start_event(std::any::type_name::(), "init"); let get_calendar_id = BuiltInBuilder::callable(realm, Self::get_calendar_id) - .name(js_string!("get calendarId")) + .name("get calendarId") .build(); let get_year = BuiltInBuilder::callable(realm, Self::get_year) - .name(js_string!("get year")) + .name("get year") .build(); let get_month = BuiltInBuilder::callable(realm, Self::get_month) - .name(js_string!("get month")) + .name("get month") .build(); let get_month_code = BuiltInBuilder::callable(realm, Self::get_month_code) - .name(js_string!("get monthCode")) + .name("get monthCode") .build(); let get_days_in_month = BuiltInBuilder::callable(realm, Self::get_days_in_month) - .name(js_string!("get daysInMonth")) + .name("get daysInMonth") .build(); let get_days_in_year = BuiltInBuilder::callable(realm, Self::get_days_in_year) - .name(js_string!("get daysInYear")) + .name("get daysInYear") .build(); let get_months_in_year = BuiltInBuilder::callable(realm, Self::get_months_in_year) - .name(js_string!("get monthsInYear")) + .name("get monthsInYear") .build(); let get_in_leap_year = BuiltInBuilder::callable(realm, Self::get_in_leap_year) - .name(js_string!("get inLeapYear")) + .name("get inLeapYear") .build(); BuiltInBuilder::from_standard_constructor::(realm) @@ -68,49 +68,49 @@ impl IntrinsicObject for PlainYearMonth { Attribute::CONFIGURABLE, ) .accessor( - utf16!("calendarId"), + "calendarId", Some(get_calendar_id), None, Attribute::default(), ) - .accessor(utf16!("year"), Some(get_year), None, Attribute::default()) - .accessor(utf16!("month"), Some(get_month), None, Attribute::default()) + .accessor("year", Some(get_year), None, Attribute::default()) + .accessor("month", Some(get_month), None, Attribute::default()) .accessor( - utf16!("monthCode"), + "monthCode", Some(get_month_code), None, Attribute::default(), ) .accessor( - utf16!("daysInMonth"), + "daysInMonth", Some(get_days_in_month), None, Attribute::default(), ) .accessor( - utf16!("daysInYear"), + "daysInYear", Some(get_days_in_year), None, Attribute::default(), ) .accessor( - utf16!("monthsInYear"), + "monthsInYear", Some(get_months_in_year), None, Attribute::default(), ) .accessor( - utf16!("inLeapYear"), + "inLeapYear", Some(get_in_leap_year), None, Attribute::default(), ) - .method(Self::with, js_string!("with"), 2) - .method(Self::add, js_string!("add"), 2) - .method(Self::subtract, js_string!("subtract"), 2) - .method(Self::until, js_string!("until"), 2) - .method(Self::since, js_string!("since"), 2) - .method(Self::equals, js_string!("equals"), 1) + .method(Self::with, "with", 2) + .method(Self::add, "add", 2) + .method(Self::subtract, "subtract", 2) + .method(Self::until, "until", 2) + .method(Self::since, "since", 2) + .method(Self::equals, "equals", 1) .build(); } diff --git a/boa_engine/src/builtins/temporal/time_zone/mod.rs b/boa_engine/src/builtins/temporal/time_zone/mod.rs index 1f053ade575..2f9ed860538 100644 --- a/boa_engine/src/builtins/temporal/time_zone/mod.rs +++ b/boa_engine/src/builtins/temporal/time_zone/mod.rs @@ -6,11 +6,10 @@ use crate::{ IntrinsicObject, }, context::intrinsics::{Intrinsics, StandardConstructor, StandardConstructors}, - js_string, object::{internal_methods::get_prototype_from_constructor, ObjectData, CONSTRUCTOR}, property::Attribute, realm::Realm, - string::{common::StaticJsStrings, utf16}, + string::common::StaticJsStrings, Context, JsArgs, JsNativeError, JsObject, JsResult, JsString, JsSymbol, JsValue, }; use boa_profiler::Profiler; @@ -32,43 +31,23 @@ impl IntrinsicObject for TimeZone { let _timer = Profiler::global().start_event(std::any::type_name::(), "init"); let get_id = BuiltInBuilder::callable(realm, Self::get_id) - .name(js_string!("get Id")) + .name("get Id") .build(); BuiltInBuilder::from_standard_constructor::(realm) .method( Self::get_offset_nanoseconds_for, - js_string!("getOffsetNanosecondsFor"), + "getOffsetNanosecondsFor", 1, ) - .method( - Self::get_offset_string_for, - js_string!("getOffsetStringFor"), - 1, - ) - .method( - Self::get_plain_date_time_for, - js_string!("getPlainDateTimeFor"), - 2, - ) - .method(Self::get_instant_for, js_string!("getInstantFor"), 2) - .method( - Self::get_possible_instants_for, - js_string!("getPossibleInstantFor"), - 1, - ) - .method( - Self::get_next_transition, - js_string!("getNextTransition"), - 1, - ) - .method( - Self::get_previous_transition, - js_string!("getPreviousTransition"), - 1, - ) - .method(Self::to_string, js_string!("toString"), 0) - .method(Self::to_string, js_string!("toJSON"), 0) + .method(Self::get_offset_string_for, "getOffsetStringFor", 1) + .method(Self::get_plain_date_time_for, "getPlainDateTimeFor", 2) + .method(Self::get_instant_for, "getInstantFor", 2) + .method(Self::get_possible_instants_for, "getPossibleInstantFor", 1) + .method(Self::get_next_transition, "getNextTransition", 1) + .method(Self::get_previous_transition, "getPreviousTransition", 1) + .method(Self::to_string, "toString", 0) + .method(Self::to_string, "toJSON", 0) .static_property( JsSymbol::to_string_tag(), Self::NAME, @@ -79,7 +58,7 @@ impl IntrinsicObject for TimeZone { realm.intrinsics().constructors().time_zone().prototype(), Attribute::default(), ) - .accessor(utf16!("id"), Some(get_id), None, Attribute::default()) + .accessor("id", Some(get_id), None, Attribute::default()) .build(); } diff --git a/boa_engine/src/builtins/typed_array/builtin.rs b/boa_engine/src/builtins/typed_array/builtin.rs index eaa05703b87..4cf9a476938 100644 --- a/boa_engine/src/builtins/typed_array/builtin.rs +++ b/boa_engine/src/builtins/typed_array/builtin.rs @@ -37,31 +37,31 @@ pub(crate) struct BuiltinTypedArray; impl IntrinsicObject for BuiltinTypedArray { fn init(realm: &Realm) { let get_species = BuiltInBuilder::callable(realm, Self::get_species) - .name(js_string!("get [Symbol.species]")) + .name("get [Symbol.species]") .build(); let get_buffer = BuiltInBuilder::callable(realm, Self::buffer) - .name(js_string!("get buffer")) + .name("get buffer") .build(); let get_byte_length = BuiltInBuilder::callable(realm, Self::byte_length) - .name(js_string!("get byteLength")) + .name("get byteLength") .build(); let get_byte_offset = BuiltInBuilder::callable(realm, Self::byte_offset) - .name(js_string!("get byteOffset")) + .name("get byteOffset") .build(); let get_length = BuiltInBuilder::callable(realm, Self::length) - .name(js_string!("get length")) + .name("get length") .build(); let get_to_string_tag = BuiltInBuilder::callable(realm, Self::to_string_tag) - .name(js_string!("get [Symbol.toStringTag]")) + .name("get [Symbol.toStringTag]") .build(); let values_function = BuiltInBuilder::callable(realm, Self::values) - .name(js_string!("values")) + .name("values") .length(0) .build(); @@ -78,25 +78,25 @@ impl IntrinsicObject for BuiltinTypedArray { Attribute::WRITABLE | Attribute::NON_ENUMERABLE | Attribute::CONFIGURABLE, ) .accessor( - utf16!("buffer"), + "buffer", Some(get_buffer), None, Attribute::CONFIGURABLE | Attribute::NON_ENUMERABLE, ) .accessor( - utf16!("byteLength"), + "byteLength", Some(get_byte_length), None, Attribute::CONFIGURABLE | Attribute::NON_ENUMERABLE, ) .accessor( - utf16!("byteOffset"), + "byteOffset", Some(get_byte_offset), None, Attribute::CONFIGURABLE | Attribute::NON_ENUMERABLE, ) .accessor( - utf16!("length"), + "length", Some(get_length), None, Attribute::CONFIGURABLE | Attribute::NON_ENUMERABLE, @@ -107,44 +107,44 @@ impl IntrinsicObject for BuiltinTypedArray { None, Attribute::CONFIGURABLE | Attribute::NON_ENUMERABLE, ) - .static_method(Self::from, js_string!("from"), 1) - .static_method(Self::of, js_string!("of"), 0) - .method(Self::at, js_string!("at"), 1) - .method(Self::copy_within, js_string!("copyWithin"), 2) - .method(Self::entries, js_string!("entries"), 0) - .method(Self::every, js_string!("every"), 1) - .method(Self::fill, js_string!("fill"), 1) - .method(Self::filter, js_string!("filter"), 1) - .method(Self::find, js_string!("find"), 1) - .method(Self::find_index, js_string!("findIndex"), 1) - .method(Self::find_last, js_string!("findLast"), 1) - .method(Self::find_last_index, js_string!("findLastIndex"), 1) - .method(Self::foreach, js_string!("forEach"), 1) - .method(Self::includes, js_string!("includes"), 1) - .method(Self::index_of, js_string!("indexOf"), 1) - .method(Self::join, js_string!("join"), 1) - .method(Self::keys, js_string!("keys"), 0) - .method(Self::last_index_of, js_string!("lastIndexOf"), 1) - .method(Self::map, js_string!("map"), 1) - .method(Self::reduce, js_string!("reduce"), 1) - .method(Self::reduceright, js_string!("reduceRight"), 1) - .method(Self::reverse, js_string!("reverse"), 0) - .method(Self::set, js_string!("set"), 1) - .method(Self::slice, js_string!("slice"), 2) - .method(Self::some, js_string!("some"), 1) - .method(Self::sort, js_string!("sort"), 1) - .method(Self::subarray, js_string!("subarray"), 2) - .method(Self::to_locale_string, js_string!("toLocaleString"), 0) + .static_method(Self::from, "from", 1) + .static_method(Self::of, "of", 0) + .method(Self::at, "at", 1) + .method(Self::copy_within, "copyWithin", 2) + .method(Self::entries, "entries", 0) + .method(Self::every, "every", 1) + .method(Self::fill, "fill", 1) + .method(Self::filter, "filter", 1) + .method(Self::find, "find", 1) + .method(Self::find_index, "findIndex", 1) + .method(Self::find_last, "findLast", 1) + .method(Self::find_last_index, "findLastIndex", 1) + .method(Self::foreach, "forEach", 1) + .method(Self::includes, "includes", 1) + .method(Self::index_of, "indexOf", 1) + .method(Self::join, "join", 1) + .method(Self::keys, "keys", 0) + .method(Self::last_index_of, "lastIndexOf", 1) + .method(Self::map, "map", 1) + .method(Self::reduce, "reduce", 1) + .method(Self::reduceright, "reduceRight", 1) + .method(Self::reverse, "reverse", 0) + .method(Self::set, "set", 1) + .method(Self::slice, "slice", 2) + .method(Self::some, "some", 1) + .method(Self::sort, "sort", 1) + .method(Self::subarray, "subarray", 2) + .method(Self::to_locale_string, "toLocaleString", 0) // 23.2.3.29 %TypedArray%.prototype.toString ( ) // The initial value of the %TypedArray%.prototype.toString data property is the same // built-in function object as the Array.prototype.toString method defined in 23.1.3.30. .property( - js_string!("toString"), + "toString", realm.intrinsics().objects().array_prototype_to_string(), Attribute::WRITABLE | Attribute::NON_ENUMERABLE | Attribute::CONFIGURABLE, ) .property( - js_string!("values"), + "values", values_function, Attribute::WRITABLE | Attribute::NON_ENUMERABLE | Attribute::CONFIGURABLE, ) @@ -2718,7 +2718,7 @@ impl BuiltinTypedArray { // a. If k > 0, then if k > 0 { // i. Set R to the string-concatenation of R and separator. - r.extend_from_slice(separator); + r.extend(separator.iter()); } // b. Let nextElement be ? Get(array, ! ToString(k)). @@ -2729,7 +2729,7 @@ impl BuiltinTypedArray { // i. Let S be ? ToString(? Invoke(nextElement, "toLocaleString", « locales, options »)). let s = next_element .invoke( - utf16!("toLocaleString"), + "toLocaleString", &[ args.get_or_undefined(0).clone(), args.get_or_undefined(1).clone(), @@ -2739,14 +2739,14 @@ impl BuiltinTypedArray { .to_string(context)?; // ii. Set R to the string-concatenation of R and S. - r.extend_from_slice(&s); + r.extend(s.iter()); } // d. Increase k by 1. } // 7. Return R. - Ok(js_string!(r).into()) + Ok(js_string!(&r[..]).into()) } /// `23.2.3.31 %TypedArray%.prototype.values ( )` diff --git a/boa_engine/src/builtins/typed_array/mod.rs b/boa_engine/src/builtins/typed_array/mod.rs index 3d0af35c551..c88c60a37f4 100644 --- a/boa_engine/src/builtins/typed_array/mod.rs +++ b/boa_engine/src/builtins/typed_array/mod.rs @@ -19,7 +19,6 @@ use crate::{ }, context::intrinsics::{Intrinsics, StandardConstructor, StandardConstructors}, error::JsNativeError, - js_string, object::{internal_methods::get_prototype_from_constructor, JsObject}, property::Attribute, realm::Realm, @@ -52,7 +51,7 @@ impl IntrinsicObject for T { let _timer = Profiler::global().start_event(std::any::type_name::(), "init"); let get_species = BuiltInBuilder::callable(realm, BuiltinTypedArray::get_species) - .name(js_string!("get [Symbol.species]")) + .name("get [Symbol.species]") .build(); BuiltInBuilder::from_standard_constructor::(realm) @@ -73,12 +72,12 @@ impl IntrinsicObject for T { Attribute::CONFIGURABLE, ) .property( - js_string!("BYTES_PER_ELEMENT"), + "BYTES_PER_ELEMENT", std::mem::size_of::(), Attribute::READONLY | Attribute::NON_ENUMERABLE | Attribute::PERMANENT, ) .static_property( - js_string!("BYTES_PER_ELEMENT"), + "BYTES_PER_ELEMENT", std::mem::size_of::(), Attribute::READONLY | Attribute::NON_ENUMERABLE | Attribute::PERMANENT, ) diff --git a/boa_engine/src/builtins/uri/mod.rs b/boa_engine/src/builtins/uri/mod.rs index dfb26d91d9e..27f09ec8ccf 100644 --- a/boa_engine/src/builtins/uri/mod.rs +++ b/boa_engine/src/builtins/uri/mod.rs @@ -305,11 +305,11 @@ where loop { // a. If k = strLen, return R. if k == str_len { - return Ok(js_string!(r)); + return Ok(js_string!(&r[..])); } // b. Let C be the code unit at index k within string. - let c = string[k]; + let c = string.to_vec()[k]; // c. If C is in unescapedSet, then if unescaped_set(c) { @@ -380,11 +380,11 @@ where loop { // a. If k = strLen, return R. if k == str_len { - return Ok(js_string!(r)); + return Ok(js_string!(&r[..])); } // b. Let C be the code unit at index k within string. - let c = string[k]; + let c = string.to_vec()[k]; // c. If C is not the code unit 0x0025 (PERCENT SIGN), then #[allow(clippy::if_not_else)] @@ -406,9 +406,9 @@ where // iii. If the code units at index (k + 1) and (k + 2) within string do not represent // hexadecimal digits, throw a URIError exception. // iv. Let B be the 8-bit value represented by the two hexadecimal digits at index (k + 1) and (k + 2). - let b = decode_hex_byte(string[k + 1], string[k + 2]).ok_or_else(|| { - JsNativeError::uri().with_message("invalid hexadecimal digit found") - })?; + let b = decode_hex_byte(string.to_vec()[k + 1], string.to_vec()[k + 2]).ok_or_else( + || JsNativeError::uri().with_message("invalid hexadecimal digit found"), + )?; // v. Set k to k + 2. k += 2; @@ -428,7 +428,7 @@ where } else { // 3. Else, // a. Let S be the substring of string from start to k + 1. - Vec::from(&string[start..=k]) + Vec::from(&string.to_vec()[start..=k]) } } else { // viii. Else, @@ -456,7 +456,7 @@ where k += 1; // b. If the code unit at index k within string is not the code unit 0x0025 (PERCENT SIGN), throw a URIError exception. - if string[k] != 0x0025 { + if string.to_vec()[k] != 0x0025 { return Err(JsNativeError::uri() .with_message("escape characters must be preceded with a % sign") .into()); @@ -464,9 +464,10 @@ where // c. If the code units at index (k + 1) and (k + 2) within string do not represent hexadecimal digits, throw a URIError exception. // d. Let B be the 8-bit value represented by the two hexadecimal digits at index (k + 1) and (k + 2). - let b = decode_hex_byte(string[k + 1], string[k + 2]).ok_or_else(|| { - JsNativeError::uri().with_message("invalid hexadecimal digit found") - })?; + let b = decode_hex_byte(string.to_vec()[k + 1], string.to_vec()[k + 2]) + .ok_or_else(|| { + JsNativeError::uri().with_message("invalid hexadecimal digit found") + })?; // e. Set k to k + 2. k += 2; diff --git a/boa_engine/src/builtins/weak/weak_ref.rs b/boa_engine/src/builtins/weak/weak_ref.rs index c6f54f4caba..f8f61a589bf 100644 --- a/boa_engine/src/builtins/weak/weak_ref.rs +++ b/boa_engine/src/builtins/weak/weak_ref.rs @@ -39,7 +39,7 @@ impl IntrinsicObject for WeakRef { js_string!("WeakRef"), Attribute::CONFIGURABLE, ) - .method(Self::deref, js_string!("deref"), 0) + .method(Self::deref, "deref", 0) .build(); } } diff --git a/boa_engine/src/builtins/weak_map/mod.rs b/boa_engine/src/builtins/weak_map/mod.rs index 19ec7dc7c22..7bb9f83d9ab 100644 --- a/boa_engine/src/builtins/weak_map/mod.rs +++ b/boa_engine/src/builtins/weak_map/mod.rs @@ -13,11 +13,10 @@ use crate::{ IntrinsicObject, }, context::intrinsics::{Intrinsics, StandardConstructor, StandardConstructors}, - js_string, object::{internal_methods::get_prototype_from_constructor, JsObject, ObjectData}, property::Attribute, realm::Realm, - string::{common::StaticJsStrings, utf16}, + string::common::StaticJsStrings, symbol::JsSymbol, Context, JsArgs, JsNativeError, JsResult, JsString, JsValue, }; @@ -40,10 +39,10 @@ impl IntrinsicObject for WeakMap { Self::NAME, Attribute::READONLY | Attribute::NON_ENUMERABLE | Attribute::CONFIGURABLE, ) - .method(Self::delete, js_string!("delete"), 1) - .method(Self::get, js_string!("get"), 1) - .method(Self::has, js_string!("has"), 1) - .method(Self::set, js_string!("set"), 2) + .method(Self::delete, "delete", 1) + .method(Self::get, "get", 1) + .method(Self::has, "has", 1) + .method(Self::set, "set", 2) .build(); } } @@ -98,7 +97,7 @@ impl BuiltInConstructor for WeakMap { } // 5. Let adder be ? Get(map, "set"). - let adder = map.get(utf16!("set"), context)?; + let adder = map.get("set", context)?; // 6. If IsCallable(adder) is false, throw a TypeError exception. if !adder.is_callable() { diff --git a/boa_engine/src/builtins/weak_set/mod.rs b/boa_engine/src/builtins/weak_set/mod.rs index 65a74221cd6..d0729fe6cc5 100644 --- a/boa_engine/src/builtins/weak_set/mod.rs +++ b/boa_engine/src/builtins/weak_set/mod.rs @@ -10,11 +10,10 @@ use crate::{ builtins::{BuiltInBuilder, BuiltInConstructor, BuiltInObject, IntrinsicObject}, context::intrinsics::{Intrinsics, StandardConstructor, StandardConstructors}, - js_string, object::{internal_methods::get_prototype_from_constructor, JsObject, ObjectData}, property::Attribute, realm::Realm, - string::{common::StaticJsStrings, utf16}, + string::common::StaticJsStrings, symbol::JsSymbol, Context, JsArgs, JsNativeError, JsResult, JsString, JsValue, }; @@ -37,9 +36,9 @@ impl IntrinsicObject for WeakSet { Self::NAME, Attribute::READONLY | Attribute::NON_ENUMERABLE | Attribute::CONFIGURABLE, ) - .method(Self::add, js_string!("add"), 1) - .method(Self::delete, js_string!("delete"), 1) - .method(Self::has, js_string!("has"), 1) + .method(Self::add, "add", 1) + .method(Self::delete, "delete", 1) + .method(Self::has, "has", 1) .build(); } } @@ -94,7 +93,7 @@ impl BuiltInConstructor for WeakSet { } // 5. Let adder be ? Get(set, "add"). - let adder = weak_set.get(utf16!("add"), context)?; + let adder = weak_set.get("add", context)?; // 6. If IsCallable(adder) is false, throw a TypeError exception. let adder = adder diff --git a/boa_engine/src/bytecompiler/declarations.rs b/boa_engine/src/bytecompiler/declarations.rs index 5e403923b00..3b7dbfc5013 100644 --- a/boa_engine/src/bytecompiler/declarations.rs +++ b/boa_engine/src/bytecompiler/declarations.rs @@ -462,7 +462,7 @@ impl ByteCompiler<'_, '_> { .map(|ident| { self.context .interner() - .get(ident.as_slice()) + .get(ident.as_slice().as_str_ref()) .expect("string should be in interner") }) .collect(); diff --git a/boa_engine/src/class.rs b/boa_engine/src/class.rs index e44e8e934ea..995dda52f4e 100644 --- a/boa_engine/src/class.rs +++ b/boa_engine/src/class.rs @@ -44,7 +44,7 @@ //! /// This is where the object is initialized. //! fn init(class: &mut ClassBuilder) -> JsResult<()> { //! class.method( -//! js_string!("speak"), +//! "speak", //! 0, //! NativeFunction::from_fn_ptr(|this, _args, _ctx| { //! if let Some(object) = this.as_object() { diff --git a/boa_engine/src/context/intrinsics.rs b/boa_engine/src/context/intrinsics.rs index 18cb4bb2596..16a274d6613 100644 --- a/boa_engine/src/context/intrinsics.rs +++ b/boa_engine/src/context/intrinsics.rs @@ -1350,7 +1350,7 @@ impl ObjectTemplates { let ordinary_object = ObjectTemplate::with_prototype(root_shape, constructors.object().prototype()); let mut array = ObjectTemplate::new(root_shape); - let length_property_key: PropertyKey = js_string!("length").into(); + let length_property_key: PropertyKey = "length".into(); array.property( length_property_key.clone(), Attribute::WRITABLE | Attribute::PERMANENT | Attribute::NON_ENUMERABLE, @@ -1369,7 +1369,7 @@ impl ObjectTemplates { ); string.set_prototype(constructors.string().prototype()); - let name_property_key: PropertyKey = js_string!("name").into(); + let name_property_key: PropertyKey = "name".into(); let mut function = ObjectTemplate::new(root_shape); function.property( length_property_key.clone(), @@ -1424,7 +1424,7 @@ impl ObjectTemplates { // [[Get]]: %ThrowTypeError%, [[Set]]: %ThrowTypeError%, [[Enumerable]]: false, // [[Configurable]]: false }). unmapped_arguments.accessor( - js_string!("callee").into(), + "callee".into(), true, true, Attribute::NON_ENUMERABLE | Attribute::PERMANENT, @@ -1433,17 +1433,17 @@ impl ObjectTemplates { // 21. Perform ! DefinePropertyOrThrow(obj, "callee", PropertyDescriptor { // [[Value]]: func, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true }). mapped_arguments.property( - js_string!("callee").into(), + "callee".into(), Attribute::WRITABLE | Attribute::NON_ENUMERABLE | Attribute::CONFIGURABLE, ); let mut iterator_result = ordinary_object.clone(); iterator_result.property( - js_string!("value").into(), + "value".into(), Attribute::WRITABLE | Attribute::CONFIGURABLE | Attribute::ENUMERABLE, ); iterator_result.property( - js_string!("done").into(), + "done".into(), Attribute::WRITABLE | Attribute::CONFIGURABLE | Attribute::ENUMERABLE, ); @@ -1456,11 +1456,11 @@ impl ObjectTemplates { with_resolvers // 4. Perform ! CreateDataPropertyOrThrow(obj, "promise", promiseCapability.[[Promise]]). - .property(js_string!("promise").into(), Attribute::all()) + .property("promise".into(), Attribute::all()) // 5. Perform ! CreateDataPropertyOrThrow(obj, "resolve", promiseCapability.[[Resolve]]). - .property(js_string!("resolve").into(), Attribute::all()) + .property("resolve".into(), Attribute::all()) // 6. Perform ! CreateDataPropertyOrThrow(obj, "reject", promiseCapability.[[Reject]]). - .property(js_string!("reject").into(), Attribute::all()); + .property("reject".into(), Attribute::all()); with_resolvers }; diff --git a/boa_engine/src/context/mod.rs b/boa_engine/src/context/mod.rs index 32dd3008f71..cc0a1f346cb 100644 --- a/boa_engine/src/context/mod.rs +++ b/boa_engine/src/context/mod.rs @@ -73,9 +73,9 @@ use self::intrinsics::StandardConstructor; /// /// // Create an object that can be used in eval calls. /// let arg = ObjectInitializer::new(&mut context) -/// .property(js_string!("x"), 12, Attribute::READONLY) +/// .property("x", 12, Attribute::READONLY) /// .build(); -/// context.register_global_property(js_string!("arg"), arg, Attribute::all()); +/// context.register_global_property("arg", arg, Attribute::all()); /// /// let value = context.eval(Source::from_bytes("test(arg)")).unwrap(); /// @@ -210,19 +210,19 @@ impl<'host> Context<'host> { /// /// context /// .register_global_property( - /// js_string!("myPrimitiveProperty"), + /// "myPrimitiveProperty", /// 10, /// Attribute::all(), /// ) /// .expect("property shouldn't exist"); /// /// let object = ObjectInitializer::new(&mut context) - /// .property(js_string!("x"), 0, Attribute::all()) - /// .property(js_string!("y"), 1, Attribute::all()) + /// .property("x", 0, Attribute::all()) + /// .property("y", 1, Attribute::all()) /// .build(); /// context /// .register_global_property( - /// js_string!("myObjectProperty"), + /// "myObjectProperty", /// object, /// Attribute::all(), /// ) diff --git a/boa_engine/src/error.rs b/boa_engine/src/error.rs index 839f404c687..06860006416 100644 --- a/boa_engine/src/error.rs +++ b/boa_engine/src/error.rs @@ -7,7 +7,6 @@ use crate::{ object::ObjectData, property::PropertyDescriptor, realm::Realm, - string::utf16, Context, JsString, JsValue, }; use boa_gc::{Finalize, Trace}; @@ -30,10 +29,10 @@ use thiserror::Error; /// /// ```rust /// # use boa_engine::{JsError, JsNativeError, JsNativeErrorKind, JsValue, js_string}; -/// let cause = JsError::from_opaque(js_string!("error!").into()); +/// let cause = JsError::from_opaque("error!".into()); /// /// assert!(cause.as_opaque().is_some()); -/// assert_eq!(cause.as_opaque().unwrap(), &JsValue::from(js_string!("error!"))); +/// assert_eq!(cause.as_opaque().unwrap(), &JsValue::from("error!")); /// /// let native_error: JsError = JsNativeError::typ() /// .with_message("invalid type!") @@ -267,7 +266,7 @@ impl JsError { ErrorKind::Syntax => JsNativeErrorKind::Syntax, ErrorKind::Uri => JsNativeErrorKind::Uri, ErrorKind::Aggregate => { - let errors = obj.get(utf16!("errors"), context).map_err(|e| { + let errors = obj.get("errors", context).map_err(|e| { TryNativeError::InaccessibleProperty { property: "errors", source: e, @@ -780,8 +779,8 @@ impl JsNativeError { /// /// assert!(error_obj.borrow().is_error()); /// assert_eq!( - /// error_obj.get(js_string!("message"), context).unwrap(), - /// js_string!("error!").into() + /// error_obj.get("message", context).unwrap(), + /// "error!".into() /// ) /// ``` /// @@ -834,15 +833,11 @@ impl JsNativeError { ObjectData::error(tag), ); - o.create_non_enumerable_data_property_or_throw( - js_string!("message"), - js_string!(&**message), - context, - ); + o.create_non_enumerable_data_property_or_throw("message", js_string!(&**message), context); if let Some(cause) = cause { o.create_non_enumerable_data_property_or_throw( - js_string!("cause"), + "cause", cause.to_opaque(context), context, ); @@ -855,7 +850,7 @@ impl JsNativeError { .collect::>(); let errors = Array::create_array_from_list(errors, context); o.define_property_or_throw( - js_string!("errors"), + "errors", PropertyDescriptor::builder() .configurable(true) .enumerable(false) diff --git a/boa_engine/src/module/mod.rs b/boa_engine/src/module/mod.rs index a2941118e41..ce8b5f3c401 100644 --- a/boa_engine/src/module/mod.rs +++ b/boa_engine/src/module/mod.rs @@ -182,7 +182,11 @@ impl Module { ) -> Self { let names: FxHashSet = export_names .iter() - .map(|string| context.interner_mut().get_or_intern(&**string)) + .map(|string| { + context + .interner_mut() + .get_or_intern(string.as_slice().as_str_ref()) + }) .collect(); let realm = realm.unwrap_or_else(|| context.realm().clone()); let inner = Gc::new_cyclic(|weak| { diff --git a/boa_engine/src/module/synthetic.rs b/boa_engine/src/module/synthetic.rs index 80716e7c5d9..ee777702783 100644 --- a/boa_engine/src/module/synthetic.rs +++ b/boa_engine/src/module/synthetic.rs @@ -360,7 +360,9 @@ impl SyntheticModule { export_value: JsValue, context: &mut Context<'_>, ) -> JsResult<()> { - let identifier = context.interner_mut().get_or_intern(&**export_name); + let identifier = context + .interner_mut() + .get_or_intern(export_name.as_slice().as_str_ref()); let identifier = Identifier::new(identifier); let environment = self diff --git a/boa_engine/src/object/builtins/jsmap.rs b/boa_engine/src/object/builtins/jsmap.rs index 074602b7ab7..4e48ac3d57b 100644 --- a/boa_engine/src/object/builtins/jsmap.rs +++ b/boa_engine/src/object/builtins/jsmap.rs @@ -4,7 +4,6 @@ use crate::{ builtins::Map, error::JsNativeError, object::{JsFunction, JsMapIterator, JsObject, JsObjectType, ObjectData}, - string::utf16, value::TryFromJs, Context, JsResult, JsValue, }; @@ -129,7 +128,7 @@ impl JsMap { // Let adder be Get(map, "set") per spec. This action should not fail with default map. let adder = map - .get(utf16!("set"), context) + .get("set", context) .expect("creating a map with the default prototype must not fail"); let _completion_record = add_entries_from_iterable(&map, iterable, &adder, context)?; diff --git a/boa_engine/src/object/builtins/jsproxy.rs b/boa_engine/src/object/builtins/jsproxy.rs index b3d005c2544..b93b9f36801 100644 --- a/boa_engine/src/object/builtins/jsproxy.rs +++ b/boa_engine/src/object/builtins/jsproxy.rs @@ -5,7 +5,6 @@ use crate::{ builtins::Proxy, native_function::{NativeFunction, NativeFunctionPointer}, object::{FunctionObjectBuilder, JsObject, JsObjectType, ObjectData}, - string::utf16, value::TryFromJs, Context, JsNativeError, JsResult, JsValue, }; @@ -405,7 +404,7 @@ impl JsProxyBuilder { .length(3) .build(); handler - .create_data_property_or_throw(utf16!("apply"), f, context) + .create_data_property_or_throw("apply", f, context) .expect("new object should be writable"); } if let Some(construct) = self.construct { @@ -414,7 +413,7 @@ impl JsProxyBuilder { .length(3) .build(); handler - .create_data_property_or_throw(utf16!("construct"), f, context) + .create_data_property_or_throw("construct", f, context) .expect("new object should be writable"); } if let Some(define_property) = self.define_property { @@ -425,7 +424,7 @@ impl JsProxyBuilder { .length(3) .build(); handler - .create_data_property_or_throw(utf16!("defineProperty"), f, context) + .create_data_property_or_throw("defineProperty", f, context) .expect("new object should be writable"); } if let Some(delete_property) = self.delete_property { @@ -436,7 +435,7 @@ impl JsProxyBuilder { .length(2) .build(); handler - .create_data_property_or_throw(utf16!("deleteProperty"), f, context) + .create_data_property_or_throw("deleteProperty", f, context) .expect("new object should be writable"); } if let Some(get) = self.get { @@ -444,7 +443,7 @@ impl JsProxyBuilder { .length(3) .build(); handler - .create_data_property_or_throw(utf16!("get"), f, context) + .create_data_property_or_throw("get", f, context) .expect("new object should be writable"); } if let Some(get_own_property_descriptor) = self.get_own_property_descriptor { @@ -455,7 +454,7 @@ impl JsProxyBuilder { .length(2) .build(); handler - .create_data_property_or_throw(utf16!("getOwnPropertyDescriptor"), f, context) + .create_data_property_or_throw("getOwnPropertyDescriptor", f, context) .expect("new object should be writable"); } if let Some(get_prototype_of) = self.get_prototype_of { @@ -466,7 +465,7 @@ impl JsProxyBuilder { .length(1) .build(); handler - .create_data_property_or_throw(utf16!("getPrototypeOf"), f, context) + .create_data_property_or_throw("getPrototypeOf", f, context) .expect("new object should be writable"); } if let Some(has) = self.has { @@ -474,7 +473,7 @@ impl JsProxyBuilder { .length(2) .build(); handler - .create_data_property_or_throw(utf16!("has"), f, context) + .create_data_property_or_throw("has", f, context) .expect("new object should be writable"); } if let Some(is_extensible) = self.is_extensible { @@ -485,7 +484,7 @@ impl JsProxyBuilder { .length(1) .build(); handler - .create_data_property_or_throw(utf16!("isExtensible"), f, context) + .create_data_property_or_throw("isExtensible", f, context) .expect("new object should be writable"); } if let Some(own_keys) = self.own_keys { @@ -494,7 +493,7 @@ impl JsProxyBuilder { .length(1) .build(); handler - .create_data_property_or_throw(utf16!("ownKeys"), f, context) + .create_data_property_or_throw("ownKeys", f, context) .expect("new object should be writable"); } if let Some(prevent_extensions) = self.prevent_extensions { @@ -505,7 +504,7 @@ impl JsProxyBuilder { .length(1) .build(); handler - .create_data_property_or_throw(utf16!("preventExtensions"), f, context) + .create_data_property_or_throw("preventExtensions", f, context) .expect("new object should be writable"); } if let Some(set) = self.set { @@ -513,7 +512,7 @@ impl JsProxyBuilder { .length(4) .build(); handler - .create_data_property_or_throw(utf16!("set"), f, context) + .create_data_property_or_throw("set", f, context) .expect("new object should be writable"); } if let Some(set_prototype_of) = self.set_prototype_of { @@ -524,7 +523,7 @@ impl JsProxyBuilder { .length(2) .build(); handler - .create_data_property_or_throw(utf16!("setPrototypeOf"), f, context) + .create_data_property_or_throw("setPrototypeOf", f, context) .expect("new object should be writable"); } diff --git a/boa_engine/src/object/internal_methods/array.rs b/boa_engine/src/object/internal_methods/array.rs index 0d95759acf8..8204b9fc6c3 100644 --- a/boa_engine/src/object/internal_methods/array.rs +++ b/boa_engine/src/object/internal_methods/array.rs @@ -2,7 +2,6 @@ use crate::{ error::JsNativeError, object::JsObject, property::{PropertyDescriptor, PropertyKey}, - string::utf16, Context, JsResult, }; @@ -34,7 +33,7 @@ pub(crate) fn array_exotic_define_own_property( // 1. Assert: IsPropertyKey(P) is true. match key { // 2. If P is "length", then - PropertyKey::String(ref s) if s == utf16!("length") => { + PropertyKey::String(ref s) if s == "length" => { // a. Return ? ArraySetLength(A, Desc). array_set_length(obj, desc, context) @@ -44,9 +43,8 @@ pub(crate) fn array_exotic_define_own_property( let index = index.get(); // a. Let oldLenDesc be OrdinaryGetOwnProperty(A, "length"). - let old_len_desc = - super::ordinary_get_own_property(obj, &utf16!("length").into(), context)? - .expect("the property descriptor must exist"); + let old_len_desc = super::ordinary_get_own_property(obj, &"length".into(), context)? + .expect("the property descriptor must exist"); // b. Assert: ! IsDataDescriptor(oldLenDesc) is true. debug_assert!(old_len_desc.is_data_descriptor()); @@ -81,7 +79,7 @@ pub(crate) fn array_exotic_define_own_property( // ii. Set succeeded to OrdinaryDefineOwnProperty(A, "length", oldLenDesc). let succeeded = super::ordinary_define_own_property( obj, - &utf16!("length").into(), + &"length".into(), old_len_desc.into(), context, )?; @@ -116,7 +114,7 @@ fn array_set_length( // 1. If Desc.[[Value]] is absent, then let Some(new_len_val) = desc.value() else { // a. Return OrdinaryDefineOwnProperty(A, "length", Desc). - return super::ordinary_define_own_property(obj, &utf16!("length").into(), desc, context); + return super::ordinary_define_own_property(obj, &"length".into(), desc, context); }; // 3. Let newLen be ? ToUint32(Desc.[[Value]]). @@ -142,7 +140,7 @@ fn array_set_length( .maybe_configurable(desc.configurable()); // 7. Let oldLenDesc be OrdinaryGetOwnProperty(A, "length"). - let old_len_desc = super::ordinary_get_own_property(obj, &utf16!("length").into(), context)? + let old_len_desc = super::ordinary_get_own_property(obj, &"length".into(), context)? .expect("the property descriptor must exist"); // 8. Assert: ! IsDataDescriptor(oldLenDesc) is true. @@ -159,7 +157,7 @@ fn array_set_length( // a. Return OrdinaryDefineOwnProperty(A, "length", newLenDesc). return super::ordinary_define_own_property( obj, - &utf16!("length").into(), + &"length".into(), new_len_desc.build(), context, ); @@ -189,7 +187,7 @@ fn array_set_length( // 16. If succeeded is false, return false. if !super::ordinary_define_own_property( obj, - &utf16!("length").into(), + &"length".into(), new_len_desc.clone().build(), context, ) @@ -226,7 +224,7 @@ fn array_set_length( // iii. Perform ! OrdinaryDefineOwnProperty(A, "length", newLenDesc). super::ordinary_define_own_property( obj, - &utf16!("length").into(), + &"length".into(), new_len_desc.build(), context, ) @@ -243,7 +241,7 @@ fn array_set_length( // PropertyDescriptor { [[Writable]]: false }). let succeeded = super::ordinary_define_own_property( obj, - &utf16!("length").into(), + &"length".into(), PropertyDescriptor::builder().writable(false).build(), context, ) diff --git a/boa_engine/src/object/internal_methods/integer_indexed.rs b/boa_engine/src/object/internal_methods/integer_indexed.rs index 3a9f95fa622..33f20a0b5da 100644 --- a/boa_engine/src/object/internal_methods/integer_indexed.rs +++ b/boa_engine/src/object/internal_methods/integer_indexed.rs @@ -1,7 +1,5 @@ use std::sync::atomic; -use boa_macros::utf16; - use crate::{ builtins::Number, object::JsObject, @@ -37,7 +35,7 @@ pub(crate) static INTEGER_INDEXED_EXOTIC_INTERNAL_METHODS: InternalObjectMethods /// [spec]: https://tc39.es/ecma262/#sec-canonicalnumericindexstring fn canonical_numeric_index_string(argument: &JsString) -> Option { // 1. If argument is "-0", return -0𝔽. - if argument == utf16!("-0") { + if argument == "-0" { return Some(-0.0); } diff --git a/boa_engine/src/object/internal_methods/proxy.rs b/boa_engine/src/object/internal_methods/proxy.rs index 4ebe9554dce..f573a5e4d26 100644 --- a/boa_engine/src/object/internal_methods/proxy.rs +++ b/boa_engine/src/object/internal_methods/proxy.rs @@ -3,7 +3,6 @@ use crate::{ error::JsNativeError, object::{InternalObjectMethods, JsObject, JsPrototype}, property::{PropertyDescriptor, PropertyKey}, - string::utf16, value::Type, Context, JsResult, JsValue, }; @@ -67,7 +66,7 @@ pub(crate) fn proxy_exotic_get_prototype_of( .try_data()?; // 5. Let trap be ? GetMethod(handler, "getPrototypeOf"). - let Some(trap) = handler.get_method(utf16!("getPrototypeOf"), context)? else { + let Some(trap) = handler.get_method("getPrototypeOf", context)? else { // 6. If trap is undefined, then // a. Return ? target.[[GetPrototypeOf]](). return target.__get_prototype_of__(context); @@ -129,7 +128,7 @@ pub(crate) fn proxy_exotic_set_prototype_of( .try_data()?; // 5. Let trap be ? GetMethod(handler, "setPrototypeOf"). - let Some(trap) = handler.get_method(utf16!("setPrototypeOf"), context)? else { + let Some(trap) = handler.get_method("setPrototypeOf", context)? else { // 6. If trap is undefined, then // a. Return ? target.[[SetPrototypeOf]](V). return target.__set_prototype_of__(val, context); @@ -192,7 +191,7 @@ pub(crate) fn proxy_exotic_is_extensible( .try_data()?; // 5. Let trap be ? GetMethod(handler, "isExtensible"). - let Some(trap) = handler.get_method(utf16!("isExtensible"), context)? else { + let Some(trap) = handler.get_method("isExtensible", context)? else { // 6. If trap is undefined, then // a. Return ? IsExtensible(target). return target.is_extensible(context); @@ -238,7 +237,7 @@ pub(crate) fn proxy_exotic_prevent_extensions( .try_data()?; // 5. Let trap be ? GetMethod(handler, "preventExtensions"). - let Some(trap) = handler.get_method(utf16!("preventExtensions"), context)? else { + let Some(trap) = handler.get_method("preventExtensions", context)? else { // 6. If trap is undefined, then // a. Return ? target.[[PreventExtensions]](). return target.__prevent_extensions__(context); @@ -284,7 +283,7 @@ pub(crate) fn proxy_exotic_get_own_property( .try_data()?; // 5. Let trap be ? GetMethod(handler, "getOwnPropertyDescriptor"). - let Some(trap) = handler.get_method(utf16!("getOwnPropertyDescriptor"), context)? else { + let Some(trap) = handler.get_method("getOwnPropertyDescriptor", context)? else { // 6. If trap is undefined, then // a. Return ? target.[[GetOwnProperty]](P). return target.__get_own_property__(key, context); @@ -408,7 +407,7 @@ pub(crate) fn proxy_exotic_define_own_property( .try_data()?; // 5. Let trap be ? GetMethod(handler, "defineProperty"). - let Some(trap) = handler.get_method(utf16!("defineProperty"), context)? else { + let Some(trap) = handler.get_method("defineProperty", context)? else { // 6. If trap is undefined, then // a. Return ? target.[[DefineOwnProperty]](P, Desc). return target.__define_own_property__(key, desc, context); @@ -519,7 +518,7 @@ pub(crate) fn proxy_exotic_has_property( .try_data()?; // 5. Let trap be ? GetMethod(handler, "has"). - let Some(trap) = handler.get_method(utf16!("has"), context)? else { + let Some(trap) = handler.get_method("has", context)? else { // 6. If trap is undefined, then // a. Return ? target.[[HasProperty]](P). return target.has_property(key.clone(), context); @@ -585,7 +584,7 @@ pub(crate) fn proxy_exotic_get( .try_data()?; // 5. Let trap be ? GetMethod(handler, "get"). - let Some(trap) = handler.get_method(utf16!("get"), context)? else { + let Some(trap) = handler.get_method("get", context)? else { // 6. If trap is undefined, then // a. Return ? target.[[Get]](P, Receiver). return target.__get__(key, receiver, context); @@ -654,7 +653,7 @@ pub(crate) fn proxy_exotic_set( .try_data()?; // 5. Let trap be ? GetMethod(handler, "set"). - let Some(trap) = handler.get_method(utf16!("set"), context)? else { + let Some(trap) = handler.get_method("set", context)? else { // 6. If trap is undefined, then // a. Return ? target.[[Set]](P, V, Receiver). return target.__set__(key, value, receiver, context); @@ -735,7 +734,7 @@ pub(crate) fn proxy_exotic_delete( .try_data()?; // 5. Let trap be ? GetMethod(handler, "deleteProperty"). - let Some(trap) = handler.get_method(utf16!("deleteProperty"), context)? else { + let Some(trap) = handler.get_method("deleteProperty", context)? else { // 6. If trap is undefined, then // a. Return ? target.[[Delete]](P). return target.__delete__(key, context); @@ -801,7 +800,7 @@ pub(crate) fn proxy_exotic_own_property_keys( .try_data()?; // 5. Let trap be ? GetMethod(handler, "ownKeys"). - let Some(trap) = handler.get_method(utf16!("ownKeys"), context)? else { + let Some(trap) = handler.get_method("ownKeys", context)? else { // 6. If trap is undefined, then // a. Return ? target.[[OwnPropertyKeys]](). return target.__own_property_keys__(context); @@ -937,7 +936,7 @@ fn proxy_exotic_call( .try_data()?; // 5. Let trap be ? GetMethod(handler, "apply"). - let Some(trap) = handler.get_method(utf16!("apply"), context)? else { + let Some(trap) = handler.get_method("apply", context)? else { // 6. If trap is undefined, then // a. Return ? Call(target, thisArgument, argumentsList). return target.call(this, args, context); @@ -980,7 +979,7 @@ fn proxy_exotic_construct( assert!(target.is_constructor()); // 6. Let trap be ? GetMethod(handler, "construct"). - let Some(trap) = handler.get_method(utf16!("construct"), context)? else { + let Some(trap) = handler.get_method("construct", context)? else { // 7. If trap is undefined, then // a. Return ? Construct(target, argumentsList, newTarget). return target.construct(args, Some(new_target), context); diff --git a/boa_engine/src/object/internal_methods/string.rs b/boa_engine/src/object/internal_methods/string.rs index aacb579603b..3b8ce0bf31a 100644 --- a/boa_engine/src/object/internal_methods/string.rs +++ b/boa_engine/src/object/internal_methods/string.rs @@ -157,7 +157,7 @@ fn string_get_own_property(obj: &JsObject, key: &PropertyKey) -> Option for FunctionBinding { + #[inline] + fn from(name: &str) -> Self { + Self::from(JsString::from(name)) + } +} + impl From for FunctionBinding { #[inline] fn from(name: JsString) -> Self { @@ -3042,8 +3048,8 @@ impl<'ctx, 'host> ConstructorBuilder<'ctx, 'host> { let constructor = { let mut constructor = self.constructor_object; - constructor.insert(utf16!("length"), length); - constructor.insert(utf16!("name"), name); + constructor.insert("length", length); + constructor.insert("name", name); let data = ObjectData::native_function( self.function, self.kind.is_some(), diff --git a/boa_engine/src/object/operations.rs b/boa_engine/src/object/operations.rs index 9dc56276590..30f441ca9b3 100644 --- a/boa_engine/src/object/operations.rs +++ b/boa_engine/src/object/operations.rs @@ -5,7 +5,6 @@ use crate::{ object::{JsObject, PrivateElement, PrivateName, CONSTRUCTOR, PROTOTYPE}, property::{PropertyDescriptor, PropertyDescriptorBuilder, PropertyKey, PropertyNameKind}, realm::Realm, - string::utf16, value::Type, Context, JsResult, JsSymbol, JsValue, }; @@ -492,7 +491,7 @@ impl JsObject { } // 2. Return ℝ(? ToLength(? Get(obj, "length"))). - self.get(utf16!("length"), context)?.to_length(context) + self.get("length", context)?.to_length(context) } /// `7.3.22 SpeciesConstructor ( O, defaultConstructor )` diff --git a/boa_engine/src/object/property_map.rs b/boa_engine/src/object/property_map.rs index 8320fe1d88a..98e75c6b5e5 100644 --- a/boa_engine/src/object/property_map.rs +++ b/boa_engine/src/object/property_map.rs @@ -356,6 +356,7 @@ impl PropertyMap { self.shape = self.shape.insert_property_transition(transition_key); // Make Sure that if we are inserting, it has the correct slot index. + // dbg!(key); debug_assert_eq!( self.shape.lookup(key), Some(Slot { diff --git a/boa_engine/src/optimizer/pass/constant_folding.rs b/boa_engine/src/optimizer/pass/constant_folding.rs index d510e11310e..244f6e812e0 100644 --- a/boa_engine/src/optimizer/pass/constant_folding.rs +++ b/boa_engine/src/optimizer/pass/constant_folding.rs @@ -32,7 +32,11 @@ fn js_value_to_literal(value: JsValue, context: &mut Context<'_>) -> Literal { JsValue::Null => Literal::Null, JsValue::Undefined => Literal::Undefined, JsValue::Boolean(v) => Literal::Bool(v), - JsValue::String(v) => Literal::String(context.interner_mut().get_or_intern(v.as_ref())), + JsValue::String(v) => Literal::String( + context + .interner_mut() + .get_or_intern(v.as_slice().as_str_ref()), + ), JsValue::Rational(v) => Literal::Num(v), JsValue::Integer(v) => Literal::Int(v), JsValue::BigInt(v) => Literal::BigInt(Box::new(v.as_inner().clone())), diff --git a/boa_engine/src/property/mod.rs b/boa_engine/src/property/mod.rs index 23ab3834730..fc906ce8d63 100644 --- a/boa_engine/src/property/mod.rs +++ b/boa_engine/src/property/mod.rs @@ -677,10 +677,18 @@ impl From<&[u16]> for PropertyKey { } } +impl From<&str> for PropertyKey { + #[inline] + fn from(string: &str) -> Self { + // debug_assert!(parse_u32_index(string).is_none()); + Self::String(JsString::from(string)) + } +} + impl From for PropertyKey { #[inline] fn from(string: JsString) -> Self { - parse_u32_index(string.as_slice().iter().copied()).map_or(Self::String(string), Self::Index) + parse_u32_index(string.iter()).map_or(Self::String(string), Self::Index) } } diff --git a/boa_engine/src/string/common.rs b/boa_engine/src/string/common.rs index 45a8d9e4a6d..8ce02c4da3c 100644 --- a/boa_engine/src/string/common.rs +++ b/boa_engine/src/string/common.rs @@ -3,7 +3,6 @@ use std::hash::BuildHasherDefault; use crate::tagged::Tagged; use super::JsString; -use boa_macros::utf16; use paste::paste; use rustc_hash::{FxHashMap, FxHasher}; @@ -11,11 +10,13 @@ macro_rules! well_known_statics { ( $( $(#[$attr:meta])* ($name:ident, $string:literal) ),+$(,)? ) => { $( paste!{ - #[doc = "Gets the static `JsString` for `\"" $string "\"`."] + // TODO: doc + // #[doc = "Gets the static `JsString` for `\"" $string "\"`."] + #[doc = "Gets the static `JsString`."] #[allow(unused)] pub(crate) const $name: JsString = JsString { ptr: Tagged::from_tag( - Self::find_index(utf16!($string)), + Self::find_index($string), ), }; } @@ -31,15 +32,15 @@ pub(crate) struct StaticJsStrings; impl StaticJsStrings { // useful to search at compile time a certain string in the array - const fn find_index(candidate: &[u16]) -> usize { - const fn const_eq(lhs: &[u16], rhs: &[u16]) -> bool { + const fn find_index(candidate: &str) -> usize { + const fn const_eq(lhs: &str, rhs: &str) -> bool { if lhs.len() != rhs.len() { return false; } let mut i = 0; while i < lhs.len() { - if lhs[i] != rhs[i] { + if lhs.as_bytes()[i] != rhs.as_bytes()[i] { return false; } i += 1; @@ -49,6 +50,7 @@ impl StaticJsStrings { let mut i = 0; while i < RAW_STATICS.len() { let s = RAW_STATICS[i]; + // assert!(s.is_ascii()); if const_eq(s, candidate) { return i; } @@ -59,7 +61,7 @@ impl StaticJsStrings { /// Gets the `JsString` corresponding to `string`, or `None` if the string /// doesn't exist inside the static array. - pub(crate) fn get_string(string: &[u16]) -> Option { + pub(crate) fn get_string(string: &str) -> Option { if string.len() > MAX_STATIC_LENGTH { return None; } @@ -73,7 +75,7 @@ impl StaticJsStrings { /// 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<&'static [u16]> { + pub(crate) fn get(index: usize) -> Option<&'static str> { RAW_STATICS.get(index).copied() } @@ -204,7 +206,7 @@ static MAX_STATIC_LENGTH: usize = { thread_local! { /// Map from a string inside [`RAW_STATICS`] to its corresponding static index on `RAW_STATICS`. - static RAW_STATICS_CACHE: FxHashMap<&'static [u16], usize> = { + static RAW_STATICS_CACHE: FxHashMap<&'static str, usize> = { let mut constants = FxHashMap::with_capacity_and_hasher( RAW_STATICS.len(), BuildHasherDefault::::default(), @@ -219,493 +221,493 @@ thread_local! { } /// Array of raw static strings that aren't reference counted. -const RAW_STATICS: &[&[u16]] = &[ - utf16!(""), +const RAW_STATICS: &[&str] = &[ + "", // Well known symbols - utf16!("Symbol.asyncIterator"), - utf16!("[Symbol.asyncIterator]"), - utf16!("Symbol.hasInstance"), - utf16!("[Symbol.hasInstance]"), - utf16!("Symbol.isConcatSpreadable"), - utf16!("[Symbol.isConcatSpreadable]"), - utf16!("Symbol.iterator"), - utf16!("[Symbol.iterator]"), - utf16!("Symbol.match"), - utf16!("[Symbol.match]"), - utf16!("Symbol.matchAll"), - utf16!("[Symbol.matchAll]"), - utf16!("Symbol.replace"), - utf16!("[Symbol.replace]"), - utf16!("Symbol.search"), - utf16!("[Symbol.search]"), - utf16!("Symbol.species"), - utf16!("[Symbol.species]"), - utf16!("Symbol.split"), - utf16!("[Symbol.split]"), - utf16!("Symbol.toPrimitive"), - utf16!("[Symbol.toPrimitive]"), - utf16!("Symbol.toStringTag"), - utf16!("[Symbol.toStringTag]"), - utf16!("Symbol.unscopables"), - utf16!("[Symbol.unscopables]"), + "Symbol.asyncIterator", + "[Symbol.asyncIterator]", + "Symbol.hasInstance", + "[Symbol.hasInstance]", + "Symbol.isConcatSpreadable", + "[Symbol.isConcatSpreadable]", + "Symbol.iterator", + "[Symbol.iterator]", + "Symbol.match", + "[Symbol.match]", + "Symbol.matchAll", + "[Symbol.matchAll]", + "Symbol.replace", + "[Symbol.replace]", + "Symbol.search", + "[Symbol.search]", + "Symbol.species", + "[Symbol.species]", + "Symbol.split", + "[Symbol.split]", + "Symbol.toPrimitive", + "[Symbol.toPrimitive]", + "Symbol.toStringTag", + "[Symbol.toStringTag]", + "Symbol.unscopables", + "[Symbol.unscopables]", // Well known builtins - utf16!("Array"), - utf16!("ArrayBuffer"), - utf16!("SharedArrayBuffer"), - utf16!("AsyncFunction"), - utf16!("AsyncGenerator"), - utf16!("AsyncGeneratorFunction"), - utf16!("BigInt"), - utf16!("Boolean"), - utf16!("DataView"), - utf16!("Date"), - utf16!("Error"), - utf16!("AggregateError"), - utf16!("EvalError"), - utf16!("RangeError"), - utf16!("ReferenceError"), - utf16!("SyntaxError"), - utf16!("TypeError"), - utf16!("URIError"), - utf16!("escape"), - utf16!("unescape"), - utf16!("eval"), - utf16!("Function"), - utf16!("Generator"), - utf16!("GeneratorFunction"), - utf16!("Intl"), - utf16!("Collator"), - utf16!("ListFormat"), - utf16!("Locale"), - utf16!("PluralRules"), - utf16!("Segmenter"), - utf16!("DateTimeFormat"), - utf16!("JSON"), - utf16!("Map"), - utf16!("Math"), - utf16!("Number"), - utf16!("isFinite"), - utf16!("isNaN"), - utf16!("parseInt"), - utf16!("parseFloat"), - utf16!("Object"), - utf16!("Promise"), - utf16!("Proxy"), - utf16!("Reflect"), - utf16!("RegExp"), - utf16!("Set"), - utf16!("String"), - utf16!("Symbol"), - utf16!("TypedArray"), - utf16!("Int8Array"), - utf16!("Uint8Array"), - utf16!("Uint8ClampedArray"), - utf16!("Int16Array"), - utf16!("Uint16Array"), - utf16!("Int32Array"), - utf16!("Uint32Array"), - utf16!("BigInt64Array"), - utf16!("BigUint64Array"), - utf16!("Float32Array"), - utf16!("Float64Array"), - utf16!("encodeURI"), - utf16!("encodeURIComponent"), - utf16!("decodeURI"), - utf16!("decodeURIComponent"), - utf16!("WeakRef"), - utf16!("WeakMap"), - utf16!("WeakSet"), - utf16!("Temporal"), - utf16!("Temporal.Now"), - utf16!("Temporal.Instant"), - utf16!("Temporal.Duration"), - utf16!("Temporal.Calendar"), - utf16!("Temporal.PlainDate"), - utf16!("Temporal.PlainDateTime"), - utf16!("Temporal.PlainMonthDay"), - utf16!("Temporal.PlainYearMonth"), - utf16!("Temporal.PlainTime"), - utf16!("Temporal.TimeZone"), - utf16!("Temporal.ZonedDateTime"), + "Array", + "ArrayBuffer", + "SharedArrayBuffer", + "AsyncFunction", + "AsyncGenerator", + "AsyncGeneratorFunction", + "BigInt", + "Boolean", + "DataView", + "Date", + "Error", + "AggregateError", + "EvalError", + "RangeError", + "ReferenceError", + "SyntaxError", + "TypeError", + "URIError", + "escape", + "unescape", + "eval", + "Function", + "Generator", + "GeneratorFunction", + "Intl", + "Collator", + "ListFormat", + "Locale", + "PluralRules", + "Segmenter", + "DateTimeFormat", + "JSON", + "Map", + "Math", + "Number", + "isFinite", + "isNaN", + "parseInt", + "parseFloat", + "Object", + "Promise", + "Proxy", + "Reflect", + "RegExp", + "Set", + "String", + "Symbol", + "TypedArray", + "Int8Array", + "Uint8Array", + "Uint8ClampedArray", + "Int16Array", + "Uint16Array", + "Int32Array", + "Uint32Array", + "BigInt64Array", + "BigUint64Array", + "Float32Array", + "Float64Array", + "encodeURI", + "encodeURIComponent", + "decodeURI", + "decodeURIComponent", + "WeakRef", + "WeakMap", + "WeakSet", + "Temporal", + "Temporal.Now", + "Temporal.Instant", + "Temporal.Duration", + "Temporal.Calendar", + "Temporal.PlainDate", + "Temporal.PlainDateTime", + "Temporal.PlainMonthDay", + "Temporal.PlainYearMonth", + "Temporal.PlainTime", + "Temporal.TimeZone", + "Temporal.ZonedDateTime", // Misc - utf16!(","), - utf16!(":"), + ",", + ":", // Generic use - utf16!("name"), - utf16!("length"), - utf16!("arguments"), - utf16!("prototype"), - utf16!("constructor"), - utf16!("return"), - utf16!("throw"), - utf16!("global"), - utf16!("globalThis"), + "name", + "length", + "arguments", + "prototype", + "constructor", + "return", + "throw", + "global", + "globalThis", // typeof - utf16!("null"), - utf16!("undefined"), - utf16!("number"), - utf16!("string"), - utf16!("symbol"), - utf16!("bigint"), - utf16!("object"), - utf16!("function"), + "null", + "undefined", + "number", + "string", + "symbol", + "bigint", + "object", + "function", // Property descriptor - utf16!("value"), - utf16!("get"), - utf16!("set"), - utf16!("writable"), - utf16!("enumerable"), - utf16!("configurable"), + "value", + "get", + "set", + "writable", + "enumerable", + "configurable", // Object object - utf16!("Object"), - utf16!("assign"), - utf16!("create"), - utf16!("toString"), - utf16!("valueOf"), - utf16!("is"), - utf16!("seal"), - utf16!("isSealed"), - utf16!("freeze"), - utf16!("isFrozen"), - utf16!("isExtensible"), - utf16!("hasOwnProperty"), - utf16!("isPrototypeOf"), - utf16!("setPrototypeOf"), - utf16!("getPrototypeOf"), - utf16!("defineProperty"), - utf16!("defineProperties"), - utf16!("deleteProperty"), - utf16!("construct"), - utf16!("hasOwn"), - utf16!("ownKeys"), - utf16!("keys"), - utf16!("values"), - utf16!("entries"), - utf16!("fromEntries"), + "Object", + "assign", + "create", + "toString", + "valueOf", + "is", + "seal", + "isSealed", + "freeze", + "isFrozen", + "isExtensible", + "hasOwnProperty", + "isPrototypeOf", + "setPrototypeOf", + "getPrototypeOf", + "defineProperty", + "defineProperties", + "deleteProperty", + "construct", + "hasOwn", + "ownKeys", + "keys", + "values", + "entries", + "fromEntries", // Function object - utf16!("apply"), - utf16!("bind"), - utf16!("call"), + "apply", + "bind", + "call", // Array object - utf16!("at"), - utf16!("from"), - utf16!("isArray"), - utf16!("of"), - utf16!("copyWithin"), - utf16!("every"), - utf16!("fill"), - utf16!("filter"), - utf16!("find"), - utf16!("findIndex"), - utf16!("findLast"), - utf16!("findLastIndex"), - utf16!("flat"), - utf16!("flatMap"), - utf16!("forEach"), - utf16!("includes"), - utf16!("indexOf"), - utf16!("join"), - utf16!("map"), - utf16!("next"), - utf16!("reduce"), - utf16!("reduceRight"), - utf16!("reverse"), - utf16!("shift"), - utf16!("slice"), - utf16!("splice"), - utf16!("some"), - utf16!("sort"), - utf16!("unshift"), - utf16!("push"), - utf16!("pop"), + "at", + "from", + "isArray", + "of", + "copyWithin", + "every", + "fill", + "filter", + "find", + "findIndex", + "findLast", + "findLastIndex", + "flat", + "flatMap", + "forEach", + "includes", + "indexOf", + "join", + "map", + "next", + "reduce", + "reduceRight", + "reverse", + "shift", + "slice", + "splice", + "some", + "sort", + "unshift", + "push", + "pop", // String object - utf16!("charAt"), - utf16!("charCodeAt"), - utf16!("codePointAt"), - utf16!("concat"), - utf16!("endsWith"), - utf16!("fromCharCode"), - utf16!("fromCodePoint"), - utf16!("lastIndexOf"), - utf16!("match"), - utf16!("matchAll"), - utf16!("normalize"), - utf16!("padEnd"), - utf16!("padStart"), - utf16!("raw"), - utf16!("repeat"), - utf16!("replace"), - utf16!("replaceAll"), - utf16!("search"), - utf16!("split"), - utf16!("startsWith"), - utf16!("substr"), - utf16!("substring"), - utf16!("toLocaleString"), - utf16!("toLowerCase"), - utf16!("toUpperCase"), - utf16!("trim"), - utf16!("trimEnd"), - utf16!("trimStart"), + "charAt", + "charCodeAt", + "codePointAt", + "concat", + "endsWith", + "fromCharCode", + "fromCodePoint", + "lastIndexOf", + "match", + "matchAll", + "normalize", + "padEnd", + "padStart", + "raw", + "repeat", + "replace", + "replaceAll", + "search", + "split", + "startsWith", + "substr", + "substring", + "toLocaleString", + "toLowerCase", + "toUpperCase", + "trim", + "trimEnd", + "trimStart", // Number object - utf16!("Infinity"), - utf16!("NaN"), - utf16!("EPSILON"), - utf16!("MAX_SAFE_INTEGER"), - utf16!("MIN_SAFE_INTEGER"), - utf16!("MAX_VALUE"), - utf16!("MIN_VALUE"), - utf16!("isSafeInteger"), - utf16!("isInteger"), - utf16!("toExponential"), - utf16!("toFixed"), - utf16!("toPrecision"), + "Infinity", + "NaN", + "EPSILON", + "MAX_SAFE_INTEGER", + "MIN_SAFE_INTEGER", + "MAX_VALUE", + "MIN_VALUE", + "isSafeInteger", + "isInteger", + "toExponential", + "toFixed", + "toPrecision", // BigInt object - utf16!("asIntN"), - utf16!("asUintN"), + "asIntN", + "asUintN", // RegExp object - utf16!("exec"), - utf16!("test"), - utf16!("flags"), - utf16!("index"), - utf16!("lastIndex"), - utf16!("hasIndices"), - utf16!("ignoreCase"), - utf16!("multiline"), - utf16!("dotAll"), - utf16!("unicode"), - utf16!("sticky"), - utf16!("source"), - utf16!("get hasIndices"), - utf16!("get global"), - utf16!("get ignoreCase"), - utf16!("get multiline"), - utf16!("get dotAll"), - utf16!("get unicode"), - utf16!("get sticky"), - utf16!("get flags"), - utf16!("get source"), + "exec", + "test", + "flags", + "index", + "lastIndex", + "hasIndices", + "ignoreCase", + "multiline", + "dotAll", + "unicode", + "sticky", + "source", + "get hasIndices", + "get global", + "get ignoreCase", + "get multiline", + "get dotAll", + "get unicode", + "get sticky", + "get flags", + "get source", // Symbol object - utf16!("for"), - utf16!("keyFor"), - utf16!("description"), - utf16!("asyncIterator"), - utf16!("hasInstance"), - utf16!("species"), - utf16!("unscopables"), - utf16!("iterator"), - utf16!("toStringTag"), - utf16!("toPrimitive"), - utf16!("get description"), + "for", + "keyFor", + "description", + "asyncIterator", + "hasInstance", + "species", + "unscopables", + "iterator", + "toStringTag", + "toPrimitive", + "get description", // Map object - utf16!("clear"), - utf16!("delete"), - utf16!("has"), - utf16!("size"), + "clear", + "delete", + "has", + "size", // Set object - utf16!("add"), + "add", // Reflect object // Proxy object - utf16!("revocable"), + "revocable", // Error objects - utf16!("message"), + "message", // Date object - utf16!("toJSON"), - utf16!("getDate"), - utf16!("getDay"), - utf16!("getFullYear"), - utf16!("getHours"), - utf16!("getMilliseconds"), - utf16!("getMinutes"), - utf16!("getMonth"), - utf16!("getSeconds"), - utf16!("getTime"), - utf16!("getYear"), - utf16!("getUTCDate"), - utf16!("getUTCDay"), - utf16!("getUTCFullYear"), - utf16!("getUTCHours"), - utf16!("getUTCMinutes"), - utf16!("getUTCMonth"), - utf16!("getUTCSeconds"), - utf16!("setDate"), - utf16!("setFullYear"), - utf16!("setHours"), - utf16!("setMilliseconds"), - utf16!("setMinutes"), - utf16!("setMonth"), - utf16!("setSeconds"), - utf16!("setYear"), - utf16!("setTime"), - utf16!("setUTCDate"), - utf16!("setUTCFullYear"), - utf16!("setUTCHours"), - utf16!("setUTCMinutes"), - utf16!("setUTCMonth"), - utf16!("setUTCSeconds"), - utf16!("toDateString"), - utf16!("toGMTString"), - utf16!("toISOString"), - utf16!("toTimeString"), - utf16!("toUTCString"), - utf16!("now"), - utf16!("UTC"), + "toJSON", + "getDate", + "getDay", + "getFullYear", + "getHours", + "getMilliseconds", + "getMinutes", + "getMonth", + "getSeconds", + "getTime", + "getYear", + "getUTCDate", + "getUTCDay", + "getUTCFullYear", + "getUTCHours", + "getUTCMinutes", + "getUTCMonth", + "getUTCSeconds", + "setDate", + "setFullYear", + "setHours", + "setMilliseconds", + "setMinutes", + "setMonth", + "setSeconds", + "setYear", + "setTime", + "setUTCDate", + "setUTCFullYear", + "setUTCHours", + "setUTCMinutes", + "setUTCMonth", + "setUTCSeconds", + "toDateString", + "toGMTString", + "toISOString", + "toTimeString", + "toUTCString", + "now", + "UTC", // JSON object - utf16!("parse"), - utf16!("stringify"), + "parse", + "stringify", // Iterator object - utf16!("Array Iterator"), - utf16!("Set Iterator"), - utf16!("String Iterator"), - utf16!("Map Iterator"), - utf16!("For In Iterator"), + "Array Iterator", + "Set Iterator", + "String Iterator", + "Map Iterator", + "For In Iterator", // Math object - utf16!("LN10"), - utf16!("LN2"), - utf16!("LOG10E"), - utf16!("LOG2E"), - utf16!("PI"), - utf16!("SQRT1_2"), - utf16!("SQRT2"), - utf16!("abs"), - utf16!("acos"), - utf16!("acosh"), - utf16!("asin"), - utf16!("asinh"), - utf16!("atan"), - utf16!("atanh"), - utf16!("atan2"), - utf16!("cbrt"), - utf16!("ceil"), - utf16!("clz32"), - utf16!("cos"), - utf16!("cosh"), - utf16!("exp"), - utf16!("expm1"), - utf16!("floor"), - utf16!("fround"), - utf16!("hypot"), - utf16!("imul"), - utf16!("log"), - utf16!("log1p"), - utf16!("log10"), - utf16!("log2"), - utf16!("max"), - utf16!("min"), - utf16!("pow"), - utf16!("random"), - utf16!("round"), - utf16!("sign"), - utf16!("sin"), - utf16!("sinh"), - utf16!("sqrt"), - utf16!("tan"), - utf16!("tanh"), - utf16!("trunc"), + "LN10", + "LN2", + "LOG10E", + "LOG2E", + "PI", + "SQRT1_2", + "SQRT2", + "abs", + "acos", + "acosh", + "asin", + "asinh", + "atan", + "atanh", + "atan2", + "cbrt", + "ceil", + "clz32", + "cos", + "cosh", + "exp", + "expm1", + "floor", + "fround", + "hypot", + "imul", + "log", + "log1p", + "log10", + "log2", + "max", + "min", + "pow", + "random", + "round", + "sign", + "sin", + "sinh", + "sqrt", + "tan", + "tanh", + "trunc", // TypedArray object - utf16!("buffer"), - utf16!("byteLength"), - utf16!("byteOffset"), - utf16!("isView"), - utf16!("subarray"), - utf16!("get byteLength"), - utf16!("get buffer"), - utf16!("get byteOffset"), - utf16!("get size"), - utf16!("get length"), + "buffer", + "byteLength", + "byteOffset", + "isView", + "subarray", + "get byteLength", + "get buffer", + "get byteOffset", + "get size", + "get length", // DataView object - utf16!("getBigInt64"), - utf16!("getBigUint64"), - utf16!("getFloat32"), - utf16!("getFloat64"), - utf16!("getInt8"), - utf16!("getInt16"), - utf16!("getInt32"), - utf16!("getUint8"), - utf16!("getUint16"), - utf16!("getUint32"), - utf16!("setBigInt64"), - utf16!("setBigUint64"), - utf16!("setFloat32"), - utf16!("setFloat64"), - utf16!("setInt8"), - utf16!("setInt16"), - utf16!("setInt32"), - utf16!("setUint8"), - utf16!("setUint16"), - utf16!("setUint32"), + "getBigInt64", + "getBigUint64", + "getFloat32", + "getFloat64", + "getInt8", + "getInt16", + "getInt32", + "getUint8", + "getUint16", + "getUint32", + "setBigInt64", + "setBigUint64", + "setFloat32", + "setFloat64", + "setInt8", + "setInt16", + "setInt32", + "setUint8", + "setUint16", + "setUint32", // Console object - utf16!("console"), - utf16!("assert"), - utf16!("debug"), - utf16!("error"), - utf16!("info"), - utf16!("trace"), - utf16!("warn"), - utf16!("exception"), - utf16!("count"), - utf16!("countReset"), - utf16!("group"), - utf16!("groupCollapsed"), - utf16!("groupEnd"), - utf16!("time"), - utf16!("timeLog"), - utf16!("timeEnd"), - utf16!("dir"), - utf16!("dirxml"), + "console", + "assert", + "debug", + "error", + "info", + "trace", + "warn", + "exception", + "count", + "countReset", + "group", + "groupCollapsed", + "groupEnd", + "time", + "timeLog", + "timeEnd", + "dir", + "dirxml", // Minified name - utf16!("a"), - utf16!("b"), - utf16!("c"), - utf16!("d"), - utf16!("e"), - utf16!("f"), - utf16!("g"), - utf16!("h"), - utf16!("i"), - utf16!("j"), - utf16!("k"), - utf16!("l"), - utf16!("m"), - utf16!("n"), - utf16!("o"), - utf16!("p"), - utf16!("q"), - utf16!("r"), - utf16!("s"), - utf16!("t"), - utf16!("u"), - utf16!("v"), - utf16!("w"), - utf16!("x"), - utf16!("y"), - utf16!("z"), - utf16!("A"), - utf16!("B"), - utf16!("C"), - utf16!("D"), - utf16!("E"), - utf16!("F"), - utf16!("G"), - utf16!("H"), - utf16!("I"), - utf16!("J"), - utf16!("K"), - utf16!("L"), - utf16!("M"), - utf16!("N"), - utf16!("O"), - utf16!("P"), - utf16!("Q"), - utf16!("R"), - utf16!("S"), - utf16!("T"), - utf16!("U"), - utf16!("V"), - utf16!("W"), - utf16!("X"), - utf16!("Y"), - utf16!("Z"), - utf16!("_"), - utf16!("$"), + "a", + "", + "c", + "d", + "e", + "f", + "g", + "h", + "i", + "j", + "k", + "l", + "m", + "n", + "o", + "p", + "q", + "r", + "s", + "t", + "u", + "v", + "w", + "x", + "y", + "z", + "A", + "", + "C", + "D", + "E", + "F", + "G", + "H", + "I", + "J", + "K", + "L", + "M", + "N", + "O", + "P", + "Q", + "R", + "S", + "T", + "U", + "V", + "W", + "X", + "Y", + "Z", + "_", + "$", ]; diff --git a/boa_engine/src/string/mod.rs b/boa_engine/src/string/mod.rs index 7483a0897e9..02ce8c8f2f0 100644 --- a/boa_engine/src/string/mod.rs +++ b/boa_engine/src/string/mod.rs @@ -29,19 +29,17 @@ use crate::{ JsBigInt, }; use boa_gc::{empty_trace, Finalize, Trace}; +use boa_interner::JStrRef; pub use boa_macros::utf16; use std::{ alloc::{alloc, dealloc, Layout}, - borrow::Borrow, cell::Cell, convert::Infallible, hash::{Hash, Hasher}, - iter::Peekable, - ops::{Deref, Index}, + iter::{FusedIterator, Peekable}, process::abort, ptr::{self, addr_of, addr_of_mut, NonNull}, - slice::SliceIndex, str::FromStr, }; @@ -73,7 +71,7 @@ fn alloc_overflow() -> ! { /// # use boa_engine::js_string; /// # use boa_engine::string::utf16; /// let hw = js_string!("Hello, world!"); -/// assert_eq!(&hw, utf16!("Hello, world!")); +/// assert_eq!(&hw, "Hello, world!"); /// ``` /// /// Any `&[u16]` slice is a valid `JsString`, including unpaired surrogates: @@ -89,11 +87,11 @@ fn alloc_overflow() -> ! { /// ``` /// # use boa_engine::js_string; /// # use boa_engine::string::utf16; -/// const NAME: &[u16] = utf16!("human! "); +/// const NAME: &[u16] = "human! "; /// let greeting = js_string!("Hello, "); -/// let msg = js_string!(&greeting, &NAME, utf16!("Nice to meet you!")); +/// let msg = js_string!(&greeting, &NAME, "Nice to meet you!"); /// -/// assert_eq!(&msg, utf16!("Hello, human! Nice to meet you!")); +/// assert_eq!(&msg, "Hello, human! Nice to meet you!"); /// ``` #[macro_export] macro_rules! js_string { @@ -101,16 +99,16 @@ macro_rules! js_string { $crate::JsString::default() }; ($s:literal) => { - $crate::JsString::from($crate::string::utf16!($s)) + $crate::JsString::from($crate::string::CowJsString::from($s)) }; ($s:expr) => { $crate::JsString::from($s) }; ( $x:expr, $y:expr ) => { - $crate::JsString::concat($x, $y) + $crate::JsString::concat($crate::string::CowJsString::from($x), $crate::string::CowJsString::from($y)) }; ( $( $s:expr ),+ ) => { - $crate::JsString::concat_array(&[ $( $s ),+ ]) + $crate::JsString::concat_array(&[ $( $crate::string::CowJsString::from($s) ),+ ]) }; } @@ -180,6 +178,8 @@ struct RawJsString { /// The UTF-16 length. len: usize, + flags: usize, + /// The number of references to the string. /// /// When this reaches `0` the string is deallocated. @@ -217,37 +217,254 @@ unsafe impl Trace for JsString { empty_trace!(); } +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub enum JsStr<'a> { + Ascii(&'a str), + U16(&'a [u16]), +} + +impl JsStr<'_> { + #[must_use] + pub fn len(&self) -> usize { + match self { + Self::Ascii(v) => v.len(), + Self::U16(v) => v.len(), + } + } + + fn is_ascii(&self) -> bool { + matches!(self, JsStr::Ascii(_)) + } + + fn as_ascii(&self) -> Option<&str> { + if let Self::Ascii(slice) = self { + return Some(slice); + } + + None + } + + /// TODO: doc + #[inline] + #[must_use] + pub fn iter(&self) -> Iter<'_> { + Iter::new(*self) + } + + pub(crate) fn as_str_ref(&self) -> JStrRef<'_> { + match self { + Self::Ascii(s) => JStrRef::Utf8(s), + Self::U16(s) => JStrRef::Utf16(s), + } + } + + pub fn is_empty(&self) -> bool { + match self { + Self::Ascii(s) => s.is_empty(), + Self::U16(s) => s.is_empty(), + } + } +} + +#[derive(Debug)] +pub enum CowJsString<'a> { + Borrowed(JsStr<'a>), + Owned(JsString), +} + +impl CowJsString<'_> { + fn as_slice(&self) -> JsStr<'_> { + match self { + CowJsString::Borrowed(s) => *s, + CowJsString::Owned(s) => s.as_slice(), + } + } +} + +impl From for CowJsString<'_> { + fn from(value: JsString) -> Self { + Self::Owned(value) + } +} + +impl<'a> From<&'a JsString> for CowJsString<'a> { + fn from(value: &'a JsString) -> Self { + Self::Borrowed(value.as_slice()) + } +} + +impl<'a> From> for CowJsString<'a> { + fn from(value: JsStr<'a>) -> Self { + Self::Borrowed(value) + } +} + +impl<'a> From<&'a str> for CowJsString<'a> { + fn from(value: &'a str) -> Self { + if value.is_ascii() { + return Self::Borrowed(JsStr::Ascii(value)); + } + + Self::Owned(JsString::from( + &value.encode_utf16().collect::>()[..], + )) + } +} + +impl<'a> From<&'a [u16]> for CowJsString<'a> { + fn from(s: &'a [u16]) -> Self { + if is_ascii(s) { + let s = s.iter().copied().map(|c| c as u8).collect::>(); + // SAFETY: Already checked that it's ASCII, so this is safe. + let s = unsafe { std::str::from_utf8_unchecked(&s) }; + return Self::Owned( + StaticJsStrings::get_string(s) + .unwrap_or_else(|| JsString::from_slice_skip_interning(JsStr::Ascii(s))), + ); + } + Self::Borrowed(JsStr::U16(s)) + } +} + +impl From> for JsString { + fn from(value: JsStr<'_>) -> Self { + match value { + // TODO: Maybe remove the check that comes from `JsString::from` <&str>. + JsStr::Ascii(s) => JsString::from(s), + JsStr::U16(s) => JsString::from(s), + } + } +} + +impl From> for JsString { + fn from(value: CowJsString<'_>) -> Self { + match value { + CowJsString::Borrowed(s) => JsString::from(s), + CowJsString::Owned(s) => s, + } + } +} + +#[derive(Debug, Clone)] +pub enum Iter<'a> { + Ascii(std::str::Bytes<'a>), + U16(std::iter::Copied>), +} + +impl<'a> Iter<'a> { + fn new(s: JsStr<'a>) -> Self { + match s { + JsStr::Ascii(s) => Self::Ascii(s.bytes()), + JsStr::U16(s) => Self::U16(s.iter().copied()), + } + } +} + +impl Iterator for Iter<'_> { + type Item = u16; + + fn next(&mut self) -> Option { + match self { + Self::Ascii(iter) => iter.map(u16::from).next(), + Self::U16(iter) => iter.next(), + } + } +} + +impl FusedIterator for Iter<'_> {} + +impl ExactSizeIterator for Iter<'_> { + fn len(&self) -> usize { + match self { + Self::Ascii(v) => v.len(), + Self::U16(v) => v.len(), + } + } +} + +impl<'a> From<&'a JsString> for JsStr<'a> { + fn from(value: &'a JsString) -> Self { + value.as_slice() + } +} + impl JsString { + /// TODO: doc + #[inline] + #[must_use] + pub fn iter(&self) -> Iter<'_> { + Iter::new(self.as_slice()) + } + /// Obtains the underlying [`&[u16]`][slice] slice of a [`JsString`] #[must_use] - pub fn as_slice(&self) -> &[u16] { - self + pub fn as_slice(&self) -> JsStr<'_> { + match self.ptr.unwrap() { + UnwrappedTagged::Ptr(h) => { + // SAFETY: + // - The `RawJsString` type has all the necessary information to reconstruct a valid + // slice (length and starting pointer). + // + // - We aligned `h.data` on allocation, and the block is of size `h.len`, so this + // should only generate valid reads. + // + // - The lifetime of `&Self::Target` is shorter than the lifetime of `self`, as seen + // by its signature, so this doesn't outlive `self`. + unsafe { + let h = h.as_ptr(); + + if (*h).flags == 0 { + JsStr::U16(std::slice::from_raw_parts( + addr_of!((*h).data).cast(), + (*h).len, + )) + } else { + JsStr::Ascii(std::str::from_utf8_unchecked(std::slice::from_raw_parts( + addr_of!((*h).data).cast(), + (*h).len, + ))) + } + } + } + UnwrappedTagged::Tag(index) => { + // SAFETY: all static strings are valid indices on `STATIC_JS_STRINGS`, so `get` should always + // return `Some`. + JsStr::Ascii(unsafe { StaticJsStrings::get(index).unwrap_unchecked() }) + } + } } /// Creates a new [`JsString`] from the concatenation of `x` and `y`. #[must_use] - pub fn concat(x: &[u16], y: &[u16]) -> Self { + pub fn concat(x: CowJsString<'_>, y: CowJsString<'_>) -> Self { Self::concat_array(&[x, y]) } /// Creates a new [`JsString`] from the concatenation of every element of /// `strings`. #[must_use] - pub fn concat_array(strings: &[&[u16]]) -> Self { + pub fn concat_array(strings: &[CowJsString<'_>]) -> Self { + let mut ascii = true; let mut full_count = 0usize; - for &string in strings { - let Some(sum) = full_count.checked_add(string.len()) else { + for string in strings { + let Some(sum) = full_count.checked_add(string.as_slice().len()) else { alloc_overflow() }; + if !string.as_slice().is_ascii() { + ascii = false; + } full_count = sum; } - let ptr = Self::allocate_inner(full_count); + // dbg!(strings); + + let ptr = Self::allocate_inner(full_count, ascii); let string = { // SAFETY: `allocate_inner` guarantees that `ptr` is a valid pointer. - let mut data = unsafe { addr_of_mut!((*ptr.as_ptr()).data).cast() }; + let mut data = unsafe { addr_of_mut!((*ptr.as_ptr()).data).cast::() }; for string in strings { + let string = string.as_slice(); let count = string.len(); // SAFETY: // The sum of all `count` for each `string` equals `full_count`, and since we're @@ -260,8 +477,23 @@ impl JsString { // `allocate_inner` must return a valid pointer to newly allocated memory, meaning // `ptr` and all `string`s should never overlap. unsafe { - ptr::copy_nonoverlapping(string.as_ptr(), data, count); - data = data.add(count); + match (ascii, string) { + (true, JsStr::Ascii(s)) => { + ptr::copy_nonoverlapping(s.as_ptr(), data.cast::(), count); + data = data.cast::().add(count).cast::(); + } + (false, JsStr::Ascii(s)) => { + for (i, byte) in s.bytes().enumerate() { + *data.cast::().add(i) = u16::from(byte); + } + data = data.cast::().add(count).cast::(); + } + (false, JsStr::U16(s)) => { + ptr::copy_nonoverlapping(s.as_ptr(), data.cast::(), count); + data = data.cast::().add(count).cast::(); + } + (true, JsStr::U16(_)) => unreachable!(), + } } } Self { @@ -270,7 +502,22 @@ impl JsString { } }; - StaticJsStrings::get_string(&string[..]).unwrap_or(string) + let slice = string.as_slice(); + // let Some(slice) = slice.as_ascii() else { + // return string; + // }; + + let slice = match slice { + JsStr::Ascii(slice) => slice, + JsStr::U16(slice) => { + if is_ascii(slice) { + unreachable!("U16 should not be ascii representable, ascii? {ascii}") + } + return string; + } + }; + + StaticJsStrings::get_string(slice).unwrap_or(string) } /// Decodes a [`JsString`] into a [`String`], replacing invalid data with its escaped representation @@ -283,7 +530,10 @@ impl JsString { /// Decodes a [`JsString`] into a [`String`], returning /// [`FromUtf16Error`][std::string::FromUtf16Error] if it contains any invalid data. pub fn to_std_string(&self) -> Result { - String::from_utf16(self) + match self.as_slice() { + JsStr::Ascii(v) => Ok(v.to_owned()), + JsStr::U16(v) => String::from_utf16(v), + } } /// Decodes a [`JsString`] into an iterator of [`Result`], returning surrogates as @@ -353,12 +603,12 @@ impl JsString { } } - js_string!(text) + js_string!(&text[..]) } /// Gets an iterator of all the Unicode codepoints of a [`JsString`]. pub fn code_points(&self) -> impl Iterator + Clone + '_ { - char::decode_utf16(self.iter().copied()).map(|res| match res { + char::decode_utf16(self.iter()).map(|res| match res { Ok(c) => CodePoint::Unicode(c), Err(e) => CodePoint::UnpairedSurrogate(e.unpaired_surrogate()), }) @@ -373,7 +623,10 @@ impl JsString { /// - [ECMAScript reference][spec] /// /// [spec]: https://tc39.es/ecma262/#sec-stringindexof - pub(crate) fn index_of(&self, search_value: &[u16], from_index: usize) -> Option { + pub(crate) fn index_of(&self, search_value: &JsStr<'_>, from_index: usize) -> Option { + let this = self.iter().collect::>(); + let search_value = search_value.iter().collect::>(); + // 1. Assert: Type(string) is String. // 2. Assert: Type(searchValue) is String. // 3. Assert: fromIndex is a non-negative integer. @@ -395,7 +648,7 @@ impl JsString { // a. Let candidate be the substring of string from i to i + searchLen. // b. If candidate is the same sequence of code units as searchValue, return i. // 8. Return -1. - self.windows(search_value.len()) + this.windows(search_value.len()) .skip(from_index) .position(|s| s == search_value) .map(|i| i + from_index) @@ -433,9 +686,10 @@ impl JsString { // 9. Set cp to ! UTF16SurrogatePairToCodePoint(first, second). // We can skip the checks and instead use the `char::decode_utf16` function to take care of that for us. - let code_point = self + let v = self.to_vec(); + let code_point = v .get(position..=position + 1) - .unwrap_or(&self[position..=position]); + .unwrap_or(&v[position..=position]); match char::decode_utf16(code_point.iter().copied()) .next() @@ -528,8 +782,8 @@ impl JsString { /// # Panics /// /// Panics if `try_allocate_inner` returns `Err`. - fn allocate_inner(str_len: usize) -> NonNull { - match Self::try_allocate_inner(str_len) { + fn allocate_inner(str_len: usize, ascii: bool) -> NonNull { + match Self::try_allocate_inner(str_len, ascii) { Ok(v) => v, Err(None) => alloc_overflow(), Err(Some(layout)) => std::alloc::handle_alloc_error(layout), @@ -544,11 +798,18 @@ impl JsString { /// /// Returns `Err(None)` on integer overflows `usize::MAX`. /// Returns `Err(Some(Layout))` on allocation error. - fn try_allocate_inner(str_len: usize) -> Result, Option> { - let (layout, offset) = Layout::array::(str_len) - .and_then(|arr| Layout::new::().extend(arr)) - .map(|(layout, offset)| (layout.pad_to_align(), offset)) - .map_err(|_| None)?; + fn try_allocate_inner( + str_len: usize, + ascii: bool, + ) -> Result, Option> { + let (layout, offset) = if ascii { + Layout::array::(str_len) + } else { + Layout::array::(str_len) + } + .and_then(|arr| Layout::new::().extend(arr)) + .map(|(layout, offset)| (layout.pad_to_align(), offset)) + .map_err(|_| None)?; debug_assert_eq!(offset, DATA_OFFSET); @@ -571,6 +832,7 @@ impl JsString { inner.as_ptr().write(RawJsString { len: str_len, refcount: Cell::new(1), + flags: usize::from(ascii), data: [0; 0], }); } @@ -596,9 +858,9 @@ impl JsString { } /// Creates a new [`JsString`] from `data`, without checking if the string is in the interner. - fn from_slice_skip_interning(string: &[u16]) -> Self { + fn from_slice_skip_interning(string: JsStr<'_>) -> Self { let count = string.len(); - let ptr = Self::allocate_inner(count); + let ptr = Self::allocate_inner(count, string.is_ascii()); // SAFETY: `allocate_inner` guarantees that `ptr` is a valid pointer. let data = unsafe { addr_of_mut!((*ptr.as_ptr()).data) }; @@ -611,24 +873,91 @@ impl JsString { // - `allocate_inner` must return a valid pointer to newly allocated memory, meaning `ptr` // and `data` should never overlap. unsafe { - ptr::copy_nonoverlapping(string.as_ptr(), data.cast(), count); + match string { + JsStr::Ascii(string) => { + ptr::copy_nonoverlapping(string.as_ptr(), data.cast::(), count); + } + JsStr::U16(string) => { + assert!(!is_ascii(string), "should be u16 not ascii"); + ptr::copy_nonoverlapping(string.as_ptr(), data.cast::(), count); + } + } } Self { // Safety: `allocate_inner` guarantees `ptr` is a valid heap pointer. ptr: Tagged::from_non_null(ptr), } } -} -impl AsRef<[u16]> for JsString { - fn as_ref(&self) -> &[u16] { - self + #[inline] + #[must_use] + pub fn len(&self) -> usize { + match self.ptr.unwrap() { + UnwrappedTagged::Ptr(h) => { + // SAFETY: + // - The `RawJsString` type has all the necessary information to reconstruct a valid + // slice (length and starting pointer). + // + // - We aligned `h.data` on allocation, and the block is of size `h.len`, so this + // should only generate valid reads. + // + // - The lifetime of `&Self::Target` is shorter than the lifetime of `self`, as seen + // by its signature, so this doesn't outlive `self`. + unsafe { + let h = h.as_ptr(); + (*h).len + } + } + UnwrappedTagged::Tag(index) => { + // SAFETY: all static strings are valid indices on `STATIC_JS_STRINGS`, so `get` should always + // return `Some`. + unsafe { StaticJsStrings::get(index).unwrap_unchecked().len() } + } + } + } + + #[inline] + #[must_use] + pub fn is_empty(&self) -> bool { + self.len() == 0 } -} -impl Borrow<[u16]> for JsString { - fn borrow(&self) -> &[u16] { - self + // pub fn get(&self, index: I) -> Option<::Owned> + // where + // I: SliceIndex<[u16]>, + // >::Output: ToOwned, + // { + // match self.as_slice() { + // StringSlice::Ascii(v) => v.get(index).map(ToOwned::to_owned), + // StringSlice::U16(v) => v.get(index).map(ToOwned::to_owned), + // } + // } + + pub fn to_vec(&self) -> Vec { + match self.as_slice() { + JsStr::Ascii(v) => v.bytes().map(u16::from).collect(), + JsStr::U16(v) => v.to_vec(), + } + } + + #[must_use] + pub fn contains(&self, element: u8) -> bool { + match self.as_slice() { + JsStr::Ascii(v) => v.as_bytes().contains(&element), + JsStr::U16(v) => v.contains(&u16::from(element)), + } + } + + pub(crate) fn trim(&self) -> JsStr<'_> { + self.as_slice().trim() + } + + pub(crate) fn trim_start(&self) -> JsStr<'_> { + self.as_slice().trim_start() + } + + pub(crate) fn trim_end(&self) -> JsStr<'_> { + self.as_slice().trim_end() } } @@ -671,12 +1000,21 @@ impl Drop for JsString { // All the checks for the validity of the layout have already been made on `alloc_inner`, // so we can skip the unwrap. let layout = unsafe { - Layout::for_value(inner) - .extend(Layout::array::(inner.len).unwrap_unchecked()) - .unwrap_unchecked() - .0 - .pad_to_align() + if inner.flags == 0 { + Layout::for_value(inner) + .extend(Layout::array::(inner.len).unwrap_unchecked()) + .unwrap_unchecked() + .0 + .pad_to_align() + } else { + Layout::for_value(inner) + .extend(Layout::array::(inner.len).unwrap_unchecked()) + .unwrap_unchecked() + .0 + .pad_to_align() + } }; + // Safety: // If refcount is 0 and we call drop, that means this is the last `JsString` which // points to this memory allocation, so deallocating it is safe. @@ -687,72 +1025,73 @@ impl Drop for JsString { } } -impl std::fmt::Debug for JsString { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - std::char::decode_utf16(self.as_slice().to_owned()) - .map(|r| { - r.map_or_else( - |err| format!("<0x{:04x}>", err.unpaired_surrogate()), - String::from, - ) - }) - .collect::() - .fmt(f) +fn is_ascii(slice: &[u16]) -> bool { + for &element in slice { + if (element & 0b0111_1111) != element { + return false; + } } + true } -impl Deref for JsString { - type Target = [u16]; - - fn deref(&self) -> &Self::Target { - match self.ptr.unwrap() { - UnwrappedTagged::Ptr(h) => { - // SAFETY: - // - The `RawJsString` type has all the necessary information to reconstruct a valid - // slice (length and starting pointer). - // - // - We aligned `h.data` on allocation, and the block is of size `h.len`, so this - // should only generate valid reads. - // - // - The lifetime of `&Self::Target` is shorter than the lifetime of `self`, as seen - // by its signature, so this doesn't outlive `self`. - unsafe { - let h = h.as_ptr(); - std::slice::from_raw_parts(addr_of!((*h).data).cast(), (*h).len) - } - } - UnwrappedTagged::Tag(index) => { - // SAFETY: all static strings are valid indices on `STATIC_JS_STRINGS`, so `get` should always - // return `Some`. - unsafe { StaticJsStrings::get(index).unwrap_unchecked() } - } +impl ToStringEscaped for JsString { + #[inline] + fn to_string_escaped(&self) -> String { + match self.as_slice() { + JsStr::Ascii(v) => v.to_owned(), + JsStr::U16(v) => v.to_string_escaped(), } } } +impl std::fmt::Debug for JsString { + #[inline] + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + self.to_std_string_escaped().fmt(f) + } +} + impl Eq for JsString {} impl From<&[u16]> for JsString { + #[inline] fn from(s: &[u16]) -> Self { - StaticJsStrings::get_string(s).unwrap_or_else(|| Self::from_slice_skip_interning(s)) - } -} - -impl From> for JsString { - fn from(vec: Vec) -> Self { - Self::from(&vec[..]) + if is_ascii(s) { + let s = s.iter().copied().map(|c| c as u8).collect::>(); + // SAFETY: Already checked that it's ASCII, so this is safe. + let s = unsafe { std::str::from_utf8_unchecked(&s) }; + return StaticJsStrings::get_string(s) + .unwrap_or_else(|| Self::from_slice_skip_interning(JsStr::Ascii(s))); + } + Self::from_slice_skip_interning(JsStr::U16(s)) } } impl From<&str> for JsString { #[inline] fn from(s: &str) -> Self { - let s = s.encode_utf16().collect::>(); - - Self::from(&s[..]) + StaticJsStrings::get_string(s).unwrap_or_else(|| { + if s.is_ascii() { + Self::from_slice_skip_interning(JsStr::Ascii(s)) + } else { + let s = s.encode_utf16().collect::>(); + Self::from_slice_skip_interning(JsStr::U16(&s[..])) + } + }) } } +impl From<&[JsString]> for JsString { + fn from(value: &[JsString]) -> Self { + Self::concat_array( + &value + .iter() + .map(Self::as_slice) + .map(Into::into) + .collect::>()[..], + ) + } +} impl From for JsString { #[inline] fn from(s: String) -> Self { @@ -768,34 +1107,34 @@ impl From<&[u16; N]> for JsString { impl Hash for JsString { fn hash(&self, state: &mut H) { - self[..].hash(state); + self.as_slice().hash(state); } } -impl> Index for JsString { - type Output = I::Output; +// impl> Index for JsString { +// type Output = I::Output; - #[inline] - fn index(&self, index: I) -> &Self::Output { - Index::index(&**self, index) - } -} +// #[inline] +// fn index(&self, index: I) -> &Self::Output { +// Index::index(&**self, index) +// } +// } impl Ord for JsString { fn cmp(&self, other: &Self) -> std::cmp::Ordering { - self[..].cmp(other) + self.to_vec().cmp(&other.to_vec()) } } impl PartialEq for JsString { fn eq(&self, other: &Self) -> bool { - self[..] == other[..] + self.as_slice() == other.as_slice() } } impl PartialEq for [u16] { fn eq(&self, other: &JsString) -> bool { - self == &**other + self == &other.to_vec() } } @@ -807,7 +1146,7 @@ impl PartialEq for [u16; N] { impl PartialEq<[u16]> for JsString { fn eq(&self, other: &[u16]) -> bool { - &**self == other + &self.to_vec() == other } } @@ -819,6 +1158,10 @@ impl PartialEq<[u16; N]> for JsString { impl PartialEq for JsString { fn eq(&self, other: &str) -> bool { + if let JsStr::Ascii(s) = self.as_slice() { + return s == other; + } + let utf16 = self.code_points(); let mut utf8 = other.chars(); @@ -856,40 +1199,50 @@ impl FromStr for JsString { } /// Utility trait that adds trimming functionality to every `UTF-16` string. -pub(crate) trait Utf16Trim { +pub(crate) trait Utf16Trim: Sized { /// Trims both leading and trailing space from `self`. - fn trim(&self) -> &Self { + fn trim(&self) -> Self { self.trim_start().trim_end() } /// Trims all leading space from `self`. - fn trim_start(&self) -> &Self; + fn trim_start(&self) -> Self; /// Trims all trailing space from `self`. - fn trim_end(&self) -> &Self; + fn trim_end(&self) -> Self; } -impl Utf16Trim for [u16] { - fn trim_start(&self) -> &Self { - if let Some(left) = self.iter().copied().position(|r| { - !char::from_u32(u32::from(r)) - .map(is_trimmable_whitespace) - .unwrap_or_default() - }) { - &self[left..] - } else { - &[] +impl Utf16Trim for JsStr<'_> { + fn trim_start(&self) -> Self { + match self { + Self::Ascii(s) => JsStr::Ascii(s.trim_start()), + Self::U16(s) => JsStr::U16( + if let Some(left) = s.iter().copied().position(|r| { + !char::from_u32(u32::from(r)) + .map(is_trimmable_whitespace) + .unwrap_or_default() + }) { + &s[left..] + } else { + &[] + }, + ), } } - fn trim_end(&self) -> &Self { - if let Some(right) = self.iter().copied().rposition(|r| { - !char::from_u32(u32::from(r)) - .map(is_trimmable_whitespace) - .unwrap_or_default() - }) { - &self[..=right] - } else { - &[] + fn trim_end(&self) -> Self { + match self { + Self::Ascii(s) => JsStr::Ascii(s.trim_end()), + Self::U16(s) => JsStr::U16( + if let Some(right) = s.iter().copied().rposition(|r| { + !char::from_u32(u32::from(r)) + .map(is_trimmable_whitespace) + .unwrap_or_default() + }) { + &s[..=right] + } else { + &[] + }, + ), } } } @@ -937,7 +1290,7 @@ mod tests { #[test] fn empty() { let s = js_string!(); - assert_eq!(*s, "".encode_utf16().collect::>()); + assert_eq!(&s, utf16!("")); } #[test] @@ -1008,10 +1361,10 @@ mod tests { #[test] fn as_str() { - const HELLO: &str = "Hello"; + const HELLO: &[u16] = utf16!("Hello"); let x = js_string!(HELLO); - assert_eq!(*x, HELLO.encode_utf16().collect::>()); + assert_eq!(&x, HELLO); } #[test] @@ -1022,7 +1375,7 @@ mod tests { const HELLOWORLD: &[u16] = utf16!("Hello World!"); let x = js_string!(HELLOWORLD); - assert_eq!(&*x, HELLOWORLD); + assert_eq!(&x, HELLOWORLD); let mut hasher = DefaultHasher::new(); HELLOWORLD.hash(&mut hasher); diff --git a/boa_engine/src/symbol.rs b/boa_engine/src/symbol.rs index cd087d31ed0..316c9902aea 100644 --- a/boa_engine/src/symbol.rs +++ b/boa_engine/src/symbol.rs @@ -23,7 +23,7 @@ use crate::{ js_string, - string::{common::StaticJsStrings, utf16}, + string::common::StaticJsStrings, tagged::{Tagged, UnwrappedTagged}, JsString, }; @@ -214,7 +214,7 @@ impl JsSymbol { return wk.fn_name(); } self.description() - .map(|s| js_string!(utf16!("["), &*s, utf16!("]"))) + .map(|s| js_string!("[", s, "]")) .unwrap_or_default() } @@ -248,7 +248,7 @@ impl JsSymbol { pub fn descriptive_string(&self) -> JsString { self.description().as_ref().map_or_else( || js_string!("Symbol()"), - |desc| js_string!(utf16!("Symbol("), desc, utf16!(")")), + |desc| js_string!("Symbol(", desc, ")"), ) } diff --git a/boa_engine/src/value/conversions/serde_json.rs b/boa_engine/src/value/conversions/serde_json.rs index f4f73f63eeb..445b78a0b90 100644 --- a/boa_engine/src/value/conversions/serde_json.rs +++ b/boa_engine/src/value/conversions/serde_json.rs @@ -180,8 +180,8 @@ mod tests { use serde_json::json; use crate::object::JsArray; + use crate::JsValue; use crate::{js_string, run_test_actions, TestAction}; - use crate::{string::utf16, JsValue}; #[test] fn json_conversions() { @@ -209,20 +209,17 @@ mod tests { let value = JsValue::from_json(&json, ctx).unwrap(); let obj = value.as_object().unwrap(); - assert_eq!( - obj.get(utf16!("name"), ctx).unwrap(), - js_string!("John Doe").into() - ); - assert_eq!(obj.get(utf16!("age"), ctx).unwrap(), 43_i32.into()); - assert_eq!(obj.get(utf16!("minor"), ctx).unwrap(), false.into()); - assert_eq!(obj.get(utf16!("adult"), ctx).unwrap(), true.into()); + assert_eq!(obj.get("name", ctx).unwrap(), js_string!("John Doe").into()); + assert_eq!(obj.get("age", ctx).unwrap(), 43_i32.into()); + assert_eq!(obj.get("minor", ctx).unwrap(), false.into()); + assert_eq!(obj.get("adult", ctx).unwrap(), true.into()); { - let extra = obj.get(utf16!("extra"), ctx).unwrap(); + let extra = obj.get("extra", ctx).unwrap(); let extra = extra.as_object().unwrap(); - assert!(extra.get(utf16!("address"), ctx).unwrap().is_null()); + assert!(extra.get("address", ctx).unwrap().is_null()); } { - let phones = obj.get(utf16!("phones"), ctx).unwrap(); + let phones = obj.get("phones", ctx).unwrap(); let phones = phones.as_object().unwrap(); let arr = JsArray::from_object(phones.clone()).unwrap(); diff --git a/boa_engine/src/value/display.rs b/boa_engine/src/value/display.rs index 1cdff70f63a..e6cec33873b 100644 --- a/boa_engine/src/value/display.rs +++ b/boa_engine/src/value/display.rs @@ -1,8 +1,8 @@ use std::borrow::Cow; use crate::{ - builtins::promise::PromiseState, object::ObjectKind, property::PropertyDescriptor, - string::utf16, JsError, JsString, + builtins::promise::PromiseState, object::ObjectKind, property::PropertyDescriptor, JsError, + JsString, }; use super::{fmt, Display, HashSet, JsValue}; @@ -117,7 +117,7 @@ pub(crate) fn log_string_from(x: &JsValue, print_internals: bool, print_children let len = v .borrow() .properties() - .get(&utf16!("length").into()) + .get(&"length".into()) .expect("array object must have 'length' property") // FIXME: handle accessor descriptors .expect_value() @@ -196,7 +196,7 @@ pub(crate) fn log_string_from(x: &JsValue, print_internals: bool, print_children } ObjectKind::Error(_) => { let name: Cow<'static, str> = v - .get_property(&utf16!("name").into()) + .get_property(&"name".into()) .as_ref() .and_then(PropertyDescriptor::value) .map_or_else( @@ -211,7 +211,7 @@ pub(crate) fn log_string_from(x: &JsValue, print_internals: bool, print_children }, ); let message = v - .get_property(&utf16!("message").into()) + .get_property(&"message".into()) .as_ref() .and_then(PropertyDescriptor::value) .map(|v| { diff --git a/boa_engine/src/value/tests.rs b/boa_engine/src/value/tests.rs index a99deb4e601..5c2444c820e 100644 --- a/boa_engine/src/value/tests.rs +++ b/boa_engine/src/value/tests.rs @@ -1,4 +1,3 @@ -use boa_macros::utf16; use indoc::indoc; use super::*; @@ -675,16 +674,13 @@ fn to_int32() { #[test] fn to_string() { run_test_actions([TestAction::inspect_context(|ctx| { - assert_eq!(&JsValue::null().to_string(ctx).unwrap(), utf16!("null")); - assert_eq!( - &JsValue::undefined().to_string(ctx).unwrap(), - utf16!("undefined") - ); - assert_eq!(&JsValue::new(55).to_string(ctx).unwrap(), utf16!("55")); - assert_eq!(&JsValue::new(55.0).to_string(ctx).unwrap(), utf16!("55")); + assert_eq!(&JsValue::null().to_string(ctx).unwrap(), "null"); + assert_eq!(&JsValue::undefined().to_string(ctx).unwrap(), "undefined"); + assert_eq!(&JsValue::new(55).to_string(ctx).unwrap(), "55"); + assert_eq!(&JsValue::new(55.0).to_string(ctx).unwrap(), "55"); assert_eq!( &JsValue::new(js_string!("hello")).to_string(ctx).unwrap(), - utf16!("hello") + "hello" ); })]); } diff --git a/boa_engine/src/vm/code_block.rs b/boa_engine/src/vm/code_block.rs index df17b441e38..618ce395192 100644 --- a/boa_engine/src/vm/code_block.rs +++ b/boa_engine/src/vm/code_block.rs @@ -11,7 +11,6 @@ use crate::{ error::JsNativeError, object::{internal_methods::get_prototype_from_constructor, JsObject, ObjectData, PROTOTYPE}, property::PropertyDescriptor, - string::utf16, vm::CallFrame, Context, JsError, JsResult, JsString, JsValue, }; @@ -998,10 +997,10 @@ pub(crate) fn create_generator_function_object( .define_property_or_throw(PROTOTYPE, prototype_property, context) .expect("failed to define the prototype property of the generator function"); constructor - .define_property_or_throw(utf16!("name"), name_property, context) + .define_property_or_throw("name", name_property, context) .expect("failed to define the name property of the generator function"); constructor - .define_property_or_throw(utf16!("length"), length_property, context) + .define_property_or_throw("length", length_property, context) .expect("failed to define the length property of the generator function"); constructor diff --git a/boa_engine/src/vm/flowgraph/mod.rs b/boa_engine/src/vm/flowgraph/mod.rs index 5152f1b200d..2ae5a02cced 100644 --- a/boa_engine/src/vm/flowgraph/mod.rs +++ b/boa_engine/src/vm/flowgraph/mod.rs @@ -2,7 +2,6 @@ use crate::vm::CodeBlock; use boa_interner::Interner; -use boa_macros::utf16; mod color; mod edge; @@ -21,7 +20,7 @@ impl CodeBlock { #[allow(clippy::match_same_arms)] pub fn to_graph(&self, interner: &Interner, graph: &mut SubGraph) { // Have to remove any invalid graph chars like `<` or `>`. - let name = if self.name() == utf16!("
") { + let name = if self.name() == "
" { "__main__".to_string() } else { self.name().to_std_string_escaped() diff --git a/boa_engine/src/vm/opcode/call/mod.rs b/boa_engine/src/vm/opcode/call/mod.rs index cfb3baa4bfc..dd101fffff3 100644 --- a/boa_engine/src/vm/opcode/call/mod.rs +++ b/boa_engine/src/vm/opcode/call/mod.rs @@ -295,7 +295,9 @@ impl Operation for ImportCall { panic!("referrer cannot be a synthetic module"); }; - let sym = context.interner_mut().get_or_intern(&*specifier); + let sym = context + .interner_mut() + .get_or_intern(specifier.as_slice().as_str_ref()); let mut loaded_modules = src.loaded_modules().borrow_mut(); diff --git a/boa_engine/src/vm/opcode/concat/mod.rs b/boa_engine/src/vm/opcode/concat/mod.rs index 5ebb102f8c3..03f6485b801 100644 --- a/boa_engine/src/vm/opcode/concat/mod.rs +++ b/boa_engine/src/vm/opcode/concat/mod.rs @@ -21,7 +21,8 @@ impl ConcatToString { &strings .iter() .map(JsString::as_slice) - .collect::>(), + .map(Into::into) + .collect::>(), ); context.vm.push(s); Ok(CompletionType::Normal) diff --git a/boa_engine/src/vm/opcode/generator/mod.rs b/boa_engine/src/vm/opcode/generator/mod.rs index c3b5bc7e574..bd4d312950d 100644 --- a/boa_engine/src/vm/opcode/generator/mod.rs +++ b/boa_engine/src/vm/opcode/generator/mod.rs @@ -10,7 +10,6 @@ use crate::{ environments::EnvironmentStack, error::JsNativeError, object::{ObjectData, PROTOTYPE}, - string::utf16, vm::{ call_frame::GeneratorResumeKind, opcode::{Operation, ReThrow}, @@ -263,9 +262,7 @@ impl Operation for GeneratorDelegateNext { context.vm.push(GeneratorResumeKind::Normal); } GeneratorResumeKind::Throw => { - let throw = iterator_record - .iterator() - .get_method(utf16!("throw"), context)?; + let throw = iterator_record.iterator().get_method("throw", context)?; if let Some(throw) = throw { let result = throw.call( &iterator_record.iterator().clone().into(), @@ -284,9 +281,7 @@ impl Operation for GeneratorDelegateNext { } } GeneratorResumeKind::Return => { - let r#return = iterator_record - .iterator() - .get_method(utf16!("return"), context)?; + let r#return = iterator_record.iterator().get_method("return", context)?; if let Some(r#return) = r#return { let result = r#return.call( &iterator_record.iterator().clone().into(), diff --git a/boa_engine/src/vm/opcode/iteration/for_in.rs b/boa_engine/src/vm/opcode/iteration/for_in.rs index 6f26cd0ddbb..443e290b727 100644 --- a/boa_engine/src/vm/opcode/iteration/for_in.rs +++ b/boa_engine/src/vm/opcode/iteration/for_in.rs @@ -1,6 +1,5 @@ use crate::{ builtins::{iterable::IteratorRecord, object::for_in_iterator::ForInIterator}, - js_string, vm::{opcode::Operation, CompletionType}, Context, JsResult, JsValue, }; @@ -22,7 +21,7 @@ impl Operation for CreateForInIterator { let object = object.to_object(context)?; let iterator = ForInIterator::create_for_in_iterator(JsValue::new(object), context); let next_method = iterator - .get(js_string!("next"), context) + .get("next", context) .expect("ForInIterator must have a `next` method"); context diff --git a/boa_engine/src/vm/opcode/iteration/iterator.rs b/boa_engine/src/vm/opcode/iteration/iterator.rs index f0083ec710d..af08a3b1936 100644 --- a/boa_engine/src/vm/opcode/iteration/iterator.rs +++ b/boa_engine/src/vm/opcode/iteration/iterator.rs @@ -2,7 +2,6 @@ use std::matches; use crate::{ builtins::{iterable::create_iter_result_object, Array}, - js_string, vm::{opcode::Operation, CompletionType, GeneratorResumeKind}, Context, JsResult, }; @@ -234,10 +233,7 @@ impl Operation for IteratorReturn { .pop() .expect("iterator on the call frame must exist"); - let Some(ret) = record - .iterator() - .get_method(js_string!("return"), context)? - else { + let Some(ret) = record.iterator().get_method("return", context)? else { context.vm.push(false); return Ok(CompletionType::Normal); }; diff --git a/boa_engine/src/vm/opcode/push/array.rs b/boa_engine/src/vm/opcode/push/array.rs index 3783a10c6cb..119b13d754b 100644 --- a/boa_engine/src/vm/opcode/push/array.rs +++ b/boa_engine/src/vm/opcode/push/array.rs @@ -1,7 +1,6 @@ use crate::{ builtins::Array, object::ObjectData, - string::utf16, vm::{opcode::Operation, CompletionType}, Context, JsResult, JsValue, }; @@ -72,7 +71,7 @@ impl Operation for PushElisionToArray { .length_of_array_like(context) .expect("arrays should always have a 'length' property"); - o.set(utf16!("length"), len + 1, true, context)?; + o.set("length", len + 1, true, context)?; context.vm.push(array); Ok(CompletionType::Normal) } diff --git a/boa_engine/src/vm/opcode/push/class/private.rs b/boa_engine/src/vm/opcode/push/class/private.rs index 0cfe63d255f..54217889879 100644 --- a/boa_engine/src/vm/opcode/push/class/private.rs +++ b/boa_engine/src/vm/opcode/push/class/private.rs @@ -2,7 +2,6 @@ use crate::{ js_string, object::PrivateElement, property::PropertyDescriptor, - string::utf16, vm::{opcode::Operation, CompletionType}, Context, JsResult, }; @@ -21,7 +20,7 @@ impl PushClassPrivateMethod { let method = context.vm.pop(); let method_object = method.as_callable().expect("method must be callable"); - let name_string = js_string!(utf16!("#"), &name); + let name_string = js_string!("#", &name); let desc = PropertyDescriptor::builder() .value(name_string) .writable(false) @@ -29,7 +28,7 @@ impl PushClassPrivateMethod { .configurable(true) .build(); method_object - .__define_own_property__(&utf16!("name").into(), desc, context) + .__define_own_property__(&"name".into(), desc, context) .expect("failed to set name property on private method"); let class = context.vm.pop(); diff --git a/boa_engine/src/vm/opcode/set/private.rs b/boa_engine/src/vm/opcode/set/private.rs index b2fd5151b57..22c4c1fa655 100644 --- a/boa_engine/src/vm/opcode/set/private.rs +++ b/boa_engine/src/vm/opcode/set/private.rs @@ -2,7 +2,6 @@ use crate::{ js_string, object::PrivateElement, property::PropertyDescriptor, - string::utf16, vm::{opcode::Operation, CompletionType}, Context, JsResult, }; @@ -112,7 +111,7 @@ impl SetPrivateMethod { let value = context.vm.pop(); let value = value.as_callable().expect("method must be callable"); - let name_string = js_string!(utf16!("#"), &name); + let name_string = js_string!("#", &name); let desc = PropertyDescriptor::builder() .value(name_string) .writable(false) @@ -120,7 +119,7 @@ impl SetPrivateMethod { .configurable(true) .build(); value - .__define_own_property__(&js_string!("name").into(), desc, context) + .__define_own_property__(&"name".into(), desc, context) .expect("failed to set name property on private method"); let object = context.vm.pop(); diff --git a/boa_engine/src/vm/opcode/set/property.rs b/boa_engine/src/vm/opcode/set/property.rs index cd044840ca1..986870e20ca 100644 --- a/boa_engine/src/vm/opcode/set/property.rs +++ b/boa_engine/src/vm/opcode/set/property.rs @@ -1,5 +1,3 @@ -use boa_macros::utf16; - use crate::{ builtins::function::set_function_name, property::{PropertyDescriptor, PropertyKey}, @@ -117,7 +115,7 @@ impl Operation for SetPropertyByValue { context.vm.push(value); let len = dense_elements.len() as u32; - let length_key = PropertyKey::from(utf16!("length")); + let length_key = PropertyKey::from("length"); let length = object_borrowed .properties_mut() .get(&length_key) diff --git a/boa_engine/src/vm/opcode/templates/mod.rs b/boa_engine/src/vm/opcode/templates/mod.rs index ebb58fa7648..8661f58818f 100644 --- a/boa_engine/src/vm/opcode/templates/mod.rs +++ b/boa_engine/src/vm/opcode/templates/mod.rs @@ -5,7 +5,6 @@ use crate::{ vm::{opcode::Operation, CompletionType}, Context, JsResult, }; -use boa_macros::utf16; /// `TemplateLookup` implements the Opcode Operation for `Opcode::TemplateLookup` /// @@ -78,7 +77,7 @@ impl TemplateCreate { .expect("should never fail per spec"); template .define_property_or_throw( - utf16!("raw"), + "raw", PropertyDescriptor::builder() .value(raw_obj) .writable(false) diff --git a/boa_examples/src/bin/classes.rs b/boa_examples/src/bin/classes.rs index 48144250daa..a83b8aa60f0 100644 --- a/boa_examples/src/bin/classes.rs +++ b/boa_examples/src/bin/classes.rs @@ -89,18 +89,14 @@ impl Class for Person { // We add a inheritable method `sayHello` with `0` arguments of length. // // This function is added to the `Person` prototype. - class.method( - js_string!("sayHello"), - 0, - NativeFunction::from_fn_ptr(Self::say_hello), - ); + class.method("sayHello", 0, NativeFunction::from_fn_ptr(Self::say_hello)); // We add a static method `is` using a closure, but it must be convertible // to a `NativeFunction`. The `NativeFunction` API has more information on which type of // Rust functions can be used to create `NativeFunction`s. // // This function is added to the `Person` class. class.static_method( - js_string!("is"), + "is", 1, NativeFunction::from_fn_ptr(|_this, args, _ctx| { if let Some(arg) = args.get(0) { @@ -117,12 +113,12 @@ impl Class for Person { // We add an `"inheritedProperty"` property to the prototype of `Person` with // a value of `10` and default attribute flags `READONLY`, `NON_ENUMERABLE` and `PERMANENT`. - class.property(js_string!("inheritedProperty"), 10, Attribute::default()); + class.property("inheritedProperty", 10, Attribute::default()); // Finally, we add a `"staticProperty"` property to `Person` with a value // of `"Im a static property"` and attribute flags `WRITABLE`, `ENUMERABLE` and `PERMANENT`. class.static_property( - js_string!("staticProperty"), + "staticProperty", js_string!("Im a static property"), Attribute::WRITABLE | Attribute::ENUMERABLE | Attribute::PERMANENT, ); diff --git a/boa_examples/src/bin/closures.rs b/boa_examples/src/bin/closures.rs index 8548f79a5e5..cf527775642 100644 --- a/boa_examples/src/bin/closures.rs +++ b/boa_examples/src/bin/closures.rs @@ -8,7 +8,6 @@ use boa_engine::{ native_function::NativeFunction, object::{builtins::JsArray, FunctionObjectBuilder, JsObject}, property::{Attribute, PropertyDescriptor}, - string::utf16, Context, JsError, JsNativeError, JsString, JsValue, Source, }; use boa_gc::{Finalize, GcRefCell, Trace}; @@ -53,7 +52,7 @@ fn main() -> Result<(), JsError> { // We create a new `JsObject` with some data let object = JsObject::with_object_proto(context.intrinsics()); object.define_property_or_throw( - js_string!("name"), + "name", PropertyDescriptor::builder() .value(js_string!("Boa dev")) .writable(false) @@ -78,18 +77,18 @@ fn main() -> Result<(), JsError> { let BigStruct { greeting, object } = &mut *captures; println!("Called `createMessage`"); // We obtain the `name` property of `captures.object` - let name = object.get(js_string!("name"), context)?; + let name = object.get("name", context)?; // We create a new message from our captured variable. let message = js_string!( - utf16!("message from `"), + "message from `", &name.to_string(context)?, - utf16!("`: "), - greeting + "`: ", + &*greeting ); // We can also mutate the moved data inside the closure. - captures.greeting = js_string!(greeting, utf16!(" Hello!")); + captures.greeting = js_string!(&*greeting, " Hello!"); println!("{}", message.to_std_string_escaped()); println!(); @@ -112,7 +111,7 @@ fn main() -> Result<(), JsError> { .register_global_property( // We set the key to access the function the same as its name for // consistency, but it may be different if needed. - js_string!("createMessage"), + "createMessage", // We pass `js_function` as a property value. js_function, // We assign to the "createMessage" property the desired attributes. diff --git a/boa_examples/src/bin/jsarray.rs b/boa_examples/src/bin/jsarray.rs index a750f16f06d..67c68dc27a1 100644 --- a/boa_examples/src/bin/jsarray.rs +++ b/boa_examples/src/bin/jsarray.rs @@ -4,7 +4,6 @@ use boa_engine::{ js_string, native_function::NativeFunction, object::{builtins::JsArray, FunctionObjectBuilder}, - string::utf16, Context, JsResult, JsValue, }; @@ -58,12 +57,12 @@ fn main() -> JsResult<()> { // Join the array with an optional separator (default ","). let joined_array = array.join(None, context)?; - assert_eq!(&joined_array, utf16!("14,13,12,11,10")); + assert_eq!(&joined_array, "14,13,12,11,10"); array.fill(false, Some(1), Some(4), context)?; let joined_array = array.join(Some("::".into()), context)?; - assert_eq!(&joined_array, utf16!("14::false::false::false::10")); + assert_eq!(&joined_array, "14::false::false::false::10"); let filter_callback = FunctionObjectBuilder::new( context.realm(), @@ -97,7 +96,7 @@ fn main() -> JsResult<()> { .concat(&[another_array.into()], context)? // [ 100, 196, 1, 2, 3, 4, 5 ] .slice(Some(1), Some(5), context)?; // [ 196, 1, 2, 3 ] - assert_eq!(&chained_array.join(None, context)?, utf16!("196,1,2,3")); + assert_eq!(&chained_array.join(None, context)?, "196,1,2,3"); let reduce_callback = FunctionObjectBuilder::new( context.realm(), diff --git a/boa_examples/src/bin/jsarraybuffer.rs b/boa_examples/src/bin/jsarraybuffer.rs index 26df61bac8c..34503d5e764 100644 --- a/boa_examples/src/bin/jsarraybuffer.rs +++ b/boa_examples/src/bin/jsarraybuffer.rs @@ -1,7 +1,6 @@ // This example shows how to manipulate a Javascript array using Rust code. use boa_engine::{ - js_string, object::builtins::{JsArrayBuffer, JsDataView, JsUint32Array, JsUint8Array}, property::Attribute, Context, JsResult, JsValue, @@ -53,7 +52,7 @@ fn main() -> JsResult<()> { // We can also register it as a global property context .register_global_property( - js_string!("myArrayBuffer"), + "myArrayBuffer", array_buffer, Attribute::WRITABLE | Attribute::ENUMERABLE | Attribute::CONFIGURABLE, ) diff --git a/boa_examples/src/bin/modules.rs b/boa_examples/src/bin/modules.rs index e6c22600caf..f3f85add724 100644 --- a/boa_examples/src/bin/modules.rs +++ b/boa_examples/src/bin/modules.rs @@ -2,7 +2,6 @@ use std::{error::Error, path::Path}; use boa_engine::{ builtins::promise::PromiseState, - js_string, module::{ModuleLoader, SimpleModuleLoader}, object::FunctionObjectBuilder, Context, JsError, JsNativeError, JsValue, Module, NativeFunction, @@ -112,17 +111,14 @@ fn main() -> Result<(), Box> { // We can access the full namespace of the module with all its exports. let namespace = module.namespace(context); - let result = namespace.get(js_string!("result"), context)?; + let result = namespace.get("result", context)?; println!("result = {}", result.display()); - assert_eq!( - namespace.get(js_string!("result"), context)?, - JsValue::from(5) - ); + assert_eq!(namespace.get("result", context)?, JsValue::from(5)); let mix = namespace - .get(js_string!("mix"), context)? + .get("mix", context)? .as_callable() .cloned() .ok_or_else(|| JsNativeError::typ().with_message("mix export wasn't a function!"))?; diff --git a/boa_examples/src/bin/synthetic.rs b/boa_examples/src/bin/synthetic.rs index 54564cf340a..9f775247f49 100644 --- a/boa_examples/src/bin/synthetic.rs +++ b/boa_examples/src/bin/synthetic.rs @@ -77,17 +77,14 @@ fn main() -> Result<(), Box> { // We can access the full namespace of the module with all its exports. let namespace = module.namespace(context); - let result = namespace.get(js_string!("result"), context)?; + let result = namespace.get("result", context)?; println!("result = {}", result.display()); - assert_eq!( - namespace.get(js_string!("result"), context)?, - JsValue::from(5) - ); + assert_eq!(namespace.get("result", context)?, JsValue::from(5)); let mix = namespace - .get(js_string!("mix"), context)? + .get("mix", context)? .as_callable() .cloned() .ok_or_else(|| JsNativeError::typ().with_message("mix export wasn't a function!"))?; @@ -111,7 +108,7 @@ fn create_operations_module(context: &mut Context<'_>) -> Module { }), ) .length(2) - .name(js_string!("sum")) + .name("sum") .build(); let sub = FunctionObjectBuilder::new( context.realm(), @@ -120,7 +117,7 @@ fn create_operations_module(context: &mut Context<'_>) -> Module { }), ) .length(2) - .name(js_string!("sub")) + .name("sub") .build(); let mult = FunctionObjectBuilder::new( context.realm(), @@ -129,7 +126,7 @@ fn create_operations_module(context: &mut Context<'_>) -> Module { }), ) .length(2) - .name(js_string!("mult")) + .name("mult") .build(); let div = FunctionObjectBuilder::new( context.realm(), @@ -138,7 +135,7 @@ fn create_operations_module(context: &mut Context<'_>) -> Module { }), ) .length(2) - .name(js_string!("div")) + .name("div") .build(); let sqrt = FunctionObjectBuilder::new( context.realm(), @@ -148,7 +145,7 @@ fn create_operations_module(context: &mut Context<'_>) -> Module { }), ) .length(1) - .name(js_string!("sqrt")) + .name("sqrt") .build(); Module::synthetic( diff --git a/boa_runtime/src/console/mod.rs b/boa_runtime/src/console/mod.rs index bb5f72a9c5f..4be185b94dd 100644 --- a/boa_runtime/src/console/mod.rs +++ b/boa_runtime/src/console/mod.rs @@ -18,12 +18,10 @@ use boa_engine::{ js_string, native_function::NativeFunction, object::{JsObject, ObjectInitializer}, - string::utf16, value::{JsValue, Numeric}, Context, JsArgs, JsResult, JsString, }; use boa_gc::{Finalize, Trace}; -// use boa_profiler::Profiler; use rustc_hash::FxHashMap; use std::{cell::RefCell, rc::Rc, time::SystemTime}; @@ -164,92 +162,40 @@ impl Console { let state = Rc::new(RefCell::new(Self::default())); ObjectInitializer::with_native(Self::default(), context) - .function( - console_method(Self::assert, state.clone()), - js_string!("assert"), - 0, - ) - .function( - console_method_mut(Self::clear, state.clone()), - js_string!("clear"), - 0, - ) - .function( - console_method(Self::debug, state.clone()), - js_string!("debug"), - 0, - ) - .function( - console_method(Self::error, state.clone()), - js_string!("error"), - 0, - ) - .function( - console_method(Self::info, state.clone()), - js_string!("info"), - 0, - ) - .function( - console_method(Self::log, state.clone()), - js_string!("log"), - 0, - ) - .function( - console_method(Self::trace, state.clone()), - js_string!("trace"), - 0, - ) - .function( - console_method(Self::warn, state.clone()), - js_string!("warn"), - 0, - ) - .function( - console_method_mut(Self::count, state.clone()), - js_string!("count"), - 0, - ) + .function(console_method(Self::assert, state.clone()), "assert", 0) + .function(console_method_mut(Self::clear, state.clone()), "clear", 0) + .function(console_method(Self::debug, state.clone()), "debug", 0) + .function(console_method(Self::error, state.clone()), "error", 0) + .function(console_method(Self::info, state.clone()), "info", 0) + .function(console_method(Self::log, state.clone()), "log", 0) + .function(console_method(Self::trace, state.clone()), "trace", 0) + .function(console_method(Self::warn, state.clone()), "warn", 0) + .function(console_method_mut(Self::count, state.clone()), "count", 0) .function( console_method_mut(Self::count_reset, state.clone()), - js_string!("countReset"), - 0, - ) - .function( - console_method_mut(Self::group, state.clone()), - js_string!("group"), + "countReset", 0, ) + .function(console_method_mut(Self::group, state.clone()), "group", 0) .function( console_method_mut(Self::group, state.clone()), - js_string!("groupCollapsed"), + "groupCollapsed", 0, ) .function( console_method_mut(Self::group_end, state.clone()), - js_string!("groupEnd"), - 0, - ) - .function( - console_method_mut(Self::time, state.clone()), - js_string!("time"), - 0, - ) - .function( - console_method(Self::time_log, state.clone()), - js_string!("timeLog"), + "groupEnd", 0, ) + .function(console_method_mut(Self::time, state.clone()), "time", 0) + .function(console_method(Self::time_log, state.clone()), "timeLog", 0) .function( console_method_mut(Self::time_end, state.clone()), - js_string!("timeEnd"), - 0, - ) - .function( - console_method(Self::dir, state.clone()), - js_string!("dir"), + "timeEnd", 0, ) - .function(console_method(Self::dir, state), js_string!("dirxml"), 0) + .function(console_method(Self::dir, state.clone()), "dir", 0) + .function(console_method(Self::dir, state), "dirxml", 0) .build() } @@ -281,7 +227,7 @@ impl Console { args.insert(0, JsValue::new(message)); } else { let value: Vec = args[0].display().to_string().encode_utf16().collect(); - let concat = js_string!(&message, utf16!(": "), &value); + let concat = js_string!(&message, ": ", &value[..]); args[0] = JsValue::new(concat); } diff --git a/boa_tester/src/exec/js262.rs b/boa_tester/src/exec/js262.rs index b66d9ed1661..2002d8820d8 100644 --- a/boa_tester/src/exec/js262.rs +++ b/boa_tester/src/exec/js262.rs @@ -1,5 +1,4 @@ use boa_engine::{ - js_string, native_function::NativeFunction, object::{JsObject, ObjectInitializer}, property::Attribute, @@ -11,24 +10,16 @@ pub(super) fn register_js262(context: &mut Context<'_>) -> JsObject { let global_obj = context.global_object(); let js262 = ObjectInitializer::new(context) - .function( - NativeFunction::from_fn_ptr(create_realm), - js_string!("createRealm"), - 0, - ) + .function(NativeFunction::from_fn_ptr(create_realm), "createRealm", 0) .function( NativeFunction::from_fn_ptr(detach_array_buffer), - js_string!("detachArrayBuffer"), + "detachArrayBuffer", 2, ) - .function( - NativeFunction::from_fn_ptr(eval_script), - js_string!("evalScript"), - 1, - ) - .function(NativeFunction::from_fn_ptr(gc), js_string!("gc"), 0) + .function(NativeFunction::from_fn_ptr(eval_script), "evalScript", 1) + .function(NativeFunction::from_fn_ptr(gc), "gc", 0) .property( - js_string!("global"), + "global", global_obj, Attribute::WRITABLE | Attribute::CONFIGURABLE, ) @@ -37,7 +28,7 @@ pub(super) fn register_js262(context: &mut Context<'_>) -> JsObject { context .register_global_property( - js_string!("$262"), + "$262", js262.clone(), Attribute::WRITABLE | Attribute::CONFIGURABLE, )