diff --git a/nova_vm/src/builtins/ordinary.rs b/nova_vm/src/builtins/ordinary.rs index 2a6c611f6..2f88b2822 100644 --- a/nova_vm/src/builtins/ordinary.rs +++ b/nova_vm/src/builtins/ordinary.rs @@ -3,8 +3,6 @@ use crate::{ types::{InternalMethods, Object, PropertyDescriptor, PropertyKey, Value}, }; -use super::ArgumentsList; - /// 10.1 Ordinary Object Internal Methods and Internal Slots /// https://tc39.es/ecma262/#sec-ordinary-object-internal-methods-and-internal-slots pub static METHODS: InternalMethods = InternalMethods { @@ -37,7 +35,7 @@ fn get_prototype_of(agent: &mut Agent, object: Object) -> Option { pub fn ordinary_get_prototype_of(agent: &mut Agent, object: Object) -> Option { // 1. Return O.[[Prototype]]. // TODO: This is wrong. - Some(Object::new(object.prototype(agent).unwrap())) + Some(Object::try_from(object.prototype(agent).unwrap()).unwrap()) } /// 10.1.2 [[SetPrototypeOf]] ( V ) @@ -105,7 +103,8 @@ pub fn ordinary_set_prototype_of( // ii. Else, set p to p.[[Prototype]]. // TODO: This is wrong - parent_prototype_outer = Some(Object::new(parent_prototype.prototype(agent).unwrap())); + parent_prototype_outer = + Some(Object::try_from(parent_prototype.prototype(agent).unwrap()).unwrap()); } // 8. Set O.[[Prototype]] to V. @@ -686,12 +685,8 @@ pub fn ordinary_set_with_own_descriptor( }; // iv. Return ? Receiver.[[DefineOwnProperty]](P, valueDesc). - return Ok((receiver.internal_methods(agent).define_own_property)( - agent, - receiver, - property_key, - value_descriptor, - )); + let define_own_property = receiver.internal_methods(agent).define_own_property; + return define_own_property(agent, receiver, property_key, value_descriptor); } // e. Else, else { diff --git a/nova_vm/src/execution/realm/intrinsics.rs b/nova_vm/src/execution/realm/intrinsics.rs index a68567984..a259dc240 100644 --- a/nova_vm/src/execution/realm/intrinsics.rs +++ b/nova_vm/src/execution/realm/intrinsics.rs @@ -1,6 +1,9 @@ use crate::{ - heap::BuiltinObjectIndexes, - types::{Object, Value}, + heap::{ + indexes::{FunctionIndex, ObjectIndex}, + BuiltinObjectIndexes, + }, + types::Object, }; // TODO: We should probably consider lazily loading intrinsics. This would @@ -12,42 +15,58 @@ pub struct Intrinsics; impl Intrinsics { /// %Array% pub const fn array() -> Object { - Object::Function(BuiltinObjectIndexes::ArrayConstructorIndex.into()) + Object::Function(FunctionIndex::from_u32_index( + BuiltinObjectIndexes::ArrayConstructorIndex as u32, + )) } /// %Array.prototype% pub const fn array_prototype() -> Object { - Object::Object(BuiltinObjectIndexes::ArrayPrototypeIndex.into()) + Object::Object(ObjectIndex::from_u32_index( + BuiltinObjectIndexes::ArrayPrototypeIndex as u32, + )) } /// %BigInt% pub const fn big_int() -> Object { - Object::Function(BuiltinObjectIndexes::BigintConstructorIndex.into()) + Object::Function(FunctionIndex::from_u32_index( + BuiltinObjectIndexes::BigintConstructorIndex as u32, + )) } /// %BigInt.prototype% pub const fn big_int_prototype() -> Object { - Object::Object(BuiltinObjectIndexes::BigintPrototypeIndex.into()) + Object::Object(ObjectIndex::from_u32_index( + BuiltinObjectIndexes::BigintPrototypeIndex as u32, + )) } /// %Boolean% pub const fn boolean() -> Object { - Object::Function(BuiltinObjectIndexes::BooleanConstructorIndex.into()) + Object::Function(FunctionIndex::from_u32_index( + BuiltinObjectIndexes::BooleanConstructorIndex as u32, + )) } /// %Boolean.prototype% pub const fn boolean_prototype() -> Object { - Object::Object(BuiltinObjectIndexes::BooleanPrototypeIndex.into()) + Object::Object(ObjectIndex::from_u32_index( + BuiltinObjectIndexes::BooleanPrototypeIndex as u32, + )) } /// %Error% pub const fn error() -> Object { - Object::Function(BuiltinObjectIndexes::ErrorConstructorIndex.into()) + Object::Function(FunctionIndex::from_u32_index( + BuiltinObjectIndexes::ErrorConstructorIndex as u32, + )) } /// %Error.prototype% pub const fn error_prototype() -> Object { - Object::Object(BuiltinObjectIndexes::ErrorPrototypeIndex.into()) + Object::Object(ObjectIndex::from_u32_index( + BuiltinObjectIndexes::ErrorPrototypeIndex as u32, + )) } /// %eval% @@ -57,7 +76,9 @@ impl Intrinsics { /// %EvalError% pub const fn eval_error() -> Object { - Object::Function(BuiltinObjectIndexes::ArrayConstructorIndex.into()) + Object::Function(FunctionIndex::from_u32_index( + BuiltinObjectIndexes::ArrayConstructorIndex as u32, + )) } /// %EvalError.prototype% @@ -67,7 +88,9 @@ impl Intrinsics { /// %Function% pub const fn function() -> Object { - Object::Function(BuiltinObjectIndexes::FunctionConstructorIndex.into()) + Object::Function(FunctionIndex::from_u32_index( + BuiltinObjectIndexes::FunctionConstructorIndex as u32, + )) } /// %Function.prototype% @@ -75,7 +98,9 @@ impl Intrinsics { // Note: This is not spec-compliant. Function prototype should // be a function that always returns undefined no matter how // it is called. That's stupid so we do not have that. - Object::Object(BuiltinObjectIndexes::FunctionPrototypeIndex.into()) + Object::Object(ObjectIndex::from_u32_index( + BuiltinObjectIndexes::FunctionPrototypeIndex as u32, + )) } /// %isFinite% @@ -90,27 +115,37 @@ impl Intrinsics { /// %Math% pub const fn math() -> Object { - Object::Object(BuiltinObjectIndexes::MathObjectIndex.into()) + Object::Object(ObjectIndex::from_u32_index( + BuiltinObjectIndexes::MathObjectIndex as u32, + )) } /// %Number% pub const fn number() -> Object { - Object::Function(BuiltinObjectIndexes::NumberConstructorIndex.into()) + Object::Function(FunctionIndex::from_u32_index( + BuiltinObjectIndexes::NumberConstructorIndex as u32, + )) } /// %Number.prototype% pub const fn number_prototype() -> Object { - Object::Object(BuiltinObjectIndexes::NumberPrototypeIndex.into()) + Object::Object(ObjectIndex::from_u32_index( + BuiltinObjectIndexes::NumberPrototypeIndex as u32, + )) } /// %Object% pub const fn object() -> Object { - Object::Function(BuiltinObjectIndexes::ObjectConstructorIndex.into()) + Object::Function(FunctionIndex::from_u32_index( + BuiltinObjectIndexes::ObjectConstructorIndex as u32, + )) } /// %Object.prototype% pub const fn object_prototype() -> Object { - Object::Object(BuiltinObjectIndexes::ObjectPrototypeIndex.into()) + Object::Object(ObjectIndex::from_u32_index( + BuiltinObjectIndexes::ObjectPrototypeIndex as u32, + )) } /// %Object.prototype.toString% @@ -145,22 +180,30 @@ impl Intrinsics { /// %String% pub const fn string() -> Object { - Object::Function(BuiltinObjectIndexes::StringConstructorIndex.into()) + Object::Function(FunctionIndex::from_u32_index( + BuiltinObjectIndexes::StringConstructorIndex as u32, + )) } /// %String.prototype% pub const fn string_prototype() -> Object { - Object::Object(BuiltinObjectIndexes::StringPrototypeIndex.into()) + Object::Object(ObjectIndex::from_u32_index( + BuiltinObjectIndexes::StringPrototypeIndex as u32, + )) } /// %Symbol% pub const fn symbol() -> Object { - Object::Function(BuiltinObjectIndexes::SymbolConstructorIndex.into()) + Object::Function(FunctionIndex::from_u32_index( + BuiltinObjectIndexes::SymbolConstructorIndex as u32, + )) } /// %Symbol.prototype% pub const fn symbol_prototype() -> Object { - Object::Object(BuiltinObjectIndexes::SymbolPrototypeIndex.into()) + Object::Object(ObjectIndex::from_u32_index( + BuiltinObjectIndexes::SymbolPrototypeIndex as u32, + )) } /// %SyntaxError% diff --git a/nova_vm/src/heap.rs b/nova_vm/src/heap.rs index db41e3821..6d050b550 100644 --- a/nova_vm/src/heap.rs +++ b/nova_vm/src/heap.rs @@ -8,7 +8,7 @@ mod function; mod heap_bits; mod heap_constants; mod heap_gc; -pub(crate) mod indexes; +pub mod indexes; mod math; mod number; mod object; @@ -16,7 +16,7 @@ mod regexp; mod string; mod symbol; -pub(crate) use self::heap_constants::BuiltinObjectIndexes; +pub use self::heap_constants::BuiltinObjectIndexes; use self::{ array::{initialize_array_heap, ArrayHeapData}, @@ -51,18 +51,18 @@ pub struct Heap { /// ElementsArrays is where all element arrays live; /// Element arrays are static arrays of Values plus /// a HashMap of possible property descriptors. - pub(crate) elements: ElementArrays, - pub(crate) arrays: Vec>, - pub(crate) bigints: Vec>, - pub(crate) errors: Vec>, - pub(crate) functions: Vec>, - pub(crate) dates: Vec>, - pub(crate) globals: Vec, - pub(crate) numbers: Vec>, - pub(crate) objects: Vec>, - pub(crate) regexps: Vec>, - pub(crate) strings: Vec>, - pub(crate) symbols: Vec>, + pub elements: ElementArrays, + pub arrays: Vec>, + pub bigints: Vec>, + pub errors: Vec>, + pub functions: Vec>, + pub dates: Vec>, + pub globals: Vec, + pub numbers: Vec>, + pub objects: Vec>, + pub regexps: Vec>, + pub strings: Vec>, + pub symbols: Vec>, } pub trait CreateHeapData { @@ -214,7 +214,7 @@ impl Heap { heap } - pub(crate) fn alloc_string(&mut self, message: &str) -> StringIndex { + pub fn alloc_string(&mut self, message: &str) -> StringIndex { let found = self.strings.iter().position(|opt| { opt.as_ref() .map_or(false, |data| data.data == Wtf8::from_str(message)) @@ -233,12 +233,12 @@ impl Heap { } } - pub(crate) fn alloc_number(&mut self, number: f64) -> NumberIndex { + pub fn alloc_number(&mut self, number: f64) -> NumberIndex { self.numbers.push(Some(NumberHeapData::new(number))); NumberIndex::last(&self.numbers) } - pub(crate) fn create_function( + pub fn create_function( &mut self, name: Value, length: u8, @@ -278,7 +278,7 @@ impl Heap { index } - pub(crate) fn create_object(&mut self, entries: Vec) -> ObjectIndex { + pub fn create_object(&mut self, entries: Vec) -> ObjectIndex { let (keys, values) = self.elements.create_object_entries(entries); let object_data = ObjectHeapData { extensible: true, @@ -290,7 +290,7 @@ impl Heap { ObjectIndex::last(&self.objects) } - pub(crate) fn create_null_object(&mut self, entries: Vec) -> ObjectIndex { + pub fn create_null_object(&mut self, entries: Vec) -> ObjectIndex { let (keys, values) = self.elements.create_object_entries(entries); let object_data = ObjectHeapData { extensible: true, @@ -302,7 +302,7 @@ impl Heap { ObjectIndex::last(&self.objects) } - pub(crate) fn create_object_with_prototype(&mut self, prototype: Value) -> ObjectIndex { + pub fn create_object_with_prototype(&mut self, prototype: Value) -> ObjectIndex { let (keys, values) = self.elements.create_object_entries(vec![]); let object_data = ObjectHeapData { extensible: true, @@ -314,7 +314,7 @@ impl Heap { ObjectIndex::last(&self.objects) } - pub(crate) fn insert_builtin_object( + pub fn insert_builtin_object( &mut self, index: BuiltinObjectIndexes, extensible: bool, diff --git a/nova_vm/src/heap/array.rs b/nova_vm/src/heap/array.rs index a23c38af5..893690af1 100644 --- a/nova_vm/src/heap/array.rs +++ b/nova_vm/src/heap/array.rs @@ -16,7 +16,7 @@ use super::{ }; #[derive(Debug, Clone, Copy)] -pub(crate) struct ArrayHeapData { +pub struct ArrayHeapData { pub object_index: Option, // TODO: Use SmallVec<[Value; 4]> pub elements: ElementsVector, diff --git a/nova_vm/src/heap/bigint.rs b/nova_vm/src/heap/bigint.rs index 8348f7676..c3532ca22 100644 --- a/nova_vm/src/heap/bigint.rs +++ b/nova_vm/src/heap/bigint.rs @@ -10,12 +10,12 @@ use crate::{ use num_bigint_dig::BigInt; #[derive(Debug, Clone)] -pub(crate) struct BigIntHeapData { +pub struct BigIntHeapData { pub(super) data: BigInt, } impl BigIntHeapData { - pub(crate) fn try_into_f64(&self) -> Option { + pub fn try_into_f64(&self) -> Option { None } } diff --git a/nova_vm/src/heap/date.rs b/nova_vm/src/heap/date.rs index b9143c3d4..d8e16d4d8 100644 --- a/nova_vm/src/heap/date.rs +++ b/nova_vm/src/heap/date.rs @@ -17,7 +17,7 @@ use super::{ }; #[derive(Debug, Clone, Copy)] -pub(crate) struct DateHeapData { +pub struct DateHeapData { pub(super) object_index: ObjectIndex, pub(super) _date: SystemTime, } diff --git a/nova_vm/src/heap/element_array.rs b/nova_vm/src/heap/element_array.rs index db0a3ad48..9dea667a1 100644 --- a/nova_vm/src/heap/element_array.rs +++ b/nova_vm/src/heap/element_array.rs @@ -2,12 +2,12 @@ use super::{ indexes::{ElementIndex, FunctionIndex}, object::{ObjectEntry, PropertyDescriptor, PropertyKey}, }; -use crate::types::Value; +use crate::{types::Value, Heap}; use core::panic; use std::{collections::HashMap, mem::MaybeUninit, num::NonZeroU16, vec}; #[derive(Debug, Clone, Copy)] -pub(crate) enum ElementArrayKey { +pub enum ElementArrayKey { /// up to 16 elements E4, /// up to 64 elements @@ -51,10 +51,10 @@ impl From for ElementArrayKey { } #[derive(Debug, Clone, Copy)] -pub(crate) struct ElementsVector { - pub(crate) elements_index: ElementIndex, - pub(crate) cap: ElementArrayKey, - pub(crate) len: u32, +pub struct ElementsVector { + pub elements_index: ElementIndex, + pub cap: ElementArrayKey, + pub len: u32, } #[derive(Debug, Clone, Copy)] @@ -386,9 +386,9 @@ impl ElementDescriptor { /// Element arrays of up to 16 elements #[derive(Debug)] -pub(crate) struct ElementArray2Pow4 { - pub(crate) values: Vec; usize::pow(2, 4)]>>, - pub(crate) descriptors: HashMap>, +pub struct ElementArray2Pow4 { + pub values: Vec; usize::pow(2, 4)]>>, + pub descriptors: HashMap>, } impl Default for ElementArray2Pow4 { @@ -411,9 +411,9 @@ impl ElementArray2Pow4 { /// Element arrays of up to 64 elements #[derive(Debug)] -pub(crate) struct ElementArray2Pow6 { - pub(crate) values: Vec; usize::pow(2, 6)]>>, - pub(crate) descriptors: HashMap>, +pub struct ElementArray2Pow6 { + pub values: Vec; usize::pow(2, 6)]>>, + pub descriptors: HashMap>, } impl Default for ElementArray2Pow6 { @@ -436,9 +436,9 @@ impl ElementArray2Pow6 { /// Element arrays of up to 256 elements #[derive(Debug)] -pub(crate) struct ElementArray2Pow8 { - pub(crate) values: Vec; usize::pow(2, 8)]>>, - pub(crate) descriptors: HashMap>, +pub struct ElementArray2Pow8 { + pub values: Vec; usize::pow(2, 8)]>>, + pub descriptors: HashMap>, } impl Default for ElementArray2Pow8 { @@ -461,9 +461,9 @@ impl ElementArray2Pow8 { /// Element arrays of up to 1024 elements #[derive(Debug)] -pub(crate) struct ElementArray2Pow10 { - pub(crate) values: Vec; usize::pow(2, 10)]>>, - pub(crate) descriptors: HashMap>, +pub struct ElementArray2Pow10 { + pub values: Vec; usize::pow(2, 10)]>>, + pub descriptors: HashMap>, } impl Default for ElementArray2Pow10 { @@ -486,9 +486,9 @@ impl ElementArray2Pow10 { /// Element arrays of up to 4096 elements #[derive(Debug)] -pub(crate) struct ElementArray2Pow12 { - pub(crate) values: Vec; usize::pow(2, 12)]>>, - pub(crate) descriptors: HashMap>, +pub struct ElementArray2Pow12 { + pub values: Vec; usize::pow(2, 12)]>>, + pub descriptors: HashMap>, } impl Default for ElementArray2Pow12 { @@ -511,9 +511,9 @@ impl ElementArray2Pow12 { /// Element arrays of up to 65536 elements #[derive(Debug)] -pub(crate) struct ElementArray2Pow16 { - pub(crate) values: Vec; usize::pow(2, 16)]>>, - pub(crate) descriptors: HashMap>, +pub struct ElementArray2Pow16 { + pub values: Vec; usize::pow(2, 16)]>>, + pub descriptors: HashMap>, } impl Default for ElementArray2Pow16 { @@ -536,9 +536,9 @@ impl ElementArray2Pow16 { /// Element arrays of up to 16777216 elements #[derive(Debug)] -pub(crate) struct ElementArray2Pow24 { - pub(crate) values: Vec; usize::pow(2, 24)]>>, - pub(crate) descriptors: HashMap>, +pub struct ElementArray2Pow24 { + pub values: Vec; usize::pow(2, 24)]>>, + pub descriptors: HashMap>, } impl Default for ElementArray2Pow24 { @@ -561,9 +561,9 @@ impl ElementArray2Pow24 { /// Element arrays of up to 4294967296 elements #[derive(Debug)] -pub(crate) struct ElementArray2Pow32 { - pub(crate) values: Vec; usize::pow(2, 32)]>>, - pub(crate) descriptors: HashMap>, +pub struct ElementArray2Pow32 { + pub values: Vec; usize::pow(2, 32)]>>, + pub descriptors: HashMap>, } impl Default for ElementArray2Pow32 { @@ -585,23 +585,23 @@ impl ElementArray2Pow32 { } #[derive(Debug)] -pub(crate) struct ElementArrays { +pub struct ElementArrays { /// up to 16 elements - pub(crate) e2pow4: ElementArray2Pow4, + pub e2pow4: ElementArray2Pow4, /// up to 64 elements - pub(crate) e2pow6: ElementArray2Pow6, + pub e2pow6: ElementArray2Pow6, /// up to 256 elements - pub(crate) e2pow8: ElementArray2Pow8, + pub e2pow8: ElementArray2Pow8, /// up to 1024 elements - pub(crate) e2pow10: ElementArray2Pow10, + pub e2pow10: ElementArray2Pow10, /// up to 4096 elements - pub(crate) e2pow12: ElementArray2Pow12, + pub e2pow12: ElementArray2Pow12, /// up to 65536 elements - pub(crate) e2pow16: ElementArray2Pow16, + pub e2pow16: ElementArray2Pow16, /// up to 16777216 elements - pub(crate) e2pow24: ElementArray2Pow24, + pub e2pow24: ElementArray2Pow24, /// up to 4294967296 elements - pub(crate) e2pow32: ElementArray2Pow32, + pub e2pow32: ElementArray2Pow32, } impl ElementArrays { @@ -775,7 +775,7 @@ impl ElementArrays { } } - pub(crate) fn create_object_entries( + pub fn create_object_entries( &mut self, mut entries: Vec, ) -> (ElementsVector, ElementsVector) { @@ -823,7 +823,7 @@ impl ElementArrays { ) } - pub(crate) fn get<'a>(&'a self, vector: ElementsVector) -> () { + pub fn get<'a>(&'a self, vector: ElementsVector) -> () { // match vector.cap { // ElementArrayKey::E4 => &self // .e2pow4 @@ -883,4 +883,73 @@ impl ElementArrays { // .as_slice()[0..vector.len as usize], // _ => unreachable!(), } + + pub fn has(&self, vector: ElementsVector, element: Value) -> bool { + match vector.cap { + ElementArrayKey::E4 => self + .e2pow4 + .values + .get(vector.elements_index.into_index()) + .unwrap() + .unwrap() + .as_slice()[0..vector.len as usize] + .contains(&Some(element)), + ElementArrayKey::E6 => self + .e2pow6 + .values + .get(vector.elements_index.into_index()) + .unwrap() + .unwrap() + .as_slice()[0..vector.len as usize] + .contains(&Some(element)), + ElementArrayKey::E8 => self + .e2pow8 + .values + .get(vector.elements_index.into_index()) + .unwrap() + .unwrap() + .as_slice()[0..vector.len as usize] + .contains(&Some(element)), + ElementArrayKey::E10 => self + .e2pow10 + .values + .get(vector.elements_index.into_index()) + .unwrap() + .unwrap() + .as_slice()[0..vector.len as usize] + .contains(&Some(element)), + ElementArrayKey::E12 => self + .e2pow12 + .values + .get(vector.elements_index.into_index()) + .unwrap() + .unwrap() + .as_slice()[0..vector.len as usize] + .contains(&Some(element)), + ElementArrayKey::E16 => self + .e2pow16 + .values + .get(vector.elements_index.into_index()) + .unwrap() + .unwrap() + .as_slice()[0..vector.len as usize] + .contains(&Some(element)), + ElementArrayKey::E24 => self + .e2pow24 + .values + .get(vector.elements_index.into_index()) + .unwrap() + .unwrap() + .as_slice()[0..vector.len as usize] + .contains(&Some(element)), + ElementArrayKey::E32 => self + .e2pow32 + .values + .get(vector.elements_index.into_index()) + .unwrap() + .unwrap() + .as_slice()[0..vector.len as usize] + .contains(&Some(element)), + } + } } diff --git a/nova_vm/src/heap/error.rs b/nova_vm/src/heap/error.rs index 136195a61..80678dbd5 100644 --- a/nova_vm/src/heap/error.rs +++ b/nova_vm/src/heap/error.rs @@ -14,7 +14,7 @@ use super::{ }; #[derive(Debug, Clone, Copy)] -pub(crate) struct ErrorHeapData { +pub struct ErrorHeapData { pub(super) object_index: ObjectIndex, // TODO: stack? name? } diff --git a/nova_vm/src/heap/function.rs b/nova_vm/src/heap/function.rs index b43154399..3c1eb39db 100644 --- a/nova_vm/src/heap/function.rs +++ b/nova_vm/src/heap/function.rs @@ -15,11 +15,11 @@ use super::{ }; #[derive(Debug, Clone)] -pub(crate) struct FunctionHeapData { +pub struct FunctionHeapData { pub(super) object_index: Option, pub(super) length: u8, - pub(crate) initial_name: Value, - // pub(crate) behaviour: Behaviour, + pub initial_name: Value, + // pub behaviour: Behaviour, // TODO: Should we create a `BoundFunctionHeapData` for an exotic object // that allows setting fields and other deoptimizations? // pub(super) uses_arguments: bool, diff --git a/nova_vm/src/heap/heap_bits.rs b/nova_vm/src/heap/heap_bits.rs index 0b0f34035..8cca9ec29 100644 --- a/nova_vm/src/heap/heap_bits.rs +++ b/nova_vm/src/heap/heap_bits.rs @@ -10,7 +10,7 @@ use super::{ Heap, }; -pub(crate) struct HeapBits { +pub struct HeapBits { pub e_2_4: Box<[AtomicBool]>, pub e_2_6: Box<[AtomicBool]>, pub e_2_8: Box<[AtomicBool]>, @@ -31,7 +31,7 @@ pub(crate) struct HeapBits { pub symbols: Box<[AtomicBool]>, } -pub(crate) struct WorkQueues { +pub struct WorkQueues { pub e_2_4: Vec, pub e_2_6: Vec, pub e_2_8: Vec, @@ -53,7 +53,7 @@ pub(crate) struct WorkQueues { } impl HeapBits { - pub(crate) fn new(heap: &Heap) -> Self { + pub fn new(heap: &Heap) -> Self { Self { e_2_4: Vec::with_capacity(heap.elements.e2pow4.values.len()).into_boxed_slice(), e_2_6: Vec::with_capacity(heap.elements.e2pow6.values.len()).into_boxed_slice(), @@ -78,7 +78,7 @@ impl HeapBits { } impl WorkQueues { - pub(crate) fn new(heap: &Heap) -> Self { + pub fn new(heap: &Heap) -> Self { Self { e_2_4: Vec::with_capacity(heap.elements.e2pow4.values.len() / 4), e_2_6: Vec::with_capacity(heap.elements.e2pow6.values.len() / 4), @@ -101,7 +101,7 @@ impl WorkQueues { } } - pub(crate) fn push_value(&mut self, value: Value) { + pub fn push_value(&mut self, value: Value) { match value { Value::Array(idx) => self.arrays.push(idx), // Value::BigIntObject(_) => todo!(), @@ -128,7 +128,7 @@ impl WorkQueues { } } - pub(crate) fn is_empty(&self) -> bool { + pub fn is_empty(&self) -> bool { self.e_2_4.is_empty() && self.e_2_6.is_empty() && self.e_2_8.is_empty() diff --git a/nova_vm/src/heap/heap_gc.rs b/nova_vm/src/heap/heap_gc.rs index 3502e7415..d9cbb617a 100644 --- a/nova_vm/src/heap/heap_gc.rs +++ b/nova_vm/src/heap/heap_gc.rs @@ -12,7 +12,7 @@ use super::{ ElementsVector, Heap, }; -pub(crate) fn heap_gc(heap: &mut Heap) { +pub fn heap_gc(heap: &mut Heap) { let bits = HeapBits::new(heap); let mut queues = WorkQueues::new(heap); diff --git a/nova_vm/src/heap/indexes.rs b/nova_vm/src/heap/indexes.rs index 90ebe47e2..7af7a5a31 100644 --- a/nova_vm/src/heap/indexes.rs +++ b/nova_vm/src/heap/indexes.rs @@ -1,4 +1,5 @@ use crate::types::Value; +use crate::Heap; use super::{ array::ArrayHeapData, bigint::BigIntHeapData, date::DateHeapData, error::ErrorHeapData, @@ -15,7 +16,7 @@ use std::{marker::PhantomData, mem::size_of, num::NonZeroU32}; /// /// This index implies a tracing reference count from this /// struct to T at the given index. -pub(crate) struct BaseIndex(NonZeroU32, PhantomData); +pub struct BaseIndex(NonZeroU32, PhantomData); const _INDEX_SIZE_IS_U32: () = assert!(size_of::>() == size_of::()); const _OPTION_INDEX_SIZE_IS_U32: () = @@ -127,14 +128,24 @@ impl BaseIndex { } } -pub(crate) type ArrayIndex = BaseIndex; -pub(crate) type BigIntIndex = BaseIndex; -pub(crate) type DateIndex = BaseIndex; -pub(crate) type ErrorIndex = BaseIndex; -pub(crate) type FunctionIndex = BaseIndex; -pub(crate) type NumberIndex = BaseIndex; -pub(crate) type ObjectIndex = BaseIndex; -pub(crate) type RegExpIndex = BaseIndex; -pub(crate) type StringIndex = BaseIndex; -pub(crate) type SymbolIndex = BaseIndex; -pub(crate) type ElementIndex = BaseIndex<[Option]>; +pub type ArrayIndex = BaseIndex; +pub type BigIntIndex = BaseIndex; +pub type DateIndex = BaseIndex; +pub type ErrorIndex = BaseIndex; +pub type FunctionIndex = BaseIndex; +pub type NumberIndex = BaseIndex; +pub type ObjectIndex = BaseIndex; +pub type RegExpIndex = BaseIndex; +pub type StringIndex = BaseIndex; +pub type SymbolIndex = BaseIndex; +pub type ElementIndex = BaseIndex<[Option]>; + +impl ObjectIndex { + pub fn get<'a>(self, heap: &'a Heap) -> &'a ObjectHeapData { + heap.objects + .get(self.into_index()) + .unwrap() + .as_ref() + .unwrap() + } +} diff --git a/nova_vm/src/heap/number.rs b/nova_vm/src/heap/number.rs index 4b65067f6..24ebd1089 100644 --- a/nova_vm/src/heap/number.rs +++ b/nova_vm/src/heap/number.rs @@ -12,7 +12,7 @@ use crate::{ }; #[derive(Debug, Clone, Copy)] -pub(crate) struct NumberHeapData { +pub struct NumberHeapData { pub(super) data: f64, } @@ -21,7 +21,7 @@ impl NumberHeapData { NumberHeapData { data } } - pub(crate) fn value(&self) -> f64 { + pub fn value(&self) -> f64 { self.data } } diff --git a/nova_vm/src/heap/object.rs b/nova_vm/src/heap/object.rs index 9ed7ce956..5aeb79f62 100644 --- a/nova_vm/src/heap/object.rs +++ b/nova_vm/src/heap/object.rs @@ -18,16 +18,16 @@ use super::{ #[derive(Debug)] pub struct ObjectEntry { - pub(crate) key: PropertyKey, - pub(crate) value: PropertyDescriptor, + pub key: PropertyKey, + pub value: PropertyDescriptor, } impl ObjectEntry { - pub(crate) fn new(key: PropertyKey, value: PropertyDescriptor) -> Self { + pub fn new(key: PropertyKey, value: PropertyDescriptor) -> Self { ObjectEntry { key, value } } - pub(crate) fn new_prototype_function_entry( + pub fn new_prototype_function_entry( heap: &mut Heap, name: &str, length: u8, @@ -46,7 +46,7 @@ impl ObjectEntry { ObjectEntry { key, value } } - pub(crate) fn new_prototype_symbol_function_entry( + pub fn new_prototype_symbol_function_entry( heap: &mut Heap, name: &str, symbol_index: SymbolIndex, @@ -61,7 +61,7 @@ impl ObjectEntry { ObjectEntry { key, value } } - pub(crate) fn new_constructor_prototype_entry(heap: &mut Heap, idx: ObjectIndex) -> Self { + pub fn new_constructor_prototype_entry(heap: &mut Heap, idx: ObjectIndex) -> Self { ObjectEntry { key: PropertyKey::from_str(heap, "prototype"), value: PropertyDescriptor::Data { @@ -73,7 +73,7 @@ impl ObjectEntry { } } - pub(crate) fn new_frozen_entry(heap: &mut Heap, key: &str, value: Value) -> Self { + pub fn new_frozen_entry(heap: &mut Heap, key: &str, value: Value) -> Self { ObjectEntry { key: PropertyKey::from_str(heap, key), value: PropertyDescriptor::roh(value), @@ -226,17 +226,17 @@ impl PropertyDescriptor { } #[derive(Debug, Clone, Copy)] -pub(crate) struct ObjectHeapData { - pub(crate) extensible: bool, +pub struct ObjectHeapData { + pub extensible: bool, // TODO: It's probably not necessary to have a whole Value here. // A prototype can only be set to be null or an object, meaning that most of the // possible Value options are impossible. // We could possibly do with just a `Option` but it would cause issues // with functions and possible other special object cases we want to track with partially // separate heap fields later down the line. - pub(crate) prototype: Value, - pub(crate) keys: ElementsVector, - pub(crate) values: ElementsVector, + pub prototype: Value, + pub keys: ElementsVector, + pub values: ElementsVector, } impl ObjectHeapData { @@ -260,6 +260,11 @@ impl ObjectHeapData { values, } } + + pub fn has(&self, heap: &Heap, key: Value) -> bool { + debug_assert!(key.is_string() || key.is_number() || key.is_symbol()); + heap.elements.has(self.keys, key) + } } pub fn initialize_object_heap(heap: &mut Heap) { diff --git a/nova_vm/src/heap/regexp.rs b/nova_vm/src/heap/regexp.rs index 0313f1b44..964a0561a 100644 --- a/nova_vm/src/heap/regexp.rs +++ b/nova_vm/src/heap/regexp.rs @@ -15,7 +15,7 @@ use super::{ }; #[derive(Debug, Clone, Copy)] -pub(crate) struct RegExpHeapData { +pub struct RegExpHeapData { pub(super) object_index: ObjectIndex, // pub(super) _regex: RegExp, } diff --git a/nova_vm/src/heap/string.rs b/nova_vm/src/heap/string.rs index e780aee94..2cd4da64a 100644 --- a/nova_vm/src/heap/string.rs +++ b/nova_vm/src/heap/string.rs @@ -9,8 +9,8 @@ use crate::{ use wtf8::Wtf8Buf; #[derive(Debug, Clone)] -pub(crate) struct StringHeapData { - pub(crate) data: Wtf8Buf, +pub struct StringHeapData { + pub data: Wtf8Buf, } impl StringHeapData { diff --git a/nova_vm/src/heap/symbol.rs b/nova_vm/src/heap/symbol.rs index 09a93126d..1de497b65 100644 --- a/nova_vm/src/heap/symbol.rs +++ b/nova_vm/src/heap/symbol.rs @@ -13,7 +13,7 @@ use super::{ }; #[derive(Debug, Clone, Copy)] -pub(crate) struct SymbolHeapData { +pub struct SymbolHeapData { pub(super) descriptor: Option, } diff --git a/nova_vm/src/small_integer.rs b/nova_vm/src/small_integer.rs index cd2f9063d..51faa1c1c 100644 --- a/nova_vm/src/small_integer.rs +++ b/nova_vm/src/small_integer.rs @@ -22,7 +22,7 @@ impl SmallInteger { self.into() } - pub(crate) fn from_i64_unchecked(value: i64) -> SmallInteger { + pub fn from_i64_unchecked(value: i64) -> SmallInteger { debug_assert!(value >= Self::MIN_NUMBER && value <= Self::MAX_NUMBER); let bytes = i64::to_ne_bytes(value); diff --git a/nova_vm/src/small_string.rs b/nova_vm/src/small_string.rs index d82e59919..36c4a421e 100644 --- a/nova_vm/src/small_string.rs +++ b/nova_vm/src/small_string.rs @@ -1,4 +1,4 @@ -#[derive(Clone, Copy)] +#[derive(Clone, Copy, PartialEq)] pub struct SmallString { bytes: [u8; 7], } @@ -41,7 +41,7 @@ impl SmallString { matches!(self.bytes, [0, 0, 0, 0, 0, 0, 0]) } - pub(crate) fn from_str_unchecked(string: &str) -> Self { + pub fn from_str_unchecked(string: &str) -> Self { let string_bytes = string.as_bytes(); // We have only 7 bytes to work with, and we cannot tell apart diff --git a/nova_vm/src/types/language/number.rs b/nova_vm/src/types/language/number.rs index 5f941a823..2a2a80113 100644 --- a/nova_vm/src/types/language/number.rs +++ b/nova_vm/src/types/language/number.rs @@ -60,7 +60,7 @@ impl TryFrom for Number { } impl Number { - pub(crate) fn new(value: Value) -> Self { + pub fn new(value: Value) -> Self { debug_assert!(matches!( value, Value::Number(_) | Value::Integer(_) | Value::Float(_) diff --git a/nova_vm/src/types/language/object.rs b/nova_vm/src/types/language/object.rs index 243ac5e75..5c153f457 100644 --- a/nova_vm/src/types/language/object.rs +++ b/nova_vm/src/types/language/object.rs @@ -194,11 +194,7 @@ impl Object { }; // 2. Return ? O.[[DefineOwnProperty]](P, newDesc). - Ok(self.internal_methods(agent).define_own_property)( - agent, - self, - property_key, - new_descriptor, - ) + let define_own_property = self.internal_methods(agent).define_own_property; + define_own_property(agent, self, property_key, new_descriptor) } } diff --git a/nova_vm/src/types/language/object/property_storage.rs b/nova_vm/src/types/language/object/property_storage.rs index 7033dafbd..d9686cf8b 100644 --- a/nova_vm/src/types/language/object/property_storage.rs +++ b/nova_vm/src/types/language/object/property_storage.rs @@ -15,7 +15,7 @@ use super::{Object, PropertyKey}; pub struct PropertyStorage(Object); impl PropertyStorage { - pub(crate) fn new(object: Object) -> Self { + pub fn new(object: Object) -> Self { Self(object) } @@ -55,20 +55,18 @@ impl PropertyStorage { let realm = realm.borrow(); let array = realm.heap.get(array); - if let Value::Integer(number) = key.into_value() { - if let Some(_) = TryInto::::try_into(number.into_i64()) - .map(|idx| array.elements.get(idx)) - .ok() - { - return true; - } + if key.is_array_index() { + return realm.heap.elements.has(array.elements, key.into_value()); } if let Some(object) = array.object_index { - return object.property_storage().has(agent, key); + realm + .heap + .elements + .has(object.get(&realm.heap).keys, key.into_value()) + } else { + false } - - false } Value::Function(_) => todo!(), _ => unreachable!(), diff --git a/nova_vm/src/types/language/value.rs b/nova_vm/src/types/language/value.rs index dfa1c700c..0546eb860 100644 --- a/nova_vm/src/types/language/value.rs +++ b/nova_vm/src/types/language/value.rs @@ -13,7 +13,7 @@ use super::{BigInt, Number}; /// 6.1 ECMAScript Language Types /// https://tc39.es/ecma262/#sec-ecmascript-language-types -#[derive(Debug, Clone, Copy)] +#[derive(Debug, Clone, Copy, PartialEq)] pub enum Value { /// 6.1.1 The Undefined Type /// https://tc39.es/ecma262/#sec-ecmascript-language-types-undefined-type diff --git a/wasm/src/decoder/util.rs b/wasm/src/decoder/util.rs index 97a467182..412460253 100644 --- a/wasm/src/decoder/util.rs +++ b/wasm/src/decoder/util.rs @@ -2,7 +2,7 @@ use super::common; use crate::error::Error; use crate::error::Result; use crate::varint::decode_u32; -pub(crate) fn decode_vec(reader: &mut R, func: F) -> Result> +pub fn decode_vec(reader: &mut R, func: F) -> Result> where R: std::io::Read, F: Fn(&mut R) -> Result,