diff --git a/nova_vm/Cargo.toml b/nova_vm/Cargo.toml index a1481ac32..9916c729d 100644 --- a/nova_vm/Cargo.toml +++ b/nova_vm/Cargo.toml @@ -24,16 +24,26 @@ unicode-normalization = { workspace = true } wtf8 = { workspace = true } [features] -default = ["math", "json", "date", "array-buffer", "shared-array-buffer", "weak-refs", "atomics"] +default = [ + "math", + "json", + "date", + "array-buffer", + "shared-array-buffer", + "weak-refs", + "atomics", + "regexp" +] array-buffer = [] atomics = ["array-buffer", "shared-array-buffer"] date = [] interleaved-gc = [] json = ["sonic-rs"] math = [] +regexp = [] shared-array-buffer = [] -typescript = [] weak-refs = [] +typescript = [] [build-dependencies] small_string = { path = "../small_string" } diff --git a/nova_vm/src/ecmascript/builtins.rs b/nova_vm/src/ecmascript/builtins.rs index 09f4fef00..da5861b1d 100644 --- a/nova_vm/src/ecmascript/builtins.rs +++ b/nova_vm/src/ecmascript/builtins.rs @@ -37,6 +37,7 @@ pub(crate) mod primitive_objects; pub(crate) mod promise; pub(crate) mod proxy; pub(crate) mod reflection; +#[cfg(feature = "regexp")] pub(crate) mod regexp; pub(crate) mod set; #[cfg(feature = "shared-array-buffer")] diff --git a/nova_vm/src/ecmascript/builtins/fundamental_objects/object_objects/object_prototype.rs b/nova_vm/src/ecmascript/builtins/fundamental_objects/object_objects/object_prototype.rs index 0cc17ad3a..82c094dcc 100644 --- a/nova_vm/src/ecmascript/builtins/fundamental_objects/object_objects/object_prototype.rs +++ b/nova_vm/src/ecmascript/builtins/fundamental_objects/object_objects/object_prototype.rs @@ -178,6 +178,7 @@ impl ObjectPrototype { // TODO: Check for [[Call]] slot of EmbedderObject Value::EmbedderObject(_) => todo!(), // 13. Else if O has a [[RegExpMatcher]] internal slot, let builtinTag be "RegExp". + #[cfg(feature = "regexp")] Value::RegExp(_) => Ok(BUILTIN_STRING_MEMORY._object_RegExp_.into_value()), Value::PrimitiveObject(idx) => match &agent[idx].data { PrimitiveObjectData::Boolean(_) => { diff --git a/nova_vm/src/ecmascript/builtins/ordinary.rs b/nova_vm/src/ecmascript/builtins/ordinary.rs index 66dd63dc3..fcce09aca 100644 --- a/nova_vm/src/ecmascript/builtins/ordinary.rs +++ b/nova_vm/src/ecmascript/builtins/ordinary.rs @@ -26,6 +26,8 @@ use crate::{ #[cfg(feature = "date")] use super::date::data::DateHeapData; +#[cfg(feature = "regexp")] +use super::regexp::RegExpHeapData; #[cfg(feature = "shared-array-buffer")] use super::shared_array_buffer::data::SharedArrayBufferHeapData; use super::{ @@ -40,7 +42,6 @@ use super::{ map::data::MapHeapData, primitive_objects::PrimitiveObjectHeapData, promise::data::PromiseHeapData, - regexp::RegExpHeapData, set::data::SetHeapData, ArrayHeapData, }; @@ -947,6 +948,7 @@ pub(crate) fn ordinary_object_create_with_intrinsics( .create(MapIteratorHeapData::default()) .into_object(), ProtoIntrinsics::Promise => agent.heap.create(PromiseHeapData::default()).into_object(), + #[cfg(feature = "regexp")] ProtoIntrinsics::RegExp => agent.heap.create(RegExpHeapData::default()).into_object(), ProtoIntrinsics::Set => agent.heap.create(SetHeapData::default()).into_object(), ProtoIntrinsics::SetIterator => agent @@ -1097,6 +1099,7 @@ pub(crate) fn get_prototype_from_constructor( ProtoIntrinsics::Promise => Some(intrinsics.promise().into_function()), ProtoIntrinsics::RangeError => Some(intrinsics.range_error().into_function()), ProtoIntrinsics::ReferenceError => Some(intrinsics.reference_error().into_function()), + #[cfg(feature = "regexp")] ProtoIntrinsics::RegExp => Some(intrinsics.reg_exp().into_function()), ProtoIntrinsics::Set => Some(intrinsics.set().into_function()), ProtoIntrinsics::SetIterator => None, diff --git a/nova_vm/src/ecmascript/builtins/text_processing.rs b/nova_vm/src/ecmascript/builtins/text_processing.rs index 5a9286659..c84e708ad 100644 --- a/nova_vm/src/ecmascript/builtins/text_processing.rs +++ b/nova_vm/src/ecmascript/builtins/text_processing.rs @@ -1,6 +1,6 @@ // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at https://mozilla.org/MPL/2.0/. - +#[cfg(feature = "regexp")] pub(crate) mod regexp_objects; pub(crate) mod string_objects; diff --git a/nova_vm/src/ecmascript/execution/realm.rs b/nova_vm/src/ecmascript/execution/realm.rs index b1a73346f..12694cabb 100644 --- a/nova_vm/src/ecmascript/execution/realm.rs +++ b/nova_vm/src/ecmascript/execution/realm.rs @@ -811,17 +811,19 @@ pub(crate) fn set_default_global_bindings( define_property_or_throw(agent, global, name, desc)?; // 19.3.26 RegExp ( . . . ) - let name = PropertyKey::from(BUILTIN_STRING_MEMORY.RegExp); - let value = agent.get_realm(realm_id).intrinsics().reg_exp(); - let desc = PropertyDescriptor { - value: Some(value.into_value()), - writable: Some(true), - enumerable: Some(false), - configurable: Some(true), - ..Default::default() - }; - define_property_or_throw(agent, global, name, desc)?; - + #[cfg(feature = "regexp")] + { + let name = PropertyKey::from(BUILTIN_STRING_MEMORY.RegExp); + let value = agent.get_realm(realm_id).intrinsics().reg_exp(); + let desc = PropertyDescriptor { + value: Some(value.into_value()), + writable: Some(true), + enumerable: Some(false), + configurable: Some(true), + ..Default::default() + }; + define_property_or_throw(agent, global, name, desc)?; + } // 19.3.27 Set ( . . . ) let name = PropertyKey::from(BUILTIN_STRING_MEMORY.Set); let value = agent.get_realm(realm_id).intrinsics().set(); @@ -1127,7 +1129,7 @@ pub(crate) fn initialize_default_realm(agent: &mut Agent) { #[cfg(test)] mod test { - + #[allow(unused_imports)] use crate::heap::{ IntrinsicConstructorIndexes, IntrinsicFunctionIndexes, IntrinsicObjectIndexes, LAST_INTRINSIC_CONSTRUCTOR_INDEX, LAST_INTRINSIC_FUNCTION_INDEX, @@ -1175,6 +1177,7 @@ mod test { } #[test] + #[cfg(feature = "regexp")] fn test_default_realm_sanity() { use super::initialize_default_realm; use crate::ecmascript::execution::{agent::Options, Agent, DefaultHostHooks}; diff --git a/nova_vm/src/ecmascript/execution/realm/intrinsics.rs b/nova_vm/src/ecmascript/execution/realm/intrinsics.rs index e9b9c208d..31c39f6b8 100644 --- a/nova_vm/src/ecmascript/execution/realm/intrinsics.rs +++ b/nova_vm/src/ecmascript/execution/realm/intrinsics.rs @@ -31,6 +31,11 @@ use crate::ecmascript::builtins::structured_data::shared_array_buffer_objects::{ shared_array_buffer_constructor::SharedArrayBufferConstructor, shared_array_buffer_prototype::SharedArrayBufferPrototype, }; +#[cfg(feature = "regexp")] +use crate::ecmascript::builtins::text_processing::regexp_objects::{ + regexp_constructor::RegExpConstructor, regexp_prototype::RegExpPrototype, + regexp_string_iterator_prototype::RegExpStringIteratorPrototype, +}; #[cfg(feature = "array-buffer")] use crate::ecmascript::builtins::{ indexed_collections::typed_array_objects::{ @@ -98,16 +103,10 @@ use crate::{ }, primitive_objects::PrimitiveObject, reflection::{proxy_constructor::ProxyConstructor, reflect_object::ReflectObject}, - text_processing::{ - regexp_objects::{ - regexp_constructor::RegExpConstructor, regexp_prototype::RegExpPrototype, - regexp_string_iterator_prototype::RegExpStringIteratorPrototype, - }, - string_objects::{ - string_constructor::StringConstructor, - string_iterator_objects::StringIteratorPrototype, - string_prototype::StringPrototype, - }, + text_processing::string_objects::{ + string_constructor::StringConstructor, + string_iterator_objects::StringIteratorPrototype, + string_prototype::StringPrototype, }, Array, BuiltinFunction, }, @@ -204,6 +203,7 @@ pub enum ProtoIntrinsics { Promise, RangeError, ReferenceError, + #[cfg(feature = "regexp")] RegExp, Set, SetIterator, @@ -289,8 +289,11 @@ impl Intrinsics { StringPrototype::create_intrinsic(agent, realm); StringConstructor::create_intrinsic(agent, realm); StringIteratorPrototype::create_intrinsic(agent, realm); + #[cfg(feature = "regexp")] RegExpPrototype::create_intrinsic(agent, realm); + #[cfg(feature = "regexp")] RegExpConstructor::create_intrinsic(agent, realm); + #[cfg(feature = "regexp")] RegExpStringIteratorPrototype::create_intrinsic(agent, realm); ArrayPrototype::create_intrinsic(agent, realm); ArrayConstructor::create_intrinsic(agent, realm); @@ -411,6 +414,7 @@ impl Intrinsics { ProtoIntrinsics::Map => self.map_prototype().into(), ProtoIntrinsics::MapIterator => self.map_iterator_prototype().into(), ProtoIntrinsics::Promise => self.promise_prototype().into(), + #[cfg(feature = "regexp")] ProtoIntrinsics::RegExp => self.reg_exp_prototype().into(), ProtoIntrinsics::Set => self.set_prototype().into(), ProtoIntrinsics::SetIterator => self.set_iterator_prototype().into(), @@ -1211,6 +1215,7 @@ impl Intrinsics { } /// %RegExp.prototype.exec% + #[cfg(feature = "regexp")] pub(crate) fn reg_exp_prototype_exec(&self) -> BuiltinFunction { IntrinsicFunctionIndexes::RegExpPrototypeExec .get_builtin_function_index(self.builtin_function_index_base) @@ -1218,6 +1223,7 @@ impl Intrinsics { } /// %RegExp.prototype% + #[cfg(feature = "regexp")] pub(crate) fn reg_exp_prototype(&self) -> OrdinaryObject { IntrinsicObjectIndexes::RegExpPrototype .get_object_index(self.object_index_base) @@ -1225,17 +1231,20 @@ impl Intrinsics { } /// %RegExp% + #[cfg(feature = "regexp")] pub(crate) fn reg_exp(&self) -> BuiltinFunction { IntrinsicConstructorIndexes::RegExp .get_builtin_function_index(self.builtin_function_index_base) .into() } + #[cfg(feature = "regexp")] pub(crate) fn reg_exp_base_object(&self) -> ObjectIndex { IntrinsicConstructorIndexes::RegExp.get_object_index(self.object_index_base) } /// %RegExpStringIteratorPrototype% + #[cfg(feature = "regexp")] pub(crate) fn reg_exp_string_iterator_prototype(&self) -> OrdinaryObject { IntrinsicObjectIndexes::RegExpStringIteratorPrototype .get_object_index(self.object_index_base) @@ -1709,9 +1718,13 @@ impl HeapMarkAndSweep for Intrinsics { self.reference_error_prototype().mark_values(queues); self.reference_error().mark_values(queues); self.reflect().mark_values(queues); + #[cfg(feature = "regexp")] self.reg_exp_prototype_exec().mark_values(queues); + #[cfg(feature = "regexp")] self.reg_exp_prototype().mark_values(queues); + #[cfg(feature = "regexp")] self.reg_exp().mark_values(queues); + #[cfg(feature = "regexp")] self.reg_exp_string_iterator_prototype().mark_values(queues); self.set_prototype_values().mark_values(queues); self.set_prototype().mark_values(queues); diff --git a/nova_vm/src/ecmascript/types/language/object.rs b/nova_vm/src/ecmascript/types/language/object.rs index 5ac3e60da..1785f88f1 100644 --- a/nova_vm/src/ecmascript/types/language/object.rs +++ b/nova_vm/src/ecmascript/types/language/object.rs @@ -13,6 +13,8 @@ use std::hash::Hash; #[cfg(feature = "date")] use super::value::DATE_DISCRIMINANT; +#[cfg(feature = "regexp")] +use super::value::REGEXP_DISCRIMINANT; #[cfg(feature = "shared-array-buffer")] use super::value::SHARED_ARRAY_BUFFER_DISCRIMINANT; #[cfg(feature = "array-buffer")] @@ -36,13 +38,15 @@ use super::{ ECMASCRIPT_FUNCTION_DISCRIMINANT, EMBEDDER_OBJECT_DISCRIMINANT, ERROR_DISCRIMINANT, FINALIZATION_REGISTRY_DISCRIMINANT, GENERATOR_DISCRIMINANT, ITERATOR_DISCRIMINANT, MAP_DISCRIMINANT, MAP_ITERATOR_DISCRIMINANT, MODULE_DISCRIMINANT, OBJECT_DISCRIMINANT, - PRIMITIVE_OBJECT_DISCRIMINANT, PROMISE_DISCRIMINANT, PROXY_DISCRIMINANT, - REGEXP_DISCRIMINANT, SET_DISCRIMINANT, SET_ITERATOR_DISCRIMINANT, + PRIMITIVE_OBJECT_DISCRIMINANT, PROMISE_DISCRIMINANT, PROXY_DISCRIMINANT, SET_DISCRIMINANT, + SET_ITERATOR_DISCRIMINANT, }, Function, IntoValue, Value, }; #[cfg(feature = "date")] use crate::ecmascript::builtins::date::Date; +#[cfg(feature = "regexp")] +use crate::ecmascript::builtins::regexp::RegExp; #[cfg(feature = "shared-array-buffer")] use crate::ecmascript::builtins::shared_array_buffer::SharedArrayBuffer; #[cfg(feature = "weak-refs")] @@ -73,7 +77,6 @@ use crate::{ primitive_objects::PrimitiveObject, promise::Promise, proxy::Proxy, - regexp::RegExp, set::Set, ArgumentsList, Array, BuiltinConstructorFunction, BuiltinFunction, ECMAScriptFunction, }, @@ -125,6 +128,7 @@ pub enum Object { Map(Map) = MAP_DISCRIMINANT, Promise(Promise) = PROMISE_DISCRIMINANT, Proxy(Proxy) = PROXY_DISCRIMINANT, + #[cfg(feature = "regexp")] RegExp(RegExp) = REGEXP_DISCRIMINANT, Set(Set) = SET_DISCRIMINANT, #[cfg(feature = "shared-array-buffer")] @@ -199,6 +203,7 @@ impl IntoValue for Object { Object::Map(data) => Value::Map(data), Object::Promise(data) => Value::Promise(data), Object::Proxy(data) => Value::Proxy(data), + #[cfg(feature = "regexp")] Object::RegExp(data) => Value::RegExp(data), Object::Set(data) => Value::Set(data), #[cfg(feature = "shared-array-buffer")] @@ -393,6 +398,7 @@ impl From for Value { Object::Map(data) => Value::Map(data), Object::Promise(data) => Value::Promise(data), Object::Proxy(data) => Value::Proxy(data), + #[cfg(feature = "regexp")] Object::RegExp(data) => Value::RegExp(data), Object::Set(data) => Value::Set(data), #[cfg(feature = "shared-array-buffer")] @@ -478,6 +484,7 @@ impl TryFrom for Object { Value::Map(data) => Ok(Object::Map(data)), Value::Promise(data) => Ok(Object::Promise(data)), Value::Proxy(data) => Ok(Object::Proxy(data)), + #[cfg(feature = "regexp")] Value::RegExp(idx) => Ok(Object::RegExp(idx)), Value::Set(data) => Ok(Object::Set(data)), #[cfg(feature = "shared-array-buffer")] @@ -560,6 +567,7 @@ impl Hash for Object { Object::Map(data) => data.get_index().hash(state), Object::Promise(data) => data.get_index().hash(state), Object::Proxy(data) => data.get_index().hash(state), + #[cfg(feature = "regexp")] Object::RegExp(data) => data.get_index().hash(state), Object::Set(data) => data.get_index().hash(state), #[cfg(feature = "shared-array-buffer")] @@ -643,6 +651,7 @@ impl InternalSlots for Object { Object::Map(data) => data.internal_extensible(agent), Object::Promise(data) => data.internal_extensible(agent), Object::Proxy(data) => data.internal_extensible(agent), + #[cfg(feature = "regexp")] Object::RegExp(data) => data.internal_extensible(agent), Object::Set(data) => data.internal_extensible(agent), #[cfg(feature = "shared-array-buffer")] @@ -720,6 +729,7 @@ impl InternalSlots for Object { Object::Map(data) => data.internal_set_extensible(agent, value), Object::Promise(data) => data.internal_set_extensible(agent, value), Object::Proxy(data) => data.internal_set_extensible(agent, value), + #[cfg(feature = "regexp")] Object::RegExp(data) => data.internal_set_extensible(agent, value), Object::Set(data) => data.internal_set_extensible(agent, value), #[cfg(feature = "shared-array-buffer")] @@ -811,6 +821,7 @@ impl InternalSlots for Object { Object::Map(data) => data.internal_prototype(agent), Object::Promise(data) => data.internal_prototype(agent), Object::Proxy(data) => data.internal_prototype(agent), + #[cfg(feature = "regexp")] Object::RegExp(data) => data.internal_prototype(agent), Object::Set(data) => data.internal_prototype(agent), #[cfg(feature = "shared-array-buffer")] @@ -890,6 +901,7 @@ impl InternalSlots for Object { Object::Map(data) => data.internal_set_prototype(agent, prototype), Object::Promise(data) => data.internal_set_prototype(agent, prototype), Object::Proxy(data) => data.internal_set_prototype(agent, prototype), + #[cfg(feature = "regexp")] Object::RegExp(data) => data.internal_set_prototype(agent, prototype), Object::Set(data) => data.internal_set_prototype(agent, prototype), #[cfg(feature = "shared-array-buffer")] @@ -983,6 +995,7 @@ impl InternalMethods for Object { Object::Map(data) => data.internal_get_prototype_of(agent), Object::Promise(data) => data.internal_get_prototype_of(agent), Object::Proxy(data) => data.internal_get_prototype_of(agent), + #[cfg(feature = "regexp")] Object::RegExp(data) => data.internal_get_prototype_of(agent), Object::Set(data) => data.internal_get_prototype_of(agent), #[cfg(feature = "shared-array-buffer")] @@ -1080,6 +1093,7 @@ impl InternalMethods for Object { Object::Map(data) => data.internal_set_prototype_of(agent, prototype), Object::Promise(data) => data.internal_set_prototype_of(agent, prototype), Object::Proxy(data) => data.internal_set_prototype_of(agent, prototype), + #[cfg(feature = "regexp")] Object::RegExp(data) => data.internal_set_prototype_of(agent, prototype), Object::Set(data) => data.internal_set_prototype_of(agent, prototype), #[cfg(feature = "shared-array-buffer")] @@ -1171,6 +1185,7 @@ impl InternalMethods for Object { Object::Map(data) => data.internal_is_extensible(agent), Object::Promise(data) => data.internal_is_extensible(agent), Object::Proxy(data) => data.internal_is_extensible(agent), + #[cfg(feature = "regexp")] Object::RegExp(data) => data.internal_is_extensible(agent), Object::Set(data) => data.internal_is_extensible(agent), #[cfg(feature = "shared-array-buffer")] @@ -1256,6 +1271,7 @@ impl InternalMethods for Object { Object::Map(data) => data.internal_prevent_extensions(agent), Object::Promise(data) => data.internal_prevent_extensions(agent), Object::Proxy(data) => data.internal_prevent_extensions(agent), + #[cfg(feature = "regexp")] Object::RegExp(data) => data.internal_prevent_extensions(agent), Object::Set(data) => data.internal_prevent_extensions(agent), #[cfg(feature = "shared-array-buffer")] @@ -1357,6 +1373,7 @@ impl InternalMethods for Object { Object::Map(data) => data.internal_get_own_property(agent, property_key), Object::Promise(data) => data.internal_get_own_property(agent, property_key), Object::Proxy(data) => data.internal_get_own_property(agent, property_key), + #[cfg(feature = "regexp")] Object::RegExp(data) => data.internal_get_own_property(agent, property_key), Object::Set(data) => data.internal_get_own_property(agent, property_key), #[cfg(feature = "shared-array-buffer")] @@ -1487,6 +1504,7 @@ impl InternalMethods for Object { Object::Proxy(data) => { data.internal_define_own_property(agent, property_key, property_descriptor) } + #[cfg(feature = "regexp")] Object::RegExp(data) => { data.internal_define_own_property(agent, property_key, property_descriptor) } @@ -1607,6 +1625,7 @@ impl InternalMethods for Object { Object::Map(data) => data.internal_has_property(agent, property_key), Object::Promise(data) => data.internal_has_property(agent, property_key), Object::Proxy(data) => data.internal_has_property(agent, property_key), + #[cfg(feature = "regexp")] Object::RegExp(data) => data.internal_has_property(agent, property_key), Object::Set(data) => data.internal_has_property(agent, property_key), #[cfg(feature = "shared-array-buffer")] @@ -1707,6 +1726,7 @@ impl InternalMethods for Object { Object::Map(data) => data.internal_get(agent, property_key, receiver), Object::Promise(data) => data.internal_get(agent, property_key, receiver), Object::Proxy(data) => data.internal_get(agent, property_key, receiver), + #[cfg(feature = "regexp")] Object::RegExp(data) => data.internal_get(agent, property_key, receiver), Object::Set(data) => data.internal_get(agent, property_key, receiver), #[cfg(feature = "shared-array-buffer")] @@ -1816,6 +1836,7 @@ impl InternalMethods for Object { Object::Map(data) => data.internal_set(agent, property_key, value, receiver), Object::Promise(data) => data.internal_set(agent, property_key, value, receiver), Object::Proxy(data) => data.internal_set(agent, property_key, value, receiver), + #[cfg(feature = "regexp")] Object::RegExp(data) => data.internal_set(agent, property_key, value, receiver), Object::Set(data) => data.internal_set(agent, property_key, value, receiver), #[cfg(feature = "shared-array-buffer")] @@ -1914,6 +1935,7 @@ impl InternalMethods for Object { Object::Map(data) => data.internal_delete(agent, property_key), Object::Promise(data) => data.internal_delete(agent, property_key), Object::Proxy(data) => data.internal_delete(agent, property_key), + #[cfg(feature = "regexp")] Object::RegExp(data) => data.internal_delete(agent, property_key), Object::Set(data) => data.internal_delete(agent, property_key), #[cfg(feature = "shared-array-buffer")] @@ -2005,6 +2027,7 @@ impl InternalMethods for Object { Object::Map(data) => data.internal_own_property_keys(agent), Object::Promise(data) => data.internal_own_property_keys(agent), Object::Proxy(data) => data.internal_own_property_keys(agent), + #[cfg(feature = "regexp")] Object::RegExp(data) => data.internal_own_property_keys(agent), Object::Set(data) => data.internal_own_property_keys(agent), #[cfg(feature = "shared-array-buffer")] @@ -2135,6 +2158,7 @@ impl HeapMarkAndSweep for Object { Object::Map(data) => data.mark_values(queues), Object::Promise(data) => data.mark_values(queues), Object::Proxy(data) => data.mark_values(queues), + #[cfg(feature = "regexp")] Object::RegExp(data) => data.mark_values(queues), Object::Set(data) => data.mark_values(queues), #[cfg(feature = "shared-array-buffer")] @@ -2204,6 +2228,7 @@ impl HeapMarkAndSweep for Object { Object::Map(data) => data.sweep_values(compactions), Object::Promise(data) => data.sweep_values(compactions), Object::Proxy(data) => data.sweep_values(compactions), + #[cfg(feature = "regexp")] Object::RegExp(data) => data.sweep_values(compactions), Object::Set(data) => data.sweep_values(compactions), #[cfg(feature = "shared-array-buffer")] diff --git a/nova_vm/src/ecmascript/types/language/value.rs b/nova_vm/src/ecmascript/types/language/value.rs index 9bd9bf3eb..b10b128ed 100644 --- a/nova_vm/src/ecmascript/types/language/value.rs +++ b/nova_vm/src/ecmascript/types/language/value.rs @@ -11,6 +11,8 @@ use super::{ }; #[cfg(feature = "date")] use crate::ecmascript::builtins::date::Date; +#[cfg(feature = "regexp")] +use crate::ecmascript::builtins::regexp::RegExp; #[cfg(feature = "shared-array-buffer")] use crate::ecmascript::builtins::shared_array_buffer::SharedArrayBuffer; #[cfg(feature = "weak-refs")] @@ -44,7 +46,6 @@ use crate::{ primitive_objects::PrimitiveObject, promise::Promise, proxy::Proxy, - regexp::RegExp, set::Set, Array, BuiltinConstructorFunction, BuiltinFunction, ECMAScriptFunction, }, @@ -162,6 +163,7 @@ pub enum Value { Map(Map), Promise(Promise), Proxy(Proxy), + #[cfg(feature = "regexp")] RegExp(RegExp), Set(Set), #[cfg(feature = "shared-array-buffer")] @@ -262,6 +264,7 @@ pub(crate) const ECMASCRIPT_FUNCTION_DISCRIMINANT: u8 = value_discriminant(Value::ECMAScriptFunction(ECMAScriptFunction::_def())); pub(crate) const BOUND_FUNCTION_DISCRIMINANT: u8 = value_discriminant(Value::BoundFunction(BoundFunction::_def())); +#[cfg(feature = "regexp")] pub(crate) const REGEXP_DISCRIMINANT: u8 = value_discriminant(Value::RegExp(RegExp::_def())); pub(crate) const BUILTIN_GENERATOR_FUNCTION_DISCRIMINANT: u8 = @@ -648,6 +651,7 @@ impl Value { discriminant.hash(hasher); data.get_index().hash(hasher); } + #[cfg(feature = "regexp")] Value::RegExp(data) => { discriminant.hash(hasher); data.get_index().hash(hasher); @@ -868,6 +872,7 @@ impl Value { discriminant.hash(hasher); data.get_index().hash(hasher); } + #[cfg(feature = "regexp")] Value::RegExp(data) => { discriminant.hash(hasher); data.get_index().hash(hasher); @@ -1329,6 +1334,7 @@ impl HeapMarkAndSweep for Value { Value::BoundFunction(data) => data.mark_values(queues), Value::BuiltinFunction(data) => data.mark_values(queues), Value::ECMAScriptFunction(data) => data.mark_values(queues), + #[cfg(feature = "regexp")] Value::RegExp(data) => data.mark_values(queues), Value::PrimitiveObject(data) => data.mark_values(queues), Value::Arguments(data) => data.mark_values(queues), @@ -1411,6 +1417,7 @@ impl HeapMarkAndSweep for Value { Value::BoundFunction(data) => data.sweep_values(compactions), Value::BuiltinFunction(data) => data.sweep_values(compactions), Value::ECMAScriptFunction(data) => data.sweep_values(compactions), + #[cfg(feature = "regexp")] Value::RegExp(data) => data.sweep_values(compactions), Value::PrimitiveObject(data) => data.sweep_values(compactions), Value::Arguments(data) => data.sweep_values(compactions), diff --git a/nova_vm/src/engine/bytecode/bytecode_compiler.rs b/nova_vm/src/engine/bytecode/bytecode_compiler.rs index a4fe144aa..aa0f2b222 100644 --- a/nova_vm/src/engine/bytecode/bytecode_compiler.rs +++ b/nova_vm/src/engine/bytecode/bytecode_compiler.rs @@ -10,9 +10,10 @@ use super::{ executable::ArrowFunctionExpression, Executable, ExecutableHeapData, FunctionExpression, Instruction, SendableRef, }; +#[cfg(feature = "regexp")] +use crate::ecmascript::builtins::regexp::reg_exp_create; use crate::{ ecmascript::{ - builtins::regexp::reg_exp_create, execution::Agent, syntax_directed_operations::{ function_definitions::{CompileFunctionBodyData, ContainsExpression}, @@ -982,7 +983,10 @@ impl CompileEvaluation for ast::ObjectExpression<'_> { ast::PropertyKey::PrivateFieldExpression(init) => init.compile(ctx), ast::PropertyKey::PrivateIdentifier(_init) => todo!(), ast::PropertyKey::PrivateInExpression(init) => init.compile(ctx), + #[cfg(feature = "regexp")] ast::PropertyKey::RegExpLiteral(init) => init.compile(ctx), + #[cfg(not(feature = "regexp"))] + ast::PropertyKey::RegExpLiteral(_) => todo!(), ast::PropertyKey::SequenceExpression(init) => init.compile(ctx), ast::PropertyKey::StaticIdentifier(id) => { if id.name == "__proto__" { @@ -1555,7 +1559,7 @@ impl CompileEvaluation for ast::PrivateInExpression<'_> { todo!() } } - +#[cfg(feature = "regexp")] impl CompileEvaluation for ast::RegExpLiteral<'_> { fn compile(&self, ctx: &mut CompileContext) { let pattern = match self.regex.pattern { @@ -1690,7 +1694,10 @@ impl CompileEvaluation for ast::Expression<'_> { ast::Expression::ParenthesizedExpression(x) => x.compile(ctx), ast::Expression::PrivateFieldExpression(x) => x.compile(ctx), ast::Expression::PrivateInExpression(x) => x.compile(ctx), + #[cfg(feature = "regexp")] ast::Expression::RegExpLiteral(x) => x.compile(ctx), + #[cfg(not(feature = "regexp"))] + ast::Expression::RegExpLiteral(_) => unreachable!(), ast::Expression::SequenceExpression(x) => x.compile(ctx), ast::Expression::StaticMemberExpression(x) => x.compile(ctx), ast::Expression::StringLiteral(x) => x.compile(ctx), @@ -2489,7 +2496,10 @@ impl CompileEvaluation for ast::ForStatement<'_> { ast::ForStatementInit::ParenthesizedExpression(init) => init.compile(ctx), ast::ForStatementInit::PrivateFieldExpression(init) => init.compile(ctx), ast::ForStatementInit::PrivateInExpression(init) => init.compile(ctx), + #[cfg(feature = "regexp")] ast::ForStatementInit::RegExpLiteral(init) => init.compile(ctx), + #[cfg(not(feature = "regexp"))] + ast::ForStatementInit::RegExpLiteral(_) => unreachable!(), ast::ForStatementInit::SequenceExpression(init) => init.compile(ctx), ast::ForStatementInit::StaticMemberExpression(init) => init.compile(ctx), ast::ForStatementInit::StringLiteral(init) => init.compile(ctx), diff --git a/nova_vm/src/engine/bytecode/vm.rs b/nova_vm/src/engine/bytecode/vm.rs index 72ec8c1b1..8602b4268 100644 --- a/nova_vm/src/engine/bytecode/vm.rs +++ b/nova_vm/src/engine/bytecode/vm.rs @@ -2235,7 +2235,6 @@ fn typeof_operator(_: &mut Agent, val: Value) -> String { Value::Error(_) | // 14. Return "object". Value::PrimitiveObject(_) | - Value::RegExp(_) | Value::Arguments(_) | Value::FinalizationRegistry(_) | Value::Map(_) | @@ -2250,6 +2249,8 @@ fn typeof_operator(_: &mut Agent, val: Value) -> String { Value::Generator(_) | Value::Module(_) | Value::EmbedderObject(_) => BUILTIN_STRING_MEMORY.object, + #[cfg(feature = "regexp")] + Value::RegExp(_) => BUILTIN_STRING_MEMORY.object, #[cfg(feature = "weak-refs")] Value::WeakMap(_) | Value::WeakRef(_) | diff --git a/nova_vm/src/heap.rs b/nova_vm/src/heap.rs index 97f8e8b0b..cf90b41f3 100644 --- a/nova_vm/src/heap.rs +++ b/nova_vm/src/heap.rs @@ -30,6 +30,8 @@ use self::{ }; #[cfg(feature = "date")] use crate::ecmascript::builtins::date::data::DateHeapData; +#[cfg(feature = "regexp")] +use crate::ecmascript::builtins::regexp::RegExpHeapData; #[cfg(feature = "shared-array-buffer")] use crate::ecmascript::builtins::shared_array_buffer::data::SharedArrayBufferHeapData; #[cfg(feature = "array-buffer")] @@ -65,7 +67,6 @@ use crate::{ primitive_objects::PrimitiveObjectHeapData, promise::data::PromiseHeapData, proxy::data::ProxyHeapData, - regexp::RegExpHeapData, set::data::SetHeapData, ArrayHeapData, }, @@ -124,6 +125,7 @@ pub struct Heap { pub promises: Vec>, pub proxys: Vec>, pub realms: Vec>, + #[cfg(feature = "regexp")] pub regexps: Vec>, pub sets: Vec>, pub set_iterators: Vec>, @@ -222,6 +224,7 @@ impl Heap { promises: Vec::with_capacity(0), proxys: Vec::with_capacity(0), realms: Vec::with_capacity(1), + #[cfg(feature = "regexp")] regexps: Vec::with_capacity(1024), scripts: Vec::with_capacity(1), sets: Vec::with_capacity(128), diff --git a/nova_vm/src/heap/heap_bits.rs b/nova_vm/src/heap/heap_bits.rs index 77bc16963..767c186e9 100644 --- a/nova_vm/src/heap/heap_bits.rs +++ b/nova_vm/src/heap/heap_bits.rs @@ -14,6 +14,8 @@ use super::{ }; #[cfg(feature = "date")] use crate::ecmascript::builtins::date::Date; +#[cfg(feature = "regexp")] +use crate::ecmascript::builtins::regexp::RegExp; #[cfg(feature = "shared-array-buffer")] use crate::ecmascript::builtins::shared_array_buffer::SharedArrayBuffer; #[cfg(feature = "array-buffer")] @@ -44,7 +46,6 @@ use crate::ecmascript::{ primitive_objects::PrimitiveObject, promise::Promise, proxy::Proxy, - regexp::RegExp, set::Set, Array, BuiltinConstructorFunction, BuiltinFunction, ECMAScriptFunction, }, @@ -105,6 +106,7 @@ pub struct HeapBits { pub promises: Box<[bool]>, pub proxys: Box<[bool]>, pub realms: Box<[bool]>, + #[cfg(feature = "regexp")] pub regexps: Box<[bool]>, pub scripts: Box<[bool]>, pub sets: Box<[bool]>, @@ -168,6 +170,7 @@ pub(crate) struct WorkQueues { pub promise_resolving_functions: Vec, pub proxys: Vec, pub realms: Vec, + #[cfg(feature = "regexp")] pub regexps: Vec, pub scripts: Vec, pub sets: Vec, @@ -231,6 +234,7 @@ impl HeapBits { let promises = vec![false; heap.promises.len()]; let proxys = vec![false; heap.proxys.len()]; let realms = vec![false; heap.realms.len()]; + #[cfg(feature = "regexp")] let regexps = vec![false; heap.regexps.len()]; let scripts = vec![false; heap.scripts.len()]; let sets = vec![false; heap.sets.len()]; @@ -291,6 +295,7 @@ impl HeapBits { promises: promises.into_boxed_slice(), proxys: proxys.into_boxed_slice(), realms: realms.into_boxed_slice(), + #[cfg(feature = "regexp")] regexps: regexps.into_boxed_slice(), scripts: scripts.into_boxed_slice(), sets: sets.into_boxed_slice(), @@ -359,6 +364,7 @@ impl WorkQueues { promises: Vec::with_capacity(heap.promises.len() / 4), proxys: Vec::with_capacity(heap.proxys.len() / 4), realms: Vec::with_capacity(heap.realms.len() / 4), + #[cfg(feature = "regexp")] regexps: Vec::with_capacity(heap.regexps.len() / 4), scripts: Vec::with_capacity(heap.scripts.len() / 4), sets: Vec::with_capacity(heap.sets.len() / 4), @@ -446,6 +452,7 @@ impl WorkQueues { promise_resolving_functions, proxys, realms, + #[cfg(feature = "regexp")] regexps, scripts, sets, @@ -480,6 +487,8 @@ impl WorkQueues { let weak_refs: &[bool; 0] = &[]; #[cfg(not(feature = "weak-refs"))] let weak_sets: &[bool; 0] = &[]; + #[cfg(not(feature = "regexp"))] + let regexps: &[bool; 0] = &[]; array_buffers.is_empty() && arrays.is_empty() @@ -731,6 +740,7 @@ pub(crate) struct CompactionLists { pub promises: CompactionList, pub proxys: CompactionList, pub realms: CompactionList, + #[cfg(feature = "regexp")] pub regexps: CompactionList, pub scripts: CompactionList, pub sets: CompactionList, @@ -807,6 +817,7 @@ impl CompactionLists { ), promises: CompactionList::from_mark_bits(&bits.promises), primitive_objects: CompactionList::from_mark_bits(&bits.primitive_objects), + #[cfg(feature = "regexp")] regexps: CompactionList::from_mark_bits(&bits.regexps), sets: CompactionList::from_mark_bits(&bits.sets), set_iterators: CompactionList::from_mark_bits(&bits.set_iterators), diff --git a/nova_vm/src/heap/heap_constants.rs b/nova_vm/src/heap/heap_constants.rs index f93e6fd95..f1101425e 100644 --- a/nova_vm/src/heap/heap_constants.rs +++ b/nova_vm/src/heap/heap_constants.rs @@ -32,6 +32,7 @@ pub(crate) enum IntrinsicObjectIndexes { DatePrototype, // Text processing + #[cfg(feature = "regexp")] RegExpPrototype, // Indexed collections @@ -155,6 +156,7 @@ pub(crate) enum IntrinsicConstructorIndexes { // Text processing String, + #[cfg(feature = "regexp")] RegExp, // Indexed collections @@ -249,6 +251,7 @@ pub(crate) enum IntrinsicFunctionIndexes { ObjectPrototypeToString, ParseFloat, ParseInt, + #[cfg(feature = "regexp")] RegExpPrototypeExec, SetPrototypeValues, StringPrototypeTrimEnd, diff --git a/nova_vm/src/heap/heap_gc.rs b/nova_vm/src/heap/heap_gc.rs index ab64372a7..8d8255d58 100644 --- a/nova_vm/src/heap/heap_gc.rs +++ b/nova_vm/src/heap/heap_gc.rs @@ -19,6 +19,8 @@ use super::{ }; #[cfg(feature = "date")] use crate::ecmascript::builtins::date::Date; +#[cfg(feature = "regexp")] +use crate::ecmascript::builtins::regexp::RegExp; #[cfg(feature = "shared-array-buffer")] use crate::ecmascript::builtins::shared_array_buffer::SharedArrayBuffer; #[cfg(feature = "array-buffer")] @@ -50,7 +52,6 @@ use crate::{ primitive_objects::PrimitiveObject, promise::Promise, proxy::Proxy, - regexp::RegExp, set::Set, Array, BuiltinConstructorFunction, BuiltinFunction, ECMAScriptFunction, }, @@ -170,6 +171,7 @@ pub fn heap_gc(agent: &mut Agent, root_realms: &mut [Option]) { promises, proxys, realms, + #[cfg(feature = "regexp")] regexps, scripts, sets, @@ -662,19 +664,22 @@ pub fn heap_gc(agent: &mut Agent, root_realms: &mut [Option]) { primitive_objects.get(index).mark_values(&mut queues); } }); - let mut regexp_marks: Box<[RegExp]> = queues.regexps.drain(..).collect(); - regexp_marks.sort(); - regexp_marks.iter().for_each(|&idx| { - let index = idx.get_index(); - if let Some(marked) = bits.regexps.get_mut(index) { - if *marked { - // Already marked, ignore - return; + #[cfg(feature = "regexp")] + { + let mut regexp_marks: Box<[RegExp]> = queues.regexps.drain(..).collect(); + regexp_marks.sort(); + regexp_marks.iter().for_each(|&idx| { + let index = idx.get_index(); + if let Some(marked) = bits.regexps.get_mut(index) { + if *marked { + // Already marked, ignore + return; + } + *marked = true; + regexps.get(index).mark_values(&mut queues); } - *marked = true; - regexps.get(index).mark_values(&mut queues); - } - }); + }); + } let mut set_marks: Box<[Set]> = queues.sets.drain(..).collect(); set_marks.sort(); set_marks.iter().for_each(|&idx| { @@ -1031,6 +1036,7 @@ fn sweep(agent: &mut Agent, bits: &HeapBits, root_realms: &mut [Option; pub type PrimitiveObjectIndex = BaseIndex; pub type PromiseIndex = BaseIndex; pub type ProxyIndex = BaseIndex; +#[cfg(feature = "regexp")] pub type RegExpIndex = BaseIndex; pub type SetIndex = BaseIndex; pub type SetIteratorIndex = BaseIndex;