From ffc654680cd5fbbe9a5aaf27ca5961dec2da2ff2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Juli=C3=A1n=20Espina?= Date: Mon, 21 Oct 2024 16:51:06 -0600 Subject: [PATCH] Switch `allow` to `expect` --- cli/src/debug/mod.rs | 2 +- cli/src/helper.rs | 6 +- cli/src/main.rs | 12 +- core/ast/src/lib.rs | 2 +- core/ast/src/scope.rs | 8 +- core/ast/src/scope_analyzer.rs | 7 +- core/ast/src/visitor.rs | 4 +- core/engine/output.rs | 2402 +++++++++++++++++ core/engine/src/builtins/array/mod.rs | 11 +- core/engine/src/builtins/array_buffer/mod.rs | 4 +- .../src/builtins/array_buffer/shared.rs | 2 +- core/engine/src/builtins/bigint/mod.rs | 6 +- core/engine/src/builtins/boolean/mod.rs | 2 +- core/engine/src/builtins/builder.rs | 7 +- core/engine/src/builtins/date/mod.rs | 4 +- core/engine/src/builtins/error/mod.rs | 2 +- .../engine/src/builtins/function/arguments.rs | 6 +- core/engine/src/builtins/function/bound.rs | 4 +- core/engine/src/builtins/function/mod.rs | 4 +- core/engine/src/builtins/function/tests.rs | 2 +- core/engine/src/builtins/intl/collator/mod.rs | 2 +- .../src/builtins/intl/date_time_format.rs | 3 +- .../src/builtins/intl/list_format/mod.rs | 1 - .../builtins/intl/number_format/options.rs | 1 - .../src/builtins/intl/plural_rules/mod.rs | 1 - core/engine/src/builtins/map/mod.rs | 2 +- core/engine/src/builtins/math/mod.rs | 6 +- core/engine/src/builtins/mod.rs | 1 - .../engine/src/builtins/number/conversions.rs | 2 +- core/engine/src/builtins/number/globals.rs | 1 - core/engine/src/builtins/number/mod.rs | 30 +- core/engine/src/builtins/object/mod.rs | 2 - core/engine/src/builtins/options.rs | 4 +- core/engine/src/builtins/promise/mod.rs | 2 +- core/engine/src/builtins/promise/tests.rs | 2 +- core/engine/src/builtins/regexp/mod.rs | 5 +- core/engine/src/builtins/set/mod.rs | 2 +- core/engine/src/builtins/string/mod.rs | 3 +- core/engine/src/builtins/symbol/mod.rs | 1 - .../src/builtins/temporal/calendar/mod.rs | 2 +- core/engine/src/builtins/temporal/mod.rs | 3 +- core/engine/src/builtins/temporal/now.rs | 14 +- core/engine/src/builtins/temporal/options.rs | 2 +- .../src/builtins/temporal/time_zone/mod.rs | 2 +- .../src/builtins/typed_array/builtin.rs | 5 +- .../src/builtins/typed_array/element/mod.rs | 3 +- core/engine/src/builtins/typed_array/mod.rs | 2 +- .../engine/src/builtins/typed_array/object.rs | 2 +- core/engine/src/builtins/uri/mod.rs | 4 +- core/engine/src/bytecompiler/declarations.rs | 54 +- core/engine/src/bytecompiler/function.rs | 2 +- core/engine/src/bytecompiler/mod.rs | 15 +- core/engine/src/bytecompiler/module.rs | 2 +- core/engine/src/bytecompiler/register.rs | 2 +- .../src/bytecompiler/statement/continue.rs | 1 - core/engine/src/class.rs | 2 +- core/engine/src/context/mod.rs | 4 +- core/engine/src/host_defined.rs | 2 +- core/engine/src/job.rs | 2 +- core/engine/src/module/loader.rs | 2 +- core/engine/src/module/mod.rs | 5 +- core/engine/src/module/namespace.rs | 10 +- core/engine/src/module/source.rs | 3 - core/engine/src/module/synthetic.rs | 1 - core/engine/src/object/builtins/jsarray.rs | 4 +- core/engine/src/object/builtins/jspromise.rs | 6 +- .../src/object/builtins/jstypedarray.rs | 4 +- .../internal_methods/immutable_prototype.rs | 2 +- .../engine/src/object/internal_methods/mod.rs | 14 +- .../src/object/internal_methods/string.rs | 2 +- core/engine/src/object/jsobject.rs | 5 +- core/engine/src/object/operations.rs | 2 +- core/engine/src/object/property_map.rs | 1 - .../src/object/shape/shared_shape/mod.rs | 2 +- core/engine/src/optimizer/mod.rs | 2 +- core/engine/src/property/mod.rs | 1 - core/engine/src/script.rs | 4 +- core/engine/src/small_map/mod.rs | 5 +- core/engine/src/string.rs | 4 +- core/engine/src/symbol.rs | 2 +- core/engine/src/tagged.rs | 6 +- core/engine/src/tests/iterators.rs | 6 +- core/engine/src/tests/promise.rs | 2 +- core/engine/src/value/conversions/mod.rs | 2 +- core/engine/src/value/equality.rs | 2 +- core/engine/src/value/mod.rs | 3 +- core/engine/src/value/operations.rs | 2 +- core/engine/src/value/tests.rs | 4 +- core/engine/src/vm/call_frame/mod.rs | 4 +- core/engine/src/vm/completion_record.rs | 1 - core/engine/src/vm/flowgraph/color.rs | 2 +- core/engine/src/vm/flowgraph/mod.rs | 2 +- core/engine/src/vm/mod.rs | 5 +- .../src/vm/opcode/control_flow/return.rs | 6 +- core/engine/src/vm/opcode/define/mod.rs | 4 +- core/engine/src/vm/opcode/get/argument.rs | 2 +- core/engine/src/vm/opcode/get/function.rs | 2 +- core/engine/src/vm/opcode/global.rs | 2 - core/engine/src/vm/opcode/locals/mod.rs | 5 +- core/engine/src/vm/opcode/mod.rs | 6 +- core/engine/src/vm/opcode/push/class/field.rs | 2 +- .../src/vm/opcode/push/class/private.rs | 6 +- core/engine/src/vm/opcode/push/environment.rs | 2 +- core/engine/src/vm/opcode/push/literal.rs | 2 +- core/engine/src/vm/opcode/set/private.rs | 8 +- core/engine/src/vm/opcode/templates/mod.rs | 2 +- core/gc/src/cell.rs | 8 +- core/gc/src/pointers/gc.rs | 4 +- core/gc/src/pointers/mod.rs | 2 +- core/gc/src/pointers/weak_map.rs | 19 +- core/gc/src/trace.rs | 4 +- core/interner/src/sym.rs | 2 +- core/interop/src/into_js_function_impls.rs | 8 +- core/interop/src/lib.rs | 5 +- core/interop/src/loaders/cached.rs | 2 +- core/interop/src/loaders/embedded.rs | 2 +- core/interop/src/loaders/fallback.rs | 2 +- core/interop/src/macros.rs | 8 +- core/interop/tests/fibonacci.rs | 1 - core/macros/src/lib.rs | 61 +- core/parser/src/error/mod.rs | 2 +- core/parser/src/lexer/cursor.rs | 4 +- core/parser/src/lexer/mod.rs | 5 +- core/parser/src/lexer/number.rs | 10 +- core/parser/src/lexer/regex.rs | 2 +- core/parser/src/lexer/string.rs | 2 +- core/parser/src/parser/mod.rs | 2 +- .../parser/statement/declaration/import.rs | 1 - core/profiler/src/lib.rs | 22 +- core/runtime/src/console/mod.rs | 7 +- core/runtime/src/console/tests.rs | 2 +- core/runtime/src/lib.rs | 5 +- core/string/src/lib.rs | 7 +- core/string/src/str.rs | 4 +- core/string/src/tagged.rs | 3 +- examples/src/bin/derive.rs | 2 +- tests/fuzz/fuzz_targets/common.rs | 2 +- tests/tester/src/exec/js262.rs | 5 +- tests/tester/src/main.rs | 8 +- tests/tester/src/read.rs | 4 +- tests/tester/src/results.rs | 2 +- 141 files changed, 2708 insertions(+), 385 deletions(-) create mode 100644 core/engine/output.rs diff --git a/cli/src/debug/mod.rs b/cli/src/debug/mod.rs index a093f76a40..a69bb467a4 100644 --- a/cli/src/debug/mod.rs +++ b/cli/src/debug/mod.rs @@ -66,7 +66,7 @@ fn create_boa_object(context: &mut Context) -> JsObject { .build() } -#[allow(clippy::redundant_pub_crate)] +#[expect(clippy::redundant_pub_crate)] pub(crate) fn init_boa_debug_object(context: &mut Context) { let boa_object = create_boa_object(context); context diff --git a/cli/src/helper.rs b/cli/src/helper.rs index ae56c98f41..b94995a69b 100644 --- a/cli/src/helper.rs +++ b/cli/src/helper.rs @@ -35,7 +35,7 @@ const IDENTIFIER_COLOR: Color = Color::TrueColor { const READLINE_COLOR: Color = Color::Cyan; -#[allow(clippy::upper_case_acronyms, clippy::redundant_pub_crate)] +#[expect(clippy::redundant_pub_crate)] #[derive(Completer, Helper, Hinter)] pub(crate) struct RLHelper { highlighter: LineHighlighter, @@ -72,7 +72,7 @@ impl Highlighter for RLHelper { } // Must match signature of Highlighter::highlight_prompt, can't elide lifetimes. - #[allow(single_use_lifetimes)] + #[expect(single_use_lifetimes)] fn highlight_prompt<'b, 's: 'b, 'p: 'b>( &'s self, prompt: &'p str, @@ -169,7 +169,7 @@ impl Highlighter for LineHighlighter { impl Replacer for Colorizer { // Changing to map_or_else moves the handling of "identifier" after all other kinds, // which reads worse than this version. - #[allow(clippy::option_if_let_else)] + #[expect(clippy::option_if_let_else)] fn replace_append(&mut self, caps: &Captures<'_>, dst: &mut String) { let colored = if let Some(cap) = caps.name("identifier") { let cap = cap.as_str(); diff --git a/cli/src/main.rs b/cli/src/main.rs index 899b73f313..3a53399075 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -53,12 +53,12 @@ static ALLOC: dhat::Alloc = dhat::Alloc; /// CLI configuration for Boa. static CLI_HISTORY: &str = ".boa_history"; -// Added #[allow(clippy::option_option)] because to StructOpt an Option> -// is an optional argument that optionally takes a value ([--opt=[val]]). -// https://docs.rs/structopt/0.3.11/structopt/#type-magic #[derive(Debug, Parser)] #[command(author, version, about, name = "boa")] -#[allow(clippy::struct_excessive_bools)] // NOTE: Allow having more than 3 bools in struct +#[expect( + clippy::struct_excessive_bools, + reason = "Allow having more than 3 bools in struct" +)] struct Opt { /// The JavaScript file(s) to be evaluated. #[arg(name = "FILE", value_hint = ValueHint::FilePath)] @@ -77,7 +77,7 @@ struct Opt { value_enum, conflicts_with = "graph" )] - #[allow(clippy::option_option)] + #[expect(clippy::option_option)] dump_ast: Option>, /// Dump the AST to stdout with the given format. @@ -102,7 +102,7 @@ struct Opt { value_enum, group = "graph" )] - #[allow(clippy::option_option)] + #[expect(clippy::option_option)] flowgraph: Option>, /// Specifies the direction of the flowgraph. Default is top-top-bottom. diff --git a/core/ast/src/lib.rs b/core/ast/src/lib.rs index edaafdc570..b24fddd7ee 100644 --- a/core/ast/src/lib.rs +++ b/core/ast/src/lib.rs @@ -115,7 +115,7 @@ pub(crate) trait ToJsString { } impl ToJsString for Sym { - #[allow(clippy::cast_possible_truncation)] + #[expect(clippy::cast_possible_truncation)] fn to_js_string(&self, interner: &Interner) -> JsString { // TODO: Identify latin1 encodeable strings during parsing to avoid this check. let string = interner.resolve_expect(*self).utf16(); diff --git a/core/ast/src/scope.rs b/core/ast/src/scope.rs index 621189ee79..812d7797bf 100644 --- a/core/ast/src/scope.rs +++ b/core/ast/src/scope.rs @@ -7,7 +7,7 @@ use rustc_hash::FxHashMap; use std::{cell::RefCell, fmt::Debug, rc::Rc}; #[derive(Clone, Debug, PartialEq)] -#[allow(clippy::struct_excessive_bools)] +#[expect(clippy::struct_excessive_bools)] struct Binding { index: u32, mutable: bool, @@ -126,7 +126,7 @@ impl Scope { /// Returns the number of bindings in this scope. #[must_use] - #[allow(clippy::cast_possible_truncation)] + #[expect(clippy::cast_possible_truncation)] pub fn num_bindings(&self) -> u32 { self.inner.bindings.borrow().len() as u32 } @@ -196,7 +196,7 @@ impl Scope { /// Creates a mutable binding. #[must_use] - #[allow(clippy::cast_possible_truncation)] + #[expect(clippy::cast_possible_truncation)] pub fn create_mutable_binding(&self, name: JsString, function_scope: bool) -> BindingLocator { let binding_index = self.inner.bindings.borrow().len() as u32; self.inner.bindings.borrow_mut().insert( @@ -213,7 +213,7 @@ impl Scope { } /// Crate an immutable binding. - #[allow(clippy::cast_possible_truncation)] + #[expect(clippy::cast_possible_truncation)] pub(crate) fn create_immutable_binding(&self, name: JsString, strict: bool) { let binding_index = self.inner.bindings.borrow().len() as u32; self.inner.bindings.borrow_mut().insert( diff --git a/core/ast/src/scope_analyzer.rs b/core/ast/src/scope_analyzer.rs index e40534e67a..43c982ff1b 100644 --- a/core/ast/src/scope_analyzer.rs +++ b/core/ast/src/scope_analyzer.rs @@ -1100,7 +1100,7 @@ impl<'ast> VisitorMut<'ast> for BindingCollectorVisitor<'_> { } impl BindingCollectorVisitor<'_> { - #[allow(clippy::too_many_arguments)] + #[expect(clippy::too_many_arguments)] fn visit_function_like( &mut self, body: &mut FunctionBody, @@ -1469,7 +1469,7 @@ fn function_declaration_instantiation( // 27. If hasParameterExpressions is false, then // 28. Else, - #[allow(unused_variables, unused_mut)] + #[expect(unused_mut)] let (mut instantiated_var_names, mut var_env) = if has_parameter_expressions { // a. NOTE: A separate Environment Record is needed to ensure that closures created by // expressions in the formal parameter list do not have @@ -1713,13 +1713,12 @@ pub struct EvalDeclarationBindings { /// /// * Returns a syntax error if a duplicate lexical declaration is found. /// * Returns a syntax error if a variable declaration in an eval function already exists as a lexical variable. -#[allow(clippy::missing_panics_doc)] pub(crate) fn eval_declaration_instantiation_scope( body: &Script, strict: bool, var_env: &Scope, lex_env: &Scope, - #[allow(unused_variables)] annex_b_function_names: &[Identifier], + annex_b_function_names: &[Identifier], interner: &Interner, ) -> Result { let mut result = EvalDeclarationBindings::default(); diff --git a/core/ast/src/visitor.rs b/core/ast/src/visitor.rs index bcc22c3f74..54514a68a9 100644 --- a/core/ast/src/visitor.rs +++ b/core/ast/src/visitor.rs @@ -89,7 +89,7 @@ macro_rules! node_ref { ) => { /// A reference to a node visitable by a [`Visitor`]. #[derive(Debug, Clone, Copy)] - #[allow(missing_docs)] + #[expect(missing_docs)] pub enum NodeRef<'a> { $( $Variant(&'a $Variant) @@ -106,7 +106,7 @@ macro_rules! node_ref { /// A mutable reference to a node visitable by a [`VisitorMut`]. #[derive(Debug)] - #[allow(missing_docs)] + #[expect(missing_docs)] pub enum NodeRefMut<'a> { $( $Variant(&'a mut $Variant) diff --git a/core/engine/output.rs b/core/engine/output.rs new file mode 100644 index 0000000000..80088e5626 --- /dev/null +++ b/core/engine/output.rs @@ -0,0 +1,2402 @@ +pub mod array_buffer { + //! Boa's implementation of ECMAScript's global `ArrayBuffer` and `SharedArrayBuffer` objects + //! + //! More information: + //! - [ECMAScript reference][spec] + //! - [MDN documentation][mdn] + //! + //! [spec]: https://tc39.es/ecma262/#sec-arraybuffer-objects + //! [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer + #![deny(unsafe_op_in_unsafe_fn)] + #![deny(clippy::undocumented_unsafe_blocks)] + pub(crate) mod shared { + #![allow(unstable_name_collisions)] + use std::{alloc, sync::{atomic::Ordering, Arc}}; + use boa_profiler::Profiler; + use portable_atomic::{AtomicU8, AtomicUsize}; + use boa_gc::{Finalize, Trace}; + use sptr::Strict; + use crate::{ + builtins::{ + Array, BuiltInBuilder, BuiltInConstructor, BuiltInObject, IntrinsicObject, + }, + context::intrinsics::{Intrinsics, StandardConstructor, StandardConstructors}, + js_string, object::internal_methods::get_prototype_from_constructor, + property::Attribute, realm::Realm, string::StaticJsStrings, Context, JsArgs, + JsData, JsNativeError, JsObject, JsResult, JsString, JsSymbol, JsValue, + }; + use super::{get_max_byte_len, utils::copy_shared_to_shared}; + /// The internal representation of a `SharedArrayBuffer` object. + /// + /// This struct implements `Send` and `Sync`, meaning it can be shared between threads + /// running different JS code at the same time. + pub struct SharedArrayBuffer { + #[unsafe_ignore_trace] + data: Arc, + } + #[automatically_derived] + impl ::core::fmt::Debug for SharedArrayBuffer { + #[inline] + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + ::core::fmt::Formatter::debug_struct_field1_finish( + f, + "SharedArrayBuffer", + "data", + &&self.data, + ) + } + } + #[automatically_derived] + impl ::core::clone::Clone for SharedArrayBuffer { + #[inline] + fn clone(&self) -> SharedArrayBuffer { + SharedArrayBuffer { + data: ::core::clone::Clone::clone(&self.data), + } + } + } + const _: () = { + unsafe impl ::boa_gc::Trace for SharedArrayBuffer { + #[inline] + unsafe fn trace(&self, tracer: &mut ::boa_gc::Tracer) { + #[expect(dead_code)] + let mut mark = |it: &dyn ::boa_gc::Trace| { + unsafe { + ::boa_gc::Trace::trace(it, tracer); + } + }; + match *self { + SharedArrayBuffer { .. } => {} + } + } + #[inline] + unsafe fn trace_non_roots(&self) { + #[expect(dead_code)] + fn mark(it: &T) { + unsafe { + ::boa_gc::Trace::trace_non_roots(it); + } + } + match *self { + SharedArrayBuffer { .. } => {} + } + } + #[inline] + fn run_finalizer(&self) { + ::boa_gc::Finalize::finalize(self); + #[expect(dead_code)] + fn mark(it: &T) { + unsafe { + ::boa_gc::Trace::run_finalizer(it); + } + } + match *self { + SharedArrayBuffer { .. } => {} + } + } + } + }; + const _: () = { + impl ::core::ops::Drop for SharedArrayBuffer { + #[expect(clippy::inline_always)] + #[inline(always)] + fn drop(&mut self) { + if ::boa_gc::finalizer_safe() { + ::boa_gc::Finalize::finalize(self); + } + } + } + }; + const _: () = { + impl ::boa_gc::Finalize for SharedArrayBuffer {} + }; + const _: () = { + impl ::boa_engine::JsData for SharedArrayBuffer {} + }; + struct Inner { + buffer: Box<[AtomicU8]>, + current_len: Option, + } + #[automatically_derived] + impl ::core::fmt::Debug for Inner { + #[inline] + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + ::core::fmt::Formatter::debug_struct_field2_finish( + f, + "Inner", + "buffer", + &self.buffer, + "current_len", + &&self.current_len, + ) + } + } + #[automatically_derived] + impl ::core::default::Default for Inner { + #[inline] + fn default() -> Inner { + Inner { + buffer: ::core::default::Default::default(), + current_len: ::core::default::Default::default(), + } + } + } + impl SharedArrayBuffer { + /// Creates a `SharedArrayBuffer` with an empty buffer. + #[must_use] + pub fn empty() -> Self { + Self { data: Arc::default() } + } + /// Gets the length of this `SharedArrayBuffer`. + pub(crate) fn len(&self, ordering: Ordering) -> usize { + self.data + .current_len + .as_ref() + .map_or_else(|| self.data.buffer.len(), |len| len.load(ordering)) + } + /// Gets the inner bytes of this `SharedArrayBuffer`. + pub(crate) fn bytes(&self, ordering: Ordering) -> &[AtomicU8] { + &self.data.buffer[..self.len(ordering)] + } + /// Gets the inner data of the buffer without accessing the current atomic length. + #[track_caller] + pub(crate) fn bytes_with_len(&self, len: usize) -> &[AtomicU8] { + &self.data.buffer[..len] + } + /// Gets a pointer to the internal shared buffer. + pub(crate) fn as_ptr(&self) -> *const AtomicU8 { + (*self.data.buffer).as_ptr() + } + pub(crate) fn is_fixed_len(&self) -> bool { + self.data.current_len.is_none() + } + } + impl IntrinsicObject for SharedArrayBuffer { + fn init(realm: &Realm) { + let _timer = Profiler::global() + .start_event(std::any::type_name::(), "init"); + let flag_attributes = Attribute::CONFIGURABLE + | Attribute::NON_ENUMERABLE; + let get_species = BuiltInBuilder::callable(realm, Self::get_species) + .name({ + const LITERAL: &crate::string::StaticJsString = &crate::string::StaticJsString::new( + ::boa_engine::string::JsStr::latin1( + [ + 103, + 101, + 116, + 32, + 91, + 83, + 121, + 109, + 98, + 111, + 108, + 46, + 115, + 112, + 101, + 99, + 105, + 101, + 115, + 93, + ] + .as_slice(), + ), + ); + crate::string::JsString::from_static_js_string(LITERAL) + }) + .build(); + let get_byte_length = BuiltInBuilder::callable( + realm, + Self::get_byte_length, + ) + .name({ + const LITERAL: &crate::string::StaticJsString = &crate::string::StaticJsString::new( + ::boa_engine::string::JsStr::latin1( + [ + 103, + 101, + 116, + 32, + 98, + 121, + 116, + 101, + 76, + 101, + 110, + 103, + 116, + 104, + ] + .as_slice(), + ), + ); + crate::string::JsString::from_static_js_string(LITERAL) + }) + .build(); + let get_growable = BuiltInBuilder::callable(realm, Self::get_growable) + .name({ + const LITERAL: &crate::string::StaticJsString = &crate::string::StaticJsString::new( + ::boa_engine::string::JsStr::latin1( + [103, 101, 116, 32, 103, 114, 111, 119, 97, 98, 108, 101] + .as_slice(), + ), + ); + crate::string::JsString::from_static_js_string(LITERAL) + }) + .build(); + let get_max_byte_length = BuiltInBuilder::callable( + realm, + Self::get_max_byte_length, + ) + .name({ + const LITERAL: &crate::string::StaticJsString = &crate::string::StaticJsString::new( + ::boa_engine::string::JsStr::latin1( + [ + 103, + 101, + 116, + 32, + 109, + 97, + 120, + 66, + 121, + 116, + 101, + 76, + 101, + 110, + 103, + 116, + 104, + ] + .as_slice(), + ), + ); + crate::string::JsString::from_static_js_string(LITERAL) + }) + .build(); + BuiltInBuilder::from_standard_constructor::(realm) + .static_accessor( + JsSymbol::species(), + Some(get_species), + None, + Attribute::CONFIGURABLE, + ) + .accessor( + { + const LITERAL: &crate::string::StaticJsString = &crate::string::StaticJsString::new( + ::boa_engine::string::JsStr::latin1( + [98, 121, 116, 101, 76, 101, 110, 103, 116, 104].as_slice(), + ), + ); + crate::string::JsString::from_static_js_string(LITERAL) + }, + Some(get_byte_length), + None, + flag_attributes, + ) + .accessor( + { + const LITERAL: &crate::string::StaticJsString = &crate::string::StaticJsString::new( + ::boa_engine::string::JsStr::latin1( + [103, 114, 111, 119, 97, 98, 108, 101].as_slice(), + ), + ); + crate::string::JsString::from_static_js_string(LITERAL) + }, + Some(get_growable), + None, + flag_attributes, + ) + .accessor( + { + const LITERAL: &crate::string::StaticJsString = &crate::string::StaticJsString::new( + ::boa_engine::string::JsStr::latin1( + [ + 109, + 97, + 120, + 66, + 121, + 116, + 101, + 76, + 101, + 110, + 103, + 116, + 104, + ] + .as_slice(), + ), + ); + crate::string::JsString::from_static_js_string(LITERAL) + }, + Some(get_max_byte_length), + None, + flag_attributes, + ) + .method( + Self::slice, + { + const LITERAL: &crate::string::StaticJsString = &crate::string::StaticJsString::new( + ::boa_engine::string::JsStr::latin1( + [115, 108, 105, 99, 101].as_slice(), + ), + ); + crate::string::JsString::from_static_js_string(LITERAL) + }, + 2, + ) + .method( + Self::grow, + { + const LITERAL: &crate::string::StaticJsString = &crate::string::StaticJsString::new( + ::boa_engine::string::JsStr::latin1( + [103, 114, 111, 119].as_slice(), + ), + ); + crate::string::JsString::from_static_js_string(LITERAL) + }, + 1, + ) + .property( + JsSymbol::to_string_tag(), + Self::NAME, + Attribute::READONLY | Attribute::NON_ENUMERABLE + | Attribute::CONFIGURABLE, + ) + .build(); + } + fn get(intrinsics: &Intrinsics) -> JsObject { + Self::STANDARD_CONSTRUCTOR(intrinsics.constructors()).constructor() + } + } + impl BuiltInObject for SharedArrayBuffer { + const NAME: JsString = StaticJsStrings::SHARED_ARRAY_BUFFER; + } + impl BuiltInConstructor for SharedArrayBuffer { + const LENGTH: usize = 1; + const STANDARD_CONSTRUCTOR: fn( + &StandardConstructors, + ) -> &StandardConstructor = StandardConstructors::shared_array_buffer; + /// `25.1.3.1 SharedArrayBuffer ( length [ , options ] )` + /// + /// More information: + /// - [ECMAScript reference][spec] + /// + /// [spec]: https://tc39.es/ecma262/#sec-sharedarraybuffer-constructor + fn constructor( + new_target: &JsValue, + args: &[JsValue], + context: &mut Context, + ) -> JsResult { + if new_target.is_undefined() { + return Err( + JsNativeError::typ() + .with_message( + "ArrayBuffer.constructor called with undefined new target", + ) + .into(), + ); + } + let byte_len = args.get_or_undefined(0).to_index(context)?; + let max_byte_len = get_max_byte_len(args.get_or_undefined(1), context)?; + Ok( + Self::allocate(new_target, byte_len, max_byte_len, context)? + .upcast() + .into(), + ) + } + } + impl SharedArrayBuffer { + /// `get SharedArrayBuffer [ @@species ]` + /// + /// More information: + /// - [ECMAScript reference][spec] + /// + /// [spec]: https://tc39.es/ecma262/#sec-sharedarraybuffer-@@species + + fn get_species( + this: &JsValue, + _: &[JsValue], + _: &mut Context, + ) -> JsResult { + Ok(this.clone()) + } + /// `get SharedArrayBuffer.prototype.byteLength` + /// + /// More information: + /// - [ECMAScript reference][spec] + /// + /// [spec]: https://tc39.es/ecma262/#sec-get-sharedarraybuffer.prototype.bytelength + pub(crate) fn get_byte_length( + this: &JsValue, + _args: &[JsValue], + _: &mut Context, + ) -> JsResult { + let buf = this + .as_object() + .and_then(JsObject::downcast_ref::) + .ok_or_else(|| { + JsNativeError::typ() + .with_message( + "SharedArrayBuffer.byteLength called with invalid value", + ) + })?; + let len = buf.bytes(Ordering::SeqCst).len() as u64; + Ok(len.into()) + } + /// [`get SharedArrayBuffer.prototype.growable`][spec]. + /// + /// [spec]: https://tc39.es/ecma262/#sec-get-sharedarraybuffer.prototype.growable + pub(crate) fn get_growable( + this: &JsValue, + _args: &[JsValue], + _context: &mut Context, + ) -> JsResult { + let buf = this + .as_object() + .and_then(JsObject::downcast_ref::) + .ok_or_else(|| { + JsNativeError::typ() + .with_message( + "get SharedArrayBuffer.growable called with invalid `this`", + ) + })?; + Ok(JsValue::from(!buf.is_fixed_len())) + } + /// [`get SharedArrayBuffer.prototype.maxByteLength`][spec]. + /// + /// [spec]: https://tc39.es/ecma262/#sec-get-sharedarraybuffer.prototype.maxbytelength + pub(crate) fn get_max_byte_length( + this: &JsValue, + _args: &[JsValue], + _context: &mut Context, + ) -> JsResult { + let buf = this + .as_object() + .and_then(JsObject::downcast_ref::) + .ok_or_else(|| { + JsNativeError::typ() + .with_message( + "get SharedArrayBuffer.maxByteLength called with invalid value", + ) + })?; + Ok(buf.data.buffer.len().into()) + } + /// [`SharedArrayBuffer.prototype.grow ( newLength )`][spec]. + /// + /// [spec]: https://tc39.es/ecma262/sec-sharedarraybuffer.prototype.grow + pub(crate) fn grow( + this: &JsValue, + args: &[JsValue], + context: &mut Context, + ) -> JsResult { + let Some(buf) = this + .as_object() + .and_then(|o| o.clone().downcast::().ok()) else { + return Err( + JsNativeError::typ() + .with_message( + "SharedArrayBuffer.grow called with non-object value", + ) + .into(), + ); + }; + if buf.borrow().data.is_fixed_len() { + return Err( + JsNativeError::typ() + .with_message( + "SharedArrayBuffer.grow: cannot grow a fixed-length buffer", + ) + .into(), + ); + } + let new_byte_len = args.get_or_undefined(0).to_index(context)?; + let buf = buf.borrow(); + let buf = &buf.data; + if new_byte_len > buf.data.buffer.len() as u64 { + return Err( + JsNativeError::range() + .with_message( + "SharedArrayBuffer.grow: new length cannot be bigger than `maxByteLength`", + ) + .into(), + ); + } + let new_byte_len = new_byte_len as usize; + let atomic_len = buf + .data + .current_len + .as_ref() + .expect("already checked that the buffer is not fixed-length"); + atomic_len + .fetch_update( + Ordering::SeqCst, + Ordering::SeqCst, + |prev_byte_len| { + (prev_byte_len <= new_byte_len).then_some(new_byte_len) + }, + ) + .map_err(|_| { + JsNativeError::range() + .with_message( + "SharedArrayBuffer.grow: failed to grow buffer to new length", + ) + })?; + Ok(JsValue::undefined()) + } + /// `SharedArrayBuffer.prototype.slice ( start, end )` + /// + /// More information: + /// - [ECMAScript reference][spec] + /// + /// [spec]: https://tc39.es/ecma262/#sec-sharedarraybuffer.prototype.slice + fn slice( + this: &JsValue, + args: &[JsValue], + context: &mut Context, + ) -> JsResult { + let buf = this + .as_object() + .and_then(|o| o.clone().downcast::().ok()) + .ok_or_else(|| { + JsNativeError::typ() + .with_message( + "SharedArrayBuffer.slice called with invalid `this` value", + ) + })?; + let len = buf.borrow().data.len(Ordering::SeqCst); + let first = Array::get_relative_start( + context, + args.get_or_undefined(0), + len as u64, + )?; + let final_ = Array::get_relative_end( + context, + args.get_or_undefined(1), + len as u64, + )?; + let new_len = final_.saturating_sub(first); + let ctor = buf + .clone() + .upcast() + .species_constructor( + StandardConstructors::shared_array_buffer, + context, + )?; + let new = ctor.construct(&[new_len.into()], Some(&ctor), context)?; + { + let buf = buf.borrow(); + let buf = &buf.data; + let new = new + .downcast_ref::() + .ok_or_else(|| { + JsNativeError::typ() + .with_message( + "SharedArrayBuffer constructor returned invalid object", + ) + })?; + if std::ptr::eq(buf.as_ptr(), new.as_ptr()) { + return Err( + JsNativeError::typ() + .with_message( + "cannot reuse the same SharedArrayBuffer for a slice operation", + ) + .into(), + ); + } + if (new.len(Ordering::SeqCst) as u64) < new_len { + return Err( + JsNativeError::typ() + .with_message( + "invalid size of constructed SharedArrayBuffer", + ) + .into(), + ); + } + let first = first as usize; + let new_len = new_len as usize; + let from_buf = &buf.bytes_with_len(len)[first..]; + let to_buf = new; + if true { + if !(from_buf.len() >= new_len) { + ::core::panicking::panic( + "assertion failed: from_buf.len() >= new_len", + ) + } + } + unsafe { + copy_shared_to_shared( + from_buf.as_ptr(), + to_buf.as_ptr(), + new_len, + ) + } + } + Ok(new.into()) + } + /// `AllocateSharedArrayBuffer ( constructor, byteLength [ , maxByteLength ] )` + /// + /// More information: + /// - [ECMAScript reference][spec] + /// + /// [spec]: https://tc39.es/ecma262/#sec-allocatesharedarraybuffer + pub(crate) fn allocate( + constructor: &JsValue, + byte_len: u64, + max_byte_len: Option, + context: &mut Context, + ) -> JsResult> { + if let Some(max_byte_len) = max_byte_len { + if byte_len > max_byte_len { + return Err( + JsNativeError::range() + .with_message( + "`length` cannot be bigger than `maxByteLength`", + ) + .into(), + ); + } + } + let prototype = get_prototype_from_constructor( + constructor, + StandardConstructors::shared_array_buffer, + context, + )?; + let alloc_len = max_byte_len.unwrap_or(byte_len); + let block = create_shared_byte_data_block(alloc_len, context)?; + let current_len = max_byte_len + .map(|_| AtomicUsize::new(byte_len as usize)); + let obj = JsObject::new( + context.root_shape(), + prototype, + Self { + data: Arc::new(Inner { + buffer: block, + current_len, + }), + }, + ); + Ok(obj) + } + } + /// [`CreateSharedByteDataBlock ( size )`][spec] abstract operation. + /// + /// Creates a new `Arc>` that can be used as a backing buffer for a [`SharedArrayBuffer`]. + /// + /// For more information, check the [spec][spec]. + /// + /// [spec]: https://tc39.es/ecma262/#sec-createsharedbytedatablock + pub(crate) fn create_shared_byte_data_block( + size: u64, + context: &mut Context, + ) -> JsResult> { + if size > context.host_hooks().max_buffer_size(context) { + return Err( + JsNativeError::range() + .with_message( + "cannot allocate a buffer that exceeds the maximum buffer size" + .to_string(), + ) + .into(), + ); + } + let size = size + .try_into() + .map_err(|e| { + JsNativeError::range() + .with_message( + ::alloc::__export::must_use({ + let res = ::alloc::fmt::format( + format_args!("couldn\'t allocate the data block: {0}", e), + ); + res + }), + ) + })?; + if size == 0 { + return Ok(Box::default()); + } + let layout = alloc::Layout::array::(size) + .map_err(|e| { + JsNativeError::range() + .with_message( + ::alloc::__export::must_use({ + let res = ::alloc::fmt::format( + format_args!("couldn\'t allocate the data block: {0}", e), + ); + res + }), + ) + })?; + let ptr: *mut AtomicU8 = unsafe { alloc::alloc_zeroed(layout).cast() }; + if ptr.is_null() { + return Err( + JsNativeError::range() + .with_message("memory allocator failed to allocate buffer") + .into(), + ); + } + let buffer = unsafe { + Box::from_raw(std::slice::from_raw_parts_mut(ptr, size)) + }; + match (&(buffer.as_ptr().addr() % align_of::()), &0) { + (left_val, right_val) => { + if !(*left_val == *right_val) { + let kind = ::core::panicking::AssertKind::Eq; + ::core::panicking::assert_failed( + kind, + &*left_val, + &*right_val, + ::core::option::Option::None, + ); + } + } + }; + Ok(buffer) + } + } + pub(crate) mod utils { + #![allow(unstable_name_collisions)] + use std::{ptr, slice::SliceIndex, sync::atomic::Ordering}; + use portable_atomic::AtomicU8; + use crate::{ + builtins::typed_array::{ + ClampedU8, Element, TypedArrayElement, TypedArrayKind, + }, + Context, JsObject, JsResult, + }; + use super::ArrayBuffer; + pub(crate) enum BytesConstPtr { + Bytes(*const u8), + AtomicBytes(*const AtomicU8), + } + #[automatically_derived] + impl ::core::clone::Clone for BytesConstPtr { + #[inline] + fn clone(&self) -> BytesConstPtr { + let _: ::core::clone::AssertParamIsClone<*const u8>; + let _: ::core::clone::AssertParamIsClone<*const AtomicU8>; + *self + } + } + #[automatically_derived] + impl ::core::marker::Copy for BytesConstPtr {} + pub(crate) enum BytesMutPtr { + Bytes(*mut u8), + AtomicBytes(*const AtomicU8), + } + #[automatically_derived] + impl ::core::clone::Clone for BytesMutPtr { + #[inline] + fn clone(&self) -> BytesMutPtr { + let _: ::core::clone::AssertParamIsClone<*mut u8>; + let _: ::core::clone::AssertParamIsClone<*const AtomicU8>; + *self + } + } + #[automatically_derived] + impl ::core::marker::Copy for BytesMutPtr {} + pub(crate) enum SliceRef<'a> { + Slice(&'a [u8]), + AtomicSlice(&'a [AtomicU8]), + } + #[automatically_derived] + impl<'a> ::core::fmt::Debug for SliceRef<'a> { + #[inline] + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + match self { + SliceRef::Slice(__self_0) => { + ::core::fmt::Formatter::debug_tuple_field1_finish( + f, + "Slice", + &__self_0, + ) + } + SliceRef::AtomicSlice(__self_0) => { + ::core::fmt::Formatter::debug_tuple_field1_finish( + f, + "AtomicSlice", + &__self_0, + ) + } + } + } + } + #[automatically_derived] + impl<'a> ::core::clone::Clone for SliceRef<'a> { + #[inline] + fn clone(&self) -> SliceRef<'a> { + let _: ::core::clone::AssertParamIsClone<&'a [u8]>; + let _: ::core::clone::AssertParamIsClone<&'a [AtomicU8]>; + *self + } + } + #[automatically_derived] + impl<'a> ::core::marker::Copy for SliceRef<'a> {} + impl SliceRef<'_> { + /// Gets the byte length of this `SliceRef`. + pub(crate) fn len(&self) -> usize { + match self { + Self::Slice(buf) => buf.len(), + Self::AtomicSlice(buf) => buf.len(), + } + } + /// Gets a subslice of this `SliceRef`. + pub(crate) fn subslice(&self, index: I) -> SliceRef<'_> + where + I: SliceIndex<[u8], Output = [u8]> + + SliceIndex<[AtomicU8], Output = [AtomicU8]>, + { + match self { + Self::Slice(buffer) => { + SliceRef::Slice(buffer.get(index).expect("index out of bounds")) + } + Self::AtomicSlice(buffer) => { + SliceRef::AtomicSlice( + buffer.get(index).expect("index out of bounds"), + ) + } + } + } + /// Gets the starting address of this `SliceRef`. + #[cfg(debug_assertions)] + pub(crate) fn addr(&self) -> usize { + use sptr::Strict; + match self { + Self::Slice(buf) => buf.as_ptr().addr(), + Self::AtomicSlice(buf) => buf.as_ptr().addr(), + } + } + /// Gets a pointer to the underlying slice. + pub(crate) fn as_ptr(&self) -> BytesConstPtr { + match self { + SliceRef::Slice(s) => BytesConstPtr::Bytes(s.as_ptr()), + SliceRef::AtomicSlice(s) => BytesConstPtr::AtomicBytes(s.as_ptr()), + } + } + /// [`GetValueFromBuffer ( arrayBuffer, byteIndex, type, isTypedArray, order [ , isLittleEndian ] )`][spec] + /// + /// The start offset is determined by the input buffer instead of a `byteIndex` parameter. + /// + /// # Safety + /// + /// - There must be enough bytes in `buffer` to read an element from an array with type `TypedArrayKind`. + /// - `buffer` must be aligned to the alignment of said element. + /// + /// [spec]: https://tc39.es/ecma262/#sec-getvaluefrombuffer + pub(crate) unsafe fn get_value( + &self, + kind: TypedArrayKind, + order: Ordering, + ) -> TypedArrayElement { + unsafe fn read_elem( + buffer: SliceRef<'_>, + order: Ordering, + ) -> T { + #[cfg(debug_assertions)] + { + if !(buffer.len() >= size_of::()) { + ::core::panicking::panic( + "assertion failed: buffer.len() >= size_of::()", + ) + } + match (&(buffer.addr() % align_of::()), &0) { + (left_val, right_val) => { + if !(*left_val == *right_val) { + let kind = ::core::panicking::AssertKind::Eq; + ::core::panicking::assert_failed( + kind, + &*left_val, + &*right_val, + ::core::option::Option::None, + ); + } + } + }; + } + unsafe { T::read(buffer).load(order) } + } + let buffer = *self; + unsafe { + match kind { + TypedArrayKind::Int8 => read_elem::(buffer, order).into(), + TypedArrayKind::Uint8 => read_elem::(buffer, order).into(), + TypedArrayKind::Uint8Clamped => { + read_elem::(buffer, order).into() + } + TypedArrayKind::Int16 => read_elem::(buffer, order).into(), + TypedArrayKind::Uint16 => read_elem::(buffer, order).into(), + TypedArrayKind::Int32 => read_elem::(buffer, order).into(), + TypedArrayKind::Uint32 => read_elem::(buffer, order).into(), + TypedArrayKind::BigInt64 => { + read_elem::(buffer, order).into() + } + TypedArrayKind::BigUint64 => { + read_elem::(buffer, order).into() + } + TypedArrayKind::Float32 => read_elem::(buffer, order).into(), + TypedArrayKind::Float64 => read_elem::(buffer, order).into(), + } + } + } + /// [`CloneArrayBuffer ( srcBuffer, srcByteOffset, srcLength )`][spec] + /// + /// [spec]: https://tc39.es/ecma262/#sec-clonearraybuffer + pub(crate) fn clone( + &self, + context: &mut Context, + ) -> JsResult> { + let target_buffer = ArrayBuffer::allocate( + &context + .realm() + .intrinsics() + .constructors() + .array_buffer() + .constructor() + .into(), + self.len() as u64, + None, + context, + )?; + { + let mut target_buffer = target_buffer.borrow_mut(); + let target_block = target_buffer + .data + .bytes_mut() + .expect("ArrayBuffer cannot be detached here"); + unsafe { + memcpy( + self.as_ptr(), + BytesMutPtr::Bytes(target_block.as_mut_ptr()), + self.len(), + ); + } + } + Ok(target_buffer) + } + } + impl<'a> From<&'a [u8]> for SliceRef<'a> { + fn from(value: &'a [u8]) -> Self { + Self::Slice(value) + } + } + impl<'a> From<&'a [AtomicU8]> for SliceRef<'a> { + fn from(value: &'a [AtomicU8]) -> Self { + Self::AtomicSlice(value) + } + } + pub(crate) enum SliceRefMut<'a> { + Slice(&'a mut [u8]), + AtomicSlice(&'a [AtomicU8]), + } + #[automatically_derived] + impl<'a> ::core::fmt::Debug for SliceRefMut<'a> { + #[inline] + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + match self { + SliceRefMut::Slice(__self_0) => { + ::core::fmt::Formatter::debug_tuple_field1_finish( + f, + "Slice", + &__self_0, + ) + } + SliceRefMut::AtomicSlice(__self_0) => { + ::core::fmt::Formatter::debug_tuple_field1_finish( + f, + "AtomicSlice", + &__self_0, + ) + } + } + } + } + impl SliceRefMut<'_> { + /// Gets the byte length of this `SliceRefMut`. + pub(crate) fn len(&self) -> usize { + match self { + Self::Slice(buf) => buf.len(), + Self::AtomicSlice(buf) => buf.len(), + } + } + /// Gets a mutable subslice of this `SliceRefMut`. + pub(crate) fn subslice_mut(&mut self, index: I) -> SliceRefMut<'_> + where + I: SliceIndex<[u8], Output = [u8]> + + SliceIndex<[AtomicU8], Output = [AtomicU8]>, + { + match self { + Self::Slice(buffer) => { + SliceRefMut::Slice( + buffer.get_mut(index).expect("index out of bounds"), + ) + } + Self::AtomicSlice(buffer) => { + SliceRefMut::AtomicSlice( + buffer.get(index).expect("index out of bounds"), + ) + } + } + } + /// Gets the starting address of this `SliceRefMut`. + #[cfg(debug_assertions)] + pub(crate) fn addr(&self) -> usize { + use sptr::Strict; + match self { + Self::Slice(buf) => buf.as_ptr().addr(), + Self::AtomicSlice(buf) => buf.as_ptr().addr(), + } + } + /// Gets a pointer to the underlying slice. + pub(crate) fn as_ptr(&mut self) -> BytesMutPtr { + match self { + Self::Slice(s) => BytesMutPtr::Bytes(s.as_mut_ptr()), + Self::AtomicSlice(s) => BytesMutPtr::AtomicBytes(s.as_ptr()), + } + } + /// `25.1.2.12 SetValueInBuffer ( arrayBuffer, byteIndex, type, value, isTypedArray, order [ , isLittleEndian ] )` + /// + /// The start offset is determined by the input buffer instead of a `byteIndex` parameter. + /// + /// # Safety + /// + /// - There must be enough bytes in `buffer` to write the `TypedArrayElement`. + /// - `buffer` must be aligned to the alignment of the `TypedArrayElement`. + /// + /// # Panics + /// + /// - Panics if the type of `value` is not equal to the content of `kind`. + /// + /// More information: + /// - [ECMAScript reference][spec] + /// + /// [spec]: https://tc39.es/ecma262/#sec-setvalueinbuffer + pub(crate) unsafe fn set_value( + &mut self, + value: TypedArrayElement, + order: Ordering, + ) { + unsafe fn write_elem( + buffer: SliceRefMut<'_>, + value: T, + order: Ordering, + ) { + #[cfg(debug_assertions)] + { + if !(buffer.len() >= size_of::()) { + ::core::panicking::panic( + "assertion failed: buffer.len() >= size_of::()", + ) + } + match (&(buffer.addr() % align_of::()), &0) { + (left_val, right_val) => { + if !(*left_val == *right_val) { + let kind = ::core::panicking::AssertKind::Eq; + ::core::panicking::assert_failed( + kind, + &*left_val, + &*right_val, + ::core::option::Option::None, + ); + } + } + }; + } + unsafe { + T::read_mut(buffer).store(value, order); + } + } + let buffer = match self { + SliceRefMut::Slice(buf) => SliceRefMut::Slice(buf), + SliceRefMut::AtomicSlice(buf) => SliceRefMut::AtomicSlice(buf), + }; + unsafe { + match value { + TypedArrayElement::Int8(e) => write_elem(buffer, e, order), + TypedArrayElement::Uint8(e) => write_elem(buffer, e, order), + TypedArrayElement::Uint8Clamped(e) => { + write_elem(buffer, e, order) + } + TypedArrayElement::Int16(e) => write_elem(buffer, e, order), + TypedArrayElement::Uint16(e) => write_elem(buffer, e, order), + TypedArrayElement::Int32(e) => write_elem(buffer, e, order), + TypedArrayElement::Uint32(e) => write_elem(buffer, e, order), + TypedArrayElement::BigInt64(e) => write_elem(buffer, e, order), + TypedArrayElement::BigUint64(e) => write_elem(buffer, e, order), + TypedArrayElement::Float32(e) => write_elem(buffer, e, order), + TypedArrayElement::Float64(e) => write_elem(buffer, e, order), + } + } + } + } + impl<'a> From<&'a mut [u8]> for SliceRefMut<'a> { + fn from(value: &'a mut [u8]) -> Self { + Self::Slice(value) + } + } + impl<'a> From<&'a [AtomicU8]> for SliceRefMut<'a> { + fn from(value: &'a [AtomicU8]) -> Self { + Self::AtomicSlice(value) + } + } + /// Copies `count` bytes from `src` into `dest` using atomic relaxed loads and stores. + /// + /// # Safety + /// + /// - Both `src` and `dest` must have at least `count` bytes to read and write, + /// respectively. + pub(super) unsafe fn copy_shared_to_shared( + src: *const AtomicU8, + dest: *const AtomicU8, + count: usize, + ) { + for i in 0..count { + unsafe { + (*dest.add(i)) + .store((*src.add(i)).load(Ordering::Relaxed), Ordering::Relaxed); + } + } + } + /// Copies `count` bytes backwards from `src` into `dest` using atomic relaxed loads and stores. + /// + /// # Safety + /// + /// - Both `src` and `dest` must have at least `count` bytes to read and write, + /// respectively. + unsafe fn copy_shared_to_shared_backwards( + src: *const AtomicU8, + dest: *const AtomicU8, + count: usize, + ) { + for i in (0..count).rev() { + unsafe { + (*dest.add(i)) + .store((*src.add(i)).load(Ordering::Relaxed), Ordering::Relaxed); + } + } + } + /// Copies `count` bytes from the buffer `src` into the buffer `dest`, using the atomic ordering + /// `Ordering::Relaxed` if any of the buffers are atomic. + /// + /// # Safety + /// + /// - Both `src` and `dest` must have at least `count` bytes to read and write, respectively. + /// - The region of memory referenced by `src` must not overlap with the region of memory + /// referenced by `dest`. + pub(crate) unsafe fn memcpy( + src: BytesConstPtr, + dest: BytesMutPtr, + count: usize, + ) { + match (src, dest) { + (BytesConstPtr::Bytes(src), BytesMutPtr::Bytes(dest)) => { + unsafe { + ptr::copy_nonoverlapping(src, dest, count); + } + } + (BytesConstPtr::Bytes(src), BytesMutPtr::AtomicBytes(dest)) => { + unsafe { + for i in 0..count { + (*dest.add(i)).store(*src.add(i), Ordering::Relaxed); + } + } + } + (BytesConstPtr::AtomicBytes(src), BytesMutPtr::Bytes(dest)) => { + unsafe { + for i in 0..count { + *dest.add(i) = (*src.add(i)).load(Ordering::Relaxed); + } + } + } + (BytesConstPtr::AtomicBytes(src), BytesMutPtr::AtomicBytes(dest)) => { + unsafe { + copy_shared_to_shared(src, dest, count); + } + } + } + } + /// Copies `count` bytes from the position `from` to the position `to` in `buffer`. + /// + /// # Safety + /// + /// - `ptr` must be valid from the offset `ptr + from` for `count` reads of bytes. + /// - `ptr` must be valid from the offset `ptr + to` for `count` writes of bytes. + pub(crate) unsafe fn memmove( + ptr: BytesMutPtr, + from: usize, + to: usize, + count: usize, + ) { + match ptr { + BytesMutPtr::Bytes(ptr) => { + unsafe { + let src = ptr.add(from); + let dest = ptr.add(to); + ptr::copy(src, dest, count); + } + } + BytesMutPtr::AtomicBytes(ptr) => { + unsafe { + let src = ptr.add(from); + let dest = ptr.add(to); + if src < dest { + copy_shared_to_shared_backwards(src, dest, count); + } else { + copy_shared_to_shared(src, dest, count); + } + } + } + } + } + } + use std::ops::{Deref, DerefMut}; + pub use shared::SharedArrayBuffer; + use std::sync::atomic::Ordering; + use crate::{ + builtins::BuiltInObject, + context::intrinsics::{Intrinsics, StandardConstructor, StandardConstructors}, + error::JsNativeError, js_string, + object::{internal_methods::get_prototype_from_constructor, JsObject, Object}, + property::Attribute, realm::Realm, string::StaticJsStrings, symbol::JsSymbol, + Context, JsArgs, JsData, JsResult, JsString, JsValue, + }; + use boa_gc::{Finalize, GcRef, GcRefMut, Trace}; + use boa_profiler::Profiler; + use self::utils::{SliceRef, SliceRefMut}; + use super::{ + typed_array::TypedArray, Array, BuiltInBuilder, BuiltInConstructor, DataView, + IntrinsicObject, + }; + pub(crate) enum BufferRef { + Buffer(B), + SharedBuffer(S), + } + #[automatically_derived] + impl ::core::fmt::Debug + for BufferRef { + #[inline] + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + match self { + BufferRef::Buffer(__self_0) => { + ::core::fmt::Formatter::debug_tuple_field1_finish( + f, + "Buffer", + &__self_0, + ) + } + BufferRef::SharedBuffer(__self_0) => { + ::core::fmt::Formatter::debug_tuple_field1_finish( + f, + "SharedBuffer", + &__self_0, + ) + } + } + } + } + #[automatically_derived] + impl ::core::clone::Clone + for BufferRef { + #[inline] + fn clone(&self) -> BufferRef { + match self { + BufferRef::Buffer(__self_0) => { + BufferRef::Buffer(::core::clone::Clone::clone(__self_0)) + } + BufferRef::SharedBuffer(__self_0) => { + BufferRef::SharedBuffer(::core::clone::Clone::clone(__self_0)) + } + } + } + } + #[automatically_derived] + impl ::core::marker::Copy + for BufferRef {} + impl BufferRef + where + B: Deref, + S: Deref, + { + /// Gets the inner data of the buffer. + pub(crate) fn bytes(&self, ordering: Ordering) -> Option> { + match self { + Self::Buffer(buf) => buf.deref().bytes().map(SliceRef::Slice), + Self::SharedBuffer(buf) => { + Some(SliceRef::AtomicSlice(buf.deref().bytes(ordering))) + } + } + } + /// Gets the inner data of the buffer without accessing the current atomic length. + /// + /// Returns `None` if the buffer is detached or if the provided `len` is bigger than + /// the allocated buffer. + #[track_caller] + pub(crate) fn bytes_with_len(&self, len: usize) -> Option> { + match self { + Self::Buffer(buf) => buf.deref().bytes_with_len(len).map(SliceRef::Slice), + Self::SharedBuffer(buf) => { + Some(SliceRef::AtomicSlice(buf.deref().bytes_with_len(len))) + } + } + } + pub(crate) fn is_fixed_len(&self) -> bool { + match self { + Self::Buffer(buf) => buf.is_fixed_len(), + Self::SharedBuffer(buf) => buf.is_fixed_len(), + } + } + } + pub(crate) enum BufferRefMut { + Buffer(B), + SharedBuffer(S), + } + #[automatically_derived] + impl ::core::fmt::Debug + for BufferRefMut { + #[inline] + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + match self { + BufferRefMut::Buffer(__self_0) => { + ::core::fmt::Formatter::debug_tuple_field1_finish( + f, + "Buffer", + &__self_0, + ) + } + BufferRefMut::SharedBuffer(__self_0) => { + ::core::fmt::Formatter::debug_tuple_field1_finish( + f, + "SharedBuffer", + &__self_0, + ) + } + } + } + } + impl BufferRefMut + where + B: DerefMut, + S: DerefMut, + { + pub(crate) fn bytes(&mut self, ordering: Ordering) -> Option> { + match self { + Self::Buffer(buf) => buf.deref_mut().bytes_mut().map(SliceRefMut::Slice), + Self::SharedBuffer(buf) => { + Some(SliceRefMut::AtomicSlice(buf.deref_mut().bytes(ordering))) + } + } + } + /// Gets the mutable inner data of the buffer without accessing the current atomic length. + /// + /// Returns `None` if the buffer is detached or if the provided `len` is bigger than + /// the allocated buffer. + pub(crate) fn bytes_with_len(&mut self, len: usize) -> Option> { + match self { + Self::Buffer(buf) => { + buf.deref_mut().bytes_with_len_mut(len).map(SliceRefMut::Slice) + } + Self::SharedBuffer(buf) => { + Some(SliceRefMut::AtomicSlice(buf.deref_mut().bytes_with_len(len))) + } + } + } + } + /// A `JsObject` containing a bytes buffer as its inner data. + #[boa_gc(unsafe_no_drop)] + pub(crate) enum BufferObject { + Buffer(JsObject), + SharedBuffer(JsObject), + } + #[automatically_derived] + impl ::core::fmt::Debug for BufferObject { + #[inline] + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + match self { + BufferObject::Buffer(__self_0) => { + ::core::fmt::Formatter::debug_tuple_field1_finish( + f, + "Buffer", + &__self_0, + ) + } + BufferObject::SharedBuffer(__self_0) => { + ::core::fmt::Formatter::debug_tuple_field1_finish( + f, + "SharedBuffer", + &__self_0, + ) + } + } + } + } + #[automatically_derived] + impl ::core::clone::Clone for BufferObject { + #[inline] + fn clone(&self) -> BufferObject { + match self { + BufferObject::Buffer(__self_0) => { + BufferObject::Buffer(::core::clone::Clone::clone(__self_0)) + } + BufferObject::SharedBuffer(__self_0) => { + BufferObject::SharedBuffer(::core::clone::Clone::clone(__self_0)) + } + } + } + } + const _: () = { + unsafe impl ::boa_gc::Trace for BufferObject { + #[inline] + unsafe fn trace(&self, tracer: &mut ::boa_gc::Tracer) { + #[expect(dead_code)] + let mut mark = |it: &dyn ::boa_gc::Trace| { + unsafe { + ::boa_gc::Trace::trace(it, tracer); + } + }; + match *self { + BufferObject::Buffer(ref __binding_0) => { + ::boa_gc::Trace::trace(__binding_0, tracer) + } + BufferObject::SharedBuffer(ref __binding_0) => { + ::boa_gc::Trace::trace(__binding_0, tracer) + } + } + } + #[inline] + unsafe fn trace_non_roots(&self) { + #[expect(dead_code)] + fn mark(it: &T) { + unsafe { + ::boa_gc::Trace::trace_non_roots(it); + } + } + match *self { + BufferObject::Buffer(ref __binding_0) => mark(__binding_0), + BufferObject::SharedBuffer(ref __binding_0) => mark(__binding_0), + } + } + #[inline] + fn run_finalizer(&self) { + ::boa_gc::Finalize::finalize(self); + #[expect(dead_code)] + fn mark(it: &T) { + unsafe { + ::boa_gc::Trace::run_finalizer(it); + } + } + match *self { + BufferObject::Buffer(ref __binding_0) => mark(__binding_0), + BufferObject::SharedBuffer(ref __binding_0) => mark(__binding_0), + } + } + } + }; + const _: () = { + impl ::boa_gc::Finalize for BufferObject {} + }; + impl From for JsObject { + fn from(value: BufferObject) -> Self { + match value { + BufferObject::Buffer(buf) => buf.upcast(), + BufferObject::SharedBuffer(buf) => buf.upcast(), + } + } + } + impl From for JsValue { + fn from(value: BufferObject) -> Self { + JsValue::from(JsObject::from(value)) + } + } + impl BufferObject { + /// Gets the buffer data of the object. + #[inline] + #[must_use] + pub(crate) fn as_buffer( + &self, + ) -> BufferRef, GcRef<'_, SharedArrayBuffer>> { + match self { + Self::Buffer(buf) => { + BufferRef::Buffer(GcRef::map(buf.borrow(), |o| &o.data)) + } + Self::SharedBuffer(buf) => { + BufferRef::SharedBuffer(GcRef::map(buf.borrow(), |o| &o.data)) + } + } + } + /// Gets the mutable buffer data of the object + #[inline] + pub(crate) fn as_buffer_mut( + &self, + ) -> BufferRefMut< + GcRefMut<'_, Object, ArrayBuffer>, + GcRefMut<'_, Object, SharedArrayBuffer>, + > { + match self { + Self::Buffer(buf) => { + BufferRefMut::Buffer( + GcRefMut::map(buf.borrow_mut(), |o| &mut o.data), + ) + } + Self::SharedBuffer(buf) => { + BufferRefMut::SharedBuffer( + GcRefMut::map(buf.borrow_mut(), |o| &mut o.data), + ) + } + } + } + /// Returns `true` if the buffer objects point to the same buffer. + #[inline] + pub(crate) fn equals(lhs: &Self, rhs: &Self) -> bool { + match (lhs, rhs) { + (BufferObject::Buffer(lhs), BufferObject::Buffer(rhs)) => { + JsObject::equals(lhs, rhs) + } + (BufferObject::SharedBuffer(lhs), BufferObject::SharedBuffer(rhs)) => { + if JsObject::equals(lhs, rhs) { + return true; + } + let lhs = lhs.borrow(); + let rhs = rhs.borrow(); + std::ptr::eq(lhs.data.as_ptr(), rhs.data.as_ptr()) + } + _ => false, + } + } + } + /// The internal representation of an `ArrayBuffer` object. + pub struct ArrayBuffer { + /// The `[[ArrayBufferData]]` internal slot. + data: Option>, + /// The `[[ArrayBufferMaxByteLength]]` internal slot. + max_byte_len: Option, + /// The `[[ArrayBufferDetachKey]]` internal slot. + detach_key: JsValue, + } + #[automatically_derived] + impl ::core::fmt::Debug for ArrayBuffer { + #[inline] + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + ::core::fmt::Formatter::debug_struct_field3_finish( + f, + "ArrayBuffer", + "data", + &self.data, + "max_byte_len", + &self.max_byte_len, + "detach_key", + &&self.detach_key, + ) + } + } + #[automatically_derived] + impl ::core::clone::Clone for ArrayBuffer { + #[inline] + fn clone(&self) -> ArrayBuffer { + ArrayBuffer { + data: ::core::clone::Clone::clone(&self.data), + max_byte_len: ::core::clone::Clone::clone(&self.max_byte_len), + detach_key: ::core::clone::Clone::clone(&self.detach_key), + } + } + } + const _: () = { + unsafe impl ::boa_gc::Trace for ArrayBuffer { + #[inline] + unsafe fn trace(&self, tracer: &mut ::boa_gc::Tracer) { + #[expect(dead_code)] + let mut mark = |it: &dyn ::boa_gc::Trace| { + unsafe { + ::boa_gc::Trace::trace(it, tracer); + } + }; + match *self { + ArrayBuffer { + data: ref __binding_0, + max_byte_len: ref __binding_1, + detach_key: ref __binding_2, + } => { + { ::boa_gc::Trace::trace(__binding_0, tracer) } + { ::boa_gc::Trace::trace(__binding_1, tracer) } + { ::boa_gc::Trace::trace(__binding_2, tracer) } + } + } + } + #[inline] + unsafe fn trace_non_roots(&self) { + #[expect(dead_code)] + fn mark(it: &T) { + unsafe { + ::boa_gc::Trace::trace_non_roots(it); + } + } + match *self { + ArrayBuffer { + data: ref __binding_0, + max_byte_len: ref __binding_1, + detach_key: ref __binding_2, + } => { + { mark(__binding_0) } + { mark(__binding_1) } + { mark(__binding_2) } + } + } + } + #[inline] + fn run_finalizer(&self) { + ::boa_gc::Finalize::finalize(self); + #[expect(dead_code)] + fn mark(it: &T) { + unsafe { + ::boa_gc::Trace::run_finalizer(it); + } + } + match *self { + ArrayBuffer { + data: ref __binding_0, + max_byte_len: ref __binding_1, + detach_key: ref __binding_2, + } => { + { mark(__binding_0) } + { mark(__binding_1) } + { mark(__binding_2) } + } + } + } + } + }; + const _: () = { + impl ::core::ops::Drop for ArrayBuffer { + #[expect(clippy::inline_always)] + #[inline(always)] + fn drop(&mut self) { + if ::boa_gc::finalizer_safe() { + ::boa_gc::Finalize::finalize(self); + } + } + } + }; + const _: () = { + impl ::boa_gc::Finalize for ArrayBuffer {} + }; + const _: () = { + impl ::boa_engine::JsData for ArrayBuffer {} + }; + impl ArrayBuffer { + pub(crate) fn from_data(data: Vec, detach_key: JsValue) -> Self { + Self { + data: Some(data), + max_byte_len: None, + detach_key, + } + } + pub(crate) fn len(&self) -> usize { + self.data.as_ref().map_or(0, Vec::len) + } + pub(crate) fn bytes(&self) -> Option<&[u8]> { + self.data.as_deref() + } + pub(crate) fn bytes_mut(&mut self) -> Option<&mut [u8]> { + self.data.as_deref_mut() + } + pub(crate) fn vec_mut(&mut self) -> Option<&mut Vec> { + self.data.as_mut() + } + /// Gets the inner bytes of the buffer without accessing the current atomic length. + #[track_caller] + pub(crate) fn bytes_with_len(&self, len: usize) -> Option<&[u8]> { + if let Some(s) = self.data.as_deref() { Some(&s[..len]) } else { None } + } + /// Gets the mutable inner bytes of the buffer without accessing the current atomic length. + #[track_caller] + pub(crate) fn bytes_with_len_mut(&mut self, len: usize) -> Option<&mut [u8]> { + if let Some(s) = self.data.as_deref_mut() { + Some(&mut s[..len]) + } else { + None + } + } + /// Detaches the inner data of this `ArrayBuffer`, returning the original buffer if still + /// present. + /// + /// # Errors + /// + /// Throws an error if the provided detach key is invalid. + pub fn detach(&mut self, key: &JsValue) -> JsResult>> { + if !JsValue::same_value(&self.detach_key, key) { + return Err( + JsNativeError::typ() + .with_message("Cannot detach array buffer with different key") + .into(), + ); + } + Ok(self.data.take()) + } + /// `IsDetachedBuffer ( arrayBuffer )` + /// + /// More information: + /// - [ECMAScript reference][spec] + /// + /// [spec]: https://tc39.es/ecma262/#sec-isdetachedbuffer + pub(crate) const fn is_detached(&self) -> bool { + self.data.is_none() + } + pub(crate) fn is_fixed_len(&self) -> bool { + self.max_byte_len.is_none() + } + } + impl IntrinsicObject for ArrayBuffer { + fn init(realm: &Realm) { + let _timer = Profiler::global() + .start_event(std::any::type_name::(), "init"); + let flag_attributes = Attribute::CONFIGURABLE | Attribute::NON_ENUMERABLE; + let get_species = BuiltInBuilder::callable(realm, Self::get_species) + .name({ + const LITERAL: &crate::string::StaticJsString = &crate::string::StaticJsString::new( + ::boa_engine::string::JsStr::latin1( + [ + 103, + 101, + 116, + 32, + 91, + 83, + 121, + 109, + 98, + 111, + 108, + 46, + 115, + 112, + 101, + 99, + 105, + 101, + 115, + 93, + ] + .as_slice(), + ), + ); + crate::string::JsString::from_static_js_string(LITERAL) + }) + .build(); + let get_byte_length = BuiltInBuilder::callable(realm, Self::get_byte_length) + .name({ + const LITERAL: &crate::string::StaticJsString = &crate::string::StaticJsString::new( + ::boa_engine::string::JsStr::latin1( + [ + 103, + 101, + 116, + 32, + 98, + 121, + 116, + 101, + 76, + 101, + 110, + 103, + 116, + 104, + ] + .as_slice(), + ), + ); + crate::string::JsString::from_static_js_string(LITERAL) + }) + .build(); + let get_resizable = BuiltInBuilder::callable(realm, Self::get_resizable) + .name({ + const LITERAL: &crate::string::StaticJsString = &crate::string::StaticJsString::new( + ::boa_engine::string::JsStr::latin1( + [ + 103, + 101, + 116, + 32, + 114, + 101, + 115, + 105, + 122, + 97, + 98, + 108, + 101, + ] + .as_slice(), + ), + ); + crate::string::JsString::from_static_js_string(LITERAL) + }) + .build(); + let get_max_byte_length = BuiltInBuilder::callable( + realm, + Self::get_max_byte_length, + ) + .name({ + const LITERAL: &crate::string::StaticJsString = &crate::string::StaticJsString::new( + ::boa_engine::string::JsStr::latin1( + [ + 103, + 101, + 116, + 32, + 109, + 97, + 120, + 66, + 121, + 116, + 101, + 76, + 101, + 110, + 103, + 116, + 104, + ] + .as_slice(), + ), + ); + crate::string::JsString::from_static_js_string(LITERAL) + }) + .build(); + let builder = BuiltInBuilder::from_standard_constructor::(realm) + .static_accessor( + JsSymbol::species(), + Some(get_species), + None, + Attribute::CONFIGURABLE, + ) + .static_method( + Self::is_view, + { + const LITERAL: &crate::string::StaticJsString = &crate::string::StaticJsString::new( + ::boa_engine::string::JsStr::latin1( + [105, 115, 86, 105, 101, 119].as_slice(), + ), + ); + crate::string::JsString::from_static_js_string(LITERAL) + }, + 1, + ) + .accessor( + { + const LITERAL: &crate::string::StaticJsString = &crate::string::StaticJsString::new( + ::boa_engine::string::JsStr::latin1( + [98, 121, 116, 101, 76, 101, 110, 103, 116, 104].as_slice(), + ), + ); + crate::string::JsString::from_static_js_string(LITERAL) + }, + Some(get_byte_length), + None, + flag_attributes, + ) + .accessor( + { + const LITERAL: &crate::string::StaticJsString = &crate::string::StaticJsString::new( + ::boa_engine::string::JsStr::latin1( + [114, 101, 115, 105, 122, 97, 98, 108, 101].as_slice(), + ), + ); + crate::string::JsString::from_static_js_string(LITERAL) + }, + Some(get_resizable), + None, + flag_attributes, + ) + .accessor( + { + const LITERAL: &crate::string::StaticJsString = &crate::string::StaticJsString::new( + ::boa_engine::string::JsStr::latin1( + [ + 109, + 97, + 120, + 66, + 121, + 116, + 101, + 76, + 101, + 110, + 103, + 116, + 104, + ] + .as_slice(), + ), + ); + crate::string::JsString::from_static_js_string(LITERAL) + }, + Some(get_max_byte_length), + None, + flag_attributes, + ) + .method( + Self::resize, + { + const LITERAL: &crate::string::StaticJsString = &crate::string::StaticJsString::new( + ::boa_engine::string::JsStr::latin1( + [114, 101, 115, 105, 122, 101].as_slice(), + ), + ); + crate::string::JsString::from_static_js_string(LITERAL) + }, + 1, + ) + .method( + Self::slice, + { + const LITERAL: &crate::string::StaticJsString = &crate::string::StaticJsString::new( + ::boa_engine::string::JsStr::latin1( + [115, 108, 105, 99, 101].as_slice(), + ), + ); + crate::string::JsString::from_static_js_string(LITERAL) + }, + 2, + ) + .property( + JsSymbol::to_string_tag(), + Self::NAME, + Attribute::READONLY | Attribute::NON_ENUMERABLE + | Attribute::CONFIGURABLE, + ); + builder.build(); + } + fn get(intrinsics: &Intrinsics) -> JsObject { + Self::STANDARD_CONSTRUCTOR(intrinsics.constructors()).constructor() + } + } + impl BuiltInObject for ArrayBuffer { + const NAME: JsString = StaticJsStrings::ARRAY_BUFFER; + } + impl BuiltInConstructor for ArrayBuffer { + const LENGTH: usize = 1; + const STANDARD_CONSTRUCTOR: fn(&StandardConstructors) -> &StandardConstructor = StandardConstructors::array_buffer; + /// `ArrayBuffer ( length )` + /// + /// More information: + /// - [ECMAScript reference][spec] + /// + /// [spec]: https://tc39.es/ecma262/#sec-arraybuffer-length + fn constructor( + new_target: &JsValue, + args: &[JsValue], + context: &mut Context, + ) -> JsResult { + if new_target.is_undefined() { + return Err( + JsNativeError::typ() + .with_message( + "ArrayBuffer.constructor called with undefined new target", + ) + .into(), + ); + } + let byte_len = args.get_or_undefined(0).to_index(context)?; + let max_byte_len = get_max_byte_len(args.get_or_undefined(1), context)?; + Ok( + Self::allocate(new_target, byte_len, max_byte_len, context)? + .upcast() + .into(), + ) + } + } + impl ArrayBuffer { + /// `ArrayBuffer.isView ( arg )` + /// + /// More information: + /// - [ECMAScript reference][spec] + /// + /// [spec]: https://tc39.es/ecma262/#sec-arraybuffer.isview + + fn is_view( + _: &JsValue, + args: &[JsValue], + _context: &mut Context, + ) -> JsResult { + Ok( + args + .get_or_undefined(0) + .as_object() + .is_some_and(|obj| obj.is::() || obj.is::()) + .into(), + ) + } + /// `get ArrayBuffer [ @@species ]` + /// + /// More information: + /// - [ECMAScript reference][spec] + /// + /// [spec]: https://tc39.es/ecma262/#sec-get-arraybuffer-@@species + + fn get_species( + this: &JsValue, + _: &[JsValue], + _: &mut Context, + ) -> JsResult { + Ok(this.clone()) + } + /// `get ArrayBuffer.prototype.byteLength` + /// + /// More information: + /// - [ECMAScript reference][spec] + /// + /// [spec]: https://tc39.es/ecma262/#sec-get-arraybuffer.prototype.bytelength + pub(crate) fn get_byte_length( + this: &JsValue, + _args: &[JsValue], + _: &mut Context, + ) -> JsResult { + let buf = this + .as_object() + .and_then(JsObject::downcast_ref::) + .ok_or_else(|| { + JsNativeError::typ() + .with_message( + "get ArrayBuffer.prototype.byteLength called with invalid `this`", + ) + })?; + Ok(buf.len().into()) + } + /// [`get ArrayBuffer.prototype.maxByteLength`][spec]. + /// + /// [spec]: https://tc39.es/ecma262/#sec-get-arraybuffer.prototype.maxbytelength + pub(crate) fn get_max_byte_length( + this: &JsValue, + _args: &[JsValue], + _context: &mut Context, + ) -> JsResult { + let buf = this + .as_object() + .and_then(JsObject::downcast_ref::) + .ok_or_else(|| { + JsNativeError::typ() + .with_message( + "get ArrayBuffer.prototype.maxByteLength called with invalid `this`", + ) + })?; + let Some(data) = buf.bytes() else { + return Ok(JsValue::from(0)); + }; + Ok(buf.max_byte_len.unwrap_or(data.len() as u64).into()) + } + /// [`get ArrayBuffer.prototype.resizable`][spec]. + /// + /// [spec]: https://tc39.es/ecma262/#sec-get-arraybuffer.prototype.resizable + pub(crate) fn get_resizable( + this: &JsValue, + _args: &[JsValue], + _context: &mut Context, + ) -> JsResult { + let buf = this + .as_object() + .and_then(JsObject::downcast_ref::) + .ok_or_else(|| { + JsNativeError::typ() + .with_message( + "get ArrayBuffer.prototype.resizable called with invalid `this`", + ) + })?; + Ok(JsValue::from(!buf.is_fixed_len())) + } + /// [`ArrayBuffer.prototype.resize ( newLength )`][spec]. + /// + /// [spec]: https://tc39.es/ecma262/#sec-arraybuffer.prototype.resize + pub(crate) fn resize( + this: &JsValue, + args: &[JsValue], + context: &mut Context, + ) -> JsResult { + let buf = this + .as_object() + .and_then(|o| o.clone().downcast::().ok()) + .ok_or_else(|| { + JsNativeError::typ() + .with_message( + "ArrayBuffer.prototype.resize called with invalid `this`", + ) + })?; + let Some(max_byte_len) = buf.borrow().data.max_byte_len else { + return Err( + JsNativeError::typ() + .with_message( + "ArrayBuffer.resize: cannot resize a fixed-length buffer", + ) + .into(), + ); + }; + let new_byte_length = args.get_or_undefined(0).to_index(context)?; + let mut buf = buf.borrow_mut(); + let Some(buf) = buf.data.vec_mut() else { + return Err( + JsNativeError::typ() + .with_message( + "ArrayBuffer.resize: cannot resize a detached buffer", + ) + .into(), + ); + }; + if new_byte_length > max_byte_len { + return Err( + JsNativeError::range() + .with_message( + "ArrayBuffer.resize: new byte length exceeds buffer's maximum byte length", + ) + .into(), + ); + } + buf.resize(new_byte_length as usize, 0); + Ok(JsValue::undefined()) + } + /// `ArrayBuffer.prototype.slice ( start, end )` + /// + /// More information: + /// - [ECMAScript reference][spec] + /// + /// [spec]: https://tc39.es/ecma262/#sec-arraybuffer.prototype.slice + fn slice( + this: &JsValue, + args: &[JsValue], + context: &mut Context, + ) -> JsResult { + let buf = this + .as_object() + .and_then(|o| o.clone().downcast::().ok()) + .ok_or_else(|| { + JsNativeError::typ() + .with_message( + "ArrayBuffer.slice called with invalid `this` value", + ) + })?; + let len = { + let buf = buf.borrow(); + if buf.data.is_detached() { + return Err( + JsNativeError::typ() + .with_message( + "ArrayBuffer.slice called with detached buffer", + ) + .into(), + ); + } + buf.data.len() as u64 + }; + let first = Array::get_relative_start( + context, + args.get_or_undefined(0), + len, + )?; + let final_ = Array::get_relative_end( + context, + args.get_or_undefined(1), + len, + )?; + let new_len = final_.saturating_sub(first); + let ctor = buf + .clone() + .upcast() + .species_constructor(StandardConstructors::array_buffer, context)?; + let new = ctor.construct(&[new_len.into()], Some(&ctor), context)?; + let Ok(new) = new.downcast::() else { + return Err( + JsNativeError::typ() + .with_message("ArrayBuffer constructor returned invalid object") + .into(), + ); + }; + if JsObject::equals(&buf, &new) { + return Err( + JsNativeError::typ() + .with_message("new ArrayBuffer is the same as this ArrayBuffer") + .into(), + ); + } + { + let mut new = new.borrow_mut(); + let Some(to_buf) = new.data.bytes_mut() else { + return Err( + JsNativeError::typ() + .with_message( + "ArrayBuffer constructor returned detached ArrayBuffer", + ) + .into(), + ); + }; + if (to_buf.len() as u64) < new_len { + return Err( + JsNativeError::typ() + .with_message("new ArrayBuffer length too small") + .into(), + ); + } + let buf = buf.borrow(); + let Some(from_buf) = buf.data.bytes() else { + return Err( + JsNativeError::typ() + .with_message( + "ArrayBuffer detached while ArrayBuffer.slice was running", + ) + .into(), + ); + }; + let first = first as usize; + let new_len = new_len as usize; + to_buf[..new_len].copy_from_slice(&from_buf[first..first + new_len]); + } + Ok(new.upcast().into()) + } + /// `AllocateArrayBuffer ( constructor, byteLength )` + /// + /// More information: + /// - [ECMAScript reference][spec] + /// + /// [spec]: https://tc39.es/ecma262/#sec-allocatearraybuffer + pub(crate) fn allocate( + constructor: &JsValue, + byte_len: u64, + max_byte_len: Option, + context: &mut Context, + ) -> JsResult> { + if let Some(max_byte_len) = max_byte_len { + if byte_len > max_byte_len { + return Err( + JsNativeError::range() + .with_message( + "`length` cannot be bigger than `maxByteLength`", + ) + .into(), + ); + } + } + let prototype = get_prototype_from_constructor( + constructor, + StandardConstructors::array_buffer, + context, + )?; + let block = create_byte_data_block(byte_len, max_byte_len, context)?; + let obj = JsObject::new( + context.root_shape(), + prototype, + Self { + data: Some(block), + max_byte_len, + detach_key: JsValue::Undefined, + }, + ); + Ok(obj) + } + } + /// Abstract operation [`GetArrayBufferMaxByteLengthOption ( options )`][spec] + /// + /// [spec]: https://tc39.es/ecma262/#sec-getarraybuffermaxbytelengthoption + fn get_max_byte_len( + options: &JsValue, + context: &mut Context, + ) -> JsResult> { + let Some(options) = options.as_object() else { + return Ok(None); + }; + let max_byte_len = options + .get( + { + const LITERAL: &crate::string::StaticJsString = &crate::string::StaticJsString::new( + ::boa_engine::string::JsStr::latin1( + [ + 109, + 97, + 120, + 66, + 121, + 116, + 101, + 76, + 101, + 110, + 103, + 116, + 104, + ] + .as_slice(), + ), + ); + crate::string::JsString::from_static_js_string(LITERAL) + }, + context, + )?; + if max_byte_len.is_undefined() { + return Ok(None); + } + max_byte_len.to_index(context).map(Some) + } + /// `CreateByteDataBlock ( size )` abstract operation. + /// + /// The abstract operation `CreateByteDataBlock` takes argument `size` (a non-negative + /// integer). For more information, check the [spec][spec]. + /// + /// [spec]: https://tc39.es/ecma262/#sec-createbytedatablock + pub(crate) fn create_byte_data_block( + size: u64, + max_buffer_size: Option, + context: &mut Context, + ) -> JsResult> { + let alloc_size = max_buffer_size.unwrap_or(size); + if !(size <= alloc_size) { + ::core::panicking::panic("assertion failed: size <= alloc_size") + } + if alloc_size > context.host_hooks().max_buffer_size(context) { + return Err( + JsNativeError::range() + .with_message( + "cannot allocate a buffer that exceeds the maximum buffer size", + ) + .into(), + ); + } + let alloc_size = alloc_size + .try_into() + .map_err(|e| { + JsNativeError::range() + .with_message( + ::alloc::__export::must_use({ + let res = ::alloc::fmt::format( + format_args!("couldn\'t allocate the data block: {0}", e), + ); + res + }), + ) + })?; + let mut data_block = Vec::new(); + data_block + .try_reserve_exact(alloc_size) + .map_err(|e| { + JsNativeError::range() + .with_message( + ::alloc::__export::must_use({ + let res = ::alloc::fmt::format( + format_args!("couldn\'t allocate the data block: {0}", e), + ); + res + }), + ) + })?; + let size = size as usize; + data_block.resize(size, 0); + Ok(data_block) + } +} diff --git a/core/engine/src/builtins/array/mod.rs b/core/engine/src/builtins/array/mod.rs index 947f76d0ca..f3f52970c6 100644 --- a/core/engine/src/builtins/array/mod.rs +++ b/core/engine/src/builtins/array/mod.rs @@ -231,7 +231,7 @@ impl BuiltInConstructor for Array { let array = Self::array_create(0, Some(prototype), context) .expect("this ArrayCreate call must not fail"); // c. If Type(len) is not Number, then - #[allow(clippy::if_not_else)] + #[expect(clippy::if_not_else)] let int_len = if !len.is_number() { // i. Perform ! CreateDataPropertyOrThrow(array, "0", len). array @@ -441,7 +441,7 @@ impl Array { /// /// [spec]: https://tc39.es/ecma262/#sec-get-array-@@species /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/@@species - #[allow(clippy::unnecessary_wraps)] + #[expect(clippy::unnecessary_wraps)] fn get_species(this: &JsValue, _: &[JsValue], _: &mut Context) -> JsResult { // 1. Return the this value. Ok(this.clone()) @@ -1032,7 +1032,7 @@ impl Array { /// /// [spec]: https://tc39.es/ecma262/#sec-array.prototype.tostring /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/toString - #[allow(clippy::wrong_self_convention)] + pub(crate) fn to_string( this: &JsValue, _: &[JsValue], @@ -1062,7 +1062,6 @@ impl Array { /// /// [spec]: https://tc39.es/ecma262/#sec-array.prototype.reverse /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reverse - #[allow(clippy::else_if_without_else)] pub(crate) fn reverse( this: &JsValue, _: &[JsValue], @@ -1844,7 +1843,7 @@ impl Array { /// - [ECMAScript reference][spec] /// /// [spec]: https://tc39.es/ecma262/#sec-flattenintoarray - #[allow(clippy::too_many_arguments)] + #[expect(clippy::too_many_arguments)] fn flatten_into_array( target: &JsObject, source: &JsObject, @@ -3504,7 +3503,7 @@ fn array_set_length( let number_len = new_len_val.to_number(context)?; // 5. If SameValueZero(newLen, numberLen) is false, throw a RangeError exception. - #[allow(clippy::float_cmp)] + #[expect(clippy::float_cmp)] if f64::from(new_len) != number_len { return Err(JsNativeError::range() .with_message("bad length for array") diff --git a/core/engine/src/builtins/array_buffer/mod.rs b/core/engine/src/builtins/array_buffer/mod.rs index d5ea40ab55..bb2d43cbd5 100644 --- a/core/engine/src/builtins/array_buffer/mod.rs +++ b/core/engine/src/builtins/array_buffer/mod.rs @@ -417,7 +417,7 @@ impl ArrayBuffer { /// - [ECMAScript reference][spec] /// /// [spec]: https://tc39.es/ecma262/#sec-arraybuffer.isview - #[allow(clippy::unnecessary_wraps)] + #[expect(clippy::unnecessary_wraps)] fn is_view(_: &JsValue, args: &[JsValue], _context: &mut Context) -> JsResult { // 1. If Type(arg) is not Object, return false. // 2. If arg has a [[ViewedArrayBuffer]] internal slot, return true. @@ -435,7 +435,7 @@ impl ArrayBuffer { /// - [ECMAScript reference][spec] /// /// [spec]: https://tc39.es/ecma262/#sec-get-arraybuffer-@@species - #[allow(clippy::unnecessary_wraps)] + #[expect(clippy::unnecessary_wraps)] fn get_species(this: &JsValue, _: &[JsValue], _: &mut Context) -> JsResult { // 1. Return the this value. Ok(this.clone()) diff --git a/core/engine/src/builtins/array_buffer/shared.rs b/core/engine/src/builtins/array_buffer/shared.rs index a9be40ce3d..446250df80 100644 --- a/core/engine/src/builtins/array_buffer/shared.rs +++ b/core/engine/src/builtins/array_buffer/shared.rs @@ -197,7 +197,7 @@ impl SharedArrayBuffer { /// - [ECMAScript reference][spec] /// /// [spec]: https://tc39.es/ecma262/#sec-sharedarraybuffer-@@species - #[allow(clippy::unnecessary_wraps)] + #[expect(clippy::unnecessary_wraps)] fn get_species(this: &JsValue, _: &[JsValue], _: &mut Context) -> JsResult { // 1. Return the this value. Ok(this.clone()) diff --git a/core/engine/src/builtins/bigint/mod.rs b/core/engine/src/builtins/bigint/mod.rs index 947183afa5..119f3c4bd0 100644 --- a/core/engine/src/builtins/bigint/mod.rs +++ b/core/engine/src/builtins/bigint/mod.rs @@ -166,7 +166,7 @@ impl BigInt { /// /// [spec]: https://tc39.es/ecma262/#sec-bigint.prototype.tostring /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt/toString - #[allow(clippy::wrong_self_convention)] + pub(crate) fn to_string( this: &JsValue, args: &[JsValue], @@ -229,7 +229,7 @@ impl BigInt { /// /// [spec]: https://tc39.es/ecma262/#sec-bigint.asintn /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt/asIntN - #[allow(clippy::wrong_self_convention)] + pub(crate) fn as_int_n( _: &JsValue, args: &[JsValue], @@ -255,7 +255,7 @@ impl BigInt { /// /// [spec]: https://tc39.es/ecma262/#sec-bigint.asuintn /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt/asUintN - #[allow(clippy::wrong_self_convention)] + pub(crate) fn as_uint_n( _: &JsValue, args: &[JsValue], diff --git a/core/engine/src/builtins/boolean/mod.rs b/core/engine/src/builtins/boolean/mod.rs index b33525a023..dea6bfb3b5 100644 --- a/core/engine/src/builtins/boolean/mod.rs +++ b/core/engine/src/builtins/boolean/mod.rs @@ -107,7 +107,7 @@ impl Boolean { /// /// [spec]: https://tc39.es/ecma262/#sec-boolean-object /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean/toString - #[allow(clippy::wrong_self_convention)] + pub(crate) fn to_string(this: &JsValue, _: &[JsValue], _: &mut Context) -> JsResult { let boolean = Self::this_boolean_value(this)?; Ok(JsValue::new(js_string!(boolean.to_string()))) diff --git a/core/engine/src/builtins/builder.rs b/core/engine/src/builtins/builder.rs index 459a5104d9..2a3ffd1a2e 100644 --- a/core/engine/src/builtins/builder.rs +++ b/core/engine/src/builtins/builder.rs @@ -17,7 +17,7 @@ use super::{function::ConstructorKind, BuiltInConstructor, IntrinsicObject}; /// Marker for a constructor function. // TODO: Remove this marker and use `Constructor` directly. -#[allow(dead_code)] +#[expect(dead_code)] pub(crate) struct Constructor { prototype: JsObject, inherits: JsPrototype, @@ -26,7 +26,7 @@ pub(crate) struct Constructor { /// Marker for a constructor function without a custom prototype for its instances. // TODO: Remove this marker and use `ConstructorNoProto` directly. -#[allow(dead_code)] +#[expect(dead_code)] pub(crate) struct ConstructorNoProto; /// Marker for an ordinary function. @@ -179,7 +179,7 @@ pub(crate) struct BuiltInConstructorWithPrototype<'ctx> { attributes: Attribute, } -#[allow(dead_code)] +#[expect(dead_code)] impl BuiltInConstructorWithPrototype<'_> { /// Specify how many arguments the constructor function takes. /// @@ -349,7 +349,6 @@ impl BuiltInConstructorWithPrototype<'_> { /// Specifies the parent prototype which objects created by this constructor inherit from. /// /// Default is `Object.prototype`. - #[allow(clippy::missing_const_for_fn)] pub(crate) fn inherits(mut self, prototype: JsPrototype) -> Self { self.inherits = prototype; self diff --git a/core/engine/src/builtins/date/mod.rs b/core/engine/src/builtins/date/mod.rs index 13f5b5c577..2b29a7cfa0 100644 --- a/core/engine/src/builtins/date/mod.rs +++ b/core/engine/src/builtins/date/mod.rs @@ -322,7 +322,7 @@ impl Date { /// /// [spec]: https://tc39.es/ecma262/#sec-date.now /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/now - #[allow(clippy::unnecessary_wraps)] + #[expect(clippy::unnecessary_wraps)] pub(crate) fn now(_: &JsValue, _: &[JsValue], context: &mut Context) -> JsResult { Ok(JsValue::new(context.host_hooks().utc_now())) } @@ -939,7 +939,7 @@ impl Date { /// /// [local]: https://tc39.es/ecma262/#sec-date.prototype.sethours /// [utc]: https://tc39.es/ecma262/#sec-date.prototype.setutchours - #[allow(clippy::many_single_char_names)] + #[expect(clippy::many_single_char_names)] pub(crate) fn set_hours( this: &JsValue, args: &[JsValue], diff --git a/core/engine/src/builtins/error/mod.rs b/core/engine/src/builtins/error/mod.rs index 343080137b..cfae613fa8 100644 --- a/core/engine/src/builtins/error/mod.rs +++ b/core/engine/src/builtins/error/mod.rs @@ -232,7 +232,7 @@ impl Error { /// /// [spec]: https://tc39.es/ecma262/#sec-error.prototype.tostring /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error/toString - #[allow(clippy::wrong_self_convention)] + pub(crate) fn to_string( this: &JsValue, _: &[JsValue], diff --git a/core/engine/src/builtins/function/arguments.rs b/core/engine/src/builtins/function/arguments.rs index 83fd821287..f44cf72ac8 100644 --- a/core/engine/src/builtins/function/arguments.rs +++ b/core/engine/src/builtins/function/arguments.rs @@ -27,7 +27,7 @@ impl UnmappedArguments { /// - [ECMAScript reference][spec] /// /// [spec]: https://tc39.es/ecma262/#sec-createunmappedargumentsobject - #[allow(clippy::new_ret_no_self)] + #[expect(clippy::new_ret_no_self)] pub(crate) fn new(arguments_list: &[JsValue], context: &mut Context) -> JsObject { // 1. Let len be the number of elements in argumentsList. let len = arguments_list.len(); @@ -202,7 +202,7 @@ impl MappedArguments { /// Creates a new mapped Arguments exotic object. /// /// - #[allow(clippy::new_ret_no_self)] + #[expect(clippy::new_ret_no_self)] pub(crate) fn new( func: &JsObject, binding_indices: &[Option], @@ -313,7 +313,7 @@ pub(crate) fn arguments_exotic_get_own_property( /// - [ECMAScript reference][spec] /// /// [spec]: https://tc39.es/ecma262/#sec-arguments-exotic-objects-defineownproperty-p-desc -#[allow(clippy::needless_pass_by_value)] +#[expect(clippy::needless_pass_by_value)] pub(crate) fn arguments_exotic_define_own_property( obj: &JsObject, key: &PropertyKey, diff --git a/core/engine/src/builtins/function/bound.rs b/core/engine/src/builtins/function/bound.rs index a45ffde150..61b77badc8 100644 --- a/core/engine/src/builtins/function/bound.rs +++ b/core/engine/src/builtins/function/bound.rs @@ -99,7 +99,7 @@ impl BoundFunction { /// - [ECMAScript reference][spec] /// /// [spec]: https://tc39.es/ecma262/#sec-bound-function-exotic-objects-call-thisargument-argumentslist -#[allow(clippy::unnecessary_wraps)] +#[expect(clippy::unnecessary_wraps)] fn bound_function_exotic_call( obj: &JsObject, argument_count: usize, @@ -137,7 +137,7 @@ fn bound_function_exotic_call( /// - [ECMAScript reference][spec] /// /// [spec]: https://tc39.es/ecma262/#sec-bound-function-exotic-objects-construct-argumentslist-newtarget -#[allow(clippy::unnecessary_wraps)] +#[expect(clippy::unnecessary_wraps)] fn bound_function_exotic_construct( function_object: &JsObject, argument_count: usize, diff --git a/core/engine/src/builtins/function/mod.rs b/core/engine/src/builtins/function/mod.rs index 8c4967e564..3e1d9e5565 100644 --- a/core/engine/src/builtins/function/mod.rs +++ b/core/engine/src/builtins/function/mod.rs @@ -821,7 +821,7 @@ impl BuiltInFunctionObject { /// /// [spec]: https://tc39.es/ecma262/#sec-function.prototype.tostring /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/toString - #[allow(clippy::wrong_self_convention)] + fn to_string(this: &JsValue, _: &[JsValue], context: &mut Context) -> JsResult { // 1. Let func be the this value. let func = this; @@ -887,7 +887,7 @@ impl BuiltInFunctionObject { Ok(JsValue::ordinary_has_instance(this, args.get_or_undefined(0), context)?.into()) } - #[allow(clippy::unnecessary_wraps)] + #[expect(clippy::unnecessary_wraps)] fn prototype(_: &JsValue, _: &[JsValue], _: &mut Context) -> JsResult { Ok(JsValue::undefined()) } diff --git a/core/engine/src/builtins/function/tests.rs b/core/engine/src/builtins/function/tests.rs index fc59ced992..ad5c2738b3 100644 --- a/core/engine/src/builtins/function/tests.rs +++ b/core/engine/src/builtins/function/tests.rs @@ -9,7 +9,7 @@ use crate::{ use boa_macros::js_str; use indoc::indoc; -#[allow(clippy::float_cmp)] +#[expect(clippy::float_cmp)] #[test] fn arguments_object() { run_test_actions([ diff --git a/core/engine/src/builtins/intl/collator/mod.rs b/core/engine/src/builtins/intl/collator/mod.rs index ea700d78b9..27d3f5b588 100644 --- a/core/engine/src/builtins/intl/collator/mod.rs +++ b/core/engine/src/builtins/intl/collator/mod.rs @@ -43,7 +43,7 @@ mod options; pub(crate) use options::*; #[derive(Debug, Finalize, JsData)] -#[allow(clippy::struct_field_names)] +#[expect(clippy::struct_field_names)] pub(crate) struct Collator { locale: Locale, collation: Value, diff --git a/core/engine/src/builtins/intl/date_time_format.rs b/core/engine/src/builtins/intl/date_time_format.rs index f6dca66bfc..c220386f31 100644 --- a/core/engine/src/builtins/intl/date_time_format.rs +++ b/core/engine/src/builtins/intl/date_time_format.rs @@ -163,7 +163,6 @@ impl BuiltInConstructor for DateTimeFormat { /// /// Since `required` and `defaults` differ only in the `any` and `all` variants, /// we combine both in a single variant `AnyAll`. -#[allow(unused)] #[derive(Debug, PartialEq)] pub(crate) enum DateTimeReqs { Date, @@ -178,7 +177,7 @@ pub(crate) enum DateTimeReqs { /// - [ECMAScript reference][spec] /// /// [spec]: https://tc39.es/ecma402/#sec-todatetimeoptions -#[allow(unused)] +#[expect(unused)] pub(crate) fn to_date_time_options( options: &JsValue, required: &DateTimeReqs, diff --git a/core/engine/src/builtins/intl/list_format/mod.rs b/core/engine/src/builtins/intl/list_format/mod.rs index 9da43f072d..ebc4373a10 100644 --- a/core/engine/src/builtins/intl/list_format/mod.rs +++ b/core/engine/src/builtins/intl/list_format/mod.rs @@ -280,7 +280,6 @@ impl ListFormat { } } - #[allow(clippy::missing_const_for_fn)] fn value(self) -> String { match self { Self::Literal(s) | Self::Element(s) => s, diff --git a/core/engine/src/builtins/intl/number_format/options.rs b/core/engine/src/builtins/intl/number_format/options.rs index ccf33a328f..c393fed8f3 100644 --- a/core/engine/src/builtins/intl/number_format/options.rs +++ b/core/engine/src/builtins/intl/number_format/options.rs @@ -360,7 +360,6 @@ impl std::str::FromStr for Unit { impl ParsableOptionType for Unit {} #[derive(Debug)] -#[allow(variant_size_differences)] // 40 bytes is not big enough to require moving `Unit` to the heap. pub(crate) enum UnitFormatOptions { Decimal, Percent, diff --git a/core/engine/src/builtins/intl/plural_rules/mod.rs b/core/engine/src/builtins/intl/plural_rules/mod.rs index 03589c1958..e82e1814e2 100644 --- a/core/engine/src/builtins/intl/plural_rules/mod.rs +++ b/core/engine/src/builtins/intl/plural_rules/mod.rs @@ -429,7 +429,6 @@ impl PluralRules { } #[derive(Debug)] -#[allow(unused)] // Will be used when we implement `selectRange` struct ResolvedPlural { category: PluralCategory, formatted: Option, diff --git a/core/engine/src/builtins/map/mod.rs b/core/engine/src/builtins/map/mod.rs index 40223620e8..d901818e12 100644 --- a/core/engine/src/builtins/map/mod.rs +++ b/core/engine/src/builtins/map/mod.rs @@ -176,7 +176,7 @@ impl Map { /// /// [spec]: https://tc39.es/ecma262/#sec-get-map-@@species /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/@@species - #[allow(clippy::unnecessary_wraps)] + #[expect(clippy::unnecessary_wraps)] fn get_species(this: &JsValue, _: &[JsValue], _: &mut Context) -> JsResult { // 1. Return the this value. Ok(this.clone()) diff --git a/core/engine/src/builtins/math/mod.rs b/core/engine/src/builtins/math/mod.rs index f33e1f336c..a71672ce1a 100644 --- a/core/engine/src/builtins/math/mod.rs +++ b/core/engine/src/builtins/math/mod.rs @@ -695,7 +695,7 @@ impl Math { /// /// [spec]: https://tc39.es/ecma262/#sec-math.pow /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/pow - #[allow(clippy::float_cmp)] + #[expect(clippy::float_cmp)] pub(crate) fn pow(_: &JsValue, args: &[JsValue], context: &mut Context) -> JsResult { // 1. Set base to ? ToNumber(base). let x = args.get_or_undefined(0).to_number(context)?; @@ -737,7 +737,7 @@ impl Math { /// /// [spec]: https://tc39.es/ecma262/#sec-math.random /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/random - #[allow(clippy::unnecessary_wraps)] + #[expect(clippy::unnecessary_wraps)] pub(crate) fn random(_: &JsValue, _: &[JsValue], _: &mut Context) -> JsResult { // NOTE: Each Math.random function created for distinct realms must produce a distinct sequence of values from successive calls. Ok(rand::random::().into()) @@ -751,7 +751,7 @@ impl Math { /// /// [spec]: https://tc39.es/ecma262/#sec-math.round /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/round - #[allow(clippy::float_cmp)] + #[expect(clippy::float_cmp)] pub(crate) fn round(_: &JsValue, args: &[JsValue], context: &mut Context) -> JsResult { let num = args .get_or_undefined(0) diff --git a/core/engine/src/builtins/mod.rs b/core/engine/src/builtins/mod.rs index b9a738f059..d9323824f4 100644 --- a/core/engine/src/builtins/mod.rs +++ b/core/engine/src/builtins/mod.rs @@ -141,7 +141,6 @@ pub(crate) trait BuiltInObject: IntrinsicObject { /// assign `"Cplx"` to this constant, making any property inside it accessible from ECMAScript /// as `Cplx.prop` // `JsString` can only be const-constructed for static strings. - #[allow(clippy::declare_interior_mutable_const)] const NAME: JsString; /// Property attribute flags of the built-in. Check [`Attribute`] for more information. diff --git a/core/engine/src/builtins/number/conversions.rs b/core/engine/src/builtins/number/conversions.rs index b81a8539d6..c7cbd1bcaa 100644 --- a/core/engine/src/builtins/number/conversions.rs +++ b/core/engine/src/builtins/number/conversions.rs @@ -1,7 +1,7 @@ /// Converts a 64-bit floating point number to an `i32` according to the [`ToInt32`][ToInt32] algorithm. /// /// [ToInt32]: https://tc39.es/ecma262/#sec-toint32 -#[allow(clippy::float_cmp)] +#[expect(clippy::float_cmp)] pub(crate) fn f64_to_int32(number: f64) -> i32 { const SIGN_MASK: u64 = 0x8000_0000_0000_0000; const EXPONENT_MASK: u64 = 0x7FF0_0000_0000_0000; diff --git a/core/engine/src/builtins/number/globals.rs b/core/engine/src/builtins/number/globals.rs index 9e60320024..518e487fed 100644 --- a/core/engine/src/builtins/number/globals.rs +++ b/core/engine/src/builtins/number/globals.rs @@ -191,7 +191,6 @@ pub(crate) fn parse_int(_: &JsValue, args: &[JsValue], context: &mut Context) -> let mut strip_prefix = true; // 8. If R ≠ 0, then - #[allow(clippy::if_not_else)] let mut r = if r != 0 { // a. If R < 2 or R > 36, return NaN. if !(2..=36).contains(&r) { diff --git a/core/engine/src/builtins/number/mod.rs b/core/engine/src/builtins/number/mod.rs index 7334591278..6b565be8d5 100644 --- a/core/engine/src/builtins/number/mod.rs +++ b/core/engine/src/builtins/number/mod.rs @@ -214,7 +214,7 @@ impl Number { /// /// [spec]: https://tc39.es/ecma262/#sec-number.prototype.toexponential /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toExponential - #[allow(clippy::wrong_self_convention)] + pub(crate) fn to_exponential( this: &JsValue, args: &[JsValue], @@ -259,7 +259,7 @@ impl Number { /// /// [spec]: https://tc39.es/ecma262/#sec-number.prototype.tofixed /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toFixed - #[allow(clippy::wrong_self_convention)] + pub(crate) fn to_fixed( this: &JsValue, args: &[JsValue], @@ -300,7 +300,7 @@ impl Number { /// /// [spec]: https://tc39.es/ecma262/#sec-number.prototype.tolocalestring /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toLocaleString - #[allow(clippy::wrong_self_convention)] + pub(crate) fn to_locale_string( this: &JsValue, _: &[JsValue], @@ -408,7 +408,7 @@ impl Number { /// /// [spec]: https://tc39.es/ecma262/#sec-number.prototype.toprecision /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toPrecision - #[allow(clippy::wrong_self_convention)] + pub(crate) fn to_precision( this: &JsValue, args: &[JsValue], @@ -533,7 +533,7 @@ impl Number { } // https://chromium.googlesource.com/v8/v8/+/refs/heads/master/src/numbers/conversions.cc#1230 - #[allow(clippy::wrong_self_convention)] + pub(crate) fn to_js_string_radix(mut value: f64, radix: u8) -> JsString { assert!(radix >= 2); assert!(radix <= 36); @@ -643,7 +643,6 @@ impl Number { )) } - #[allow(clippy::wrong_self_convention)] pub(crate) fn to_js_string(x: f64) -> JsString { let mut buffer = ryu_js::Buffer::new(); js_string!(buffer.format(x).to_string()) @@ -659,7 +658,6 @@ impl Number { /// /// [spec]: https://tc39.es/ecma262/#sec-number.prototype.tostring /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toString - #[allow(clippy::wrong_self_convention)] pub(crate) fn to_string( this: &JsValue, args: &[JsValue], @@ -740,7 +738,7 @@ impl Number { /// /// [spec]: https://tc39.es/ecma262/#sec-number.isfinite /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isFinite - #[allow(clippy::unnecessary_wraps)] + #[expect(clippy::unnecessary_wraps)] pub(crate) fn number_is_finite( _: &JsValue, args: &[JsValue], @@ -766,7 +764,7 @@ impl Number { /// /// [spec]: https://tc39.es/ecma262/#sec-number.isinteger /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isInteger - #[allow(clippy::unnecessary_wraps)] + #[expect(clippy::unnecessary_wraps)] pub(crate) fn number_is_integer( _: &JsValue, args: &[JsValue], @@ -789,7 +787,7 @@ impl Number { /// /// [spec]: https://tc39.es/ecma262/#sec-isnan-number /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isNaN - #[allow(clippy::unnecessary_wraps)] + #[expect(clippy::unnecessary_wraps)] pub(crate) fn number_is_nan( _: &JsValue, args: &[JsValue], @@ -818,7 +816,7 @@ impl Number { /// /// [spec]: https://tc39.es/ecma262/#sec-isnan-number /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isNaN - #[allow(clippy::unnecessary_wraps)] + #[expect(clippy::unnecessary_wraps)] pub(crate) fn is_safe_integer( _: &JsValue, args: &[JsValue], @@ -848,7 +846,7 @@ impl Number { } /// Checks if the float argument is an integer. - #[allow(clippy::float_cmp)] + #[expect(clippy::float_cmp)] pub(crate) fn is_float_integer(number: f64) -> bool { number.is_finite() && number.trunc() == number } @@ -857,7 +855,7 @@ impl Number { /// x (a Number) and y (a Number). It performs the following steps when called: /// /// - #[allow(clippy::float_cmp)] + #[expect(clippy::float_cmp)] pub(crate) fn equal(x: f64, y: f64) -> bool { x == y } @@ -866,7 +864,7 @@ impl Number { /// x (a Number) and y (a Number). It performs the following steps when called: /// /// - #[allow(clippy::float_cmp)] + #[expect(clippy::float_cmp)] pub(crate) fn same_value(a: f64, b: f64) -> bool { if a.is_nan() && b.is_nan() { return true; @@ -878,7 +876,7 @@ impl Number { /// x (a Number) and y (a Number). It performs the following steps when called: /// /// - #[allow(clippy::float_cmp)] + #[expect(clippy::float_cmp)] pub(crate) fn same_value_zero(x: f64, y: f64) -> bool { if x.is_nan() && y.is_nan() { return true; @@ -887,7 +885,7 @@ impl Number { x == y } - #[allow(clippy::float_cmp)] + #[expect(clippy::float_cmp)] pub(crate) fn less_than(x: f64, y: f64) -> AbstractRelation { if x.is_nan() || y.is_nan() { return AbstractRelation::Undefined; diff --git a/core/engine/src/builtins/object/mod.rs b/core/engine/src/builtins/object/mod.rs index d90a5bd06a..fe43148e9a 100644 --- a/core/engine/src/builtins/object/mod.rs +++ b/core/engine/src/builtins/object/mod.rs @@ -820,7 +820,6 @@ impl OrdinaryObject { /// /// [spec]: https://tc39.es/ecma262/#sec-object.prototype.tostring /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/toString - #[allow(clippy::wrong_self_convention)] pub fn to_string(this: &JsValue, _: &[JsValue], context: &mut Context) -> JsResult { // 1. If the this value is undefined, return "[object Undefined]". if this.is_undefined() { @@ -888,7 +887,6 @@ impl OrdinaryObject { /// /// [spec]: https://tc39.es/ecma262/#sec-object.prototype.tolocalestring /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/toLocaleString - #[allow(clippy::wrong_self_convention)] pub fn to_locale_string( this: &JsValue, _: &[JsValue], diff --git a/core/engine/src/builtins/options.rs b/core/engine/src/builtins/options.rs index 4c939c9164..dc6d48a122 100644 --- a/core/engine/src/builtins/options.rs +++ b/core/engine/src/builtins/options.rs @@ -200,7 +200,7 @@ pub(crate) enum UnsignedRoundingMode { impl RoundingMode { // TODO: remove once confirmed. #[cfg(feature = "temporal")] - #[allow(dead_code)] + #[expect(dead_code)] pub(crate) const fn negate(self) -> Self { use RoundingMode::{ Ceil, Expand, Floor, HalfCeil, HalfEven, HalfExpand, HalfFloor, HalfTrunc, Trunc, @@ -221,7 +221,7 @@ impl RoundingMode { // TODO: remove once confirmed. #[cfg(feature = "temporal")] - #[allow(dead_code)] + #[expect(dead_code)] pub(crate) const fn get_unsigned_round_mode(self, is_negative: bool) -> UnsignedRoundingMode { use RoundingMode::{ Ceil, Expand, Floor, HalfCeil, HalfEven, HalfExpand, HalfFloor, HalfTrunc, Trunc, diff --git a/core/engine/src/builtins/promise/mod.rs b/core/engine/src/builtins/promise/mod.rs index f9e0fe4e08..49330ddad1 100644 --- a/core/engine/src/builtins/promise/mod.rs +++ b/core/engine/src/builtins/promise/mod.rs @@ -1549,7 +1549,7 @@ impl Promise { /// /// [spec]: https://tc39.es/ecma262/#sec-get-promise-@@species /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/@@species - #[allow(clippy::unnecessary_wraps)] + #[expect(clippy::unnecessary_wraps)] fn get_species(this: &JsValue, _: &[JsValue], _: &mut Context) -> JsResult { // 1. Return the this value. Ok(this.clone()) diff --git a/core/engine/src/builtins/promise/tests.rs b/core/engine/src/builtins/promise/tests.rs index 7f6c316fb9..0117b51e28 100644 --- a/core/engine/src/builtins/promise/tests.rs +++ b/core/engine/src/builtins/promise/tests.rs @@ -13,7 +13,7 @@ fn promise() { count += 1; "#}), TestAction::assert_eq("count", 2), - #[allow(clippy::redundant_closure_for_method_calls)] + #[expect(clippy::redundant_closure_for_method_calls)] TestAction::inspect_context(|ctx| ctx.run_jobs()), TestAction::assert_eq("count", 3), ]); diff --git a/core/engine/src/builtins/regexp/mod.rs b/core/engine/src/builtins/regexp/mod.rs index beb782af1a..6929841d94 100644 --- a/core/engine/src/builtins/regexp/mod.rs +++ b/core/engine/src/builtins/regexp/mod.rs @@ -421,7 +421,7 @@ impl RegExp { /// /// [spec]: https://tc39.es/ecma262/#sec-get-regexp-@@species /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/@@species - #[allow(clippy::unnecessary_wraps)] + #[expect(clippy::unnecessary_wraps)] fn get_species(this: &JsValue, _: &[JsValue], _: &mut Context) -> JsResult { // 1. Return the this value. Ok(this.clone()) @@ -1081,7 +1081,7 @@ impl RegExp { // 30. If R contains any GroupName, then // 31. Else, // 33. For each integer i such that 1 ≤ i ≤ n, in ascending order, do - #[allow(clippy::if_not_else)] + #[expect(clippy::if_not_else)] let (groups, group_names) = if !named_groups.clone().is_empty() { // a. Let groups be OrdinaryObjectCreate(null). let groups = JsObject::with_null_proto(); @@ -1297,7 +1297,6 @@ impl RegExp { /// /// [spec]: https://tc39.es/ecma262/#sec-regexp.prototype.tostring /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/toString - #[allow(clippy::wrong_self_convention)] pub(crate) fn to_string( this: &JsValue, _: &[JsValue], diff --git a/core/engine/src/builtins/set/mod.rs b/core/engine/src/builtins/set/mod.rs index c29fca4f4e..446a111776 100644 --- a/core/engine/src/builtins/set/mod.rs +++ b/core/engine/src/builtins/set/mod.rs @@ -208,7 +208,7 @@ impl Set { /// /// [spec]: https://tc39.es/ecma262/#sec-get-set-@@species /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set/@@species - #[allow(clippy::unnecessary_wraps)] + #[expect(clippy::unnecessary_wraps)] fn get_species(this: &JsValue, _: &[JsValue], _: &mut Context) -> JsResult { // 1. Return the this value. Ok(this.clone()) diff --git a/core/engine/src/builtins/string/mod.rs b/core/engine/src/builtins/string/mod.rs index 7656c3a0cb..3d4b83ee31 100644 --- a/core/engine/src/builtins/string/mod.rs +++ b/core/engine/src/builtins/string/mod.rs @@ -473,7 +473,6 @@ impl String { /// - [ECMAScript reference][spec] /// /// [spec]: https://tc39.es/ecma262/#sec-string.prototype.tostring - #[allow(clippy::wrong_self_convention)] pub(crate) fn to_string(this: &JsValue, _: &[JsValue], _: &mut Context) -> JsResult { // 1. Return ? thisStringValue(this value). Ok(Self::this_string_value(this)?.into()) @@ -2757,7 +2756,7 @@ pub(crate) fn get_substitution( } // c. If none is found, the replacement text is the String "$<". - #[allow(clippy::if_not_else)] + #[expect(clippy::if_not_else)] if !found { result.extend_from_slice(utf16!("$<")); result.extend_from_slice(&group_name); diff --git a/core/engine/src/builtins/symbol/mod.rs b/core/engine/src/builtins/symbol/mod.rs index ca18aee702..b34d91707b 100644 --- a/core/engine/src/builtins/symbol/mod.rs +++ b/core/engine/src/builtins/symbol/mod.rs @@ -256,7 +256,6 @@ impl Symbol { /// /// [spec]: https://tc39.es/ecma262/#sec-symbol.prototype.tostring /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/toString - #[allow(clippy::wrong_self_convention)] pub(crate) fn to_string(this: &JsValue, _: &[JsValue], _: &mut Context) -> JsResult { // 1. Let sym be ? thisSymbolValue(this value). let symbol = Self::this_symbol_value(this)?; diff --git a/core/engine/src/builtins/temporal/calendar/mod.rs b/core/engine/src/builtins/temporal/calendar/mod.rs index 11b5a4a049..8a3a72726c 100644 --- a/core/engine/src/builtins/temporal/calendar/mod.rs +++ b/core/engine/src/builtins/temporal/calendar/mod.rs @@ -9,7 +9,7 @@ use temporal_rs::components::calendar::Calendar; // -- `Calendar` Abstract Operations -- /// 12.2.21 `GetTemporalCalendarSlotValueWithISODefault ( item )` -#[allow(unused)] +#[expect(unused)] pub(crate) fn get_temporal_calendar_slot_value_with_default( item: &JsObject, context: &mut Context, diff --git a/core/engine/src/builtins/temporal/mod.rs b/core/engine/src/builtins/temporal/mod.rs index 9f4fd983aa..75e3f83165 100644 --- a/core/engine/src/builtins/temporal/mod.rs +++ b/core/engine/src/builtins/temporal/mod.rs @@ -54,7 +54,6 @@ pub(crate) fn ns_min_instant() -> JsBigInt { } // An enum representing common fields across `Temporal` objects. -#[allow(unused)] pub(crate) enum DateTimeValues { Year, Month, @@ -323,7 +322,7 @@ pub(crate) fn is_partial_temporal_object<'value>( /// 13.43 `ToPositiveIntegerWithTruncation ( argument )` #[inline] -#[allow(unused)] +#[expect(unused)] pub(crate) fn to_positive_integer_with_trunc( value: &JsValue, context: &mut Context, diff --git a/core/engine/src/builtins/temporal/now.rs b/core/engine/src/builtins/temporal/now.rs index 45da161bc2..079d0787e5 100644 --- a/core/engine/src/builtins/temporal/now.rs +++ b/core/engine/src/builtins/temporal/now.rs @@ -62,7 +62,7 @@ impl Now { /// - [ECMAScript specification][spec] /// /// [spec]: https://tc39.es/proposal-temporal/#sec-temporal.now.timezone - #[allow(clippy::unnecessary_wraps)] + fn time_zone_id(_: &JsValue, _args: &[JsValue], context: &mut Context) -> JsResult { // 1. Return ! SystemTimeZone(). system_time_zone(context)? @@ -140,32 +140,32 @@ fn clamp_epoc_nanos(ns: JsBigInt) -> JsBigInt { } /// 2.3.2 `SystemUTCEpochMilliseconds` -#[allow(unused)] +#[expect(unused)] fn system_utc_epoch_millis() -> JsResult { let now = host_system_utc_epoch_nanoseconds()?; Ok(now.to_f64().div_euclid(1_000_000_f64).floor()) } /// 2.3.3 `SystemUTCEpochNanoseconds` -#[allow(unused)] +#[expect(unused)] fn system_utc_epoch_nanos() -> JsResult { host_system_utc_epoch_nanoseconds() } /// `SystemInstant` -#[allow(unused)] +#[expect(unused)] fn system_instant() { todo!() } /// `SystemDateTime` -#[allow(unused)] +#[expect(unused)] fn system_date_time() { todo!() } /// `SystemZonedDateTime` -#[allow(unused)] +#[expect(unused)] fn system_zoned_date_time() { todo!() } @@ -176,7 +176,7 @@ fn system_zoned_date_time() { /// - [ECMAScript specififcation][spec] /// /// [spec]: https://tc39.es/proposal-temporal/#sec-temporal-systemtimezone -#[allow(unused)] +#[expect(unused)] fn system_time_zone(context: &mut Context) -> JsResult { // 1. Let identifier be ! DefaultTimeZone(). let identifier = default_time_zone(context); diff --git a/core/engine/src/builtins/temporal/options.rs b/core/engine/src/builtins/temporal/options.rs index 06b83e2087..1fbe9ec931 100644 --- a/core/engine/src/builtins/temporal/options.rs +++ b/core/engine/src/builtins/temporal/options.rs @@ -63,7 +63,7 @@ pub(crate) fn get_difference_settings( } #[derive(Debug, Clone, Copy)] -#[allow(unused)] +#[expect(unused)] pub(crate) enum TemporalUnitGroup { Date, // Need to assert if this is neede anymore with the removal of `Temporal.Calendar` Time, diff --git a/core/engine/src/builtins/temporal/time_zone/mod.rs b/core/engine/src/builtins/temporal/time_zone/mod.rs index c5cd5c6b6c..35158e04b7 100644 --- a/core/engine/src/builtins/temporal/time_zone/mod.rs +++ b/core/engine/src/builtins/temporal/time_zone/mod.rs @@ -19,7 +19,7 @@ use crate::{builtins::temporal::to_zero_padded_decimal_string, Context}; /// - [ECMAScript specififcation][spec] /// /// [spec]: https://tc39.es/proposal-temporal/#sec-defaulttimezone -#[allow(unused)] +#[expect(unused)] pub(super) fn default_time_zone(context: &mut Context) -> String { // The minimum implementation of DefaultTimeZone for ECMAScript implementations that do not // include the ECMA-402 API, supporting only the "UTC" time zone, performs the following steps diff --git a/core/engine/src/builtins/typed_array/builtin.rs b/core/engine/src/builtins/typed_array/builtin.rs index cde663cd6e..3e48c6d9db 100644 --- a/core/engine/src/builtins/typed_array/builtin.rs +++ b/core/engine/src/builtins/typed_array/builtin.rs @@ -352,7 +352,7 @@ impl BuiltinTypedArray { /// - [ECMAScript reference][spec] /// /// [spec]: https://tc39.es/ecma262/#sec-get-%typedarray%-@@species - #[allow(clippy::unnecessary_wraps)] + #[expect(clippy::unnecessary_wraps)] pub(super) fn get_species(this: &JsValue, _: &[JsValue], _: &mut Context) -> JsResult { // 1. Return the this value. Ok(this.clone()) @@ -1553,7 +1553,6 @@ impl BuiltinTypedArray { /// - [ECMAScript reference][spec] /// /// [spec]: https://tc39.es/ecma262/#sec-%typedarray%.prototype.reverse - #[allow(clippy::float_cmp)] pub(crate) fn reverse( this: &JsValue, _: &[JsValue], @@ -2596,7 +2595,7 @@ impl BuiltinTypedArray { /// - [ECMAScript reference][spec] /// /// [spec]: https://tc39.es/ecma262/#sec-get-%typedarray%.prototype-@@tostringtag - #[allow(clippy::unnecessary_wraps)] + #[expect(clippy::unnecessary_wraps)] pub(crate) fn to_string_tag( this: &JsValue, _: &[JsValue], diff --git a/core/engine/src/builtins/typed_array/element/mod.rs b/core/engine/src/builtins/typed_array/element/mod.rs index e3fe61d555..b8ab9e1a5d 100644 --- a/core/engine/src/builtins/typed_array/element/mod.rs +++ b/core/engine/src/builtins/typed_array/element/mod.rs @@ -250,8 +250,7 @@ macro_rules! element { to_be: $to_be:expr, to_le: $to_le:expr $(,)? ) => { - #[allow(clippy::redundant_closure_call)] - #[allow(clippy::undocumented_unsafe_blocks)] // Invariants are checked by the caller. + #[expect(clippy::undocumented_unsafe_blocks)] // Invariants are checked by the caller. impl Element for $element { type Atomic = $atomic; diff --git a/core/engine/src/builtins/typed_array/mod.rs b/core/engine/src/builtins/typed_array/mod.rs index 168464d25e..56c3f78657 100644 --- a/core/engine/src/builtins/typed_array/mod.rs +++ b/core/engine/src/builtins/typed_array/mod.rs @@ -515,7 +515,7 @@ impl TypedArrayElement { /// This is guaranteed to never fail, since all numeric types supported by JS are less than /// 8 bytes long. pub(crate) fn to_bits(self) -> u64 { - #[allow(clippy::cast_lossless)] + #[expect(clippy::cast_lossless)] match self { TypedArrayElement::Int8(num) => num as u64, TypedArrayElement::Uint8(num) => num as u64, diff --git a/core/engine/src/builtins/typed_array/object.rs b/core/engine/src/builtins/typed_array/object.rs index 0389956c5e..824bd11084 100644 --- a/core/engine/src/builtins/typed_array/object.rs +++ b/core/engine/src/builtins/typed_array/object.rs @@ -563,7 +563,7 @@ pub(crate) fn typed_array_exotic_delete( /// - [ECMAScript reference][spec] /// /// [spec]: https://tc39.es/ecma262/#sec-typedarray-ownpropertykeys -#[allow(clippy::unnecessary_wraps)] +#[expect(clippy::unnecessary_wraps)] pub(crate) fn typed_array_exotic_own_property_keys( obj: &JsObject, _context: &mut Context, diff --git a/core/engine/src/builtins/uri/mod.rs b/core/engine/src/builtins/uri/mod.rs index 0e7fb3d476..706e2f708d 100644 --- a/core/engine/src/builtins/uri/mod.rs +++ b/core/engine/src/builtins/uri/mod.rs @@ -362,7 +362,7 @@ where /// - [ECMAScript reference][spec] /// /// [spec]: https://tc39.es/ecma262/#sec-decode -#[allow(clippy::many_single_char_names)] +#[expect(clippy::many_single_char_names)] fn decode(string: &JsString, reserved_set: F) -> JsResult where F: Fn(u16) -> bool, @@ -387,7 +387,7 @@ where let c = string.get_expect(k); // c. If C is not the code unit 0x0025 (PERCENT SIGN), then - #[allow(clippy::if_not_else)] + #[expect(clippy::if_not_else)] let s = if c != 0x0025_u16 { // i. Let S be the String value containing only the code unit C. Vec::from([c]) diff --git a/core/engine/src/bytecompiler/declarations.rs b/core/engine/src/bytecompiler/declarations.rs index e040c99a5d..94ccdb64d3 100644 --- a/core/engine/src/bytecompiler/declarations.rs +++ b/core/engine/src/bytecompiler/declarations.rs @@ -3,6 +3,7 @@ use crate::{ vm::{BindingOpcode, Opcode}, Context, JsNativeError, JsResult, }; +use boa_ast::operations::annex_b_function_declarations_names; use boa_ast::{ declaration::Binding, expression::Identifier, @@ -19,9 +20,6 @@ use boa_ast::{ }; use boa_interner::{JStrRef, Sym}; -#[cfg(feature = "annex-b")] -use boa_ast::operations::annex_b_function_declarations_names; - use super::{Operand, ToJsString}; /// `GlobalDeclarationInstantiation ( script, env )` @@ -33,34 +31,16 @@ use super::{Operand, ToJsString}; /// - [ECMAScript reference][spec] /// /// [spec]: https://tc39.es/ecma262/#sec-globaldeclarationinstantiation -#[cfg(not(feature = "annex-b"))] -#[allow(clippy::unnecessary_wraps)] -#[allow(clippy::ptr_arg)] -pub(crate) fn global_declaration_instantiation_context( - _annex_b_function_names: &mut Vec, - _script: &Script, - _env: &Scope, - _context: &mut Context, -) -> JsResult<()> { - Ok(()) -} - -/// `GlobalDeclarationInstantiation ( script, env )` -/// -/// This diverges from the specification by separating the context from the compilation process. -/// Many steps are skipped that are done during bytecode compilation. -/// -/// More information: -/// - [ECMAScript reference][spec] -/// -/// [spec]: https://tc39.es/ecma262/#sec-globaldeclarationinstantiation -#[cfg(feature = "annex-b")] pub(crate) fn global_declaration_instantiation_context( annex_b_function_names: &mut Vec, script: &Script, env: &Scope, context: &mut Context, ) -> JsResult<()> { + if cfg!(not(feature = "annex-b")) { + return Ok(()); + } + // SKIP: 1. Let lexNames be the LexicallyDeclaredNames of script. // SKIP: 2. Let varNames be the VarDeclaredNames of script. // SKIP: 3. For each element name of lexNames, do @@ -198,11 +178,11 @@ pub(crate) fn global_declaration_instantiation_context( /// /// [spec]: https://tc39.es/ecma262/#sec-evaldeclarationinstantiation pub(crate) fn eval_declaration_instantiation_context( - #[allow(unused, clippy::ptr_arg)] annex_b_function_names: &mut Vec, + annex_b_function_names: &mut Vec, body: &Script, - #[allow(unused)] strict: bool, - #[allow(unused)] var_env: &Scope, - #[allow(unused)] lex_env: &Scope, + strict: bool, + var_env: &Scope, + lex_env: &Scope, context: &mut Context, ) -> JsResult<()> { // SKIP: 3. If strict is false, then @@ -234,18 +214,19 @@ pub(crate) fn eval_declaration_instantiation_context( .into()); } + if cfg!(not(feature = "annex-b")) { + return Ok(()); + } + // 2. Let varDeclarations be the VarScopedDeclarations of body. - #[cfg(feature = "annex-b")] let var_declarations = var_scoped_declarations(body); // SKIP: 8. Let functionsToInitialize be a new empty List. // 9. Let declaredFunctionNames be a new empty List. - #[cfg(feature = "annex-b")] let mut declared_function_names = Vec::new(); // 10. For each element d of varDeclarations, in reverse List order, do - #[cfg(feature = "annex-b")] for declaration in var_declarations.iter().rev() { // a. If d is not either a VariableDeclaration, a ForBinding, or a BindingIdentifier, then // a.i. Assert: d is either a FunctionDeclaration, a GeneratorDeclaration, an AsyncFunctionDeclaration, or an AsyncGeneratorDeclaration. @@ -272,7 +253,6 @@ pub(crate) fn eval_declaration_instantiation_context( // 11. NOTE: Annex B.3.2.3 adds additional steps at this point. // 11. If strict is false, then - #[cfg(feature = "annex-b")] if !strict { let lexically_declared_names = lexically_declared_names(body); @@ -608,7 +588,7 @@ impl ByteCompiler<'_> { pub(crate) fn eval_declaration_instantiation( &mut self, body: &Script, - #[allow(unused_variables)] strict: bool, + strict: bool, var_env: &Scope, bindings: EvalDeclarationBindings, ) { @@ -1049,8 +1029,7 @@ impl ByteCompiler<'_> { // 27. If hasParameterExpressions is false, then // 28. Else, - #[allow(unused_variables, unused_mut)] - let (mut instantiated_var_names, mut variable_scope) = + let (instantiated_var_names, variable_scope) = if let Some(scope) = scopes.parameters_scope() { // a. NOTE: A separate Environment Record is needed to ensure that closures created by // expressions in the formal parameter list do not have @@ -1060,7 +1039,7 @@ impl ByteCompiler<'_> { let scope_index = self.push_scope(scope); self.emit_with_varying_operand(Opcode::PushScope, scope_index); - let mut variable_scope = self.lexical_scope.clone(); + let variable_scope = self.lexical_scope.clone(); // d. Let instantiatedVarNames be a new empty List. let mut instantiated_var_names = Vec::new(); @@ -1136,6 +1115,7 @@ impl ByteCompiler<'_> { // 29. If strict is false, then #[cfg(feature = "annex-b")] if !strict { + let mut instantiated_var_names = instantiated_var_names; // a. For each FunctionDeclaration f that is directly contained in the StatementList // of a Block, CaseClause, or DefaultClause, do for f in annex_b_function_declarations_names(body) { diff --git a/core/engine/src/bytecompiler/function.rs b/core/engine/src/bytecompiler/function.rs index 3fef0a612d..9fc951802f 100644 --- a/core/engine/src/bytecompiler/function.rs +++ b/core/engine/src/bytecompiler/function.rs @@ -14,7 +14,7 @@ use boa_interner::Interner; /// `FunctionCompiler` is used to compile AST functions to bytecode. #[derive(Debug, Clone)] -#[allow(clippy::struct_excessive_bools)] +#[expect(clippy::struct_excessive_bools)] pub(crate) struct FunctionCompiler { name: JsString, generator: bool, diff --git a/core/engine/src/bytecompiler/mod.rs b/core/engine/src/bytecompiler/mod.rs index da428e4e2d..a1c918caa3 100644 --- a/core/engine/src/bytecompiler/mod.rs +++ b/core/engine/src/bytecompiler/mod.rs @@ -356,7 +356,7 @@ impl Access<'_> { /// An opcode operand. #[derive(Debug, Clone, Copy)] -#[allow(unused)] +#[expect(unused)] pub(crate) enum Operand { Bool(bool), I8(i8), @@ -372,7 +372,6 @@ pub(crate) enum Operand { /// The [`ByteCompiler`] is used to compile ECMAScript AST from [`boa_ast`] to bytecode. #[derive(Debug)] -#[allow(clippy::struct_excessive_bools)] pub struct ByteCompiler<'ctx> { /// Name of this function. pub(crate) function_name: JsString, @@ -444,8 +443,8 @@ impl<'ctx> ByteCompiler<'ctx> { /// Creates a new [`ByteCompiler`]. #[inline] - #[allow(clippy::too_many_arguments)] - #[allow(clippy::fn_params_excessive_bools)] + #[expect(clippy::too_many_arguments)] + #[expect(clippy::fn_params_excessive_bools)] pub(crate) fn new( name: JsString, strict: bool, @@ -685,12 +684,12 @@ impl<'ctx> ByteCompiler<'ctx> { } /// TODO: Temporary function, remove once transition is complete. - #[allow(unused)] + #[expect(unused)] fn pop_into_register(&mut self, dst: &Register) { self.emit(Opcode::PopIntoRegister, &[Operand::Varying(dst.index())]); } /// TODO: Temporary function, remove once transition is complete. - #[allow(unused)] + #[expect(unused)] fn push_from_register(&mut self, src: &Register) { self.emit(Opcode::PushFromRegister, &[Operand::Varying(src.index())]); } @@ -860,7 +859,7 @@ impl<'ctx> ByteCompiler<'ctx> { } else { let f32_value = value as f32; - #[allow(clippy::float_cmp)] + #[expect(clippy::float_cmp)] if f64::from(f32_value) == value { self.emit(Opcode::PushFloat, &[Operand::U32(f32_value.to_bits())]); } else { @@ -1448,7 +1447,6 @@ impl<'ctx> ByteCompiler<'ctx> { } /// Compile a [`Declaration`]. - #[allow(unused_variables)] pub fn compile_decl(&mut self, decl: &Declaration, block: bool) { match decl { #[cfg(feature = "annex-b")] @@ -1746,7 +1744,6 @@ impl<'ctx> ByteCompiler<'ctx> { /// Finish compiling code with the [`ByteCompiler`] and return the generated [`CodeBlock`]. #[inline] #[must_use] - #[allow(clippy::missing_const_for_fn)] pub fn finish(mut self) -> CodeBlock { // Push return at the end of the function compilation. if let Some(async_handler) = self.async_handler { diff --git a/core/engine/src/bytecompiler/module.rs b/core/engine/src/bytecompiler/module.rs index f29d473d71..5deb11aca9 100644 --- a/core/engine/src/bytecompiler/module.rs +++ b/core/engine/src/bytecompiler/module.rs @@ -26,7 +26,7 @@ impl ByteCompiler<'_> { // 1. Return empty. } ModuleItem::ExportDeclaration(export) => { - #[allow(clippy::match_same_arms)] + #[expect(clippy::match_same_arms)] match export { ExportDeclaration::ReExport { .. } | ExportDeclaration::List(_) => { // ExportDeclaration : diff --git a/core/engine/src/bytecompiler/register.rs b/core/engine/src/bytecompiler/register.rs index b0c288637b..9e6e32bfb8 100644 --- a/core/engine/src/bytecompiler/register.rs +++ b/core/engine/src/bytecompiler/register.rs @@ -108,7 +108,7 @@ impl RegisterAllocator { reg } - #[allow(unused)] + #[expect(unused)] pub(crate) fn dealloc(&mut self, reg: Register) { assert!( !reg.flags.is_persistent(), diff --git a/core/engine/src/bytecompiler/statement/continue.rs b/core/engine/src/bytecompiler/statement/continue.rs index d05611da26..441fa7e076 100644 --- a/core/engine/src/bytecompiler/statement/continue.rs +++ b/core/engine/src/bytecompiler/statement/continue.rs @@ -5,7 +5,6 @@ use crate::bytecompiler::{ use boa_ast::statement::Continue; impl ByteCompiler<'_> { - #[allow(clippy::unnecessary_wraps)] pub(crate) fn compile_continue(&mut self, node: Continue, _use_expr: bool) { let actions = self.continue_jump_record_actions(node); diff --git a/core/engine/src/class.rs b/core/engine/src/class.rs index 609f74ced3..41757fa7da 100644 --- a/core/engine/src/class.rs +++ b/core/engine/src/class.rs @@ -138,7 +138,7 @@ pub trait Class: NativeObject + Sized { /// /// Useful to initialize additional properties for the constructed object that aren't /// stored inside the native data. - #[allow(unused_variables)] // Saves work when IDEs autocomplete trait impls. + #[expect(unused_variables)] // Saves work when IDEs autocomplete trait impls. fn object_constructor( instance: &JsObject, args: &[JsValue], diff --git a/core/engine/src/context/mod.rs b/core/engine/src/context/mod.rs index dd27ebf8f6..ea56c0432a 100644 --- a/core/engine/src/context/mod.rs +++ b/core/engine/src/context/mod.rs @@ -182,7 +182,6 @@ impl Context { /// /// Note that this won't run any scheduled promise jobs; you need to call [`Context::run_jobs`] /// on the context or [`JobQueue::run_jobs`] on the provided queue to run them. - #[allow(clippy::unit_arg, dropping_copy_types)] pub fn eval(&mut self, src: Source<'_, R>) -> JsResult { let main_timer = Profiler::global().start_event("Script evaluation", "Main"); @@ -482,7 +481,7 @@ impl Context { /// Concurrent job execution cannot be guaranteed by the engine, since this depends on the /// specific handling of each [`JobQueue`]. If you want to execute jobs concurrently, you must /// provide a custom implementor of `JobQueue` to the context. - #[allow(clippy::future_not_send)] + #[expect(clippy::future_not_send)] pub async fn run_jobs_async(&mut self) { self.job_queue().run_jobs_async(self).await; self.clear_kept_objects(); @@ -922,7 +921,6 @@ impl ContextBuilder { /// This is useful when you want to initialize an [`Interner`] with /// a collection of words before parsing. #[must_use] - #[allow(clippy::missing_const_for_fn)] pub fn interner(mut self, interner: Interner) -> Self { self.interner = Some(interner); self diff --git a/core/engine/src/host_defined.rs b/core/engine/src/host_defined.rs index df523f27f4..b1027b7d41 100644 --- a/core/engine/src/host_defined.rs +++ b/core/engine/src/host_defined.rs @@ -9,7 +9,7 @@ use crate::object::NativeObject; /// /// This allows storing types which are mapped by their [`TypeId`]. #[derive(Default, Trace, Finalize)] -#[allow(missing_debug_implementations)] +#[expect(missing_debug_implementations)] pub struct HostDefined { // INVARIANT: All key-value pairs `(id, obj)` satisfy: // `id == TypeId::of::() && obj.is::()` diff --git a/core/engine/src/job.rs b/core/engine/src/job.rs index 63cd6b794d..a9b05b6bba 100644 --- a/core/engine/src/job.rs +++ b/core/engine/src/job.rs @@ -65,7 +65,7 @@ pub type FutureJob = Pin + 'static>>; /// [Job]: https://tc39.es/ecma262/#sec-jobs /// [`NativeFunction`]: crate::native_function::NativeFunction pub struct NativeJob { - #[allow(clippy::type_complexity)] + #[expect(clippy::type_complexity)] f: Box JsResult>, realm: Option, } diff --git a/core/engine/src/module/loader.rs b/core/engine/src/module/loader.rs index 8a90fab679..a688cfb162 100644 --- a/core/engine/src/module/loader.rs +++ b/core/engine/src/module/loader.rs @@ -168,7 +168,7 @@ pub trait ModuleLoader { /// /// [spec]: https://tc39.es/ecma262/#sec-HostLoadImportedModule /// [finish]: https://tc39.es/ecma262/#sec-FinishLoadingImportedModule - #[allow(clippy::type_complexity)] + #[expect(clippy::type_complexity)] fn load_imported_module( &self, referrer: Referrer, diff --git a/core/engine/src/module/mod.rs b/core/engine/src/module/mod.rs index c8692895b6..263bced642 100644 --- a/core/engine/src/module/mod.rs +++ b/core/engine/src/module/mod.rs @@ -281,7 +281,7 @@ impl Module { /// that will resolve when the loading process either completes or fails. /// /// [spec]: https://tc39.es/ecma262/#table-abstract-methods-of-module-records - #[allow(clippy::missing_panics_doc)] + #[expect(clippy::missing_panics_doc)] #[inline] pub fn load(&self, context: &mut Context) -> JsPromise { match self.kind() { @@ -393,7 +393,6 @@ impl Module { /// This must only be called if the [`JsPromise`] returned by [`Module::load`] has fulfilled. /// /// [spec]: https://tc39.es/ecma262/#table-abstract-methods-of-module-records - #[allow(clippy::mutable_key_type)] pub(crate) fn resolve_export( &self, export_name: JsString, @@ -418,7 +417,6 @@ impl Module { /// This must only be called if the [`JsPromise`] returned by [`Module::load`] has fulfilled. /// /// [spec]: https://tc39.es/ecma262/#table-abstract-methods-of-module-records - #[allow(clippy::missing_panics_doc)] #[inline] pub fn link(&self, context: &mut Context) -> JsResult<()> { match self.kind() { @@ -531,7 +529,6 @@ impl Module { /// PromiseState::Fulfilled(JsValue::undefined()) /// ); /// ``` - #[allow(dropping_copy_types)] #[inline] pub fn load_link_evaluate(&self, context: &mut Context) -> JsPromise { let main_timer = Profiler::global().start_event("Module evaluation", "Main"); diff --git a/core/engine/src/module/namespace.rs b/core/engine/src/module/namespace.rs index 196e0dd084..5e9924c7aa 100644 --- a/core/engine/src/module/namespace.rs +++ b/core/engine/src/module/namespace.rs @@ -95,7 +95,7 @@ impl ModuleNamespace { /// [`[[GetPrototypeOf]] ( )`][spec]. /// /// [spec]: https://tc39.es/ecma262/#sec-module-namespace-exotic-objects-getprototypeof -#[allow(clippy::unnecessary_wraps)] +#[expect(clippy::unnecessary_wraps)] fn module_namespace_exotic_get_prototype_of( _: &JsObject, _: &mut Context, @@ -107,7 +107,7 @@ fn module_namespace_exotic_get_prototype_of( /// [`[[SetPrototypeOf]] ( V )`][spec]. /// /// [spec]: https://tc39.es/ecma262/#sec-module-namespace-exotic-objects-setprototypeof-v -#[allow(clippy::unnecessary_wraps)] +#[expect(clippy::unnecessary_wraps)] fn module_namespace_exotic_set_prototype_of( obj: &JsObject, val: JsPrototype, @@ -123,7 +123,7 @@ fn module_namespace_exotic_set_prototype_of( /// [`[[IsExtensible]] ( )`][spec]. /// /// [spec]: https://tc39.es/ecma262/#sec-module-namespace-exotic-objects-isextensible -#[allow(clippy::unnecessary_wraps)] +#[expect(clippy::unnecessary_wraps)] fn module_namespace_exotic_is_extensible(_: &JsObject, _: &mut Context) -> JsResult { // 1. Return false. Ok(false) @@ -132,7 +132,7 @@ fn module_namespace_exotic_is_extensible(_: &JsObject, _: &mut Context) -> JsRes /// [`[[PreventExtensions]] ( )`][spec]. /// /// [spec]: https://tc39.es/ecma262/#sec-module-namespace-exotic-objects-preventextensions -#[allow(clippy::unnecessary_wraps)] +#[expect(clippy::unnecessary_wraps)] fn module_namespace_exotic_prevent_extensions(_: &JsObject, _: &mut Context) -> JsResult { Ok(true) } @@ -414,7 +414,7 @@ fn module_namespace_exotic_get( /// [`[[Set]] ( P, V, Receiver )`][spec]. /// /// [spec]: https://tc39.es/ecma262/#sec-module-namespace-exotic-objects-set-p-v-receiver -#[allow(clippy::needless_pass_by_value, clippy::unnecessary_wraps)] +#[expect(clippy::needless_pass_by_value, clippy::unnecessary_wraps)] fn module_namespace_exotic_set( _obj: &JsObject, _key: PropertyKey, diff --git a/core/engine/src/module/source.rs b/core/engine/src/module/source.rs index e7f10c7f10..a0e70ca151 100644 --- a/core/engine/src/module/source.rs +++ b/core/engine/src/module/source.rs @@ -520,7 +520,6 @@ impl SourceTextModule { /// Concrete method [`ResolveExport ( exportName [ , resolveSet ] )`][spec] /// /// [spec]: https://tc39.es/ecma262/#sec-resolveexport - #[allow(clippy::mutable_key_type)] pub(super) fn resolve_export( &self, module_self: &Module, @@ -1309,7 +1308,6 @@ impl SourceTextModule { /// Abstract operation [`GatherAvailableAncestors ( module, execList )`][spec]. /// /// [spec]: https://tc39.es/ecma262/#sec-gather-available-ancestors - #[allow(clippy::mutable_key_type)] fn gather_available_ancestors(&self, exec_list: &mut FxHashSet) { // 1. For each Cyclic Module Record m of module.[[AsyncParentModules]], do for m in &*self.async_parent_modules.borrow() { @@ -1788,7 +1786,6 @@ impl SourceTextModule { /// Abstract operation [`AsyncModuleExecutionFulfilled ( module )`][spec]. /// /// [spec]: https://tc39.es/ecma262/#sec-async-module-execution-fulfilled -#[allow(clippy::mutable_key_type)] fn async_module_execution_fulfilled(module: &Module, context: &mut Context) { let ModuleKind::SourceText(module_src) = module.kind() else { unreachable!("async executed module must be a source text module"); diff --git a/core/engine/src/module/synthetic.rs b/core/engine/src/module/synthetic.rs index 5e8309e0b6..3439f24526 100644 --- a/core/engine/src/module/synthetic.rs +++ b/core/engine/src/module/synthetic.rs @@ -249,7 +249,6 @@ impl SyntheticModule { /// Concrete method [`ResolveExport ( exportName )`][spec] /// /// [spec]: https://tc39.es/proposal-json-modules/#sec-smr-resolveexport - #[allow(clippy::mutable_key_type)] pub(super) fn resolve_export( &self, module_self: &Module, diff --git a/core/engine/src/object/builtins/jsarray.rs b/core/engine/src/object/builtins/jsarray.rs index 7b7aff8d0e..7e03fd2353 100644 --- a/core/engine/src/object/builtins/jsarray.rs +++ b/core/engine/src/object/builtins/jsarray.rs @@ -177,7 +177,7 @@ impl JsArray { .as_number() .expect("Array.prototype.indexOf should always return number"); - #[allow(clippy::float_cmp)] + #[expect(clippy::float_cmp)] if index == -1.0 { Ok(None) } else { @@ -203,7 +203,7 @@ impl JsArray { .as_number() .expect("Array.prototype.lastIndexOf should always return number"); - #[allow(clippy::float_cmp)] + #[expect(clippy::float_cmp)] if index == -1.0 { Ok(None) } else { diff --git a/core/engine/src/object/builtins/jspromise.rs b/core/engine/src/object/builtins/jspromise.rs index 393e34e80a..cbda788b59 100644 --- a/core/engine/src/object/builtins/jspromise.rs +++ b/core/engine/src/object/builtins/jspromise.rs @@ -483,7 +483,7 @@ impl JsPromise { /// /// [`Promise.prototype.then`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/then #[inline] - #[allow(clippy::return_self_not_must_use)] // Could just be used to add handlers on an existing promise + #[expect(clippy::return_self_not_must_use)] // Could just be used to add handlers on an existing promise pub fn then( &self, on_fulfilled: Option, @@ -546,7 +546,7 @@ impl JsPromise { /// [`Promise.prototype.catch`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/catch /// [then]: JsPromise::then #[inline] - #[allow(clippy::return_self_not_must_use)] // Could just be used to add a handler on an existing promise + #[expect(clippy::return_self_not_must_use)] // Could just be used to add a handler on an existing promise pub fn catch(&self, on_rejected: JsFunction, context: &mut Context) -> Self { self.then(None, Some(on_rejected), context) } @@ -618,7 +618,7 @@ impl JsPromise { /// [`Promise.prototype.finally()`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/finally /// [then]: JsPromise::then #[inline] - #[allow(clippy::return_self_not_must_use)] // Could just be used to add a handler on an existing promise + #[expect(clippy::return_self_not_must_use)] // Could just be used to add a handler on an existing promise pub fn finally(&self, on_finally: JsFunction, context: &mut Context) -> Self { let (then, catch) = Promise::then_catch_finally_closures( context.intrinsics().constructors().promise().constructor(), diff --git a/core/engine/src/object/builtins/jstypedarray.rs b/core/engine/src/object/builtins/jstypedarray.rs index e694e2d086..7b97cd2f49 100644 --- a/core/engine/src/object/builtins/jstypedarray.rs +++ b/core/engine/src/object/builtins/jstypedarray.rs @@ -765,7 +765,7 @@ impl JsTypedArray { .as_number() .expect("TypedArray.prototype.indexOf should always return number"); - #[allow(clippy::float_cmp)] + #[expect(clippy::float_cmp)] if index == -1.0 { Ok(None) } else { @@ -791,7 +791,7 @@ impl JsTypedArray { .as_number() .expect("TypedArray.prototype.lastIndexOf should always return number"); - #[allow(clippy::float_cmp)] + #[expect(clippy::float_cmp)] if index == -1.0 { Ok(None) } else { diff --git a/core/engine/src/object/internal_methods/immutable_prototype.rs b/core/engine/src/object/internal_methods/immutable_prototype.rs index 57c3ccb898..0412c3f81b 100644 --- a/core/engine/src/object/internal_methods/immutable_prototype.rs +++ b/core/engine/src/object/internal_methods/immutable_prototype.rs @@ -17,7 +17,7 @@ pub(crate) static IMMUTABLE_PROTOTYPE_EXOTIC_INTERNAL_METHODS: InternalObjectMet /// [`[[SetPrototypeOf]] ( V )`][spec]. /// /// [spec]: https://tc39.es/ecma262/#sec-immutable-prototype-exotic-objects-setprototypeof-v -#[allow(clippy::needless_pass_by_value)] +#[expect(clippy::needless_pass_by_value)] pub(crate) fn immutable_prototype_exotic_set_prototype_of( obj: &JsObject, val: JsPrototype, diff --git a/core/engine/src/object/internal_methods/mod.rs b/core/engine/src/object/internal_methods/mod.rs index ac671752f3..308f01449a 100644 --- a/core/engine/src/object/internal_methods/mod.rs +++ b/core/engine/src/object/internal_methods/mod.rs @@ -345,7 +345,7 @@ pub(crate) static ORDINARY_INTERNAL_METHODS: InternalObjectMethods = InternalObj /// /// For a guide on how to implement exotic internal methods, see `ORDINARY_INTERNAL_METHODS`. #[derive(Debug, Clone, Copy)] -#[allow(clippy::type_complexity, clippy::struct_field_names)] +#[expect(clippy::struct_field_names)] pub struct InternalObjectMethods { pub(crate) __get_prototype_of__: fn(&JsObject, &mut Context) -> JsResult, pub(crate) __set_prototype_of__: fn(&JsObject, JsPrototype, &mut Context) -> JsResult, @@ -431,7 +431,7 @@ impl CallValue { /// - [ECMAScript reference][spec] /// /// [spec]: https://tc39.es/ecma262/#sec-ordinarygetprototypeof -#[allow(clippy::unnecessary_wraps)] +#[expect(clippy::unnecessary_wraps)] pub(crate) fn ordinary_get_prototype_of( obj: &JsObject, _context: &mut Context, @@ -448,7 +448,7 @@ pub(crate) fn ordinary_get_prototype_of( /// - [ECMAScript reference][spec] /// /// [spec]: https://tc39.es/ecma262/#sec-ordinarysetprototypeof -#[allow(clippy::unnecessary_wraps)] +#[expect(clippy::unnecessary_wraps)] pub(crate) fn ordinary_set_prototype_of( obj: &JsObject, val: JsPrototype, @@ -504,7 +504,7 @@ pub(crate) fn ordinary_set_prototype_of( /// - [ECMAScript reference][spec] /// /// [spec]: https://tc39.es/ecma262/#sec-ordinaryisextensible -#[allow(clippy::unnecessary_wraps)] +#[expect(clippy::unnecessary_wraps)] pub(crate) fn ordinary_is_extensible(obj: &JsObject, _context: &mut Context) -> JsResult { // 1. Return O.[[Extensible]]. Ok(obj.borrow().extensible) @@ -516,7 +516,7 @@ pub(crate) fn ordinary_is_extensible(obj: &JsObject, _context: &mut Context) -> /// - [ECMAScript reference][spec] /// /// [spec]: https://tc39.es/ecma262/#sec-ordinarypreventextensions -#[allow(clippy::unnecessary_wraps)] +#[expect(clippy::unnecessary_wraps)] pub(crate) fn ordinary_prevent_extensions( obj: &JsObject, _context: &mut Context, @@ -534,7 +534,7 @@ pub(crate) fn ordinary_prevent_extensions( /// - [ECMAScript reference][spec] /// /// [spec]: https://tc39.es/ecma262/#sec-ordinarygetownproperty -#[allow(clippy::unnecessary_wraps)] +#[expect(clippy::unnecessary_wraps)] pub(crate) fn ordinary_get_own_property( obj: &JsObject, key: &PropertyKey, @@ -878,7 +878,7 @@ pub(crate) fn ordinary_delete( /// - [ECMAScript reference][spec] /// /// [spec]: https://tc39.es/ecma262/#sec-ordinaryownpropertykeys -#[allow(clippy::unnecessary_wraps)] +#[expect(clippy::unnecessary_wraps)] pub(crate) fn ordinary_own_property_keys( obj: &JsObject, _context: &mut Context, diff --git a/core/engine/src/object/internal_methods/string.rs b/core/engine/src/object/internal_methods/string.rs index ce26b9da30..b20734053e 100644 --- a/core/engine/src/object/internal_methods/string.rs +++ b/core/engine/src/object/internal_methods/string.rs @@ -81,7 +81,7 @@ pub(crate) fn string_exotic_define_own_property( /// - [ECMAScript reference][spec] /// /// [spec]: https://tc39.es/ecma262/#sec-string-exotic-objects-ownpropertykeys -#[allow(clippy::unnecessary_wraps)] +#[expect(clippy::unnecessary_wraps)] pub(crate) fn string_exotic_own_property_keys( obj: &JsObject, _context: &mut Context, diff --git a/core/engine/src/object/jsobject.rs b/core/engine/src/object/jsobject.rs index eccb1f8138..6d5bb48f72 100644 --- a/core/engine/src/object/jsobject.rs +++ b/core/engine/src/object/jsobject.rs @@ -63,7 +63,6 @@ impl Clone for JsObject { // We have to skip implementing `Debug` for this because not using the // implementation of `Debug` for `JsObject` could easily cause stack overflows, // so we have to force our users to debug the `JsObject` instead. -#[allow(missing_debug_implementations)] #[derive(Trace, Finalize)] pub(crate) struct VTableObject { #[unsafe_ignore_trace] @@ -527,7 +526,7 @@ Cannot both specify accessors and a value or writable attribute", } // Allow lint, false positive. - #[allow(clippy::assigning_clones)] + #[expect(clippy::assigning_clones)] pub(crate) fn get_property(&self, key: &PropertyKey) -> Option { let mut obj = Some(self.clone()); @@ -714,7 +713,7 @@ impl JsObject { /// Panics if the object is currently mutably borrowed #[inline] #[track_caller] - #[allow(clippy::must_use_candidate)] + #[expect(clippy::must_use_candidate)] pub fn set_prototype(&self, prototype: JsPrototype) -> bool { self.borrow_mut().set_prototype(prototype) } diff --git a/core/engine/src/object/operations.rs b/core/engine/src/object/operations.rs index 9a989b5cc2..03a40560ce 100644 --- a/core/engine/src/object/operations.rs +++ b/core/engine/src/object/operations.rs @@ -842,7 +842,7 @@ impl JsObject { /// - [ECMAScript specification][spec] /// /// [spec]: https://tc39.es/ecma262/#sec-privateelementfind - #[allow(clippy::similar_names)] + #[expect(clippy::similar_names)] pub(crate) fn private_element_find( &self, name: &PrivateName, diff --git a/core/engine/src/object/property_map.rs b/core/engine/src/object/property_map.rs index f995f66872..6b95c66823 100644 --- a/core/engine/src/object/property_map.rs +++ b/core/engine/src/object/property_map.rs @@ -860,7 +860,6 @@ impl FusedIterator for IndexPropertyKeys<'_> {} /// An iterator over the index values (`Property`) of an `Object`. #[derive(Debug, Clone)] -#[allow(variant_size_differences)] pub enum IndexPropertyValues<'a> { /// An iterator over dense, Vec backed indexed property entries of an `Object`. DenseI32(std::slice::Iter<'a, i32>), diff --git a/core/engine/src/object/shape/shared_shape/mod.rs b/core/engine/src/object/shape/shared_shape/mod.rs index b27b5f6200..216ad8bb1e 100644 --- a/core/engine/src/object/shape/shared_shape/mod.rs +++ b/core/engine/src/object/shape/shared_shape/mod.rs @@ -37,7 +37,7 @@ const CONFIGURE_PROPERTY_TRANSITION_TYPE: u8 = 0b0000_0001; const PROTOTYPE_TRANSITION_TYPE: u8 = 0b0000_0010; // Reserved for future use! -#[allow(unused)] +#[expect(unused)] const RESEREVED_TRANSITION_TYPE: u8 = 0b0000_0011; bitflags! { diff --git a/core/engine/src/optimizer/mod.rs b/core/engine/src/optimizer/mod.rs index d1bf71ec5d..3501be37ba 100644 --- a/core/engine/src/optimizer/mod.rs +++ b/core/engine/src/optimizer/mod.rs @@ -115,7 +115,7 @@ impl<'context> Optimizer<'context> { pub(crate) fn apply(&mut self, statement_list: &mut StatementList) -> OptimizerStatistics { self.visit_statement_list_mut(statement_list); - #[allow(clippy::print_stdout)] + #[expect(clippy::print_stdout)] if self .context .optimizer_options() diff --git a/core/engine/src/property/mod.rs b/core/engine/src/property/mod.rs index bb095142f2..3f24ef2982 100644 --- a/core/engine/src/property/mod.rs +++ b/core/engine/src/property/mod.rs @@ -573,7 +573,6 @@ impl PropertyDescriptorBuilder { /// Consumes the builder and returns the [`PropertyDescriptor`]. #[must_use] - #[allow(clippy::missing_const_for_fn)] pub fn build(self) -> PropertyDescriptor { self.inner } diff --git a/core/engine/src/script.rs b/core/engine/src/script.rs index 52c59110e2..530e7b9ea3 100644 --- a/core/engine/src/script.rs +++ b/core/engine/src/script.rs @@ -181,7 +181,7 @@ impl Script { /// This uses an implementation defined amount of "clock cycles" that need to pass before /// execution is suspended. See [`Script::evaluate_async_with_budget`] if you want to also /// customize this parameter. - #[allow(clippy::future_not_send)] + #[expect(clippy::future_not_send)] pub async fn evaluate_async(&self, context: &mut Context) -> JsResult { self.evaluate_async_with_budget(context, 256).await } @@ -193,7 +193,7 @@ impl Script { /// CPU clock cycles a VM instruction will take, but all instructions have a "cost" associated /// with them that depends on their individual complexity. We'd recommend benchmarking with /// different budget sizes in order to find the ideal yielding time for your application. - #[allow(clippy::future_not_send)] + #[expect(clippy::future_not_send)] pub async fn evaluate_async_with_budget( &self, context: &mut Context, diff --git a/core/engine/src/small_map/mod.rs b/core/engine/src/small_map/mod.rs index 0e2c133769..d5f1f6869f 100644 --- a/core/engine/src/small_map/mod.rs +++ b/core/engine/src/small_map/mod.rs @@ -173,7 +173,7 @@ impl SmallMap { /// /// The supplied key may be any borrowed form of the map's key type, but the ordering /// on the borrowed form *must* match the ordering on the key type. - #[allow(clippy::map_identity)] + pub fn get_key_value(&self, key: &Q) -> Option<(&K, &V)> where K: Borrow + Ord + Eq, @@ -372,7 +372,6 @@ impl<'a, K, V, const ARRAY_SIZE: usize> IntoIterator for &'a SmallMap Iterator for Iter<'a, K, V> { type Item = (&'a K, &'a V); - #[allow(clippy::map_identity)] fn next(&mut self) -> Option { match &mut self.inner { InnerIter::Inline(i) => i.next().map(|(k, v)| (k, v)), @@ -387,7 +386,6 @@ impl<'a, K, V> Iterator for Iter<'a, K, V> { } } - #[allow(clippy::map_identity)] fn last(self) -> Option<(&'a K, &'a V)> { match self.inner { InnerIter::Inline(i) => i.last().map(|(k, v)| (k, v)), @@ -399,7 +397,6 @@ impl<'a, K, V> Iterator for Iter<'a, K, V> { impl FusedIterator for Iter<'_, K, V> {} impl<'a, K: 'a, V: 'a> DoubleEndedIterator for Iter<'a, K, V> { - #[allow(clippy::map_identity)] fn next_back(&mut self) -> Option<(&'a K, &'a V)> { match &mut self.inner { InnerIter::Inline(i) => i.next_back().map(|(k, v)| (k, v)), diff --git a/core/engine/src/string.rs b/core/engine/src/string.rs index a8aee6201c..627451072d 100644 --- a/core/engine/src/string.rs +++ b/core/engine/src/string.rs @@ -49,7 +49,7 @@ pub use boa_string::*; /// assert_eq!(&msg, "Hello, human! Nice to meet you!"); /// ``` #[macro_export] -#[allow(clippy::module_name_repetitions)] +#[expect(clippy::module_name_repetitions)] macro_rules! js_string { () => { $crate::string::JsString::default() @@ -70,7 +70,7 @@ macro_rules! js_string { }; } -#[allow(clippy::redundant_clone)] +#[expect(clippy::redundant_clone)] #[cfg(test)] mod tests { use std::hash::{BuildHasher, BuildHasherDefault, Hash}; diff --git a/core/engine/src/symbol.rs b/core/engine/src/symbol.rs index a25cf08855..252368f883 100644 --- a/core/engine/src/symbol.rs +++ b/core/engine/src/symbol.rs @@ -135,7 +135,7 @@ struct Inner { // Safety: JsSymbol does not contain any objects which needs to be traced, // so this is safe. #[boa_gc(unsafe_empty_trace)] -#[allow(clippy::module_name_repetitions)] +#[expect(clippy::module_name_repetitions)] pub struct JsSymbol { repr: Tagged, } diff --git a/core/engine/src/tagged.rs b/core/engine/src/tagged.rs index 63540ad1e5..12ed083478 100644 --- a/core/engine/src/tagged.rs +++ b/core/engine/src/tagged.rs @@ -39,7 +39,7 @@ impl Clone for Tagged { impl Copy for Tagged {} -#[allow(dead_code)] +#[expect(dead_code)] impl Tagged { /// Creates a new, tagged `Tagged` pointer from an integer. /// @@ -90,13 +90,13 @@ impl Tagged { } /// Gets the address of the inner pointer. - #[allow(unused)] + #[expect(unused)] pub(crate) fn addr(self) -> usize { self.0.as_ptr().addr() } /// Returns `true` if `self ` is a tagged pointer. - #[allow(unused)] + #[expect(unused)] pub(crate) fn is_tagged(self) -> bool { self.0.as_ptr().addr() & 1 > 0 } diff --git a/core/engine/src/tests/iterators.rs b/core/engine/src/tests/iterators.rs index eb341f1f98..b9c03cf867 100644 --- a/core/engine/src/tests/iterators.rs +++ b/core/engine/src/tests/iterators.rs @@ -46,7 +46,7 @@ fn iterator_close_in_continue_before_jobs() { actual.push("async fn end"); }(); "#}), - #[allow(clippy::redundant_closure_for_method_calls)] + #[expect(clippy::redundant_closure_for_method_calls)] TestAction::inspect_context(|ctx| ctx.run_jobs()), TestAction::assert(indoc! {r#" arrayEquals( @@ -110,7 +110,7 @@ fn async_iterator_close_in_continue_is_awaited() { actual.push("async fn end"); }(); "#}), - #[allow(clippy::redundant_closure_for_method_calls)] + #[expect(clippy::redundant_closure_for_method_calls)] TestAction::inspect_context(|ctx| ctx.run_jobs()), TestAction::assert(indoc! {r#" arrayEquals( @@ -198,7 +198,7 @@ fn mixed_iterators_close_in_continue() { actual.push("async fn end"); }(); "#}), - #[allow(clippy::redundant_closure_for_method_calls)] + #[expect(clippy::redundant_closure_for_method_calls)] TestAction::inspect_context(|ctx| ctx.run_jobs()), TestAction::assert(indoc! {r#" arrayEquals( diff --git a/core/engine/src/tests/promise.rs b/core/engine/src/tests/promise.rs index c8d64b8809..50866111da 100644 --- a/core/engine/src/tests/promise.rs +++ b/core/engine/src/tests/promise.rs @@ -3,7 +3,7 @@ use indoc::indoc; use crate::{run_test_actions, TestAction}; #[test] -#[allow(clippy::redundant_closure_for_method_calls)] +#[expect(clippy::redundant_closure_for_method_calls)] fn issue_2658() { run_test_actions([ TestAction::run(indoc! { diff --git a/core/engine/src/value/conversions/mod.rs b/core/engine/src/value/conversions/mod.rs index b247db10f9..faba6e78e9 100644 --- a/core/engine/src/value/conversions/mod.rs +++ b/core/engine/src/value/conversions/mod.rs @@ -176,7 +176,7 @@ impl From for JsValue { impl From<()> for JsValue { #[inline] - #[allow(clippy::pedantic)] // didn't want to increase our MSRV for just a lint. + #[expect(clippy::pedantic)] // didn't want to increase our MSRV for just a lint. fn from(_: ()) -> Self { let _timer = Profiler::global().start_event("From<()>", "value"); diff --git a/core/engine/src/value/equality.rs b/core/engine/src/value/equality.rs index d14a95d1af..a5bf17ca0a 100644 --- a/core/engine/src/value/equality.rs +++ b/core/engine/src/value/equality.rs @@ -37,7 +37,7 @@ impl JsValue { /// /// This method is executed when doing abstract equality comparisons with the `==` operator. /// For more information, check - #[allow(clippy::float_cmp)] + #[expect(clippy::float_cmp)] pub fn equals(&self, other: &Self, context: &mut Context) -> JsResult { // 1. If Type(x) is the same as Type(y), then // a. Return the result of performing Strict Equality Comparison x === y. diff --git a/core/engine/src/value/mod.rs b/core/engine/src/value/mod.rs index 34e8e27377..e4d5471842 100644 --- a/core/engine/src/value/mod.rs +++ b/core/engine/src/value/mod.rs @@ -290,7 +290,7 @@ impl JsValue { /// /// [spec]: https://tc39.es/ecma262/#sec-isintegralnumber #[must_use] - #[allow(clippy::float_cmp)] + #[expect(clippy::float_cmp)] pub fn is_integral_number(&self) -> bool { // If it can fit in a i32 and the truncated version is // equal to the original then it is an integer. @@ -307,7 +307,6 @@ impl JsValue { /// /// Similar to [`JsValue::is_integral_number()`] except that it returns `false` for `-0`. #[must_use] - #[allow(clippy::float_cmp)] pub fn is_integer(&self) -> bool { // If it can fit in a i32 and the truncated version is // equal to the original then it is an integer. diff --git a/core/engine/src/value/operations.rs b/core/engine/src/value/operations.rs index d243315bea..2c1d1c0fd4 100644 --- a/core/engine/src/value/operations.rs +++ b/core/engine/src/value/operations.rs @@ -196,7 +196,7 @@ impl JsValue { /// Perform the binary `**` operator on the value and return the result. // NOTE: There are some cases in the spec where we have to compare floats - #[allow(clippy::float_cmp)] + #[expect(clippy::float_cmp)] pub fn pow(&self, other: &Self, context: &mut Context) -> JsResult { Ok(match (self, other) { // Fast path: diff --git a/core/engine/src/value/tests.rs b/core/engine/src/value/tests.rs index c689a1fc3c..78f5f110e4 100644 --- a/core/engine/src/value/tests.rs +++ b/core/engine/src/value/tests.rs @@ -98,7 +98,7 @@ fn hash_value(value: &JsValue) -> u64 { hasher.finish() } -#[allow(clippy::redundant_clone)] +#[expect(clippy::redundant_clone)] #[test] fn hash_undefined() { let value1 = JsValue::undefined(); @@ -312,7 +312,7 @@ fn bitand_rational_and_rational() { } #[test] -#[allow(clippy::float_cmp)] +#[expect(clippy::float_cmp)] fn pow_number_and_number() { run_test_actions([TestAction::assert_eq("3 ** 3", 27.0)]); } diff --git a/core/engine/src/vm/call_frame/mod.rs b/core/engine/src/vm/call_frame/mod.rs index 3aca4f33a2..9bce2f8547 100644 --- a/core/engine/src/vm/call_frame/mod.rs +++ b/core/engine/src/vm/call_frame/mod.rs @@ -355,11 +355,13 @@ impl CallFrame { /// Indicates how a generator function that has been called/resumed should return. #[derive(Copy, Clone, Debug, PartialEq, Eq, Default)] #[repr(u8)] -#[allow(missing_docs)] pub enum GeneratorResumeKind { #[default] + /// Usual execution. Normal = 0, + /// Finished by throwing an error. Throw, + /// Finished by returning. Return, } diff --git a/core/engine/src/vm/completion_record.rs b/core/engine/src/vm/completion_record.rs index 18b45d1213..4ee2ede23a 100644 --- a/core/engine/src/vm/completion_record.rs +++ b/core/engine/src/vm/completion_record.rs @@ -39,7 +39,6 @@ impl CompletionRecord { // - https://github.com/rust-lang/rust-clippy/issues/4041 // - https://github.com/rust-lang/rust/issues/60964 // - https://github.com/rust-lang/rust/issues/73255 - #[allow(clippy::missing_const_for_fn)] pub(crate) fn consume(self) -> JsResult { match self { Self::Throw(error) => Err(error), diff --git a/core/engine/src/vm/flowgraph/color.rs b/core/engine/src/vm/flowgraph/color.rs index bf5587c786..983411b63f 100644 --- a/core/engine/src/vm/flowgraph/color.rs +++ b/core/engine/src/vm/flowgraph/color.rs @@ -28,7 +28,7 @@ pub enum Color { impl Color { /// Function for converting HSV to RGB color format. - #[allow(clippy::many_single_char_names)] + #[expect(clippy::many_single_char_names)] #[must_use] pub fn hsv_to_rgb(h: f64, s: f64, v: f64) -> Self { let h_i = (h * 6.0) as i64; diff --git a/core/engine/src/vm/flowgraph/mod.rs b/core/engine/src/vm/flowgraph/mod.rs index baf607b03a..0af5e3cc56 100644 --- a/core/engine/src/vm/flowgraph/mod.rs +++ b/core/engine/src/vm/flowgraph/mod.rs @@ -17,7 +17,7 @@ use super::{Constant, Instruction, InstructionIterator}; impl CodeBlock { /// Output the [`CodeBlock`] VM instructions into a [`Graph`]. - #[allow(clippy::match_same_arms)] + #[expect(clippy::match_same_arms)] pub fn to_graph(&self, graph: &mut SubGraph) { // Have to remove any invalid graph chars like `<` or `>`. let name = if self.name() == &js_str!("
") { diff --git a/core/engine/src/vm/mod.rs b/core/engine/src/vm/mod.rs index 4e17a00121..3c43659aa4 100644 --- a/core/engine/src/vm/mod.rs +++ b/core/engine/src/vm/mod.rs @@ -30,7 +30,6 @@ pub mod flowgraph; pub(crate) use inline_cache::InlineCache; // TODO: see if this can be exposed on all features. -#[allow(unused_imports)] pub(crate) use opcode::{Instruction, InstructionIterator, Opcode, VaryingOperandKind}; pub use runtime_limits::RuntimeLimits; pub use { @@ -277,7 +276,7 @@ pub(crate) enum CompletionType { Yield, } -#[allow(clippy::print_stdout)] +#[expect(clippy::print_stdout)] #[cfg(feature = "trace")] impl Context { const COLUMN_WIDTH: usize = 26; @@ -554,7 +553,7 @@ impl Context { /// Runs the current frame to completion, yielding to the caller each time `budget` /// "clock cycles" have passed. - #[allow(clippy::future_not_send)] + #[expect(clippy::future_not_send)] pub(crate) async fn run_async_with_budget(&mut self, budget: u32) -> CompletionRecord { let _timer = Profiler::global().start_event("run_async_with_budget", "vm"); diff --git a/core/engine/src/vm/opcode/control_flow/return.rs b/core/engine/src/vm/opcode/control_flow/return.rs index 03ef1e0aef..f2f4cd9f85 100644 --- a/core/engine/src/vm/opcode/control_flow/return.rs +++ b/core/engine/src/vm/opcode/control_flow/return.rs @@ -120,8 +120,7 @@ impl Operation for SetReturnValue { pub(crate) struct PopIntoRegister; impl PopIntoRegister { - #[allow(clippy::unnecessary_wraps)] - #[allow(clippy::needless_pass_by_value)] + #[expect(clippy::unnecessary_wraps)] fn operation(dst: u32, context: &mut Context) -> JsResult { let value = context.vm.pop(); @@ -157,8 +156,7 @@ impl Operation for PopIntoRegister { pub(crate) struct PushFromRegister; impl PushFromRegister { - #[allow(clippy::unnecessary_wraps)] - #[allow(clippy::needless_pass_by_value)] + #[expect(clippy::unnecessary_wraps)] fn operation(dst: u32, context: &mut Context) -> JsResult { let rp = context.vm.frame().rp; let value = context.vm.stack[(rp + dst) as usize].clone(); diff --git a/core/engine/src/vm/opcode/define/mod.rs b/core/engine/src/vm/opcode/define/mod.rs index ecc5cb4a7d..f494e8ae41 100644 --- a/core/engine/src/vm/opcode/define/mod.rs +++ b/core/engine/src/vm/opcode/define/mod.rs @@ -17,7 +17,7 @@ pub(crate) use own_property::*; pub(crate) struct DefVar; impl DefVar { - #[allow(clippy::unnecessary_wraps)] + #[expect(clippy::unnecessary_wraps)] fn operation(context: &mut Context, index: usize) -> JsResult { // TODO: spec specifies to return `empty` on empty vars, but we're trying to initialize. let binding_locator = context.vm.frame().code_block.bindings[index].clone(); @@ -101,7 +101,7 @@ impl Operation for DefInitVar { pub(crate) struct PutLexicalValue; impl PutLexicalValue { - #[allow(clippy::unnecessary_wraps)] + #[expect(clippy::unnecessary_wraps)] fn operation(context: &mut Context, index: usize) -> JsResult { let value = context.vm.pop(); let binding_locator = context.vm.frame().code_block.bindings[index].clone(); diff --git a/core/engine/src/vm/opcode/get/argument.rs b/core/engine/src/vm/opcode/get/argument.rs index dcfd8cb667..8334fc7c40 100644 --- a/core/engine/src/vm/opcode/get/argument.rs +++ b/core/engine/src/vm/opcode/get/argument.rs @@ -11,7 +11,7 @@ use crate::{ pub(crate) struct GetArgument; impl GetArgument { - #[allow(clippy::unnecessary_wraps)] + #[expect(clippy::unnecessary_wraps)] fn operation(context: &mut Context, index: usize) -> JsResult { let value = context .vm diff --git a/core/engine/src/vm/opcode/get/function.rs b/core/engine/src/vm/opcode/get/function.rs index bd19632532..e93ce680ca 100644 --- a/core/engine/src/vm/opcode/get/function.rs +++ b/core/engine/src/vm/opcode/get/function.rs @@ -11,7 +11,7 @@ use crate::{ pub(crate) struct GetFunction; impl GetFunction { - #[allow(clippy::unnecessary_wraps)] + #[expect(clippy::unnecessary_wraps)] fn operation(context: &mut Context, index: usize) -> JsResult { let code = context.vm.frame().code_block().constant_function(index); let function = create_function_object_fast(code, context); diff --git a/core/engine/src/vm/opcode/global.rs b/core/engine/src/vm/opcode/global.rs index 49666dc437..9b7615b8b9 100644 --- a/core/engine/src/vm/opcode/global.rs +++ b/core/engine/src/vm/opcode/global.rs @@ -129,7 +129,6 @@ impl Operation for CanDeclareGlobalVar { pub(crate) struct CreateGlobalFunctionBinding; impl CreateGlobalFunctionBinding { - #[allow(clippy::unnecessary_wraps)] fn operation( context: &mut Context, index: usize, @@ -182,7 +181,6 @@ impl Operation for CreateGlobalFunctionBinding { pub(crate) struct CreateGlobalVarBinding; impl CreateGlobalVarBinding { - #[allow(clippy::unnecessary_wraps)] fn operation( context: &mut Context, index: usize, diff --git a/core/engine/src/vm/opcode/locals/mod.rs b/core/engine/src/vm/opcode/locals/mod.rs index 20d4e62633..97d9652bdf 100644 --- a/core/engine/src/vm/opcode/locals/mod.rs +++ b/core/engine/src/vm/opcode/locals/mod.rs @@ -11,8 +11,7 @@ use crate::{ pub(crate) struct PopIntoLocal; impl PopIntoLocal { - #[allow(clippy::unnecessary_wraps)] - #[allow(clippy::needless_pass_by_value)] + #[expect(clippy::unnecessary_wraps)] fn operation(dst: u32, context: &mut Context) -> JsResult { context.vm.frame_mut().local_binings_initialized[dst as usize] = true; let value = context.vm.pop(); @@ -52,8 +51,6 @@ impl Operation for PopIntoLocal { pub(crate) struct PushFromLocal; impl PushFromLocal { - #[allow(clippy::unnecessary_wraps)] - #[allow(clippy::needless_pass_by_value)] fn operation(dst: u32, context: &mut Context) -> JsResult { if !context.vm.frame().local_binings_initialized[dst as usize] { return Err(JsNativeError::reference() diff --git a/core/engine/src/vm/opcode/mod.rs b/core/engine/src/vm/opcode/mod.rs index 5d2f075c8a..09037bee0b 100644 --- a/core/engine/src/vm/opcode/mod.rs +++ b/core/engine/src/vm/opcode/mod.rs @@ -393,7 +393,7 @@ macro_rules! generate_opcodes { impl From for Opcode { #[inline] - #[allow(non_upper_case_globals)] + #[expect(non_upper_case_globals)] fn from(value: u8) -> Self { $( const $Variant: u8 = Opcode::$Variant as u8; @@ -490,7 +490,7 @@ macro_rules! generate_opcodes { impl Instruction { /// Convert [`Instruction`] to compact bytecode. #[inline] - #[allow(dead_code)] + #[expect(dead_code)] pub(crate) fn to_bytecode(&self, bytes: &mut Vec) { match self { $( @@ -2303,7 +2303,6 @@ pub(crate) struct InstructionIterator<'bytecode> { } // TODO: see if this can be exposed on all features. -#[allow(unused)] impl<'bytecode> InstructionIterator<'bytecode> { /// Create a new [`InstructionIterator`] from bytecode array. #[inline] @@ -2315,6 +2314,7 @@ impl<'bytecode> InstructionIterator<'bytecode> { /// Create a new [`InstructionIterator`] from bytecode array at pc. #[inline] #[must_use] + #[allow(unused)] pub(crate) const fn with_pc(bytes: &'bytecode [u8], pc: usize) -> Self { Self { bytes, pc } } diff --git a/core/engine/src/vm/opcode/push/class/field.rs b/core/engine/src/vm/opcode/push/class/field.rs index 3614e41700..76f35d8bf7 100644 --- a/core/engine/src/vm/opcode/push/class/field.rs +++ b/core/engine/src/vm/opcode/push/class/field.rs @@ -60,7 +60,7 @@ impl Operation for PushClassField { pub(crate) struct PushClassFieldPrivate; impl PushClassFieldPrivate { - #[allow(clippy::unnecessary_wraps)] + #[expect(clippy::unnecessary_wraps)] fn operation(context: &mut Context, index: usize) -> JsResult { let name = context.vm.frame().code_block().constant_string(index); let field_function_value = context.vm.pop(); diff --git a/core/engine/src/vm/opcode/push/class/private.rs b/core/engine/src/vm/opcode/push/class/private.rs index d40b355597..a613724ba5 100644 --- a/core/engine/src/vm/opcode/push/class/private.rs +++ b/core/engine/src/vm/opcode/push/class/private.rs @@ -15,7 +15,7 @@ use crate::{ pub(crate) struct PushClassPrivateMethod; impl PushClassPrivateMethod { - #[allow(clippy::unnecessary_wraps)] + #[expect(clippy::unnecessary_wraps)] fn operation(context: &mut Context, index: usize) -> JsResult { let name = context.vm.frame().code_block().constant_string(index); let method = context.vm.pop(); @@ -87,7 +87,7 @@ impl Operation for PushClassPrivateMethod { pub(crate) struct PushClassPrivateGetter; impl PushClassPrivateGetter { - #[allow(clippy::unnecessary_wraps)] + #[expect(clippy::unnecessary_wraps)] fn operation(context: &mut Context, index: usize) -> JsResult { let name = context.vm.frame().code_block().constant_string(index); let getter = context.vm.pop(); @@ -139,7 +139,7 @@ impl Operation for PushClassPrivateGetter { pub(crate) struct PushClassPrivateSetter; impl PushClassPrivateSetter { - #[allow(clippy::unnecessary_wraps)] + #[expect(clippy::unnecessary_wraps)] fn operation(context: &mut Context, index: usize) -> JsResult { let name = context.vm.frame().code_block().constant_string(index); let setter = context.vm.pop(); diff --git a/core/engine/src/vm/opcode/push/environment.rs b/core/engine/src/vm/opcode/push/environment.rs index cfd66eca84..c5cd0d8ae8 100644 --- a/core/engine/src/vm/opcode/push/environment.rs +++ b/core/engine/src/vm/opcode/push/environment.rs @@ -14,7 +14,7 @@ use boa_gc::Gc; pub(crate) struct PushScope; impl PushScope { - #[allow(clippy::unnecessary_wraps)] + #[expect(clippy::unnecessary_wraps)] fn operation(context: &mut Context, index: usize) -> JsResult { let scope = context.vm.frame().code_block().constant_scope(index); context.vm.environments.push_lexical(scope.num_bindings()); diff --git a/core/engine/src/vm/opcode/push/literal.rs b/core/engine/src/vm/opcode/push/literal.rs index e7b66c25bd..a444ca66e6 100644 --- a/core/engine/src/vm/opcode/push/literal.rs +++ b/core/engine/src/vm/opcode/push/literal.rs @@ -12,7 +12,7 @@ use crate::{ pub(crate) struct PushLiteral; impl PushLiteral { - #[allow(clippy::unnecessary_wraps)] + #[expect(clippy::unnecessary_wraps)] fn operation(context: &mut Context, index: usize) -> JsResult { let constant = &context.vm.frame().code_block().constants[index]; let value: JsValue = match constant { diff --git a/core/engine/src/vm/opcode/set/private.rs b/core/engine/src/vm/opcode/set/private.rs index dd0c8631f1..679d340eb3 100644 --- a/core/engine/src/vm/opcode/set/private.rs +++ b/core/engine/src/vm/opcode/set/private.rs @@ -61,7 +61,7 @@ impl Operation for SetPrivateField { pub(crate) struct DefinePrivateField; impl DefinePrivateField { - #[allow(clippy::unnecessary_wraps)] + #[expect(clippy::unnecessary_wraps)] fn operation(context: &mut Context, index: usize) -> JsResult { let name = context.vm.frame().code_block().constant_string(index); let value = context.vm.pop(); @@ -107,7 +107,7 @@ impl Operation for DefinePrivateField { pub(crate) struct SetPrivateMethod; impl SetPrivateMethod { - #[allow(clippy::unnecessary_wraps)] + #[expect(clippy::unnecessary_wraps)] fn operation(context: &mut Context, index: usize) -> JsResult { let name = context.vm.frame().code_block().constant_string(index); let value = context.vm.pop(); @@ -167,7 +167,7 @@ impl Operation for SetPrivateMethod { pub(crate) struct SetPrivateSetter; impl SetPrivateSetter { - #[allow(clippy::unnecessary_wraps)] + #[expect(clippy::unnecessary_wraps)] fn operation(context: &mut Context, index: usize) -> JsResult { let name = context.vm.frame().code_block().constant_string(index); let value = context.vm.pop(); @@ -218,7 +218,7 @@ impl Operation for SetPrivateSetter { pub(crate) struct SetPrivateGetter; impl SetPrivateGetter { - #[allow(clippy::unnecessary_wraps)] + #[expect(clippy::unnecessary_wraps)] fn operation(context: &mut Context, index: usize) -> JsResult { let name = context.vm.frame().code_block().constant_string(index); let value = context.vm.pop(); diff --git a/core/engine/src/vm/opcode/templates/mod.rs b/core/engine/src/vm/opcode/templates/mod.rs index affb3a723e..e962e1198e 100644 --- a/core/engine/src/vm/opcode/templates/mod.rs +++ b/core/engine/src/vm/opcode/templates/mod.rs @@ -40,7 +40,7 @@ impl Operation for TemplateLookup { pub(crate) struct TemplateCreate; impl TemplateCreate { - #[allow(clippy::unnecessary_wraps)] + #[expect(clippy::unnecessary_wraps)] fn operation(context: &mut Context, count: u32, site: u64) -> JsResult { let template = Array::array_create(count.into(), None, context).expect("cannot fail per spec"); diff --git a/core/gc/src/cell.rs b/core/gc/src/cell.rs index 3666d88d97..b975915936 100644 --- a/core/gc/src/cell.rs +++ b/core/gc/src/cell.rs @@ -263,7 +263,7 @@ impl<'a, T: ?Sized> GcRef<'a, T> { /// `GcCellRef::clone(...)`. A `Clone` implementation or a method /// would interfere with the use of `c.borrow().clone()` to clone /// the contents of a `GcCell`. - #[allow(clippy::should_implement_trait)] + #[expect(clippy::should_implement_trait)] #[must_use] pub fn clone(orig: &GcRef<'a, T>) -> GcRef<'a, T> { orig.flags.set(orig.flags.get().add_reading()); @@ -404,7 +404,6 @@ impl<'a, T: ?Sized, U: ?Sized> GcRefMut<'a, T, U> { V: ?Sized, F: FnOnce(&mut U) -> Option<&mut V>, { - #[allow(trivial_casts)] // SAFETY: This is safe as `GcCellRefMut` is already borrowed, so the value is rooted. let value = unsafe { &mut *ptr::from_mut::(orig.value) }; @@ -433,7 +432,6 @@ impl<'a, T: ?Sized, U: ?Sized> GcRefMut<'a, T, U> { V: ?Sized, F: FnOnce(&mut U) -> &mut V, { - #[allow(trivial_casts)] // SAFETY: This is safe as `GcCellRefMut` is already borrowed, so the value is rooted. let value = unsafe { &mut *ptr::from_mut::(orig.value) }; @@ -498,7 +496,7 @@ impl Default for GcRefCell { } } -#[allow(clippy::inline_always)] +#[expect(clippy::inline_always)] impl PartialEq for GcRefCell { #[inline(always)] fn eq(&self, other: &Self) -> bool { @@ -508,7 +506,7 @@ impl PartialEq for GcRefCell { impl Eq for GcRefCell {} -#[allow(clippy::inline_always)] +#[expect(clippy::inline_always)] impl PartialOrd for GcRefCell { #[inline(always)] fn partial_cmp(&self, other: &Self) -> Option { diff --git a/core/gc/src/pointers/gc.rs b/core/gc/src/pointers/gc.rs index 04d773b3d9..8943ebefe2 100644 --- a/core/gc/src/pointers/gc.rs +++ b/core/gc/src/pointers/gc.rs @@ -212,7 +212,7 @@ impl Default for Gc { } } -#[allow(clippy::inline_always)] +#[expect(clippy::inline_always)] impl PartialEq for Gc { #[inline(always)] fn eq(&self, other: &Self) -> bool { @@ -222,7 +222,7 @@ impl PartialEq for Gc { impl Eq for Gc {} -#[allow(clippy::inline_always)] +#[expect(clippy::inline_always)] impl PartialOrd for Gc { #[inline(always)] fn partial_cmp(&self, other: &Self) -> Option { diff --git a/core/gc/src/pointers/mod.rs b/core/gc/src/pointers/mod.rs index dd6d1d5836..a4c5494f8a 100644 --- a/core/gc/src/pointers/mod.rs +++ b/core/gc/src/pointers/mod.rs @@ -14,7 +14,7 @@ pub(crate) use gc::NonTraceable; pub(crate) use weak_map::RawWeakMap; // Replace with std::ptr::addr_eq when 1.76 releases -#[allow(clippy::ptr_as_ptr, clippy::ptr_eq)] +#[expect(clippy::ptr_as_ptr, clippy::ptr_eq)] fn addr_eq(p: *const T, q: *const U) -> bool { (p as *const ()) == (q as *const ()) } diff --git a/core/gc/src/pointers/weak_map.rs b/core/gc/src/pointers/weak_map.rs index f5fed3fdf8..c66fe21e0a 100644 --- a/core/gc/src/pointers/weak_map.rs +++ b/core/gc/src/pointers/weak_map.rs @@ -119,7 +119,7 @@ where /// /// The map will be able to hold at least `capacity` elements without reallocating. /// If `capacity` is 0, the map will not allocate. - #[allow(unused)] + #[expect(unused)] pub(crate) fn with_capacity(capacity: usize) -> Self { Self::with_capacity_and_hasher(capacity, DefaultHashBuilder::default()) } @@ -155,7 +155,7 @@ where } /// Returns a reference to the map's [`BuildHasher`]. - #[allow(unused)] + #[expect(unused)] pub(crate) const fn hasher(&self) -> &S { &self.hash_builder } @@ -164,7 +164,7 @@ where /// /// This number is a lower bound; the map might be able to hold more, but is guaranteed to be /// able to hold at least this many. - #[allow(unused)] + #[expect(unused)] pub(crate) fn capacity(&self) -> usize { self.table.capacity() } @@ -185,7 +185,6 @@ where /// /// This is an upper bound; the map might contain some expired keys which haven't been /// removed. - #[allow(unused)] pub(crate) fn len(&self) -> usize { self.table.len() } @@ -194,7 +193,7 @@ where /// /// This might return `false` if the map has expired keys that are still pending to be /// cleaned up. - #[allow(unused)] + #[expect(unused)] pub(crate) fn is_empty(&self) -> bool { self.len() == 0 } @@ -224,7 +223,7 @@ where /// Clears the map, removing all key-value pairs. Keeps the allocated memory /// for reuse. - #[allow(unused)] + #[expect(unused)] pub(crate) fn clear(&mut self) { self.table.clear(); } @@ -245,7 +244,7 @@ where /// Panics if the new capacity exceeds [`isize::MAX`] bytes and [`abort`](std::process::abort) /// the program in case of allocation error. Use [`try_reserve`](RawWeakMap::try_reserve) instead /// if you want to handle memory allocation failure. - #[allow(unused)] + #[expect(unused)] pub(crate) fn reserve(&mut self, additional: usize) { self.table .reserve(additional, make_hasher(&self.hash_builder)); @@ -259,7 +258,7 @@ where /// /// If the capacity overflows, or the allocator reports a failure, then an error /// is returned. - #[allow(unused)] + #[expect(unused)] pub(crate) fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> { self.table .try_reserve(additional, make_hasher(&self.hash_builder)) @@ -268,7 +267,7 @@ where /// Shrinks the capacity of the map as much as possible. It will drop /// down as much as possible while maintaining the internal rules /// and possibly leaving some space in accordance with the resize policy. - #[allow(unused)] + #[expect(unused)] pub(crate) fn shrink_to_fit(&mut self) { self.table .shrink_to(0, make_hasher::<_, V, S>(&self.hash_builder)); @@ -280,7 +279,7 @@ where /// /// This function does nothing if the current capacity is smaller than the /// supplied minimum capacity. - #[allow(unused)] + #[expect(unused)] pub(crate) fn shrink_to(&mut self, min_capacity: usize) { self.table .shrink_to(min_capacity, make_hasher::<_, V, S>(&self.hash_builder)); diff --git a/core/gc/src/trace.rs b/core/gc/src/trace.rs index beb684fcd4..0079c1d90e 100644 --- a/core/gc/src/trace.rs +++ b/core/gc/src/trace.rs @@ -18,7 +18,7 @@ use crate::GcErasedPointer; /// A queue used to trace [`crate::Gc`] non-recursively. #[doc(hidden)] -#[allow(missing_debug_implementations)] +#[expect(missing_debug_implementations)] pub struct Tracer { queue: VecDeque, } @@ -442,7 +442,7 @@ impl Finalize for LinkedList {} // SAFETY: All the elements of the `LinkedList` are correctly marked. unsafe impl Trace for LinkedList { custom_trace!(this, mark, { - #[allow(clippy::explicit_iter_loop)] + #[expect(clippy::explicit_iter_loop)] for v in this.iter() { mark(v); } diff --git a/core/interner/src/sym.rs b/core/interner/src/sym.rs index 7f30598ca5..9942939aee 100644 --- a/core/interner/src/sym.rs +++ b/core/interner/src/sym.rs @@ -12,7 +12,7 @@ use core::num::NonZeroUsize; serde(transparent) )] #[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))] -#[allow(clippy::unsafe_derive_deserialize)] +#[expect(clippy::unsafe_derive_deserialize)] #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Finalize)] pub struct Sym { value: NonZeroUsize, diff --git a/core/interop/src/into_js_function_impls.rs b/core/interop/src/into_js_function_impls.rs index 772a9914f8..d2bfe28476 100644 --- a/core/interop/src/into_js_function_impls.rs +++ b/core/interop/src/into_js_function_impls.rs @@ -48,7 +48,7 @@ macro_rules! impl_into_js_function { R: TryIntoJsResult, T: FnMut($($t,)*) -> R + 'static, { - #[allow(unused_variables)] + #[expect(unused_variables)] unsafe fn into_js_function_unsafe(self, _context: &mut Context) -> NativeFunction { let s = RefCell::new(self); unsafe { @@ -100,7 +100,7 @@ macro_rules! impl_into_js_function { R: TryIntoJsResult, T: FnMut($($t,)* &mut Context) -> R + 'static, { - #[allow(unused_variables)] + #[expect(unused_variables)] unsafe fn into_js_function_unsafe(self, _context: &mut Context) -> NativeFunction { let s = RefCell::new(self); unsafe { @@ -145,7 +145,7 @@ macro_rules! impl_into_js_function { R: TryIntoJsResult, T: Fn($($t,)*) -> R + 'static + Copy, { - #[allow(unused_variables)] + #[expect(unused_variables)] fn into_js_function_copied(self, _context: &mut Context) -> NativeFunction { let s = self; NativeFunction::from_copy_closure(move |this, args, ctx| { @@ -185,7 +185,7 @@ macro_rules! impl_into_js_function { R: TryIntoJsResult, T: Fn($($t,)* &mut Context) -> R + 'static + Copy, { - #[allow(unused_variables)] + #[expect(unused_variables)] fn into_js_function_copied(self, _context: &mut Context) -> NativeFunction { let s = self; NativeFunction::from_copy_closure(move |this, args, ctx| { diff --git a/core/interop/src/lib.rs b/core/interop/src/lib.rs index af282f77d3..aa63097bd6 100644 --- a/core/interop/src/lib.rs +++ b/core/interop/src/lib.rs @@ -204,7 +204,6 @@ impl<'a> TryFromJsArgument<'a> for Ignore { #[derive(Debug, Clone)] pub struct JsRest<'a>(pub &'a [JsValue]); -#[allow(unused)] impl<'a> JsRest<'a> { /// Consumes the `JsRest` and returns the inner list of `JsValue`. #[must_use] @@ -472,7 +471,7 @@ impl<'a, T: NativeObject + Clone> TryFromJsArgument<'a> for ContextData { mod into_js_function_impls; #[test] -#[allow(clippy::missing_panics_doc)] +#[expect(clippy::missing_panics_doc)] pub fn into_js_module() { use boa_engine::{js_string, JsValue, Source}; use boa_gc::{Gc, GcRefCell}; @@ -640,12 +639,10 @@ fn class() { } impl Test { - #[allow(clippy::needless_pass_by_value)] fn get_value(this: JsClass) -> i32 { this.borrow().value } - #[allow(clippy::needless_pass_by_value)] fn set_value(this: JsClass, new_value: i32) { (*this.borrow_mut()).value = new_value; } diff --git a/core/interop/src/loaders/cached.rs b/core/interop/src/loaders/cached.rs index a8948b7b67..9f30483c79 100644 --- a/core/interop/src/loaders/cached.rs +++ b/core/interop/src/loaders/cached.rs @@ -7,7 +7,7 @@ use std::path::PathBuf; use std::rc::Rc; /// A module loader that caches modules once they're resolved. -#[allow(clippy::module_name_repetitions)] +#[expect(clippy::module_name_repetitions)] #[derive(Clone, Debug)] pub struct CachedModuleLoader where diff --git a/core/interop/src/loaders/embedded.rs b/core/interop/src/loaders/embedded.rs index 0f89c0a2cd..6ff6888fd9 100644 --- a/core/interop/src/loaders/embedded.rs +++ b/core/interop/src/loaders/embedded.rs @@ -70,7 +70,7 @@ impl EmbeddedModuleEntry { /// The resulting type of creating an embedded module loader. #[derive(Debug, Clone)] -#[allow(clippy::module_name_repetitions)] +#[expect(clippy::module_name_repetitions)] pub struct EmbeddedModuleLoader { map: HashMap>, } diff --git a/core/interop/src/loaders/fallback.rs b/core/interop/src/loaders/fallback.rs index 9ca5e34dd0..bda1dc9e24 100644 --- a/core/interop/src/loaders/fallback.rs +++ b/core/interop/src/loaders/fallback.rs @@ -4,7 +4,7 @@ use boa_engine::{Context, JsResult, JsString, Module}; /// A [`ModuleLoader`] that tries to load a module from one loader, and if that fails, /// falls back to another loader. -#[allow(clippy::module_name_repetitions)] +#[expect(clippy::module_name_repetitions)] #[derive(Clone, Debug)] pub struct FallbackModuleLoader(L, R); diff --git a/core/interop/src/macros.rs b/core/interop/src/macros.rs index 9be07ef765..a87bb392b6 100644 --- a/core/interop/src/macros.rs +++ b/core/interop/src/macros.rs @@ -183,12 +183,12 @@ macro_rules! js_class { const LENGTH: usize = $crate::__count!( $( $ctor_arg )* ); - #[allow(clippy::items_after_statements)] + #[expect(clippy::items_after_statements)] fn init(class: &mut $crate::boa_engine::class::ClassBuilder<'_>) -> $crate::boa_engine::JsResult<()> { // Add properties. $( // Declare a function so that the compiler prevents duplicated names. - #[allow(dead_code)] + #[expect(dead_code)] fn $field_prop_name() {} $crate::__get_set_decl!( @@ -237,7 +237,7 @@ macro_rules! js_class { Ok(()) } - #[allow(unused_variables)] + #[expect(unused_variables)] fn data_constructor( new_target: &$crate::boa_engine::JsValue, args: &[$crate::boa_engine::JsValue], @@ -390,7 +390,7 @@ macro_rules! __get_set_decl { // We allow too many lines. This test is straightforward but has a lot of boilerplate // still. #[test] -#[allow(clippy::too_many_lines)] +#[expect(clippy::too_many_lines)] fn js_class_test() { use crate::IntoJsFunctionCopied; use crate::{js_class, loaders, JsClass}; diff --git a/core/interop/tests/fibonacci.rs b/core/interop/tests/fibonacci.rs index 0ce64e3cab..7356f30a13 100644 --- a/core/interop/tests/fibonacci.rs +++ b/core/interop/tests/fibonacci.rs @@ -8,7 +8,6 @@ use boa_engine::{js_error, js_str, Context, JsResult, Module, Source}; use boa_interop::IntoJsFunctionCopied; use std::path::PathBuf; -#[allow(clippy::needless_pass_by_value)] fn fibonacci( a: usize, cb_a: TypedJsFunction<(usize, JsFunction, JsFunction), usize>, diff --git a/core/macros/src/lib.rs b/core/macros/src/lib.rs index 0807d9a0a8..5a3e3a3818 100644 --- a/core/macros/src/lib.rs +++ b/core/macros/src/lib.rs @@ -217,7 +217,7 @@ decl_derive! { } /// Derives the `Trace` trait. -#[allow(clippy::too_many_lines)] +#[expect(clippy::too_many_lines)] fn derive_trace(mut s: Structure<'_>) -> proc_macro2::TokenStream { struct EmptyTrace { copy: bool, @@ -282,8 +282,21 @@ fn derive_trace(mut s: Structure<'_>) -> proc_macro2::TokenStream { .iter() .any(|attr| attr.path().is_ident("unsafe_ignore_trace")) }); - let trace_body = s.each(|bi| quote!(::boa_gc::Trace::trace(#bi, tracer))); - let trace_other_body = s.each(|bi| quote!(mark(#bi))); + let trace_body = s.each(|bi| { + quote! { + unsafe { + ::boa_gc::Trace::trace(#bi, tracer); + } + } + }); + let trace_non_roots_body = s.each(|bi| { + quote! { + unsafe { + ::boa_gc::Trace::trace_non_roots(#bi); + } + } + }); + let run_finalizer_body = s.each(|bi| quote!(::boa_gc::Trace::run_finalizer(#bi))); s.add_bounds(AddBounds::Fields); let trace_impl = s.unsafe_bound_impl( @@ -291,36 +304,16 @@ fn derive_trace(mut s: Structure<'_>) -> proc_macro2::TokenStream { quote! { #[inline] unsafe fn trace(&self, tracer: &mut ::boa_gc::Tracer) { - #[allow(dead_code)] - let mut mark = |it: &dyn ::boa_gc::Trace| { - // SAFETY: The implementor must ensure that `trace` is correctly implemented. - unsafe { - ::boa_gc::Trace::trace(it, tracer); - } - }; match *self { #trace_body } } #[inline] unsafe fn trace_non_roots(&self) { - #[allow(dead_code)] - fn mark(it: &T) { - // SAFETY: The implementor must ensure that `trace_non_roots` is correctly implemented. - unsafe { - ::boa_gc::Trace::trace_non_roots(it); - } - } - match *self { #trace_other_body } + match *self { #trace_non_roots_body } } #[inline] fn run_finalizer(&self) { ::boa_gc::Finalize::finalize(self); - #[allow(dead_code)] - fn mark(it: &T) { - unsafe { - ::boa_gc::Trace::run_finalizer(it); - } - } - match *self { #trace_other_body } + match *self { #run_finalizer_body } } }, ); @@ -332,7 +325,7 @@ fn derive_trace(mut s: Structure<'_>) -> proc_macro2::TokenStream { s.unbound_impl( quote!(::core::ops::Drop), quote! { - #[allow(clippy::inline_always)] + #[expect(clippy::inline_always)] #[inline(always)] fn drop(&mut self) { if ::boa_gc::finalizer_safe() { @@ -358,7 +351,7 @@ decl_derive! { } /// Derives the `Finalize` trait. -#[allow(clippy::needless_pass_by_value)] +#[expect(clippy::needless_pass_by_value)] fn derive_finalize(s: Structure<'_>) -> proc_macro2::TokenStream { s.unbound_impl(quote!(::boa_gc::Finalize), quote!()) } @@ -370,7 +363,7 @@ decl_derive! { } /// Derives the `JsData` trait. -#[allow(clippy::needless_pass_by_value)] +#[expect(clippy::needless_pass_by_value)] fn derive_js_data(s: Structure<'_>) -> proc_macro2::TokenStream { s.unbound_impl(quote!(::boa_engine::JsData), quote!()) } @@ -393,7 +386,10 @@ pub fn derive_try_from_js(input: TokenStream) -> TokenStream { panic!("you can only derive TryFromJs for named-field structs") }; - let conv = generate_conversion(fields).unwrap_or_else(to_compile_errors); + let conv = generate_conversion(fields).unwrap_or_else(|e| { + let compile_errors = e.iter().map(syn::Error::to_compile_error); + quote!(#(#compile_errors)*) + }); let type_name = input.ident; @@ -490,10 +486,3 @@ fn generate_conversion(fields: FieldsNamed) -> Result) -> proc_macro2::TokenStream { - let compile_errors = errors.iter().map(syn::Error::to_compile_error); - quote!(#(#compile_errors)*) -} diff --git a/core/parser/src/error/mod.rs b/core/parser/src/error/mod.rs index 727c247bbe..6a99f57169 100644 --- a/core/parser/src/error/mod.rs +++ b/core/parser/src/error/mod.rs @@ -16,7 +16,7 @@ pub(crate) trait ErrorContext { fn set_context(self, context: &'static str) -> Self; /// Gets the context of the error, if any. - #[allow(dead_code)] + #[allow(unused)] fn context(&self) -> Option<&'static str>; } diff --git a/core/parser/src/lexer/cursor.rs b/core/parser/src/lexer/cursor.rs index ae352621da..1ee8e52a60 100644 --- a/core/parser/src/lexer/cursor.rs +++ b/core/parser/src/lexer/cursor.rs @@ -121,7 +121,7 @@ impl Cursor { Ok(match self.peek_char()? { Some(byte) if (0..=0x7F).contains(&byte) => { - #[allow(clippy::cast_possible_truncation)] + #[expect(clippy::cast_possible_truncation)] pred(char::from(byte as u8)) } Some(_) | None => false, @@ -163,7 +163,7 @@ impl Cursor { if !self.next_is_ascii_pred(pred)? { return Ok(()); } else if let Some(byte) = self.next_char()? { - #[allow(clippy::cast_possible_truncation)] + #[expect(clippy::cast_possible_truncation)] buf.push(byte as u8); } else { // next_is_pred will return false if the next value is None so the None case should already be handled. diff --git a/core/parser/src/lexer/mod.rs b/core/parser/src/lexer/mod.rs index d0c41b0da8..91d2da130c 100644 --- a/core/parser/src/lexer/mod.rs +++ b/core/parser/src/lexer/mod.rs @@ -312,7 +312,7 @@ impl Lexer { let start = self.cursor.pos(); SingleLineComment.lex(&mut self.cursor, start, interner) } - #[allow(clippy::cast_possible_truncation)] + #[expect(clippy::cast_possible_truncation)] '=' | '*' | '+' | '-' | '%' | '|' | '&' | '^' | '<' | '>' | '!' | '~' | '?' => { Operator::new(next_ch as u8).lex(&mut self.cursor, start, interner) } @@ -322,7 +322,7 @@ impl Lexer { _ if Identifier::is_identifier_start(c as u32) => { Identifier::new(c).lex(&mut self.cursor, start, interner) } - #[allow(clippy::cast_possible_truncation)] + #[expect(clippy::cast_possible_truncation)] _ if c.is_ascii_digit() => { NumberLiteral::new(next_ch as u8).lex(&mut self.cursor, start, interner) } @@ -355,7 +355,6 @@ impl Lexer { /// /// Will return `Err` on invalid tokens and invalid reads of the bytes being lexed. // We intentionally don't implement Iterator trait as Result