Browse Source

Fix lints from rustc 1.80.0 (#3936)

pull/3939/head
José Julián Espina 4 months ago committed by GitHub
parent
commit
4c76af8c67
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 30
      Cargo.toml
  2. 4
      core/ast/src/expression/access.rs
  3. 2
      core/ast/src/expression/optional.rs
  4. 2
      core/ast/src/operations.rs
  5. 2
      core/engine/src/builtins/array_buffer/shared.rs
  6. 12
      core/engine/src/builtins/array_buffer/utils.rs
  7. 14
      core/engine/src/builtins/dataview/mod.rs
  8. 4
      core/engine/src/builtins/date/mod.rs
  9. 4
      core/engine/src/builtins/intl/locale/utils.rs
  10. 4
      core/engine/src/builtins/intl/mod.rs
  11. 2
      core/engine/src/builtins/mod.rs
  12. 2
      core/engine/src/builtins/number/globals.rs
  13. 4
      core/engine/src/builtins/promise/mod.rs
  14. 12
      core/engine/src/builtins/typed_array/mod.rs
  15. 6
      core/engine/src/bytecompiler/mod.rs
  16. 4
      core/engine/src/class.rs
  17. 18
      core/engine/src/context/hooks.rs
  18. 14
      core/engine/src/job.rs
  19. 16
      core/engine/src/module/loader.rs
  20. 14
      core/engine/src/object/builtins/jspromise.rs
  21. 10
      core/engine/src/object/jsobject.rs
  22. 4
      core/engine/src/object/mod.rs
  23. 31
      core/engine/src/object/property_map.rs
  24. 6
      core/engine/src/tagged.rs
  25. 2
      core/engine/src/vm/opcode/get/name.rs
  26. 2
      core/engine/src/vm/opcode/iteration/iterator.rs
  27. 30
      core/engine/src/vm/opcode/mod.rs
  28. 2
      core/gc/src/internals/vtable.rs
  29. 10
      core/gc/src/lib.rs
  30. 2
      core/gc/src/pointers/ephemeron.rs
  31. 2
      core/gc/src/test/allocation.rs
  32. 4
      core/gc/src/test/weak.rs
  33. 4
      core/gc/src/trace.rs
  34. 4
      core/interner/src/interned_str.rs
  35. 1
      core/parser/src/lexer/template.rs
  36. 5
      core/parser/src/lexer/token.rs
  37. 2
      core/parser/src/parser/cursor/buffered_lexer/mod.rs
  38. 2
      core/string/src/lib.rs
  39. 6
      core/string/src/tagged.rs
  40. 19
      examples/src/bin/commuter_visitor.rs

30
Cargo.toml

@ -29,7 +29,7 @@ exclude = [
[workspace.package] [workspace.package]
edition = "2021" edition = "2021"
version = "0.19.0" version = "0.19.0"
rust-version = "1.79.0" rust-version = "1.80.0"
authors = ["boa-dev"] authors = ["boa-dev"]
repository = "https://github.com/boa-dev/boa" repository = "https://github.com/boa-dev/boa"
license = "Unlicense OR MIT" license = "Unlicense OR MIT"
@ -185,13 +185,13 @@ codegen-units = 1
[workspace.lints.rust] [workspace.lints.rust]
# rustc lint groups https://doc.rust-lang.org/rustc/lints/groups.html # rustc lint groups https://doc.rust-lang.org/rustc/lints/groups.html
warnings = "warn" warnings = "warn"
future_incompatible = "warn" future_incompatible = { level = "warn", priority = -1 }
let_underscore = "warn" let_underscore = { level = "warn", priority = -1 }
nonstandard_style = "warn" nonstandard_style = { level = "warn", priority = -1 }
rust_2018_compatibility = "warn" rust_2018_compatibility = { level = "warn", priority = -1 }
rust_2018_idioms = "warn" rust_2018_idioms = { level = "warn", priority = -1 }
rust_2021_compatibility = "warn" rust_2021_compatibility = { level = "warn", priority = -1 }
unused = "warn" unused = { level = "warn", priority = -1 }
# rustc allowed-by-default lints https://doc.rust-lang.org/rustc/lints/listing/allowed-by-default.html # rustc allowed-by-default lints https://doc.rust-lang.org/rustc/lints/listing/allowed-by-default.html
missing_docs = "warn" missing_docs = "warn"
@ -228,10 +228,10 @@ bare_urls = "warn"
dbg_macro = "warn" dbg_macro = "warn"
# clippy categories https://doc.rust-lang.org/clippy/ # clippy categories https://doc.rust-lang.org/clippy/
all = "warn" all = { level = "warn", priority = -1 }
correctness = "warn" correctness = { level = "warn", priority = -1 }
suspicious = "warn" suspicious = { level = "warn", priority = -1 }
style = "warn" style = { level = "warn", priority = -1 }
complexity = "warn" complexity = { level = "warn", priority = -1 }
perf = "warn" perf = { level = "warn", priority = -1 }
pedantic = "warn" pedantic = { level = "warn", priority = -1 }

4
core/ast/src/expression/access.rs

@ -3,9 +3,9 @@
//! [Property access expressions][access] provide two ways to access properties of an object: *dot notation* //! [Property access expressions][access] provide two ways to access properties of an object: *dot notation*
//! and *bracket notation*. //! and *bracket notation*.
//! - *Dot notation* is mostly used when the name of the property is static, and a valid Javascript //! - *Dot notation* is mostly used when the name of the property is static, and a valid Javascript
//! identifier e.g. `obj.prop`, `arr.$val`. //! identifier e.g. `obj.prop`, `arr.$val`.
//! - *Bracket notation* is used when the name of the property is either variable, not a valid //! - *Bracket notation* is used when the name of the property is either variable, not a valid
//! identifier or a symbol e.g. `arr[var]`, `arr[5]`, `arr[Symbol.iterator]`. //! identifier or a symbol e.g. `arr[var]`, `arr[5]`, `arr[Symbol.iterator]`.
//! //!
//! A property access expression can be represented by a [`SimplePropertyAccess`] (`x.y`), a //! A property access expression can be represented by a [`SimplePropertyAccess`] (`x.y`), a
//! [`PrivatePropertyAccess`] (`x.#y`) or a [`SuperPropertyAccess`] (`super["y"]`), each of them with //! [`PrivatePropertyAccess`] (`x.#y`) or a [`SuperPropertyAccess`] (`super["y"]`), each of them with

2
core/ast/src/expression/optional.rs

@ -38,7 +38,7 @@ impl VisitWith for OptionalOperationKind {
Self::SimplePropertyAccess { field } => visitor.visit_property_access_field(field), Self::SimplePropertyAccess { field } => visitor.visit_property_access_field(field),
Self::PrivatePropertyAccess { field } => visitor.visit_private_name(field), Self::PrivatePropertyAccess { field } => visitor.visit_private_name(field),
Self::Call { args } => { Self::Call { args } => {
for arg in args.iter() { for arg in args {
try_break!(visitor.visit_expression(arg)); try_break!(visitor.visit_expression(arg));
} }
ControlFlow::Continue(()) ControlFlow::Continue(())

2
core/ast/src/operations.rs

@ -993,7 +993,7 @@ impl<'ast> Visitor<'ast> for AllPrivateIdentifiersValidVisitor {
} }
} }
OptionalOperationKind::Call { args } => { OptionalOperationKind::Call { args } => {
for arg in args.iter() { for arg in args {
try_break!(self.visit_expression(arg)); try_break!(self.visit_expression(arg));
} }
ControlFlow::Continue(()) ControlFlow::Continue(())

2
core/engine/src/builtins/array_buffer/shared.rs

@ -609,7 +609,7 @@ pub(crate) fn create_shared_byte_data_block(
// This could be replaced with a custom `Box` implementation, but most architectures // This could be replaced with a custom `Box` implementation, but most architectures
// already align pointers to 8 bytes, so it's a lot of work for such a small // already align pointers to 8 bytes, so it's a lot of work for such a small
// compatibility improvement. // compatibility improvement.
assert_eq!(buffer.as_ptr().addr() % std::mem::align_of::<u64>(), 0); assert_eq!(buffer.as_ptr().addr() % align_of::<u64>(), 0);
// 3. Return db. // 3. Return db.
Ok(buffer) Ok(buffer)

12
core/engine/src/builtins/array_buffer/utils.rs

@ -91,8 +91,8 @@ impl SliceRef<'_> {
// 2. Assert: There are sufficient bytes in arrayBuffer starting at byteIndex to represent a value of type. // 2. Assert: There are sufficient bytes in arrayBuffer starting at byteIndex to represent a value of type.
#[cfg(debug_assertions)] #[cfg(debug_assertions)]
{ {
assert!(buffer.len() >= std::mem::size_of::<T>()); assert!(buffer.len() >= size_of::<T>());
assert_eq!(buffer.addr() % std::mem::align_of::<T>(), 0); assert_eq!(buffer.addr() % align_of::<T>(), 0);
} }
// 3. Let block be arrayBuffer.[[ArrayBufferData]]. // 3. Let block be arrayBuffer.[[ArrayBufferData]].
@ -270,8 +270,8 @@ impl SliceRefMut<'_> {
// 3. Assert: value is a BigInt if IsBigIntElementType(type) is true; otherwise, value is a Number. // 3. Assert: value is a BigInt if IsBigIntElementType(type) is true; otherwise, value is a Number.
#[cfg(debug_assertions)] #[cfg(debug_assertions)]
{ {
assert!(buffer.len() >= std::mem::size_of::<T>()); assert!(buffer.len() >= size_of::<T>());
assert_eq!(buffer.addr() % std::mem::align_of::<T>(), 0); assert_eq!(buffer.addr() % align_of::<T>(), 0);
} }
// 4. Let block be arrayBuffer.[[ArrayBufferData]]. // 4. Let block be arrayBuffer.[[ArrayBufferData]].
@ -335,7 +335,7 @@ impl<'a> From<&'a [AtomicU8]> for SliceRefMut<'a> {
/// # Safety /// # Safety
/// ///
/// - Both `src` and `dest` must have at least `count` bytes to read and write, /// - Both `src` and `dest` must have at least `count` bytes to read and write,
/// respectively. /// respectively.
pub(super) unsafe fn copy_shared_to_shared( pub(super) unsafe fn copy_shared_to_shared(
src: *const AtomicU8, src: *const AtomicU8,
dest: *const AtomicU8, dest: *const AtomicU8,
@ -355,7 +355,7 @@ pub(super) unsafe fn copy_shared_to_shared(
/// # Safety /// # Safety
/// ///
/// - Both `src` and `dest` must have at least `count` bytes to read and write, /// - Both `src` and `dest` must have at least `count` bytes to read and write,
/// respectively. /// respectively.
unsafe fn copy_shared_to_shared_backwards( unsafe fn copy_shared_to_shared_backwards(
src: *const AtomicU8, src: *const AtomicU8,
dest: *const AtomicU8, dest: *const AtomicU8,

14
core/engine/src/builtins/dataview/mod.rs

@ -7,7 +7,7 @@
//! [spec]: https://tc39.es/ecma262/#sec-dataview-objects //! [spec]: https://tc39.es/ecma262/#sec-dataview-objects
//! [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DataView //! [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DataView
use std::{mem, sync::atomic::Ordering}; use std::sync::atomic::Ordering;
use crate::{ use crate::{
builtins::BuiltInObject, builtins::BuiltInObject,
@ -467,7 +467,7 @@ impl DataView {
let view_size = view.byte_length(data.len()); let view_size = view.byte_length(data.len());
// 10. Let elementSize be the Element Size value specified in Table 71 for Element Type type. // 10. Let elementSize be the Element Size value specified in Table 71 for Element Type type.
let element_size = mem::size_of::<T>() as u64; let element_size = size_of::<T>() as u64;
// 11. If getIndex + elementSize > viewSize, throw a RangeError exception. // 11. If getIndex + elementSize > viewSize, throw a RangeError exception.
if get_index + element_size > view_size { if get_index + element_size > view_size {
@ -481,7 +481,7 @@ impl DataView {
let src = data.subslice(buffer_index..); let src = data.subslice(buffer_index..);
debug_assert!(src.len() >= mem::size_of::<T>()); debug_assert!(src.len() >= size_of::<T>());
// 13. Return GetValueFromBuffer(view.[[ViewedArrayBuffer]], bufferIndex, type, false, unordered, isLittleEndian). // 13. Return GetValueFromBuffer(view.[[ViewedArrayBuffer]], bufferIndex, type, false, unordered, isLittleEndian).
// SAFETY: All previous checks ensure the element fits in the buffer. // SAFETY: All previous checks ensure the element fits in the buffer.
@ -490,7 +490,7 @@ impl DataView {
memcpy( memcpy(
src.as_ptr(), src.as_ptr(),
BytesMutPtr::Bytes(bytes_of_mut(&mut value).as_mut_ptr()), BytesMutPtr::Bytes(bytes_of_mut(&mut value).as_mut_ptr()),
mem::size_of::<T>(), size_of::<T>(),
); );
if is_little_endian { if is_little_endian {
@ -789,7 +789,7 @@ impl DataView {
let view_offset = view.byte_offset; let view_offset = view.byte_offset;
// 12. Let elementSize be the Element Size value specified in Table 71 for Element Type type. // 12. Let elementSize be the Element Size value specified in Table 71 for Element Type type.
let elem_size = mem::size_of::<T>(); let elem_size = size_of::<T>();
// 13. If getIndex + elementSize > viewSize, throw a RangeError exception. // 13. If getIndex + elementSize > viewSize, throw a RangeError exception.
if get_index + elem_size as u64 > view_size { if get_index + elem_size as u64 > view_size {
@ -803,7 +803,7 @@ impl DataView {
let mut target = data.subslice_mut(buffer_index..); let mut target = data.subslice_mut(buffer_index..);
debug_assert!(target.len() >= mem::size_of::<T>()); debug_assert!(target.len() >= size_of::<T>());
// 15. Perform SetValueInBuffer(view.[[ViewedArrayBuffer]], bufferIndex, type, numberValue, false, unordered, isLittleEndian). // 15. Perform SetValueInBuffer(view.[[ViewedArrayBuffer]], bufferIndex, type, numberValue, false, unordered, isLittleEndian).
// SAFETY: All previous checks ensure the element fits in the buffer. // SAFETY: All previous checks ensure the element fits in the buffer.
@ -817,7 +817,7 @@ impl DataView {
memcpy( memcpy(
BytesConstPtr::Bytes(bytes_of(&value).as_ptr()), BytesConstPtr::Bytes(bytes_of(&value).as_ptr()),
target.as_ptr(), target.as_ptr(),
mem::size_of::<T>(), size_of::<T>(),
); );
} }

4
core/engine/src/builtins/date/mod.rs

@ -193,8 +193,8 @@ impl BuiltInConstructor for Date {
/// ///
/// - When called as a function, returns a string displaying the current time in the UTC timezone. /// - When called as a function, returns a string displaying the current time in the UTC timezone.
/// - When called as a constructor, it returns a new `Date` object from the provided arguments. /// - When called as a constructor, it returns a new `Date` object from the provided arguments.
/// The [MDN documentation][mdn] has a more extensive explanation on the usages and return /// The [MDN documentation][mdn] has a more extensive explanation on the usages and return
/// values for all possible arguments. /// values for all possible arguments.
/// ///
/// [spec]: https://tc39.es/ecma262/#sec-date-constructor /// [spec]: https://tc39.es/ecma262/#sec-date-constructor
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/Date /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/Date

4
core/engine/src/builtins/intl/locale/utils.rs

@ -155,8 +155,8 @@ pub(crate) fn canonicalize_locale_list(
/// # Notes /// # Notes
/// ///
/// - This differs a bit from the spec, since we don't have an `[[AvailableLocales]]` /// - This differs a bit from the spec, since we don't have an `[[AvailableLocales]]`
/// list to compare with. However, we can do data requests to a [`DataProvider`] /// list to compare with. However, we can do data requests to a [`DataProvider`]
/// in order to see if a certain [`Locale`] is supported. /// in order to see if a certain [`Locale`] is supported.
/// ///
/// - Calling this function with a singleton `KeyedDataMarker` will always return `None`. /// - Calling this function with a singleton `KeyedDataMarker` will always return `None`.
/// ///

4
core/engine/src/builtins/intl/mod.rs

@ -202,9 +202,9 @@ trait Service {
/// # Note /// # Note
/// ///
/// - A correct implementation must ensure `locale` and `options` are both written with the /// - A correct implementation must ensure `locale` and `options` are both written with the
/// new final values. /// new final values.
/// - If the implementor service doesn't contain any `[[RelevantExtensionKeys]]`, this can be /// - If the implementor service doesn't contain any `[[RelevantExtensionKeys]]`, this can be
/// skipped. /// skipped.
fn resolve( fn resolve(
_locale: &mut icu_locid::Locale, _locale: &mut icu_locid::Locale,
_options: &mut Self::LocaleOptions, _options: &mut Self::LocaleOptions,

2
core/engine/src/builtins/mod.rs

@ -140,6 +140,8 @@ pub(crate) trait BuiltInObject: IntrinsicObject {
/// E.g. If you want access the properties of a `Complex` built-in with the name `Cplx` you must /// E.g. If you want access the properties of a `Complex` built-in with the name `Cplx` you must
/// assign `"Cplx"` to this constant, making any property inside it accessible from ECMAScript /// assign `"Cplx"` to this constant, making any property inside it accessible from ECMAScript
/// as `Cplx.prop` /// as `Cplx.prop`
// `JsString` can only be const-constructed for static strings.
#[allow(clippy::declare_interior_mutable_const)]
const NAME: JsString; const NAME: JsString;
/// Property attribute flags of the built-in. Check [`Attribute`] for more information. /// Property attribute flags of the built-in. Check [`Attribute`] for more information.

2
core/engine/src/builtins/number/globals.rs

@ -99,7 +99,7 @@ fn from_js_str_radix(src: JsStr<'_>, radix: u8) -> Option<f64> {
/// Note that if the radix is known to the compiler, it is just the check of digits.len that /// Note that if the radix is known to the compiler, it is just the check of digits.len that
/// is done at runtime. /// is done at runtime.
fn can_not_overflow(radix: u8, digits_len: usize) -> bool { fn can_not_overflow(radix: u8, digits_len: usize) -> bool {
usize::from(radix) <= 16 && digits_len <= std::mem::size_of::<u64>() * 2 usize::from(radix) <= 16 && digits_len <= size_of::<u64>() * 2
} }
const fn to_digit(input: u8, radix: u8) -> Option<u8> { const fn to_digit(input: u8, radix: u8) -> Option<u8> {

4
core/engine/src/builtins/promise/mod.rs

@ -88,8 +88,8 @@ pub struct Promise {
/// Per the spec: /// Per the spec:
/// ///
/// > If operation is "handle", an implementation should not hold a reference to promise in a way /// > If operation is "handle", an implementation should not hold a reference to promise in a way
/// that would interfere with garbage collection. An implementation may hold a reference to promise /// > that would interfere with garbage collection. An implementation may hold a reference to promise
/// if operation is "reject", since it is expected that rejections will be rare and not on hot code paths. /// > if operation is "reject", since it is expected that rejections will be rare and not on hot code paths.
/// ///
/// [fn]: https://tc39.es/ecma262/#sec-host-promise-rejection-tracker /// [fn]: https://tc39.es/ecma262/#sec-host-promise-rejection-tracker
#[derive(Debug, Clone, Copy, PartialEq, Eq)] #[derive(Debug, Clone, Copy, PartialEq, Eq)]

12
core/engine/src/builtins/typed_array/mod.rs

@ -76,12 +76,12 @@ impl<T: TypedArrayMarker> IntrinsicObject for T {
) )
.property( .property(
js_str!("BYTES_PER_ELEMENT"), js_str!("BYTES_PER_ELEMENT"),
std::mem::size_of::<T::Element>(), size_of::<T::Element>(),
Attribute::READONLY | Attribute::NON_ENUMERABLE | Attribute::PERMANENT, Attribute::READONLY | Attribute::NON_ENUMERABLE | Attribute::PERMANENT,
) )
.static_property( .static_property(
js_str!("BYTES_PER_ELEMENT"), js_str!("BYTES_PER_ELEMENT"),
std::mem::size_of::<T::Element>(), size_of::<T::Element>(),
Attribute::READONLY | Attribute::NON_ENUMERABLE | Attribute::PERMANENT, Attribute::READONLY | Attribute::NON_ENUMERABLE | Attribute::PERMANENT,
) )
.build(); .build();
@ -437,14 +437,14 @@ impl TypedArrayKind {
pub(crate) const fn element_size(self) -> u64 { pub(crate) const fn element_size(self) -> u64 {
match self { match self {
TypedArrayKind::Int8 | TypedArrayKind::Uint8 | TypedArrayKind::Uint8Clamped => { TypedArrayKind::Int8 | TypedArrayKind::Uint8 | TypedArrayKind::Uint8Clamped => {
std::mem::size_of::<u8>() as u64 size_of::<u8>() as u64
} }
TypedArrayKind::Int16 | TypedArrayKind::Uint16 => std::mem::size_of::<u16>() as u64, TypedArrayKind::Int16 | TypedArrayKind::Uint16 => size_of::<u16>() as u64,
TypedArrayKind::Int32 | TypedArrayKind::Uint32 | TypedArrayKind::Float32 => { TypedArrayKind::Int32 | TypedArrayKind::Uint32 | TypedArrayKind::Float32 => {
std::mem::size_of::<u32>() as u64 size_of::<u32>() as u64
} }
TypedArrayKind::BigInt64 | TypedArrayKind::BigUint64 | TypedArrayKind::Float64 => { TypedArrayKind::BigInt64 | TypedArrayKind::BigUint64 | TypedArrayKind::Float64 => {
std::mem::size_of::<u64>() as u64 size_of::<u64>() as u64
} }
} }
} }

6
core/engine/src/bytecompiler/mod.rs

@ -743,7 +743,7 @@ impl<'ctx> ByteCompiler<'ctx> {
} }
pub(crate) fn patch_jump_with_target(&mut self, label: Label, target: u32) { pub(crate) fn patch_jump_with_target(&mut self, label: Label, target: u32) {
const U32_SIZE: usize = std::mem::size_of::<u32>(); const U32_SIZE: usize = size_of::<u32>();
let Label { index } = label; let Label { index } = label;
@ -1104,9 +1104,9 @@ impl<'ctx> ByteCompiler<'ctx> {
/// ///
/// # Requirements /// # Requirements
/// - This should only be called after verifying that the previous value of the chain /// - This should only be called after verifying that the previous value of the chain
/// is not null or undefined (if the operator `?.` was used). /// is not null or undefined (if the operator `?.` was used).
/// - This assumes that the state of the stack before compiling is `...rest, this, value`, /// - This assumes that the state of the stack before compiling is `...rest, this, value`,
/// since the operation compiled by this function could be a call. /// since the operation compiled by this function could be a call.
fn compile_optional_item_kind(&mut self, kind: &OptionalOperationKind) { fn compile_optional_item_kind(&mut self, kind: &OptionalOperationKind) {
match kind { match kind {
OptionalOperationKind::SimplePropertyAccess { field } => { OptionalOperationKind::SimplePropertyAccess { field } => {

4
core/engine/src/class.rs

@ -154,7 +154,7 @@ pub trait Class: NativeObject + Sized {
/// ///
/// - Throws an error if `new_target` is undefined. /// - Throws an error if `new_target` is undefined.
/// - Throws an error if this class is not registered in `new_target`'s realm. /// - Throws an error if this class is not registered in `new_target`'s realm.
/// See [`Context::register_global_class`]. /// See [`Context::register_global_class`].
/// ///
/// <div class="warning"> /// <div class="warning">
/// Overriding this method could be useful for certain usages, but incorrectly implementing this /// Overriding this method could be useful for certain usages, but incorrectly implementing this
@ -211,7 +211,7 @@ pub trait Class: NativeObject + Sized {
/// ///
/// # Errors /// # Errors
/// - Throws an error if this class is not registered in the context's realm. See /// - Throws an error if this class is not registered in the context's realm. See
/// [`Context::register_global_class`]. /// [`Context::register_global_class`].
/// ///
/// <div class="warning"> /// <div class="warning">
/// Overriding this method could be useful for certain usages, but incorrectly implementing this /// Overriding this method could be useful for certain usages, but incorrectly implementing this

18
core/engine/src/context/hooks.rs

@ -96,7 +96,7 @@ pub trait HostHooks {
/// # Requirements /// # Requirements
/// ///
/// - It must complete normally (i.e. not return an abrupt completion). This is already /// - It must complete normally (i.e. not return an abrupt completion). This is already
/// ensured by the return type. /// ensured by the return type.
/// ///
/// [spec]: https://tc39.es/ecma262/#sec-host-promise-rejection-tracker /// [spec]: https://tc39.es/ecma262/#sec-host-promise-rejection-tracker
fn promise_rejection_tracker( fn promise_rejection_tracker(
@ -113,7 +113,7 @@ pub trait HostHooks {
/// # Requirements /// # Requirements
/// ///
/// - If the returned Completion Record is a normal completion, it must be a normal completion /// - If the returned Completion Record is a normal completion, it must be a normal completion
/// containing unused. This is already ensured by the return type. /// containing unused. This is already ensured by the return type.
/// ///
/// [spec]: https://tc39.es/ecma262/#sec-hostensurecancompilestrings /// [spec]: https://tc39.es/ecma262/#sec-hostensurecancompilestrings
fn ensure_can_compile_strings( fn ensure_can_compile_strings(
@ -133,7 +133,7 @@ pub trait HostHooks {
/// # Requirements /// # Requirements
/// ///
/// - It must be deterministic with respect to its parameters. Each time it is called with a /// - It must be deterministic with respect to its parameters. Each time it is called with a
/// specific `func` as its argument, it must return the same result. /// specific `func` as its argument, it must return the same result.
/// ///
/// [spec]: https://tc39.es/ecma262/#sec-hosthassourcetextavailable /// [spec]: https://tc39.es/ecma262/#sec-hosthassourcetextavailable
fn has_source_text_available(&self, _function: &JsFunction, _context: &mut Context) -> bool { fn has_source_text_available(&self, _function: &JsFunction, _context: &mut Context) -> bool {
@ -146,9 +146,9 @@ pub trait HostHooks {
/// # Requirements /// # Requirements
/// ///
/// - If `O` is not a host-defined exotic object, this abstract operation must return /// - If `O` is not a host-defined exotic object, this abstract operation must return
/// `NormalCompletion(unused)` and perform no other steps. /// `NormalCompletion(unused)` and perform no other steps.
/// - Any two calls of this abstract operation with the same argument must return the same kind /// - Any two calls of this abstract operation with the same argument must return the same kind
/// of *Completion Record*. /// of *Completion Record*.
/// - This abstract operation should only be overriden by ECMAScript hosts that are web browsers. /// - This abstract operation should only be overriden by ECMAScript hosts that are web browsers.
/// ///
/// [spec]: https://tc39.es/ecma262/#sec-hostensurecanaddprivateelement /// [spec]: https://tc39.es/ecma262/#sec-hostensurecanaddprivateelement
@ -212,10 +212,10 @@ pub trait HostHooks {
/// [specification]: /// [specification]:
/// ///
/// > If a host is multi-tenanted (i.e. it runs many ECMAScript applications simultaneously), /// > If a host is multi-tenanted (i.e. it runs many ECMAScript applications simultaneously),
/// such as a web browser, and its implementations choose to implement in-place growth by reserving /// > such as a web browser, and its implementations choose to implement in-place growth by reserving
/// virtual memory, we recommend that both 32-bit and 64-bit implementations throw for values of /// > virtual memory, we recommend that both 32-bit and 64-bit implementations throw for values of
/// "`maxByteLength`" ≥ 1GiB to 1.5GiB. This is to reduce the likelihood a single application can /// > "`maxByteLength`" ≥ 1GiB to 1.5GiB. This is to reduce the likelihood a single application can
/// exhaust the virtual memory address space and to reduce interoperability risk. /// > exhaust the virtual memory address space and to reduce interoperability risk.
/// ///
/// ///
/// [specification]: https://tc39.es/ecma262/#sec-resizable-arraybuffer-guidelines /// [specification]: https://tc39.es/ecma262/#sec-resizable-arraybuffer-guidelines

14
core/engine/src/job.rs

@ -10,9 +10,9 @@
//! implementing custom event loops, custom handling of Jobs or other fun things. //! implementing custom event loops, custom handling of Jobs or other fun things.
//! This trait is also accompanied by two implementors of the trait: //! This trait is also accompanied by two implementors of the trait:
//! - [`IdleJobQueue`], which is a queue that does nothing, and the default queue if no queue is //! - [`IdleJobQueue`], which is a queue that does nothing, and the default queue if no queue is
//! provided. Useful for hosts that want to disable promises. //! provided. Useful for hosts that want to disable promises.
//! - [`SimpleJobQueue`], which is a simple FIFO queue that runs all jobs to completion, bailing //! - [`SimpleJobQueue`], which is a simple FIFO queue that runs all jobs to completion, bailing
//! on the first error encountered. //! on the first error encountered.
//! //!
//! [Job]: https://tc39.es/ecma262/#sec-jobs //! [Job]: https://tc39.es/ecma262/#sec-jobs
//! [JobCallback]: https://tc39.es/ecma262/#sec-jobcallback-records //! [JobCallback]: https://tc39.es/ecma262/#sec-jobcallback-records
@ -37,7 +37,7 @@ pub type FutureJob = Pin<Box<dyn Future<Output = NativeJob> + 'static>>;
/// ### Requirements /// ### Requirements
/// ///
/// - At some future point in time, when there is no running execution context and the execution /// - At some future point in time, when there is no running execution context and the execution
/// context stack is empty, the implementation must: /// context stack is empty, the implementation must:
/// - Perform any host-defined preparation steps. /// - Perform any host-defined preparation steps.
/// - Invoke the Job Abstract Closure. /// - Invoke the Job Abstract Closure.
/// - Perform any host-defined cleanup steps, after which the execution context stack must be empty. /// - Perform any host-defined cleanup steps, after which the execution context stack must be empty.
@ -196,12 +196,12 @@ pub trait JobQueue {
/// ///
/// Per the [spec]: /// Per the [spec]:
/// > An implementation of `HostEnqueuePromiseJob` must conform to the requirements in [9.5][Jobs] as well as the /// > An implementation of `HostEnqueuePromiseJob` must conform to the requirements in [9.5][Jobs] as well as the
/// following: /// > following:
/// > - If `realm` is not null, each time `job` is invoked the implementation must perform implementation-defined steps /// > - If `realm` is not null, each time `job` is invoked the implementation must perform implementation-defined steps
/// such that execution is prepared to evaluate ECMAScript code at the time of job's invocation. /// > such that execution is prepared to evaluate ECMAScript code at the time of job's invocation.
/// > - Let `scriptOrModule` be `GetActiveScriptOrModule()` at the time `HostEnqueuePromiseJob` is invoked. If realm /// > - Let `scriptOrModule` be `GetActiveScriptOrModule()` at the time `HostEnqueuePromiseJob` is invoked. If realm
/// is not null, each time job is invoked the implementation must perform implementation-defined steps such that /// > is not null, each time job is invoked the implementation must perform implementation-defined steps such that
/// `scriptOrModule` is the active script or module at the time of job's invocation. /// > `scriptOrModule` is the active script or module at the time of job's invocation.
/// > - Jobs must run in the same order as the `HostEnqueuePromiseJob` invocations that scheduled them. /// > - Jobs must run in the same order as the `HostEnqueuePromiseJob` invocations that scheduled them.
/// ///
/// Of all the requirements, Boa guarantees the first two by its internal implementation of `NativeJob`, meaning /// Of all the requirements, Boa guarantees the first two by its internal implementation of `NativeJob`, meaning

16
core/engine/src/module/loader.rs

@ -155,16 +155,16 @@ pub trait ModuleLoader {
/// # Requirements /// # Requirements
/// ///
/// - The host environment must perform `FinishLoadingImportedModule(referrer, specifier, payload, result)`, /// - The host environment must perform `FinishLoadingImportedModule(referrer, specifier, payload, result)`,
/// where result is either a normal completion containing the loaded Module Record or a throw /// where result is either a normal completion containing the loaded Module Record or a throw
/// completion, either synchronously or asynchronously. This is equivalent to calling the `finish_load` /// completion, either synchronously or asynchronously. This is equivalent to calling the `finish_load`
/// callback. /// callback.
/// - If this operation is called multiple times with the same `(referrer, specifier)` pair and /// - If this operation is called multiple times with the same `(referrer, specifier)` pair and
/// it performs FinishLoadingImportedModule(referrer, specifier, payload, result) where result /// it performs FinishLoadingImportedModule(referrer, specifier, payload, result) where result
/// is a normal completion, then it must perform /// is a normal completion, then it must perform
/// `FinishLoadingImportedModule(referrer, specifier, payload, result)` with the same result each /// `FinishLoadingImportedModule(referrer, specifier, payload, result)` with the same result each
/// time. /// time.
/// - The operation must treat payload as an opaque value to be passed through to /// - The operation must treat payload as an opaque value to be passed through to
/// `FinishLoadingImportedModule`. (can be ignored) /// `FinishLoadingImportedModule`. (can be ignored)
/// ///
/// [spec]: https://tc39.es/ecma262/#sec-HostLoadImportedModule /// [spec]: https://tc39.es/ecma262/#sec-HostLoadImportedModule
/// [finish]: https://tc39.es/ecma262/#sec-FinishLoadingImportedModule /// [finish]: https://tc39.es/ecma262/#sec-FinishLoadingImportedModule

14
core/engine/src/object/builtins/jspromise.rs

@ -110,8 +110,8 @@ impl JsPromise {
/// - The executor function `executor` is called synchronously just after the promise is created. /// - The executor function `executor` is called synchronously just after the promise is created.
/// - The executor return value is ignored. /// - The executor return value is ignored.
/// - Any error thrown within the execution of `executor` will call the `reject` function /// - Any error thrown within the execution of `executor` will call the `reject` function
/// of the newly created promise, unless either `resolve` or `reject` were already called /// of the newly created promise, unless either `resolve` or `reject` were already called
/// beforehand. /// beforehand.
/// ///
/// `executor` receives as an argument the [`ResolvingFunctions`] needed to settle the promise, /// `executor` receives as an argument the [`ResolvingFunctions`] needed to settle the promise,
/// which can be done by either calling the `resolve` function or the `reject` function. /// which can be done by either calling the `resolve` function or the `reject` function.
@ -424,9 +424,9 @@ impl JsPromise {
/// the original promise settles: /// the original promise settles:
/// ///
/// - If the original promise is fulfilled, `on_fulfilled` is called with the fulfillment value /// - If the original promise is fulfilled, `on_fulfilled` is called with the fulfillment value
/// of the original promise. /// of the original promise.
/// - If the original promise is rejected, `on_rejected` is called with the rejection reason /// - If the original promise is rejected, `on_rejected` is called with the rejection reason
/// of the original promise. /// of the original promise.
/// ///
/// The return value of the handlers can be used to mutate the state of the created promise. If /// The return value of the handlers can be used to mutate the state of the created promise. If
/// the callback: /// the callback:
@ -437,7 +437,7 @@ impl JsPromise {
/// - returns a fulfilled promise: the created promise gets fulfilled with that promise's value as its value. /// - returns a fulfilled promise: the created promise gets fulfilled with that promise's value as its value.
/// - returns a rejected promise: the created promise gets rejected with that promise's value as its value. /// - returns a rejected promise: the created promise gets rejected with that promise's value as its value.
/// - returns another pending promise: the created promise remains pending but becomes settled with that /// - returns another pending promise: the created promise remains pending but becomes settled with that
/// promise's value as its value immediately after that promise becomes settled. /// promise's value as its value immediately after that promise becomes settled.
/// ///
/// # Examples /// # Examples
/// ///
@ -559,8 +559,8 @@ impl JsPromise {
/// it has slightly different semantics than `then`: /// it has slightly different semantics than `then`:
/// - `on_finally` doesn't receive any argument, unlike `on_fulfilled` and `on_rejected`. /// - `on_finally` doesn't receive any argument, unlike `on_fulfilled` and `on_rejected`.
/// - `finally()` is transparent; a call like `Promise.resolve("first").finally(() => "second")` /// - `finally()` is transparent; a call like `Promise.resolve("first").finally(() => "second")`
/// returns a promise fulfilled with the value `"first"`, which would return `"second"` if `finally` /// returns a promise fulfilled with the value `"first"`, which would return `"second"` if `finally`
/// was a shortcut of `then`. /// was a shortcut of `then`.
/// ///
/// # Examples /// # Examples
/// ///

10
core/engine/src/object/jsobject.rs

@ -193,14 +193,8 @@ impl JsObject {
let erased = ptr.as_ref(); let erased = ptr.as_ref();
// Some sanity checks to ensure we're doing the correct cast. // Some sanity checks to ensure we're doing the correct cast.
assert_eq!( assert_eq!(size_of_val(erased), size_of::<GcBox<VTableObject<T>>>());
std::mem::size_of_val(erased), assert_eq!(align_of_val(erased), align_of::<GcBox<VTableObject<T>>>());
std::mem::size_of::<GcBox<VTableObject<T>>>()
);
assert_eq!(
std::mem::align_of_val(erased),
std::mem::align_of::<GcBox<VTableObject<T>>>()
);
} }
let ptr: NonNull<GcBox<VTableObject<T>>> = ptr.cast(); let ptr: NonNull<GcBox<VTableObject<T>>> = ptr.cast();

4
core/engine/src/object/mod.rs

@ -461,9 +461,9 @@ impl Object<dyn NativeObject> {
/// ///
/// There are two implementations: /// There are two implementations:
/// - From a single type `T` which implements `Into<FunctionBinding>` which sets the binding /// - From a single type `T` which implements `Into<FunctionBinding>` which sets the binding
/// name and the function name to the same value. /// name and the function name to the same value.
/// - From a tuple `(B: Into<PropertyKey>, N: Into<JsString>)`, where the `B` is the binding name /// - From a tuple `(B: Into<PropertyKey>, N: Into<JsString>)`, where the `B` is the binding name
/// and the `N` is the function name. /// and the `N` is the function name.
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct FunctionBinding { pub struct FunctionBinding {
pub(crate) binding: PropertyKey, pub(crate) binding: PropertyKey,

31
core/engine/src/object/property_map.rs

@ -7,7 +7,7 @@ use super::{
}, },
JsPrototype, ObjectStorage, PropertyDescriptor, PropertyKey, JsPrototype, ObjectStorage, PropertyDescriptor, PropertyKey,
}; };
use crate::{property::PropertyDescriptorBuilder, JsString, JsSymbol, JsValue}; use crate::{property::PropertyDescriptorBuilder, JsValue};
use boa_gc::{custom_trace, Finalize, Trace}; use boa_gc::{custom_trace, Finalize, Trace};
use indexmap::IndexMap; use indexmap::IndexMap;
use rustc_hash::{FxHashMap, FxHasher}; use rustc_hash::{FxHashMap, FxHasher};
@ -749,35 +749,6 @@ impl PropertyMap {
} }
} }
/// An iterator over the property entries of an `Object`
#[derive(Debug, Clone)]
pub struct Iter<'a> {
indexed_properties: IndexProperties<'a>,
string_properties: indexmap::map::Iter<'a, JsString, PropertyDescriptor>,
symbol_properties: indexmap::map::Iter<'a, JsSymbol, PropertyDescriptor>,
}
impl Iterator for Iter<'_> {
type Item = (PropertyKey, PropertyDescriptor);
fn next(&mut self) -> Option<Self::Item> {
if let Some((key, value)) = self.indexed_properties.next() {
Some((key.into(), value))
} else if let Some((key, value)) = self.string_properties.next() {
Some((key.clone().into(), value.clone()))
} else {
let (key, value) = self.symbol_properties.next()?;
Some((key.clone().into(), value.clone()))
}
}
}
impl ExactSizeIterator for Iter<'_> {
#[inline]
fn len(&self) -> usize {
self.indexed_properties.len() + self.string_properties.len() + self.symbol_properties.len()
}
}
/// An iterator over the indexed property entries of an `Object`. /// An iterator over the indexed property entries of an `Object`.
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub enum IndexProperties<'a> { pub enum IndexProperties<'a> {

6
core/engine/src/tagged.rs

@ -48,7 +48,7 @@ impl<T> Tagged<T> {
/// - `T` must have an alignment of at least 2. /// - `T` must have an alignment of at least 2.
/// - `tag` must fit inside `usize::BITS - 1` bits /// - `tag` must fit inside `usize::BITS - 1` bits
pub(crate) const fn from_tag(tag: usize) -> Self { pub(crate) const fn from_tag(tag: usize) -> Self {
debug_assert!(std::mem::align_of::<T>() >= 2); debug_assert!(align_of::<T>() >= 2);
let addr = (tag << 1) | 1; let addr = (tag << 1) | 1;
// SAFETY: `addr` is never zero, since we always set its LSB to 1 // SAFETY: `addr` is never zero, since we always set its LSB to 1
unsafe { Self(NonNull::new_unchecked(sptr::invalid_mut(addr))) } unsafe { Self(NonNull::new_unchecked(sptr::invalid_mut(addr))) }
@ -64,7 +64,7 @@ impl<T> Tagged<T> {
/// ///
/// - `T` must be non null. /// - `T` must be non null.
pub(crate) const unsafe fn from_ptr(ptr: *mut T) -> Self { pub(crate) const unsafe fn from_ptr(ptr: *mut T) -> Self {
debug_assert!(std::mem::align_of::<T>() >= 2); debug_assert!(align_of::<T>() >= 2);
// SAFETY: the caller must ensure the invariants hold. // SAFETY: the caller must ensure the invariants hold.
unsafe { Self(NonNull::new_unchecked(ptr)) } unsafe { Self(NonNull::new_unchecked(ptr)) }
} }
@ -75,7 +75,7 @@ impl<T> Tagged<T> {
/// ///
/// - `T` must have an alignment of at least 2. /// - `T` must have an alignment of at least 2.
pub(crate) const fn from_non_null(ptr: NonNull<T>) -> Self { pub(crate) const fn from_non_null(ptr: NonNull<T>) -> Self {
debug_assert!(std::mem::align_of::<T>() >= 2); debug_assert!(align_of::<T>() >= 2);
Self(ptr) Self(ptr)
} }

2
core/engine/src/vm/opcode/get/name.rs

@ -89,7 +89,7 @@ impl Operation for GetLocator {
/// ///
/// Operation: /// Operation:
/// - Find a binding on the environment chain and push its value to the stack, setting the /// - Find a binding on the environment chain and push its value to the stack, setting the
/// `current_binding` of the current frame. /// `current_binding` of the current frame.
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
pub(crate) struct GetNameAndLocator; pub(crate) struct GetNameAndLocator;

2
core/engine/src/vm/opcode/iteration/iterator.rs

@ -67,7 +67,7 @@ impl Operation for IteratorNextWithoutPop {
/// ///
/// Operation: /// Operation:
/// - Finishes the call to `Opcode::IteratorNext` within a `for await` loop by setting the current /// - Finishes the call to `Opcode::IteratorNext` within a `for await` loop by setting the current
/// result of the current iterator. /// result of the current iterator.
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
pub(crate) struct IteratorFinishAsyncNext; pub(crate) struct IteratorFinishAsyncNext;

30
core/engine/src/vm/opcode/mod.rs

@ -123,7 +123,7 @@ pub(crate) fn read<T>(bytes: &[u8], offset: usize) -> T
where where
T: Readable, T: Readable,
{ {
assert!(offset + std::mem::size_of::<T>() - 1 < bytes.len()); assert!(offset + size_of::<T>() - 1 < bytes.len());
// Safety: We checked that it is not an out-of-bounds read, // Safety: We checked that it is not an out-of-bounds read,
// so this is safe. // so this is safe.
@ -211,7 +211,7 @@ impl BytecodeConversion for GeneratorResumeKind {
} }
fn from_bytecode(bytes: &[u8], pc: &mut usize, _varying_kind: VaryingOperandKind) -> Self { fn from_bytecode(bytes: &[u8], pc: &mut usize, _varying_kind: VaryingOperandKind) -> Self {
let value = read::<u8>(bytes, *pc); let value = read::<u8>(bytes, *pc);
*pc += std::mem::size_of::<Self>(); *pc += size_of::<Self>();
JsValue::from(value).to_generator_resume_kind() JsValue::from(value).to_generator_resume_kind()
} }
} }
@ -222,7 +222,7 @@ impl BytecodeConversion for bool {
} }
fn from_bytecode(bytes: &[u8], pc: &mut usize, _varying_kind: VaryingOperandKind) -> Self { fn from_bytecode(bytes: &[u8], pc: &mut usize, _varying_kind: VaryingOperandKind) -> Self {
let value = read::<u8>(bytes, *pc); let value = read::<u8>(bytes, *pc);
*pc += std::mem::size_of::<Self>(); *pc += size_of::<Self>();
value != 0 value != 0
} }
} }
@ -233,7 +233,7 @@ impl BytecodeConversion for i8 {
} }
fn from_bytecode(bytes: &[u8], pc: &mut usize, _varying_kind: VaryingOperandKind) -> Self { fn from_bytecode(bytes: &[u8], pc: &mut usize, _varying_kind: VaryingOperandKind) -> Self {
let value = read::<Self>(bytes, *pc); let value = read::<Self>(bytes, *pc);
*pc += std::mem::size_of::<Self>(); *pc += size_of::<Self>();
value value
} }
} }
@ -244,7 +244,7 @@ impl BytecodeConversion for u8 {
} }
fn from_bytecode(bytes: &[u8], pc: &mut usize, _varying_kind: VaryingOperandKind) -> Self { fn from_bytecode(bytes: &[u8], pc: &mut usize, _varying_kind: VaryingOperandKind) -> Self {
let value = read::<Self>(bytes, *pc); let value = read::<Self>(bytes, *pc);
*pc += std::mem::size_of::<Self>(); *pc += size_of::<Self>();
value value
} }
} }
@ -255,7 +255,7 @@ impl BytecodeConversion for i16 {
} }
fn from_bytecode(bytes: &[u8], pc: &mut usize, _varying_kind: VaryingOperandKind) -> Self { fn from_bytecode(bytes: &[u8], pc: &mut usize, _varying_kind: VaryingOperandKind) -> Self {
let value = read::<Self>(bytes, *pc); let value = read::<Self>(bytes, *pc);
*pc += std::mem::size_of::<Self>(); *pc += size_of::<Self>();
value value
} }
} }
@ -266,7 +266,7 @@ impl BytecodeConversion for u16 {
} }
fn from_bytecode(bytes: &[u8], pc: &mut usize, _varying_kind: VaryingOperandKind) -> Self { fn from_bytecode(bytes: &[u8], pc: &mut usize, _varying_kind: VaryingOperandKind) -> Self {
let value = read::<Self>(bytes, *pc); let value = read::<Self>(bytes, *pc);
*pc += std::mem::size_of::<Self>(); *pc += size_of::<Self>();
value value
} }
} }
@ -277,7 +277,7 @@ impl BytecodeConversion for i32 {
} }
fn from_bytecode(bytes: &[u8], pc: &mut usize, _varying_kind: VaryingOperandKind) -> Self { fn from_bytecode(bytes: &[u8], pc: &mut usize, _varying_kind: VaryingOperandKind) -> Self {
let value = read::<Self>(bytes, *pc); let value = read::<Self>(bytes, *pc);
*pc += std::mem::size_of::<Self>(); *pc += size_of::<Self>();
value value
} }
} }
@ -288,7 +288,7 @@ impl BytecodeConversion for u32 {
} }
fn from_bytecode(bytes: &[u8], pc: &mut usize, _varying_kind: VaryingOperandKind) -> Self { fn from_bytecode(bytes: &[u8], pc: &mut usize, _varying_kind: VaryingOperandKind) -> Self {
let value = read::<Self>(bytes, *pc); let value = read::<Self>(bytes, *pc);
*pc += std::mem::size_of::<Self>(); *pc += size_of::<Self>();
value value
} }
} }
@ -299,7 +299,7 @@ impl BytecodeConversion for i64 {
} }
fn from_bytecode(bytes: &[u8], pc: &mut usize, _varying_kind: VaryingOperandKind) -> Self { fn from_bytecode(bytes: &[u8], pc: &mut usize, _varying_kind: VaryingOperandKind) -> Self {
let value = read::<Self>(bytes, *pc); let value = read::<Self>(bytes, *pc);
*pc += std::mem::size_of::<Self>(); *pc += size_of::<Self>();
value value
} }
} }
@ -310,7 +310,7 @@ impl BytecodeConversion for u64 {
} }
fn from_bytecode(bytes: &[u8], pc: &mut usize, _varying_kind: VaryingOperandKind) -> Self { fn from_bytecode(bytes: &[u8], pc: &mut usize, _varying_kind: VaryingOperandKind) -> Self {
let value = read::<Self>(bytes, *pc); let value = read::<Self>(bytes, *pc);
*pc += std::mem::size_of::<Self>(); *pc += size_of::<Self>();
value value
} }
} }
@ -321,7 +321,7 @@ impl BytecodeConversion for f32 {
} }
fn from_bytecode(bytes: &[u8], pc: &mut usize, _varying_kind: VaryingOperandKind) -> Self { fn from_bytecode(bytes: &[u8], pc: &mut usize, _varying_kind: VaryingOperandKind) -> Self {
let value = read::<Self>(bytes, *pc); let value = read::<Self>(bytes, *pc);
*pc += std::mem::size_of::<Self>(); *pc += size_of::<Self>();
value value
} }
} }
@ -332,7 +332,7 @@ impl BytecodeConversion for f64 {
} }
fn from_bytecode(bytes: &[u8], pc: &mut usize, _varying_kind: VaryingOperandKind) -> Self { fn from_bytecode(bytes: &[u8], pc: &mut usize, _varying_kind: VaryingOperandKind) -> Self {
let value = read::<Self>(bytes, *pc); let value = read::<Self>(bytes, *pc);
*pc += std::mem::size_of::<Self>(); *pc += size_of::<Self>();
value value
} }
} }
@ -346,11 +346,11 @@ impl BytecodeConversion for ThinVec<u32> {
} }
fn from_bytecode(bytes: &[u8], pc: &mut usize, _varying_kind: VaryingOperandKind) -> Self { fn from_bytecode(bytes: &[u8], pc: &mut usize, _varying_kind: VaryingOperandKind) -> Self {
let count = read::<u32>(bytes, *pc); let count = read::<u32>(bytes, *pc);
*pc += std::mem::size_of::<u32>(); *pc += size_of::<u32>();
let mut result = Self::with_capacity(count as usize); let mut result = Self::with_capacity(count as usize);
for _ in 0..count { for _ in 0..count {
let item = read::<u32>(bytes, *pc); let item = read::<u32>(bytes, *pc);
*pc += std::mem::size_of::<u32>(); *pc += size_of::<u32>();
result.push(item); result.push(item);
} }
result result

2
core/gc/src/internals/vtable.rs

@ -48,7 +48,7 @@ pub(crate) const fn vtable_of<T: Trace + 'static>() -> &'static VTable {
trace_non_roots_fn: T::trace_non_roots_fn, trace_non_roots_fn: T::trace_non_roots_fn,
run_finalizer_fn: T::run_finalizer_fn, run_finalizer_fn: T::run_finalizer_fn,
drop_fn: T::drop_fn, drop_fn: T::drop_fn,
size: std::mem::size_of::<GcBox<T>>(), size: size_of::<GcBox<T>>(),
}; };
} }

10
core/gc/src/lib.rs

@ -131,7 +131,7 @@ impl Allocator {
/// Allocate a new garbage collected value to the Garbage Collector's heap. /// Allocate a new garbage collected value to the Garbage Collector's heap.
fn alloc_gc<T: Trace>(value: GcBox<T>) -> NonNull<GcBox<T>> { fn alloc_gc<T: Trace>(value: GcBox<T>) -> NonNull<GcBox<T>> {
let _timer = Profiler::global().start_event("New GcBox", "BoaAlloc"); let _timer = Profiler::global().start_event("New GcBox", "BoaAlloc");
let element_size = mem::size_of_val::<GcBox<T>>(&value); let element_size = size_of_val::<GcBox<T>>(&value);
BOA_GC.with(|st| { BOA_GC.with(|st| {
let mut gc = st.borrow_mut(); let mut gc = st.borrow_mut();
@ -151,7 +151,7 @@ impl Allocator {
value: EphemeronBox<K, V>, value: EphemeronBox<K, V>,
) -> NonNull<EphemeronBox<K, V>> { ) -> NonNull<EphemeronBox<K, V>> {
let _timer = Profiler::global().start_event("New EphemeronBox", "BoaAlloc"); let _timer = Profiler::global().start_event("New EphemeronBox", "BoaAlloc");
let element_size = mem::size_of_val::<EphemeronBox<K, V>>(&value); let element_size = size_of_val::<EphemeronBox<K, V>>(&value);
BOA_GC.with(|st| { BOA_GC.with(|st| {
let mut gc = st.borrow_mut(); let mut gc = st.borrow_mut();
@ -478,9 +478,9 @@ impl Collector {
/// # Safety /// # Safety
/// ///
/// - Providing an invalid pointer in the `heap_start` or in any of the headers of each /// - Providing an invalid pointer in the `heap_start` or in any of the headers of each
/// node will result in Undefined Behaviour. /// node will result in Undefined Behaviour.
/// - Providing a list of pointers that weren't allocated by `Box::into_raw(Box::new(..))` /// - Providing a list of pointers that weren't allocated by `Box::into_raw(Box::new(..))`
/// will result in Undefined Behaviour. /// will result in Undefined Behaviour.
unsafe fn sweep( unsafe fn sweep(
strong: &mut Vec<GcErasedPointer>, strong: &mut Vec<GcErasedPointer>,
weak: &mut Vec<EphemeronPointer>, weak: &mut Vec<EphemeronPointer>,
@ -526,7 +526,7 @@ impl Collector {
// SAFETY: The algorithm ensures only unmarked/unreachable pointers are dropped. // SAFETY: The algorithm ensures only unmarked/unreachable pointers are dropped.
// The caller must ensure all pointers were allocated by `Box::into_raw(Box::new(..))`. // The caller must ensure all pointers were allocated by `Box::into_raw(Box::new(..))`.
let unmarked_eph = unsafe { Box::from_raw(eph.as_ptr()) }; let unmarked_eph = unsafe { Box::from_raw(eph.as_ptr()) };
let unallocated_bytes = mem::size_of_val(&*unmarked_eph); let unallocated_bytes = size_of_val(&*unmarked_eph);
*total_allocated -= unallocated_bytes; *total_allocated -= unallocated_bytes;
false false

2
core/gc/src/pointers/ephemeron.rs

@ -15,7 +15,7 @@ use super::addr_eq;
/// You can read more about ephemerons on: /// You can read more about ephemerons on:
/// - Racket's page about [**ephemerons**][eph], which gives a brief overview. /// - Racket's page about [**ephemerons**][eph], which gives a brief overview.
/// - Barry Hayes' paper ["_Ephemerons_: a new finalization mechanism"][acm] which explains the topic /// - Barry Hayes' paper ["_Ephemerons_: a new finalization mechanism"][acm] which explains the topic
/// in full detail. /// in full detail.
/// ///
/// ///
/// [eph]: https://docs.racket-lang.org/reference/ephemerons.html /// [eph]: https://docs.racket-lang.org/reference/ephemerons.html

2
core/gc/src/test/allocation.rs

@ -43,7 +43,7 @@ fn gc_recursion() {
next: Option<Gc<S>>, next: Option<Gc<S>>,
} }
const SIZE: usize = std::mem::size_of::<GcBox<S>>(); const SIZE: usize = size_of::<GcBox<S>>();
const COUNT: usize = 1_000_000; const COUNT: usize = 1_000_000;
let mut root = Gc::new(S { i: 0, next: None }); let mut root = Gc::new(S { i: 0, next: None });

4
core/gc/src/test/weak.rs

@ -154,7 +154,7 @@ fn eph_self_referential() {
inner: GcRefCell::new(None), inner: GcRefCell::new(None),
}), }),
}; };
let root_size = std::mem::size_of::<GcBox<InnerCell>>(); let root_size = size_of::<GcBox<InnerCell>>();
Harness::assert_exact_bytes_allocated(root_size); Harness::assert_exact_bytes_allocated(root_size);
@ -183,7 +183,7 @@ fn eph_self_referential_chain() {
} }
run_test(|| { run_test(|| {
let root = Gc::new(GcRefCell::new(None)); let root = Gc::new(GcRefCell::new(None));
let root_size = std::mem::size_of::<GcBox<GcRefCell<Option<Ephemeron<u8, TestCell>>>>>(); let root_size = size_of::<GcBox<GcRefCell<Option<Ephemeron<u8, TestCell>>>>>();
Harness::assert_exact_bytes_allocated(root_size); Harness::assert_exact_bytes_allocated(root_size);

4
core/gc/src/trace.rs

@ -54,10 +54,10 @@ pub trait Finalize {
/// # Safety /// # Safety
/// ///
/// - An incorrect implementation of the trait can result in heap overflows, data corruption, /// - An incorrect implementation of the trait can result in heap overflows, data corruption,
/// use-after-free, or Undefined Behaviour in general. /// use-after-free, or Undefined Behaviour in general.
/// ///
/// - Calling any of the functions marked as `unsafe` outside of the context of the garbage collector /// - Calling any of the functions marked as `unsafe` outside of the context of the garbage collector
/// can result in Undefined Behaviour. /// can result in Undefined Behaviour.
pub unsafe trait Trace: Finalize { pub unsafe trait Trace: Finalize {
/// Marks all contained `Gc`s. /// Marks all contained `Gc`s.
/// ///

4
core/interner/src/interned_str.rs

@ -9,8 +9,8 @@ use core::{hash::Hash, ptr::NonNull};
/// - Use without ensuring the referenced memory is still allocated. /// - Use without ensuring the referenced memory is still allocated.
/// - Construction of an [`InternedStr`] from an invalid [`NonNull<Char>`] pointer. /// - Construction of an [`InternedStr`] from an invalid [`NonNull<Char>`] pointer.
/// - Construction of an [`InternedStr`] from a [`NonNull<Char>`] pointer /// - Construction of an [`InternedStr`] from a [`NonNull<Char>`] pointer
/// without checking if the pointed memory of the [`NonNull<Char>`] outlives /// without checking if the pointed memory of the [`NonNull<Char>`] outlives
/// the [`InternedStr`]. /// the [`InternedStr`].
/// ///
/// In general, this should not be used outside of an [`Interner`][`super::Interner`]. /// In general, this should not be used outside of an [`Interner`][`super::Interner`].
#[derive(Debug)] #[derive(Debug)]

1
core/parser/src/lexer/template.rs

@ -9,7 +9,6 @@ use boa_interner::{Interner, Sym};
use boa_profiler::Profiler; use boa_profiler::Profiler;
use std::io::{self, ErrorKind}; use std::io::{self, ErrorKind};
#[cfg_attr(feature = "deser", derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug, Clone, Copy, PartialEq, Eq)] #[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct TemplateString { pub struct TemplateString {
/// The raw template string. /// The raw template string.

5
core/parser/src/lexer/token.rs

@ -17,7 +17,6 @@ use num_bigint::BigInt;
/// - [ECMAScript reference][spec] /// - [ECMAScript reference][spec]
/// ///
/// [spec]: https://tc39.es/ecma262/#sec-tokens /// [spec]: https://tc39.es/ecma262/#sec-tokens
#[cfg_attr(feature = "deser", derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
pub struct Token { pub struct Token {
/// The token kind, which contains the actual data of the token. /// The token kind, which contains the actual data of the token.
@ -56,7 +55,6 @@ impl Token {
} }
/// Represents the type different types of numeric literals. /// Represents the type different types of numeric literals.
#[cfg_attr(feature = "deser", derive(serde::Serialize, serde::Deserialize))]
#[derive(Clone, PartialEq, Debug)] #[derive(Clone, PartialEq, Debug)]
pub enum Numeric { pub enum Numeric {
/// A floating point number. /// A floating point number.
@ -91,7 +89,6 @@ impl From<BigInt> for Numeric {
} }
/// Represents the type of Token and the data it has inside. /// Represents the type of Token and the data it has inside.
#[cfg_attr(feature = "deser", derive(serde::Serialize, serde::Deserialize))]
#[derive(Clone, PartialEq, Debug)] #[derive(Clone, PartialEq, Debug)]
pub enum TokenKind { pub enum TokenKind {
/// A boolean literal, which is either `true` or `false`. /// A boolean literal, which is either `true` or `false`.
@ -290,7 +287,6 @@ impl TokenKind {
bitflags! { bitflags! {
/// Indicates the set of escape sequences a string contains. /// Indicates the set of escape sequences a string contains.
#[cfg_attr(feature = "deser", derive(serde::Serialize, serde::Deserialize))]
#[derive(Clone, Copy, Debug, PartialEq, Eq)] #[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct EscapeSequence: u8 { pub struct EscapeSequence: u8 {
/// A legacy escape sequence starting with `0` - `7`. /// A legacy escape sequence starting with `0` - `7`.
@ -322,6 +318,5 @@ bitflags! {
} }
/// Indicates if an identifier contains an escape sequence. /// Indicates if an identifier contains an escape sequence.
#[cfg_attr(feature = "deser", derive(serde::Serialize, serde::Deserialize))]
#[derive(Clone, Copy, Debug, PartialEq, Eq)] #[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct ContainsEscapeSequence(pub bool); pub struct ContainsEscapeSequence(pub bool);

2
core/parser/src/parser/cursor/buffered_lexer/mod.rs

@ -213,7 +213,7 @@ where
/// i.e. if there are tokens `A`, `B`, `C`, `D`, `E` and `peek(0, false)` returns `A` then: /// i.e. if there are tokens `A`, `B`, `C`, `D`, `E` and `peek(0, false)` returns `A` then:
/// - `peek(1, false) == peek(1, true) == B`. /// - `peek(1, false) == peek(1, true) == B`.
/// - `peek(2, false)` will return `C`. /// - `peek(2, false)` will return `C`.
/// where `A`, `B`, `C`, `D` and `E` are tokens but not line terminators. /// where `A`, `B`, `C`, `D` and `E` are tokens but not line terminators.
/// ///
/// If `skip_line_terminators` is `true` then line terminators will be discarded. /// If `skip_line_terminators` is `true` then line terminators will be discarded.
/// i.e. If there are tokens `A`, `\n`, `B` and `peek(0, false)` is `A` then the following /// i.e. If there are tokens `A`, `\n`, `B` and `peek(0, false)` is `A` then the following

2
core/string/src/lib.rs

@ -183,7 +183,7 @@ impl RawJsString {
} }
} }
const DATA_OFFSET: usize = std::mem::size_of::<RawJsString>(); const DATA_OFFSET: usize = size_of::<RawJsString>();
/// A Latin1 or UTF-16–encoded, reference counted, immutable string. /// A Latin1 or UTF-16–encoded, reference counted, immutable string.
/// ///

6
core/string/src/tagged.rs

@ -47,7 +47,7 @@ impl<T> Tagged<T> {
/// - `T` must have an alignment of at least 2. /// - `T` must have an alignment of at least 2.
/// - `tag` must fit inside `usize::BITS - 1` bits /// - `tag` must fit inside `usize::BITS - 1` bits
pub(crate) const fn from_tag(tag: usize) -> Self { pub(crate) const fn from_tag(tag: usize) -> Self {
debug_assert!(std::mem::align_of::<T>() >= 2); debug_assert!(align_of::<T>() >= 2);
let addr = (tag << 1) | 1; let addr = (tag << 1) | 1;
// SAFETY: `addr` is never zero, since we always set its LSB to 1 // SAFETY: `addr` is never zero, since we always set its LSB to 1
unsafe { Self(NonNull::new_unchecked(sptr::invalid_mut(addr))) } unsafe { Self(NonNull::new_unchecked(sptr::invalid_mut(addr))) }
@ -63,7 +63,7 @@ impl<T> Tagged<T> {
/// ///
/// - `T` must be non null. /// - `T` must be non null.
pub(crate) const unsafe fn from_ptr(ptr: *mut T) -> Self { pub(crate) const unsafe fn from_ptr(ptr: *mut T) -> Self {
debug_assert!(std::mem::align_of::<T>() >= 2); debug_assert!(align_of::<T>() >= 2);
// SAFETY: the caller must ensure the invariants hold. // SAFETY: the caller must ensure the invariants hold.
unsafe { Self(NonNull::new_unchecked(ptr)) } unsafe { Self(NonNull::new_unchecked(ptr)) }
} }
@ -74,7 +74,7 @@ impl<T> Tagged<T> {
/// ///
/// - `T` must have an alignment of at least 2. /// - `T` must have an alignment of at least 2.
pub(crate) const fn from_non_null(ptr: NonNull<T>) -> Self { pub(crate) const fn from_non_null(ptr: NonNull<T>) -> Self {
debug_assert!(std::mem::align_of::<T>() >= 2); debug_assert!(align_of::<T>() >= 2);
Self(ptr) Self(ptr)
} }

19
examples/src/bin/commuter_visitor.rs

@ -46,18 +46,13 @@ impl<'ast> VisitorMut<'ast> for CommutorVisitor {
type BreakTy = Infallible; type BreakTy = Infallible;
fn visit_binary_mut(&mut self, node: &'ast mut Binary) -> ControlFlow<Self::BreakTy> { fn visit_binary_mut(&mut self, node: &'ast mut Binary) -> ControlFlow<Self::BreakTy> {
if let BinaryOp::Arithmetic(op) = node.op() { if let BinaryOp::Arithmetic(ArithmeticOp::Add | ArithmeticOp::Mul) = node.op() {
match op { // set up the exchanger and swap lhs and rhs
ArithmeticOp::Add | ArithmeticOp::Mul => { let mut exchanger = OpExchanger::default();
// set up the exchanger and swap lhs and rhs assert!(matches!(
let mut exchanger = OpExchanger::default(); exchanger.visit_binary_mut(node),
assert!(matches!( ControlFlow::Break(())
exchanger.visit_binary_mut(node), ));
ControlFlow::Break(())
));
}
_ => {}
}
} }
// traverse further in; there may nested binary operations // traverse further in; there may nested binary operations
node.visit_with_mut(self) node.visit_with_mut(self)

Loading…
Cancel
Save