From 2a5f3365646222372fcf3e89a7cb27ed65c825e1 Mon Sep 17 00:00:00 2001 From: Aapo Alasuutari Date: Thu, 16 Jan 2025 00:56:52 +0200 Subject: [PATCH] feat(gc): Object lifetime --- nova_cli/src/helper.rs | 13 +- nova_cli/src/main.rs | 16 +- .../operations_on_iterator_objects.rs | 74 +- .../operations_on_objects.rs | 142 +++- .../abstract_operations/type_conversion.rs | 33 +- .../builders/builtin_function_builder.rs | 6 +- .../builders/ordinary_object_builder.rs | 12 +- nova_vm/src/ecmascript/builtins/arguments.rs | 38 +- nova_vm/src/ecmascript/builtins/array.rs | 24 +- .../builtins/array/abstract_operations.rs | 15 +- .../src/ecmascript/builtins/array_buffer.rs | 17 +- .../src/ecmascript/builtins/bound_function.rs | 55 +- .../builtins/builtin_constructor.rs | 56 +- .../ecmascript/builtins/builtin_function.rs | 35 +- .../async_function_constructor.rs | 2 +- .../async_function_objects/await_reaction.rs | 2 +- .../async_generator_function_constructor.rs | 2 +- .../async_generator_objects.rs | 6 +- .../generator_function_constructor.rs | 3 +- .../generator_objects.rs | 57 +- .../generator_prototype.rs | 14 +- .../async_from_sync_iterator_prototype.rs | 6 +- .../iteration/async_iterator_prototype.rs | 2 +- .../iteration/iterator_prototype.rs | 2 +- .../promise_capability_records.rs | 2 +- .../promise_jobs.rs | 8 +- .../promise_resolving_functions.rs | 36 +- .../promise_objects/promise_constructor.rs | 36 +- .../promise_objects/promise_prototype.rs | 6 +- nova_vm/src/ecmascript/builtins/data_view.rs | 14 +- .../builtins/data_view/abstract_operations.rs | 2 +- nova_vm/src/ecmascript/builtins/date.rs | 14 +- .../builtins/ecmascript_function.rs | 89 +- .../ecmascript/builtins/embedder_object.rs | 12 +- nova_vm/src/ecmascript/builtins/error.rs | 42 +- .../builtins/finalization_registry.rs | 10 +- .../boolean_objects/boolean_constructor.rs | 2 +- .../boolean_objects/boolean_prototype.rs | 4 +- .../aggregate_error_constructors.rs | 2 +- .../error_objects/error_constructor.rs | 4 +- .../error_objects/error_prototype.rs | 2 +- .../native_error_constructors.rs | 24 +- .../function_objects/function_constructor.rs | 15 +- .../function_objects/function_prototype.rs | 14 +- .../object_objects/object_constructor.rs | 293 ++++--- .../object_objects/object_prototype.rs | 24 +- .../symbol_objects/symbol_constructor.rs | 6 +- .../symbol_objects/symbol_prototype.rs | 6 +- .../src/ecmascript/builtins/global_object.rs | 26 +- .../array_objects/array_constructor.rs | 73 +- .../array_iterator_objects/array_iterator.rs | 18 +- .../array_iterator_prototype.rs | 12 +- .../array_objects/array_prototype.rs | 785 +++++++++++------- .../abstract_operations.rs | 20 +- .../map_objects/map_constructor.rs | 36 +- .../map_iterator_objects/map_iterator.rs | 14 +- .../map_iterator_prototype.rs | 8 +- .../map_objects/map_prototype.rs | 20 +- .../set_objects/set_constructor.rs | 27 +- .../set_iterator_objects/set_iterator.rs | 14 +- .../set_iterator_prototype.rs | 8 +- .../set_objects/set_prototype.rs | 16 +- .../weak_map_objects/weak_map_constructor.rs | 2 +- .../weak_map_objects/weak_map_prototype.rs | 8 +- .../weak_set_objects/weak_set_constructor.rs | 2 +- .../weak_set_objects/weak_set_prototype.rs | 6 +- .../finalization_registry_constructor.rs | 2 +- .../finalization_registry_prototype.rs | 4 +- .../weak_ref_objects/weak_ref_constructor.rs | 2 +- .../weak_ref_objects/weak_ref_prototype.rs | 2 +- nova_vm/src/ecmascript/builtins/map.rs | 14 +- nova_vm/src/ecmascript/builtins/module.rs | 42 +- .../bigint_objects/bigint_constructor.rs | 6 +- .../bigint_objects/bigint_prototype.rs | 6 +- .../date_objects/date_constructor.rs | 8 +- .../date_objects/date_prototype.rs | 88 +- .../builtins/numbers_and_dates/math_object.rs | 70 +- .../number_objects/number_constructor.rs | 10 +- .../number_objects/number_prototype.rs | 12 +- nova_vm/src/ecmascript/builtins/ordinary.rs | 80 +- .../ecmascript/builtins/primitive_objects.rs | 53 +- nova_vm/src/ecmascript/builtins/promise.rs | 10 +- nova_vm/src/ecmascript/builtins/proxy.rs | 174 ++-- .../builtins/proxy/abstract_operations.rs | 12 +- nova_vm/src/ecmascript/builtins/proxy/data.rs | 4 +- .../builtins/reflection/proxy_constructor.rs | 4 +- .../builtins/reflection/reflect_object.rs | 57 +- nova_vm/src/ecmascript/builtins/regexp.rs | 20 +- .../builtins/regexp/abstract_operations.rs | 3 +- nova_vm/src/ecmascript/builtins/set.rs | 14 +- .../builtins/shared_array_buffer.rs | 10 +- .../array_buffer_constructor.rs | 8 +- .../array_buffer_prototype.rs | 18 +- .../structured_data/atomics_object.rs | 26 +- .../data_view_constructor.rs | 10 +- .../data_view_objects/data_view_prototype.rs | 46 +- .../builtins/structured_data/json_object.rs | 30 +- .../shared_array_buffer_constructor.rs | 4 +- .../shared_array_buffer_prototype.rs | 10 +- .../regexp_objects/regexp_constructor.rs | 4 +- .../regexp_objects/regexp_prototype.rs | 36 +- .../regexp_string_iterator_prototype.rs | 2 +- .../string_objects/string_constructor.rs | 13 +- .../string_objects/string_iterator_objects.rs | 2 +- .../string_objects/string_prototype.rs | 72 +- .../src/ecmascript/builtins/typed_array.rs | 12 +- nova_vm/src/ecmascript/builtins/weak_map.rs | 10 +- nova_vm/src/ecmascript/builtins/weak_ref.rs | 10 +- nova_vm/src/ecmascript/builtins/weak_set.rs | 10 +- nova_vm/src/ecmascript/execution/agent.rs | 18 +- .../src/ecmascript/execution/environments.rs | 24 +- .../environments/declarative_environment.rs | 2 +- .../environments/function_environment.rs | 12 +- .../environments/global_environment.rs | 50 +- .../environments/object_environment.rs | 28 +- .../ecmascript/execution/execution_context.rs | 5 +- nova_vm/src/ecmascript/execution/realm.rs | 49 +- .../ecmascript/execution/realm/intrinsics.rs | 2 +- .../ecmascript/scripts_and_modules/script.rs | 13 +- .../scripts_and_modules/source_code.rs | 2 +- .../class_definitions.rs | 38 +- .../function_definitions.rs | 16 +- .../src/ecmascript/types/language/function.rs | 62 +- .../types/language/function/into_function.rs | 28 +- .../src/ecmascript/types/language/object.rs | 574 ++++++------- .../ecmascript/types/language/object/data.rs | 2 +- .../types/language/object/internal_methods.rs | 82 +- .../types/language/object/internal_slots.rs | 6 +- .../types/language/object/into_object.rs | 6 +- .../types/language/object/property_storage.rs | 8 +- .../src/ecmascript/types/language/value.rs | 16 +- .../types/spec/property_descriptor.rs | 4 +- .../src/ecmascript/types/spec/reference.rs | 22 +- nova_vm/src/engine/bytecode/iterator.rs | 36 +- nova_vm/src/engine/bytecode/vm.rs | 46 +- .../src/engine/bytecode/vm/binding_methods.rs | 32 +- nova_vm/src/engine/rootable.rs | 10 +- nova_vm/src/engine/rootable/global.rs | 4 +- nova_vm/src/heap.rs | 2 +- nova_vm/src/heap/heap_gc.rs | 4 +- nova_vm/src/heap/indexes.rs | 24 +- nova_vm/tests/garbage_collection_tests.rs | 9 +- 142 files changed, 2615 insertions(+), 2045 deletions(-) diff --git a/nova_cli/src/helper.rs b/nova_cli/src/helper.rs index a24d8d662..d7424335c 100644 --- a/nova_cli/src/helper.rs +++ b/nova_cli/src/helper.rs @@ -7,14 +7,9 @@ use nova_vm::engine::context::GcScope; use oxc_diagnostics::OxcDiagnostic; /// Initialize the global object with the built-in functions. -pub fn initialize_global_object(agent: &mut Agent, global: Object, mut gc: GcScope<'_, '_>) { +pub fn initialize_global_object(agent: &mut Agent, global: Object, mut gc: GcScope) { // `print` function - fn print( - agent: &mut Agent, - _this: Value, - args: ArgumentsList, - gc: GcScope<'_, '_>, - ) -> JsResult { + fn print(agent: &mut Agent, _this: Value, args: ArgumentsList, gc: GcScope) -> JsResult { if args.len() == 0 { println!(); } else { @@ -28,7 +23,7 @@ pub fn initialize_global_object(agent: &mut Agent, global: Object, mut gc: GcSco agent: &mut Agent, _: Value, args: ArgumentsList, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { if args.len() != 1 { return Err(agent.throw_exception_with_static_message( @@ -55,7 +50,7 @@ pub fn initialize_global_object(agent: &mut Agent, global: Object, mut gc: GcSco agent: &mut Agent, _this: Value, args: ArgumentsList, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { let Value::ArrayBuffer(array_buffer) = args.get(0) else { return Err(agent.throw_exception_with_static_message( diff --git a/nova_cli/src/main.rs b/nova_cli/src/main.rs index 8f59f70bf..ac4d2b999 100644 --- a/nova_cli/src/main.rs +++ b/nova_cli/src/main.rs @@ -127,8 +127,12 @@ fn main() -> Result<(), Box> { host_hooks, ); assert!(!paths.is_empty()); - let create_global_object: Option) -> Object> = None; - let create_global_this_value: Option) -> Object> = None; + let create_global_object: Option< + for<'a> fn(&mut Agent, GcScope<'a, '_>) -> Object<'a>, + > = None; + let create_global_this_value: Option< + for<'a> fn(&mut Agent, GcScope<'a, '_>) -> Object<'a>, + > = None; let realm = agent.create_realm( create_global_object, create_global_this_value, @@ -205,8 +209,12 @@ fn main() -> Result<(), Box> { }, host_hooks, ); - let create_global_object: Option) -> Object> = None; - let create_global_this_value: Option) -> Object> = None; + let create_global_object: Option< + for<'a> fn(&mut Agent, GcScope<'a, '_>) -> Object<'a>, + > = None; + let create_global_this_value: Option< + for<'a> fn(&mut Agent, GcScope<'a, '_>) -> Object<'a>, + > = None; let realm = agent.create_realm( create_global_object, create_global_this_value, diff --git a/nova_vm/src/ecmascript/abstract_operations/operations_on_iterator_objects.rs b/nova_vm/src/ecmascript/abstract_operations/operations_on_iterator_objects.rs index 05685950f..a22b8c90e 100644 --- a/nova_vm/src/ecmascript/abstract_operations/operations_on_iterator_objects.rs +++ b/nova_vm/src/ecmascript/abstract_operations/operations_on_iterator_objects.rs @@ -8,7 +8,7 @@ use crate::{ ecmascript::{ abstract_operations::{ operations_on_objects::{call, call_function, get, get_method, try_get_method}, - type_conversion::{to_boolean, to_object}, + type_conversion::to_boolean, }, builtins::{ordinary::ordinary_object_create_with_intrinsics, ArgumentsList}, execution::{agent::ExceptionType, Agent, JsResult, ProtoIntrinsics}, @@ -27,7 +27,7 @@ use crate::{ /// AsyncIterator along with the next method. #[derive(Debug, Clone, Copy)] pub(crate) struct IteratorRecord { - pub(crate) iterator: Object, + pub(crate) iterator: Object<'static>, pub(crate) next_method: Value, pub(crate) done: bool, } @@ -42,25 +42,27 @@ pub(crate) fn get_iterator_from_method( agent: &mut Agent, obj: Value, method: Function, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { let method = method.bind(gc.nogc()); // 1. Let iterator be ? Call(method, obj). let iterator = call(agent, method.into(), obj, None, gc.reborrow())?; // 2. If iterator is not an Object, throw a TypeError exception. - let Ok(iterator) = to_object(agent, iterator, gc.nogc()) else { + let Ok(iterator) = Object::try_from(iterator) else { return Err(agent.throw_exception_with_static_message( ExceptionType::TypeError, "Iterator is not an object", gc.nogc(), )); }; + let iterator = iterator.bind(gc.nogc()); + let scoped_iterator = iterator.scope(agent, gc.nogc()); // 3. Let nextMethod be ? Get(iterator, "next"). let next_method = get( agent, - iterator, + iterator.unbind(), BUILTIN_STRING_MEMORY.next.into(), gc.reborrow(), )?; @@ -68,7 +70,7 @@ pub(crate) fn get_iterator_from_method( // 4. Let iteratorRecord be the Iterator Record { [[Iterator]]: iterator, [[NextMethod]]: nextMethod, [[Done]]: false }. // 5. Return iteratorRecord. Ok(IteratorRecord { - iterator, + iterator: scoped_iterator.get(agent).unbind(), next_method, done: false, }) @@ -83,7 +85,7 @@ pub(crate) fn get_iterator( agent: &mut Agent, obj: Value, is_async: bool, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { // 1. If kind is async, then let method = if is_async { @@ -152,12 +154,12 @@ pub(crate) fn get_iterator( /// Iterator Record) and optional argument value (an ECMAScript language value) /// and returns either a normal completion containing an Object or a throw /// completion. -pub(crate) fn iterator_next( +pub(crate) fn iterator_next<'a>( agent: &mut Agent, iterator_record: &IteratorRecord, value: Option, - mut gc: GcScope<'_, '_>, -) -> JsResult { + mut gc: GcScope<'a, '_>, +) -> JsResult> { // 1. If value is not present, then // a. Let result be ? Call(iteratorRecord.[[NextMethod]], iteratorRecord.[[Iterator]]). // 2. Else, @@ -191,7 +193,7 @@ pub(crate) fn iterator_next( pub(crate) fn iterator_complete( agent: &mut Agent, iter_result: Object, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { // 1. Return ToBoolean(? Get(iterResult, "done")). let done = get( @@ -211,7 +213,7 @@ pub(crate) fn iterator_complete( pub(crate) fn iterator_value( agent: &mut Agent, iter_result: Object, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { // 1. Return ? Get(iterResult, "value"). get( @@ -234,16 +236,19 @@ pub(crate) fn iterator_value( /// /// > NOTE: Instead of returning the boolean value false we return an Option /// > where the false state is None. That way we can pass the Object as is. -pub(crate) fn iterator_step( +pub(crate) fn iterator_step<'a>( agent: &mut Agent, iterator_record: &IteratorRecord, - mut gc: GcScope<'_, '_>, -) -> JsResult> { + mut gc: GcScope<'a, '_>, +) -> JsResult>> { // 1. Let result be ? IteratorNext(iteratorRecord). - let result = iterator_next(agent, iterator_record, None, gc.reborrow())?; + let result = iterator_next(agent, iterator_record, None, gc.reborrow())? + .unbind() + .bind(gc.nogc()); + let scoped_result = result.scope(agent, gc.nogc()); // 2. Let done be ? IteratorComplete(result). - let done = iterator_complete(agent, result, gc.reborrow())?; + let done = iterator_complete(agent, result.unbind(), gc.reborrow())?; // 3. If done is true, return false. if done { @@ -251,7 +256,7 @@ pub(crate) fn iterator_step( } // 4. Return result. - Ok(Some(result)) + Ok(Some(scoped_result.get(agent).bind(gc.into_nogc()))) } /// ### [7.4.8 IteratorStepValue ( iteratorRecord )](https://tc39.es/ecma262/#sec-iteratorstepvalue) @@ -265,7 +270,7 @@ pub(crate) fn iterator_step( pub(crate) fn iterator_step_value( agent: &mut Agent, iterator_record: &mut IteratorRecord, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult> { // 1. Let result be Completion(IteratorNext(iteratorRecord)). let result = iterator_next(agent, iterator_record, None, gc.reborrow()); @@ -280,11 +285,12 @@ pub(crate) fn iterator_step_value( return Err(err); } // 3. Set result to ! result. - Ok(result) => result, + Ok(result) => result.unbind().bind(gc.nogc()), }; + let scoped_result = result.scope(agent, gc.nogc()); // 4. Let done be Completion(IteratorComplete(result)). - let done = iterator_complete(agent, result, gc.reborrow()); + let done = iterator_complete(agent, result.unbind(), gc.reborrow()); // 5. If done is a throw completion, then let done = match done { @@ -311,7 +317,7 @@ pub(crate) fn iterator_step_value( // 8. Let value be Completion(Get(result, "value")). let value = get( agent, - result, + scoped_result.get(agent), BUILTIN_STRING_MEMORY.value.into(), gc.reborrow(), ); @@ -337,7 +343,7 @@ pub(crate) fn iterator_close( agent: &mut Agent, iterator_record: &IteratorRecord, completion: JsResult, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { // 1. Assert: iteratorRecord.[[Iterator]] is an Object. // 2. Let iterator be iteratorRecord.[[Iterator]]. @@ -395,7 +401,7 @@ pub(crate) fn try_iterator_close( agent: &mut Agent, iterator_record: &IteratorRecord, completion: JsResult, - gc: NoGcScope<'_, '_>, + gc: NoGcScope, ) -> TryResult> { // 1. Assert: iteratorRecord.[[Iterator]] is an Object. // 2. Let iterator be iteratorRecord.[[Iterator]]. @@ -439,7 +445,7 @@ pub(crate) fn if_abrupt_close_iterator( agent: &mut Agent, value: JsResult, iterator_record: &IteratorRecord, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { // 1. Assert: value is a Completion Record. // 2. If value is an abrupt completion, return ? IteratorClose(iteratorRecord, value). @@ -462,7 +468,7 @@ pub(crate) fn async_iterator_close( _agent: &mut Agent, _iterator_record: &IteratorRecord, _completion: JsResult, - _gc: GcScope<'_, '_>, + _gc: GcScope, ) -> JsResult { // 1. Assert: iteratorRecord.[[Iterator]] is an Object. // 2. Let iterator be iteratorRecord.[[Iterator]]. @@ -485,9 +491,15 @@ pub(crate) fn async_iterator_close( /// ECMAScript language value) and done (a Boolean) and returns an Object that /// conforms to the IteratorResult interface. It creates an object that /// conforms to the IteratorResult interface. -pub(crate) fn create_iter_result_object(agent: &mut Agent, value: Value, done: bool) -> Object { +pub(crate) fn create_iter_result_object<'a>( + agent: &mut Agent, + value: Value, + done: bool, + gc: NoGcScope<'a, '_>, +) -> Object<'a> { // 1. Let obj be OrdinaryObjectCreate(%Object.prototype%). - let obj = ordinary_object_create_with_intrinsics(agent, Some(ProtoIntrinsics::Object), None); + let obj = + ordinary_object_create_with_intrinsics(agent, Some(ProtoIntrinsics::Object), None, gc); // 2. Perform ! CreateDataPropertyOrThrow(obj, "value", value). obj.property_storage().set( agent, @@ -513,7 +525,7 @@ pub(crate) fn create_iter_result_object(agent: &mut Agent, value: Value, done: b pub(crate) fn create_list_iterator_record( _agent: &mut Agent, _list: &[Value], - _gc: GcScope<'_, '_>, + _gc: GcScope, ) -> JsResult { // 1. Let closure be a new Abstract Closure with no parameters that captures list and performs the following steps when called: // a. For each element E of list, do @@ -532,7 +544,7 @@ pub(crate) fn create_list_iterator_record( pub(crate) fn iterator_to_list( agent: &mut Agent, iterator_record: &IteratorRecord, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult> { // 1. Let values be a new empty List. let mut values = Vec::new(); @@ -544,7 +556,7 @@ pub(crate) fn iterator_to_list( while let Some(next) = iterator_step(agent, iterator_record, gc.reborrow())? { // i. Let nextValue be ? IteratorValue(next). // ii. Append nextValue to values. - values.push(iterator_value(agent, next, gc.reborrow())?); + values.push(iterator_value(agent, next.unbind(), gc.reborrow())?); } // 4. Return values. diff --git a/nova_vm/src/ecmascript/abstract_operations/operations_on_objects.rs b/nova_vm/src/ecmascript/abstract_operations/operations_on_objects.rs index a31b143be..7fb0b11db 100644 --- a/nova_vm/src/ecmascript/abstract_operations/operations_on_objects.rs +++ b/nova_vm/src/ecmascript/abstract_operations/operations_on_objects.rs @@ -9,7 +9,7 @@ use ahash::AHashSet; use super::{ operations_on_iterator_objects::{get_iterator, if_abrupt_close_iterator, iterator_close}, testing_and_comparison::{is_callable, require_object_coercible, same_value}, - type_conversion::{to_length, to_object, to_property_key}, + type_conversion::{to_length, to_object, to_property_key, try_to_length}, }; use crate::{ ecmascript::types::{bind_property_keys, scope_property_keys, unbind_property_keys}, @@ -57,7 +57,7 @@ use crate::{ /// > overriding some or all of that object's internal methods. In order to /// > encapsulate exotic object creation, the object's essential internal /// > methods are never modified outside those operations. -pub(crate) fn make_basic_object(_agent: &mut Agent, _internal_slots_list: ()) -> Object { +pub(crate) fn make_basic_object(_agent: &mut Agent, _internal_slots_list: ()) -> Object<'static> { // 1. Let obj be a newly created object with an internal slot for each name in internalSlotsList. // 2. Set obj's essential internal methods to the default ordinary object definitions specified in 10.1. // 3. Assert: If the caller will not be overriding both obj's [[GetPrototypeOf]] and [[SetPrototypeOf]] essential @@ -76,9 +76,9 @@ pub(crate) fn make_basic_object(_agent: &mut Agent, _internal_slots_list: ()) -> /// language value or a throw completion. It is used to retrieve the value of a /// specific property of an object. #[inline] -pub(crate) fn get( +pub(crate) fn get<'a>( agent: &mut Agent, - o: impl IntoObject, + o: impl IntoObject<'a>, p: PropertyKey, gc: GcScope, ) -> JsResult { @@ -95,9 +95,9 @@ pub(crate) fn get( /// language value or a throw completion. It is used to retrieve the value of a /// specific property of an object. #[inline] -pub(crate) fn try_get( +pub(crate) fn try_get<'a>( agent: &mut Agent, - o: impl IntoObject, + o: impl IntoObject<'a>, p: PropertyKey, gc: NoGcScope, ) -> TryResult { @@ -117,7 +117,7 @@ pub(crate) fn get_v(agent: &mut Agent, v: Value, p: PropertyKey, gc: GcScope) -> let mut p = p.bind(gc.nogc()); // 1. Let O be ? ToObject(V). let o = if let Ok(o) = Object::try_from(v) { - o + o.bind(gc.nogc()) } else { let scoped_p = p.scope(agent, gc.nogc()); let o = to_object(agent, v, gc.nogc())?; @@ -125,7 +125,7 @@ pub(crate) fn get_v(agent: &mut Agent, v: Value, p: PropertyKey, gc: GcScope) -> o }; // 2. Return ? O.[[Get]](P, V). - o.internal_get(agent, p.unbind(), o.into(), gc) + o.unbind().internal_get(agent, p.unbind(), o.into(), gc) } /// ### Try [7.3.3 GetV ( V, P )](https://tc39.es/ecma262/#sec-getv) @@ -228,9 +228,9 @@ pub(crate) fn try_set( /// > assignment operator. Normally, the property will not already exist. If it /// > does exist and is not configurable or if O is not extensible, /// > [\[DefineOwnProperty]] will return false. -pub(crate) fn try_create_data_property( +pub(crate) fn try_create_data_property<'a>( agent: &mut Agent, - object: impl InternalMethods, + object: impl InternalMethods<'a>, property_key: PropertyKey, value: Value, gc: NoGcScope, @@ -260,9 +260,9 @@ pub(crate) fn try_create_data_property( /// > assignment operator. Normally, the property will not already exist. If it /// > does exist and is not configurable or if O as not extensible, /// > [\[DefineOwnProperty]] will return false. -pub(crate) fn create_data_property( +pub(crate) fn create_data_property<'a>( agent: &mut Agent, - object: impl InternalMethods, + object: impl InternalMethods<'a>, property_key: PropertyKey, value: Value, gc: GcScope, @@ -288,9 +288,9 @@ pub(crate) fn create_data_property( /// returns either a normal completion containing UNUSED or a throw completion. /// It is used to create a new own property of an object. at throws a TypeError /// exception if the requested property update cannot be performed. -pub(crate) fn try_create_data_property_or_throw( +pub(crate) fn try_create_data_property_or_throw<'a>( agent: &mut Agent, - object: impl InternalMethods, + object: impl InternalMethods<'a>, property_key: PropertyKey, value: Value, gc: NoGcScope, @@ -317,9 +317,9 @@ pub(crate) fn try_create_data_property_or_throw( /// returns either a normal completion containing UNUSED or a throw completion. /// It is used to create a new own property of an object. at throws a TypeError /// exception if the requested property update cannot be performed. -pub(crate) fn create_data_property_or_throw( +pub(crate) fn create_data_property_or_throw<'a>( agent: &mut Agent, - object: impl InternalMethods, + object: impl InternalMethods<'a>, property_key: PropertyKey, value: Value, mut gc: GcScope, @@ -352,9 +352,9 @@ pub(crate) fn create_data_property_or_throw( /// call the \[\[DefineOwnProperty]] internal method of an object in a manner /// that will throw a TypeError exception if tae requested property update /// cannot be performed. -pub(crate) fn try_define_property_or_throw( +pub(crate) fn try_define_property_or_throw<'a>( agent: &mut Agent, - object: impl InternalMethods, + object: impl InternalMethods<'a>, property_key: PropertyKey, desc: PropertyDescriptor, gc: NoGcScope, @@ -382,9 +382,9 @@ pub(crate) fn try_define_property_or_throw( /// call the \[\[DefineOwnProperty]] internal method of an object in a manner /// that will throw a TypeError exception if tae requested property update /// cannot be performed. -pub(crate) fn define_property_or_throw( +pub(crate) fn define_property_or_throw<'a>( agent: &mut Agent, - object: impl InternalMethods, + object: impl InternalMethods<'a>, property_key: PropertyKey, desc: PropertyDescriptor, mut gc: GcScope, @@ -412,9 +412,9 @@ pub(crate) fn define_property_or_throw( /// and P (a property key) and returns either a normal completion containing /// unused or a throw completion. It is used to removeaa specific own property /// of an object. It throws an exception if the property is not configurable. -pub(crate) fn try_delete_property_or_throw( +pub(crate) fn try_delete_property_or_throw<'a>( agent: &mut Agent, - o: impl InternalMethods, + o: impl InternalMethods<'a>, p: PropertyKey, gc: NoGcScope, ) -> TryResult> { @@ -439,9 +439,9 @@ pub(crate) fn try_delete_property_or_throw( /// and P (a property key) and returns either a normal completion containing /// unused or a throw completion. It is used to remove a specific own property /// of an object. It throws an exception if the property is not configurable. -pub(crate) fn delete_property_or_throw( +pub(crate) fn delete_property_or_throw<'a>( agent: &mut Agent, - o: impl InternalMethods, + o: impl InternalMethods<'a>, p: PropertyKey, mut gc: GcScope, ) -> JsResult<()> { @@ -1006,6 +1006,32 @@ pub(crate) fn length_of_array_like( to_length(agent, property, gc) } +/// ### [7.3.18 LengthOfArrayLike ( obj )](https://tc39.es/ecma262/#sec-lengthofarraylike) +/// +/// The abstract operation LengthOfArrayLike takes argument obj (an Object) and +/// returns either a normal completion containing a non-negative integer or a +/// throw completion. It returns the value of the "length" property of an +/// array-like object. +pub(crate) fn try_length_of_array_like( + agent: &mut Agent, + obj: Object, + gc: NoGcScope, +) -> TryResult> { + // NOTE: Fast path for Array objects. + if let Ok(array) = Array::try_from(obj) { + return TryResult::Continue(Ok(array.len(agent) as i64)); + } + + // 1. Return โ„(? ToLength(? Get(obj, "length"))). + let property = try_get( + agent, + obj, + PropertyKey::from(BUILTIN_STRING_MEMORY.length), + gc, + )?; + try_to_length(agent, property, gc) +} + /// ### [7.3.19 CreateListFromArrayLike ( obj [ , elementTypes ] )](https://tc39.es/ecma262/#sec-createlistfromarraylike) /// /// The abstract operation CreateListFromArrayLike takes argument obj (an ECMAScript language value) @@ -1078,13 +1104,13 @@ pub(crate) fn call_function( result } -pub(crate) fn construct( +pub(crate) fn construct<'a>( agent: &mut Agent, f: Function, arguments_list: Option, new_target: Option, - gc: GcScope, -) -> JsResult { + gc: GcScope<'a, '_>, +) -> JsResult> { let f = f.bind(gc.nogc()); // 1. If newTarget is not present, set newTarget to F. let new_target = new_target.unwrap_or(f); @@ -1170,9 +1196,10 @@ pub(crate) fn ordinary_has_instance<'a, 'b>( pub(crate) fn is_prototype_of_loop( agent: &mut Agent, o: Object, - mut v: Object, + v: Object, mut gc: GcScope, ) -> JsResult { + let mut v = v.bind(gc.nogc()); { let gc = gc.nogc(); loop { @@ -1192,7 +1219,11 @@ pub(crate) fn is_prototype_of_loop( } let o = o.scope(agent, gc.nogc()); loop { - let proto = v.internal_get_prototype_of(agent, gc.reborrow())?; + let proto = v + .unbind() + .internal_get_prototype_of(agent, gc.reborrow())? + .map(|f| f.unbind()) + .map(|f| f.bind(gc.nogc())); if let Some(proto) = proto { v = proto; if o.get(agent) == v { @@ -1242,7 +1273,7 @@ pub(crate) mod enumerable_properties_kind { /// ECMAScript property keys or a throw completion. pub(crate) fn scoped_enumerable_own_keys<'a>( agent: &mut Agent, - o: Scoped<'a, Object>, + o: Scoped<'a, Object<'static>>, mut gc: GcScope<'_, 'a>, ) -> JsResult>>> { // Note: Only Proxy and possibly Module and EmbedderObject can run JS in @@ -1515,7 +1546,10 @@ fn enumerable_own_properties_slow( /// The abstract operation GetFunctionRealm takes argument obj (a function /// object) and returns either a normal completion containing a Realm Record or /// a throw completion. -pub(crate) fn get_function_realm(agent: &Agent, obj: impl IntoObject) -> JsResult { +pub(crate) fn get_function_realm<'a>( + agent: &Agent, + obj: impl IntoObject<'a>, +) -> JsResult { // 1. If obj has a [[Realm]] internal slot, then // a. Return obj.[[Realm]]. let obj = obj.into_object(); @@ -1554,18 +1588,33 @@ pub(crate) fn copy_data_properties( source: Value, mut gc: GcScope, ) -> JsResult<()> { + let mut target = target.bind(gc.nogc()); // 1. If source is either undefined or null, return unused. if source.is_undefined() || source.is_null() { return Ok(()); } // 2. Let from be ! ToObject(source). - let from = to_object(agent, source, gc.nogc()).unwrap(); + let mut from = to_object(agent, source, gc.nogc()).unwrap(); + let mut scoped_target = None; + let mut scoped_from = None; // 3. Let keys be ? from.[[OwnPropertyKeys]](). - let mut keys = bind_property_keys( - unbind_property_keys(from.internal_own_property_keys(agent, gc.reborrow())?), - gc.nogc(), - ); + let mut keys = if let TryResult::Continue(keys) = from.try_own_property_keys(agent, gc.nogc()) { + keys + } else { + scoped_target = Some(target.scope(agent, gc.nogc())); + scoped_from = Some(from.scope(agent, gc.nogc())); + let keys = bind_property_keys( + unbind_property_keys( + from.unbind() + .internal_own_property_keys(agent, gc.reborrow())?, + ), + gc.nogc(), + ); + target = scoped_target.as_ref().unwrap().get(agent).bind(gc.nogc()); + from = scoped_from.as_ref().unwrap().get(agent).bind(gc.nogc()); + keys + }; // Reserve space in the target's vectors. { let new_size = agent[target] @@ -1612,6 +1661,8 @@ pub(crate) fn copy_data_properties( if broke { let _ = keys.drain(..i); let keys = unbind_property_keys(keys); + let target = scoped_target.unwrap_or_else(|| target.scope(agent, gc.nogc())); + let from = scoped_from.unwrap_or_else(|| from.scope(agent, gc.nogc())); copy_data_properties_slow(agent, target, from, keys, gc) } else { // 5. Return UNUSED. @@ -1621,8 +1672,8 @@ pub(crate) fn copy_data_properties( fn copy_data_properties_slow( agent: &mut Agent, - target: OrdinaryObject, - from: Object, + target: Scoped<'_, OrdinaryObject<'static>>, + from: Scoped<'_, Object<'static>>, keys: Vec, mut gc: GcScope, ) -> JsResult<()> { @@ -1631,15 +1682,16 @@ fn copy_data_properties_slow( // i. Let desc be ? from.[[GetOwnProperty]](nextKey). // ii. If desc is not undefined and desc.[[Enumerable]] is true, then if let Some(dest) = - from.internal_get_own_property(agent, next_key.get(agent), gc.reborrow())? + from.get(agent) + .internal_get_own_property(agent, next_key.get(agent), gc.reborrow())? { if dest.enumerable.unwrap() { // 1. Let propValue be ? Get(from, nextKey). - let prop_value = get(agent, from, next_key.get(agent), gc.reborrow())?; + let prop_value = get(agent, from.get(agent), next_key.get(agent), gc.reborrow())?; // 2. Perform ! CreateDataPropertyOrThrow(target, nextKey, propValue). create_data_property( agent, - target, + target.get(agent), next_key.get(agent), prop_value, gc.reborrow(), @@ -1660,9 +1712,9 @@ fn copy_data_properties_slow( /// NOTE: This implementation of CopyDataProperties also creates the target object with /// `OrdinaryObjectCreate(%Object.prototype%)`. This can be used to implement the rest operator in /// object destructuring, but not the spread operator in object literals. -pub(crate) fn try_copy_data_properties_into_object<'a>( +pub(crate) fn try_copy_data_properties_into_object<'a, 'b>( agent: &mut Agent, - source: impl IntoObject, + source: impl IntoObject<'b>, excluded_items: &AHashSet, gc: NoGcScope<'a, '_>, ) -> TryResult> { @@ -1717,9 +1769,9 @@ pub(crate) fn try_copy_data_properties_into_object<'a>( /// NOTE: This implementation of CopyDataProperties also creates the target object with /// `OrdinaryObjectCreate(%Object.prototype%)`. This can be used to implement the rest operator in /// object destructuring, but not the spread operator in object literals. -pub(crate) fn copy_data_properties_into_object<'a>( +pub(crate) fn copy_data_properties_into_object<'a, 'b>( agent: &mut Agent, - source: impl IntoObject, + source: impl IntoObject<'b>, excluded_items: &AHashSet>, mut gc: GcScope<'a, '_>, ) -> JsResult> { diff --git a/nova_vm/src/ecmascript/abstract_operations/type_conversion.rs b/nova_vm/src/ecmascript/abstract_operations/type_conversion.rs index 16fe167cd..469988306 100644 --- a/nova_vm/src/ecmascript/abstract_operations/type_conversion.rs +++ b/nova_vm/src/ecmascript/abstract_operations/type_conversion.rs @@ -125,9 +125,9 @@ pub(crate) fn to_primitive<'a>( } } -pub(crate) fn to_primitive_object<'a>( +pub(crate) fn to_primitive_object<'a, 'b>( agent: &mut Agent, - input: impl IntoObject, + input: impl IntoObject<'b>, preferred_type: Option, mut gc: GcScope<'a, '_>, ) -> JsResult> { @@ -1079,7 +1079,11 @@ pub(crate) fn to_string_primitive<'gc>( /// language value) and returns either a normal completion containing an Object /// or a throw completion. It converts argument to a value of type Object /// according to [Table 13](https://tc39.es/ecma262/#table-toobject-conversions): -pub(crate) fn to_object(agent: &mut Agent, argument: Value, gc: NoGcScope) -> JsResult { +pub(crate) fn to_object<'a>( + agent: &mut Agent, + argument: Value, + gc: NoGcScope<'a, '_>, +) -> JsResult> { match argument { Value::Undefined | Value::Null => Err(agent.throw_exception_with_static_message( ExceptionType::TypeError, @@ -1302,6 +1306,29 @@ pub(crate) fn to_length(agent: &mut Agent, argument: Value, gc: GcScope) -> JsRe Ok(len.min(SmallInteger::MAX_NUMBER)) } +/// ### [7.1.20 ToLength ( argument )](https://tc39.es/ecma262/#sec-tolength) +pub(crate) fn try_to_length( + agent: &mut Agent, + argument: Value, + gc: NoGcScope, +) -> TryResult> { + // TODO: This can be heavily optimized by inlining `to_integer_or_infinity`. + + // 1. Let len be ? ToIntegerOrInfinity(argument). + let len = match try_to_integer_or_infinity(agent, argument, gc)? { + Ok(len) => len.into_i64(), + Err(err) => return TryResult::Continue(Err(err)), + }; + + // 2. If len โ‰ค 0, return +0๐”ฝ. + if len <= 0 { + return TryResult::Continue(Ok(0)); + } + + // 3. Return ๐”ฝ(min(len, 2**53 - 1)). + TryResult::Continue(Ok(len.min(SmallInteger::MAX_NUMBER))) +} + /// ### [7.1.21 CanonicalNumericIndexString ( argument )](https://tc39.es/ecma262/#sec-canonicalnumericindexstring) pub(crate) fn canonical_numeric_index_string<'gc>( agent: &mut Agent, diff --git a/nova_vm/src/ecmascript/builders/builtin_function_builder.rs b/nova_vm/src/ecmascript/builders/builtin_function_builder.rs index 04683e8e6..596ae76fc 100644 --- a/nova_vm/src/ecmascript/builders/builtin_function_builder.rs +++ b/nova_vm/src/ecmascript/builders/builtin_function_builder.rs @@ -26,7 +26,7 @@ use super::property_builder::{self, PropertyBuilder}; pub struct NoPrototype; #[derive(Clone, Copy)] -pub struct CreatorPrototype(Option); +pub struct CreatorPrototype(Option>); #[derive(Default, Clone, Copy)] pub struct NoLength; @@ -187,7 +187,7 @@ impl<'agent, L, N, B, Pr> BuiltinFunctionBuilder<'agent, NoPrototype, L, N, B, P #[must_use] pub fn with_prototype( self, - prototype: Object, + prototype: Object<'static>, ) -> BuiltinFunctionBuilder<'agent, CreatorPrototype, L, N, B, Pr> { let object_index = if prototype != self @@ -451,7 +451,7 @@ impl<'agent, P, L, N, B> BuiltinFunctionBuilder<'agent, P, L, N, B, CreatorPrope } #[must_use] - pub fn with_prototype_property(mut self, prototype: Object) -> Self { + pub fn with_prototype_property(mut self, prototype: Object<'static>) -> Self { let property = PropertyBuilder::new(self.agent) .with_configurable(false) .with_enumerable(false) diff --git a/nova_vm/src/ecmascript/builders/ordinary_object_builder.rs b/nova_vm/src/ecmascript/builders/ordinary_object_builder.rs index 5245fbf49..5a8a2f94b 100644 --- a/nova_vm/src/ecmascript/builders/ordinary_object_builder.rs +++ b/nova_vm/src/ecmascript/builders/ordinary_object_builder.rs @@ -23,7 +23,7 @@ use super::{ pub struct NoPrototype; #[derive(Clone, Copy)] -pub struct CreatorPrototype(T); +pub struct CreatorPrototype>(T); #[derive(Default, Clone, Copy)] pub struct NoProperties; @@ -94,7 +94,7 @@ impl<'agent, P, Pr> OrdinaryObjectBuilder<'agent, P, Pr> { impl<'agent, Pr> OrdinaryObjectBuilder<'agent, NoPrototype, Pr> { #[must_use] - pub fn with_prototype( + pub fn with_prototype>( self, prototype: T, ) -> OrdinaryObjectBuilder<'agent, CreatorPrototype, Pr> { @@ -280,7 +280,9 @@ impl<'agent> OrdinaryObjectBuilder<'agent, NoPrototype, NoProperties> { } } -impl<'agent, T: IntoObject> OrdinaryObjectBuilder<'agent, CreatorPrototype, NoProperties> { +impl<'agent, T: IntoObject<'static>> + OrdinaryObjectBuilder<'agent, CreatorPrototype, NoProperties> +{ pub fn build(self) -> OrdinaryObject<'static> { let (keys, values) = self.agent.heap.elements.create_with_stuff(vec![]); let slot = self @@ -336,7 +338,9 @@ impl<'agent> OrdinaryObjectBuilder<'agent, NoPrototype, CreatorProperties> { } } -impl<'agent, T: IntoObject> OrdinaryObjectBuilder<'agent, CreatorPrototype, CreatorProperties> { +impl<'agent, T: IntoObject<'static>> + OrdinaryObjectBuilder<'agent, CreatorPrototype, CreatorProperties> +{ pub fn build(self) -> OrdinaryObject<'static> { assert_eq!(self.properties.0.len(), self.properties.0.capacity()); { diff --git a/nova_vm/src/ecmascript/builtins/arguments.rs b/nova_vm/src/ecmascript/builtins/arguments.rs index 6d7c92a1c..e1f84df5f 100644 --- a/nova_vm/src/ecmascript/builtins/arguments.rs +++ b/nova_vm/src/ecmascript/builtins/arguments.rs @@ -26,11 +26,12 @@ //! //! ECMAScript implementations of arguments exotic objects have historically contained an accessor property named "caller". Prior to ECMAScript 2017, this specification included the definition of a throwing "caller" property on ordinary arguments objects. Since implementations do not contain this extension any longer, ECMAScript 2017 dropped the requirement for a throwing "caller" accessor. -use crate::engine::context::GcScope; +use crate::engine::context::NoGcScope; +use crate::engine::unwrap_try; use crate::{ ecmascript::{ abstract_operations::operations_on_objects::{ - create_data_property_or_throw, define_property_or_throw, + try_create_data_property_or_throw, try_define_property_or_throw, }, execution::{agent::Agent, ProtoIntrinsics}, types::{ @@ -121,23 +122,24 @@ use super::ordinary::ordinary_object_create_with_intrinsics; /// The abstract operation CreateUnmappedArgumentsObject takes argument /// argumentsList (a List of ECMAScript language values) and returns an /// ordinary object. -pub(crate) fn create_unmapped_arguments_object( +pub(crate) fn create_unmapped_arguments_object<'a>( agent: &mut Agent, arguments_list: &[Value], - mut gc: GcScope<'_, '_>, -) -> Object { + gc: NoGcScope<'a, '_>, +) -> Object<'a> { // 1. Let len be the number of elements in argumentsList. let len = arguments_list.len(); - let len = Number::from_f64(agent, len as f64, gc.nogc()).into_value(); + let len = Number::from_f64(agent, len as f64, gc).into_value(); // 2. Let obj be OrdinaryObjectCreate(%Object.prototype%, ยซ [[ParameterMap]] ยป). - let obj = ordinary_object_create_with_intrinsics(agent, Some(ProtoIntrinsics::Object), None); + let obj = + ordinary_object_create_with_intrinsics(agent, Some(ProtoIntrinsics::Object), None, gc); let Object::Object(obj) = obj else { unreachable!() }; // 3. Set obj.[[ParameterMap]] to undefined. // 4. Perform ! DefinePropertyOrThrow(obj, "length", PropertyDescriptor { let key = PropertyKey::from(BUILTIN_STRING_MEMORY.length); - define_property_or_throw( + unwrap_try(try_define_property_or_throw( agent, obj, key, @@ -152,25 +154,25 @@ pub(crate) fn create_unmapped_arguments_object( configurable: Some(true), ..Default::default() }, - gc.reborrow(), - ) + gc, + )) .unwrap(); // 5. Let index be 0. // 6. Repeat, while index < len, - for (index, val) in arguments_list.iter().enumerate() { + for (index, &val) in arguments_list.iter().enumerate() { // a. Let val be argumentsList[index]. // b. Perform ! CreateDataPropertyOrThrow(obj, ! ToString(๐”ฝ(index)), val). debug_assert!(index < u32::MAX as usize); let index = index as u32; let key = PropertyKey::Integer(index.into()); - create_data_property_or_throw(agent, obj, key, *val, gc.reborrow()).unwrap(); + unwrap_try(try_create_data_property_or_throw(agent, obj, key, val, gc)).unwrap(); // c. Set index to index + 1. } // 7. Perform ! DefinePropertyOrThrow(obj, @@iterator, PropertyDescriptor { let key = PropertyKey::Symbol(WellKnownSymbolIndexes::Iterator.into()); // TODO: "as if the property was accessed prior to any ECMAScript code being evaluated" // let array_prototype_values = agent.current_realm().intrinsics().array_prototype(); - define_property_or_throw( + unwrap_try(try_define_property_or_throw( agent, obj, key, @@ -191,13 +193,13 @@ pub(crate) fn create_unmapped_arguments_object( configurable: Some(true), ..Default::default() }, - gc.reborrow(), - ) + gc, + )) .unwrap(); let throw_type_error = agent.current_realm().intrinsics().throw_type_error(); // 8. Perform ! DefinePropertyOrThrow(obj, "callee", PropertyDescriptor { let key = PropertyKey::from(BUILTIN_STRING_MEMORY.callee); - define_property_or_throw( + unwrap_try(try_define_property_or_throw( agent, obj, key, @@ -212,8 +214,8 @@ pub(crate) fn create_unmapped_arguments_object( configurable: Some(false), ..Default::default() }, - gc.reborrow(), - ) + gc, + )) .unwrap(); // 9. Return obj. Object::Arguments(obj) diff --git a/nova_vm/src/ecmascript/builtins/array.rs b/nova_vm/src/ecmascript/builtins/array.rs index 6520f8bed..d2ba6c63c 100644 --- a/nova_vm/src/ecmascript/builtins/array.rs +++ b/nova_vm/src/ecmascript/builtins/array.rs @@ -196,8 +196,8 @@ impl IntoValue for Array<'_> { } } -impl IntoObject for Array<'_> { - fn into_object(self) -> Object { +impl<'a> IntoObject<'a> for Array<'a> { + fn into_object(self) -> Object<'a> { self.into() } } @@ -208,7 +208,7 @@ impl<'a> From> for Array<'a> { } } -impl From> for Object { +impl<'a> From> for Object<'a> { fn from(value: Array) -> Self { Self::Array(value.unbind()) } @@ -231,10 +231,10 @@ impl TryFrom for Array<'_> { } } -impl TryFrom for Array<'_> { +impl<'a> TryFrom> for Array<'a> { type Error = (); - fn try_from(value: Object) -> Result { + fn try_from(value: Object<'a>) -> Result { match value { Object::Array(data) => Ok(data), _ => Err(()), @@ -242,7 +242,7 @@ impl TryFrom for Array<'_> { } } -impl InternalSlots for Array<'_> { +impl<'a> InternalSlots<'a> for Array<'a> { const DEFAULT_PROTOTYPE: ProtoIntrinsics = ProtoIntrinsics::Array; #[inline(always)] @@ -283,7 +283,7 @@ impl InternalSlots for Array<'_> { } } -impl InternalMethods for Array<'_> { +impl<'a> InternalMethods<'a> for Array<'a> { fn try_get_own_property( self, agent: &mut Agent, @@ -494,7 +494,9 @@ impl InternalMethods for Array<'_> { // 4. If parent is not null, then if let Some(parent) = parent { // a. Return ? parent.[[HasProperty]](P). - return parent.internal_has_property(agent, property_key.unbind(), gc); + return parent + .unbind() + .internal_has_property(agent, property_key.unbind(), gc); } // 5. Return false. @@ -669,11 +671,11 @@ impl InternalMethods for Array<'_> { } } - fn try_own_property_keys<'a>( + fn try_own_property_keys<'gc>( self, agent: &mut Agent, - gc: NoGcScope<'a, '_>, - ) -> TryResult>> { + gc: NoGcScope<'gc, '_>, + ) -> TryResult>> { let backing_keys = if let Some(backing_object) = self.get_backing_object(agent) { unwrap_try(backing_object.try_own_property_keys(agent, gc)) } else { diff --git a/nova_vm/src/ecmascript/builtins/array/abstract_operations.rs b/nova_vm/src/ecmascript/builtins/array/abstract_operations.rs index 6f3b6b90c..be1a7fa42 100644 --- a/nova_vm/src/ecmascript/builtins/array/abstract_operations.rs +++ b/nova_vm/src/ecmascript/builtins/array/abstract_operations.rs @@ -91,23 +91,24 @@ pub(crate) fn array_create<'a>( /// > execution context. This maintains compatibility with Web browsers that /// > have historically had that behaviour for the Array.prototype methods /// > that now are defined using ArraySpeciesCreate. -pub(crate) fn array_species_create( +pub(crate) fn array_species_create<'a>( agent: &mut Agent, original_array: Object, length: usize, - mut gc: GcScope<'_, '_>, -) -> JsResult { + mut gc: GcScope<'a, '_>, +) -> JsResult> { + let original_array = original_array.bind(gc.nogc()); // 1. Let isArray be ? IsArray(originalArray). let original_is_array = is_array(agent, original_array.into_value(), gc.nogc())?; // 2. If isArray is false, return ? ArrayCreate(length). if !original_is_array { - let new_array = array_create(agent, length, length, None, gc.nogc())?; + let new_array = array_create(agent, length, length, None, gc.into_nogc())?; return Ok(new_array.into_object()); } // 3. Let C be ? Get(originalArray, "constructor"). let mut c = get( agent, - original_array, + original_array.unbind(), BUILTIN_STRING_MEMORY.constructor.into(), gc.reborrow(), )?; @@ -141,7 +142,7 @@ pub(crate) fn array_species_create( } // 6. If C is undefined, return ? ArrayCreate(length). if c.is_undefined() { - let new_array = array_create(agent, length, length, None, gc.nogc())?; + let new_array = array_create(agent, length, length, None, gc.into_nogc())?; return Ok(new_array.into_object()); } // 7. If IsConstructor(C) is false, throw a TypeError exception. @@ -164,7 +165,7 @@ pub(crate) fn array_set_length( agent: &mut Agent, a: Array, desc: PropertyDescriptor, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { let a = a.bind(gc.nogc()); // 1. If Desc does not have a [[Value]] field, then diff --git a/nova_vm/src/ecmascript/builtins/array_buffer.rs b/nova_vm/src/ecmascript/builtins/array_buffer.rs index 7effd9570..d9e0f3ce7 100644 --- a/nova_vm/src/ecmascript/builtins/array_buffer.rs +++ b/nova_vm/src/ecmascript/builtins/array_buffer.rs @@ -102,12 +102,7 @@ impl<'a> ArrayBuffer<'a> { } } - pub fn detach( - self, - agent: &mut Agent, - key: Option, - gc: NoGcScope<'_, '_>, - ) -> JsResult<()> { + pub fn detach(self, agent: &mut Agent, key: Option, gc: NoGcScope) -> JsResult<()> { detach_array_buffer(agent, self, key, gc) } @@ -157,8 +152,8 @@ impl<'a> ArrayBuffer<'a> { } } -impl IntoObject for ArrayBuffer<'_> { - fn into_object(self) -> Object { +impl<'a> IntoObject<'a> for ArrayBuffer<'a> { + fn into_object(self) -> Object<'a> { self.into() } } @@ -192,7 +187,7 @@ impl IntoBaseIndex<'_, ArrayBufferHeapData> for ArrayBuffer<'static> { } } -impl From> for Object { +impl<'a> From> for Object<'a> { fn from(value: ArrayBuffer) -> Self { Self::ArrayBuffer(value.unbind()) } @@ -238,7 +233,7 @@ impl IndexMut> for Vec> { } } -impl InternalSlots for ArrayBuffer<'_> { +impl<'a> InternalSlots<'a> for ArrayBuffer<'a> { const DEFAULT_PROTOTYPE: ProtoIntrinsics = ProtoIntrinsics::ArrayBuffer; #[inline(always)] @@ -254,7 +249,7 @@ impl InternalSlots for ArrayBuffer<'_> { } } -impl InternalMethods for ArrayBuffer<'_> {} +impl<'a> InternalMethods<'a> for ArrayBuffer<'a> {} impl Rootable for ArrayBuffer<'static> { type RootRepr = HeapRootRef; diff --git a/nova_vm/src/ecmascript/builtins/bound_function.rs b/nova_vm/src/ecmascript/builtins/bound_function.rs index f23832918..46b2b6110 100644 --- a/nova_vm/src/ecmascript/builtins/bound_function.rs +++ b/nova_vm/src/ecmascript/builtins/bound_function.rs @@ -7,7 +7,7 @@ use std::ops::{Index, IndexMut}; use crate::ecmascript::types::{function_try_get, function_try_has_property, function_try_set}; use crate::engine::context::{GcScope, NoGcScope}; use crate::engine::rootable::{HeapRootData, HeapRootRef, Rootable}; -use crate::engine::{Scoped, TryResult}; +use crate::engine::{unwrap_try, Scoped, TryResult}; use crate::{ ecmascript::{ abstract_operations::{ @@ -86,8 +86,8 @@ impl IntoValue for BoundFunction<'_> { } } -impl IntoObject for BoundFunction<'_> { - fn into_object(self) -> Object { +impl<'a> IntoObject<'a> for BoundFunction<'a> { + fn into_object(self) -> Object<'a> { Object::BoundFunction(self.unbind()) } } @@ -122,7 +122,9 @@ pub(crate) fn bound_function_create<'a>( let scoped_target_function = target_function.scope(agent, gc.nogc()); let proto = target_function .unbind() - .internal_get_prototype_of(agent, gc.reborrow())?; + .internal_get_prototype_of(agent, gc.reborrow())? + .map(|p| p.unbind()) + .map(|p| p.bind(gc.nogc())); target_function = scoped_target_function.get(agent).bind(gc.nogc()); proto }; @@ -154,8 +156,7 @@ pub(crate) fn bound_function_create<'a>( // 8. Set obj.[[BoundThis]] to boundThis. // 9. Set obj.[[BoundArguments]] to boundArgs. let obj = agent.heap.create(data); - obj.internal_set_prototype_of(agent, proto, gc.reborrow()) - .unwrap(); + unwrap_try(obj.try_set_prototype_of(agent, proto, gc.nogc())); // 10. Return obj. Ok(obj) } @@ -170,7 +171,7 @@ impl<'a> FunctionInternalProperties<'a> for BoundFunction<'a> { } } -impl InternalSlots for BoundFunction<'_> { +impl<'a> InternalSlots<'a> for BoundFunction<'a> { const DEFAULT_PROTOTYPE: ProtoIntrinsics = ProtoIntrinsics::Function; #[inline(always)] @@ -190,12 +191,12 @@ impl InternalSlots for BoundFunction<'_> { } } -impl InternalMethods for BoundFunction<'_> { +impl<'a> InternalMethods<'a> for BoundFunction<'a> { fn try_get_own_property( self, agent: &mut Agent, property_key: PropertyKey, - _gc: NoGcScope<'_, '_>, + _gc: NoGcScope, ) -> TryResult> { TryResult::Continue(function_internal_get_own_property( self, @@ -209,7 +210,7 @@ impl InternalMethods for BoundFunction<'_> { agent: &mut Agent, property_key: PropertyKey, property_descriptor: PropertyDescriptor, - gc: NoGcScope<'_, '_>, + gc: NoGcScope, ) -> TryResult { TryResult::Continue(function_internal_define_own_property( self, @@ -224,7 +225,7 @@ impl InternalMethods for BoundFunction<'_> { self, agent: &mut Agent, property_key: PropertyKey, - gc: NoGcScope<'_, '_>, + gc: NoGcScope, ) -> TryResult { function_try_has_property(self, agent, property_key, gc) } @@ -233,7 +234,7 @@ impl InternalMethods for BoundFunction<'_> { self, agent: &mut Agent, property_key: PropertyKey, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { function_internal_has_property(self, agent, property_key, gc) } @@ -243,7 +244,7 @@ impl InternalMethods for BoundFunction<'_> { agent: &mut Agent, property_key: PropertyKey, receiver: Value, - gc: NoGcScope<'_, '_>, + gc: NoGcScope, ) -> TryResult { function_try_get(self, agent, property_key, receiver, gc) } @@ -253,7 +254,7 @@ impl InternalMethods for BoundFunction<'_> { agent: &mut Agent, property_key: PropertyKey, receiver: Value, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { function_internal_get(self, agent, property_key, receiver, gc) } @@ -264,7 +265,7 @@ impl InternalMethods for BoundFunction<'_> { property_key: PropertyKey, value: Value, receiver: Value, - gc: NoGcScope<'_, '_>, + gc: NoGcScope, ) -> TryResult { function_try_set(self, agent, property_key, value, receiver, gc) } @@ -275,7 +276,7 @@ impl InternalMethods for BoundFunction<'_> { property_key: PropertyKey, value: Value, receiver: Value, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { function_internal_set(self, agent, property_key, value, receiver, gc) } @@ -284,16 +285,16 @@ impl InternalMethods for BoundFunction<'_> { self, agent: &mut Agent, property_key: PropertyKey, - gc: NoGcScope<'_, '_>, + gc: NoGcScope, ) -> TryResult { TryResult::Continue(function_internal_delete(self, agent, property_key, gc)) } - fn try_own_property_keys<'a>( + fn try_own_property_keys<'gc>( self, agent: &mut Agent, - gc: NoGcScope<'a, '_>, - ) -> TryResult>> { + gc: NoGcScope<'gc, '_>, + ) -> TryResult>> { TryResult::Continue(function_internal_own_property_keys(self, agent, gc)) } @@ -309,7 +310,7 @@ impl InternalMethods for BoundFunction<'_> { agent: &mut Agent, _: Value, arguments_list: ArgumentsList, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { // 1. Let target be F.[[BoundTargetFunction]]. let target = agent[self].bound_target_function; @@ -343,16 +344,16 @@ impl InternalMethods for BoundFunction<'_> { /// takes arguments argumentsList (a List of ECMAScript language values) /// and newTarget (a constructor) and returns either a normal completion /// containing an Object or a throw completion. - fn internal_construct( + fn internal_construct<'gc>( self, agent: &mut Agent, arguments_list: ArgumentsList, new_target: Function, - mut gc: GcScope<'_, '_>, - ) -> JsResult { + gc: GcScope<'gc, '_>, + ) -> JsResult> { let new_target = new_target.bind(gc.nogc()); // 1. Let target be F.[[BoundTargetFunction]]. - let target = agent[self].bound_target_function; + let target = agent[self].bound_target_function.bind(gc.nogc()); // 2. Assert: IsConstructor(target) is true. assert!(is_constructor(agent, target).is_some()); // 3. Let boundArgs be F.[[BoundArguments]]. @@ -376,10 +377,10 @@ impl InternalMethods for BoundFunction<'_> { // 6. Return ? Construct(target, args, newTarget). construct( agent, - target, + target.unbind(), Some(ArgumentsList(&args)), Some(new_target.unbind()), - gc.reborrow(), + gc, ) } } diff --git a/nova_vm/src/ecmascript/builtins/builtin_constructor.rs b/nova_vm/src/ecmascript/builtins/builtin_constructor.rs index 11d846384..a27207852 100644 --- a/nova_vm/src/ecmascript/builtins/builtin_constructor.rs +++ b/nova_vm/src/ecmascript/builtins/builtin_constructor.rs @@ -102,8 +102,8 @@ impl IntoValue for BuiltinConstructorFunction<'_> { } } -impl IntoObject for BuiltinConstructorFunction<'_> { - fn into_object(self) -> Object { +impl<'a> IntoObject<'a> for BuiltinConstructorFunction<'a> { + fn into_object(self) -> Object<'a> { self.into() } } @@ -120,7 +120,7 @@ impl From> for Value { } } -impl From> for Object { +impl<'a> From> for Object<'a> { fn from(value: BuiltinConstructorFunction) -> Self { Self::BuiltinConstructorFunction(value.unbind()) } @@ -143,10 +143,10 @@ impl TryFrom for BuiltinConstructorFunction<'_> { } } -impl TryFrom for BuiltinConstructorFunction<'_> { +impl<'a> TryFrom> for BuiltinConstructorFunction<'a> { type Error = (); - fn try_from(value: Object) -> Result { + fn try_from(value: Object<'a>) -> Result { match value { Object::BuiltinConstructorFunction(data) => Ok(data), _ => Err(()), @@ -209,7 +209,7 @@ impl<'a> FunctionInternalProperties<'a> for BuiltinConstructorFunction<'a> { } } -impl InternalSlots for BuiltinConstructorFunction<'_> { +impl<'a> InternalSlots<'a> for BuiltinConstructorFunction<'a> { const DEFAULT_PROTOTYPE: ProtoIntrinsics = ProtoIntrinsics::Function; #[inline(always)] @@ -229,12 +229,12 @@ impl InternalSlots for BuiltinConstructorFunction<'_> { } } -impl InternalMethods for BuiltinConstructorFunction<'_> { +impl<'a> InternalMethods<'a> for BuiltinConstructorFunction<'a> { fn try_get_own_property( self, agent: &mut Agent, property_key: PropertyKey, - _gc: NoGcScope<'_, '_>, + _gc: NoGcScope, ) -> TryResult> { TryResult::Continue(function_internal_get_own_property( self, @@ -248,7 +248,7 @@ impl InternalMethods for BuiltinConstructorFunction<'_> { agent: &mut Agent, property_key: PropertyKey, property_descriptor: PropertyDescriptor, - gc: NoGcScope<'_, '_>, + gc: NoGcScope, ) -> TryResult { TryResult::Continue(function_internal_define_own_property( self, @@ -263,7 +263,7 @@ impl InternalMethods for BuiltinConstructorFunction<'_> { self, agent: &mut Agent, property_key: PropertyKey, - gc: NoGcScope<'_, '_>, + gc: NoGcScope, ) -> TryResult { function_try_has_property(self, agent, property_key, gc) } @@ -272,7 +272,7 @@ impl InternalMethods for BuiltinConstructorFunction<'_> { self, agent: &mut Agent, property_key: PropertyKey, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { function_internal_has_property(self, agent, property_key, gc) } @@ -282,7 +282,7 @@ impl InternalMethods for BuiltinConstructorFunction<'_> { agent: &mut Agent, property_key: PropertyKey, receiver: Value, - gc: NoGcScope<'_, '_>, + gc: NoGcScope, ) -> TryResult { function_try_get(self, agent, property_key, receiver, gc) } @@ -292,7 +292,7 @@ impl InternalMethods for BuiltinConstructorFunction<'_> { agent: &mut Agent, property_key: PropertyKey, receiver: Value, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { function_internal_get(self, agent, property_key, receiver, gc) } @@ -303,7 +303,7 @@ impl InternalMethods for BuiltinConstructorFunction<'_> { property_key: PropertyKey, value: Value, receiver: Value, - gc: NoGcScope<'_, '_>, + gc: NoGcScope, ) -> TryResult { function_try_set(self, agent, property_key, value, receiver, gc) } @@ -314,7 +314,7 @@ impl InternalMethods for BuiltinConstructorFunction<'_> { property_key: PropertyKey, value: Value, receiver: Value, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { function_internal_set(self, agent, property_key, value, receiver, gc) } @@ -323,16 +323,16 @@ impl InternalMethods for BuiltinConstructorFunction<'_> { self, agent: &mut Agent, property_key: PropertyKey, - gc: NoGcScope<'_, '_>, + gc: NoGcScope, ) -> TryResult { TryResult::Continue(function_internal_delete(self, agent, property_key, gc)) } - fn try_own_property_keys<'a>( + fn try_own_property_keys<'gc>( self, agent: &mut Agent, - gc: NoGcScope<'a, '_>, - ) -> TryResult>> { + gc: NoGcScope<'gc, '_>, + ) -> TryResult>> { TryResult::Continue(function_internal_own_property_keys(self, agent, gc)) } @@ -348,7 +348,7 @@ impl InternalMethods for BuiltinConstructorFunction<'_> { agent: &mut Agent, _: Value, _: ArgumentsList, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { // 1. Return ? BuiltinCallOrConstruct(F, thisArgument, argumentsList, undefined). // ii. If NewTarget is undefined, throw a TypeError exception. @@ -365,13 +365,13 @@ impl InternalMethods for BuiltinConstructorFunction<'_> { /// the method is present) takes arguments argumentsList (a List of /// ECMAScript language values) and newTarget (a constructor) and returns /// either a normal completion containing an Object or a throw completion. - fn internal_construct( + fn internal_construct<'gc>( self, agent: &mut Agent, arguments_list: ArgumentsList, new_target: Function, - gc: GcScope<'_, '_>, - ) -> JsResult { + gc: GcScope<'gc, '_>, + ) -> JsResult> { // 1. Return ? BuiltinCallOrConstruct(F, uninitialized, argumentsList, newTarget). builtin_call_or_construct(agent, self, arguments_list, new_target, gc) } @@ -384,13 +384,13 @@ impl InternalMethods for BuiltinConstructorFunction<'_> { /// uninitialized), argumentsList (a List of ECMAScript language values), and /// newTarget (a constructor or undefined) and returns either a normal /// completion containing an ECMAScript language value or a throw completion. -fn builtin_call_or_construct( +fn builtin_call_or_construct<'a>( agent: &mut Agent, f: BuiltinConstructorFunction, arguments_list: ArgumentsList, new_target: Function, - gc: GcScope<'_, '_>, -) -> JsResult { + gc: GcScope<'a, '_>, +) -> JsResult> { let f = f.bind(gc.nogc()); // 1. Let callerContext be the running execution context. let caller_context = agent.running_execution_context(); @@ -443,8 +443,8 @@ fn builtin_call_or_construct( pub(crate) struct BuiltinConstructorArgs<'a> { pub(crate) is_derived: bool, pub(crate) class_name: String<'a>, - pub(crate) prototype: Option, - pub(crate) prototype_property: Object, + pub(crate) prototype: Option>, + pub(crate) prototype_property: Object<'static>, pub(crate) compiled_initializer_bytecode: Option, pub(crate) env: EnvironmentIndex, pub(crate) private_env: Option, diff --git a/nova_vm/src/ecmascript/builtins/builtin_function.rs b/nova_vm/src/ecmascript/builtins/builtin_function.rs index 3403d13f3..764345591 100644 --- a/nova_vm/src/ecmascript/builtins/builtin_function.rs +++ b/nova_vm/src/ecmascript/builtins/builtin_function.rs @@ -48,9 +48,9 @@ impl ArgumentsList<'_> { } } -pub type RegularFn = fn(&mut Agent, Value, ArgumentsList<'_>, GcScope) -> JsResult; +pub type RegularFn = fn(&mut Agent, Value, ArgumentsList, GcScope) -> JsResult; pub type ConstructorFn = - fn(&mut Agent, Value, ArgumentsList<'_>, Option, GcScope) -> JsResult; + fn(&mut Agent, Value, ArgumentsList, Option, GcScope) -> JsResult; #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum Behaviour { @@ -93,15 +93,15 @@ pub(crate) trait BuiltinIntrinsic: Builtin { pub trait BuiltinGetter: Builtin {} #[derive(Debug, Default)] -pub struct BuiltinFunctionArgs { +pub struct BuiltinFunctionArgs<'a> { pub length: u32, pub name: &'static str, pub realm: Option, - pub prototype: Option, + pub prototype: Option>, pub prefix: Option<&'static str>, } -impl BuiltinFunctionArgs { +impl BuiltinFunctionArgs<'static> { pub fn new(length: u32, name: &'static str, realm: RealmIdentifier) -> Self { Self { length, @@ -171,8 +171,8 @@ impl IntoValue for BuiltinFunction<'_> { } } -impl IntoObject for BuiltinFunction<'_> { - fn into_object(self) -> Object { +impl<'a> IntoObject<'a> for BuiltinFunction<'a> { + fn into_object(self) -> Object<'a> { self.into() } } @@ -189,7 +189,7 @@ impl From> for Value { } } -impl From> for Object { +impl<'a> From> for Object<'a> { fn from(value: BuiltinFunction) -> Self { Object::BuiltinFunction(value.unbind()) } @@ -245,7 +245,7 @@ impl<'a> FunctionInternalProperties<'a> for BuiltinFunction<'a> { } } -impl InternalSlots for BuiltinFunction<'_> { +impl<'a> InternalSlots<'a> for BuiltinFunction<'a> { const DEFAULT_PROTOTYPE: ProtoIntrinsics = ProtoIntrinsics::Function; #[inline(always)] @@ -265,7 +265,7 @@ impl InternalSlots for BuiltinFunction<'_> { } } -impl InternalMethods for BuiltinFunction<'_> { +impl<'a> InternalMethods<'a> for BuiltinFunction<'a> { fn try_get_own_property( self, agent: &mut Agent, @@ -364,11 +364,11 @@ impl InternalMethods for BuiltinFunction<'_> { TryResult::Continue(function_internal_delete(self, agent, property_key, gc)) } - fn try_own_property_keys<'a>( + fn try_own_property_keys<'gc>( self, agent: &mut Agent, - gc: NoGcScope<'a, '_>, - ) -> TryResult>> { + gc: NoGcScope<'gc, '_>, + ) -> TryResult>> { TryResult::Continue(function_internal_own_property_keys(self, agent, gc)) } @@ -396,13 +396,13 @@ impl InternalMethods for BuiltinFunction<'_> { /// the method is present) takes arguments argumentsList (a List of /// ECMAScript language values) and newTarget (a constructor) and returns /// either a normal completion containing an Object or a throw completion. - fn internal_construct( + fn internal_construct<'gc>( self, agent: &mut Agent, arguments_list: ArgumentsList, new_target: Function, - gc: GcScope, - ) -> JsResult { + gc: GcScope<'gc, '_>, + ) -> JsResult> { // 1. Return ? BuiltinCallOrConstruct(F, uninitialized, argumentsList, newTarget). builtin_call_or_construct(agent, self, None, arguments_list, Some(new_target), gc) .map(|result| result.try_into().unwrap()) @@ -425,6 +425,7 @@ pub(crate) fn builtin_call_or_construct( gc: GcScope, ) -> JsResult { let f = f.bind(gc.nogc()); + let new_target = new_target.map(|f| f.bind(gc.nogc())); // 1. Let callerContext be the running execution context. let caller_context = agent.running_execution_context(); // 2. If callerContext is not already suspended, suspend callerContext. @@ -477,7 +478,7 @@ pub(crate) fn builtin_call_or_construct( agent, this_argument.unwrap_or(Value::Undefined), arguments_list, - new_target.map(|target| target.into_object()), + new_target.map(|target| target.into_object().unbind()), gc, ), }; diff --git a/nova_vm/src/ecmascript/builtins/control_abstraction_objects/async_function_objects/async_function_constructor.rs b/nova_vm/src/ecmascript/builtins/control_abstraction_objects/async_function_objects/async_function_constructor.rs index b2717ebd4..7f70b2629 100644 --- a/nova_vm/src/ecmascript/builtins/control_abstraction_objects/async_function_objects/async_function_constructor.rs +++ b/nova_vm/src/ecmascript/builtins/control_abstraction_objects/async_function_objects/async_function_constructor.rs @@ -34,7 +34,7 @@ impl AsyncFunctionConstructor { _this_value: Value, arguments: ArgumentsList, new_target: Option, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { // 2. If bodyArg is not present, set bodyArg to the empty String. let (parameter_args, body_arg) = if arguments.is_empty() { diff --git a/nova_vm/src/ecmascript/builtins/control_abstraction_objects/async_function_objects/await_reaction.rs b/nova_vm/src/ecmascript/builtins/control_abstraction_objects/async_function_objects/await_reaction.rs index 950fa7acd..f8d45d262 100644 --- a/nova_vm/src/ecmascript/builtins/control_abstraction_objects/async_function_objects/await_reaction.rs +++ b/nova_vm/src/ecmascript/builtins/control_abstraction_objects/async_function_objects/await_reaction.rs @@ -59,7 +59,7 @@ impl AwaitReactionIdentifier { agent: &mut Agent, reaction_type: PromiseReactionType, value: Value, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) { // [27.7.5.3 Await ( value )](https://tc39.es/ecma262/#await) // 3. c. Push asyncContext onto the execution context stack; asyncContext is now the running execution context. diff --git a/nova_vm/src/ecmascript/builtins/control_abstraction_objects/async_generator_function_objects/async_generator_function_constructor.rs b/nova_vm/src/ecmascript/builtins/control_abstraction_objects/async_generator_function_objects/async_generator_function_constructor.rs index a7223890c..4e309ca79 100644 --- a/nova_vm/src/ecmascript/builtins/control_abstraction_objects/async_generator_function_objects/async_generator_function_constructor.rs +++ b/nova_vm/src/ecmascript/builtins/control_abstraction_objects/async_generator_function_objects/async_generator_function_constructor.rs @@ -35,7 +35,7 @@ impl AsyncGeneratorFunctionConstructor { _this_value: Value, arguments: ArgumentsList, new_target: Option, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { // 2. If bodyArg is not present, set bodyArg to the empty String. let (parameter_args, body_arg) = if arguments.is_empty() { diff --git a/nova_vm/src/ecmascript/builtins/control_abstraction_objects/async_generator_objects.rs b/nova_vm/src/ecmascript/builtins/control_abstraction_objects/async_generator_objects.rs index d74b3b78b..6740edbbd 100644 --- a/nova_vm/src/ecmascript/builtins/control_abstraction_objects/async_generator_objects.rs +++ b/nova_vm/src/ecmascript/builtins/control_abstraction_objects/async_generator_objects.rs @@ -45,7 +45,7 @@ impl AsyncGeneratorPrototype { _agent: &mut Agent, _this_value: Value, _arguments: ArgumentsList, - _gc: GcScope<'_, '_>, + _gc: GcScope, ) -> JsResult { todo!() } @@ -54,7 +54,7 @@ impl AsyncGeneratorPrototype { _agent: &mut Agent, _this_value: Value, _arguments: ArgumentsList, - _gc: GcScope<'_, '_>, + _gc: GcScope, ) -> JsResult { todo!() } @@ -63,7 +63,7 @@ impl AsyncGeneratorPrototype { _agent: &mut Agent, _this_value: Value, _arguments: ArgumentsList, - _gc: GcScope<'_, '_>, + _gc: GcScope, ) -> JsResult { todo!() } diff --git a/nova_vm/src/ecmascript/builtins/control_abstraction_objects/generator_function_objects/generator_function_constructor.rs b/nova_vm/src/ecmascript/builtins/control_abstraction_objects/generator_function_objects/generator_function_constructor.rs index 6e0e961e3..a0c088326 100644 --- a/nova_vm/src/ecmascript/builtins/control_abstraction_objects/generator_function_objects/generator_function_constructor.rs +++ b/nova_vm/src/ecmascript/builtins/control_abstraction_objects/generator_function_objects/generator_function_constructor.rs @@ -42,7 +42,7 @@ impl GeneratorFunctionConstructor { _this_value: Value, arguments: ArgumentsList, new_target: Option, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { // 2. If bodyArg is not present, set bodyArg to the empty String. let (parameter_args, body_arg) = if arguments.is_empty() { @@ -82,6 +82,7 @@ impl GeneratorFunctionConstructor { .generator_prototype() .into_object(), ), + gc, ); // b. Perform ! DefinePropertyOrThrow(F, "prototype", PropertyDescriptor { [[Value]]: prototype, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false }). unwrap_try(try_define_property_or_throw( diff --git a/nova_vm/src/ecmascript/builtins/control_abstraction_objects/generator_objects.rs b/nova_vm/src/ecmascript/builtins/control_abstraction_objects/generator_objects.rs index 94496eb3e..4a4833ac2 100644 --- a/nova_vm/src/ecmascript/builtins/control_abstraction_objects/generator_objects.rs +++ b/nova_vm/src/ecmascript/builtins/control_abstraction_objects/generator_objects.rs @@ -67,12 +67,12 @@ impl Generator<'_> { } /// [27.5.3.3 GeneratorResume ( generator, value, generatorBrand )](https://tc39.es/ecma262/#sec-generatorresume) - pub(crate) fn resume( + pub(crate) fn resume<'a>( self, agent: &mut Agent, value: Value, - mut gc: GcScope<'_, '_>, - ) -> JsResult { + mut gc: GcScope<'a, '_>, + ) -> JsResult> { let generator = self.bind(gc.nogc()); // 1. Let state be ? GeneratorValidate(generator, generatorBrand). match agent[generator].generator_state.as_ref().unwrap() { @@ -88,7 +88,12 @@ impl Generator<'_> { } GeneratorState::Completed => { // 2. If state is completed, return CreateIterResultObject(undefined, true). - return Ok(create_iter_result_object(agent, Value::Undefined, true)); + return Ok(create_iter_result_object( + agent, + Value::Undefined, + true, + gc.into_nogc(), + )); } }; @@ -148,7 +153,12 @@ impl Generator<'_> { // j. Else if result is a return completion, then // i. Let resultValue be result.[[Value]]. // l. Return CreateIterResultObject(resultValue, true). - Ok(create_iter_result_object(agent, result_value, true)) + Ok(create_iter_result_object( + agent, + result_value, + true, + gc.into_nogc(), + )) } ExecutionResult::Throw(err) => { // GeneratorStart step 4: @@ -174,7 +184,12 @@ impl Generator<'_> { }); // 8. Resume callerContext passing NormalCompletion(iterNextObj). ... // NOTE: `callerContext` here is the `GeneratorResume` execution context. - Ok(create_iter_result_object(agent, yielded_value, false)) + Ok(create_iter_result_object( + agent, + yielded_value, + false, + gc.into_nogc(), + )) } ExecutionResult::Await { .. } => unreachable!(), } @@ -182,12 +197,12 @@ impl Generator<'_> { /// [27.5.3.4 GeneratorResumeAbrupt ( generator, abruptCompletion, generatorBrand )](https://tc39.es/ecma262/#sec-generatorresumeabrupt) /// NOTE: This method only accepts throw completions. - pub(crate) fn resume_throw( + pub(crate) fn resume_throw<'a>( self, agent: &mut Agent, value: Value, - mut gc: GcScope<'_, '_>, - ) -> JsResult { + mut gc: GcScope<'a, '_>, + ) -> JsResult> { // 1. Let state be ? GeneratorValidate(generator, generatorBrand). match agent[self].generator_state.as_ref().unwrap() { GeneratorState::Suspended { @@ -260,7 +275,12 @@ impl Generator<'_> { match execution_result { ExecutionResult::Return(result) => { agent[self].generator_state = Some(GeneratorState::Completed); - Ok(create_iter_result_object(agent, result, true)) + Ok(create_iter_result_object( + agent, + result, + true, + gc.into_nogc(), + )) } ExecutionResult::Throw(err) => { agent[self].generator_state = Some(GeneratorState::Completed); @@ -272,7 +292,12 @@ impl Generator<'_> { executable, execution_context, }); - Ok(create_iter_result_object(agent, yielded_value, false)) + Ok(create_iter_result_object( + agent, + yielded_value, + false, + gc.into_nogc(), + )) } ExecutionResult::Await { .. } => unreachable!(), } @@ -285,8 +310,8 @@ impl IntoValue for Generator<'_> { } } -impl IntoObject for Generator<'_> { - fn into_object(self) -> Object { +impl<'a> IntoObject<'a> for Generator<'a> { + fn into_object(self) -> Object<'a> { self.into() } } @@ -297,7 +322,7 @@ impl From> for Value { } } -impl From> for Object { +impl<'a> From> for Object<'a> { fn from(value: Generator) -> Self { Object::Generator(value.unbind()) } @@ -315,7 +340,7 @@ impl TryFrom for Generator<'_> { } } -impl InternalSlots for Generator<'_> { +impl<'a> InternalSlots<'a> for Generator<'a> { const DEFAULT_PROTOTYPE: ProtoIntrinsics = ProtoIntrinsics::Generator; fn get_backing_object(self, agent: &Agent) -> Option> { @@ -330,7 +355,7 @@ impl InternalSlots for Generator<'_> { } } -impl InternalMethods for Generator<'_> {} +impl<'a> InternalMethods<'a> for Generator<'a> {} impl CreateHeapData> for Heap { fn create(&mut self, data: GeneratorHeapData) -> Generator<'static> { diff --git a/nova_vm/src/ecmascript/builtins/control_abstraction_objects/generator_prototype.rs b/nova_vm/src/ecmascript/builtins/control_abstraction_objects/generator_prototype.rs index fc1bd0914..429adfdf2 100644 --- a/nova_vm/src/ecmascript/builtins/control_abstraction_objects/generator_prototype.rs +++ b/nova_vm/src/ecmascript/builtins/control_abstraction_objects/generator_prototype.rs @@ -52,7 +52,7 @@ impl GeneratorPrototype { agent: &mut Agent, this_value: Value, arguments: ArgumentsList, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { // GeneratorResume: 1. Let state be ? GeneratorValidate(generator, generatorBrand). let Value::Generator(generator) = this_value else { @@ -71,8 +71,9 @@ impl GeneratorPrototype { agent: &mut Agent, this_value: Value, arguments: ArgumentsList, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { + let gc = gc.into_nogc(); // 1. Let g be the this value. // 2. Let C be Completion Record { [[Type]]: return, [[Value]]: value, [[Target]]: empty }. // 3. Return ? GeneratorResumeAbrupt(g, C, empty). @@ -83,9 +84,10 @@ impl GeneratorPrototype { return Err(agent.throw_exception_with_static_message( ExceptionType::TypeError, "Generator expected", - gc.nogc(), + gc, )); }; + let generator = generator.bind(gc); match agent[generator].generator_state.as_ref().unwrap() { // 2. If state is suspended-start, then @@ -109,7 +111,7 @@ impl GeneratorPrototype { return Err(agent.throw_exception_with_static_message( ExceptionType::TypeError, "The generator is currently running", - gc.nogc(), + gc, )) } GeneratorState::Completed => {} @@ -119,14 +121,14 @@ impl GeneratorPrototype { // 3. If state is completed, then // a. If abruptCompletion is a return completion, then // i. Return CreateIterResultObject(abruptCompletion.[[Value]], true). - Ok(create_iter_result_object(agent, arguments.get(0), true).into_value()) + Ok(create_iter_result_object(agent, arguments.get(0), true, gc).into_value()) } fn throw( agent: &mut Agent, this_value: Value, arguments: ArgumentsList, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { // GeneratorResumeAbrupt: 1. Let state be ? GeneratorValidate(generator, generatorBrand). let Value::Generator(generator) = this_value else { diff --git a/nova_vm/src/ecmascript/builtins/control_abstraction_objects/iteration/async_from_sync_iterator_prototype.rs b/nova_vm/src/ecmascript/builtins/control_abstraction_objects/iteration/async_from_sync_iterator_prototype.rs index 01cd21be1..9b7631d83 100644 --- a/nova_vm/src/ecmascript/builtins/control_abstraction_objects/iteration/async_from_sync_iterator_prototype.rs +++ b/nova_vm/src/ecmascript/builtins/control_abstraction_objects/iteration/async_from_sync_iterator_prototype.rs @@ -38,7 +38,7 @@ impl AsyncFromSyncIteratorPrototype { _agent: &mut Agent, _this_value: Value, _: ArgumentsList, - _gc: GcScope<'_, '_>, + _gc: GcScope, ) -> JsResult { todo!() } @@ -47,7 +47,7 @@ impl AsyncFromSyncIteratorPrototype { _agent: &mut Agent, _this_value: Value, _: ArgumentsList, - _gc: GcScope<'_, '_>, + _gc: GcScope, ) -> JsResult { todo!() } @@ -56,7 +56,7 @@ impl AsyncFromSyncIteratorPrototype { _agent: &mut Agent, _this_value: Value, _: ArgumentsList, - _gc: GcScope<'_, '_>, + _gc: GcScope, ) -> JsResult { todo!() } diff --git a/nova_vm/src/ecmascript/builtins/control_abstraction_objects/iteration/async_iterator_prototype.rs b/nova_vm/src/ecmascript/builtins/control_abstraction_objects/iteration/async_iterator_prototype.rs index 2f76b8983..b9a4ee123 100644 --- a/nova_vm/src/ecmascript/builtins/control_abstraction_objects/iteration/async_iterator_prototype.rs +++ b/nova_vm/src/ecmascript/builtins/control_abstraction_objects/iteration/async_iterator_prototype.rs @@ -29,7 +29,7 @@ impl AsyncIteratorPrototype { _agent: &mut Agent, this_value: Value, _: ArgumentsList, - _gc: GcScope<'_, '_>, + _gc: GcScope, ) -> JsResult { Ok(this_value) } diff --git a/nova_vm/src/ecmascript/builtins/control_abstraction_objects/iteration/iterator_prototype.rs b/nova_vm/src/ecmascript/builtins/control_abstraction_objects/iteration/iterator_prototype.rs index 41b256b6c..7d8a774d3 100644 --- a/nova_vm/src/ecmascript/builtins/control_abstraction_objects/iteration/iterator_prototype.rs +++ b/nova_vm/src/ecmascript/builtins/control_abstraction_objects/iteration/iterator_prototype.rs @@ -29,7 +29,7 @@ impl IteratorPrototype { _agent: &mut Agent, this_value: Value, _: ArgumentsList, - _gc: GcScope<'_, '_>, + _gc: GcScope, ) -> JsResult { Ok(this_value) } diff --git a/nova_vm/src/ecmascript/builtins/control_abstraction_objects/promise_objects/promise_abstract_operations/promise_capability_records.rs b/nova_vm/src/ecmascript/builtins/control_abstraction_objects/promise_objects/promise_abstract_operations/promise_capability_records.rs index 15b1788b6..14461514e 100644 --- a/nova_vm/src/ecmascript/builtins/control_abstraction_objects/promise_objects/promise_abstract_operations/promise_capability_records.rs +++ b/nova_vm/src/ecmascript/builtins/control_abstraction_objects/promise_objects/promise_abstract_operations/promise_capability_records.rs @@ -137,7 +137,7 @@ impl PromiseCapability { } /// [27.2.1.3.2 Promise Resolve Functions](https://tc39.es/ecma262/#sec-promise-resolve-functions) - pub fn resolve(self, agent: &mut Agent, resolution: Value, gc: GcScope<'_, '_>) { + pub fn resolve(self, agent: &mut Agent, resolution: Value, gc: GcScope) { // 1. Let F be the active function object. // 2. Assert: F has a [[Promise]] internal slot whose value is an Object. // 3. Let promise be F.[[Promise]]. diff --git a/nova_vm/src/ecmascript/builtins/control_abstraction_objects/promise_objects/promise_abstract_operations/promise_jobs.rs b/nova_vm/src/ecmascript/builtins/control_abstraction_objects/promise_objects/promise_abstract_operations/promise_jobs.rs index f94117a27..337c4b4f5 100644 --- a/nova_vm/src/ecmascript/builtins/control_abstraction_objects/promise_objects/promise_abstract_operations/promise_jobs.rs +++ b/nova_vm/src/ecmascript/builtins/control_abstraction_objects/promise_objects/promise_abstract_operations/promise_jobs.rs @@ -27,11 +27,11 @@ use super::{ #[derive(Debug, Clone, Copy)] pub(crate) struct PromiseResolveThenableJob { promise_to_resolve: Promise<'static>, - thenable: Object, + thenable: Object<'static>, then: Function<'static>, } impl PromiseResolveThenableJob { - pub(crate) fn run(self, agent: &mut Agent, gc: GcScope<'_, '_>) -> JsResult<()> { + pub(crate) fn run(self, agent: &mut Agent, gc: GcScope) -> JsResult<()> { // The following are substeps of point 1 in NewPromiseResolveThenableJob. // a. Let resolvingFunctions be CreateResolvingFunctions(promiseToResolve). let promise_capability = PromiseCapability::from_promise(self.promise_to_resolve, false); @@ -94,7 +94,7 @@ pub(crate) fn new_promise_resolve_thenable_job( realm: Some(then_realm), inner: InnerJob::PromiseResolveThenable(PromiseResolveThenableJob { promise_to_resolve: promise_to_resolve.unbind(), - thenable, + thenable: thenable.unbind(), then: then.unbind(), }), } @@ -106,7 +106,7 @@ pub(crate) struct PromiseReactionJob { argument: Value, } impl PromiseReactionJob { - pub(crate) fn run(self, agent: &mut Agent, mut gc: GcScope<'_, '_>) -> JsResult<()> { + pub(crate) fn run(self, agent: &mut Agent, mut gc: GcScope) -> JsResult<()> { // The following are substeps of point 1 in NewPromiseReactionJob. let handler_result = match agent[self.reaction].handler { PromiseReactionHandler::Empty => match agent[self.reaction].reaction_type { diff --git a/nova_vm/src/ecmascript/builtins/control_abstraction_objects/promise_objects/promise_abstract_operations/promise_resolving_functions.rs b/nova_vm/src/ecmascript/builtins/control_abstraction_objects/promise_objects/promise_abstract_operations/promise_resolving_functions.rs index a1450ce3f..04fb68ba6 100644 --- a/nova_vm/src/ecmascript/builtins/control_abstraction_objects/promise_objects/promise_abstract_operations/promise_resolving_functions.rs +++ b/nova_vm/src/ecmascript/builtins/control_abstraction_objects/promise_objects/promise_abstract_operations/promise_resolving_functions.rs @@ -106,14 +106,14 @@ impl<'a> IntoFunction<'a> for BuiltinPromiseResolvingFunction<'a> { } } -impl From> for Object { +impl<'a> From> for Object<'a> { fn from(value: BuiltinPromiseResolvingFunction) -> Self { Self::BuiltinPromiseResolvingFunction(value.unbind()) } } -impl IntoObject for BuiltinPromiseResolvingFunction<'_> { - fn into_object(self) -> Object { +impl<'a> IntoObject<'a> for BuiltinPromiseResolvingFunction<'a> { + fn into_object(self) -> Object<'a> { self.into() } } @@ -140,7 +140,7 @@ impl<'a> FunctionInternalProperties<'a> for BuiltinPromiseResolvingFunction<'a> } } -impl InternalSlots for BuiltinPromiseResolvingFunction<'_> { +impl<'a> InternalSlots<'a> for BuiltinPromiseResolvingFunction<'a> { const DEFAULT_PROTOTYPE: ProtoIntrinsics = ProtoIntrinsics::Function; #[inline(always)] @@ -160,12 +160,12 @@ impl InternalSlots for BuiltinPromiseResolvingFunction<'_> { } } -impl InternalMethods for BuiltinPromiseResolvingFunction<'_> { +impl<'a> InternalMethods<'a> for BuiltinPromiseResolvingFunction<'a> { fn try_get_own_property( self, agent: &mut Agent, property_key: PropertyKey, - _gc: NoGcScope<'_, '_>, + _gc: NoGcScope, ) -> TryResult> { TryResult::Continue(function_internal_get_own_property( self, @@ -179,7 +179,7 @@ impl InternalMethods for BuiltinPromiseResolvingFunction<'_> { agent: &mut Agent, property_key: PropertyKey, property_descriptor: PropertyDescriptor, - gc: NoGcScope<'_, '_>, + gc: NoGcScope, ) -> TryResult { TryResult::Continue(function_internal_define_own_property( self, @@ -194,7 +194,7 @@ impl InternalMethods for BuiltinPromiseResolvingFunction<'_> { self, agent: &mut Agent, property_key: PropertyKey, - gc: NoGcScope<'_, '_>, + gc: NoGcScope, ) -> TryResult { function_try_has_property(self, agent, property_key, gc) } @@ -203,7 +203,7 @@ impl InternalMethods for BuiltinPromiseResolvingFunction<'_> { self, agent: &mut Agent, property_key: PropertyKey, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { function_internal_has_property(self, agent, property_key, gc) } @@ -213,7 +213,7 @@ impl InternalMethods for BuiltinPromiseResolvingFunction<'_> { agent: &mut Agent, property_key: PropertyKey, receiver: Value, - gc: NoGcScope<'_, '_>, + gc: NoGcScope, ) -> TryResult { function_try_get(self, agent, property_key, receiver, gc) } @@ -223,7 +223,7 @@ impl InternalMethods for BuiltinPromiseResolvingFunction<'_> { agent: &mut Agent, property_key: PropertyKey, receiver: Value, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { function_internal_get(self, agent, property_key, receiver, gc) } @@ -234,7 +234,7 @@ impl InternalMethods for BuiltinPromiseResolvingFunction<'_> { property_key: PropertyKey, value: Value, receiver: Value, - gc: NoGcScope<'_, '_>, + gc: NoGcScope, ) -> TryResult { function_try_set(self, agent, property_key, value, receiver, gc) } @@ -245,7 +245,7 @@ impl InternalMethods for BuiltinPromiseResolvingFunction<'_> { property_key: PropertyKey, value: Value, receiver: Value, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { function_internal_set(self, agent, property_key, value, receiver, gc) } @@ -254,16 +254,16 @@ impl InternalMethods for BuiltinPromiseResolvingFunction<'_> { self, agent: &mut Agent, property_key: PropertyKey, - gc: NoGcScope<'_, '_>, + gc: NoGcScope, ) -> TryResult { TryResult::Continue(function_internal_delete(self, agent, property_key, gc)) } - fn try_own_property_keys<'a>( + fn try_own_property_keys<'gc>( self, agent: &mut Agent, - gc: NoGcScope<'a, '_>, - ) -> TryResult>> { + gc: NoGcScope<'gc, '_>, + ) -> TryResult>> { TryResult::Continue(function_internal_own_property_keys(self, agent, gc)) } @@ -272,7 +272,7 @@ impl InternalMethods for BuiltinPromiseResolvingFunction<'_> { agent: &mut Agent, _this_value: Value, args: ArgumentsList, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { let arg = args.get(0); let promise_capability = agent[self].promise_capability; diff --git a/nova_vm/src/ecmascript/builtins/control_abstraction_objects/promise_objects/promise_constructor.rs b/nova_vm/src/ecmascript/builtins/control_abstraction_objects/promise_objects/promise_constructor.rs index e3812abb3..c3e0bd2a6 100644 --- a/nova_vm/src/ecmascript/builtins/control_abstraction_objects/promise_objects/promise_constructor.rs +++ b/nova_vm/src/ecmascript/builtins/control_abstraction_objects/promise_objects/promise_constructor.rs @@ -107,8 +107,10 @@ impl PromiseConstructor { _this_value: Value, args: ArgumentsList, new_target: Option, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { + let executor = args.get(0); + // 1. If NewTarget is undefined, throw a TypeError exception. let Some(new_target) = new_target else { return Err(agent.throw_exception_with_static_message( @@ -117,6 +119,7 @@ impl PromiseConstructor { gc.nogc(), )); }; + let new_target = new_target.unbind().bind(gc.nogc()); // We currently don't support Promise subclassing. assert_eq!( @@ -126,13 +129,14 @@ impl PromiseConstructor { // 2. If IsCallable(executor) is false, throw a TypeError exception. // TODO: Callable proxies - let Ok(executor) = Function::try_from(args.get(0)) else { + let Ok(executor) = Function::try_from(executor) else { return Err(agent.throw_exception_with_static_message( ExceptionType::TypeError, "Not a callable value", gc.nogc(), )); }; + let executor = executor.unbind().bind(gc.nogc()).scope(agent, gc.nogc()); // 3. Let promise be ? OrdinaryCreateFromConstructor(NewTarget, "%Promise.prototype%", ยซ [[PromiseState]], [[PromiseResult]], [[PromiseFulfillReactions]], [[PromiseRejectReactions]], [[PromiseIsHandled]] ยป). // 4. Set promise.[[PromiseState]] to pending. @@ -141,13 +145,15 @@ impl PromiseConstructor { // 7. Set promise.[[PromiseIsHandled]] to false. let Object::Promise(promise) = ordinary_create_from_constructor( agent, - Function::try_from(new_target).unwrap(), + Function::try_from(new_target.unbind()).unwrap(), ProtoIntrinsics::Promise, gc.reborrow(), )? else { unreachable!() }; + let promise = promise.unbind().bind(gc.nogc()); + let scoped_promise = promise.scope(agent, gc.nogc()); // 8. Let resolvingFunctions be CreateResolvingFunctions(promise). let promise_capability = PromiseCapability::from_promise(promise, true); @@ -172,24 +178,24 @@ impl PromiseConstructor { // 10. If completion is an abrupt completion, then if let Err(err) = call_function( agent, - executor, + executor.get(agent), Value::Undefined, Some(ArgumentsList(&[resolve_function, reject_function])), - gc, + gc.reborrow(), ) { // a. Perform ? Call(resolvingFunctions.[[Reject]], undefined, ยซ completion.[[Value]] ยป). promise_capability.reject(agent, err.value()); } // 11. Return promise. - Ok(promise.into_value()) + Ok(scoped_promise.get(agent).into_value()) } fn all( _agent: &mut Agent, _this_value: Value, _arguments: ArgumentsList, - _gc: GcScope<'_, '_>, + _gc: GcScope, ) -> JsResult { todo!() } @@ -198,7 +204,7 @@ impl PromiseConstructor { _agent: &mut Agent, _this_value: Value, _arguments: ArgumentsList, - _gc: GcScope<'_, '_>, + _gc: GcScope, ) -> JsResult { todo!() } @@ -206,7 +212,7 @@ impl PromiseConstructor { _agent: &mut Agent, _this_value: Value, _arguments: ArgumentsList, - _gc: GcScope<'_, '_>, + _gc: GcScope, ) -> JsResult { todo!() } @@ -214,7 +220,7 @@ impl PromiseConstructor { _agent: &mut Agent, _this_value: Value, _arguments: ArgumentsList, - _gc: GcScope<'_, '_>, + _gc: GcScope, ) -> JsResult { todo!() } @@ -223,7 +229,7 @@ impl PromiseConstructor { agent: &mut Agent, this_value: Value, arguments: ArgumentsList, - _: GcScope<'_, '_>, + _: GcScope, ) -> JsResult { // We currently don't support Promise subclassing. assert_eq!( @@ -251,7 +257,7 @@ impl PromiseConstructor { agent: &mut Agent, this_value: Value, arguments: ArgumentsList, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { // We currently don't support Promise subclassing. assert_eq!( @@ -268,7 +274,7 @@ impl PromiseConstructor { agent: &mut Agent, this_value: Value, arguments: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { // 1. Let C be the this value. // 2. If C is not an Object, throw a TypeError exception. @@ -321,7 +327,7 @@ impl PromiseConstructor { agent: &mut Agent, this_value: Value, _arguments: ArgumentsList, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { // Step 2 will throw if `this_value` is not a constructor. if is_constructor(agent, this_value).is_none() { @@ -391,7 +397,7 @@ impl PromiseConstructor { _: &mut Agent, this_value: Value, _: ArgumentsList, - _: GcScope<'_, '_>, + _: GcScope, ) -> JsResult { Ok(this_value) } diff --git a/nova_vm/src/ecmascript/builtins/control_abstraction_objects/promise_objects/promise_prototype.rs b/nova_vm/src/ecmascript/builtins/control_abstraction_objects/promise_objects/promise_prototype.rs index e0dd74be5..8ab760321 100644 --- a/nova_vm/src/ecmascript/builtins/control_abstraction_objects/promise_objects/promise_prototype.rs +++ b/nova_vm/src/ecmascript/builtins/control_abstraction_objects/promise_objects/promise_prototype.rs @@ -57,7 +57,7 @@ impl PromisePrototype { agent: &mut Agent, this_value: Value, args: ArgumentsList, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { // 1. Let promise be the this value. // 2. Return ? Invoke(promise, "then", ยซ undefined, onRejected ยป). @@ -77,7 +77,7 @@ impl PromisePrototype { _agent: &mut Agent, _this_value: Value, _: ArgumentsList, - _gc: GcScope<'_, '_>, + _gc: GcScope, ) -> JsResult { todo!() } @@ -86,7 +86,7 @@ impl PromisePrototype { agent: &mut Agent, this_value: Value, args: ArgumentsList, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { // 1. Let promise be the this value. // 2. If IsPromise(promise) is false, throw a TypeError exception. diff --git a/nova_vm/src/ecmascript/builtins/data_view.rs b/nova_vm/src/ecmascript/builtins/data_view.rs index f61e05368..fb2d919f3 100644 --- a/nova_vm/src/ecmascript/builtins/data_view.rs +++ b/nova_vm/src/ecmascript/builtins/data_view.rs @@ -119,8 +119,8 @@ impl IntoValue for DataView<'_> { } } -impl IntoObject for DataView<'_> { - fn into_object(self) -> Object { +impl<'a> IntoObject<'a> for DataView<'a> { + fn into_object(self) -> Object<'a> { self.into() } } @@ -131,16 +131,16 @@ impl From> for Value { } } -impl From> for Object { +impl<'a> From> for Object<'a> { fn from(val: DataView) -> Self { Object::DataView(val.unbind()) } } -impl TryFrom for DataView<'_> { +impl<'a> TryFrom> for DataView<'a> { type Error = (); - fn try_from(value: Object) -> Result { + fn try_from(value: Object<'a>) -> Result { match value { Object::DataView(data) => Ok(data), _ => Err(()), @@ -182,7 +182,7 @@ impl IndexMut> for Vec> { } } -impl InternalSlots for DataView<'_> { +impl<'a> InternalSlots<'a> for DataView<'a> { const DEFAULT_PROTOTYPE: ProtoIntrinsics = ProtoIntrinsics::DataView; #[inline(always)] @@ -198,7 +198,7 @@ impl InternalSlots for DataView<'_> { } } -impl InternalMethods for DataView<'_> {} +impl<'a> InternalMethods<'a> for DataView<'a> {} impl Rootable for DataView<'_> { type RootRepr = HeapRootRef; diff --git a/nova_vm/src/ecmascript/builtins/data_view/abstract_operations.rs b/nova_vm/src/ecmascript/builtins/data_view/abstract_operations.rs index 236dad818..0f34179fb 100644 --- a/nova_vm/src/ecmascript/builtins/data_view/abstract_operations.rs +++ b/nova_vm/src/ecmascript/builtins/data_view/abstract_operations.rs @@ -257,7 +257,7 @@ pub(crate) fn set_view_value( // 6. Set isLittleEndian to ToBoolean(isLittleEndian). is_little_endian: bool, value: Value, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { // 1. Perform ? RequireInternalSlot(view, [[DataView]]). // 2. Assert: view has a [[ViewedArrayBuffer]] internal slot. diff --git a/nova_vm/src/ecmascript/builtins/date.rs b/nova_vm/src/ecmascript/builtins/date.rs index 14bd46ada..1b9cc54d7 100644 --- a/nova_vm/src/ecmascript/builtins/date.rs +++ b/nova_vm/src/ecmascript/builtins/date.rs @@ -79,13 +79,13 @@ impl From> for Value { } } -impl IntoObject for Date<'_> { - fn into_object(self) -> Object { +impl<'a> IntoObject<'a> for Date<'a> { + fn into_object(self) -> Object<'a> { self.into() } } -impl From> for Object { +impl<'a> From> for Object<'a> { fn from(value: Date) -> Self { Object::Date(value.unbind()) } @@ -102,10 +102,10 @@ impl TryFrom for Date<'_> { } } -impl TryFrom for Date<'_> { +impl<'a> TryFrom> for Date<'a> { type Error = (); - fn try_from(value: Object) -> Result { + fn try_from(value: Object<'a>) -> Result { match value { Object::Date(idx) => Ok(idx), _ => Err(()), @@ -113,7 +113,7 @@ impl TryFrom for Date<'_> { } } -impl InternalSlots for Date<'_> { +impl<'a> InternalSlots<'a> for Date<'a> { const DEFAULT_PROTOTYPE: ProtoIntrinsics = ProtoIntrinsics::Date; #[inline(always)] @@ -129,7 +129,7 @@ impl InternalSlots for Date<'_> { } } -impl InternalMethods for Date<'_> {} +impl<'a> InternalMethods<'a> for Date<'a> {} impl Index> for Agent { type Output = DateHeapData; diff --git a/nova_vm/src/ecmascript/builtins/ecmascript_function.rs b/nova_vm/src/ecmascript/builtins/ecmascript_function.rs index 2f3ff3cb1..4d8dd7886 100644 --- a/nova_vm/src/ecmascript/builtins/ecmascript_function.rs +++ b/nova_vm/src/ecmascript/builtins/ecmascript_function.rs @@ -77,8 +77,8 @@ impl IntoValue for ECMAScriptFunction<'_> { } } -impl IntoObject for ECMAScriptFunction<'_> { - fn into_object(self) -> Object { +impl<'a> IntoObject<'a> for ECMAScriptFunction<'a> { + fn into_object(self) -> Object<'a> { self.into() } } @@ -101,10 +101,10 @@ impl TryFrom for ECMAScriptFunction<'_> { } } -impl TryFrom for ECMAScriptFunction<'_> { +impl<'a> TryFrom> for ECMAScriptFunction<'a> { type Error = (); - fn try_from(value: Object) -> Result { + fn try_from(value: Object<'a>) -> Result { if let Object::ECMAScriptFunction(function) = value { Ok(function) } else { @@ -131,7 +131,7 @@ impl From> for Value { } } -impl From> for Object { +impl<'a> From> for Object<'a> { fn from(val: ECMAScriptFunction) -> Self { Object::ECMAScriptFunction(val.unbind()) } @@ -222,7 +222,7 @@ pub(crate) struct ECMAScriptFunctionObjectHeapData { pub strict: bool, /// \[\[HomeObject]] - pub home_object: Option, + pub home_object: Option>, /// \[\[SourceText]] pub source_text: Span, @@ -235,8 +235,8 @@ pub(crate) struct ECMAScriptFunctionObjectHeapData { // TODO: [[Fields]], [[PrivateMethods]], [[ClassFieldInitializerName]] } -pub(crate) struct OrdinaryFunctionCreateParams<'agent, 'program> { - pub function_prototype: Option, +pub(crate) struct OrdinaryFunctionCreateParams<'agent, 'program, 'gc> { + pub function_prototype: Option>, pub source_code: Option, pub source_text: Span, pub parameters_list: &'agent FormalParameters<'program>, @@ -327,7 +327,7 @@ impl<'a> ECMAScriptFunction<'a> { } } -impl InternalSlots for ECMAScriptFunction<'_> { +impl<'a> InternalSlots<'a> for ECMAScriptFunction<'a> { const DEFAULT_PROTOTYPE: ProtoIntrinsics = ProtoIntrinsics::Function; #[inline(always)] @@ -346,7 +346,7 @@ impl InternalSlots for ECMAScriptFunction<'_> { function_create_backing_object(self, agent) } - fn internal_prototype(self, agent: &Agent) -> Option { + fn internal_prototype(self, agent: &Agent) -> Option> { if let Some(object_index) = self.get_backing_object(agent) { object_index.internal_prototype(agent) } else { @@ -378,12 +378,12 @@ impl<'a> FunctionInternalProperties<'a> for ECMAScriptFunction<'a> { } } -impl InternalMethods for ECMAScriptFunction<'_> { +impl<'a> InternalMethods<'a> for ECMAScriptFunction<'a> { fn try_get_own_property( self, agent: &mut Agent, property_key: PropertyKey, - _gc: NoGcScope<'_, '_>, + _gc: NoGcScope, ) -> TryResult> { TryResult::Continue(function_internal_get_own_property( self, @@ -397,7 +397,7 @@ impl InternalMethods for ECMAScriptFunction<'_> { agent: &mut Agent, property_key: PropertyKey, property_descriptor: PropertyDescriptor, - gc: NoGcScope<'_, '_>, + gc: NoGcScope, ) -> TryResult { TryResult::Continue(function_internal_define_own_property( self, @@ -412,7 +412,7 @@ impl InternalMethods for ECMAScriptFunction<'_> { self, agent: &mut Agent, property_key: PropertyKey, - gc: NoGcScope<'_, '_>, + gc: NoGcScope, ) -> TryResult { function_try_has_property(self, agent, property_key, gc) } @@ -421,7 +421,7 @@ impl InternalMethods for ECMAScriptFunction<'_> { self, agent: &mut Agent, property_key: PropertyKey, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { function_internal_has_property(self, agent, property_key, gc) } @@ -431,7 +431,7 @@ impl InternalMethods for ECMAScriptFunction<'_> { agent: &mut Agent, property_key: PropertyKey, receiver: Value, - gc: NoGcScope<'_, '_>, + gc: NoGcScope, ) -> TryResult { function_try_get(self, agent, property_key, receiver, gc) } @@ -441,7 +441,7 @@ impl InternalMethods for ECMAScriptFunction<'_> { agent: &mut Agent, property_key: PropertyKey, receiver: Value, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { function_internal_get(self, agent, property_key, receiver, gc) } @@ -452,7 +452,7 @@ impl InternalMethods for ECMAScriptFunction<'_> { property_key: PropertyKey, value: Value, receiver: Value, - gc: NoGcScope<'_, '_>, + gc: NoGcScope, ) -> TryResult { function_try_set(self, agent, property_key, value, receiver, gc) } @@ -463,7 +463,7 @@ impl InternalMethods for ECMAScriptFunction<'_> { property_key: PropertyKey, value: Value, receiver: Value, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { function_internal_set(self, agent, property_key, value, receiver, gc) } @@ -472,16 +472,16 @@ impl InternalMethods for ECMAScriptFunction<'_> { self, agent: &mut Agent, property_key: PropertyKey, - gc: NoGcScope<'_, '_>, + gc: NoGcScope, ) -> TryResult { TryResult::Continue(function_internal_delete(self, agent, property_key, gc)) } - fn try_own_property_keys<'a>( + fn try_own_property_keys<'gc>( self, agent: &mut Agent, - gc: NoGcScope<'a, '_>, - ) -> TryResult>> { + gc: NoGcScope<'gc, '_>, + ) -> TryResult>> { TryResult::Continue(function_internal_own_property_keys(self, agent, gc)) } @@ -496,8 +496,8 @@ impl InternalMethods for ECMAScriptFunction<'_> { self, agent: &mut Agent, this_argument: Value, - arguments_list: ArgumentsList<'_>, - gc: GcScope<'_, '_>, + arguments_list: ArgumentsList, + gc: GcScope, ) -> JsResult { // 1. Let callerContext be the running execution context. let _ = agent.running_execution_context(); @@ -546,21 +546,23 @@ impl InternalMethods for ECMAScriptFunction<'_> { result } - fn internal_construct( + fn internal_construct<'gc>( self, agent: &mut Agent, arguments_list: ArgumentsList, new_target: Function, - mut gc: GcScope<'_, '_>, - ) -> JsResult { + mut gc: GcScope<'gc, '_>, + ) -> JsResult> { + let mut self_fn = self.bind(gc.nogc()); let mut new_target = new_target.bind(gc.nogc()); // 2. Let kind be F.[[ConstructorKind]]. - let is_base = !agent[self] + let is_base = !agent[self_fn] .ecmascript_function .constructor_status .is_derived_class(); // 3. If kind is BASE, then let this_argument = if is_base { + let scoped_self_fn = self_fn.scope(agent, gc.nogc()); let scoped_new_target = new_target.scope(agent, gc.nogc()); // a. Let thisArgument be ? OrdinaryCreateFromConstructor(newTarget, "%Object.prototype%"). let this_argument = ordinary_create_from_constructor( @@ -568,7 +570,10 @@ impl InternalMethods for ECMAScriptFunction<'_> { new_target.unbind(), ProtoIntrinsics::Object, gc.reborrow(), - )?; + )? + .unbind() + .bind(gc.nogc()); + self_fn = scoped_self_fn.get(agent).bind(gc.nogc()); new_target = scoped_new_target.get(agent).bind(gc.nogc()); Some(this_argument) } else { @@ -576,7 +581,8 @@ impl InternalMethods for ECMAScriptFunction<'_> { }; // 4. Let calleeContext be PrepareForOrdinaryCall(F, newTarget). - let callee_context = prepare_for_ordinary_call(agent, self, Some(new_target.into_object())); + let callee_context = + prepare_for_ordinary_call(agent, self_fn, Some(new_target.into_object())); // 7. Let constructorEnv be the LexicalEnvironment of calleeContext. let constructor_env = callee_context .ecmascript_code @@ -607,8 +613,11 @@ impl InternalMethods for ECMAScriptFunction<'_> { // TODO: Classes. } + let scoped_this_argument = this_argument.map(|f| f.scope(agent, gc.nogc())); + // 8. Let result be Completion(OrdinaryCallEvaluateBody(F, argumentsList)). - let result = ordinary_call_evaluate_body(agent, self, arguments_list, gc.reborrow()); + let result = + ordinary_call_evaluate_body(agent, self_fn.unbind(), arguments_list, gc.reborrow()); // 9. Remove calleeContext from the execution context stack and restore // callerContext as the running execution context. agent.execution_context_stack.pop(); @@ -623,7 +632,7 @@ impl InternalMethods for ECMAScriptFunction<'_> { } else // b. If kind is base, return thisArgument. if is_base { - Ok(this_argument.unwrap()) + Ok(scoped_this_argument.unwrap().get(agent)) } else // c. If result.[[Value]] is not undefined, throw a TypeError exception. if !value.is_undefined() { @@ -734,7 +743,7 @@ pub(crate) fn ordinary_call_bind_this( // ii. Assert: globalEnv is a Global Environment Record. let global_env = global_env.unwrap(); // iii. Let thisValue be globalEnv.[[GlobalThisValue]]. - global_env.get_this_binding(agent).into_value() + global_env.get_this_binding(agent, gc).into_value() } else { // b. Else, // i. Let thisValue be ! ToObject(thisArgument). @@ -763,7 +772,7 @@ pub(crate) fn evaluate_body( agent: &mut Agent, function_object: ECMAScriptFunction, arguments_list: ArgumentsList, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { let function_object = function_object.bind(gc.nogc()); let function_heap_data = &agent[function_object].ecmascript_function; @@ -834,7 +843,7 @@ pub(crate) fn ordinary_call_evaluate_body( agent: &mut Agent, f: ECMAScriptFunction, arguments_list: ArgumentsList, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { // 1. Return ? EvaluateBody of F.[[ECMAScriptCode]] with arguments F and argumentsList. evaluate_body(agent, f, arguments_list, gc) @@ -854,7 +863,7 @@ pub(crate) fn ordinary_call_evaluate_body( /// the syntactic definition of the function to be created. pub(crate) fn ordinary_function_create<'agent, 'program, 'gc>( agent: &'agent mut Agent, - params: OrdinaryFunctionCreateParams<'agent, 'program>, + params: OrdinaryFunctionCreateParams<'agent, 'program, 'gc>, gc: NoGcScope<'gc, '_>, ) -> ECMAScriptFunction<'gc> { let (source_code, outer_env_is_strict) = if let Some(source_code) = params.source_code { @@ -966,9 +975,10 @@ pub(crate) fn ordinary_function_create<'agent, 'program, 'gc>( /// UNUSED. It converts F into a constructor. pub(crate) fn make_constructor<'a>( agent: &mut Agent, - function: impl IntoFunction<'a> + InternalMethods, + function: impl IntoFunction<'a> + InternalMethods<'a>, writable_prototype: Option, prototype: Option, + gc: NoGcScope, ) { // 4. If writablePrototype is not present, set writablePrototype to true. let writable_prototype = writable_prototype.unwrap_or(true); @@ -1001,6 +1011,7 @@ pub(crate) fn make_constructor<'a>( agent, Some(ProtoIntrinsics::Object), None, + gc, )) .unwrap(); // b. Perform ! DefinePropertyOrThrow(prototype, "constructor", PropertyDescriptor { [[Value]]: F, [[Writable]]: writablePrototype, [[Enumerable]]: false, [[Configurable]]: true }). @@ -1047,7 +1058,7 @@ pub(crate) fn make_constructor<'a>( pub(crate) fn make_method(agent: &mut Agent, f: ECMAScriptFunction, home_object: Object) { // 1. Assert: homeObject is an ordinary object. // 2. Set F.[[HomeObject]] to homeObject. - agent[f].ecmascript_function.home_object = Some(home_object); + agent[f].ecmascript_function.home_object = Some(home_object.unbind()); // 3. Return unused. } diff --git a/nova_vm/src/ecmascript/builtins/embedder_object.rs b/nova_vm/src/ecmascript/builtins/embedder_object.rs index 3873c4620..0604e2b16 100644 --- a/nova_vm/src/ecmascript/builtins/embedder_object.rs +++ b/nova_vm/src/ecmascript/builtins/embedder_object.rs @@ -70,8 +70,8 @@ impl IntoValue for EmbedderObject<'_> { } } -impl IntoObject for EmbedderObject<'_> { - fn into_object(self) -> Object { +impl<'a> IntoObject<'a> for EmbedderObject<'a> { + fn into_object(self) -> Object<'a> { self.into() } } @@ -82,13 +82,13 @@ impl From> for Value { } } -impl From> for Object { +impl<'a> From> for Object<'a> { fn from(val: EmbedderObject) -> Self { Object::EmbedderObject(val.unbind()) } } -impl InternalSlots for EmbedderObject<'_> { +impl<'a> InternalSlots<'a> for EmbedderObject<'a> { #[inline(always)] fn get_backing_object(self, _agent: &Agent) -> Option> { todo!(); @@ -109,7 +109,7 @@ impl InternalSlots for EmbedderObject<'_> { todo!(); } - fn internal_prototype(self, _agent: &Agent) -> Option { + fn internal_prototype(self, _agent: &Agent) -> Option> { todo!(); } @@ -118,7 +118,7 @@ impl InternalSlots for EmbedderObject<'_> { } } -impl InternalMethods for EmbedderObject<'_> {} +impl<'a> InternalMethods<'a> for EmbedderObject<'a> {} impl Index> for Agent { type Output = EmbedderObjectHeapData; diff --git a/nova_vm/src/ecmascript/builtins/error.rs b/nova_vm/src/ecmascript/builtins/error.rs index 0950fc8a1..4b6121cd7 100644 --- a/nova_vm/src/ecmascript/builtins/error.rs +++ b/nova_vm/src/ecmascript/builtins/error.rs @@ -79,13 +79,13 @@ impl From> for Value { } } -impl IntoObject for Error<'_> { - fn into_object(self) -> Object { +impl<'a> IntoObject<'a> for Error<'a> { + fn into_object(self) -> Object<'a> { self.into() } } -impl From> for Object { +impl<'a> From> for Object<'a> { fn from(value: Error) -> Self { Object::Error(value.unbind()) } @@ -102,10 +102,10 @@ impl TryFrom for Error<'_> { } } -impl TryFrom for Error<'_> { +impl<'a> TryFrom> for Error<'a> { type Error = (); - fn try_from(value: Object) -> Result { + fn try_from(value: Object<'a>) -> Result { match value { Object::Error(idx) => Ok(idx), _ => Err(()), @@ -113,7 +113,7 @@ impl TryFrom for Error<'_> { } } -impl InternalSlots for Error<'_> { +impl<'a> InternalSlots<'a> for Error<'a> { const DEFAULT_PROTOTYPE: ProtoIntrinsics = ProtoIntrinsics::Error; #[inline(always)] @@ -171,7 +171,7 @@ impl InternalSlots for Error<'_> { backing_object } - fn internal_prototype(self, agent: &Agent) -> Option { + fn internal_prototype(self, agent: &Agent) -> Option> { if let Some(object_index) = self.get_backing_object(agent) { object_index.internal_prototype(agent) } else { @@ -195,12 +195,12 @@ impl InternalSlots for Error<'_> { } } -impl InternalMethods for Error<'_> { +impl<'a> InternalMethods<'a> for Error<'a> { fn try_get_own_property( self, agent: &mut Agent, property_key: PropertyKey, - gc: NoGcScope<'_, '_>, + gc: NoGcScope, ) -> TryResult> { match self.get_backing_object(agent) { Some(backing_object) => backing_object.try_get_own_property(agent, property_key, gc), @@ -229,7 +229,7 @@ impl InternalMethods for Error<'_> { self, agent: &mut Agent, property_key: PropertyKey, - gc: NoGcScope<'_, '_>, + gc: NoGcScope, ) -> TryResult { match self.get_backing_object(agent) { Some(backing_object) => backing_object.try_has_property(agent, property_key, gc), @@ -249,7 +249,7 @@ impl InternalMethods for Error<'_> { self, agent: &mut Agent, property_key: PropertyKey, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { let property_key = property_key.bind(gc.nogc()); match self.get_backing_object(agent) { @@ -273,7 +273,7 @@ impl InternalMethods for Error<'_> { agent: &mut Agent, property_key: PropertyKey, receiver: Value, - gc: NoGcScope<'_, '_>, + gc: NoGcScope, ) -> TryResult { match self.get_backing_object(agent) { Some(backing_object) => backing_object.try_get(agent, property_key, receiver, gc), @@ -303,7 +303,7 @@ impl InternalMethods for Error<'_> { agent: &mut Agent, property_key: PropertyKey, receiver: Value, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { let property_key = property_key.bind(gc.nogc()); match self.get_backing_object(agent) { @@ -326,7 +326,9 @@ impl InternalMethods for Error<'_> { // Note: Error is never a prototype so [[GetPrototypeOf]] // cannot call user code. // c. Return ? parent.[[Get]](P, Receiver). - parent.internal_get(agent, property_key.unbind(), receiver, gc) + parent + .unbind() + .internal_get(agent, property_key.unbind(), receiver, gc) } else { Ok(Value::Undefined) } @@ -340,7 +342,7 @@ impl InternalMethods for Error<'_> { property_key: PropertyKey, value: Value, receiver: Value, - gc: NoGcScope<'_, '_>, + gc: NoGcScope, ) -> TryResult { match self.get_backing_object(agent) { Some(backing_object) => { @@ -369,7 +371,7 @@ impl InternalMethods for Error<'_> { property_key: PropertyKey, value: Value, receiver: Value, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { let property_key = property_key.bind(gc.nogc()); match self.get_backing_object(agent) { @@ -397,7 +399,7 @@ impl InternalMethods for Error<'_> { self, agent: &mut Agent, property_key: PropertyKey, - gc: NoGcScope<'_, '_>, + gc: NoGcScope, ) -> TryResult { match self.get_backing_object(agent) { Some(backing_object) => TryResult::Continue(unwrap_try(backing_object.try_delete( @@ -416,11 +418,11 @@ impl InternalMethods for Error<'_> { } } - fn try_own_property_keys<'a>( + fn try_own_property_keys<'gc>( self, agent: &mut Agent, - gc: NoGcScope<'a, '_>, - ) -> TryResult>> { + gc: NoGcScope<'gc, '_>, + ) -> TryResult>> { match self.get_backing_object(agent) { Some(backing_object) => { TryResult::Continue(unwrap_try(backing_object.try_own_property_keys(agent, gc))) diff --git a/nova_vm/src/ecmascript/builtins/finalization_registry.rs b/nova_vm/src/ecmascript/builtins/finalization_registry.rs index 7bfb8fbc2..07a59551a 100644 --- a/nova_vm/src/ecmascript/builtins/finalization_registry.rs +++ b/nova_vm/src/ecmascript/builtins/finalization_registry.rs @@ -74,8 +74,8 @@ impl IntoValue for FinalizationRegistry<'_> { } } -impl IntoObject for FinalizationRegistry<'_> { - fn into_object(self) -> Object { +impl<'a> IntoObject<'a> for FinalizationRegistry<'a> { + fn into_object(self) -> Object<'a> { self.into() } } @@ -86,13 +86,13 @@ impl From> for Value { } } -impl From> for Object { +impl<'a> From> for Object<'a> { fn from(val: FinalizationRegistry) -> Self { Object::FinalizationRegistry(val.unbind()) } } -impl InternalSlots for FinalizationRegistry<'_> { +impl<'a> InternalSlots<'a> for FinalizationRegistry<'a> { const DEFAULT_PROTOTYPE: ProtoIntrinsics = ProtoIntrinsics::FinalizationRegistry; #[inline(always)] @@ -108,7 +108,7 @@ impl InternalSlots for FinalizationRegistry<'_> { } } -impl InternalMethods for FinalizationRegistry<'_> {} +impl<'a> InternalMethods<'a> for FinalizationRegistry<'a> {} impl Index> for Agent { type Output = FinalizationRegistryHeapData; diff --git a/nova_vm/src/ecmascript/builtins/fundamental_objects/boolean_objects/boolean_constructor.rs b/nova_vm/src/ecmascript/builtins/fundamental_objects/boolean_objects/boolean_constructor.rs index 0988e8be6..1cf71fe05 100644 --- a/nova_vm/src/ecmascript/builtins/fundamental_objects/boolean_objects/boolean_constructor.rs +++ b/nova_vm/src/ecmascript/builtins/fundamental_objects/boolean_objects/boolean_constructor.rs @@ -43,7 +43,7 @@ impl BooleanConstructor { _this_value: Value, arguments: ArgumentsList, new_target: Option, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { let value = arguments.get(0); let b = to_boolean(agent, value); diff --git a/nova_vm/src/ecmascript/builtins/fundamental_objects/boolean_objects/boolean_prototype.rs b/nova_vm/src/ecmascript/builtins/fundamental_objects/boolean_objects/boolean_prototype.rs index 88faf95dc..feb117555 100644 --- a/nova_vm/src/ecmascript/builtins/fundamental_objects/boolean_objects/boolean_prototype.rs +++ b/nova_vm/src/ecmascript/builtins/fundamental_objects/boolean_objects/boolean_prototype.rs @@ -42,7 +42,7 @@ impl BooleanPrototype { agent: &mut Agent, this_value: Value, _: ArgumentsList, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { let b = this_boolean_value(agent, this_value, gc.nogc())?; if b { @@ -56,7 +56,7 @@ impl BooleanPrototype { agent: &mut Agent, this_value: Value, _: ArgumentsList, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { this_boolean_value(agent, this_value, gc.nogc()).map(|result| result.into()) } diff --git a/nova_vm/src/ecmascript/builtins/fundamental_objects/error_objects/aggregate_error_constructors.rs b/nova_vm/src/ecmascript/builtins/fundamental_objects/error_objects/aggregate_error_constructors.rs index 6c9ead5c4..cd36375b6 100644 --- a/nova_vm/src/ecmascript/builtins/fundamental_objects/error_objects/aggregate_error_constructors.rs +++ b/nova_vm/src/ecmascript/builtins/fundamental_objects/error_objects/aggregate_error_constructors.rs @@ -31,7 +31,7 @@ impl AggregateErrorConstructor { _this_value: Value, _arguments: ArgumentsList, _new_target: Option, - _gc: GcScope<'_, '_>, + _gc: GcScope, ) -> JsResult { todo!() } diff --git a/nova_vm/src/ecmascript/builtins/fundamental_objects/error_objects/error_constructor.rs b/nova_vm/src/ecmascript/builtins/fundamental_objects/error_objects/error_constructor.rs index 9c6149667..f15e310a1 100644 --- a/nova_vm/src/ecmascript/builtins/fundamental_objects/error_objects/error_constructor.rs +++ b/nova_vm/src/ecmascript/builtins/fundamental_objects/error_objects/error_constructor.rs @@ -48,7 +48,7 @@ impl ErrorConstructor { _this_value: Value, arguments: ArgumentsList, new_target: Option, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { let message = arguments.get(0); let options = arguments.get(1); @@ -104,7 +104,7 @@ impl ErrorConstructor { pub(super) fn get_error_cause( agent: &mut Agent, options: Value, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult> { let Ok(options) = Object::try_from(options) else { return Ok(None); diff --git a/nova_vm/src/ecmascript/builtins/fundamental_objects/error_objects/error_prototype.rs b/nova_vm/src/ecmascript/builtins/fundamental_objects/error_objects/error_prototype.rs index 6bc6ae4d4..bc2ce8961 100644 --- a/nova_vm/src/ecmascript/builtins/fundamental_objects/error_objects/error_prototype.rs +++ b/nova_vm/src/ecmascript/builtins/fundamental_objects/error_objects/error_prototype.rs @@ -32,7 +32,7 @@ impl ErrorPrototype { agent: &mut Agent, this_value: Value, _: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { // 1. Let O be the this value. // 2. If O is not an Object, throw a TypeError exception. diff --git a/nova_vm/src/ecmascript/builtins/fundamental_objects/error_objects/native_error_constructors.rs b/nova_vm/src/ecmascript/builtins/fundamental_objects/error_objects/native_error_constructors.rs index 1ddc2323e..56d8fadf7 100644 --- a/nova_vm/src/ecmascript/builtins/fundamental_objects/error_objects/native_error_constructors.rs +++ b/nova_vm/src/ecmascript/builtins/fundamental_objects/error_objects/native_error_constructors.rs @@ -100,7 +100,7 @@ impl NativeErrorConstructors { error_kind: ExceptionType, arguments: ArgumentsList, new_target: Option, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { let message = arguments.get(0); let options = arguments.get(1); @@ -123,12 +123,16 @@ impl NativeErrorConstructors { .unwrap() .into_object() }); + let new_target = new_target.bind(gc.nogc()); let o = ordinary_create_from_constructor( agent, - Function::try_from(new_target).unwrap(), + Function::try_from(new_target.unbind()).unwrap(), intrinsic, gc.reborrow(), - )?; + )? + .unbind() + .bind(gc.nogc()) + .scope(agent, gc.nogc()); let msg = if !message.is_undefined() { Some( to_string(agent, message, gc.reborrow())? @@ -139,7 +143,7 @@ impl NativeErrorConstructors { None }; let cause = get_error_cause(agent, options, gc.reborrow())?; - let o = Error::try_from(o).unwrap(); + let o = Error::try_from(o.get(agent).bind(gc.nogc())).unwrap(); // b. Perform CreateNonEnumerableDataPropertyOrThrow(O, "message", msg). let msg = msg.map(|msg| msg.get(agent)); let heap_data = &mut agent[o]; @@ -154,7 +158,7 @@ impl NativeErrorConstructors { _this_value: Value, arguments: ArgumentsList, new_target: Option, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { Self::constructor(agent, ExceptionType::EvalError, arguments, new_target, gc) } @@ -164,7 +168,7 @@ impl NativeErrorConstructors { _this_value: Value, arguments: ArgumentsList, new_target: Option, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { Self::constructor(agent, ExceptionType::RangeError, arguments, new_target, gc) } @@ -174,7 +178,7 @@ impl NativeErrorConstructors { _this_value: Value, arguments: ArgumentsList, new_target: Option, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { Self::constructor( agent, @@ -190,7 +194,7 @@ impl NativeErrorConstructors { _this_value: Value, arguments: ArgumentsList, new_target: Option, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { Self::constructor(agent, ExceptionType::SyntaxError, arguments, new_target, gc) } @@ -200,7 +204,7 @@ impl NativeErrorConstructors { _this_value: Value, arguments: ArgumentsList, new_target: Option, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { Self::constructor(agent, ExceptionType::TypeError, arguments, new_target, gc) } @@ -210,7 +214,7 @@ impl NativeErrorConstructors { _this_value: Value, arguments: ArgumentsList, new_target: Option, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { Self::constructor(agent, ExceptionType::UriError, arguments, new_target, gc) } diff --git a/nova_vm/src/ecmascript/builtins/fundamental_objects/function_objects/function_constructor.rs b/nova_vm/src/ecmascript/builtins/fundamental_objects/function_objects/function_constructor.rs index bdac41a57..9d7084ae1 100644 --- a/nova_vm/src/ecmascript/builtins/fundamental_objects/function_objects/function_constructor.rs +++ b/nova_vm/src/ecmascript/builtins/fundamental_objects/function_objects/function_constructor.rs @@ -46,7 +46,7 @@ impl FunctionConstructor { _this_value: Value, arguments: ArgumentsList, new_target: Option, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { // 2. If bodyArg is not present, set bodyArg to the empty String. let (parameter_args, body_arg) = if arguments.is_empty() { @@ -69,11 +69,13 @@ impl FunctionConstructor { parameter_args, body_arg, gc.reborrow(), - )?; + )? + .unbind() + .bind(gc.nogc()); // 20.2.1.1.1 CreateDynamicFunction ( constructor, newTarget, kind, parameterArgs, bodyArg ) // 32. Else if kind is normal, then // a. Perform MakeConstructor(F). - make_constructor(agent, f, None, None); + make_constructor(agent, f.unbind(), None, None, gc.nogc()); Ok(f.into_value()) } @@ -290,7 +292,9 @@ pub(crate) fn create_dynamic_function<'a>( constructor.unbind(), kind.intrinsic_prototype(), gc.reborrow(), - )?, + )? + .map(|p| p.unbind()) + .map(|p| p.bind(gc.nogc())), source_code: Some(source_code), source_text: function.span, parameters_list: &function.params, @@ -302,8 +306,9 @@ pub(crate) fn create_dynamic_function<'a>( env: EnvironmentIndex::Global(agent.current_realm().global_env.unwrap()), private_env: None, }; + let f = ordinary_function_create(agent, params, gc.nogc()).unbind(); let gc = gc.into_nogc(); - let f = ordinary_function_create(agent, params, gc); + let f = f.bind(gc); set_function_name( agent, diff --git a/nova_vm/src/ecmascript/builtins/fundamental_objects/function_objects/function_prototype.rs b/nova_vm/src/ecmascript/builtins/fundamental_objects/function_objects/function_prototype.rs index 0db4a645b..d51d8a634 100644 --- a/nova_vm/src/ecmascript/builtins/fundamental_objects/function_objects/function_prototype.rs +++ b/nova_vm/src/ecmascript/builtins/fundamental_objects/function_objects/function_prototype.rs @@ -103,7 +103,7 @@ impl Builtin for FunctionPrototypeHasInstance { } impl FunctionPrototype { - fn behaviour(_: &mut Agent, _: Value, _: ArgumentsList, _: GcScope<'_, '_>) -> JsResult { + fn behaviour(_: &mut Agent, _: Value, _: ArgumentsList, _: GcScope) -> JsResult { Ok(Value::Undefined) } @@ -112,7 +112,7 @@ impl FunctionPrototype { agent: &mut Agent, this_value: Value, args: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { // 1. Let func be the this value. let Some(func) = is_callable(this_value, gc.nogc()) else { @@ -157,7 +157,7 @@ impl FunctionPrototype { agent: &mut Agent, this_value: Value, args: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { let this_arg = args.get(0); let args = if args.len() > 1 { &args[1..] } else { &[] }; @@ -298,7 +298,7 @@ impl FunctionPrototype { agent: &mut Agent, this_value: Value, args: ArgumentsList, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { let Some(func) = is_callable(this_value, gc.nogc()) else { return Err(agent.throw_exception_with_static_message( @@ -318,7 +318,7 @@ impl FunctionPrototype { agent: &mut Agent, this_value: Value, _: ArgumentsList, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { // Let func be the this value. let Ok(func) = Function::try_from(this_value) else { @@ -396,7 +396,7 @@ impl FunctionPrototype { agent: &mut Agent, this_value: Value, args: ArgumentsList, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { let v = args.get(0); let f = this_value; @@ -464,7 +464,7 @@ impl ThrowTypeError { agent: &mut Agent, _: Value, _: ArgumentsList, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { Err(agent.throw_exception_with_static_message(ExceptionType::TypeError, "'caller', 'callee', and 'arguments' properties may not be accessed on strict mode functions or the arguments objects for calls to them", gc.nogc())) } diff --git a/nova_vm/src/ecmascript/builtins/fundamental_objects/object_objects/object_constructor.rs b/nova_vm/src/ecmascript/builtins/fundamental_objects/object_objects/object_constructor.rs index 3756bd270..7546f6fab 100644 --- a/nova_vm/src/ecmascript/builtins/fundamental_objects/object_objects/object_constructor.rs +++ b/nova_vm/src/ecmascript/builtins/fundamental_objects/object_objects/object_constructor.rs @@ -2,12 +2,6 @@ // 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/. -use crate::ecmascript::abstract_operations::operations_on_objects::{ - create_array_from_scoped_list, try_create_data_property, try_define_property_or_throw, try_get, -}; -use crate::ecmascript::types::{bind_property_keys, scope_property_keys, unbind_property_keys}; -use crate::engine::context::{GcScope, NoGcScope}; -use crate::engine::{unwrap_try, TryResult}; use crate::{ ecmascript::{ abstract_operations::{ @@ -15,11 +9,12 @@ use crate::{ get_iterator, if_abrupt_close_iterator, iterator_close, iterator_step_value, }, operations_on_objects::{ - create_array_from_list, create_data_property_or_throw, define_property_or_throw, + create_array_from_list, create_array_from_scoped_list, define_property_or_throw, enumerable_own_properties, enumerable_properties_kind, get, get_method, group_by_property, has_own_property, integrity::{Frozen, Sealed}, - set, set_integrity_level, test_integrity_level, + set, set_integrity_level, test_integrity_level, try_create_data_property, + try_define_property_or_throw, try_get, }, testing_and_comparison::{require_object_coercible, same_value}, type_conversion::{to_object, to_property_key, to_property_key_simple}, @@ -31,10 +26,15 @@ use crate::{ }, execution::{agent::ExceptionType, Agent, JsResult, ProtoIntrinsics, RealmIdentifier}, types::{ - InternalMethods, IntoFunction, IntoObject, IntoValue, Object, OrdinaryObject, - PropertyDescriptor, PropertyKey, String, Value, BUILTIN_STRING_MEMORY, + bind_property_keys, scope_property_keys, unbind_property_keys, InternalMethods, + IntoFunction, IntoObject, IntoValue, Object, OrdinaryObject, PropertyDescriptor, + PropertyKey, String, Value, BUILTIN_STRING_MEMORY, }, }, + engine::{ + context::{GcScope, NoGcScope}, + unwrap_try, Scoped, TryResult, + }, heap::{IntrinsicConstructorIndexes, ObjectEntry, WellKnownSymbolIndexes}, }; @@ -269,9 +269,10 @@ impl ObjectConstructor { _this_value: Value, arguments: ArgumentsList, new_target: Option, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { let value = arguments.get(0); + let new_target = new_target.map(|f| f.bind(gc.nogc())); // 1. If NewTarget is neither undefined nor the active function object, then if new_target.is_some() && new_target @@ -284,20 +285,27 @@ impl ObjectConstructor { ordinary_create_from_constructor( agent, // SAFETY: 'new_target' is checked to be is_some() above - unsafe { new_target.unwrap_unchecked() }.try_into().unwrap(), + unsafe { new_target.unwrap_unchecked().unbind() } + .try_into() + .unwrap(), ProtoIntrinsics::Object, gc.reborrow(), ) .map(|value| value.into_value()) } else if value == Value::Undefined || value == Value::Null { // 2. If value is either undefined or null, return OrdinaryObjectCreate(%Object.prototype%). - Ok( - ordinary_object_create_with_intrinsics(agent, Some(ProtoIntrinsics::Object), None) - .into_value(), + Ok(ordinary_object_create_with_intrinsics( + agent, + Some(ProtoIntrinsics::Object), + None, + gc.into_nogc(), ) + .into_value()) } else { // 3. Return ! ToObject(value). - Ok(to_object(agent, value, gc.nogc()).unwrap().into_value()) + Ok(to_object(agent, value, gc.into_nogc()) + .unwrap() + .into_value()) } } @@ -309,7 +317,7 @@ impl ObjectConstructor { agent: &mut Agent, _: Value, arguments: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { let target = arguments.get(0); // 1. Let to be ? ToObject(target). @@ -318,6 +326,7 @@ impl ObjectConstructor { if arguments.len() <= 1 { return Ok(to.into_value()); } + let to = to.scope(agent, gc.nogc()); let sources = &arguments[1..]; // 3. For each element nextSource of sources, do for next_source in sources { @@ -326,16 +335,20 @@ impl ObjectConstructor { continue; } // i. Let from be ! ToObject(nextSource). - let from = to_object(agent, *next_source, gc.nogc())?; + let from = to_object(agent, *next_source, gc.nogc())?.scope(agent, gc.nogc()); // ii. Let keys be ? from.[[OwnPropertyKeys]](). - let keys = unbind_property_keys(from.internal_own_property_keys(agent, gc.reborrow())?); + let keys = unbind_property_keys( + from.get(agent) + .internal_own_property_keys(agent, gc.reborrow())?, + ); let keys = scope_property_keys(agent, keys, gc.nogc()); // iii. For each element nextKey of keys, do for next_key in keys { // 1. Let desc be ? from.[[GetOwnProperty]](nextKey). let desc = { let next_key = next_key.get(agent); - from.internal_get_own_property(agent, next_key, gc.reborrow())? + from.get(agent) + .internal_get_own_property(agent, next_key, gc.reborrow())? }; // 2. If desc is not undefined and desc.[[Enumerable]] is true, then let Some(desc) = desc else { @@ -347,22 +360,29 @@ impl ObjectConstructor { // a. Let propValue be ? Get(from, nextKey). let prop_value = { let next_key = next_key.get(agent); - get(agent, from, next_key, gc.reborrow())? + get(agent, from.get(agent), next_key, gc.reborrow())? }; // b. Perform ? Set(to, nextKey, propValue, true). let next_key = next_key.get(agent); - set(agent, to, next_key, prop_value, true, gc.reborrow())?; + set( + agent, + to.get(agent), + next_key, + prop_value, + true, + gc.reborrow(), + )?; } } // 4. Return to. - Ok(to.into_value()) + Ok(to.get(agent).into_value()) } fn create( agent: &mut Agent, _this_value: Value, arguments: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { let o = arguments.get(0); let obj: OrdinaryObject = if o == Value::Null { @@ -391,7 +411,7 @@ impl ObjectConstructor { agent: &mut Agent, _: Value, arguments: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { let o = arguments.get(0); let properties = arguments.get(1); @@ -416,7 +436,7 @@ impl ObjectConstructor { agent: &mut Agent, _: Value, arguments: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { let o = arguments.get(0); let p = arguments.get(1); @@ -445,7 +465,7 @@ impl ObjectConstructor { agent: &mut Agent, _: Value, arguments: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { let o = arguments.get(0); // 1. Let obj be ? ToObject(O). @@ -453,7 +473,7 @@ impl ObjectConstructor { // 2. Let entryList be ? EnumerableOwnProperties(obj, KEY+VALUE). let entry_list = enumerable_own_properties::< enumerable_properties_kind::EnumerateKeysAndValues, - >(agent, obj, gc.reborrow())?; + >(agent, obj.unbind(), gc.reborrow())?; // 3. Return CreateArrayFromList(entryList). Ok(create_array_from_list(agent, &entry_list, gc.nogc()).into_value()) } @@ -463,7 +483,7 @@ impl ObjectConstructor { agent: &mut Agent, _: Value, arguments: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { // 1. If O is not an Object, return O. let o = arguments.get(0); @@ -490,7 +510,7 @@ impl ObjectConstructor { agent: &mut Agent, _: Value, arguments: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { let iterable = arguments.get(0); // Fast path: Simple, dense array of N simple, dense arrays. @@ -500,7 +520,8 @@ impl ObjectConstructor { .current_realm() .intrinsics() .array_prototype_values() - .into_function(); + .into_function() + .unbind(); let array_iterator = get_method( agent, array_prototype.into_value(), @@ -587,20 +608,21 @@ impl ObjectConstructor { // 1. Perform ? RequireObjectCoercible(iterable). require_object_coercible(agent, iterable, gc.nogc())?; // 2. Let obj be OrdinaryObjectCreate(%Object.prototype%). - let obj = - ordinary_object_create_with_intrinsics(agent, Some(ProtoIntrinsics::Object), None); + let obj = ordinary_object_create_with_intrinsics( + agent, + Some(ProtoIntrinsics::Object), + None, + gc.nogc(), + ); // 3. Assert: obj is an extensible ordinary object with no own properties. let obj = OrdinaryObject::try_from(obj).unwrap(); - debug_assert!(obj - .internal_own_property_keys(agent, gc.reborrow()) - .unwrap() - .is_empty()); + debug_assert!(agent[obj].keys.is_empty()); // 4. Let closure be a new Abstract Closure with parameters (key, // value) that captures obj and performs the following steps when // called: // 5. Let adder be CreateBuiltinFunction(closure, 2, "", ยซ ยป). // 6. Return ? AddEntriesFromIterable(obj, iterable, adder). - add_entries_from_iterable_from_entries(agent, obj, iterable, gc.reborrow()) + add_entries_from_iterable_from_entries(agent, obj.unbind(), iterable, gc) .map(|obj| obj.into_value()) } @@ -609,18 +631,27 @@ impl ObjectConstructor { agent: &mut Agent, _: Value, arguments: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { let o = arguments.get(0); let p = arguments.get(1); // 1. Let obj be ? ToObject(O). - let obj = to_object(agent, o, gc.nogc())?; + let mut obj = to_object(agent, o, gc.nogc())?; // 2. Let key be ? ToPropertyKey(P). - let key = to_property_key(agent, p, gc.reborrow())? - .unbind() - .bind(gc.nogc()); + let key = if let TryResult::Continue(key) = to_property_key_simple(agent, p, gc.nogc()) { + key + } else { + let scoped_obj = obj.scope(agent, gc.nogc()); + let key = to_property_key(agent, p, gc.reborrow())? + .unbind() + .bind(gc.nogc()); + obj = scoped_obj.get(agent).bind(gc.nogc()); + key + }; // 3. Let desc be ? obj.[[GetOwnProperty]](key). - let desc = obj.internal_get_own_property(agent, key.unbind(), gc.reborrow())?; + let desc = obj + .unbind() + .internal_get_own_property(agent, key.unbind(), gc.reborrow())?; // 4. Return FromPropertyDescriptor(desc). Ok( PropertyDescriptor::from_property_descriptor(desc, agent, gc.nogc()) @@ -633,16 +664,28 @@ impl ObjectConstructor { agent: &mut Agent, _: Value, arguments: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { let o = arguments.get(0); // 1. Let obj be ? ToObject(O). - let obj = to_object(agent, o, gc.nogc())?; + let mut obj = to_object(agent, o, gc.nogc())?; + let mut scoped_obj = None; // 2. Let ownKeys be ? obj.[[OwnPropertyKeys]](). - let mut own_keys = bind_property_keys( - unbind_property_keys(obj.internal_own_property_keys(agent, gc.reborrow())?), - gc.nogc(), - ); + let mut own_keys = + if let TryResult::Continue(own_keys) = obj.try_own_property_keys(agent, gc.nogc()) { + own_keys + } else { + scoped_obj = Some(obj.scope(agent, gc.nogc())); + let own_keys = bind_property_keys( + unbind_property_keys( + obj.unbind() + .internal_own_property_keys(agent, gc.reborrow())?, + ), + gc.nogc(), + ); + obj = scoped_obj.as_ref().unwrap().get(agent).bind(gc.nogc()); + own_keys + }; let mut descriptors = Vec::with_capacity(own_keys.len()); // 4. For each element key of ownKeys, do @@ -661,18 +704,22 @@ impl ObjectConstructor { i += 1; } // 3. Let descriptors be OrdinaryObjectCreate(%Object.prototype%). - let descriptors = agent.heap.create_object_with_prototype( - agent - .current_realm() - .intrinsics() - .object_prototype() - .into_object(), - &descriptors, - ); + let descriptors = agent + .heap + .create_object_with_prototype( + agent + .current_realm() + .intrinsics() + .object_prototype() + .into_object(), + &descriptors, + ) + .bind(gc.nogc()); if i < own_keys.len() { let _ = own_keys.drain(..i); let own_keys = unbind_property_keys(own_keys); - get_own_property_descriptors_slow(agent, obj, own_keys, descriptors, gc) + let obj = scoped_obj.unwrap_or_else(|| obj.scope(agent, gc.nogc())); + get_own_property_descriptors_slow(agent, obj, own_keys, descriptors.unbind(), gc) } else { // 5. Return descriptors. Ok(descriptors.into_value()) @@ -684,7 +731,7 @@ impl ObjectConstructor { agent: &mut Agent, _: Value, arguments: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { let o = arguments.get(0); // 1. Return CreateArrayFromList(? GetOwnPropertyKeys(O, STRING)). @@ -697,7 +744,7 @@ impl ObjectConstructor { agent: &mut Agent, _: Value, arguments: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { let o = arguments.get(0); // 1. Return CreateArrayFromList(? GetOwnPropertyKeys(O, SYMBOL)). @@ -710,13 +757,14 @@ impl ObjectConstructor { agent: &mut Agent, _this_value: Value, arguments: ArgumentsList, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { let obj = to_object(agent, arguments.get(0), gc.nogc())?; // Note: We do not use try_get_prototype_of here as we don't need to // protect any on-stack values from GC. We're perfectly okay with // triggering GC here. - obj.internal_get_prototype_of(agent, gc) + obj.unbind() + .internal_get_prototype_of(agent, gc) .map(|proto| proto.map_or(Value::Null, |proto| proto.into_value())) } @@ -725,7 +773,7 @@ impl ObjectConstructor { agent: &mut Agent, _this_value: Value, arguments: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { let items = arguments.get(0); let callback_fn = arguments.get(1); @@ -734,23 +782,19 @@ impl ObjectConstructor { let groups = group_by_property(agent, items, callback_fn, gc.reborrow())?; // 2. Let obj be OrdinaryObjectCreate(null). - let object = - ordinary_object_create_with_intrinsics(agent, Some(ProtoIntrinsics::Object), None); - // 3. For each Record { [[Key]], [[Elements]] } g of groups, do - for g in groups { - // a. Let elements be CreateArrayFromList(g.[[Elements]]). - let elements = create_array_from_scoped_list(agent, g.elements, gc.nogc()).into_value(); - - // b. Perform ! CreateDataPropertyOrThrow(obj, g.[[Key]], elements). - create_data_property_or_throw( - agent, - object, - g.key.get(agent), - elements, - gc.reborrow(), - )?; - } + // a. Let elements be CreateArrayFromList(g.[[Elements]]). + // b. Perform ! CreateDataPropertyOrThrow(obj, g.[[Key]], elements). + let entries = groups + .into_iter() + .map(|g| { + ObjectEntry::new_data_entry( + g.key.get(agent), + create_array_from_scoped_list(agent, g.elements, gc.nogc()).into_value(), + ) + }) + .collect::>(); + let object = agent.heap.create_null_object(&entries); // 4. Return obj. Ok(object.into_value()) @@ -760,20 +804,29 @@ impl ObjectConstructor { agent: &mut Agent, _this_value: Value, arguments: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { - let obj = to_object(agent, arguments.get(0), gc.nogc())?; - let key = to_property_key(agent, arguments.get(1), gc.reborrow())? - .unbind() - .bind(gc.nogc()); - has_own_property(agent, obj, key.unbind(), gc.reborrow()).map(|result| result.into()) + let p = arguments.get(1); + let mut obj = to_object(agent, arguments.get(0), gc.nogc())?; + let key = if let TryResult::Continue(key) = to_property_key_simple(agent, p, gc.nogc()) { + key + } else { + let scoped_obj = obj.scope(agent, gc.nogc()); + let key = to_property_key(agent, p, gc.reborrow())? + .unbind() + .bind(gc.nogc()); + obj = scoped_obj.get(agent).bind(gc.nogc()); + key + }; + has_own_property(agent, obj.unbind(), key.unbind(), gc.reborrow()) + .map(|result| result.into()) } fn is( agent: &mut Agent, _this_value: Value, arguments: ArgumentsList, - _gc: GcScope<'_, '_>, + _gc: GcScope, ) -> JsResult { Ok(same_value(agent, arguments.get(0), arguments.get(1)).into()) } @@ -782,7 +835,7 @@ impl ObjectConstructor { agent: &mut Agent, _: Value, arguments: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { let o = arguments.get(0); let result = match Object::try_from(o) { @@ -796,7 +849,7 @@ impl ObjectConstructor { agent: &mut Agent, _this_value: Value, arguments: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { let o = arguments.get(0); let result = match Object::try_from(o) { @@ -810,7 +863,7 @@ impl ObjectConstructor { agent: &mut Agent, _this_value: Value, arguments: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { let o = arguments.get(0); let result = match Object::try_from(o) { @@ -825,7 +878,7 @@ impl ObjectConstructor { agent: &mut Agent, _: Value, arguments: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { let o = arguments.get(0); // 1. Let obj be ? ToObject(O). @@ -833,7 +886,7 @@ impl ObjectConstructor { // 2. Let keyList be ? EnumerableOwnProperties(obj, KEY). let key_list = enumerable_own_properties::( agent, - obj, + obj.unbind(), gc.reborrow(), )?; // 3. Return CreateArrayFromList(keyList). @@ -845,7 +898,7 @@ impl ObjectConstructor { agent: &mut Agent, _: Value, arguments: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { // 1. If O is not an Object, return O. let o = arguments.get(0); @@ -872,7 +925,7 @@ impl ObjectConstructor { agent: &mut Agent, _: Value, arguments: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { // 1. If O is not an Object, return O. let o = arguments.get(0); @@ -899,7 +952,7 @@ impl ObjectConstructor { agent: &mut Agent, _: Value, arguments: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { let o = arguments.get(0); let proto = arguments.get(1); @@ -939,7 +992,7 @@ impl ObjectConstructor { agent: &mut Agent, _: Value, arguments: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { let o = arguments.get(0); // 1. Let obj be ? ToObject(O). @@ -947,7 +1000,7 @@ impl ObjectConstructor { // 2. Let valueList be ? EnumerableOwnProperties(obj, VALUE). let value_list = enumerable_own_properties::( agent, - obj, + obj.unbind(), gc.reborrow(), )?; // 3. Return CreateArrayFromList(valueList). @@ -993,17 +1046,21 @@ impl ObjectConstructor { /// The abstract operation ObjectDefineProperties takes arguments O (an Object) /// and Properties (an ECMAScript language value) and returns either a normal /// completion containing an Object or a throw completion. -fn object_define_properties( +fn object_define_properties<'a, T: InternalMethods<'a>>( agent: &mut Agent, o: T, properties: Value, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { // 1. Let props be ? ToObject(Properties). - let props = to_object(agent, properties, gc.nogc())?; + let props = to_object(agent, properties, gc.nogc())?.scope(agent, gc.nogc()); // 2. Let keys be ? props.[[OwnPropertyKeys]](). let keys = bind_property_keys( - unbind_property_keys(props.internal_own_property_keys(agent, gc.reborrow())?), + unbind_property_keys( + props + .get(agent) + .internal_own_property_keys(agent, gc.reborrow())?, + ), gc.nogc(), ); let keys = scope_property_keys(agent, keys, gc.nogc()); @@ -1012,8 +1069,11 @@ fn object_define_properties( // 4. For each element nextKey of keys, do for next_key in keys { // a. Let propDesc be ? props.[[GetOwnProperty]](nextKey). - let prop_desc = - props.internal_get_own_property(agent, next_key.get(agent), gc.reborrow())?; + let prop_desc = props.get(agent).internal_get_own_property( + agent, + next_key.get(agent), + gc.reborrow(), + )?; // b. If propDesc is not undefined and propDesc.[[Enumerable]] is true, then let Some(prop_desc) = prop_desc else { continue; @@ -1022,7 +1082,7 @@ fn object_define_properties( continue; } // i. Let descObj be ? Get(props, nextKey). - let desc_obj = get(agent, props, next_key.get(agent), gc.reborrow())?; + let desc_obj = get(agent, props.get(agent), next_key.get(agent), gc.reborrow())?; // ii. Let desc be ? ToPropertyDescriptor(descObj). let desc = PropertyDescriptor::to_property_descriptor(agent, desc_obj, gc.reborrow())? .scope(agent, gc.nogc()); @@ -1044,11 +1104,11 @@ fn object_define_properties( Ok(o) } -fn try_object_define_properties( +fn try_object_define_properties<'a, T: InternalMethods<'a>>( agent: &mut Agent, o: T, properties: Value, - gc: NoGcScope<'_, '_>, + gc: NoGcScope, ) -> TryResult> { // 1. Let props be ? ToObject(Properties). let props = match to_object(agent, properties, gc) { @@ -1119,7 +1179,7 @@ fn try_object_define_properties( /// does not need to be defined as a JavaScript function. pub fn add_entries_from_iterable_from_entries<'a>( agent: &mut Agent, - target: OrdinaryObject<'_>, + target: OrdinaryObject, iterable: Value, mut gc: GcScope<'a, '_>, ) -> JsResult> { @@ -1185,12 +1245,15 @@ pub fn add_entries_from_iterable_from_entries<'a>( fn get_own_string_property_keys( agent: &mut Agent, o: Value, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult> { // 1. Let obj be ? ToObject(O). let obj = to_object(agent, o, gc.nogc())?; // 2. Let keys be ? obj.[[OwnPropertyKeys]](). - let keys = unbind_property_keys(obj.internal_own_property_keys(agent, gc.reborrow())?); + let keys = unbind_property_keys( + obj.unbind() + .internal_own_property_keys(agent, gc.reborrow())?, + ); let gc = gc.into_nogc(); let keys = bind_property_keys(keys, gc); // 3. Let nameList be a new empty List. @@ -1216,12 +1279,14 @@ fn get_own_string_property_keys( fn get_own_symbol_property_keys( agent: &mut Agent, o: Value, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult> { // 1. Let obj be ? ToObject(O). let obj = to_object(agent, o, gc.nogc())?; // 2. Let keys be ? obj.[[OwnPropertyKeys]](). - let keys = obj.internal_own_property_keys(agent, gc.reborrow())?; + let keys = obj + .unbind() + .internal_own_property_keys(agent, gc.reborrow())?; // 3. Let nameList be a new empty List. let mut name_list = Vec::with_capacity(keys.len()); // 4. For each element nextKey of keys, do @@ -1237,7 +1302,7 @@ fn get_own_symbol_property_keys( fn get_own_property_descriptors_slow( agent: &mut Agent, - obj: Object, + obj: Scoped<'_, Object<'static>>, own_keys: Vec, descriptors: OrdinaryObject, mut gc: GcScope, @@ -1246,7 +1311,9 @@ fn get_own_property_descriptors_slow( let own_keys = scope_property_keys(agent, own_keys, gc.nogc()); for key in own_keys { // a. Let desc be ? obj.[[GetOwnProperty]](key). - let desc = obj.internal_get_own_property(agent, key.get(agent), gc.reborrow())?; + let desc = + obj.get(agent) + .internal_get_own_property(agent, key.get(agent), gc.reborrow())?; // b. Let descriptor be FromPropertyDescriptor(desc). let descriptor = PropertyDescriptor::from_property_descriptor(desc, agent, gc.nogc()); // c. If descriptor is not undefined, perform ! CreateDataPropertyOrThrow(descriptors, key, descriptor). 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 92b6edd4c..b69f1b7f2 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 @@ -85,27 +85,27 @@ impl ObjectPrototype { agent: &mut Agent, this_value: Value, arguments: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { let p = to_property_key(agent, arguments.get(0), gc.reborrow())? .unbind() .bind(gc.nogc()); let o = to_object(agent, this_value, gc.nogc())?; - has_own_property(agent, o, p.unbind(), gc.reborrow()).map(|result| result.into()) + has_own_property(agent, o.unbind(), p.unbind(), gc.reborrow()).map(|result| result.into()) } fn is_prototype_of( agent: &mut Agent, this_value: Value, arguments: ArgumentsList, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { let v = arguments.get(0); let Ok(v) = Object::try_from(v) else { return Ok(false.into()); }; let o = to_object(agent, this_value, gc.nogc())?; - let result = is_prototype_of_loop(agent, o, v, gc)?; + let result = is_prototype_of_loop(agent, o.unbind(), v, gc)?; Ok(result.into()) } @@ -113,13 +113,15 @@ impl ObjectPrototype { agent: &mut Agent, this_value: Value, arguments: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { let p = to_property_key(agent, arguments.get(0), gc.reborrow())? .unbind() .bind(gc.nogc()); let o = to_object(agent, this_value, gc.nogc())?; - let desc = o.internal_get_own_property(agent, p.unbind(), gc.reborrow())?; + let desc = o + .unbind() + .internal_get_own_property(agent, p.unbind(), gc.reborrow())?; if let Some(desc) = desc { Ok(desc.enumerable.unwrap_or(false).into()) } else { @@ -131,7 +133,7 @@ impl ObjectPrototype { agent: &mut Agent, this_value: Value, _arguments: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { let o = this_value; let p = PropertyKey::from(BUILTIN_STRING_MEMORY.toString); @@ -142,7 +144,7 @@ impl ObjectPrototype { agent: &mut Agent, this_value: Value, _arguments: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { match this_value { // 1. If the this value is undefined, return "[object Undefined]". @@ -202,7 +204,7 @@ impl ObjectPrototype { let o = to_object(agent, this_value, gc.nogc()).unwrap(); let tag = get( agent, - o, + o.unbind(), WellKnownSymbolIndexes::ToStringTag.into(), gc.reborrow(), )?; @@ -223,7 +225,7 @@ impl ObjectPrototype { let o = to_object(agent, this_value, gc.nogc()).unwrap(); let tag = get( agent, - o, + o.unbind(), WellKnownSymbolIndexes::ToStringTag.into(), gc.reborrow(), )?; @@ -243,7 +245,7 @@ impl ObjectPrototype { agent: &mut Agent, this_value: Value, _arguments: ArgumentsList, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { to_object(agent, this_value, gc.nogc()).map(|result| result.into_value()) } diff --git a/nova_vm/src/ecmascript/builtins/fundamental_objects/symbol_objects/symbol_constructor.rs b/nova_vm/src/ecmascript/builtins/fundamental_objects/symbol_objects/symbol_constructor.rs index d6b260ae6..b79f5ab62 100644 --- a/nova_vm/src/ecmascript/builtins/fundamental_objects/symbol_objects/symbol_constructor.rs +++ b/nova_vm/src/ecmascript/builtins/fundamental_objects/symbol_objects/symbol_constructor.rs @@ -64,7 +64,7 @@ impl SymbolConstructor { _this_value: Value, arguments: ArgumentsList, new_target: Option, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { if new_target.is_some() { return Err(agent.throw_exception_with_static_message( @@ -92,7 +92,7 @@ impl SymbolConstructor { _agent: &mut Agent, _this_value: Value, arguments: ArgumentsList, - _gc: GcScope<'_, '_>, + _gc: GcScope, ) -> JsResult { Ok(arguments.get(0)) } @@ -101,7 +101,7 @@ impl SymbolConstructor { _agent: &mut Agent, _this_value: Value, arguments: ArgumentsList, - _gc: GcScope<'_, '_>, + _gc: GcScope, ) -> JsResult { Ok(arguments.get(0)) } diff --git a/nova_vm/src/ecmascript/builtins/fundamental_objects/symbol_objects/symbol_prototype.rs b/nova_vm/src/ecmascript/builtins/fundamental_objects/symbol_objects/symbol_prototype.rs index fc8c59ac1..c5f3c0b63 100644 --- a/nova_vm/src/ecmascript/builtins/fundamental_objects/symbol_objects/symbol_prototype.rs +++ b/nova_vm/src/ecmascript/builtins/fundamental_objects/symbol_objects/symbol_prototype.rs @@ -75,7 +75,7 @@ impl SymbolPrototype { agent: &mut Agent, this_value: Value, _: ArgumentsList, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { // 1. Let s be the this value. // 2. Let sym be ? ThisSymbolValue(s). @@ -90,7 +90,7 @@ impl SymbolPrototype { agent: &mut Agent, this_value: Value, _: ArgumentsList, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { let symb = this_symbol_value(agent, this_value, gc.nogc())?; Ok(symbol_descriptive_string(agent, symb, gc.nogc()).into_value()) @@ -100,7 +100,7 @@ impl SymbolPrototype { agent: &mut Agent, this_value: Value, _: ArgumentsList, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { this_symbol_value(agent, this_value, gc.nogc()).map(|res| res.into_value()) } diff --git a/nova_vm/src/ecmascript/builtins/global_object.rs b/nova_vm/src/ecmascript/builtins/global_object.rs index c46d975fd..78e8cb12b 100644 --- a/nova_vm/src/ecmascript/builtins/global_object.rs +++ b/nova_vm/src/ecmascript/builtins/global_object.rs @@ -150,7 +150,7 @@ pub fn perform_eval( x: Value, direct: bool, strict_caller: bool, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { // 1. Assert: If direct is false, then strictCaller is also false. assert!(direct || !strict_caller); @@ -373,7 +373,7 @@ pub fn eval_declaration_instantiation( lex_env: EnvironmentIndex, private_env: Option, strict_eval: bool, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult<()> { // 1. Let varNames be the VarDeclaredNames of body. let var_names = script_var_declared_names(script); @@ -713,7 +713,7 @@ impl GlobalObject { agent: &mut Agent, _this_value: Value, arguments: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { let x = arguments.get(0); @@ -728,7 +728,7 @@ impl GlobalObject { agent: &mut Agent, _: Value, arguments: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { let number = arguments.get(0); // 1. Let num be ? ToNumber(number). @@ -749,7 +749,7 @@ impl GlobalObject { agent: &mut Agent, _: Value, arguments: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { let number = arguments.get(0); // 1. Let num be ? ToNumber(number). @@ -767,7 +767,7 @@ impl GlobalObject { agent: &mut Agent, _this_value: Value, arguments: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { if arguments.len() == 0 { return Ok(Value::nan()); @@ -836,7 +836,7 @@ impl GlobalObject { agent: &mut Agent, _this_value: Value, arguments: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { let string = arguments.get(0); let radix = arguments.get(1); @@ -1013,7 +1013,7 @@ impl GlobalObject { _agent: &mut Agent, _this_value: Value, _: ArgumentsList, - _gc: GcScope<'_, '_>, + _gc: GcScope, ) -> JsResult { todo!() } @@ -1021,7 +1021,7 @@ impl GlobalObject { _agent: &mut Agent, _this_value: Value, _: ArgumentsList, - _gc: GcScope<'_, '_>, + _gc: GcScope, ) -> JsResult { todo!() } @@ -1029,7 +1029,7 @@ impl GlobalObject { _agent: &mut Agent, _this_value: Value, _: ArgumentsList, - _gc: GcScope<'_, '_>, + _gc: GcScope, ) -> JsResult { todo!() } @@ -1037,7 +1037,7 @@ impl GlobalObject { _agent: &mut Agent, _this_value: Value, _: ArgumentsList, - _gc: GcScope<'_, '_>, + _gc: GcScope, ) -> JsResult { todo!() } @@ -1045,7 +1045,7 @@ impl GlobalObject { _agent: &mut Agent, _this_value: Value, _: ArgumentsList, - _gc: GcScope<'_, '_>, + _gc: GcScope, ) -> JsResult { todo!() } @@ -1053,7 +1053,7 @@ impl GlobalObject { _agent: &mut Agent, _this_value: Value, _: ArgumentsList, - _gc: GcScope<'_, '_>, + _gc: GcScope, ) -> JsResult { todo!() } diff --git a/nova_vm/src/ecmascript/builtins/indexed_collections/array_objects/array_constructor.rs b/nova_vm/src/ecmascript/builtins/indexed_collections/array_objects/array_constructor.rs index 78f9f624c..d1204a35f 100644 --- a/nova_vm/src/ecmascript/builtins/indexed_collections/array_objects/array_constructor.rs +++ b/nova_vm/src/ecmascript/builtins/indexed_collections/array_objects/array_constructor.rs @@ -98,7 +98,7 @@ impl ArrayConstructor { _this_value: Value, arguments: ArgumentsList, new_target: Option, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { // 1. If NewTarget is undefined, let newTarget be the active function object; else let newTarget be NewTarget. let new_target = new_target.map_or_else( @@ -112,7 +112,9 @@ impl ArrayConstructor { new_target, ProtoIntrinsics::Array, gc.reborrow(), - )?; + )? + .map(|p| p.unbind()) + .map(|p| p.bind(gc.nogc())); // 3. Let numberOfArgs be the number of elements in values. let number_of_args = arguments.len(); @@ -150,6 +152,7 @@ impl ArrayConstructor { } else { // d. Else, // i. Let intLen be ! ToUint32(len). + let proto = proto.map(|p| p.scope(agent, gc.nogc())); let int_len = len.to_uint32(agent, gc.reborrow()).unwrap(); // ii. If SameValueZero(intLen, len) is false, throw a RangeError exception. if !same_value_zero(agent, int_len, len) { @@ -159,9 +162,14 @@ impl ArrayConstructor { gc.nogc(), )); } - let array = - array_create(agent, int_len as usize, int_len as usize, proto, gc.nogc()) - .unwrap(); + let array = array_create( + agent, + int_len as usize, + int_len as usize, + proto.map(|p| p.get(agent)), + gc.nogc(), + ) + .unwrap(); // e. Perform ! Set(array, "length", intLen, true). debug_assert_eq!(agent[array].elements.len(), int_len); array @@ -218,7 +226,7 @@ impl ArrayConstructor { agent: &mut Agent, this_value: Value, arguments: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { let items = arguments.get(0); let mapfn = arguments.get(1); @@ -259,7 +267,9 @@ impl ArrayConstructor { let a = if let Some(c) = is_constructor(agent, this_value) { let scoped_using_iterator = using_iterator.scope(agent, gc.nogc()); // i. Let A be ? Construct(C). - let a = construct(agent, c, None, None, gc.reborrow())?; + let a = construct(agent, c, None, None, gc.reborrow())? + .unbind() + .bind(gc.nogc()); using_iterator = scoped_using_iterator.get(agent).bind(gc.nogc()); a } else { @@ -270,6 +280,8 @@ impl ArrayConstructor { .into_object() }; + let a = a.scope(agent, gc.nogc()); + // c. Let iteratorRecord be ? GetIteratorFromMethod(items, usingIterator). let mut iterator_record = get_iterator_from_method(agent, items, using_iterator.unbind(), gc.reborrow())?; @@ -306,7 +318,7 @@ impl ArrayConstructor { // 1. Perform ? Set(A, "length", ๐”ฝ(k), true). set( agent, - a, + a.get(agent), PropertyKey::from(BUILTIN_STRING_MEMORY.length), fk, true, @@ -314,7 +326,7 @@ impl ArrayConstructor { )?; // 2. Return A. - return Ok(a.into_value()); + return Ok(a.get(agent).into_value()); }; // v. If mapping is true, then @@ -344,8 +356,13 @@ impl ArrayConstructor { }; // vii. Let defineStatus be Completion(CreateDataPropertyOrThrow(A, Pk, mappedValue)). - let define_status = - create_data_property_or_throw(agent, a, pk, mapped_value, gc.reborrow()); + let define_status = create_data_property_or_throw( + agent, + a.get(agent), + pk, + mapped_value, + gc.reborrow(), + ); // viii. IfAbruptCloseIterator(defineStatus, iteratorRecord). let _ = if_abrupt_close_iterator( @@ -362,10 +379,12 @@ impl ArrayConstructor { // 6. NOTE: items is not an Iterable so assume it is an array-like object. // 7. Let arrayLike be ! ToObject(items). - let array_like = to_object(agent, items, gc.nogc()).unwrap(); + let array_like = to_object(agent, items, gc.nogc()) + .unwrap() + .scope(agent, gc.nogc()); // 8. Let len be ? LengthOfArrayLike(arrayLike). - let len = length_of_array_like(agent, array_like, gc.reborrow())?; + let len = length_of_array_like(agent, array_like.get(agent), gc.reborrow())?; let len_value = Value::try_from(len).unwrap(); // 9. If IsConstructor(C) is true, then @@ -378,12 +397,16 @@ impl ArrayConstructor { None, gc.reborrow(), )? + .unbind() + .bind(gc.nogc()) } else { // 10. Else, // a. Let A be ? ArrayCreate(len). array_create(agent, len as usize, len as usize, None, gc.nogc())?.into_object() }; + let a = a.scope(agent, gc.nogc()); + // 11. Let k be 0. let mut k = 0; @@ -397,7 +420,7 @@ impl ArrayConstructor { let pk = PropertyKey::from(sk); // b. Let kValue be ? Get(arrayLike, Pk). - let k_value = get(agent, array_like, pk, gc.reborrow())?; + let k_value = get(agent, array_like.get(agent), pk, gc.reborrow())?; // c. If mapping is true, then let mapped_value = if let Some(mapping) = &mapping { @@ -416,7 +439,7 @@ impl ArrayConstructor { }; // e. Perform ? CreateDataPropertyOrThrow(A, Pk, mappedValue). - create_data_property_or_throw(agent, a, pk, mapped_value, gc.reborrow())?; + create_data_property_or_throw(agent, a.get(agent), pk, mapped_value, gc.reborrow())?; // f. Set k to k + 1. k += 1; @@ -425,7 +448,7 @@ impl ArrayConstructor { // 13. Perform ? Set(A, "length", ๐”ฝ(len), true). set( agent, - a, + a.get(agent), PropertyKey::from(BUILTIN_STRING_MEMORY.length), Value::try_from(len).unwrap(), true, @@ -433,7 +456,7 @@ impl ArrayConstructor { )?; // 14. Return A. - Ok(a.into_value()) + Ok(a.get(agent).into_value()) } /// ### [23.1.2.2 Array.isArray ( arg )](https://tc39.es/ecma262/#sec-array.isarray) @@ -441,7 +464,7 @@ impl ArrayConstructor { agent: &mut Agent, _this_value: Value, arguments: ArgumentsList, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { is_array(agent, arguments.get(0), gc.nogc()).map(Value::Boolean) } @@ -451,7 +474,7 @@ impl ArrayConstructor { agent: &mut Agent, this_value: Value, arguments: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { // 1. Let len be the number of elements in items. let len = arguments.len(); @@ -470,6 +493,8 @@ impl ArrayConstructor { None, gc.reborrow(), )? + .unbind() + .bind(gc.nogc()) } else { // 5. Else, // a. Let A be ? ArrayCreate(len). @@ -479,6 +504,8 @@ impl ArrayConstructor { // 6. Let k be 0. let mut k = 0; + let a = a.scope(agent, gc.nogc()); + // 7. Repeat, while k < len, while k < len { // a. Let kValue be items[k]. @@ -489,7 +516,7 @@ impl ArrayConstructor { let pk = PropertyKey::from(SmallInteger::from(k as u32)); // c. Perform ? CreateDataPropertyOrThrow(A, Pk, kValue). - create_data_property_or_throw(agent, a, pk, k_value, gc.reborrow())?; + create_data_property_or_throw(agent, a.get(agent), pk, k_value, gc.reborrow())?; // d. Set k to k + 1. k += 1; @@ -498,7 +525,7 @@ impl ArrayConstructor { // 8. Perform ? Set(A, "length", lenNumber, true). set( agent, - a, + a.get(agent), PropertyKey::from(BUILTIN_STRING_MEMORY.length), len_number, true, @@ -506,14 +533,14 @@ impl ArrayConstructor { )?; // 9. Return A. - Ok(a.into_value()) + Ok(a.get(agent).into_value()) } fn get_species( _: &mut Agent, this_value: Value, _: ArgumentsList, - _gc: GcScope<'_, '_>, + _gc: GcScope, ) -> JsResult { Ok(this_value) } diff --git a/nova_vm/src/ecmascript/builtins/indexed_collections/array_objects/array_iterator_objects/array_iterator.rs b/nova_vm/src/ecmascript/builtins/indexed_collections/array_objects/array_iterator_objects/array_iterator.rs index 4c59546ed..82ccd9e56 100644 --- a/nova_vm/src/ecmascript/builtins/indexed_collections/array_objects/array_iterator_objects/array_iterator.rs +++ b/nova_vm/src/ecmascript/builtins/indexed_collections/array_objects/array_iterator_objects/array_iterator.rs @@ -67,7 +67,7 @@ impl ArrayIterator<'_> { ) -> Self { agent.heap.create(ArrayIteratorHeapData { object_index: None, - array: Some(array), + array: Some(array.unbind()), next_index: 0, kind, }) @@ -80,13 +80,13 @@ impl IntoValue for ArrayIterator<'_> { } } -impl IntoObject for ArrayIterator<'_> { - fn into_object(self) -> Object { +impl<'a> IntoObject<'a> for ArrayIterator<'a> { + fn into_object(self) -> Object<'a> { self.into() } } -impl From> for Object { +impl<'a> From> for Object<'a> { fn from(value: ArrayIterator) -> Self { Self::ArrayIterator(value.unbind()) } @@ -109,10 +109,10 @@ impl TryFrom for ArrayIterator<'_> { } } -impl TryFrom for ArrayIterator<'_> { +impl<'a> TryFrom> for ArrayIterator<'a> { type Error = (); - fn try_from(value: Object) -> Result { + fn try_from(value: Object<'a>) -> Result { match value { Object::ArrayIterator(data) => Ok(data), _ => Err(()), @@ -120,7 +120,7 @@ impl TryFrom for ArrayIterator<'_> { } } -impl InternalSlots for ArrayIterator<'_> { +impl<'a> InternalSlots<'a> for ArrayIterator<'a> { const DEFAULT_PROTOTYPE: ProtoIntrinsics = ProtoIntrinsics::ArrayIterator; fn get_backing_object(self, agent: &Agent) -> Option> { @@ -135,7 +135,7 @@ impl InternalSlots for ArrayIterator<'_> { } } -impl InternalMethods for ArrayIterator<'_> {} +impl<'a> InternalMethods<'a> for ArrayIterator<'a> {} impl Index> for Agent { type Output = ArrayIteratorHeapData; @@ -212,7 +212,7 @@ pub(crate) enum CollectionIteratorKind { #[derive(Debug, Clone, Copy, Default)] pub struct ArrayIteratorHeapData { pub(crate) object_index: Option>, - pub(crate) array: Option, + pub(crate) array: Option>, pub(crate) next_index: i64, pub(crate) kind: CollectionIteratorKind, } diff --git a/nova_vm/src/ecmascript/builtins/indexed_collections/array_objects/array_iterator_objects/array_iterator_prototype.rs b/nova_vm/src/ecmascript/builtins/indexed_collections/array_objects/array_iterator_objects/array_iterator_prototype.rs index 9e7a8b9aa..43ff6c6b5 100644 --- a/nova_vm/src/ecmascript/builtins/indexed_collections/array_objects/array_iterator_objects/array_iterator_prototype.rs +++ b/nova_vm/src/ecmascript/builtins/indexed_collections/array_objects/array_iterator_objects/array_iterator_prototype.rs @@ -50,7 +50,7 @@ impl ArrayIteratorPrototype { agent: &mut Agent, this_value: Value, _arguments: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { // 27.5.3.2 GeneratorValidate ( generator, generatorBrand ) // 3. If generator.[[GeneratorBrand]] is not generatorBrand, throw a TypeError exception. @@ -66,7 +66,9 @@ impl ArrayIteratorPrototype { // 23.1.5.1 CreateArrayIterator ( array, kind ), step 1. b // NOTE: We set `array` to None when the generator in the spec text has returned. let Some(array) = agent[iterator].array else { - return Ok(create_iter_result_object(agent, Value::Undefined, true).into_value()); + return Ok( + create_iter_result_object(agent, Value::Undefined, true, gc.nogc()).into_value(), + ); }; let len: i64 = match array { @@ -185,7 +187,9 @@ impl ArrayIteratorPrototype { // iii. If index โ‰ฅ len, return NormalCompletion(undefined). if agent[iterator].next_index >= len { agent[iterator].array = None; - return Ok(create_iter_result_object(agent, Value::Undefined, true).into_value()); + return Ok( + create_iter_result_object(agent, Value::Undefined, true, gc.nogc()).into_value(), + ); } // iv. Let indexNumber be ๐”ฝ(index). @@ -241,7 +245,7 @@ impl ArrayIteratorPrototype { }; // vii. Perform ? GeneratorYield(CreateIteratorResultObject(result, false)). - Ok(create_iter_result_object(agent, result, false).into_value()) + Ok(create_iter_result_object(agent, result, false, gc.nogc()).into_value()) } pub(crate) fn create_intrinsic(agent: &mut Agent, realm: RealmIdentifier) { diff --git a/nova_vm/src/ecmascript/builtins/indexed_collections/array_objects/array_prototype.rs b/nova_vm/src/ecmascript/builtins/indexed_collections/array_objects/array_prototype.rs index 4ecfd853b..aa22e309e 100644 --- a/nova_vm/src/ecmascript/builtins/indexed_collections/array_objects/array_prototype.rs +++ b/nova_vm/src/ecmascript/builtins/indexed_collections/array_objects/array_prototype.rs @@ -6,8 +6,12 @@ use std::cmp::Ordering; use small_string::SmallString; -use crate::ecmascript::abstract_operations::operations_on_objects::try_create_data_property_or_throw; -use crate::ecmascript::abstract_operations::type_conversion::try_to_string; +use crate::ecmascript::abstract_operations::operations_on_objects::{ + try_create_data_property_or_throw, try_length_of_array_like, +}; +use crate::ecmascript::abstract_operations::type_conversion::{ + try_to_integer_or_infinity, try_to_string, +}; use crate::engine::context::GcScope; use crate::engine::{unwrap_try, Scoped, TryResult}; use crate::{ @@ -288,15 +292,32 @@ impl ArrayPrototype { agent: &mut Agent, this_value: Value, arguments: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { + let index = arguments.get(0); + // 1. Let O be ? ToObject(this value). - let o = to_object(agent, this_value, gc.nogc())?; + let mut o = to_object(agent, this_value, gc.nogc())?; + let mut scoped_o = None; // 2. Let len be ? LengthOfArrayLike(O). - let len = length_of_array_like(agent, o, gc.reborrow())?; - let index = arguments.get(0); + let len = if let TryResult::Continue(len) = try_length_of_array_like(agent, o, gc.nogc()) { + len? + } else { + scoped_o = Some(o.scope(agent, gc.nogc())); + let result = length_of_array_like(agent, o.unbind(), gc.reborrow())?; + o = scoped_o.as_ref().unwrap().get(agent).bind(gc.nogc()); + result + }; // 3. Let relativeIndex be ? ToIntegerOrInfinity(index). - let relative_index = to_integer_or_infinity(agent, index, gc.reborrow())?.into_i64(); + let relative_index = + if let TryResult::Continue(len) = try_to_integer_or_infinity(agent, index, gc.nogc()) { + len?.into_i64() + } else { + scoped_o = Some(scoped_o.unwrap_or_else(|| o.scope(agent, gc.nogc()))); + let result = to_integer_or_infinity(agent, index, gc.reborrow())?.into_i64(); + o = scoped_o.unwrap().get(agent).bind(gc.nogc()); + result + }; // 4. If relativeIndex โ‰ฅ 0, then let k = if relative_index >= 0 { // a. Let k be relativeIndex. @@ -313,7 +334,7 @@ impl ArrayPrototype { // 7. Return ? Get(O, ! ToString(๐”ฝ(k))). get( agent, - o, + o.unbind(), PropertyKey::Integer(k.try_into().unwrap()), gc.reborrow(), ) @@ -337,25 +358,37 @@ impl ArrayPrototype { agent: &mut Agent, this_value: Value, items: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { // 1. Let O be ? ToObject(this value). let o = to_object(agent, this_value, gc.nogc())?; + let scoped_o = o.scope(agent, gc.nogc()); // 2. Let A be ? ArraySpeciesCreate(O, 0). - let a = array_species_create(agent, o, 0, gc.reborrow())?; + let a = array_species_create(agent, o.unbind(), 0, gc.reborrow())? + .unbind() + .bind(gc.nogc()) + .scope(agent, gc.nogc()); // 3. Let n be 0. let mut n = 0; // 4. Prepend O to items. - let mut items = Vec::from(items.0); - items.insert(0, o.into_value()); + let mut items = items + .0 + .iter() + .map(|i| i.scope(agent, gc.nogc())) + .collect::>(); + items.insert(0, scoped_o.get(agent).into_value().scope(agent, gc.nogc())); // 5. For each element E of items, do for e in items { // a. Let spreadable be ? IsConcatSpreadable(E). - let e_is_spreadable = is_concat_spreadable(agent, e, gc.reborrow())?; + let e_is_spreadable = is_concat_spreadable(agent, e.get(agent), gc.reborrow())?; // b. If spreadable is true, then - if let Some(e) = e_is_spreadable { + if e_is_spreadable { // i. Let len be ? LengthOfArrayLike(E). - let len = length_of_array_like(agent, e, gc.reborrow())?; + let len = length_of_array_like( + agent, + Object::try_from(e.get(agent)).unwrap(), + gc.reborrow(), + )?; // ii. If n + len > 2**53 - 1, throw a TypeError exception. if (n + len) > SmallInteger::MAX_NUMBER { return Err(agent.throw_exception_with_static_message( @@ -371,17 +404,27 @@ impl ArrayPrototype { // 1. Let Pk be ! ToString(๐”ฝ(k)). let pk = PropertyKey::Integer(k.try_into().unwrap()); // 2. Let exists be ? HasProperty(E, Pk). - let exists = has_property(agent, e, pk, gc.reborrow())?; + let exists = has_property( + agent, + Object::try_from(e.get(agent)).unwrap(), + pk, + gc.reborrow(), + )?; // 3. If exists is true, then if exists { // a. Let subElement be ? Get(E, Pk). - let sub_element = get(agent, e, pk, gc.reborrow())?; + let sub_element = get( + agent, + Object::try_from(e.get(agent)).unwrap(), + pk, + gc.reborrow(), + )?; // b. Perform ? CreateDataPropertyOrThrow(A, ! ToString(๐”ฝ(n)), subElement). create_data_property_or_throw( agent, - a, + a.get(agent), PropertyKey::Integer(n.try_into().unwrap()), - sub_element, + sub_element.unbind(), gc.reborrow(), )?; } @@ -404,9 +447,9 @@ impl ArrayPrototype { // iii. Perform ? CreateDataPropertyOrThrow(A, ! ToString(๐”ฝ(n)), E). create_data_property_or_throw( agent, - a, + a.get(agent), PropertyKey::Integer(n.try_into().unwrap()), - e, + e.get(agent), gc.reborrow(), )?; // iv. Set n to n + 1. @@ -416,14 +459,14 @@ impl ArrayPrototype { // 6. Perform ? Set(A, "length", ๐”ฝ(n), true). set( agent, - a, + a.get(agent), BUILTIN_STRING_MEMORY.length.into(), Value::try_from(n).unwrap(), true, gc.reborrow(), )?; // 7. Return A. - Ok(a.into_value()) + Ok(a.get(agent).into_value()) } /// ### [23.1.3.4 Array.prototype.copyWithin ( target, start \[ , end \] )](https://tc39.es/ecma262/#sec-array.prototype.copywithin) @@ -448,7 +491,7 @@ impl ArrayPrototype { agent: &mut Agent, this_value: Value, arguments: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { let target = arguments.get(0); let start = arguments.get(1); @@ -503,9 +546,9 @@ impl ArrayPrototype { } } // 1. Let O be ? ToObject(this value). - let o = to_object(agent, this_value, gc.nogc())?; + let o = to_object(agent, this_value, gc.nogc())?.scope(agent, gc.nogc()); // 2. Let len be ? LengthOfArrayLike(O). - let len: i64 = length_of_array_like(agent, o, gc.reborrow())?; + let len: i64 = length_of_array_like(agent, o.get(agent), gc.reborrow())?; // 3. Let relativeTarget be ? ToIntegerOrInfinity(target). let relative_target = to_integer_or_infinity(agent, target, gc.reborrow())?; @@ -574,18 +617,18 @@ impl ArrayPrototype { // b. Let toKey be ! ToString(๐”ฝ(to)). let to_key = PropertyKey::Integer(to.try_into().unwrap()); // c. Let fromPresent be ? HasProperty(O, fromKey). - let from_present = has_property(agent, o, from_key, gc.reborrow())?; + let from_present = has_property(agent, o.get(agent), from_key, gc.reborrow())?; // d. If fromPresent is true, then if from_present { // i. Let fromValue be ? Get(O, fromKey). - let from_value = get(agent, o, from_key, gc.reborrow())?; + let from_value = get(agent, o.get(agent), from_key, gc.reborrow())?; // ii. Perform ? Set(O, toKey, fromValue, true). - set(agent, o, to_key, from_value, true, gc.reborrow())?; + set(agent, o.get(agent), to_key, from_value, true, gc.reborrow())?; } else { // e. Else, // i. Assert: fromPresent is false. // ii. Perform ? DeletePropertyOrThrow(O, toKey). - delete_property_or_throw(agent, o, to_key, gc.reborrow())?; + delete_property_or_throw(agent, o.get(agent), to_key, gc.reborrow())?; } // f. Set from to from + direction. from += direction; @@ -595,14 +638,14 @@ impl ArrayPrototype { count -= 1; } // 19. Return O. - Ok(o.into_value()) + Ok(o.get(agent).into_value()) } fn entries( agent: &mut Agent, this_value: Value, _: ArgumentsList, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { // 1. Let O be ? ToObject(this value). let Ok(o) = Object::try_from(this_value) else { @@ -656,13 +699,14 @@ impl ArrayPrototype { agent: &mut Agent, this_value: Value, arguments: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { + let callback_fn = arguments.get(0); + let this_arg = arguments.get(1); // 1. Let O be ? ToObject(this value). - let o = to_object(agent, this_value, gc.nogc())?; + let o = to_object(agent, this_value, gc.nogc())?.scope(agent, gc.nogc()); // 2. Let len be ? LengthOfArrayLike(O). - let len = length_of_array_like(agent, o, gc.reborrow())?; - let callback_fn = arguments.get(0); + let len = length_of_array_like(agent, o.get(agent), gc.reborrow())?; // 3. If IsCallable(callbackfn) is false, throw a TypeError exception. let Some(callback_fn) = is_callable(callback_fn, gc.nogc()) else { return Err(agent.throw_exception_with_static_message( @@ -672,7 +716,6 @@ impl ArrayPrototype { )); }; let callback_fn = callback_fn.scope(agent, gc.nogc()); - let this_arg = arguments.get(1); // 4. Let k be 0. let mut k = 0; // 5. Repeat, while k < len, @@ -680,11 +723,11 @@ impl ArrayPrototype { // a. Let Pk be ! ToString(๐”ฝ(k)). let pk = PropertyKey::Integer(k.try_into().unwrap()); // b. Let kPresent be ? HasProperty(O, Pk). - let k_present = has_property(agent, o, pk, gc.reborrow())?; + let k_present = has_property(agent, o.get(agent), pk, gc.reborrow())?; // c. If kPresent is true, then if k_present { // i. Let kValue be ? Get(O, Pk). - let k_value = get(agent, o, pk, gc.reborrow())?; + let k_value = get(agent, o.get(agent), pk, gc.reborrow())?; // ii. Let testResult be ToBoolean(? Call(callbackfn, thisArg, ยซ kValue, ๐”ฝ(k), O ยป)). let f_k = Number::try_from(k).unwrap().into_value(); let test_result = call_function( @@ -731,7 +774,7 @@ impl ArrayPrototype { agent: &mut Agent, this_value: Value, arguments: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { let value = arguments.get(0); let start = arguments.get(1); @@ -777,9 +820,9 @@ impl ArrayPrototype { } }; // 1. Let O be ? ToObject(this value). - let o = to_object(agent, this_value, gc.nogc())?; + let o = to_object(agent, this_value, gc.nogc())?.scope(agent, gc.nogc()); // 2. Let len be ? LengthOfArrayLike(O). - let len = length_of_array_like(agent, o, gc.reborrow())?; + let len = length_of_array_like(agent, o.get(agent), gc.reborrow())?; // 3. Let relativeStart be ? ToIntegerOrInfinity(start). let relative_start = to_integer_or_infinity(agent, start, gc.reborrow())?; @@ -816,12 +859,12 @@ impl ArrayPrototype { // a. Let Pk be ! ToString(๐”ฝ(k)). let pk = PropertyKey::Integer(k.try_into().unwrap()); // b. Perform ? Set(O, Pk, value, true). - set(agent, o, pk, value, true, gc.reborrow())?; + set(agent, o.get(agent), pk, value, true, gc.reborrow())?; // c. Set k to k + 1. k += 1; } // 12. Return O. - Ok(o.into_value()) + Ok(o.get(agent).into_value()) } /// ### [23.1.3.8 Array.prototype.filter ( callbackfn \[ , thisArg \] )](https://tc39.es/ecma262/#sec-array.prototype.filter) @@ -862,15 +905,15 @@ impl ArrayPrototype { agent: &mut Agent, this_value: Value, arguments: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { let callback_fn = arguments.get(0); let this_arg = arguments.get(1); // 1. Let O be ? ToObject(this value). - let o = to_object(agent, this_value, gc.nogc())?; + let o = to_object(agent, this_value, gc.nogc())?.scope(agent, gc.nogc()); // 2. Let len be ? LengthOfArrayLike(O). - let len = length_of_array_like(agent, o, gc.reborrow())?; + let len = length_of_array_like(agent, o.get(agent), gc.reborrow())?; // 3. If IsCallable(callbackfn) is false, throw a TypeError exception. let Some(callback_fn) = is_callable(callback_fn, gc.nogc()) else { return Err(agent.throw_exception_with_static_message( @@ -881,7 +924,9 @@ impl ArrayPrototype { }; let callback_fn = callback_fn.scope(agent, gc.nogc()); // 4. Let A be ? ArraySpeciesCreate(O, 0). - let a = array_species_create(agent, o, 0, gc.reborrow())?; + let a = array_species_create(agent, o.get(agent), 0, gc.reborrow())? + .unbind() + .scope(agent, gc.nogc()); // 5. Let k be 0. let mut k = 0; // 6. Let to be 0. @@ -891,11 +936,11 @@ impl ArrayPrototype { // a. Let Pk be ! ToString(๐”ฝ(k)). let pk = PropertyKey::from(SmallInteger::try_from(k).unwrap()); // b. Let kPresent be ? HasProperty(O, Pk). - let k_present = has_property(agent, o, pk, gc.reborrow())?; + let k_present = has_property(agent, o.get(agent), pk, gc.reborrow())?; // c. If kPresent is true, then if k_present { // i. Let kValue be ? Get(O, Pk). - let k_value = get(agent, o, pk, gc.reborrow())?; + let k_value = get(agent, o.get(agent), pk, gc.reborrow())?; // ii. Let selected be ToBoolean(? Call(callbackfn, thisArg, ยซ kValue, ๐”ฝ(k), O ยป)). let result = call_function( agent, @@ -904,7 +949,7 @@ impl ArrayPrototype { Some(ArgumentsList(&[ k_value, k.try_into().unwrap(), - o.into_value(), + o.get(agent).into_value(), ])), gc.reborrow(), )?; @@ -912,7 +957,13 @@ impl ArrayPrototype { // iii. If selected is true, then if selected { // 1. Perform ? CreateDataPropertyOrThrow(A, ! ToString(๐”ฝ(to)), kValue). - create_data_property_or_throw(agent, a, to.into(), k_value, gc.reborrow())?; + create_data_property_or_throw( + agent, + a.get(agent), + to.into(), + k_value, + gc.reborrow(), + )?; // 2. Set to to to + 1. to += 1; } @@ -921,7 +972,7 @@ impl ArrayPrototype { k += 1; } // 8. Return A. - Ok(a.into_value()) + Ok(a.get(agent).into_value()) } /// ### [23.1.3.9 Array.prototype.find ( predicate \[ , thisArg \] )](https://tc39.es/ecma262/#sec-array.prototype.find) @@ -945,14 +996,15 @@ impl ArrayPrototype { agent: &mut Agent, this_value: Value, arguments: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { - // 1. Let O be ? ToObject(this value). - let o = to_object(agent, this_value, gc.nogc())?; - // 2. Let len be ? LengthOfArrayLike(O). - let len = length_of_array_like(agent, o, gc.reborrow())?; let predicate = arguments.get(0); let this_arg = arguments.get(1); + + // 1. Let O be ? ToObject(this value). + let o = to_object(agent, this_value, gc.nogc())?.scope(agent, gc.nogc()); + // 2. Let len be ? LengthOfArrayLike(O). + let len = length_of_array_like(agent, o.get(agent), gc.reborrow())?; // 3. Let findRec be ? FindViaPredicate(O, len, ascending, predicate, thisArg). let find_rec = find_via_predicate(agent, o, len, true, predicate, this_arg, gc.reborrow())?; // 4. Return findRec.[[Value]]. @@ -980,14 +1032,15 @@ impl ArrayPrototype { agent: &mut Agent, this_value: Value, arguments: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { - // 1. Let O be ? ToObject(this value). - let o = to_object(agent, this_value, gc.nogc())?; - // 2. Let len be ? LengthOfArrayLike(O). - let len = length_of_array_like(agent, o, gc.reborrow())?; let predicate = arguments.get(0); let this_arg = arguments.get(1); + + // 1. Let O be ? ToObject(this value). + let o = to_object(agent, this_value, gc.nogc())?.scope(agent, gc.nogc()); + // 2. Let len be ? LengthOfArrayLike(O). + let len = length_of_array_like(agent, o.get(agent), gc.reborrow())?; // 3. Let findRec be ? FindViaPredicate(O, len, ascending, predicate, thisArg). let find_rec = find_via_predicate(agent, o, len, true, predicate, this_arg, gc.reborrow())?; // 4. Return findRec.[[Index]]. @@ -999,14 +1052,15 @@ impl ArrayPrototype { agent: &mut Agent, this_value: Value, arguments: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { - // 1. Let O be ? ToObject(this value). - let o = to_object(agent, this_value, gc.nogc())?; - // 2. Let len be ? LengthOfArrayLike(O). - let len = length_of_array_like(agent, o, gc.reborrow())?; let predicate = arguments.get(0); let this_arg = arguments.get(1); + + // 1. Let O be ? ToObject(this value). + let o = to_object(agent, this_value, gc.nogc())?.scope(agent, gc.nogc()); + // 2. Let len be ? LengthOfArrayLike(O). + let len = length_of_array_like(agent, o.get(agent), gc.reborrow())?; // 3. Let findRec be ? FindViaPredicate(O, len, descending, predicate, thisArg). let find_rec = find_via_predicate(agent, o, len, false, predicate, this_arg, gc.reborrow())?; @@ -1019,14 +1073,15 @@ impl ArrayPrototype { agent: &mut Agent, this_value: Value, arguments: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { - // 1. Let O be ? ToObject(this value). - let o = to_object(agent, this_value, gc.nogc())?; - // 2. Let len be ? LengthOfArrayLike(O). - let len = length_of_array_like(agent, o, gc.reborrow())?; let predicate = arguments.get(0); let this_arg = arguments.get(1); + + // 1. Let O be ? ToObject(this value). + let o = to_object(agent, this_value, gc.nogc())?.scope(agent, gc.nogc()); + // 2. Let len be ? LengthOfArrayLike(O). + let len = length_of_array_like(agent, o.get(agent), gc.reborrow())?; // 3. Let findRec be ? FindViaPredicate(O, len, descending, predicate, thisArg). let find_rec = find_via_predicate(agent, o, len, false, predicate, this_arg, gc.reborrow())?; @@ -1039,13 +1094,13 @@ impl ArrayPrototype { agent: &mut Agent, this_value: Value, arguments: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { let depth = arguments.get(0); // 1. Let O be ? ToObject(this value). - let o = to_object(agent, this_value, gc.nogc())?; + let o = to_object(agent, this_value, gc.nogc())?.scope(agent, gc.nogc()); // 2. Let sourceLen be ? LengthOfArrayLike(O). - let source_len = length_of_array_like(agent, o, gc.reborrow())? as usize; + let source_len = length_of_array_like(agent, o.get(agent), gc.reborrow())? as usize; // 3. Let depthNum be 1. let mut depth_num = 1; // 4. If depth is not undefined, then @@ -1058,11 +1113,13 @@ impl ArrayPrototype { depth_num = 0; } // 5. Let A be ? ArraySpeciesCreate(O, 0). - let a = array_species_create(agent, o, 0, gc.reborrow())?; + let a = array_species_create(agent, o.get(agent), 0, gc.reborrow())? + .unbind() + .scope(agent, gc.nogc()); // 6. Perform ? FlattenIntoArray(A, O, sourceLen, 0, depthNum). flatten_into_array( agent, - a, + a.clone(), o, source_len, 0, @@ -1072,7 +1129,7 @@ impl ArrayPrototype { gc.reborrow(), )?; // 7. Return A. - Ok(a.into_value()) + Ok(a.get(agent).into_value()) } /// ### [23.1.3.14 Array.prototype.flatMap ( mapperFunction \[ , thisArg \] )](https://tc39.es/ecma262/#sec-array.prototype.flatmap) @@ -1080,15 +1137,15 @@ impl ArrayPrototype { agent: &mut Agent, this_value: Value, arguments: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { let mapper_function = arguments.get(0); let this_arg = arguments.get(1); // 1. Let O be ? ToObject(this value). - let o = to_object(agent, this_value, gc.nogc())?; + let o = to_object(agent, this_value, gc.nogc())?.scope(agent, gc.nogc()); // 2. Let sourceLen be ? LengthOfArrayLike(O). - let source_len = length_of_array_like(agent, o, gc.reborrow())? as usize; + let source_len = length_of_array_like(agent, o.get(agent), gc.reborrow())? as usize; // 3. If IsCallable(mapperFunction) is false, throw a TypeError exception. let Some(mapper_function) = is_callable(mapper_function, gc.nogc()) else { return Err(agent.throw_exception_with_static_message( @@ -1099,11 +1156,13 @@ impl ArrayPrototype { }; let mapper_function = mapper_function.scope(agent, gc.nogc()); // 4. Let A be ? ArraySpeciesCreate(O, 0). - let a = array_species_create(agent, o, 0, gc.reborrow())?; + let a = array_species_create(agent, o.get(agent), 0, gc.reborrow())? + .unbind() + .scope(agent, gc.nogc()); // 5. Perform ? FlattenIntoArray(A, O, sourceLen, 0, 1, mapperFunction, thisArg). flatten_into_array( agent, - a, + a.clone(), o, source_len, 0, @@ -1113,7 +1172,7 @@ impl ArrayPrototype { gc.reborrow(), )?; // 6. Return A. - Ok(a.into_value()) + Ok(a.get(agent).into_value()) } /// ### [23.1.3.15 Array.prototype.forEach ( callbackfn \[ , thisArg \] )](https://tc39.es/ecma262/#sec-array.prototype.foreach) @@ -1154,12 +1213,12 @@ impl ArrayPrototype { agent: &mut Agent, this_value: Value, arguments: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { // 1. Let O be ? ToObject(this value). - let o = to_object(agent, this_value, gc.nogc())?; + let o = to_object(agent, this_value, gc.nogc())?.scope(agent, gc.nogc()); // 2. Let len be ? LengthOfArrayLike(O). - let len = length_of_array_like(agent, o, gc.reborrow())?; + let len = length_of_array_like(agent, o.get(agent), gc.reborrow())?; let callback_fn = arguments.get(0); @@ -1181,11 +1240,11 @@ impl ArrayPrototype { // a. Let Pk be ! ToString(๐”ฝ(k)). let pk = PropertyKey::Integer(k.try_into().unwrap()); // b. Let kPresent be ? HasProperty(O, Pk). - let k_present = has_property(agent, o, pk, gc.reborrow())?; + let k_present = has_property(agent, o.get(agent), pk, gc.reborrow())?; // c. If kPresent is true, then if k_present { // i. Let kValue be ? Get(O, Pk). - let k_value = get(agent, o, pk, gc.reborrow())?; + let k_value = get(agent, o.get(agent), pk, gc.reborrow())?; // ii. Perform ? Call(callbackfn, thisArg, ยซ kValue, ๐”ฝ(k), O ยป). call_function( agent, @@ -1194,7 +1253,7 @@ impl ArrayPrototype { Some(ArgumentsList(&[ k_value, k.try_into().unwrap(), - o.into_value(), + o.get(agent).into_value(), ])), gc.reborrow(), )?; @@ -1239,7 +1298,7 @@ impl ArrayPrototype { agent: &mut Agent, this_value: Value, arguments: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { let search_element = arguments.get(0); let from_index = arguments.get(1); @@ -1285,9 +1344,9 @@ impl ArrayPrototype { } }; // 1. Let O be ? ToObject(this value). - let o = to_object(agent, this_value, gc.nogc())?; + let o = to_object(agent, this_value, gc.nogc())?.scope(agent, gc.nogc()); // 2. Let len be ? LengthOfArrayLike(O). - let len = length_of_array_like(agent, o, gc.reborrow())?; + let len = length_of_array_like(agent, o.get(agent), gc.reborrow())?; // 3. If len = 0, return false. if len == 0 { return Ok(false.into()); @@ -1325,7 +1384,7 @@ impl ArrayPrototype { while k < len { // a. Let elementK be ? Get(O, ! ToString(๐”ฝ(k))). let pk = PropertyKey::Integer(k.try_into().unwrap()); - let element_k = get(agent, o, pk, gc.reborrow())?; + let element_k = get(agent, o.get(agent), pk, gc.reborrow())?; // b. If SameValueZero(searchElement, elementK) is true, return true. if same_value_zero(agent, search_element, element_k) { return Ok(true.into()); @@ -1362,7 +1421,7 @@ impl ArrayPrototype { agent: &mut Agent, this_value: Value, arguments: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { let search_element = arguments.get(0); let from_index = arguments.get(1); @@ -1408,9 +1467,9 @@ impl ArrayPrototype { } }; // 1. Let O be ? ToObject(this value). - let o = to_object(agent, this_value, gc.nogc())?; + let o = to_object(agent, this_value, gc.nogc())?.scope(agent, gc.nogc()); // 2. Let len be ? LengthOfArrayLike(O). - let len = length_of_array_like(agent, o, gc.reborrow())?; + let len = length_of_array_like(agent, o.get(agent), gc.reborrow())?; // 3. If len = 0, return -1๐”ฝ. if len == 0 { return Ok((-1).into()); @@ -1449,11 +1508,11 @@ impl ArrayPrototype { // a. Let Pk be ! ToString(๐”ฝ(k)). let pk = PropertyKey::Integer(k.try_into().unwrap()); // b. Let kPresent be ? HasProperty(O, Pk). - let k_present = has_property(agent, o, pk, gc.reborrow())?; + let k_present = has_property(agent, o.get(agent), pk, gc.reborrow())?; // c. If kPresent is true, then if k_present { // i. Let elementK be ? Get(O, Pk). - let element_k = get(agent, o, pk, gc.reborrow())?; + let element_k = get(agent, o.get(agent), pk, gc.reborrow())?; // ii. If IsStrictlyEqual(searchElement, elementK) is true, return ๐”ฝ(k). if is_strictly_equal(agent, search_element, element_k) { return Ok(k.try_into().unwrap()); @@ -1475,14 +1534,14 @@ impl ArrayPrototype { agent: &mut Agent, this_value: Value, arguments: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { let separator = arguments.get(0); // 1. Let O be ? ToObject(this value). - let o = to_object(agent, this_value, gc.nogc())?; + let o = to_object(agent, this_value, gc.nogc())?.scope(agent, gc.nogc()); // 2. Let len be ? LengthOfArrayLike(O). - let len = length_of_array_like(agent, o, gc.reborrow())?; + let len = length_of_array_like(agent, o.get(agent), gc.reborrow())?; if len == 0 { return Ok(String::EMPTY_STRING.into_value()); } @@ -1504,7 +1563,7 @@ impl ArrayPrototype { // 7. Repeat, while k < len, // b. Let element be ? Get(O, ! ToString(๐”ฝ(k))). { - let element = get(agent, o, 0.into(), gc.reborrow())?; + let element = get(agent, o.get(agent), 0.into(), gc.reborrow())?; // c. If element is neither undefined nor null, then if !element.is_undefined() && !element.is_null() { // i. Let S be ? ToString(element). @@ -1519,7 +1578,7 @@ impl ArrayPrototype { // b. Let element be ? Get(O, ! ToString(๐”ฝ(k))). let element = get( agent, - o, + o.get(agent), SmallInteger::try_from(k as u64).unwrap().into(), gc.reborrow(), )?; @@ -1540,7 +1599,7 @@ impl ArrayPrototype { agent: &mut Agent, this_value: Value, _: ArgumentsList, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { // 1. Let O be ? ToObject(this value). let Ok(o) = Object::try_from(this_value) else { @@ -1579,7 +1638,7 @@ impl ArrayPrototype { agent: &mut Agent, this_value: Value, arguments: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { let search_element = arguments.get(0); let from_index = if arguments.len() > 1 { @@ -1632,9 +1691,9 @@ impl ArrayPrototype { } }; // 1. Let O be ? ToObject(this value). - let o = to_object(agent, this_value, gc.nogc())?; + let o = to_object(agent, this_value, gc.nogc())?.scope(agent, gc.nogc()); // 2. Let len be ? LengthOfArrayLike(O). - let len = length_of_array_like(agent, o, gc.reborrow())?; + let len = length_of_array_like(agent, o.get(agent), gc.reborrow())?; // 3. If len = 0, return -1๐”ฝ. if len == 0 { return Ok((-1).into()); @@ -1665,11 +1724,11 @@ impl ArrayPrototype { // a. Let Pk be ! ToString(๐”ฝ(k)). let pk = PropertyKey::Integer(k.try_into().unwrap()); // b. Let kPresent be ? HasProperty(O, Pk). - let k_present = has_property(agent, o, pk, gc.reborrow())?; + let k_present = has_property(agent, o.get(agent), pk, gc.reborrow())?; // c. If kPresent is true, then if k_present { // i. Let elementK be ? Get(O, Pk). - let element_k = get(agent, o, pk, gc.reborrow())?; + let element_k = get(agent, o.get(agent), pk, gc.reborrow())?; // ii. If IsStrictlyEqual(searchElement, elementK) is true, return ๐”ฝ(k). if is_strictly_equal(agent, search_element, element_k) { return Ok(k.try_into().unwrap()); @@ -1719,15 +1778,15 @@ impl ArrayPrototype { agent: &mut Agent, this_value: Value, arguments: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { let callback_fn = arguments.get(0); let this_arg = arguments.get(1); // 1. Let O be ? ToObject(this value). - let o = to_object(agent, this_value, gc.nogc())?; + let o = to_object(agent, this_value, gc.nogc())?.scope(agent, gc.nogc()); // 2. Let len be ? LengthOfArrayLike(O). - let len = length_of_array_like(agent, o, gc.reborrow())?; + let len = length_of_array_like(agent, o.get(agent), gc.reborrow())?; // 3. If IsCallable(callbackfn) is false, throw a TypeError exception. let Some(callback_fn) = is_callable(callback_fn, gc.nogc()) else { return Err(agent.throw_exception_with_static_message( @@ -1738,7 +1797,9 @@ impl ArrayPrototype { }; let callback_fn = callback_fn.scope(agent, gc.nogc()); // 4. Let A be ? ArraySpeciesCreate(O, len). - let a = array_species_create(agent, o, len as usize, gc.reborrow())?; + let a = array_species_create(agent, o.get(agent), len as usize, gc.reborrow())? + .unbind() + .scope(agent, gc.nogc()); // 5. Let k be 0. let mut k = 0; // 6. Repeat, while k < len, @@ -1746,11 +1807,11 @@ impl ArrayPrototype { // a. Let Pk be ! ToString(๐”ฝ(k)). let pk = PropertyKey::Integer(k.try_into().unwrap()); // b. Let kPresent be ? HasProperty(O, Pk). - let k_present = has_property(agent, o, pk, gc.reborrow())?; + let k_present = has_property(agent, o.get(agent), pk, gc.reborrow())?; // c. If kPresent is true, then if k_present { // i. Let kValue be ? Get(O, Pk). - let k_value = get(agent, o, pk, gc.reborrow())?; + let k_value = get(agent, o.get(agent), pk, gc.reborrow())?; // ii. Let mappedValue be ? Call(callbackfn, thisArg, ยซ kValue, ๐”ฝ(k), O ยป). let mapped_value = call_function( agent, @@ -1759,18 +1820,24 @@ impl ArrayPrototype { Some(ArgumentsList(&[ k_value, k.try_into().unwrap(), - o.into_value(), + o.get(agent).into_value(), ])), gc.reborrow(), )?; // iii. Perform ? CreateDataPropertyOrThrow(A, Pk, mappedValue). - create_data_property_or_throw(agent, a, pk, mapped_value, gc.reborrow())?; + create_data_property_or_throw( + agent, + a.get(agent), + pk, + mapped_value, + gc.reborrow(), + )?; } // d. Set k to k + 1. k += 1; } // 7. Return A. - Ok(a.into_value()) + Ok(a.get(agent).into_value()) } /// ### [23.1.3.22 Array.prototype.pop ( )](https://tc39.es/ecma262/#sec-array.prototype.pop) @@ -1788,7 +1855,7 @@ impl ArrayPrototype { agent: &mut Agent, this_value: Value, _: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { if let Value::Array(array) = this_value { // Fast path: Trivial (no descriptors) array means mutating @@ -1827,15 +1894,15 @@ impl ArrayPrototype { } } // 1. Let O be ? ToObject(this value). - let o = to_object(agent, this_value, gc.nogc())?; + let o = to_object(agent, this_value, gc.nogc())?.scope(agent, gc.nogc()); // 2. Let len be ? LengthOfArrayLike(O). - let len = length_of_array_like(agent, o, gc.reborrow())?; + let len = length_of_array_like(agent, o.get(agent), gc.reborrow())?; // 3. If len = 0, then if len == 0 { // a. Perform ? Set(O, "length", +0๐”ฝ, true). set( agent, - o, + o.get(agent), BUILTIN_STRING_MEMORY.length.into(), 0.into(), true, @@ -1852,13 +1919,13 @@ impl ArrayPrototype { // c. Let index be ! ToString(newLen). let index = PropertyKey::Integer(new_len.try_into().unwrap()); // d. Let element be ? Get(O, index). - let element = get(agent, o, index, gc.reborrow())?; + let element = get(agent, o.get(agent), index, gc.reborrow())?; // e. Perform ? DeletePropertyOrThrow(O, index). - delete_property_or_throw(agent, o, index, gc.reborrow())?; + delete_property_or_throw(agent, o.get(agent), index, gc.reborrow())?; // f. Perform ? Set(O, "length", newLen, true). set( agent, - o, + o.get(agent), BUILTIN_STRING_MEMORY.length.into(), new_len.try_into().unwrap(), true, @@ -1886,12 +1953,12 @@ impl ArrayPrototype { agent: &mut Agent, this_value: Value, items: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { // 1. Let O be ? ToObject(this value). - let o = to_object(agent, this_value, gc.nogc())?; + let o = to_object(agent, this_value, gc.nogc())?.scope(agent, gc.nogc()); // 2. Let len be ? LengthOfArrayLike(O). - let mut len = length_of_array_like(agent, o, gc.reborrow())?; + let mut len = length_of_array_like(agent, o.get(agent), gc.reborrow())?; // 3. Let argCount be the number of elements in items. let arg_count = items.len(); // 4. If len + argCount > 2**53 - 1, throw a TypeError exception. @@ -1902,7 +1969,7 @@ impl ArrayPrototype { gc.nogc(), )); } - if let Object::Array(array) = o { + if let Object::Array(array) = o.get(agent) { // Fast path: Reserve enough room in the array. let Heap { arrays, elements, .. @@ -1916,7 +1983,7 @@ impl ArrayPrototype { // a. Perform ? Set(O, ! ToString(๐”ฝ(len)), E, true). set( agent, - o, + o.get(agent), PropertyKey::Integer(len.try_into().unwrap()), *e, true, @@ -1929,7 +1996,7 @@ impl ArrayPrototype { let len: Value = len.try_into().unwrap(); set( agent, - o, + o.get(agent), BUILTIN_STRING_MEMORY.length.into(), len, true, @@ -1980,7 +2047,7 @@ impl ArrayPrototype { agent: &mut Agent, this_value: Value, arguments: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { let callback_fn = arguments.get(0); let initial_value = if arguments.len() >= 2 { @@ -1990,9 +2057,9 @@ impl ArrayPrototype { }; // 1. Let O be ? ToObject(this value). - let o = to_object(agent, this_value, gc.nogc())?; + let o = to_object(agent, this_value, gc.nogc())?.scope(agent, gc.nogc()); // 2. Let len be ? LengthOfArrayLike(O). - let len = length_of_array_like(agent, o, gc.reborrow())?; + let len = length_of_array_like(agent, o.get(agent), gc.reborrow())?; // 3. If IsCallable(callbackfn) is false, throw a TypeError exception. let Some(callback_fn) = is_callable(callback_fn, gc.nogc()) else { @@ -2031,12 +2098,12 @@ impl ArrayPrototype { let pk = PropertyKey::Integer(k.try_into().unwrap()); // ii. Set kPresent to ? HasProperty(O, Pk). - k_present = has_property(agent, o, pk, gc.reborrow())?; + k_present = has_property(agent, o.get(agent), pk, gc.reborrow())?; // iii. If kPresent is true, then if k_present { // 1. Set accumulator to ? Get(O, Pk). - accumulator = get(agent, o, pk, gc.reborrow())?; + accumulator = get(agent, o.get(agent), pk, gc.reborrow())?; } // iv. Set k to k + 1. @@ -2060,12 +2127,12 @@ impl ArrayPrototype { let pk = PropertyKey::Integer(k_int); // b. Let kPresent be ? HasProperty(O, Pk). - let k_present = has_property(agent, o, pk, gc.reborrow())?; + let k_present = has_property(agent, o.get(agent), pk, gc.reborrow())?; // c. If kPresent is true, then if k_present { // i. Let kValue be ? Get(O, Pk). - let k_value = get(agent, o, pk, gc.reborrow())?; + let k_value = get(agent, o.get(agent), pk, gc.reborrow())?; // ii. Set accumulator to ? Call(callbackfn, undefined, ยซ accumulator, kValue, ๐”ฝ(k), O ยป). accumulator = call_function( @@ -2076,7 +2143,7 @@ impl ArrayPrototype { accumulator, k_value, Number::from(k_int).into_value(), - o.into_value(), + o.get(agent).into_value(), ])), gc.reborrow(), )?; @@ -2130,7 +2197,7 @@ impl ArrayPrototype { agent: &mut Agent, this_value: Value, arguments: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { let callback_fn = arguments.get(0); let initial_value = if arguments.len() >= 2 { @@ -2140,10 +2207,10 @@ impl ArrayPrototype { }; // 1. Let O be ? ToObject(this value). - let o = to_object(agent, this_value, gc.nogc())?; + let o = to_object(agent, this_value, gc.nogc())?.scope(agent, gc.nogc()); // 2. Let len be ? LengthOfArrayLike(O). - let len = length_of_array_like(agent, o, gc.reborrow())?; + let len = length_of_array_like(agent, o.get(agent), gc.reborrow())?; // 3. If IsCallable(callbackfn) is false, throw a TypeError exception. let Some(callback_fn) = is_callable(callback_fn, gc.nogc()) else { @@ -2182,12 +2249,12 @@ impl ArrayPrototype { let pk = PropertyKey::try_from(k).unwrap(); // ii. Set kPresent to ? HasProperty(O, Pk). - k_present = has_property(agent, o, pk, gc.reborrow())?; + k_present = has_property(agent, o.get(agent), pk, gc.reborrow())?; // iii. If kPresent is true, then if k_present { // 1. Set accumulator to ? Get(O, Pk). - accumulator = get(agent, o, pk, gc.reborrow())?; + accumulator = get(agent, o.get(agent), pk, gc.reborrow())?; } // iv. Set k to k - 1. @@ -2210,12 +2277,12 @@ impl ArrayPrototype { let pk = PropertyKey::try_from(k).unwrap(); // b. Let kPresent be ? HasProperty(O, Pk). - let k_present = has_property(agent, o, pk, gc.reborrow())?; + let k_present = has_property(agent, o.get(agent), pk, gc.reborrow())?; // c. If kPresent is true, then if k_present { // i. Let kValue be ? Get(O, Pk). - let k_value = get(agent, o, pk, gc.reborrow())?; + let k_value = get(agent, o.get(agent), pk, gc.reborrow())?; // ii. Set accumulator to ? Call(callbackfn, undefined, ยซ accumulator, kValue, ๐”ฝ(k), O ยป). accumulator = call_function( @@ -2226,7 +2293,7 @@ impl ArrayPrototype { accumulator, k_value, Number::try_from(k).unwrap().into(), - o.into_value(), + o.get(agent).into_value(), ])), gc.reborrow(), )?; @@ -2244,7 +2311,7 @@ impl ArrayPrototype { agent: &mut Agent, this_value: Value, _: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { if let Value::Array(array) = this_value { // Fast path: Array is dense and contains no descriptors. No JS @@ -2256,9 +2323,9 @@ impl ArrayPrototype { } // 1. Let O be ? ToObject(this value). - let o = to_object(agent, this_value, gc.nogc())?; + let o = to_object(agent, this_value, gc.nogc())?.scope(agent, gc.nogc()); // 2. Let len be ? LengthOfArrayLike(O). - let len = length_of_array_like(agent, o, gc.reborrow())?; + let len = length_of_array_like(agent, o.get(agent), gc.reborrow())?; // 3. Let middle be floor(len / 2). let middle = len / 2; // 4. Let lower be 0. @@ -2274,36 +2341,64 @@ impl ArrayPrototype { // d. Let lowerExists be ? HasProperty(O, lowerP). // e. If lowerExists is true, then // i. Let lowerValue be ? Get(O, lowerP). - let lower_exists = has_property(agent, o, lower_p, gc.reborrow())?; + let lower_exists = has_property(agent, o.get(agent), lower_p, gc.reborrow())?; // f. Let upperExists be ? HasProperty(O, upperP). // g. If upperExists is true, then // i. Let upperValue be ? Get(O, upperP). - let upper_exists = has_property(agent, o, upper_p, gc.reborrow())?; + let upper_exists = has_property(agent, o.get(agent), upper_p, gc.reborrow())?; // h. If lowerExists is true and upperExists is true, then if lower_exists && upper_exists { // i. Perform ? Set(O, lowerP, upperValue, true). // ii. Perform ? Set(O, upperP, lowerValue, true). - let lower_value = get(agent, o, lower_p, gc.reborrow())?; - let upper_value = get(agent, o, upper_p, gc.reborrow())?; - set(agent, o, lower_p, upper_value, true, gc.reborrow())?; - set(agent, o, upper_p, lower_value, true, gc.reborrow())?; + let lower_value = get(agent, o.get(agent), lower_p, gc.reborrow())?; + let upper_value = get(agent, o.get(agent), upper_p, gc.reborrow())?; + set( + agent, + o.get(agent), + lower_p, + upper_value, + true, + gc.reborrow(), + )?; + set( + agent, + o.get(agent), + upper_p, + lower_value, + true, + gc.reborrow(), + )?; } // i. Else if lowerExists is false and upperExists is true, then else if !lower_exists && upper_exists { // i. Perform ? Set(O, lowerP, upperValue, true). // ii. Perform ? DeletePropertyOrThrow(O, upperP). - let upper_value = get(agent, o, upper_p, gc.reborrow())?; - set(agent, o, lower_p, upper_value, true, gc.reborrow())?; - delete_property_or_throw(agent, o, upper_p, gc.reborrow())?; + let upper_value = get(agent, o.get(agent), upper_p, gc.reborrow())?; + set( + agent, + o.get(agent), + lower_p, + upper_value, + true, + gc.reborrow(), + )?; + delete_property_or_throw(agent, o.get(agent), upper_p, gc.reborrow())?; } // j. Else if lowerExists is true and upperExists is false, then else if lower_exists && !upper_exists { // i. Perform ? DeletePropertyOrThrow(O, lowerP). // ii. Perform ? Set(O, upperP, lowerValue, true). - let lower_value = get(agent, o, lower_p, gc.reborrow())?; - delete_property_or_throw(agent, o, lower_p, gc.reborrow())?; - set(agent, o, upper_p, lower_value, true, gc.reborrow())?; + let lower_value = get(agent, o.get(agent), lower_p, gc.reborrow())?; + delete_property_or_throw(agent, o.get(agent), lower_p, gc.reborrow())?; + set( + agent, + o.get(agent), + upper_p, + lower_value, + true, + gc.reborrow(), + )?; } // k. Else, else { @@ -2315,7 +2410,7 @@ impl ArrayPrototype { lower += 1; } // 6. Return O. - Ok(o.into_value()) + Ok(o.get(agent).into_value()) } /// ### [23.1.3.27 Array.prototype.shift ( )](https://tc39.es/ecma262/#sec-array.prototype.shift) @@ -2331,7 +2426,7 @@ impl ArrayPrototype { agent: &mut Agent, this_value: Value, _: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { if let Value::Array(array) = this_value { if array.is_empty(agent) { @@ -2376,15 +2471,15 @@ impl ArrayPrototype { } } // 1. Let O be ? ToObject(this value). - let o = to_object(agent, this_value, gc.nogc())?; + let o = to_object(agent, this_value, gc.nogc())?.scope(agent, gc.nogc()); // 2. Let len be ? LengthOfArrayLike(O). - let len = length_of_array_like(agent, o, gc.reborrow())?; + let len = length_of_array_like(agent, o.get(agent), gc.reborrow())?; // 3. If len = 0, then if len == 0 { // a. Perform ? Set(O, "length", +0๐”ฝ, true). set( agent, - o, + o.get(agent), BUILTIN_STRING_MEMORY.length.into(), 0.into(), true, @@ -2394,7 +2489,7 @@ impl ArrayPrototype { return Ok(Value::Undefined); } // 4. Let first be ? Get(O, "0"). - let first = get(agent, o, 0.into(), gc.reborrow())?; + let first = get(agent, o.get(agent), 0.into(), gc.reborrow())?; // 5. Let k be 1. let mut k = 1; // 6. Repeat, while k < len, @@ -2404,28 +2499,33 @@ impl ArrayPrototype { // b. Let to be ! ToString(๐”ฝ(k - 1)). let to = (k - 1).try_into().unwrap(); // c. Let fromPresent be ? HasProperty(O, from). - let from_present = has_property(agent, o, from, gc.reborrow())?; + let from_present = has_property(agent, o.get(agent), from, gc.reborrow())?; // d. If fromPresent is true, then if from_present { // i. Let fromValue be ? Get(O, from). - let from_value = get(agent, o, from, gc.reborrow())?; + let from_value = get(agent, o.get(agent), from, gc.reborrow())?; // ii. Perform ? Set(O, to, fromValue, true). - set(agent, o, to, from_value, true, gc.reborrow())?; + set(agent, o.get(agent), to, from_value, true, gc.reborrow())?; } else { // e. Else, // i. Assert: fromPresent is false. // ii. Perform ? DeletePropertyOrThrow(O, to). - delete_property_or_throw(agent, o, to, gc.reborrow())?; + delete_property_or_throw(agent, o.get(agent), to, gc.reborrow())?; } // f. Set k to k + 1. k += 1; } // 7. Perform ? DeletePropertyOrThrow(O, ! ToString(๐”ฝ(len - 1))). - delete_property_or_throw(agent, o, (len - 1).try_into().unwrap(), gc.reborrow())?; + delete_property_or_throw( + agent, + o.get(agent), + (len - 1).try_into().unwrap(), + gc.reborrow(), + )?; // 8. Perform ? Set(O, "length", ๐”ฝ(len - 1), true). set( agent, - o, + o.get(agent), BUILTIN_STRING_MEMORY.length.into(), (len - 1).try_into().unwrap(), true, @@ -2456,7 +2556,7 @@ impl ArrayPrototype { agent: &mut Agent, this_value: Value, arguments: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { let start = arguments.get(0); let end = arguments.get(1); @@ -2466,6 +2566,7 @@ impl ArrayPrototype { Value::Undefined | Value::Integer(_), ) = (this_value, start, end) { + let array = array.bind(gc.nogc()); let len = array.len(agent) as usize; if array.is_trivial(agent) && array.is_dense(agent) { let start = if let Value::Integer(relative_start) = start { @@ -2488,26 +2589,34 @@ impl ArrayPrototype { } else { len }; + let array = array.scope(agent, gc.nogc()); let count = end.saturating_sub(start); - let a = array_species_create(agent, array.into_object(), count, gc.reborrow())?; + let a = array_species_create( + agent, + array.get(agent).into_object(), + count, + gc.reborrow(), + )? + .unbind() + .scope(agent, gc.nogc()); if count == 0 { set( agent, - a, + a.get(agent), BUILTIN_STRING_MEMORY.length.into(), 0.into(), true, gc.reborrow(), )?; - return Ok(a.into_value()); + return Ok(a.get(agent).into_value()); } - if let Object::Array(a) = a { + if let Object::Array(a) = a.get(agent) { if a.len(agent) as usize == count && a.is_trivial(agent) && a.as_slice(agent).iter().all(|el| el.is_none()) { // Array full of holes - let source_data = array.as_slice(agent)[start..end].as_ptr(); + let source_data = array.get(agent).as_slice(agent)[start..end].as_ptr(); let destination_data = a.as_mut_slice(agent).as_mut_ptr(); // SAFETY: Source and destination are properly aligned // and valid for reads/writes. They do not overlap. @@ -2536,9 +2645,15 @@ impl ArrayPrototype { // Note: Array is dense, we do not need to check this. // c. If kPresent is true, then // i. Let kValue be ? Get(O, Pk). - let k_value = array.as_slice(agent)[k].unwrap(); + let k_value = array.get(agent).as_slice(agent)[k].unwrap(); // ii. Perform ? CreateDataPropertyOrThrow(A, ! ToString(๐”ฝ(n)), kValue). - create_data_property_or_throw(agent, a, n.into(), k_value, gc.reborrow())?; + create_data_property_or_throw( + agent, + a.get(agent), + n.into(), + k_value, + gc.reborrow(), + )?; // d. Set k to k + 1. k += 1; // e. Set n to n + 1. @@ -2547,20 +2662,20 @@ impl ArrayPrototype { // 15. Perform ? Set(A, "length", ๐”ฝ(n), true). set( agent, - a.into_object(), + a.get(agent).into_object(), BUILTIN_STRING_MEMORY.length.into(), n.into(), true, gc.reborrow(), )?; // 16. Return A. - return Ok(a.into_value()); + return Ok(a.get(agent).into_value()); } } // 1. Let O be ? ToObject(this value). - let o = to_object(agent, this_value, gc.nogc())?; + let o = to_object(agent, this_value, gc.nogc())?.scope(agent, gc.nogc()); // 2. Let len be ? LengthOfArrayLike(O). - let len = length_of_array_like(agent, o, gc.reborrow())? as usize; + let len = length_of_array_like(agent, o.get(agent), gc.reborrow())? as usize; // 3. Let relativeStart be ? ToIntegerOrInfinity(start). let relative_start = to_integer_or_infinity(agent, start, gc.reborrow())?; // 4. If relativeStart = -โˆž, let k be 0. @@ -2593,7 +2708,9 @@ impl ArrayPrototype { // 11. Let count be max(final - k, 0). let count = final_end.saturating_sub(k); // 12. Let A be ? ArraySpeciesCreate(O, count). - let a = array_species_create(agent, o, count, gc.reborrow())?; + let a = array_species_create(agent, o.get(agent), count, gc.reborrow())? + .unbind() + .scope(agent, gc.nogc()); // 13. Let n be 0. let mut n = 0u32; // 14. Repeat, while k < final, @@ -2601,13 +2718,19 @@ impl ArrayPrototype { // a. Let Pk be ! ToString(๐”ฝ(k)). let pk = k.try_into().unwrap(); // b. Let kPresent be ? HasProperty(O, Pk). - let k_present = has_property(agent, o, pk, gc.reborrow())?; + let k_present = has_property(agent, o.get(agent), pk, gc.reborrow())?; // c. If kPresent is true, then if k_present { // i. Let kValue be ? Get(O, Pk). - let k_value = get(agent, o, pk, gc.reborrow())?; + let k_value = get(agent, o.get(agent), pk, gc.reborrow())?; // ii. Perform ? CreateDataPropertyOrThrow(A, ! ToString(๐”ฝ(n)), kValue). - create_data_property_or_throw(agent, a, n.into(), k_value, gc.reborrow())?; + create_data_property_or_throw( + agent, + a.get(agent), + n.into(), + k_value, + gc.reborrow(), + )?; } // d. Set k to k + 1. k += 1; @@ -2617,14 +2740,14 @@ impl ArrayPrototype { // 15. Perform ? Set(A, "length", ๐”ฝ(n), true). set( agent, - a, + a.get(agent), BUILTIN_STRING_MEMORY.length.into(), n.into(), true, gc.reborrow(), )?; // 16. Return A. - Ok(a.into_value()) + Ok(a.get(agent).into_value()) } /// ### 23.1.3.29 Array.prototype.some ( callbackfn \[ , thisArg \] )(https://tc39.es/ecma262/#sec-array.prototype.some) @@ -2669,15 +2792,15 @@ impl ArrayPrototype { agent: &mut Agent, this_value: Value, arguments: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { let callback_fn = arguments.get(0); let this_arg = arguments.get(1); // 1. Let O be ? ToObject(this value). - let o = to_object(agent, this_value, gc.nogc())?; + let o = to_object(agent, this_value, gc.nogc())?.scope(agent, gc.nogc()); // 2. Let len be ? LengthOfArrayLike(O). - let len = length_of_array_like(agent, o, gc.reborrow())?; + let len = length_of_array_like(agent, o.get(agent), gc.reborrow())?; // 3. If IsCallable(callbackfn) is false, throw a TypeError exception. let Some(callback_fn) = is_callable(callback_fn, gc.nogc()) else { return Err(agent.throw_exception_with_static_message( @@ -2694,11 +2817,11 @@ impl ArrayPrototype { // a. Let Pk be ! ToString(๐”ฝ(k)). let pk = k.try_into().unwrap(); // b. Let kPresent be ? HasProperty(O, Pk). - let k_present = has_property(agent, o, pk, gc.reborrow())?; + let k_present = has_property(agent, o.get(agent), pk, gc.reborrow())?; // c. If kPresent is true, then if k_present { // i. Let kValue be ? Get(O, Pk). - let k_value = get(agent, o, pk, gc.reborrow())?; + let k_value = get(agent, o.get(agent), pk, gc.reborrow())?; // ii. Let testResult be ToBoolean(? Call(callbackfn, thisArg, ยซ kValue, ๐”ฝ(k), O ยป)). let test_result = call_function( agent, @@ -2707,7 +2830,7 @@ impl ArrayPrototype { Some(ArgumentsList(&[ k_value, k.try_into().unwrap(), - o.into_value(), + o.get(agent).into_value(), ])), gc.reborrow(), )?; @@ -2751,7 +2874,7 @@ impl ArrayPrototype { agent: &mut Agent, this_value: Value, args: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { let comparator = args.get(0); // 1. If comparator is not undefined and IsCallable(comparator) is false, throw a TypeError exception. @@ -2767,17 +2890,23 @@ impl ArrayPrototype { )); }; // 2. Let obj be ? ToObject(this value). - let obj = to_object(agent, this_value, gc.nogc())?; + let obj = to_object(agent, this_value, gc.nogc())?.scope(agent, gc.nogc()); // 3. Let len be ? LengthOfArrayLike(obj). - let len = usize::try_from(length_of_array_like(agent, obj, gc.reborrow())?).unwrap(); + let len = + usize::try_from(length_of_array_like(agent, obj.get(agent), gc.reborrow())?).unwrap(); // 4. Let SortCompare be a new Abstract Closure with parameters (x, y) // that captures comparator and performs the following steps when // called: // a. Return ? CompareArrayElements(x, y, comparator). // 5. Let sortedList be ? SortIndexedProperties(obj, len, SortCompare, // skip-holes). - let sorted_list: Vec = - sort_indexed_properties::(agent, obj, len, comparator, gc.reborrow())?; + let sorted_list: Vec = sort_indexed_properties::( + agent, + obj.get(agent), + len, + comparator, + gc.reborrow(), + )?; // 6. Let itemCount be the number of elements in sortedList. let item_count = sorted_list.len(); // 7. Let j be 0. @@ -2787,7 +2916,7 @@ impl ArrayPrototype { // a. Perform ? Set(obj, ! ToString(๐”ฝ(j)), sortedList[j], true). set( agent, - obj, + obj.get(agent), j.try_into().unwrap(), sorted_list[j], true, @@ -2803,19 +2932,19 @@ impl ArrayPrototype { // 10. Repeat, while j < len, while j < len { // a. Perform ? DeletePropertyOrThrow(obj, ! ToString(๐”ฝ(j))). - delete_property_or_throw(agent, obj, j.try_into().unwrap(), gc.reborrow())?; + delete_property_or_throw(agent, obj.get(agent), j.try_into().unwrap(), gc.reborrow())?; // b. Set j to j + 1. j += 1; } // 11. Return obj. - Ok(obj.into_value()) + Ok(obj.get(agent).into_value()) } fn splice( agent: &mut Agent, this_value: Value, arguments: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { let start = arguments.get(0); let delete_count = arguments.get(1); @@ -2825,9 +2954,9 @@ impl ArrayPrototype { &[] }; // 1. Let O be ? ToObject(this value). - let o = to_object(agent, this_value, gc.nogc())?; + let o = to_object(agent, this_value, gc.nogc())?.scope(agent, gc.nogc()); // 2. Let len be ? LengthOfArrayLike(O). - let len = length_of_array_like(agent, o, gc.reborrow())?; + let len = length_of_array_like(agent, o.get(agent), gc.reborrow())?; // 3. Let relativeStart be ? ToIntegerOrInfinity(start). let relative_start = to_integer_or_infinity(agent, start, gc.reborrow())?; let actual_start = if relative_start.is_neg_infinity() { @@ -2866,7 +2995,9 @@ impl ArrayPrototype { )); } // 12. Let A be ? ArraySpeciesCreate(O, actualDeleteCount). - let a = array_species_create(agent, o, actual_delete_count, gc.reborrow())?; + let a = array_species_create(agent, o.get(agent), actual_delete_count, gc.reborrow())? + .unbind() + .scope(agent, gc.nogc()); // 13. Let k be 0. let mut k = 0; // 14. Repeat, while k < actualDeleteCount, @@ -2874,13 +3005,13 @@ impl ArrayPrototype { // a. Let from be ! ToString(๐”ฝ(actualStart + k)). let from = (actual_start + k).try_into().unwrap(); // b. If ? HasProperty(O, from) is true, then - if has_property(agent, o, from, gc.reborrow())? { + if has_property(agent, o.get(agent), from, gc.reborrow())? { // i. Let fromValue be ? Get(O, from). - let from_value = get(agent, o, from, gc.reborrow())?; + let from_value = get(agent, o.get(agent), from, gc.reborrow())?; // ii. Perform ? CreateDataPropertyOrThrow(A, ! ToString(๐”ฝ(k)), fromValue). create_data_property_or_throw( agent, - a, + a.get(agent), k.try_into().unwrap(), from_value, gc.reborrow(), @@ -2892,7 +3023,7 @@ impl ArrayPrototype { // 15. Perform ? Set(A, "length", ๐”ฝ(actualDeleteCount), true). set( agent, - a, + a.get(agent), BUILTIN_STRING_MEMORY.length.into(), (actual_delete_count as i64).try_into().unwrap(), true, @@ -2910,15 +3041,15 @@ impl ArrayPrototype { // ii. Let to be ! ToString(๐”ฝ(k + itemCount)). let to = (k + item_count).try_into().unwrap(); // iii. If ? HasProperty(O, from) is true, then - if has_property(agent, o, from, gc.reborrow())? { + if has_property(agent, o.get(agent), from, gc.reborrow())? { // 1. Let fromValue be ? Get(O, from). - let from_value = get(agent, o, from, gc.reborrow())?; + let from_value = get(agent, o.get(agent), from, gc.reborrow())?; // 2. Perform ? Set(O, to, fromValue, true). - set(agent, o, to, from_value, true, gc.reborrow())?; + set(agent, o.get(agent), to, from_value, true, gc.reborrow())?; } else { // iv. Else, // 1. Perform ? DeletePropertyOrThrow(O, to). - delete_property_or_throw(agent, o, to, gc.reborrow())?; + delete_property_or_throw(agent, o.get(agent), to, gc.reborrow())?; } k += 1; // v. Set k to k + 1. @@ -2928,7 +3059,12 @@ impl ArrayPrototype { // d. Repeat, while k > (len - actualDeleteCount + itemCount), while k > (len as usize - actual_delete_count + item_count) { // i. Perform ? DeletePropertyOrThrow(O, ! ToString(๐”ฝ(k - 1))). - delete_property_or_throw(agent, o, (k - 1).try_into().unwrap(), gc.reborrow())?; + delete_property_or_throw( + agent, + o.get(agent), + (k - 1).try_into().unwrap(), + gc.reborrow(), + )?; // ii. Set k to k - 1. k -= 1; } @@ -2944,15 +3080,15 @@ impl ArrayPrototype { // ii. Let to be ! ToString(๐”ฝ(k + itemCount - 1)). let to = (k + item_count - 1).try_into().unwrap(); // iii. If ? HasProperty(O, from) is true, then - if has_property(agent, o, from, gc.reborrow())? { + if has_property(agent, o.get(agent), from, gc.reborrow())? { // 1. Let fromValue be ? Get(O, from). - let from_value = get(agent, o, from, gc.reborrow())?; + let from_value = get(agent, o.get(agent), from, gc.reborrow())?; // 2. Perform ? Set(O, to, fromValue, true). - set(agent, o, to, from_value, true, gc.reborrow())?; + set(agent, o.get(agent), to, from_value, true, gc.reborrow())?; } else { // iv. Else, // 1. Perform ? DeletePropertyOrThrow(O, to). - delete_property_or_throw(agent, o, to, gc.reborrow())?; + delete_property_or_throw(agent, o.get(agent), to, gc.reborrow())?; } // v. Set k to k - 1. k -= 1; @@ -2965,14 +3101,21 @@ impl ArrayPrototype { // 19. For each element E of items, do for e in items { // a. Perform ? Set(O, ! ToString(๐”ฝ(k)), E, true). - set(agent, o, k.try_into().unwrap(), *e, true, gc.reborrow())?; + set( + agent, + o.get(agent), + k.try_into().unwrap(), + *e, + true, + gc.reborrow(), + )?; // b. Set k to k + 1. k += 1; } // 20. Perform ? Set(O, "length", ๐”ฝ(len - actualDeleteCount + itemCount), true). set( agent, - o, + o.get(agent), BUILTIN_STRING_MEMORY.length.into(), (len as i64 - actual_delete_count as i64 + item_count as i64) .try_into() @@ -2981,14 +3124,14 @@ impl ArrayPrototype { gc.reborrow(), )?; // 21. Return A. - Ok(a.into_value()) + Ok(a.get(agent).into_value()) } fn to_locale_string( _agent: &mut Agent, _this_value: Value, _: ArgumentsList, - _gc: GcScope<'_, '_>, + _gc: GcScope, ) -> JsResult { todo!(); } @@ -2997,7 +3140,7 @@ impl ArrayPrototype { agent: &mut Agent, this_value: Value, _: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { if let Value::Array(array) = this_value { let array = array.bind(gc.nogc()); @@ -3014,7 +3157,7 @@ impl ArrayPrototype { let o = to_object(agent, this_value, gc.nogc())?; let scoped_o = o.scope(agent, gc.nogc()); // 2. Let len be ? LengthOfArrayLike(O). - let len = length_of_array_like(agent, o, gc.reborrow())?; + let len = length_of_array_like(agent, o.unbind(), gc.reborrow())?; // 3. Let A be ? ArrayCreate(len). let a = array_create(agent, len as usize, len as usize, None, gc.nogc())? .scope(agent, gc.nogc()); @@ -3049,7 +3192,7 @@ impl ArrayPrototype { agent: &mut Agent, this_value: Value, args: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { let comparator = args.get(0); // 1. If comparator is not undefined and IsCallable(comparator) is false, throw a TypeError exception. @@ -3065,9 +3208,10 @@ impl ArrayPrototype { )); }; // 2. Let o be ? ToObject(this value). - let o = to_object(agent, this_value, gc.nogc())?; + let o = to_object(agent, this_value, gc.nogc())?.scope(agent, gc.nogc()); // 3. Let len be ? LengthOfArrayLike(obj). - let len = usize::try_from(length_of_array_like(agent, o, gc.reborrow())?).unwrap(); + let len = + usize::try_from(length_of_array_like(agent, o.get(agent), gc.reborrow())?).unwrap(); // 4. Let A be ? ArrayCreate(len). let a = array_create(agent, len, len, None, gc.nogc())?.scope(agent, gc.nogc()); // 5. Let SortCompare be a new Abstract Closure with parameters (x, y) @@ -3075,8 +3219,13 @@ impl ArrayPrototype { // called: // a. Return ? CompareArrayElements(x, y, comparator). // 6. Let sortedList be ? SortIndexedProperties(O, len, SortCompare, read-through-holes). - let sorted_list: Vec = - sort_indexed_properties::(agent, o, len, comparator, gc.reborrow())?; + let sorted_list: Vec = sort_indexed_properties::( + agent, + o.get(agent), + len, + comparator, + gc.reborrow(), + )?; // 7. Let j be 0. // 8. Repeat, while j < len, // a. Perform ! CreateDataPropertyOrThrow(A, ! ToString(๐”ฝ(j)), sortedList[j]). @@ -3098,7 +3247,7 @@ impl ArrayPrototype { _agent: &mut Agent, _this_value: Value, _: ArgumentsList, - _gc: GcScope<'_, '_>, + _gc: GcScope, ) -> JsResult { todo!(); } @@ -3108,14 +3257,14 @@ impl ArrayPrototype { agent: &mut Agent, this_value: Value, _: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { // 1. Let array be ? ToObject(this value). - let array = to_object(agent, this_value, gc.nogc())?; + let array = to_object(agent, this_value, gc.nogc())?.scope(agent, gc.nogc()); // 2. Let func be ? Get(array, "join"). let func = get( agent, - array, + array.get(agent), BUILTIN_STRING_MEMORY.join.into(), gc.reborrow(), )?; @@ -3128,7 +3277,13 @@ impl ArrayPrototype { .into_function() }); // 4. Return ? Call(func, array). - call_function(agent, func.unbind(), array.into_value(), None, gc) + call_function( + agent, + func.unbind(), + array.get(agent).into_value(), + None, + gc, + ) } /// ### [23.1.3.37 Array.prototype.unshift ( ...items )](https://tc39.es/ecma262/#sec-array.prototype.unshift) @@ -3146,7 +3301,7 @@ impl ArrayPrototype { agent: &mut Agent, this_value: Value, items: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { // Fast path: Array is dense and contains no descriptors. No JS // functions can thus be called by unshift. @@ -3178,9 +3333,9 @@ impl ArrayPrototype { } } // 1. Let O be ? ToObject(this value). - let o = to_object(agent, this_value, gc.nogc())?; + let o = to_object(agent, this_value, gc.nogc())?.scope(agent, gc.nogc()); // 2. Let len be ? LengthOfArrayLike(O). - let len = length_of_array_like(agent, o, gc.reborrow())?; + let len = length_of_array_like(agent, o.get(agent), gc.reborrow())?; // 3. Let argCount be the number of elements in items. let arg_count = items.len(); // 4. If argCount > 0, then @@ -3202,18 +3357,18 @@ impl ArrayPrototype { // ii. Let to be !ย ToString(๐”ฝ(k + argCount - 1)). let to = (k + arg_count as i64 - 1).try_into().unwrap(); // iii. Let fromPresent be ? HasProperty(O, from). - let from_present = has_property(agent, o, from, gc.reborrow())?; + let from_present = has_property(agent, o.get(agent), from, gc.reborrow())?; // iv. If fromPresent is true, then if from_present { // 1. Let fromValue be ?ย Get(O, from). - let from_value = get(agent, o, from, gc.reborrow())?; + let from_value = get(agent, o.get(agent), from, gc.reborrow())?; // 2. Perform ?ย Set(O, to, fromValue, true). - set(agent, o, to, from_value, true, gc.reborrow())?; + set(agent, o.get(agent), to, from_value, true, gc.reborrow())?; } else { // v. Else, // 1. Assert: fromPresent is false. // 2. Perform ? DeletePropertyOrThrow(O, to). - delete_property_or_throw(agent, o, to, gc.reborrow())?; + delete_property_or_throw(agent, o.get(agent), to, gc.reborrow())?; } // vi. Set k to k - 1. k -= 1; @@ -3223,14 +3378,21 @@ impl ArrayPrototype { for (j, e) in items.iter().enumerate() { // i. Perform ?ย Set(O, !ย ToString(j), E, true). // ii. Set j to j + 1๐”ฝ. - set(agent, o, j.try_into().unwrap(), *e, true, gc.reborrow())?; + set( + agent, + o.get(agent), + j.try_into().unwrap(), + *e, + true, + gc.reborrow(), + )?; } } // 5. Perform ?ย Set(O, "length", ๐”ฝ(len + argCount), true). let len: Value = (len + arg_count as i64).try_into().unwrap(); set( agent, - o, + o.get(agent), BUILTIN_STRING_MEMORY.length.into(), len, true, @@ -3244,7 +3406,7 @@ impl ArrayPrototype { agent: &mut Agent, this_value: Value, _: ArgumentsList, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { // 1. Let O be ? ToObject(this value). let Ok(o) = Object::try_from(this_value) else { @@ -3263,7 +3425,7 @@ impl ArrayPrototype { agent: &mut Agent, this_value: Value, arguments: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { let index = arguments.get(0); let value = arguments.get(1); @@ -3292,9 +3454,9 @@ impl ArrayPrototype { } } // 1. Let O be ? ToObject(this value). - let o = to_object(agent, this_value, gc.nogc())?; + let o = to_object(agent, this_value, gc.nogc())?.scope(agent, gc.nogc()); // 2. Let len be ? LengthOfArrayLike(O). - let len = length_of_array_like(agent, o, gc.reborrow())?; + let len = length_of_array_like(agent, o.get(agent), gc.reborrow())?; // 3. Let relativeIndex be ? ToIntegerOrInfinity(index). let relative_index = to_integer_or_infinity(agent, index, gc.reborrow())?.into_i64(); // 4. If relativeIndex โ‰ฅ 0, let actualIndex be relativeIndex. @@ -3326,7 +3488,7 @@ impl ArrayPrototype { value // c. Else, let fromValue be ? Get(O, Pk). } else { - get(agent, o, pk, gc.reborrow())? + get(agent, o.get(agent), pk, gc.reborrow())? }; // d. Perform ! CreateDataPropertyOrThrow(A, Pk, fromValue). unwrap_try(try_create_data_property_or_throw( @@ -3459,42 +3621,39 @@ impl ArrayPrototype { /// The abstract operation IsConcatSpreadable takes argument O (an ECMAScript /// language value) and returns either a normal completion containing a Boolean /// or a throw completion. -/// -/// > Note: Instead of returning a bool, Nova returns an Option. -fn is_concat_spreadable( +fn is_concat_spreadable<'a>( agent: &mut Agent, o: Value, - mut gc: GcScope<'_, '_>, -) -> JsResult> { + mut gc: GcScope<'a, '_>, +) -> JsResult { // 1. If O is not an Object, return false. - if let Ok(o) = Object::try_from(o) { - // 2. Let spreadable be ? Get(O, @@isConcatSpreadable). - let spreadable = get( - agent, - o, - WellKnownSymbolIndexes::IsConcatSpreadable.into(), - gc.reborrow(), - )?; - // 3. If spreadable is not undefined, return ToBoolean(spreadable). - if !spreadable.is_undefined() { - let spreadable = to_boolean(agent, spreadable); - if spreadable { - Ok(Some(o)) - } else { - Ok(None) - } + let Ok(o) = Object::try_from(o) else { + return Ok(false); + }; + // 2. Let spreadable be ? Get(O, @@isConcatSpreadable). + let spreadable = get( + agent, + o, + WellKnownSymbolIndexes::IsConcatSpreadable.into(), + gc.reborrow(), + )?; + // 3. If spreadable is not undefined, return ToBoolean(spreadable). + if !spreadable.is_undefined() { + let spreadable = to_boolean(agent, spreadable); + if spreadable { + Ok(true) } else { - // 4. Return ? IsArray(O). - let o_is_array = is_array(agent, o.into_value(), gc.nogc())?; - if o_is_array { - Ok(Some(o)) - } else { - Ok(None) - } + Ok(false) } } else { - Ok(None) + // 4. Return ? IsArray(O). + let o_is_array = is_array(agent, o.into_value(), gc.nogc())?; + if o_is_array { + Ok(true) + } else { + Ok(false) + } } } @@ -3534,12 +3693,12 @@ fn is_concat_spreadable( /// looked up from the prototype or are undefined. fn find_via_predicate( agent: &mut Agent, - o: Object, + o: Scoped<'_, Object<'static>>, len: i64, ascending: bool, predicate: Value, this_arg: Value, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult<(i64, Value)> { // 1. If IsCallable(predicate) is false, throw a TypeError exception. let Some(predicate) = is_callable(predicate, gc.nogc()) else { @@ -3552,17 +3711,17 @@ fn find_via_predicate( let predicate = predicate.scope(agent, gc.nogc()); // 4. For each integer k of indices, do let check = |agent: &mut Agent, - o: Object, + o: Scoped<'_, Object<'static>>, predicate: Scoped<'_, Function<'static>>, this_arg: Value, k: i64, - mut gc: GcScope<'_, '_>| + mut gc: GcScope| -> JsResult> { // a. Let Pk be ! ToString(๐”ฝ(k)). let pk = PropertyKey::Integer(k.try_into().unwrap()); // b. NOTE: If O is a TypedArray, the following invocation of Get will return a normal completion. // c. Let kValue be ? Get(O, Pk). - let k_value = get(agent, o, pk, gc.reborrow())?; + let k_value = get(agent, o.get(agent), pk, gc.reborrow())?; // d. Let testResult be ? Call(predicate, thisArg, ยซ kValue, ๐”ฝ(k), O ยป). let test_result = call_function( @@ -3571,7 +3730,7 @@ fn find_via_predicate( this_arg, Some(ArgumentsList(&[ Number::try_from(k).unwrap().into_value(), - o.into_value(), + o.get(agent).into_value(), ])), gc.reborrow(), )?; @@ -3587,7 +3746,14 @@ fn find_via_predicate( if ascending { // a. Let indices be a List of the integers in the interval from 0 (inclusive) to len (exclusive), in ascending order. for k in 0..len { - if let Some(result) = check(agent, o, predicate.clone(), this_arg, k, gc.reborrow())? { + if let Some(result) = check( + agent, + o.clone(), + predicate.clone(), + this_arg, + k, + gc.reborrow(), + )? { return Ok(result); } } @@ -3595,7 +3761,14 @@ fn find_via_predicate( // 3. Else, // a. Let indices be a List of the integers in the interval from 0 (inclusive) to len (exclusive), in descending order. for k in (0..len).rev() { - if let Some(result) = check(agent, o, predicate.clone(), this_arg, k, gc.reborrow())? { + if let Some(result) = check( + agent, + o.clone(), + predicate.clone(), + this_arg, + k, + gc.reborrow(), + )? { return Ok(result); } } @@ -3614,14 +3787,14 @@ fn find_via_predicate( #[allow(clippy::too_many_arguments)] fn flatten_into_array( agent: &mut Agent, - target: Object, - source: Object, + target: Scoped<'_, Object<'static>>, + source: Scoped<'_, Object<'static>>, source_len: usize, start: usize, depth: Option, mapper_function: Option>>, this_arg: Option, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { // 1. Assert: If mapperFunction is present, then IsCallable(mapperFunction) is true, thisArg is present, and depth is 1. assert!(mapper_function.is_none() || this_arg.is_some() && depth == Some(1)); @@ -3635,7 +3808,7 @@ fn flatten_into_array( let source_index_number = Number::try_from(source_index).unwrap(); let p = PropertyKey::try_from(source_index).unwrap(); // b. Let exists be ? HasProperty(source, P). - let exists = has_property(agent, source, p, gc.reborrow())?; + let exists = has_property(agent, source.get(agent), p, gc.reborrow())?; // c. If exists is true, then if !exists { // d. Set sourceIndex to sourceIndex + 1๐”ฝ. @@ -3643,7 +3816,7 @@ fn flatten_into_array( continue; } // i. Let element be ? Get(source, P). - let element = get(agent, source, p, gc.reborrow())?; + let element = get(agent, source.get(agent), p, gc.reborrow())?; // ii. If mapperFunction is present, then let element = if let Some(mapper_function) = &mapper_function { // 1. Set element to ? Call(mapperFunction, thisArg, ยซ element, sourceIndex, source ยป). @@ -3654,7 +3827,7 @@ fn flatten_into_array( Some(ArgumentsList(&[ element, source_index_number.into_value(), - source.into_value(), + source.get(agent).into_value(), ])), gc.reborrow(), )? @@ -3671,14 +3844,18 @@ fn flatten_into_array( // v. If shouldFlatten is true, then if should_flatten { // Note: Element is necessary an Array. - let element = Object::try_from(element).unwrap(); + let element = Object::try_from(element) + .unwrap() + .bind(gc.nogc()) + .scope(agent, gc.nogc()); let new_depth = depth.map(|depth| depth - 1); // 3. Let elementLen be ? LengthOfArrayLike(element). - let element_len = length_of_array_like(agent, element, gc.reborrow())? as usize; + let element_len = + length_of_array_like(agent, element.get(agent), gc.reborrow())? as usize; // 4. Set targetIndex to ? FlattenIntoArray(target, element, elementLen, targetIndex, newDepth). target_index = flatten_into_array( agent, - target, + target.clone(), element, element_len, target_index, @@ -3700,7 +3877,7 @@ fn flatten_into_array( // 2. Perform ? CreateDataPropertyOrThrow(target, ! ToString(๐”ฝ(targetIndex)), element). create_data_property_or_throw( agent, - target, + target.get(agent), target_index.try_into().unwrap(), element, gc.reborrow(), @@ -3772,7 +3949,7 @@ fn sort_indexed_properties( obj: Object, len: usize, comparator: Option>>, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult> { // 1. Let items be a new empty List. let mut items = Vec::with_capacity(len); @@ -3840,7 +4017,7 @@ fn compare_array_elements( x: Value, y: Value, comparator: Option>>, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { // 1. If x and y are both undefined, return +0๐”ฝ. if x.is_undefined() && y.is_undefined() { diff --git a/nova_vm/src/ecmascript/builtins/indexed_collections/typed_array_objects/abstract_operations.rs b/nova_vm/src/ecmascript/builtins/indexed_collections/typed_array_objects/abstract_operations.rs index fbf59b888..2af26f130 100644 --- a/nova_vm/src/ecmascript/builtins/indexed_collections/typed_array_objects/abstract_operations.rs +++ b/nova_vm/src/ecmascript/builtins/indexed_collections/typed_array_objects/abstract_operations.rs @@ -350,11 +350,12 @@ pub(crate) fn allocate_typed_array<'a, T: Viewable>( let new_target = new_target.bind(gc.nogc()); // 1. Let proto be ? GetPrototypeFromConstructor(newTarget, defaultProto). let proto = - get_prototype_from_constructor(agent, new_target.unbind(), default_proto, gc.reborrow())?; + get_prototype_from_constructor(agent, new_target.unbind(), default_proto, gc.reborrow())? + .map(|p| p.unbind()) + .map(|p| p.bind(gc.nogc())); // 2. Let obj be TypedArrayCreate(proto). - let gc = gc.into_nogc(); - let obj = typed_array_create::(agent, proto, gc); + let obj = typed_array_create::(agent, proto, gc.nogc()); // NOTE: Steps 3-7 are skipped, it's the defaults for TypedArrayHeapData. // 3. Assert: obj.[[ViewedArrayBuffer]] is undefined. @@ -369,11 +370,11 @@ pub(crate) fn allocate_typed_array<'a, T: Viewable>( if let Some(length) = length { // 8. Else, // a. Perform ? AllocateTypedArrayBuffer(obj, length). - allocate_typed_array_buffer::(agent, obj, length, gc)?; + allocate_typed_array_buffer::(agent, obj, length, gc.nogc())?; } // 9. Return obj. - Ok(obj) + Ok(obj.unbind().bind(gc.into_nogc())) } /// ### [23.2.5.1.2 InitializeTypedArrayFromTypedArray ( O, srcArray )](https://tc39.es/ecma262/#sec-initializetypedarrayfromtypedarray) @@ -674,7 +675,14 @@ pub(crate) fn initialize_typed_array_from_list( gc.nogc(), ))?; } else { - set(agent, o.into_object(), pk, k_value, true, gc.reborrow())?; + set( + agent, + o.unbind().into_object(), + pk, + k_value, + true, + gc.reborrow(), + )?; o = scoped_o.get(agent).bind(gc.nogc()); } } diff --git a/nova_vm/src/ecmascript/builtins/keyed_collections/map_objects/map_constructor.rs b/nova_vm/src/ecmascript/builtins/keyed_collections/map_objects/map_constructor.rs index 9906d8ed0..c4a828e9f 100644 --- a/nova_vm/src/ecmascript/builtins/keyed_collections/map_objects/map_constructor.rs +++ b/nova_vm/src/ecmascript/builtins/keyed_collections/map_objects/map_constructor.rs @@ -6,7 +6,9 @@ use std::hash::Hasher; use ahash::AHasher; +use crate::ecmascript::abstract_operations::operations_on_objects::try_get; use crate::engine::context::GcScope; +use crate::engine::TryResult; use crate::{ ecmascript::{ abstract_operations::{ @@ -68,7 +70,7 @@ impl MapConstructor { _: Value, arguments: ArgumentsList, new_target: Option, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { // If NewTarget is undefined, throw a TypeError exception. let Some(new_target) = new_target else { @@ -80,13 +82,15 @@ impl MapConstructor { }; let new_target = Function::try_from(new_target).unwrap(); // 2. Let map be ? OrdinaryCreateFromConstructor(NewTarget, "%Map.prototype%", ยซ [[MapData]] ยป). - let map = Map::try_from(ordinary_create_from_constructor( + let mut map = Map::try_from(ordinary_create_from_constructor( agent, new_target, ProtoIntrinsics::Map, gc.reborrow(), )?) - .unwrap(); + .unwrap() + .unbind() + .bind(gc.nogc()); // 3. Set map.[[MapData]] to a new empty List. let iterable = arguments.get(0); // 4. If iterable is either undefined or null, return map. @@ -102,12 +106,24 @@ impl MapConstructor { // key. // 5. Let adder be ? Get(map, "set"). - let adder = get( + let adder = if let TryResult::Continue(adder) = try_get( agent, - map.into_object(), + map.into_object().unbind(), BUILTIN_STRING_MEMORY.set.to_property_key(), - gc.reborrow(), - )?; + gc.nogc(), + ) { + adder + } else { + let scoped_map = map.scope(agent, gc.nogc()); + let adder = get( + agent, + map.into_object().unbind(), + BUILTIN_STRING_MEMORY.set.to_property_key(), + gc.reborrow(), + )?; + map = scoped_map.get(agent).bind(gc.nogc()); + adder + }; // 6. If IsCallable(adder) is false, throw a TypeError exception. let Some(adder) = is_callable(adder, gc.nogc()) else { return Err(agent.throw_exception_with_static_message( @@ -119,7 +135,7 @@ impl MapConstructor { // 7. Return ? AddEntriesFromIterable(map, iterable, adder). add_entries_from_iterable_map_constructor( agent, - map, + map.unbind(), iterable, adder.unbind(), gc.reborrow(), @@ -132,7 +148,7 @@ impl MapConstructor { _agent: &mut Agent, _this_value: Value, _arguments: ArgumentsList, - _gc: GcScope<'_, '_>, + _gc: GcScope, ) -> JsResult { todo!() } @@ -141,7 +157,7 @@ impl MapConstructor { _: &mut Agent, this_value: Value, _: ArgumentsList, - _gc: GcScope<'_, '_>, + _gc: GcScope, ) -> JsResult { Ok(this_value) } diff --git a/nova_vm/src/ecmascript/builtins/keyed_collections/map_objects/map_iterator_objects/map_iterator.rs b/nova_vm/src/ecmascript/builtins/keyed_collections/map_objects/map_iterator_objects/map_iterator.rs index aecb119ec..fc67ab890 100644 --- a/nova_vm/src/ecmascript/builtins/keyed_collections/map_objects/map_iterator_objects/map_iterator.rs +++ b/nova_vm/src/ecmascript/builtins/keyed_collections/map_objects/map_iterator_objects/map_iterator.rs @@ -80,13 +80,13 @@ impl IntoValue for MapIterator<'_> { } } -impl IntoObject for MapIterator<'_> { - fn into_object(self) -> Object { +impl<'a> IntoObject<'a> for MapIterator<'a> { + fn into_object(self) -> Object<'a> { self.into() } } -impl From> for Object { +impl<'a> From> for Object<'a> { fn from(value: MapIterator) -> Self { Self::MapIterator(value.unbind()) } @@ -109,10 +109,10 @@ impl TryFrom for MapIterator<'_> { } } -impl TryFrom for MapIterator<'_> { +impl<'a> TryFrom> for MapIterator<'a> { type Error = (); - fn try_from(value: Object) -> Result { + fn try_from(value: Object<'a>) -> Result { match value { Object::MapIterator(data) => Ok(data), _ => Err(()), @@ -120,7 +120,7 @@ impl TryFrom for MapIterator<'_> { } } -impl InternalSlots for MapIterator<'_> { +impl<'a> InternalSlots<'a> for MapIterator<'a> { const DEFAULT_PROTOTYPE: ProtoIntrinsics = ProtoIntrinsics::MapIterator; fn get_backing_object(self, agent: &Agent) -> Option> { @@ -135,7 +135,7 @@ impl InternalSlots for MapIterator<'_> { } } -impl InternalMethods for MapIterator<'_> {} +impl<'a> InternalMethods<'a> for MapIterator<'a> {} impl Index> for Agent { type Output = MapIteratorHeapData; diff --git a/nova_vm/src/ecmascript/builtins/keyed_collections/map_objects/map_iterator_objects/map_iterator_prototype.rs b/nova_vm/src/ecmascript/builtins/keyed_collections/map_objects/map_iterator_objects/map_iterator_prototype.rs index 8a9e6bdb5..98e59c42f 100644 --- a/nova_vm/src/ecmascript/builtins/keyed_collections/map_objects/map_iterator_objects/map_iterator_prototype.rs +++ b/nova_vm/src/ecmascript/builtins/keyed_collections/map_objects/map_iterator_objects/map_iterator_prototype.rs @@ -37,7 +37,7 @@ impl MapIteratorPrototype { agent: &mut Agent, this_value: Value, _arguments: ArgumentsList, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { let gc = gc.into_nogc(); // 27.5.3.2 GeneratorValidate ( generator, generatorBrand ) @@ -54,7 +54,7 @@ impl MapIteratorPrototype { // 24.1.5.1 CreateMapIterator ( map, kind ), step 2 // NOTE: We set `map` to None when the generator in the spec text has returned. let Some(map) = agent[iterator].map else { - return Ok(create_iter_result_object(agent, Value::Undefined, true).into_value()); + return Ok(create_iter_result_object(agent, Value::Undefined, true, gc).into_value()); }; // a. Let entries be map.[[MapData]]. @@ -99,14 +99,14 @@ impl MapIteratorPrototype { }; // 4. Perform ? GeneratorYield(CreateIteratorResultObject(result, false)). - return Ok(create_iter_result_object(agent, result, false).into_value()); + return Ok(create_iter_result_object(agent, result, false, gc).into_value()); } debug_assert_eq!(agent[iterator].next_index, agent[map].keys().len()); // e. Return undefined. agent[iterator].map = None; - Ok(create_iter_result_object(agent, Value::Undefined, true).into_value()) + Ok(create_iter_result_object(agent, Value::Undefined, true, gc).into_value()) } pub(crate) fn create_intrinsic(agent: &mut Agent, realm: RealmIdentifier) { diff --git a/nova_vm/src/ecmascript/builtins/keyed_collections/map_objects/map_prototype.rs b/nova_vm/src/ecmascript/builtins/keyed_collections/map_objects/map_prototype.rs index 6f86e09e4..a670da908 100644 --- a/nova_vm/src/ecmascript/builtins/keyed_collections/map_objects/map_prototype.rs +++ b/nova_vm/src/ecmascript/builtins/keyed_collections/map_objects/map_prototype.rs @@ -105,7 +105,7 @@ impl MapPrototype { agent: &mut Agent, this_value: Value, _: ArgumentsList, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { // 1. Let M be the this value. // 2. Perform ? RequireInternalSlot(M, [[MapData]]). @@ -129,7 +129,7 @@ impl MapPrototype { agent: &mut Agent, this_value: Value, arguments: ArgumentsList, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { // 1. Let M be the this value. // 2. Perform ? RequireInternalSlot(M, [[MapData]]). @@ -185,7 +185,7 @@ impl MapPrototype { agent: &mut Agent, this_value: Value, _: ArgumentsList, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { // 1. Let M be the this value. // 2. Return ? CreateMapIterator(M, KEY+VALUE). @@ -226,7 +226,7 @@ impl MapPrototype { agent: &mut Agent, this_value: Value, arguments: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { let callback_fn = arguments.get(0); let this_arg = arguments.get(1); @@ -286,7 +286,7 @@ impl MapPrototype { agent: &mut Agent, this_value: Value, arguments: ArgumentsList, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { // 1. Let M be the this value. // 2. Perform ? RequireInternalSlot(M, [[MapData]]). @@ -337,7 +337,7 @@ impl MapPrototype { agent: &mut Agent, this_value: Value, arguments: ArgumentsList, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { // 1. Let M be the this value. // 2. Perform ? RequireInternalSlot(M, [[MapData]]). @@ -380,7 +380,7 @@ impl MapPrototype { agent: &mut Agent, this_value: Value, _: ArgumentsList, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { // 1. Let M be the this value. // 2. Return ? CreateMapIterator(M, KEY). @@ -397,7 +397,7 @@ impl MapPrototype { agent: &mut Agent, this_value: Value, arguments: ArgumentsList, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { let value = arguments.get(1); // 1. Let M be the this value. @@ -466,7 +466,7 @@ impl MapPrototype { agent: &mut Agent, this_value: Value, _: ArgumentsList, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { let gc = gc.into_nogc(); let m = require_map_data_internal_slot(agent, this_value, gc)?; @@ -478,7 +478,7 @@ impl MapPrototype { agent: &mut Agent, this_value: Value, _: ArgumentsList, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { // 1. Let M be the this value. // 2. Return ? CreateMapIterator(M, VALUE). diff --git a/nova_vm/src/ecmascript/builtins/keyed_collections/set_objects/set_constructor.rs b/nova_vm/src/ecmascript/builtins/keyed_collections/set_objects/set_constructor.rs index e16ddafb9..d2aac0179 100644 --- a/nova_vm/src/ecmascript/builtins/keyed_collections/set_objects/set_constructor.rs +++ b/nova_vm/src/ecmascript/builtins/keyed_collections/set_objects/set_constructor.rs @@ -60,7 +60,7 @@ impl SetConstructor { _: Value, arguments: ArgumentsList, new_target: Option, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { let iterable = arguments.get(0); // 1. If NewTarget is undefined, throw a TypeError exception. @@ -79,14 +79,22 @@ impl SetConstructor { ProtoIntrinsics::Set, gc.reborrow(), )?) - .unwrap(); + .unwrap() + .unbind() + .bind(gc.nogc()); + let scoped_set = set.scope(agent, gc.nogc()); // 3. Set set.[[SetData]] to a new empty List. // 4. If iterable is either undefined or null, return set. if iterable.is_undefined() || iterable.is_null() { return Ok(set.into_value()); } // 5. Let adder be ? Get(set, "add"). - let adder = get(agent, set, BUILTIN_STRING_MEMORY.add.into(), gc.reborrow())?; + let adder = get( + agent, + set.into_object().unbind(), + BUILTIN_STRING_MEMORY.add.into(), + gc.reborrow(), + )?; // 6. If IsCallable(adder) is false, throw a TypeError exception. let Some(adder) = is_callable(adder, gc.nogc()) else { return Err(agent.throw_exception_with_static_message( @@ -97,11 +105,13 @@ impl SetConstructor { }; let adder = adder.scope(agent, gc.nogc()); if let Value::Array(iterable) = iterable { + let iterable = iterable.bind(gc.nogc()); + let scoped_iterable = iterable.scope(agent, gc.nogc()); if iterable.is_trivial(agent) && iterable.is_dense(agent) && get_method( agent, - iterable.into_value(), + iterable.unbind().into_value(), PropertyKey::Symbol(WellKnownSymbolIndexes::Iterator.into()), gc.reborrow(), )? == Some( @@ -114,7 +124,8 @@ impl SetConstructor { { // Accessorless, holeless array with standard Array values // iterator. We can fast-path this. - + let set = scoped_set.get(agent).bind(gc.nogc()); + let iterable = scoped_iterable.get(agent).bind(gc.nogc()); let Heap { elements, arrays, @@ -177,13 +188,13 @@ impl SetConstructor { let next = iterator_step_value(agent, &mut iterator_record, gc.reborrow())?; // b. If next is DONE, return set. let Some(next) = next else { - return Ok(set.into_value()); + return Ok(scoped_set.get(agent).into_value()); }; // c. Let status be Completion(Call(adder, set, ยซ next ยป)). let status = call_function( agent, adder.get(agent), - set.into_value(), + scoped_set.get(agent).into_value(), Some(ArgumentsList(&[next])), gc.reborrow(), ); @@ -196,7 +207,7 @@ impl SetConstructor { _: &mut Agent, this_value: Value, _: ArgumentsList, - _gc: GcScope<'_, '_>, + _gc: GcScope, ) -> JsResult { Ok(this_value) } diff --git a/nova_vm/src/ecmascript/builtins/keyed_collections/set_objects/set_iterator_objects/set_iterator.rs b/nova_vm/src/ecmascript/builtins/keyed_collections/set_objects/set_iterator_objects/set_iterator.rs index 0375ef91b..6e802813b 100644 --- a/nova_vm/src/ecmascript/builtins/keyed_collections/set_objects/set_iterator_objects/set_iterator.rs +++ b/nova_vm/src/ecmascript/builtins/keyed_collections/set_objects/set_iterator_objects/set_iterator.rs @@ -80,13 +80,13 @@ impl IntoValue for SetIterator<'_> { } } -impl IntoObject for SetIterator<'_> { - fn into_object(self) -> Object { +impl<'a> IntoObject<'a> for SetIterator<'a> { + fn into_object(self) -> Object<'a> { self.into() } } -impl From> for Object { +impl<'a> From> for Object<'a> { fn from(value: SetIterator) -> Self { Self::SetIterator(value.unbind()) } @@ -109,10 +109,10 @@ impl TryFrom for SetIterator<'_> { } } -impl TryFrom for SetIterator<'_> { +impl<'a> TryFrom> for SetIterator<'a> { type Error = (); - fn try_from(value: Object) -> Result { + fn try_from(value: Object<'a>) -> Result { match value { Object::SetIterator(data) => Ok(data), _ => Err(()), @@ -120,7 +120,7 @@ impl TryFrom for SetIterator<'_> { } } -impl InternalSlots for SetIterator<'_> { +impl<'a> InternalSlots<'a> for SetIterator<'a> { const DEFAULT_PROTOTYPE: ProtoIntrinsics = ProtoIntrinsics::SetIterator; fn get_backing_object(self, agent: &Agent) -> Option> { @@ -135,7 +135,7 @@ impl InternalSlots for SetIterator<'_> { } } -impl InternalMethods for SetIterator<'_> {} +impl<'a> InternalMethods<'a> for SetIterator<'a> {} impl Index> for Agent { type Output = SetIteratorHeapData; diff --git a/nova_vm/src/ecmascript/builtins/keyed_collections/set_objects/set_iterator_objects/set_iterator_prototype.rs b/nova_vm/src/ecmascript/builtins/keyed_collections/set_objects/set_iterator_objects/set_iterator_prototype.rs index f905adf49..000f00479 100644 --- a/nova_vm/src/ecmascript/builtins/keyed_collections/set_objects/set_iterator_objects/set_iterator_prototype.rs +++ b/nova_vm/src/ecmascript/builtins/keyed_collections/set_objects/set_iterator_objects/set_iterator_prototype.rs @@ -37,7 +37,7 @@ impl SetIteratorPrototype { agent: &mut Agent, this_value: Value, _arguments: ArgumentsList, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { let gc = gc.into_nogc(); // 27.5.3.2 GeneratorValidate ( generator, generatorBrand ) @@ -54,7 +54,7 @@ impl SetIteratorPrototype { // 24.2.6.1 CreateSetIterator ( set, kind ) // NOTE: We set `set` to None when the generator in the spec text has returned. let Some(set) = agent[iterator].set else { - return Ok(create_iter_result_object(agent, Value::Undefined, true).into_value()); + return Ok(create_iter_result_object(agent, Value::Undefined, true, gc).into_value()); }; // b. Let entries be set.[[SetData]]. @@ -87,14 +87,14 @@ impl SetIteratorPrototype { } }; - return Ok(create_iter_result_object(agent, result, false).into_value()); + return Ok(create_iter_result_object(agent, result, false, gc).into_value()); } debug_assert_eq!(agent[iterator].next_index, agent[set].values().len()); // e. Return undefined. agent[iterator].set = None; - Ok(create_iter_result_object(agent, Value::Undefined, true).into_value()) + Ok(create_iter_result_object(agent, Value::Undefined, true, gc).into_value()) } pub(crate) fn create_intrinsic(agent: &mut Agent, realm: RealmIdentifier) { diff --git a/nova_vm/src/ecmascript/builtins/keyed_collections/set_objects/set_prototype.rs b/nova_vm/src/ecmascript/builtins/keyed_collections/set_objects/set_prototype.rs index bfbaf3bcf..32aa115ae 100644 --- a/nova_vm/src/ecmascript/builtins/keyed_collections/set_objects/set_prototype.rs +++ b/nova_vm/src/ecmascript/builtins/keyed_collections/set_objects/set_prototype.rs @@ -92,7 +92,7 @@ impl SetPrototype { agent: &mut Agent, this_value: Value, arguments: ArgumentsList, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { // 1. Let S be the this value. // 2. Perform ? RequireInternalSlot(S, [[SetData]]). @@ -154,7 +154,7 @@ impl SetPrototype { agent: &mut Agent, this_value: Value, _: ArgumentsList, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { // 1. Let S be the this value. // 2. Perform ? RequireInternalSlot(S, [[SetData]]). @@ -179,7 +179,7 @@ impl SetPrototype { agent: &mut Agent, this_value: Value, arguments: ArgumentsList, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { // 1. Let S be the this value. // 2. Perform ? RequireInternalSlot(S, [[SetData]]). @@ -230,7 +230,7 @@ impl SetPrototype { agent: &mut Agent, this_value: Value, _: ArgumentsList, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { // 1. Let S be the this value. // 2. Return ? CreateSetIterator(S, KEY+VALUE). @@ -279,7 +279,7 @@ impl SetPrototype { agent: &mut Agent, this_value: Value, arguments: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { let callback_fn = arguments.get(0); let this_arg = arguments.get(1); @@ -336,7 +336,7 @@ impl SetPrototype { agent: &mut Agent, this_value: Value, arguments: ArgumentsList, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { // 1. Let S be the this value. // 2. Perform ? RequireInternalSlot(S, [[SetData]]). @@ -384,7 +384,7 @@ impl SetPrototype { agent: &mut Agent, this_value: Value, _: ArgumentsList, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { // 1. Let S be the this value. // 2. Perform ? RequireInternalSlot(S, [[SetData]]). @@ -400,7 +400,7 @@ impl SetPrototype { agent: &mut Agent, this_value: Value, _: ArgumentsList, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { // 1. Let S be the this value. // 2. Return ? CreateSetIterator(S, VALUE). diff --git a/nova_vm/src/ecmascript/builtins/keyed_collections/weak_map_objects/weak_map_constructor.rs b/nova_vm/src/ecmascript/builtins/keyed_collections/weak_map_objects/weak_map_constructor.rs index 7f4711800..e5e8b44b5 100644 --- a/nova_vm/src/ecmascript/builtins/keyed_collections/weak_map_objects/weak_map_constructor.rs +++ b/nova_vm/src/ecmascript/builtins/keyed_collections/weak_map_objects/weak_map_constructor.rs @@ -31,7 +31,7 @@ impl WeakMapConstructor { _this_value: Value, _arguments: ArgumentsList, _new_target: Option, - _gc: GcScope<'_, '_>, + _gc: GcScope, ) -> JsResult { todo!() } diff --git a/nova_vm/src/ecmascript/builtins/keyed_collections/weak_map_objects/weak_map_prototype.rs b/nova_vm/src/ecmascript/builtins/keyed_collections/weak_map_objects/weak_map_prototype.rs index 3df81cb91..4699205ef 100644 --- a/nova_vm/src/ecmascript/builtins/keyed_collections/weak_map_objects/weak_map_prototype.rs +++ b/nova_vm/src/ecmascript/builtins/keyed_collections/weak_map_objects/weak_map_prototype.rs @@ -45,7 +45,7 @@ impl WeakMapPrototype { _agent: &mut Agent, _this_value: Value, _: ArgumentsList, - _gc: GcScope<'_, '_>, + _gc: GcScope, ) -> JsResult { todo!() } @@ -54,7 +54,7 @@ impl WeakMapPrototype { _agent: &mut Agent, _this_value: Value, _: ArgumentsList, - _gc: GcScope<'_, '_>, + _gc: GcScope, ) -> JsResult { todo!() } @@ -63,7 +63,7 @@ impl WeakMapPrototype { _agent: &mut Agent, _this_value: Value, _: ArgumentsList, - _gc: GcScope<'_, '_>, + _gc: GcScope, ) -> JsResult { todo!() } @@ -72,7 +72,7 @@ impl WeakMapPrototype { _agent: &mut Agent, _this_value: Value, _: ArgumentsList, - _gc: GcScope<'_, '_>, + _gc: GcScope, ) -> JsResult { todo!() } diff --git a/nova_vm/src/ecmascript/builtins/keyed_collections/weak_set_objects/weak_set_constructor.rs b/nova_vm/src/ecmascript/builtins/keyed_collections/weak_set_objects/weak_set_constructor.rs index 424c817ac..6bd45b3c8 100644 --- a/nova_vm/src/ecmascript/builtins/keyed_collections/weak_set_objects/weak_set_constructor.rs +++ b/nova_vm/src/ecmascript/builtins/keyed_collections/weak_set_objects/weak_set_constructor.rs @@ -31,7 +31,7 @@ impl WeakSetConstructor { _this_value: Value, _arguments: ArgumentsList, _new_target: Option, - _gc: GcScope<'_, '_>, + _gc: GcScope, ) -> JsResult { todo!() } diff --git a/nova_vm/src/ecmascript/builtins/keyed_collections/weak_set_objects/weak_set_prototype.rs b/nova_vm/src/ecmascript/builtins/keyed_collections/weak_set_objects/weak_set_prototype.rs index 0ec1a5ada..6ec345070 100644 --- a/nova_vm/src/ecmascript/builtins/keyed_collections/weak_set_objects/weak_set_prototype.rs +++ b/nova_vm/src/ecmascript/builtins/keyed_collections/weak_set_objects/weak_set_prototype.rs @@ -39,7 +39,7 @@ impl WeakSetPrototype { _agent: &mut Agent, _this_value: Value, _: ArgumentsList, - _gc: GcScope<'_, '_>, + _gc: GcScope, ) -> JsResult { todo!() } @@ -48,7 +48,7 @@ impl WeakSetPrototype { _agent: &mut Agent, _this_value: Value, _: ArgumentsList, - _gc: GcScope<'_, '_>, + _gc: GcScope, ) -> JsResult { todo!() } @@ -57,7 +57,7 @@ impl WeakSetPrototype { _agent: &mut Agent, _this_value: Value, _: ArgumentsList, - _gc: GcScope<'_, '_>, + _gc: GcScope, ) -> JsResult { todo!() } diff --git a/nova_vm/src/ecmascript/builtins/managing_memory/finalization_registry_objects/finalization_registry_constructor.rs b/nova_vm/src/ecmascript/builtins/managing_memory/finalization_registry_objects/finalization_registry_constructor.rs index 161811813..6bb19b6ea 100644 --- a/nova_vm/src/ecmascript/builtins/managing_memory/finalization_registry_objects/finalization_registry_constructor.rs +++ b/nova_vm/src/ecmascript/builtins/managing_memory/finalization_registry_objects/finalization_registry_constructor.rs @@ -31,7 +31,7 @@ impl FinalizationRegistryConstructor { _this_value: Value, _arguments: ArgumentsList, _new_target: Option, - _gc: GcScope<'_, '_>, + _gc: GcScope, ) -> JsResult { todo!() } diff --git a/nova_vm/src/ecmascript/builtins/managing_memory/finalization_registry_objects/finalization_registry_prototype.rs b/nova_vm/src/ecmascript/builtins/managing_memory/finalization_registry_objects/finalization_registry_prototype.rs index f72d64d91..518bd399f 100644 --- a/nova_vm/src/ecmascript/builtins/managing_memory/finalization_registry_objects/finalization_registry_prototype.rs +++ b/nova_vm/src/ecmascript/builtins/managing_memory/finalization_registry_objects/finalization_registry_prototype.rs @@ -33,7 +33,7 @@ impl FinalizationRegistryPrototype { _agent: &mut Agent, _this_value: Value, _: ArgumentsList, - _gc: GcScope<'_, '_>, + _gc: GcScope, ) -> JsResult { todo!() } @@ -42,7 +42,7 @@ impl FinalizationRegistryPrototype { _agent: &mut Agent, _this_value: Value, _: ArgumentsList, - _gc: GcScope<'_, '_>, + _gc: GcScope, ) -> JsResult { todo!() } diff --git a/nova_vm/src/ecmascript/builtins/managing_memory/weak_ref_objects/weak_ref_constructor.rs b/nova_vm/src/ecmascript/builtins/managing_memory/weak_ref_objects/weak_ref_constructor.rs index b7fdffd55..cf86aa805 100644 --- a/nova_vm/src/ecmascript/builtins/managing_memory/weak_ref_objects/weak_ref_constructor.rs +++ b/nova_vm/src/ecmascript/builtins/managing_memory/weak_ref_objects/weak_ref_constructor.rs @@ -31,7 +31,7 @@ impl WeakRefConstructor { _this_value: Value, _arguments: ArgumentsList, _new_target: Option, - _gc: GcScope<'_, '_>, + _gc: GcScope, ) -> JsResult { todo!() } diff --git a/nova_vm/src/ecmascript/builtins/managing_memory/weak_ref_objects/weak_ref_prototype.rs b/nova_vm/src/ecmascript/builtins/managing_memory/weak_ref_objects/weak_ref_prototype.rs index c6a85a3b8..1cb80851a 100644 --- a/nova_vm/src/ecmascript/builtins/managing_memory/weak_ref_objects/weak_ref_prototype.rs +++ b/nova_vm/src/ecmascript/builtins/managing_memory/weak_ref_objects/weak_ref_prototype.rs @@ -27,7 +27,7 @@ impl WeakRefPrototype { _agent: &mut Agent, _this_value: Value, _: ArgumentsList, - _gc: GcScope<'_, '_>, + _gc: GcScope, ) -> JsResult { todo!() } diff --git a/nova_vm/src/ecmascript/builtins/map.rs b/nova_vm/src/ecmascript/builtins/map.rs index 1fb339cd0..558c253cf 100644 --- a/nova_vm/src/ecmascript/builtins/map.rs +++ b/nova_vm/src/ecmascript/builtins/map.rs @@ -74,8 +74,8 @@ impl IntoValue for Map<'_> { } } -impl IntoObject for Map<'_> { - fn into_object(self) -> Object { +impl<'a> IntoObject<'a> for Map<'a> { + fn into_object(self) -> Object<'a> { self.into() } } @@ -86,16 +86,16 @@ impl From> for Value { } } -impl From> for Object { +impl<'a> From> for Object<'a> { fn from(val: Map) -> Self { Object::Map(val.unbind()) } } -impl TryFrom for Map<'_> { +impl<'a> TryFrom> for Map<'a> { type Error = (); - fn try_from(value: Object) -> Result { + fn try_from(value: Object<'a>) -> Result { match value { Object::Map(data) => Ok(data), _ => Err(()), @@ -103,7 +103,7 @@ impl TryFrom for Map<'_> { } } -impl InternalSlots for Map<'_> { +impl<'a> InternalSlots<'a> for Map<'a> { const DEFAULT_PROTOTYPE: ProtoIntrinsics = ProtoIntrinsics::Map; #[inline(always)] @@ -119,7 +119,7 @@ impl InternalSlots for Map<'_> { } } -impl InternalMethods for Map<'_> {} +impl<'a> InternalMethods<'a> for Map<'a> {} impl HeapMarkAndSweep for Map<'static> { fn mark_values(&self, queues: &mut WorkQueues) { diff --git a/nova_vm/src/ecmascript/builtins/module.rs b/nova_vm/src/ecmascript/builtins/module.rs index f34937b8b..6424f8db2 100644 --- a/nova_vm/src/ecmascript/builtins/module.rs +++ b/nova_vm/src/ecmascript/builtins/module.rs @@ -51,8 +51,8 @@ impl IntoValue for Module<'_> { } } -impl IntoObject for Module<'_> { - fn into_object(self) -> Object { +impl<'a> IntoObject<'a> for Module<'a> { + fn into_object(self) -> Object<'a> { self.into() } } @@ -63,7 +63,7 @@ impl From> for Value { } } -impl From> for Object { +impl<'a> From> for Object<'a> { fn from(val: Module) -> Self { Object::Module(val.unbind()) } @@ -141,7 +141,7 @@ impl Module<'_> { } } -impl InternalSlots for Module<'_> { +impl<'a> InternalSlots<'a> for Module<'a> { #[inline(always)] fn get_backing_object(self, agent: &Agent) -> Option> { agent[self].object_index @@ -164,20 +164,20 @@ impl InternalSlots for Module<'_> { fn internal_set_extensible(self, _agent: &mut Agent, _value: bool) {} - fn internal_prototype(self, _agent: &Agent) -> Option { + fn internal_prototype(self, _agent: &Agent) -> Option> { None } fn internal_set_prototype(self, _agent: &mut Agent, _prototype: Option) {} } -impl InternalMethods for Module<'_> { +impl<'a> InternalMethods<'a> for Module<'a> { /// ### [10.4.6.1 \[\[GetPrototypeOf\]\] ( )](https://tc39.es/ecma262/#sec-module-namespace-exotic-objects-getprototypeof) - fn try_get_prototype_of( + fn try_get_prototype_of<'gc>( self, _: &mut Agent, - _: NoGcScope<'_, '_>, - ) -> TryResult> { + _: NoGcScope<'gc, '_>, + ) -> TryResult>> { TryResult::Continue(None) } @@ -186,19 +186,19 @@ impl InternalMethods for Module<'_> { self, _: &mut Agent, prototype: Option, - _: NoGcScope<'_, '_>, + _: NoGcScope, ) -> TryResult { // This is what it all comes down to in the end. TryResult::Continue(prototype.is_none()) } /// ### [10.4.6.3 \[\[IsExtensible\]\] ( )](https://tc39.es/ecma262/#sec-module-namespace-exotic-objects-isextensible) - fn try_is_extensible(self, _: &mut Agent, _: NoGcScope<'_, '_>) -> TryResult { + fn try_is_extensible(self, _: &mut Agent, _: NoGcScope) -> TryResult { TryResult::Continue(false) } /// ### [10.4.6.4 \[\[PreventExtensions\]\] ( )](https://tc39.es/ecma262/#sec-module-namespace-exotic-objects-preventextensions) - fn try_prevent_extensions(self, _: &mut Agent, _: NoGcScope<'_, '_>) -> TryResult { + fn try_prevent_extensions(self, _: &mut Agent, _: NoGcScope) -> TryResult { TryResult::Continue(true) } @@ -206,7 +206,7 @@ impl InternalMethods for Module<'_> { self, agent: &mut Agent, property_key: PropertyKey, - gc: NoGcScope<'_, '_>, + gc: NoGcScope, ) -> TryResult> { match property_key { PropertyKey::Symbol(_) => { @@ -250,7 +250,7 @@ impl InternalMethods for Module<'_> { self, agent: &mut Agent, property_key: PropertyKey, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult> { let property_key = property_key.bind(gc.nogc()); match property_key { @@ -295,7 +295,7 @@ impl InternalMethods for Module<'_> { agent: &mut Agent, property_key: PropertyKey, property_descriptor: PropertyDescriptor, - gc: NoGcScope<'_, '_>, + gc: NoGcScope, ) -> TryResult { match property_key { PropertyKey::Symbol(_) => { @@ -350,7 +350,7 @@ impl InternalMethods for Module<'_> { agent: &mut Agent, property_key: PropertyKey, property_descriptor: PropertyDescriptor, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { let property_key = property_key.bind(gc.nogc()); match property_key { @@ -406,7 +406,7 @@ impl InternalMethods for Module<'_> { self, agent: &mut Agent, property_key: PropertyKey, - gc: NoGcScope<'_, '_>, + gc: NoGcScope, ) -> TryResult { match property_key { PropertyKey::Integer(_) | PropertyKey::SmallString(_) | PropertyKey::String(_) => { @@ -441,7 +441,7 @@ impl InternalMethods for Module<'_> { agent: &mut Agent, property_key: PropertyKey, receiver: Value, - gc: NoGcScope<'_, '_>, + gc: NoGcScope, ) -> TryResult { // NOTE: ResolveExport is side-effect free. Each time this operation // is called with a specific exportName, resolveSet pair as arguments @@ -515,7 +515,7 @@ impl InternalMethods for Module<'_> { agent: &mut Agent, property_key: PropertyKey, receiver: Value, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { let property_key = property_key.bind(gc.nogc()); @@ -601,7 +601,7 @@ impl InternalMethods for Module<'_> { _: PropertyKey, _: Value, _: Value, - _: NoGcScope<'_, '_>, + _: NoGcScope, ) -> TryResult { TryResult::Continue(false) } @@ -611,7 +611,7 @@ impl InternalMethods for Module<'_> { self, agent: &mut Agent, property_key: PropertyKey, - gc: NoGcScope<'_, '_>, + gc: NoGcScope, ) -> TryResult { match property_key { PropertyKey::Symbol(_) => { diff --git a/nova_vm/src/ecmascript/builtins/numbers_and_dates/bigint_objects/bigint_constructor.rs b/nova_vm/src/ecmascript/builtins/numbers_and_dates/bigint_objects/bigint_constructor.rs index 8148b69b2..61df0d03a 100644 --- a/nova_vm/src/ecmascript/builtins/numbers_and_dates/bigint_objects/bigint_constructor.rs +++ b/nova_vm/src/ecmascript/builtins/numbers_and_dates/bigint_objects/bigint_constructor.rs @@ -65,7 +65,7 @@ impl BigIntConstructor { _this_value: Value, arguments: ArgumentsList, new_target: Option, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { if new_target.is_some() { return Err(agent.throw_exception_with_static_message( @@ -95,7 +95,7 @@ impl BigIntConstructor { agent: &mut Agent, _this_value: Value, arguments: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { let bits = to_index(agent, arguments.get(0), gc.reborrow())?; let Ok(bits) = u32::try_from(bits) else { @@ -173,7 +173,7 @@ impl BigIntConstructor { agent: &mut Agent, _this_value: Value, arguments: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { let bits = to_index(agent, arguments.get(0), gc.reborrow())?; let Ok(bits) = u32::try_from(bits) else { diff --git a/nova_vm/src/ecmascript/builtins/numbers_and_dates/bigint_objects/bigint_prototype.rs b/nova_vm/src/ecmascript/builtins/numbers_and_dates/bigint_objects/bigint_prototype.rs index 9a2023345..e99860ef4 100644 --- a/nova_vm/src/ecmascript/builtins/numbers_and_dates/bigint_objects/bigint_prototype.rs +++ b/nova_vm/src/ecmascript/builtins/numbers_and_dates/bigint_objects/bigint_prototype.rs @@ -50,7 +50,7 @@ impl BigIntPrototype { agent: &mut Agent, this_value: Value, arguments: ArgumentsList, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { Self::to_string(agent, this_value, arguments, gc) } @@ -59,7 +59,7 @@ impl BigIntPrototype { agent: &mut Agent, this_value: Value, arguments: ArgumentsList, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { let _x = this_big_int_value(agent, this_value, gc.nogc())?; let radix = arguments.get(0); @@ -75,7 +75,7 @@ impl BigIntPrototype { agent: &mut Agent, this_value: Value, _: ArgumentsList, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { this_big_int_value(agent, this_value, gc.nogc()).map(|result| result.into_value()) } diff --git a/nova_vm/src/ecmascript/builtins/numbers_and_dates/date_objects/date_constructor.rs b/nova_vm/src/ecmascript/builtins/numbers_and_dates/date_objects/date_constructor.rs index 884fb6430..cccc7fb40 100644 --- a/nova_vm/src/ecmascript/builtins/numbers_and_dates/date_objects/date_constructor.rs +++ b/nova_vm/src/ecmascript/builtins/numbers_and_dates/date_objects/date_constructor.rs @@ -62,7 +62,7 @@ impl DateConstructor { _this_value: Value, arguments: ArgumentsList, new_target: Option, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { // 1. If NewTarget is undefined, then let Some(new_target) = new_target else { @@ -129,7 +129,7 @@ impl DateConstructor { _agent: &mut Agent, _this_value: Value, _arguments: ArgumentsList, - _gc: GcScope<'_, '_>, + _gc: GcScope, ) -> JsResult { let time_value = SystemTime::now() .duration_since(SystemTime::UNIX_EPOCH) @@ -148,7 +148,7 @@ impl DateConstructor { _agent: &mut Agent, _this_value: Value, _arguments: ArgumentsList, - _gc: GcScope<'_, '_>, + _gc: GcScope, ) -> JsResult { todo!(); } @@ -158,7 +158,7 @@ impl DateConstructor { agent: &mut Agent, _this_value: Value, arguments: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { let _ns = arguments.get(0); // 1. Let y be ? ToNumber(year). diff --git a/nova_vm/src/ecmascript/builtins/numbers_and_dates/date_objects/date_prototype.rs b/nova_vm/src/ecmascript/builtins/numbers_and_dates/date_objects/date_prototype.rs index 873e6e4ad..ca0613697 100644 --- a/nova_vm/src/ecmascript/builtins/numbers_and_dates/date_objects/date_prototype.rs +++ b/nova_vm/src/ecmascript/builtins/numbers_and_dates/date_objects/date_prototype.rs @@ -302,7 +302,7 @@ impl DatePrototype { agent: &mut Agent, this_value: Value, _: ArgumentsList, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { let _date_object = check_date_object(agent, this_value, gc.nogc())?; todo!() @@ -312,7 +312,7 @@ impl DatePrototype { agent: &mut Agent, this_value: Value, _: ArgumentsList, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { let _date_object = check_date_object(agent, this_value, gc.nogc())?; todo!() @@ -322,7 +322,7 @@ impl DatePrototype { agent: &mut Agent, this_value: Value, _: ArgumentsList, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { let _date_object = check_date_object(agent, this_value, gc.nogc())?; todo!() @@ -332,7 +332,7 @@ impl DatePrototype { agent: &mut Agent, this_value: Value, _: ArgumentsList, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { let _date_object = check_date_object(agent, this_value, gc.nogc())?; todo!() @@ -342,7 +342,7 @@ impl DatePrototype { agent: &mut Agent, this_value: Value, _: ArgumentsList, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { let _date_object = check_date_object(agent, this_value, gc.nogc())?; todo!() @@ -352,7 +352,7 @@ impl DatePrototype { agent: &mut Agent, this_value: Value, _: ArgumentsList, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { let _date_object = check_date_object(agent, this_value, gc.nogc())?; todo!() @@ -362,7 +362,7 @@ impl DatePrototype { agent: &mut Agent, this_value: Value, _: ArgumentsList, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { let _date_object = check_date_object(agent, this_value, gc.nogc())?; todo!() @@ -372,7 +372,7 @@ impl DatePrototype { agent: &mut Agent, this_value: Value, _: ArgumentsList, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { let _date_object = check_date_object(agent, this_value, gc.nogc())?; todo!() @@ -382,7 +382,7 @@ impl DatePrototype { agent: &mut Agent, this_value: Value, _: ArgumentsList, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { let _date_object = check_date_object(agent, this_value, gc.nogc())?; todo!() @@ -392,7 +392,7 @@ impl DatePrototype { agent: &mut Agent, this_value: Value, _: ArgumentsList, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { let _date_object = check_date_object(agent, this_value, gc.nogc())?; todo!() @@ -402,7 +402,7 @@ impl DatePrototype { agent: &mut Agent, this_value: Value, _: ArgumentsList, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { let _date_object = check_date_object(agent, this_value, gc.nogc())?; todo!() @@ -412,7 +412,7 @@ impl DatePrototype { agent: &mut Agent, this_value: Value, _: ArgumentsList, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { let _date_object = check_date_object(agent, this_value, gc.nogc())?; todo!() @@ -422,7 +422,7 @@ impl DatePrototype { agent: &mut Agent, this_value: Value, _: ArgumentsList, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { let _date_object = check_date_object(agent, this_value, gc.nogc())?; todo!() @@ -432,7 +432,7 @@ impl DatePrototype { agent: &mut Agent, this_value: Value, _: ArgumentsList, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { let _date_object = check_date_object(agent, this_value, gc.nogc())?; todo!() @@ -442,7 +442,7 @@ impl DatePrototype { agent: &mut Agent, this_value: Value, _: ArgumentsList, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { let _date_object = check_date_object(agent, this_value, gc.nogc())?; todo!() @@ -452,7 +452,7 @@ impl DatePrototype { agent: &mut Agent, this_value: Value, _: ArgumentsList, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { let _date_object = check_date_object(agent, this_value, gc.nogc())?; todo!() @@ -462,7 +462,7 @@ impl DatePrototype { agent: &mut Agent, this_value: Value, _: ArgumentsList, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { let _date_object = check_date_object(agent, this_value, gc.nogc())?; todo!() @@ -472,7 +472,7 @@ impl DatePrototype { agent: &mut Agent, this_value: Value, _: ArgumentsList, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { let _date_object = check_date_object(agent, this_value, gc.nogc())?; todo!() @@ -482,7 +482,7 @@ impl DatePrototype { agent: &mut Agent, this_value: Value, _: ArgumentsList, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { let _date_object = check_date_object(agent, this_value, gc.nogc())?; todo!() @@ -492,7 +492,7 @@ impl DatePrototype { agent: &mut Agent, this_value: Value, _: ArgumentsList, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { let _date_object = check_date_object(agent, this_value, gc.nogc())?; todo!() @@ -502,7 +502,7 @@ impl DatePrototype { agent: &mut Agent, this_value: Value, _: ArgumentsList, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { let _date_object = check_date_object(agent, this_value, gc.nogc())?; todo!() @@ -512,7 +512,7 @@ impl DatePrototype { agent: &mut Agent, this_value: Value, _: ArgumentsList, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { let _date_object = check_date_object(agent, this_value, gc.nogc())?; todo!() @@ -522,7 +522,7 @@ impl DatePrototype { agent: &mut Agent, this_value: Value, _: ArgumentsList, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { let _date_object = check_date_object(agent, this_value, gc.nogc())?; todo!() @@ -532,7 +532,7 @@ impl DatePrototype { agent: &mut Agent, this_value: Value, _: ArgumentsList, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { let _date_object = check_date_object(agent, this_value, gc.nogc())?; todo!() @@ -542,7 +542,7 @@ impl DatePrototype { agent: &mut Agent, this_value: Value, _: ArgumentsList, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { let _date_object = check_date_object(agent, this_value, gc.nogc())?; todo!() @@ -552,7 +552,7 @@ impl DatePrototype { agent: &mut Agent, this_value: Value, _: ArgumentsList, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { let _date_object = check_date_object(agent, this_value, gc.nogc())?; todo!() @@ -562,7 +562,7 @@ impl DatePrototype { agent: &mut Agent, this_value: Value, _: ArgumentsList, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { let _date_object = check_date_object(agent, this_value, gc.nogc())?; todo!() @@ -572,7 +572,7 @@ impl DatePrototype { agent: &mut Agent, this_value: Value, _: ArgumentsList, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { let _date_object = check_date_object(agent, this_value, gc.nogc())?; todo!() @@ -582,7 +582,7 @@ impl DatePrototype { agent: &mut Agent, this_value: Value, _: ArgumentsList, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { let _date_object = check_date_object(agent, this_value, gc.nogc())?; todo!() @@ -592,7 +592,7 @@ impl DatePrototype { agent: &mut Agent, this_value: Value, _: ArgumentsList, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { let _date_object = check_date_object(agent, this_value, gc.nogc())?; todo!() @@ -602,7 +602,7 @@ impl DatePrototype { agent: &mut Agent, this_value: Value, _: ArgumentsList, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { let _date_object = check_date_object(agent, this_value, gc.nogc())?; todo!() @@ -612,7 +612,7 @@ impl DatePrototype { agent: &mut Agent, this_value: Value, _: ArgumentsList, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { let _date_object = check_date_object(agent, this_value, gc.nogc())?; todo!() @@ -622,7 +622,7 @@ impl DatePrototype { agent: &mut Agent, this_value: Value, _: ArgumentsList, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { let _date_object = check_date_object(agent, this_value, gc.nogc())?; todo!() @@ -632,7 +632,7 @@ impl DatePrototype { agent: &mut Agent, this_value: Value, _: ArgumentsList, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { let _date_object = check_date_object(agent, this_value, gc.nogc())?; todo!() @@ -642,7 +642,7 @@ impl DatePrototype { agent: &mut Agent, this_value: Value, _: ArgumentsList, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { let _date_object = check_date_object(agent, this_value, gc.nogc())?; todo!() @@ -652,7 +652,7 @@ impl DatePrototype { _agent: &mut Agent, _this_value: Value, _: ArgumentsList, - _gc: GcScope<'_, '_>, + _gc: GcScope, ) -> JsResult { todo!() } @@ -661,7 +661,7 @@ impl DatePrototype { _agent: &mut Agent, _this_value: Value, _: ArgumentsList, - _gc: GcScope<'_, '_>, + _gc: GcScope, ) -> JsResult { todo!() } @@ -670,7 +670,7 @@ impl DatePrototype { _agent: &mut Agent, _this_value: Value, _: ArgumentsList, - _gc: GcScope<'_, '_>, + _gc: GcScope, ) -> JsResult { todo!() } @@ -679,7 +679,7 @@ impl DatePrototype { _agent: &mut Agent, _this_value: Value, _: ArgumentsList, - _gc: GcScope<'_, '_>, + _gc: GcScope, ) -> JsResult { todo!() } @@ -688,7 +688,7 @@ impl DatePrototype { agent: &mut Agent, this_value: Value, _: ArgumentsList, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { let _date_object = check_date_object(agent, this_value, gc.nogc())?; todo!() @@ -698,7 +698,7 @@ impl DatePrototype { agent: &mut Agent, this_value: Value, _: ArgumentsList, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { let _date_object = check_date_object(agent, this_value, gc.nogc())?; todo!() @@ -708,7 +708,7 @@ impl DatePrototype { agent: &mut Agent, this_value: Value, _: ArgumentsList, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { let _date_object = check_date_object(agent, this_value, gc.nogc())?; todo!() @@ -718,7 +718,7 @@ impl DatePrototype { agent: &mut Agent, this_value: Value, _: ArgumentsList, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { let date_object = check_date_object(agent, this_value, gc.nogc())?; let data = &agent[date_object].date; @@ -773,7 +773,7 @@ impl DatePrototype { agent: &mut Agent, this_value: Value, arguments: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { let hint = arguments.get(0); // 1. Let O be the this value. diff --git a/nova_vm/src/ecmascript/builtins/numbers_and_dates/math_object.rs b/nova_vm/src/ecmascript/builtins/numbers_and_dates/math_object.rs index 0993c881b..c0aaa5082 100644 --- a/nova_vm/src/ecmascript/builtins/numbers_and_dates/math_object.rs +++ b/nova_vm/src/ecmascript/builtins/numbers_and_dates/math_object.rs @@ -340,7 +340,7 @@ impl MathObject { agent: &mut Agent, _this_value: Value, arguments: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { let n = to_number(agent, arguments.get(0), gc.reborrow())?; Ok(n.abs(agent).into_value()) @@ -350,7 +350,7 @@ impl MathObject { agent: &mut Agent, _this_value: Value, arguments: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { // 1. Let n be ? ToNumber(x). let n = to_number(agent, arguments.get(0), gc.reborrow())?.into_f64(agent); @@ -364,7 +364,7 @@ impl MathObject { agent: &mut Agent, _this_value: Value, arguments: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { // 1. Let n be ? ToNumber(x). let n = to_number(agent, arguments.get(0), gc.reborrow())?; @@ -390,7 +390,7 @@ impl MathObject { agent: &mut Agent, _this_value: Value, arguments: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { // 1. Let n be ? ToNumber(x). let n = to_number(agent, arguments.get(0), gc.reborrow())?; @@ -415,7 +415,7 @@ impl MathObject { agent: &mut Agent, _this_value: Value, arguments: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { // 1. Let n be ? ToNumber(x). let n = to_number(agent, arguments.get(0), gc.reborrow())?; @@ -434,7 +434,7 @@ impl MathObject { agent: &mut Agent, _this_value: Value, arguments: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { // 1. Let n be ? ToNumber(x). let n = to_number(agent, arguments.get(0), gc.reborrow())?; @@ -463,7 +463,7 @@ impl MathObject { agent: &mut Agent, _this_value: Value, arguments: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { // 1. Let n be ? ToNumber(x). let n = to_number(agent, arguments.get(0), gc.reborrow())?; @@ -498,7 +498,7 @@ impl MathObject { agent: &mut Agent, _this_value: Value, arguments: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { // 1. Let ny be ? ToNumber(y). let ny = to_number(agent, arguments.get(0), gc.reborrow())?.into_f64(agent); @@ -641,7 +641,7 @@ impl MathObject { agent: &mut Agent, _this_value: Value, arguments: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { // 1. Let n be ? ToNumber(x). let n = to_number(agent, arguments.get(0), gc.reborrow())?.unbind(); @@ -661,7 +661,7 @@ impl MathObject { agent: &mut Agent, _this_value: Value, arguments: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { let n = arguments.get(0); // 4. If n is an integral Number, return n. @@ -697,7 +697,7 @@ impl MathObject { agent: &mut Agent, _this_value: Value, arguments: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { // 1. Let n be ? ToUint32(x). let n = to_uint32(agent, arguments.get(0), gc.reborrow())?; @@ -713,7 +713,7 @@ impl MathObject { agent: &mut Agent, _this_value: Value, arguments: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { // 1. Let n be ? ToNumber(x). let n = to_number(agent, arguments.get(0), gc.reborrow())?.into_f64(agent); @@ -736,7 +736,7 @@ impl MathObject { agent: &mut Agent, _this_value: Value, arguments: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { // 1. Let n be ? ToNumber(x). let n = to_number(agent, arguments.get(0), gc.reborrow())?.into_f64(agent); @@ -764,7 +764,7 @@ impl MathObject { agent: &mut Agent, _this_value: Value, arguments: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { //1. Let n be ? ToNumber(x). let n = to_number(agent, arguments.get(0), gc.reborrow())?; @@ -794,7 +794,7 @@ impl MathObject { agent: &mut Agent, _this_value: Value, arguments: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { // 1. Let n be ? ToNumber(x). let n = to_number(agent, arguments.get(0), gc.reborrow())?; @@ -823,7 +823,7 @@ impl MathObject { agent: &mut Agent, _this_value: Value, arguments: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { let n = arguments.get(0); @@ -860,7 +860,7 @@ impl MathObject { agent: &mut Agent, _this_value: Value, arguments: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { // 1. Let n be ? ToNumber(x). let n = to_number(agent, arguments.get(0), gc.reborrow())?; @@ -893,7 +893,7 @@ impl MathObject { agent: &mut Agent, _this_value: Value, arguments: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { // 1. Let coerced be a new empty List. @@ -951,7 +951,7 @@ impl MathObject { agent: &mut Agent, _this_value: Value, arguments: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { // 1. Let a be โ„(? ToUint32(x)). let a = to_uint32(agent, arguments.get(0), gc.reborrow())?; @@ -970,7 +970,7 @@ impl MathObject { agent: &mut Agent, _this_value: Value, arguments: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { // 1. Let n be ? ToNumber(x). let n_number = to_number(agent, arguments.get(0), gc.reborrow())?; @@ -1004,7 +1004,7 @@ impl MathObject { agent: &mut Agent, _this_value: Value, arguments: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { // 1. Let n be ? ToNumber(x). let n_number = to_number(agent, arguments.get(0), gc.reborrow())?; @@ -1029,7 +1029,7 @@ impl MathObject { agent: &mut Agent, _this_value: Value, arguments: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { // 1. Let n be ? ToNumber(x). let n_number = to_number(agent, arguments.get(0), gc.reborrow())?; @@ -1059,7 +1059,7 @@ impl MathObject { agent: &mut Agent, _this_value: Value, arguments: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { // 1. Let n be ? ToNumber(x). let n_number = to_number(agent, arguments.get(0), gc.reborrow())?; @@ -1088,7 +1088,7 @@ impl MathObject { agent: &mut Agent, _this_value: Value, arguments: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { if arguments.is_empty() { return Ok(Value::neg_inf()); @@ -1187,7 +1187,7 @@ impl MathObject { agent: &mut Agent, _this_value: Value, arguments: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { if arguments.is_empty() { return Ok(Value::pos_inf()); @@ -1288,7 +1288,7 @@ impl MathObject { agent: &mut Agent, _this_value: Value, arguments: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { let base = arguments.get(0); let exponent = arguments.get(1); @@ -1345,7 +1345,7 @@ impl MathObject { agent: &mut Agent, _this_value: Value, _: ArgumentsList, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { Ok(Value::from_f64( agent, @@ -1358,7 +1358,7 @@ impl MathObject { agent: &mut Agent, _this_value: Value, arguments: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { let n = arguments.get(0); if n.is_integer() { @@ -1392,7 +1392,7 @@ impl MathObject { agent: &mut Agent, _this_value: Value, arguments: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { // 1. Let n be ? ToNumber(x). let n = to_number(agent, arguments.get(0), gc.reborrow())?; @@ -1412,7 +1412,7 @@ impl MathObject { agent: &mut Agent, _this_value: Value, arguments: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { // 1. Let n be ? ToNumber(x). let n_number = to_number(agent, arguments.get(0), gc.reborrow())?; @@ -1433,7 +1433,7 @@ impl MathObject { agent: &mut Agent, _this_value: Value, arguments: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { // 1. Let n be ? ToNumber(x). let n_number = to_number(agent, arguments.get(0), gc.reborrow())?; @@ -1450,7 +1450,7 @@ impl MathObject { agent: &mut Agent, _this_value: Value, arguments: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { // 1. Let n be ? ToNumber(x). let n_number = to_number(agent, arguments.get(0), gc.reborrow())?; @@ -1471,7 +1471,7 @@ impl MathObject { agent: &mut Agent, _this_value: Value, arguments: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { // 1. Let n be ? ToNumber(x). let n_number = to_number(agent, arguments.get(0), gc.reborrow())?; @@ -1492,7 +1492,7 @@ impl MathObject { agent: &mut Agent, _this_value: Value, arguments: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { // 1. Let n be ? ToNumber(x). let n_number = to_number(agent, arguments.get(0), gc.reborrow())?; @@ -1517,7 +1517,7 @@ impl MathObject { agent: &mut Agent, _this_value: Value, arguments: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { // 1. Let n be ? ToNumber(x). let n_number = to_number(agent, arguments.get(0), gc.reborrow())?; diff --git a/nova_vm/src/ecmascript/builtins/numbers_and_dates/number_objects/number_constructor.rs b/nova_vm/src/ecmascript/builtins/numbers_and_dates/number_objects/number_constructor.rs index 245031448..172d2ffd3 100644 --- a/nova_vm/src/ecmascript/builtins/numbers_and_dates/number_objects/number_constructor.rs +++ b/nova_vm/src/ecmascript/builtins/numbers_and_dates/number_objects/number_constructor.rs @@ -75,7 +75,7 @@ impl NumberConstructor { _this_value: Value, arguments: ArgumentsList, new_target: Option, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { let value = arguments.get(0); @@ -144,7 +144,7 @@ impl NumberConstructor { agent: &mut Agent, _this_value: Value, arguments: ArgumentsList, - _gc: GcScope<'_, '_>, + _gc: GcScope, ) -> JsResult { let maybe_number = arguments.get(0); @@ -163,7 +163,7 @@ impl NumberConstructor { agent: &mut Agent, _this_value: Value, arguments: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { let maybe_number = arguments.get(0); @@ -176,7 +176,7 @@ impl NumberConstructor { agent: &mut Agent, _this_value: Value, arguments: ArgumentsList, - _gc: GcScope<'_, '_>, + _gc: GcScope, ) -> JsResult { let maybe_number = arguments.get(0); @@ -195,7 +195,7 @@ impl NumberConstructor { agent: &mut Agent, _this_value: Value, arguments: ArgumentsList, - _gc: GcScope<'_, '_>, + _gc: GcScope, ) -> JsResult { let maybe_number = arguments.get(0); diff --git a/nova_vm/src/ecmascript/builtins/numbers_and_dates/number_objects/number_prototype.rs b/nova_vm/src/ecmascript/builtins/numbers_and_dates/number_objects/number_prototype.rs index a24cb1e26..3103f25be 100644 --- a/nova_vm/src/ecmascript/builtins/numbers_and_dates/number_objects/number_prototype.rs +++ b/nova_vm/src/ecmascript/builtins/numbers_and_dates/number_objects/number_prototype.rs @@ -84,7 +84,7 @@ impl NumberPrototype { agent: &mut Agent, this_value: Value, arguments: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { let fraction_digits = arguments.get(0); // Let x be ? ThisNumberValue(this value). @@ -130,7 +130,7 @@ impl NumberPrototype { agent: &mut Agent, this_value: Value, arguments: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { let fraction_digits = arguments.get(0); // Let x be ? ThisNumberValue(this value). @@ -175,7 +175,7 @@ impl NumberPrototype { agent: &mut Agent, this_value: Value, arguments: ArgumentsList, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { Self::to_string(agent, this_value, arguments, gc) } @@ -188,7 +188,7 @@ impl NumberPrototype { agent: &mut Agent, this_value: Value, arguments: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { let precision = arguments.get(0); @@ -434,7 +434,7 @@ impl NumberPrototype { agent: &mut Agent, this_value: Value, arguments: ArgumentsList, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { let x = this_number_value(agent, this_value, gc.nogc())?; let radix = arguments.get(0); @@ -449,7 +449,7 @@ impl NumberPrototype { agent: &mut Agent, this_value: Value, _: ArgumentsList, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { this_number_value(agent, this_value, gc.nogc()).map(|result| result.into_value()) } diff --git a/nova_vm/src/ecmascript/builtins/ordinary.rs b/nova_vm/src/ecmascript/builtins/ordinary.rs index aeac0445e..ff5c28e6b 100644 --- a/nova_vm/src/ecmascript/builtins/ordinary.rs +++ b/nova_vm/src/ecmascript/builtins/ordinary.rs @@ -98,14 +98,14 @@ impl IndexMut> for Vec> { } /// ### [10.1 Ordinary Object Internal Methods and Internal Slots](https://tc39.es/ecma262/#sec-ordinary-object-internal-methods-and-internal-slots) -impl InternalMethods for OrdinaryObject<'_> {} +impl<'a> InternalMethods<'a> for OrdinaryObject<'a> {} /// ### [10.1.1.1 OrdinaryGetPrototypeOf ( O )](https://tc39.es/ecma262/#sec-ordinarygetprototypeof) -pub(crate) fn ordinary_get_prototype_of( +pub(crate) fn ordinary_get_prototype_of<'a>( agent: &mut Agent, object: OrdinaryObject, - _: NoGcScope, -) -> Option { + _: NoGcScope<'a, '_>, +) -> Option> { // 1. Return O.[[Prototype]]. object.internal_prototype(agent) } @@ -552,12 +552,17 @@ pub(crate) fn ordinary_has_property( property_key: PropertyKey, mut gc: GcScope, ) -> JsResult { + let object = object.bind(gc.nogc()); let property_key = property_key.bind(gc.nogc()); // Note: We scope here because it's likely we've already tried. + let scoped_object = object.scope(agent, gc.nogc()); let scoped_property_key = property_key.scope(agent, gc.nogc()); // 1. Let hasOwn be ? O.[[GetOwnProperty]](P). - let has_own = object.internal_get_own_property(agent, property_key.unbind(), gc.reborrow())?; + let has_own = + object + .unbind() + .internal_get_own_property(agent, property_key.unbind(), gc.reborrow())?; // 2. If hasOwn is not undefined, return true. if has_own.is_some() { @@ -565,13 +570,17 @@ pub(crate) fn ordinary_has_property( } // 3. Let parent be ? O.[[GetPrototypeOf]](). + let object = scoped_object.get(agent).bind(gc.nogc()); let (parent, property_key) = if let TryResult::Continue(parent) = object.try_get_prototype_of(agent, gc.nogc()) { (parent, scoped_property_key.get(agent).bind(gc.nogc())) } else { - // Note: We should root property_key here. ( - object.internal_get_prototype_of(agent, gc.reborrow())?, + object + .unbind() + .internal_get_prototype_of(agent, gc.reborrow())? + .map(|f| f.unbind()) + .map(|f| f.bind(gc.nogc())), scoped_property_key.get(agent).bind(gc.nogc()), ) }; @@ -579,7 +588,9 @@ pub(crate) fn ordinary_has_property( // 4. If parent is not null, then if let Some(parent) = parent { // a. Return ? parent.[[HasProperty]](P). - return parent.internal_has_property(agent, property_key.unbind(), gc); + return parent + .unbind() + .internal_has_property(agent, property_key.unbind(), gc); } // 5. Return false. @@ -643,16 +654,21 @@ pub(crate) fn ordinary_get( receiver: Value, mut gc: GcScope, ) -> JsResult { + let object = object.bind(gc.nogc()); let property_key = property_key.bind(gc.nogc()); // Note: We scope here because it's likely we've already tried. + let scoped_object = object.scope(agent, gc.nogc()); let scoped_property_key = property_key.scope(agent, gc.nogc()); // 1. Let desc be ? O.[[GetOwnProperty]](P). let Some(descriptor) = - object.internal_get_own_property(agent, property_key.unbind(), gc.reborrow())? + object + .unbind() + .internal_get_own_property(agent, property_key.unbind(), gc.reborrow())? else { // 2. If desc is undefined, then // a. Let parent be ? O.[[GetPrototypeOf]](). + let object = scoped_object.get(agent).bind(gc.nogc()); let (parent, property_key, receiver) = if let TryResult::Continue(parent) = object.try_get_prototype_of(agent, gc.nogc()) { let Some(parent) = parent else { @@ -666,9 +682,13 @@ pub(crate) fn ordinary_get( } else { // Note: We should root property_key and receiver here. let receiver = receiver.scope(agent, gc.nogc()); - let Some(parent) = object.internal_get_prototype_of(agent, gc.reborrow())? else { + let Some(parent) = object + .unbind() + .internal_get_prototype_of(agent, gc.reborrow())? + else { return Ok(Value::Undefined); }; + let parent = parent.unbind().bind(gc.nogc()); let receiver = receiver.get(agent); ( parent, @@ -678,7 +698,9 @@ pub(crate) fn ordinary_get( }; // c. Return ? parent.[[Get]](P, Receiver). - return parent.internal_get(agent, property_key.unbind(), receiver, gc); + return parent + .unbind() + .internal_get(agent, property_key.unbind(), receiver, gc.reborrow()); }; // 3. If IsDataDescriptor(desc) is true, return desc.[[Value]]. @@ -868,7 +890,7 @@ fn ordinary_try_set_with_own_descriptor( fn ordinary_set_with_own_descriptor( agent: &mut Agent, object: Object, - scoped_property_key: Scoped<'_, PropertyKey>, + scoped_property_key: Scoped<'_, PropertyKey<'static>>, value: Value, receiver: Value, own_descriptor: Option, @@ -887,7 +909,9 @@ fn ordinary_set_with_own_descriptor( if let Some(parent) = parent { // i. Return ? parent.[[Set]](P, V, Receiver). // Note: Prototype might be a Proxy or contain a setter. - return parent.internal_set(agent, property_key.unbind(), value, receiver, gc); + return parent + .unbind() + .internal_set(agent, property_key.unbind(), value, receiver, gc); } // c. Else, else { @@ -1094,11 +1118,12 @@ pub(crate) fn ordinary_own_property_keys<'a>( /// default prototype from the intrinsics, otherwise with the given prototype. /// To create an object with null prototype, both `proto_intrinsics` and /// `prototype` must be None. -pub(crate) fn ordinary_object_create_with_intrinsics( +pub(crate) fn ordinary_object_create_with_intrinsics<'a>( agent: &mut Agent, proto_intrinsics: Option, prototype: Option, -) -> Object { + gc: NoGcScope<'a, '_>, +) -> Object<'a> { let Some(proto_intrinsics) = proto_intrinsics else { assert!(prototype.is_none()); return agent.heap.create_null_object(&[]).into(); @@ -1291,7 +1316,7 @@ pub(crate) fn ordinary_object_create_with_intrinsics( object.internal_set_prototype(agent, Some(prototype)); } - object + object.bind(gc) } /// ### [10.1.13 OrdinaryCreateFromConstructor ( constructor, intrinsicDefaultProto \[ , internalSlotsList \] )](https://tc39.es/ecma262/#sec-ordinarycreatefromconstructor) @@ -1310,27 +1335,32 @@ pub(crate) fn ordinary_object_create_with_intrinsics( /// NOTE: In this implementation, `intrinsic_default_proto` also defines which /// kind of heap data type the created object uses, and therefore which internal /// slots it has. Therefore the `internalSlotsList` property isn't present. -pub(crate) fn ordinary_create_from_constructor( +pub(crate) fn ordinary_create_from_constructor<'a>( agent: &mut Agent, constructor: Function, intrinsic_default_proto: ProtoIntrinsics, - gc: GcScope, -) -> JsResult { + mut gc: GcScope<'a, '_>, +) -> JsResult> { let constructor = constructor.bind(gc.nogc()); // 1. Assert: intrinsicDefaultProto is this specification's name of an // intrinsic object. The corresponding object must be an intrinsic that is // intended to be used as the [[Prototype]] value of an object. // 2. Let proto be ? GetPrototypeFromConstructor(constructor, intrinsicDefaultProto). - let proto = - get_prototype_from_constructor(agent, constructor.unbind(), intrinsic_default_proto, gc)?; + let proto = get_prototype_from_constructor( + agent, + constructor.unbind(), + intrinsic_default_proto, + gc.reborrow(), + )?; // 3. If internalSlotsList is present, let slotsList be internalSlotsList. // 4. Else, let slotsList be a new empty List. // 5. Return OrdinaryObjectCreate(proto, slotsList). Ok(ordinary_object_create_with_intrinsics( agent, Some(intrinsic_default_proto), - proto, + proto.map(|f| f.unbind()), + gc.into_nogc(), )) } @@ -1348,12 +1378,12 @@ pub(crate) fn ordinary_create_from_constructor( /// NOTE: In this implementation, the function returns None if the prototype it /// would otherwise return is the prototype that corresponds to /// `intrinsic_default_proto`. -pub(crate) fn get_prototype_from_constructor( +pub(crate) fn get_prototype_from_constructor<'a>( agent: &mut Agent, constructor: Function, intrinsic_default_proto: ProtoIntrinsics, - gc: GcScope, -) -> JsResult> { + gc: GcScope<'a, '_>, +) -> JsResult>> { let constructor = constructor.bind(gc.nogc()); let function_realm = get_function_realm(agent, constructor); // NOTE: %Constructor%.prototype is an immutable property; we can thus diff --git a/nova_vm/src/ecmascript/builtins/primitive_objects.rs b/nova_vm/src/ecmascript/builtins/primitive_objects.rs index 5524bba7c..416ef2bc5 100644 --- a/nova_vm/src/ecmascript/builtins/primitive_objects.rs +++ b/nova_vm/src/ecmascript/builtins/primitive_objects.rs @@ -46,7 +46,7 @@ impl<'a> From> for PrimitiveObject<'a> { } } -impl From> for Object { +impl<'a> From> for Object<'a> { fn from(value: PrimitiveObject) -> Self { Self::PrimitiveObject(value.unbind()) } @@ -58,8 +58,8 @@ impl From> for Value { } } -impl IntoObject for PrimitiveObject<'_> { - fn into_object(self) -> Object { +impl<'a> IntoObject<'a> for PrimitiveObject<'a> { + fn into_object(self) -> Object<'a> { self.into() } } @@ -70,10 +70,10 @@ impl IntoValue for PrimitiveObject<'_> { } } -impl TryFrom for PrimitiveObject<'_> { +impl<'a> TryFrom> for PrimitiveObject<'a> { type Error = (); - fn try_from(value: Object) -> Result { + fn try_from(value: Object<'a>) -> Result { match value { Object::PrimitiveObject(obj) => Ok(obj), _ => Err(()), @@ -131,7 +131,7 @@ impl<'a> PrimitiveObject<'a> { /// the PrimitiveObject as a parameter in a call that can perform garbage /// collection. pub fn unbind(self) -> PrimitiveObject<'static> { - unsafe { std::mem::transmute::, PrimitiveObject<'static>>(self) } + unsafe { std::mem::transmute::>(self) } } // Bind this PrimitiveObject to the garbage collection lifetime. This enables Rust's @@ -191,7 +191,7 @@ impl<'a> PrimitiveObject<'a> { } } -impl InternalSlots for PrimitiveObject<'_> { +impl<'a> InternalSlots<'a> for PrimitiveObject<'a> { #[inline(always)] fn get_backing_object(self, agent: &Agent) -> Option> { agent[self].object_index @@ -204,10 +204,7 @@ impl InternalSlots for PrimitiveObject<'_> { .is_none()); } - fn internal_prototype( - self, - agent: &crate::ecmascript::execution::Agent, - ) -> Option { + fn internal_prototype(self, agent: &Agent) -> Option> { match self.get_backing_object(agent) { Some(obj) => obj.internal_prototype(agent), None => { @@ -237,12 +234,12 @@ impl InternalSlots for PrimitiveObject<'_> { } } -impl InternalMethods for PrimitiveObject<'_> { +impl<'a> InternalMethods<'a> for PrimitiveObject<'a> { fn try_get_own_property( self, agent: &mut Agent, property_key: PropertyKey, - _: NoGcScope<'_, '_>, + _: NoGcScope, ) -> TryResult> { // For non-string primitive objects: // 1. Return OrdinaryGetOwnProperty(O, P). @@ -270,7 +267,7 @@ impl InternalMethods for PrimitiveObject<'_> { agent: &mut Agent, property_key: PropertyKey, property_descriptor: PropertyDescriptor, - gc: NoGcScope<'_, '_>, + gc: NoGcScope, ) -> TryResult { if let Ok(string) = String::try_from(agent[self].data) { // For string exotic objects: @@ -306,7 +303,7 @@ impl InternalMethods for PrimitiveObject<'_> { self, agent: &mut Agent, property_key: PropertyKey, - gc: NoGcScope<'_, '_>, + gc: NoGcScope, ) -> TryResult { if let Ok(string) = String::try_from(agent[self].data) { if string @@ -342,7 +339,7 @@ impl InternalMethods for PrimitiveObject<'_> { self, agent: &mut Agent, property_key: PropertyKey, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { let property_key = property_key.bind(gc.nogc()); if let Ok(string) = String::try_from(agent[self].data) { @@ -367,7 +364,9 @@ impl InternalMethods for PrimitiveObject<'_> { // 4. If parent is not null, then if let Some(parent) = parent { // a. Return ? parent.[[HasProperty]](P). - parent.internal_has_property(agent, property_key.unbind(), gc) + parent + .unbind() + .internal_has_property(agent, property_key.unbind(), gc) } else { // 5. Return false. Ok(false) @@ -381,7 +380,7 @@ impl InternalMethods for PrimitiveObject<'_> { agent: &mut Agent, property_key: PropertyKey, receiver: Value, - gc: NoGcScope<'_, '_>, + gc: NoGcScope, ) -> TryResult { if let Ok(string) = String::try_from(agent[self].data) { if let Some(string_desc) = string.get_property_descriptor(agent, property_key) { @@ -412,7 +411,7 @@ impl InternalMethods for PrimitiveObject<'_> { agent: &mut Agent, property_key: PropertyKey, receiver: Value, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { let property_key = property_key.bind(gc.nogc()); if let Ok(string) = String::try_from(agent[self].data) { @@ -434,7 +433,9 @@ impl InternalMethods for PrimitiveObject<'_> { }; // c. Return ? parent.[[Get]](P, Receiver). - parent.internal_get(agent, property_key.unbind(), receiver, gc) + parent + .unbind() + .internal_get(agent, property_key.unbind(), receiver, gc) } } } @@ -445,7 +446,7 @@ impl InternalMethods for PrimitiveObject<'_> { property_key: PropertyKey, value: Value, receiver: Value, - gc: NoGcScope<'_, '_>, + gc: NoGcScope, ) -> TryResult { if let Ok(string) = String::try_from(agent[self].data) { if string @@ -466,7 +467,7 @@ impl InternalMethods for PrimitiveObject<'_> { property_key: PropertyKey, value: Value, receiver: Value, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { let property_key = property_key.bind(gc.nogc()); if let Ok(string) = String::try_from(agent[self].data) { @@ -493,7 +494,7 @@ impl InternalMethods for PrimitiveObject<'_> { self, agent: &mut Agent, property_key: PropertyKey, - gc: NoGcScope<'_, '_>, + gc: NoGcScope, ) -> TryResult { if let Ok(string) = String::try_from(agent[self].data) { // A String will return unconfigurable descriptors for length and @@ -517,11 +518,11 @@ impl InternalMethods for PrimitiveObject<'_> { } } - fn try_own_property_keys<'a>( + fn try_own_property_keys<'gc>( self, agent: &mut Agent, - gc: NoGcScope<'a, '_>, - ) -> TryResult>> { + gc: NoGcScope<'gc, '_>, + ) -> TryResult>> { if let Ok(string) = String::try_from(agent[self].data) { let len = string.utf16_len(agent); let mut keys = Vec::with_capacity(len + 1); diff --git a/nova_vm/src/ecmascript/builtins/promise.rs b/nova_vm/src/ecmascript/builtins/promise.rs index fccf88e1d..86eb24492 100644 --- a/nova_vm/src/ecmascript/builtins/promise.rs +++ b/nova_vm/src/ecmascript/builtins/promise.rs @@ -92,8 +92,8 @@ impl IntoValue for Promise<'_> { } } -impl IntoObject for Promise<'_> { - fn into_object(self) -> Object { +impl<'a> IntoObject<'a> for Promise<'a> { + fn into_object(self) -> Object<'a> { self.into() } } @@ -104,13 +104,13 @@ impl From> for Value { } } -impl From> for Object { +impl<'a> From> for Object<'a> { fn from(val: Promise) -> Self { Object::Promise(val.unbind()) } } -impl InternalSlots for Promise<'_> { +impl<'a> InternalSlots<'a> for Promise<'a> { const DEFAULT_PROTOTYPE: ProtoIntrinsics = ProtoIntrinsics::Promise; #[inline(always)] @@ -126,7 +126,7 @@ impl InternalSlots for Promise<'_> { } } -impl InternalMethods for Promise<'_> {} +impl<'a> InternalMethods<'a> for Promise<'a> {} impl CreateHeapData> for Heap { fn create(&mut self, data: PromiseHeapData) -> Promise<'static> { diff --git a/nova_vm/src/ecmascript/builtins/proxy.rs b/nova_vm/src/ecmascript/builtins/proxy.rs index 9e0079d5c..b5bc35b20 100644 --- a/nova_vm/src/ecmascript/builtins/proxy.rs +++ b/nova_vm/src/ecmascript/builtins/proxy.rs @@ -88,8 +88,8 @@ impl IntoValue for Proxy<'_> { } } -impl IntoObject for Proxy<'_> { - fn into_object(self) -> Object { +impl<'a> IntoObject<'a> for Proxy<'a> { + fn into_object(self) -> Object<'a> { self.into() } } @@ -100,13 +100,13 @@ impl From> for Value { } } -impl From> for Object { +impl<'a> From> for Object<'a> { fn from(val: Proxy) -> Self { Object::Proxy(val.unbind()) } } -impl InternalSlots for Proxy<'_> { +impl<'a> InternalSlots<'a> for Proxy<'a> { #[inline(always)] fn get_backing_object(self, _agent: &Agent) -> Option> { todo!() @@ -128,7 +128,7 @@ impl InternalSlots for Proxy<'_> { todo!(); } - fn internal_prototype(self, _agent: &Agent) -> Option { + fn internal_prototype(self, _agent: &Agent) -> Option> { todo!(); } @@ -137,16 +137,20 @@ impl InternalSlots for Proxy<'_> { } } -impl InternalMethods for Proxy<'_> { - fn try_get_prototype_of(self, _: &mut Agent, _: NoGcScope) -> TryResult> { +impl<'a> InternalMethods<'a> for Proxy<'a> { + fn try_get_prototype_of<'gc>( + self, + _: &mut Agent, + _: NoGcScope<'gc, '_>, + ) -> TryResult>> { TryResult::Break(()) } - fn internal_get_prototype_of( + fn internal_get_prototype_of<'gc>( self, agent: &mut Agent, - mut gc: GcScope, - ) -> JsResult> { + mut gc: GcScope<'gc, '_>, + ) -> JsResult>> { // 1. Perform ? ValidateNonRevokedProxy(O). // 2. Let target be O.[[ProxyTarget]]. // 3. Let handler be O.[[ProxyHandler]]. @@ -169,7 +173,7 @@ impl InternalMethods for Proxy<'_> { let scoped_handler = handler.scope(agent, gc.nogc()); let trap = get_object_method( agent, - handler, + handler.unbind(), BUILTIN_STRING_MEMORY.getPrototypeOf.into(), gc.reborrow(), )? @@ -261,6 +265,7 @@ impl InternalMethods for Proxy<'_> { mut target, mut handler, } = validate_non_revoked_proxy(agent, self, gc.nogc())?; + let scoped_target = target.scope(agent, gc.nogc()); // 5. Let trap be ? GetMethod(handler, "setPrototypeOf"). let trap = if let TryResult::Continue(trap) = try_get_object_method( agent, @@ -270,11 +275,10 @@ impl InternalMethods for Proxy<'_> { ) { trap? } else { - let scoped_target = target.scope(agent, gc.nogc()); let scoped_handler = handler.scope(agent, gc.nogc()); let trap = get_object_method( agent, - handler, + handler.unbind(), BUILTIN_STRING_MEMORY.setPrototypeOf.into(), gc.reborrow(), )? @@ -288,7 +292,9 @@ impl InternalMethods for Proxy<'_> { // 6. If trap is undefined, then let Some(trap) = trap else { // a. Return ? target.[[SetPrototypeOf]](V). - return target.internal_set_prototype_of(agent, prototype, gc); + return target + .unbind() + .internal_set_prototype_of(agent, prototype, gc); }; // 7. Let booleanTrapResult be ToBoolean(? Call(trap, handler, ยซ target, V ยป)). let argument = call_function( @@ -304,13 +310,15 @@ impl InternalMethods for Proxy<'_> { return Ok(false); } // 9. Let extensibleTarget be ? IsExtensible(target). - let extensible_target = is_extensible(agent, target, gc.reborrow())?; + let extensible_target = is_extensible(agent, scoped_target.get(agent), gc.reborrow())?; // 10. If extensibleTarget is true, return true. if extensible_target { return Ok(true); } // 11. Let targetProto be ? target.[[GetPrototypeOf]](). - let target_proto = target.internal_get_prototype_of(agent, gc.reborrow())?; + let target_proto = scoped_target + .get(agent) + .internal_get_prototype_of(agent, gc.reborrow())?; // 12. If SameValue(V, targetProto) is false, throw a TypeError exception. if prototype != target_proto { return Err(agent.throw_exception_with_static_message( @@ -350,7 +358,7 @@ impl InternalMethods for Proxy<'_> { let scoped_handler = handler.scope(agent, gc.nogc()); let trap = get_object_method( agent, - handler, + handler.unbind(), BUILTIN_STRING_MEMORY.isExtensible.into(), gc.reborrow(), )? @@ -419,7 +427,7 @@ impl InternalMethods for Proxy<'_> { let scoped_handler = handler.scope(agent, gc.nogc()); let trap = get_object_method( agent, - handler, + handler.unbind(), BUILTIN_STRING_MEMORY.preventExtensions.into(), gc.reborrow(), )? @@ -493,6 +501,7 @@ impl InternalMethods for Proxy<'_> { mut target, mut handler, } = validate_non_revoked_proxy(agent, self, gc.nogc())?; + let scoped_target = target.scope(agent, gc.nogc()); // 5. Let trap be ? GetMethod(handler, "getOwnPropertyDescriptor"). let trap = if let TryResult::Continue(trap) = try_get_object_method( agent, @@ -502,11 +511,10 @@ impl InternalMethods for Proxy<'_> { ) { trap? } else { - let scoped_target = target.scope(agent, gc.nogc()); let scoped_handler = handler.scope(agent, gc.nogc()); let trap = get_object_method( agent, - handler, + handler.unbind(), BUILTIN_STRING_MEMORY.getOwnPropertyDescriptor.into(), gc.reborrow(), )? @@ -520,7 +528,9 @@ impl InternalMethods for Proxy<'_> { // 6. If trap is undefined, then let Some(trap) = trap else { // a. Return ? target.[[GetOwnProperty]](P). - return target.internal_get_own_property(agent, property_key, gc); + return target + .unbind() + .internal_get_own_property(agent, property_key.unbind(), gc); }; // 7. Let trapResultObj be ? Call(trap, handler, ยซ target, P ยป). @@ -541,7 +551,10 @@ impl InternalMethods for Proxy<'_> { )); }; // 9. Let targetDesc be ? target.[[GetOwnProperty]](P). - let target_desc = target.internal_get_own_property(agent, property_key, gc.reborrow())?; + let target_desc = scoped_target + .get(agent) + .unbind() + .internal_get_own_property(agent, property_key.unbind(), gc.reborrow())?; // 10. If trapResultObj is undefined, then if trap_result_obj.is_undefined() { if let Some(target_desc) = target_desc { @@ -561,7 +574,7 @@ impl InternalMethods for Proxy<'_> { return Ok(None); } // c. Let extensibleTarget be ? IsExtensible(target). - let extensible_target = is_extensible(agent, target, gc.reborrow())?; + let extensible_target = is_extensible(agent, scoped_target.get(agent), gc.reborrow())?; // d. If extensibleTarget is false, throw a TypeError exception. if !extensible_target { return Err(agent.throw_exception( @@ -577,7 +590,7 @@ impl InternalMethods for Proxy<'_> { return Ok(None); }; // 11. Let extensibleTarget be ? IsExtensible(target). - let extensible_target = is_extensible(agent, target, gc.reborrow())?; + let extensible_target = is_extensible(agent, scoped_target.get(agent), gc.reborrow())?; // 12. Let resultDesc be ? ToPropertyDescriptor(trapResultObj). let mut result_desc = PropertyDescriptor::to_property_descriptor(agent, trap_result_obj, gc.reborrow())?; @@ -663,6 +676,7 @@ impl InternalMethods for Proxy<'_> { mut target, mut handler, } = validate_non_revoked_proxy(agent, self, gc.nogc())?; + let mut scoped_target = None; // 5. Let trap be ? GetMethod(handler, "defineProperty"). let trap = if let TryResult::Continue(trap) = try_get_object_method( agent, @@ -673,10 +687,10 @@ impl InternalMethods for Proxy<'_> { trap? } else { let scoped_handler = handler.scope(agent, gc.nogc()); - let scoped_target = target.scope(agent, gc.nogc()); + scoped_target = Some(target.scope(agent, gc.nogc())); let trap = get_object_method( agent, - handler, + handler.unbind(), BUILTIN_STRING_MEMORY.defineProperty.into(), gc.reborrow(), )? @@ -684,19 +698,20 @@ impl InternalMethods for Proxy<'_> { let gc = gc.nogc(); let trap = trap.map(|f| f.bind(gc)); handler = scoped_handler.get(agent).bind(gc); - target = scoped_target.get(agent).bind(gc); + target = scoped_target.as_ref().unwrap().get(agent).bind(gc); trap }; // 6. If trap is undefined, then let Some(trap) = trap else { // a. Return ? target.[[DefineOwnProperty]](P, Desc). - return target.internal_define_own_property( + return target.unbind().internal_define_own_property( agent, property_key.unbind(), property_descriptor, gc, ); }; + let scoped_target = scoped_target.unwrap_or_else(|| target.scope(agent, gc.nogc())); // 7. Let descObj be FromPropertyDescriptor(Desc). let desc_obj = PropertyDescriptor::from_property_descriptor( property_descriptor.clone().into(), @@ -718,9 +733,13 @@ impl InternalMethods for Proxy<'_> { return Ok(false); }; // 10. Let targetDesc be ? target.[[GetOwnProperty]](P). - let target_desc = target.internal_get_own_property(agent, property_key, gc.reborrow())?; + let target_desc = scoped_target.get(agent).internal_get_own_property( + agent, + property_key.unbind(), + gc.reborrow(), + )?; // 11. Let extensibleTarget be ? IsExtensible(target). - let extensible_target = is_extensible(agent, target, gc.reborrow())?; + let extensible_target = is_extensible(agent, scoped_target.get(agent), gc.reborrow())?; // 12. If Desc has a [[Configurable]] field and Desc.[[Configurable]] is false, then let setting_config_false = property_descriptor.configurable == Some(false); // 14. If targetDesc is undefined, then @@ -769,7 +788,7 @@ impl InternalMethods for Proxy<'_> { }; // b. If settingConfigFalse is true and targetDesc.[[Configurable]] is true, throw a TypeError exception. if setting_config_false { - if let Some(ref target_desc) = target_desc { + if let Some(target_desc) = &target_desc { if target_desc.configurable == Some(true) { return Err(agent.throw_exception( ExceptionType::TypeError, @@ -840,7 +859,7 @@ impl InternalMethods for Proxy<'_> { let scoped_handler = handler.scope(agent, gc.nogc()); let trap = get_object_method( agent, - handler, + handler.unbind(), BUILTIN_STRING_MEMORY.has.into(), gc.reborrow(), )? @@ -855,7 +874,9 @@ impl InternalMethods for Proxy<'_> { // 6. If trap is undefined, then let Some(trap) = trap else { // Return ? target.[[HasProperty]](P). - return target.internal_has_property(agent, property_key.unbind(), gc); + return target + .unbind() + .internal_has_property(agent, property_key.unbind(), gc); }; // 7. Let booleanTrapResult be ToBoolean(? Call(trap, handler, ยซ target, P ยป)). @@ -874,8 +895,11 @@ impl InternalMethods for Proxy<'_> { // a. Let targetDesc be ? target.[[GetOwnProperty]](P). let target = scoped_target.get(agent).bind(gc.nogc()); let property_key = scoped_property_key.get(agent).bind(gc.nogc()); - let target_desc = - target.internal_get_own_property(agent, property_key.unbind(), gc.reborrow())?; + let target_desc = target.unbind().internal_get_own_property( + agent, + property_key.unbind(), + gc.reborrow(), + )?; // b. If targetDesc is not undefined, then if let Some(target_desc) = target_desc { // i. If targetDesc.[[Configurable]] is false, throw a TypeError exception. @@ -954,7 +978,7 @@ impl InternalMethods for Proxy<'_> { let scoped_receiver = receiver.scope(agent, gc.nogc()); let trap = get_object_method( agent, - handler, + handler.unbind(), BUILTIN_STRING_MEMORY.get.into(), gc.reborrow(), )? @@ -970,7 +994,9 @@ impl InternalMethods for Proxy<'_> { // 6. If trap is undefined, then let Some(trap) = trap else { // a. Return ? target.[[Get]](P, Receiver). - return target.internal_get(agent, property_key.unbind(), receiver, gc); + return target + .unbind() + .internal_get(agent, property_key.unbind(), receiver, gc); }; // 7. Let trapResult be ? Call(trap, handler, ยซ target, P, Receiver ยป). let p = property_key.convert_to_value(agent, gc.nogc()); @@ -984,8 +1010,11 @@ impl InternalMethods for Proxy<'_> { // 8. Let targetDesc be ? target.[[GetOwnProperty]](P). let target = scoped_target.get(agent).bind(gc.nogc()); let property_key = scoped_property_key.get(agent).bind(gc.nogc()); - let target_desc = - target.internal_get_own_property(agent, property_key.unbind(), gc.reborrow())?; + let target_desc = target.unbind().internal_get_own_property( + agent, + property_key.unbind(), + gc.reborrow(), + )?; // 9. If targetDesc is not undefined and targetDesc.[[Configurable]] is false, then if let Some(target_desc) = target_desc { if target_desc.configurable == Some(false) { @@ -1065,7 +1094,7 @@ impl InternalMethods for Proxy<'_> { let scoped_receiver = receiver.scope(agent, gc.nogc()); let trap = get_object_method( agent, - handler, + handler.unbind(), BUILTIN_STRING_MEMORY.set.into(), gc.reborrow(), )? @@ -1081,7 +1110,9 @@ impl InternalMethods for Proxy<'_> { // 6. If trap is undefined, then let Some(trap) = trap else { // a. Return ?ย target.[[Set]](P, V, Receiver). - return target.internal_set(agent, property_key.unbind(), value, receiver, gc); + return target + .unbind() + .internal_set(agent, property_key.unbind(), value, receiver, gc); }; // 7. Let booleanTrapResult be ToBoolean(? Call(trap, handler, ยซ target, P, V, Receiverย ยป)). let p = property_key.convert_to_value(agent, gc.nogc()); @@ -1102,8 +1133,11 @@ impl InternalMethods for Proxy<'_> { // 9. Let targetDesc be ?ย target.[[GetOwnProperty]](P). let target = scoped_target.get(agent).bind(gc.nogc()); let property_key = scoped_property_key.get(agent).bind(gc.nogc()); - let target_desc = - target.internal_get_own_property(agent, property_key.unbind(), gc.reborrow())?; + let target_desc = target.unbind().internal_get_own_property( + agent, + property_key.unbind(), + gc.reborrow(), + )?; // 10. If targetDesc is not undefined and targetDesc.[[Configurable]] is false, then if let Some(target_desc) = target_desc { if target_desc.configurable == Some(false) { @@ -1150,6 +1184,7 @@ impl InternalMethods for Proxy<'_> { mut target, mut handler, } = validate_non_revoked_proxy(agent, self, gc.nogc())?; + let mut scoped_target = None; // 5. Let trap be ? GetMethod(handler, "deleteProperty"). let trap = if let TryResult::Continue(trap) = try_get_object_method( agent, @@ -1160,11 +1195,11 @@ impl InternalMethods for Proxy<'_> { trap? } else { let scoped_handler = handler.scope(agent, gc.nogc()); - let scoped_target = target.scope(agent, gc.nogc()); + scoped_target = Some(target.scope(agent, gc.nogc())); let scoped_property_key = property_key.scope(agent, gc.nogc()); let trap = get_object_method( agent, - handler, + handler.unbind(), BUILTIN_STRING_MEMORY.deleteProperty.into(), gc.reborrow(), )? @@ -1172,15 +1207,18 @@ impl InternalMethods for Proxy<'_> { let gc = gc.nogc(); let trap = trap.map(|f| f.bind(gc)); handler = scoped_handler.get(agent).bind(gc); - target = scoped_target.get(agent).bind(gc); + target = scoped_target.as_ref().unwrap().get(agent).bind(gc); property_key = scoped_property_key.get(agent); trap }; // 6. If trap is undefined, then let Some(trap) = trap else { // a. Return ? target.[[Delete]](P). - return target.internal_delete(agent, property_key, gc); + return target + .unbind() + .internal_delete(agent, property_key.unbind(), gc); }; + let scoped_target = scoped_target.unwrap_or_else(|| target.scope(agent, gc.nogc())); // 7. Let booleanTrapResult be ToBoolean(? Call(trap, handler, ยซ target, P ยป)). let p = property_key.convert_to_value(agent, gc.nogc()); let argument = call_function( @@ -1196,7 +1234,11 @@ impl InternalMethods for Proxy<'_> { return Ok(false); }; // 9. Let targetDesc be ? target.[[GetOwnProperty]](P). - let target_desc = target.internal_get_own_property(agent, property_key, gc.reborrow())?; + let target_desc = scoped_target.get(agent).internal_get_own_property( + agent, + property_key.unbind(), + gc.reborrow(), + )?; // 10. If targetDesc is undefined, return true. let Some(target_desc) = target_desc else { return Ok(true); @@ -1213,7 +1255,7 @@ impl InternalMethods for Proxy<'_> { )); }; // 12. Let extensibleTarget be ? IsExtensible(target). - let extensible_target = is_extensible(agent, target, gc.reborrow())?; + let extensible_target = is_extensible(agent, scoped_target.get(agent), gc.reborrow())?; // 13. If extensibleTarget is false, throw a TypeError exception. if !extensible_target { return Err(agent.throw_exception( @@ -1229,19 +1271,19 @@ impl InternalMethods for Proxy<'_> { Ok(true) } - fn try_own_property_keys<'a>( + fn try_own_property_keys<'gc>( self, _: &mut Agent, - _: NoGcScope<'a, '_>, - ) -> TryResult>> { + _: NoGcScope<'gc, '_>, + ) -> TryResult>> { TryResult::Break(()) } - fn internal_own_property_keys<'a>( + fn internal_own_property_keys<'gc>( self, _agent: &mut Agent, - _gc: GcScope<'a, '_>, - ) -> JsResult>> { + _gc: GcScope<'gc, '_>, + ) -> JsResult>> { todo!(); } @@ -1282,7 +1324,7 @@ impl InternalMethods for Proxy<'_> { let scoped_target = target.scope(agent, gc.nogc()); let trap = get_object_method( agent, - handler, + handler.unbind(), BUILTIN_STRING_MEMORY.apply.into(), gc.reborrow(), )? @@ -1320,13 +1362,13 @@ impl InternalMethods for Proxy<'_> { ); } - fn internal_construct( + fn internal_construct<'gc>( self, agent: &mut Agent, arguments_list: ArgumentsList, new_target: Function, - mut gc: GcScope<'_, '_>, - ) -> JsResult { + mut gc: GcScope<'gc, '_>, + ) -> JsResult> { // 1. Perform ? ValidateNonRevokedProxy(O). // 2. Let target be O.[[ProxyTarget]]. // 4. Let handler be O.[[ProxyHandler]]. @@ -1336,7 +1378,7 @@ impl InternalMethods for Proxy<'_> { mut handler, } = validate_non_revoked_proxy(agent, self, gc.nogc())?; // 3. Assert: IsConstructor(target) is true. - let target = is_constructor(agent, target).unwrap(); + let mut target = is_constructor(agent, target).unwrap(); // 6. Let trap be ? GetMethod(handler, "construct"). let trap = if let TryResult::Continue(trap) = try_get_object_method( agent, @@ -1346,23 +1388,31 @@ impl InternalMethods for Proxy<'_> { ) { trap? } else { + let scoped_target = target.scope(agent, gc.nogc()); let scoped_handler = handler.scope(agent, gc.nogc()); let trap = get_object_method( agent, - handler, + handler.unbind(), BUILTIN_STRING_MEMORY.construct.into(), gc.reborrow(), )? .map(Function::unbind); let gc = gc.nogc(); let trap = trap.map(|f| f.bind(gc)); + target = scoped_target.get(agent).bind(gc); handler = scoped_handler.get(agent).bind(gc); trap }; // 7. If trap is undefined, then let Some(trap) = trap else { // a. Return ? Construct(target, argumentsList, newTarget). - return construct(agent, target, Some(arguments_list), Some(new_target), gc); + return construct( + agent, + target.unbind(), + Some(arguments_list), + Some(new_target), + gc, + ); }; // 8. Let argArray be CreateArrayFromList(argumentsList). let arg_array = create_array_from_list(agent, arguments_list.0, gc.nogc()); diff --git a/nova_vm/src/ecmascript/builtins/proxy/abstract_operations.rs b/nova_vm/src/ecmascript/builtins/proxy/abstract_operations.rs index 9486d3fd8..61b95647b 100644 --- a/nova_vm/src/ecmascript/builtins/proxy/abstract_operations.rs +++ b/nova_vm/src/ecmascript/builtins/proxy/abstract_operations.rs @@ -13,9 +13,9 @@ use crate::{ use super::Proxy; #[derive(Debug, Clone, Copy)] -pub(crate) struct NonRevokedProxy { - pub(crate) target: Object, - pub(crate) handler: Object, +pub(crate) struct NonRevokedProxy<'a> { + pub(crate) target: Object<'a>, + pub(crate) handler: Object<'a>, } /// ### [10.5.14 ValidateNonRevokedProxy ( proxy )](https://tc39.es/ecma262/#sec-validatenonrevokedproxy) @@ -23,11 +23,11 @@ pub(crate) struct NonRevokedProxy { /// The abstract operation ValidateNonRevokedProxy takes argument /// proxy (a Proxy exotic object) and returns either a normal completion containing unused or a throw completion. /// It throws a TypeError exception if proxy has been revoked. -pub(crate) fn validate_non_revoked_proxy( +pub(crate) fn validate_non_revoked_proxy<'a>( agent: &mut Agent, proxy: Proxy, - gc: NoGcScope, -) -> JsResult { + gc: NoGcScope<'a, '_>, +) -> JsResult> { let proxy_data = &agent[proxy]; // 1. If proxy.[[ProxyTarget]] is null, throw a TypeError exception. diff --git a/nova_vm/src/ecmascript/builtins/proxy/data.rs b/nova_vm/src/ecmascript/builtins/proxy/data.rs index e3f9577e8..4e809a0e7 100644 --- a/nova_vm/src/ecmascript/builtins/proxy/data.rs +++ b/nova_vm/src/ecmascript/builtins/proxy/data.rs @@ -10,9 +10,9 @@ use crate::{ #[derive(Debug, Clone)] pub struct ProxyHeapData { /// [[ProxyTarget]] - pub(crate) proxy_target: Option, + pub(crate) proxy_target: Option>, /// [[ProxyHandler]] - pub(crate) proxy_handler: Option, + pub(crate) proxy_handler: Option>, } impl HeapMarkAndSweep for ProxyHeapData { diff --git a/nova_vm/src/ecmascript/builtins/reflection/proxy_constructor.rs b/nova_vm/src/ecmascript/builtins/reflection/proxy_constructor.rs index 177f99273..9773285f9 100644 --- a/nova_vm/src/ecmascript/builtins/reflection/proxy_constructor.rs +++ b/nova_vm/src/ecmascript/builtins/reflection/proxy_constructor.rs @@ -44,7 +44,7 @@ impl ProxyConstructor { _this_value: Value, arguments: ArgumentsList, new_target: Option, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { let gc = gc.into_nogc(); let target = arguments.get(0); @@ -65,7 +65,7 @@ impl ProxyConstructor { _agent: &mut Agent, _this_value: Value, _arguments: ArgumentsList, - _gc: GcScope<'_, '_>, + _gc: GcScope, ) -> JsResult { todo!() } diff --git a/nova_vm/src/ecmascript/builtins/reflection/reflect_object.rs b/nova_vm/src/ecmascript/builtins/reflection/reflect_object.rs index 0b6d09d56..d8b9d839f 100644 --- a/nova_vm/src/ecmascript/builtins/reflection/reflect_object.rs +++ b/nova_vm/src/ecmascript/builtins/reflection/reflect_object.rs @@ -155,7 +155,7 @@ impl ReflectObject { agent: &mut Agent, _this_value: Value, arguments: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { let target = arguments.get(0); let this_argument = arguments.get(1); @@ -188,7 +188,7 @@ impl ReflectObject { agent: &mut Agent, _this_value: Value, arguments: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { let target = arguments.get(0); let arguments_list = arguments.get(1); @@ -236,20 +236,21 @@ impl ReflectObject { agent: &mut Agent, _this_value: Value, arguments: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { let target = arguments.get(0); let property_key = arguments.get(1); let mut attributes = arguments.get(2); // 1. If target is not an Object, throw a TypeError exception. - let Ok(mut target) = Object::try_from(target) else { + let Ok(target) = Object::try_from(target) else { return Err(agent.throw_exception_with_static_message( ExceptionType::TypeError, "Value is not an object", gc.nogc(), )); }; + let mut target = target.bind(gc.nogc()); let mut scoped_target = None; @@ -286,7 +287,12 @@ impl ReflectObject { desc }; // 4. Return ? target.[[DefineOwnProperty]](key, desc). - let ret = target.internal_define_own_property(agent, key.unbind(), desc, gc.reborrow())?; + let ret = target.unbind().internal_define_own_property( + agent, + key.unbind(), + desc, + gc.reborrow(), + )?; Ok(ret.into()) } @@ -296,7 +302,7 @@ impl ReflectObject { agent: &mut Agent, _this_value: Value, arguments: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { let target = arguments.get(0); let property_key = arguments.get(1); @@ -334,7 +340,7 @@ impl ReflectObject { agent: &mut Agent, _this_value: Value, arguments: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { let target = arguments.get(0); let property_key = arguments.get(1); @@ -345,13 +351,14 @@ impl ReflectObject { }; // 1. If target is not an Object, throw a TypeError exception. - let Ok(mut target) = Object::try_from(target) else { + let Ok(target) = Object::try_from(target) else { return Err(agent.throw_exception_with_static_message( ExceptionType::TypeError, "Value is not an object", gc.nogc(), )); }; + let mut target = target.bind(gc.nogc()); // 2. Let key be ? ToPropertyKey(propertyKey). let key = if let TryResult::Continue(key) = @@ -372,7 +379,9 @@ impl ReflectObject { // a. Set receiver to target. let receiver = receiver.unwrap_or(target.into_value()); // 4. Return ? target.[[Get]](key, receiver). - target.internal_get(agent, key.unbind(), receiver, gc.reborrow()) + target + .unbind() + .internal_get(agent, key.unbind(), receiver, gc.reborrow()) } /// [28.1.6 Reflect.getOwnPropertyDescriptor ( target, propertyKey )](https://tc39.es/ecma262/#sec-reflect.getownpropertydescriptor) @@ -380,19 +389,20 @@ impl ReflectObject { agent: &mut Agent, _this_value: Value, arguments: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { let target = arguments.get(0); let property_key = arguments.get(1); // 1. If target is not an Object, throw a TypeError exception. - let Ok(mut target) = Object::try_from(target) else { + let Ok(target) = Object::try_from(target) else { return Err(agent.throw_exception_with_static_message( ExceptionType::TypeError, "Value is not an object", gc.nogc(), )); }; + let mut target = target.bind(gc.nogc()); // 2. Let key be ? ToPropertyKey(propertyKey). let key = if let TryResult::Continue(key) = @@ -408,7 +418,9 @@ impl ReflectObject { key }; // 3. Let desc be ? target.[[GetOwnProperty]](key). - let desc = target.internal_get_own_property(agent, key.unbind(), gc.reborrow())?; + let desc = target + .unbind() + .internal_get_own_property(agent, key.unbind(), gc.reborrow())?; // 4. Return FromPropertyDescriptor(desc). match PropertyDescriptor::from_property_descriptor(desc, agent, gc.nogc()) { Some(ret) => Ok(ret.into_value()), @@ -421,7 +433,7 @@ impl ReflectObject { agent: &mut Agent, _this_value: Value, arguments: ArgumentsList, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { let target = arguments.get(0); @@ -446,19 +458,20 @@ impl ReflectObject { agent: &mut Agent, _this_value: Value, arguments: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { let target = arguments.get(0); let property_key = arguments.get(1); // 1. If target is not an Object, throw a TypeError exception. - let Ok(mut target) = Object::try_from(target) else { + let Ok(target) = Object::try_from(target) else { return Err(agent.throw_exception_with_static_message( ExceptionType::TypeError, "Value is not an object", gc.nogc(), )); }; + let mut target = target.bind(gc.nogc()); // 2. Let key be ? ToPropertyKey(propertyKey). let key = if let TryResult::Continue(key) = @@ -474,7 +487,9 @@ impl ReflectObject { key }; // 3. Return ? target.[[HasProperty]](key). - let ret = target.internal_has_property(agent, key.unbind(), gc.reborrow())?; + let ret = target + .unbind() + .internal_has_property(agent, key.unbind(), gc.reborrow())?; Ok(ret.into()) } @@ -483,7 +498,7 @@ impl ReflectObject { agent: &mut Agent, _this_value: Value, arguments: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { let target = arguments.get(0); @@ -506,7 +521,7 @@ impl ReflectObject { agent: &mut Agent, _this_value: Value, arguments: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { let target = arguments.get(0); @@ -538,7 +553,7 @@ impl ReflectObject { agent: &mut Agent, _this_value: Value, arguments: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { let target = arguments.get(0); @@ -561,7 +576,7 @@ impl ReflectObject { agent: &mut Agent, _this_value: Value, arguments: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { let target = arguments.get(0); let property_key = arguments.get(1); @@ -613,7 +628,7 @@ impl ReflectObject { agent: &mut Agent, _this_value: Value, arguments: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { let target = arguments.get(0); let proto = arguments.get(1); diff --git a/nova_vm/src/ecmascript/builtins/regexp.rs b/nova_vm/src/ecmascript/builtins/regexp.rs index 4aec5301f..6e374cda5 100644 --- a/nova_vm/src/ecmascript/builtins/regexp.rs +++ b/nova_vm/src/ecmascript/builtins/regexp.rs @@ -80,16 +80,16 @@ impl From> for Value { } } -impl From> for Object { +impl<'a> From> for Object<'a> { fn from(value: RegExp) -> Self { Self::RegExp(value.unbind()) } } -impl TryFrom for RegExp<'_> { +impl<'a> TryFrom> for RegExp<'a> { type Error = (); - fn try_from(value: Object) -> Result { + fn try_from(value: Object<'a>) -> Result { match value { Object::RegExp(regexp) => Ok(regexp), _ => Err(()), @@ -114,13 +114,13 @@ impl IntoValue for RegExp<'_> { } } -impl IntoObject for RegExp<'_> { - fn into_object(self) -> Object { +impl<'a> IntoObject<'a> for RegExp<'a> { + fn into_object(self) -> Object<'a> { self.into() } } -impl InternalSlots for RegExp<'_> { +impl<'a> InternalSlots<'a> for RegExp<'a> { const DEFAULT_PROTOTYPE: ProtoIntrinsics = ProtoIntrinsics::RegExp; fn create_backing_object(self, agent: &mut Agent) -> OrdinaryObject<'static> { @@ -160,7 +160,7 @@ impl InternalSlots for RegExp<'_> { } } -impl InternalMethods for RegExp<'_> { +impl<'a> InternalMethods<'a> for RegExp<'a> { fn try_get_own_property( self, agent: &mut Agent, @@ -362,11 +362,11 @@ impl InternalMethods for RegExp<'_> { } } - fn try_own_property_keys<'a>( + fn try_own_property_keys<'gc>( self, agent: &mut Agent, - gc: NoGcScope<'a, '_>, - ) -> TryResult>> { + gc: NoGcScope<'gc, '_>, + ) -> TryResult>> { TryResult::Continue( if let Some(backing_object) = self.get_backing_object(agent) { // Note: If backing object exists, it also contains the diff --git a/nova_vm/src/ecmascript/builtins/regexp/abstract_operations.rs b/nova_vm/src/ecmascript/builtins/regexp/abstract_operations.rs index d9218a109..b94dc5702 100644 --- a/nova_vm/src/ecmascript/builtins/regexp/abstract_operations.rs +++ b/nova_vm/src/ecmascript/builtins/regexp/abstract_operations.rs @@ -84,6 +84,7 @@ pub(crate) fn reg_exp_initialize_from_string<'a>( gc: GcScope<'a, '_>, ) -> JsResult> { let obj = obj.bind(gc.nogc()); + let p = p.bind(gc.nogc()); // 3. If flags is undefined, let F be the empty String. let f = flags.unwrap_or(RegExpFlags::empty()); // 4. Else, let F be ? ToString(flags). @@ -125,7 +126,7 @@ pub(crate) fn reg_exp_initialize_from_string<'a>( let scoped_obj = obj.into_object().scope(agent, gc.nogc()); set( agent, - obj.into_object(), + obj.unbind().into_object(), BUILTIN_STRING_MEMORY.lastIndex.into(), 0.into(), true, diff --git a/nova_vm/src/ecmascript/builtins/set.rs b/nova_vm/src/ecmascript/builtins/set.rs index 162c0d04d..919ea30af 100644 --- a/nova_vm/src/ecmascript/builtins/set.rs +++ b/nova_vm/src/ecmascript/builtins/set.rs @@ -71,8 +71,8 @@ impl IntoValue for Set<'_> { } } -impl IntoObject for Set<'_> { - fn into_object(self) -> Object { +impl<'a> IntoObject<'a> for Set<'a> { + fn into_object(self) -> Object<'a> { self.into() } } @@ -83,7 +83,7 @@ impl From> for Value { } } -impl From> for Object { +impl<'a> From> for Object<'a> { fn from(val: Set) -> Self { Object::Set(val.unbind()) } @@ -101,10 +101,10 @@ impl TryFrom for Set<'_> { } } -impl TryFrom for Set<'_> { +impl<'a> TryFrom> for Set<'a> { type Error = (); - fn try_from(value: Object) -> Result { + fn try_from(value: Object<'a>) -> Result { if let Object::Set(set) = value { Ok(set) } else { @@ -113,7 +113,7 @@ impl TryFrom for Set<'_> { } } -impl InternalSlots for Set<'_> { +impl<'a> InternalSlots<'a> for Set<'a> { const DEFAULT_PROTOTYPE: ProtoIntrinsics = ProtoIntrinsics::Set; #[inline(always)] @@ -129,7 +129,7 @@ impl InternalSlots for Set<'_> { } } -impl InternalMethods for Set<'_> {} +impl<'a> InternalMethods<'a> for Set<'a> {} impl HeapMarkAndSweep for Set<'static> { fn mark_values(&self, queues: &mut WorkQueues) { diff --git a/nova_vm/src/ecmascript/builtins/shared_array_buffer.rs b/nova_vm/src/ecmascript/builtins/shared_array_buffer.rs index 8543cf0ff..3a8ddbcf5 100644 --- a/nova_vm/src/ecmascript/builtins/shared_array_buffer.rs +++ b/nova_vm/src/ecmascript/builtins/shared_array_buffer.rs @@ -70,8 +70,8 @@ impl IntoValue for SharedArrayBuffer<'_> { } } -impl IntoObject for SharedArrayBuffer<'_> { - fn into_object(self) -> Object { +impl<'a> IntoObject<'a> for SharedArrayBuffer<'a> { + fn into_object(self) -> Object<'a> { self.into() } } @@ -82,7 +82,7 @@ impl From> for Value { } } -impl From> for Object { +impl<'a> From> for Object<'a> { fn from(val: SharedArrayBuffer) -> Self { Object::SharedArrayBuffer(val.unbind()) } @@ -122,7 +122,7 @@ impl IndexMut> for Vec> } } -impl InternalSlots for SharedArrayBuffer<'_> { +impl<'a> InternalSlots<'a> for SharedArrayBuffer<'a> { const DEFAULT_PROTOTYPE: ProtoIntrinsics = ProtoIntrinsics::SharedArrayBuffer; #[inline(always)] @@ -138,7 +138,7 @@ impl InternalSlots for SharedArrayBuffer<'_> { } } -impl InternalMethods for SharedArrayBuffer<'_> {} +impl<'a> InternalMethods<'a> for SharedArrayBuffer<'a> {} impl TryFrom for SharedArrayBuffer<'_> { type Error = (); diff --git a/nova_vm/src/ecmascript/builtins/structured_data/array_buffer_objects/array_buffer_constructor.rs b/nova_vm/src/ecmascript/builtins/structured_data/array_buffer_objects/array_buffer_constructor.rs index 7d266b8a3..ff09f9840 100644 --- a/nova_vm/src/ecmascript/builtins/structured_data/array_buffer_objects/array_buffer_constructor.rs +++ b/nova_vm/src/ecmascript/builtins/structured_data/array_buffer_objects/array_buffer_constructor.rs @@ -61,7 +61,7 @@ impl ArrayBufferConstructor { _this_value: Value, arguments: ArgumentsList, new_target: Option, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { // 1. If NewTarget is undefined, throw a TypeError exception. let Some(new_target) = new_target else { @@ -95,7 +95,7 @@ impl ArrayBufferConstructor { _agent: &mut Agent, _this_value: Value, arguments: ArgumentsList, - _gc: GcScope<'_, '_>, + _gc: GcScope, ) -> JsResult { // 1. If arg is not an Object, return false. // 2. If arg has a [[ViewedArrayBuffer]] internal slot, return true. @@ -133,7 +133,7 @@ impl ArrayBufferConstructor { _agent: &mut Agent, this_value: Value, _arguments: ArgumentsList, - _gc: GcScope<'_, '_>, + _gc: GcScope, ) -> JsResult { // 1. Return the this value. // The value of the "name" property of this function is "get [Symbol.species]". @@ -162,7 +162,7 @@ impl ArrayBufferConstructor { fn get_array_buffer_max_byte_length_option( agent: &mut Agent, options: Value, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult> { // 1. If options is not an Object, return empty. let Ok(options) = Object::try_from(options) else { diff --git a/nova_vm/src/ecmascript/builtins/structured_data/array_buffer_objects/array_buffer_prototype.rs b/nova_vm/src/ecmascript/builtins/structured_data/array_buffer_objects/array_buffer_prototype.rs index 4458887e3..f98d8c06e 100644 --- a/nova_vm/src/ecmascript/builtins/structured_data/array_buffer_objects/array_buffer_prototype.rs +++ b/nova_vm/src/ecmascript/builtins/structured_data/array_buffer_objects/array_buffer_prototype.rs @@ -96,7 +96,7 @@ impl ArrayBufferPrototype { agent: &mut Agent, this_value: Value, _: ArgumentsList, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { // 1. Let O be the this value. // 2. Perform ? RequireInternalSlot(O, [[ArrayBufferData]]). @@ -118,7 +118,7 @@ impl ArrayBufferPrototype { agent: &mut Agent, this_value: Value, _: ArgumentsList, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { // 1. Let O be the this value. // 2. Perform ? RequireInternalSlot(O, [[ArrayBufferData]]). @@ -135,7 +135,7 @@ impl ArrayBufferPrototype { agent: &mut Agent, this_value: Value, _: ArgumentsList, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { // 1. Let O be the this value. // 2. Perform ? RequireInternalSlot(O, [[ArrayBufferData]]). @@ -157,7 +157,7 @@ impl ArrayBufferPrototype { agent: &mut Agent, this_value: Value, _: ArgumentsList, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { // 1. Let O be the this value. // 2. Perform ? RequireInternalSlot(O, [[ArrayBufferData]]). @@ -174,7 +174,7 @@ impl ArrayBufferPrototype { agent: &mut Agent, this_value: Value, arguments: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { let new_length = arguments.get(0); // 1. Let O be the this value. @@ -240,7 +240,7 @@ impl ArrayBufferPrototype { agent: &mut Agent, this_value: Value, arguments: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { let start = arguments.get(0); let end = arguments.get(1); @@ -303,7 +303,7 @@ impl ArrayBufferPrototype { None, gc.reborrow(), )? - else { + .unbind() else { unreachable!(); }; let gc = gc.into_nogc(); @@ -366,7 +366,7 @@ impl ArrayBufferPrototype { _agent: &mut Agent, _this_value: Value, _: ArgumentsList, - _gc: GcScope<'_, '_>, + _gc: GcScope, ) -> JsResult { // 1. Let O be the this value. // 2. Return ? ArrayBufferCopyAndDetach(O, newLength, preserve-resizability). @@ -380,7 +380,7 @@ impl ArrayBufferPrototype { _agent: &mut Agent, _this_value: Value, _: ArgumentsList, - _gc: GcScope<'_, '_>, + _gc: GcScope, ) -> JsResult { // 1. Let O be the this value. // 2. Return ? ArrayBufferCopyAndDetach(O, newLength, fixed-length). diff --git a/nova_vm/src/ecmascript/builtins/structured_data/atomics_object.rs b/nova_vm/src/ecmascript/builtins/structured_data/atomics_object.rs index 7bdb16e6d..e50e86675 100644 --- a/nova_vm/src/ecmascript/builtins/structured_data/atomics_object.rs +++ b/nova_vm/src/ecmascript/builtins/structured_data/atomics_object.rs @@ -139,7 +139,7 @@ impl AtomicsObject { _agent: &mut Agent, _this_value: Value, _arguments: ArgumentsList, - _gc: GcScope<'_, '_>, + _gc: GcScope, ) -> JsResult { todo!(); } @@ -148,7 +148,7 @@ impl AtomicsObject { _agent: &mut Agent, _this_value: Value, _arguments: ArgumentsList, - _gc: GcScope<'_, '_>, + _gc: GcScope, ) -> JsResult { todo!(); } @@ -157,7 +157,7 @@ impl AtomicsObject { _agent: &mut Agent, _this_value: Value, _arguments: ArgumentsList, - _gc: GcScope<'_, '_>, + _gc: GcScope, ) -> JsResult { todo!(); } @@ -166,7 +166,7 @@ impl AtomicsObject { _agent: &mut Agent, _this_value: Value, _arguments: ArgumentsList, - _gc: GcScope<'_, '_>, + _gc: GcScope, ) -> JsResult { todo!(); } @@ -175,7 +175,7 @@ impl AtomicsObject { _agent: &mut Agent, _this_value: Value, _arguments: ArgumentsList, - _gc: GcScope<'_, '_>, + _gc: GcScope, ) -> JsResult { todo!(); } @@ -184,7 +184,7 @@ impl AtomicsObject { _agent: &mut Agent, _this_value: Value, _arguments: ArgumentsList, - _gc: GcScope<'_, '_>, + _gc: GcScope, ) -> JsResult { todo!(); } @@ -193,7 +193,7 @@ impl AtomicsObject { _agent: &mut Agent, _this_value: Value, _arguments: ArgumentsList, - _gc: GcScope<'_, '_>, + _gc: GcScope, ) -> JsResult { todo!(); } @@ -202,7 +202,7 @@ impl AtomicsObject { _agent: &mut Agent, _this_value: Value, _arguments: ArgumentsList, - _gc: GcScope<'_, '_>, + _gc: GcScope, ) -> JsResult { todo!(); } @@ -211,7 +211,7 @@ impl AtomicsObject { _agent: &mut Agent, _this_value: Value, _arguments: ArgumentsList, - _gc: GcScope<'_, '_>, + _gc: GcScope, ) -> JsResult { todo!(); } @@ -220,7 +220,7 @@ impl AtomicsObject { _agent: &mut Agent, _this_value: Value, _arguments: ArgumentsList, - _gc: GcScope<'_, '_>, + _gc: GcScope, ) -> JsResult { todo!(); } @@ -229,7 +229,7 @@ impl AtomicsObject { _agent: &mut Agent, _this_value: Value, _arguments: ArgumentsList, - _gc: GcScope<'_, '_>, + _gc: GcScope, ) -> JsResult { todo!(); } @@ -238,7 +238,7 @@ impl AtomicsObject { _agent: &mut Agent, _this_value: Value, _arguments: ArgumentsList, - _gc: GcScope<'_, '_>, + _gc: GcScope, ) -> JsResult { todo!(); } @@ -247,7 +247,7 @@ impl AtomicsObject { _agent: &mut Agent, _this_value: Value, _arguments: ArgumentsList, - _gc: GcScope<'_, '_>, + _gc: GcScope, ) -> JsResult { todo!(); } diff --git a/nova_vm/src/ecmascript/builtins/structured_data/data_view_objects/data_view_constructor.rs b/nova_vm/src/ecmascript/builtins/structured_data/data_view_objects/data_view_constructor.rs index f2d21199b..2816a1961 100644 --- a/nova_vm/src/ecmascript/builtins/structured_data/data_view_objects/data_view_constructor.rs +++ b/nova_vm/src/ecmascript/builtins/structured_data/data_view_objects/data_view_constructor.rs @@ -48,7 +48,7 @@ impl DataViewConstructor { _this_value: Value, arguments: ArgumentsList, new_target: Option, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { // 1. If NewTarget is undefined, throw a TypeError exception. let Some(new_target) = new_target else { @@ -133,9 +133,11 @@ impl DataViewConstructor { new_target, ProtoIntrinsics::DataView, gc.reborrow(), - )?; + )? + .unbind(); let gc = gc.into_nogc(); + let o = o.bind(gc); let buffer = scoped_buffer.get(agent).bind(gc); // 11. If IsDetachedBuffer(buffer) is true, throw a TypeError exception. if is_detached_buffer(agent, buffer) { @@ -187,11 +189,11 @@ impl DataViewConstructor { agent .heap .data_view_byte_lengths - .insert(o, view_byte_length.unwrap()); + .insert(o.unbind(), view_byte_length.unwrap()); } if byte_offset == ViewedArrayBufferByteOffset::heap() { - agent.heap.data_view_byte_offsets.insert(o, offset); + agent.heap.data_view_byte_offsets.insert(o.unbind(), offset); } // 18. Return O. diff --git a/nova_vm/src/ecmascript/builtins/structured_data/data_view_objects/data_view_prototype.rs b/nova_vm/src/ecmascript/builtins/structured_data/data_view_objects/data_view_prototype.rs index d7aaa164b..3f8aaedc6 100644 --- a/nova_vm/src/ecmascript/builtins/structured_data/data_view_objects/data_view_prototype.rs +++ b/nova_vm/src/ecmascript/builtins/structured_data/data_view_objects/data_view_prototype.rs @@ -184,7 +184,7 @@ impl DataViewPrototype { agent: &mut Agent, this_value: Value, _: ArgumentsList, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { // 1. Let O be the this value. // 2. Perform ? RequireInternalSlot(O, [[DataView]]). @@ -204,7 +204,7 @@ impl DataViewPrototype { agent: &mut Agent, this_value: Value, _: ArgumentsList, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { // 1. Let O be the this value. // 2. Perform ? RequireInternalSlot(O, [[DataView]]). @@ -235,7 +235,7 @@ impl DataViewPrototype { agent: &mut Agent, this_value: Value, _: ArgumentsList, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { // 1. Let O be the this value. // 2. Perform ? RequireInternalSlot(O, [[DataView]]). @@ -262,7 +262,7 @@ impl DataViewPrototype { agent: &mut Agent, this_value: Value, arguments: ArgumentsList, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { let byte_offset = arguments.get(0); let little_endian = to_boolean(agent, arguments.get(1)); @@ -277,7 +277,7 @@ impl DataViewPrototype { agent: &mut Agent, this_value: Value, arguments: ArgumentsList, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { let byte_offset = arguments.get(0); let little_endian = to_boolean(agent, arguments.get(1)); @@ -292,7 +292,7 @@ impl DataViewPrototype { agent: &mut Agent, this_value: Value, arguments: ArgumentsList, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { let byte_offset = arguments.get(0); // 2. If littleEndian is not present, set littleEndian to false. @@ -308,7 +308,7 @@ impl DataViewPrototype { agent: &mut Agent, this_value: Value, arguments: ArgumentsList, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { let byte_offset = arguments.get(0); // 2. If littleEndian is not present, set littleEndian to false. @@ -324,7 +324,7 @@ impl DataViewPrototype { agent: &mut Agent, this_value: Value, arguments: ArgumentsList, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { let byte_offset = arguments.get(0); // 1. Let v be the this value. @@ -337,7 +337,7 @@ impl DataViewPrototype { agent: &mut Agent, this_value: Value, arguments: ArgumentsList, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { let byte_offset = arguments.get(0); // 2. If littleEndian is not present, set littleEndian to false. @@ -353,7 +353,7 @@ impl DataViewPrototype { agent: &mut Agent, this_value: Value, arguments: ArgumentsList, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { let byte_offset = arguments.get(0); // 2. If littleEndian is not present, set littleEndian to false. @@ -369,7 +369,7 @@ impl DataViewPrototype { agent: &mut Agent, this_value: Value, arguments: ArgumentsList, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { let byte_offset = arguments.get(0); // 1. Let v be the this value. @@ -382,7 +382,7 @@ impl DataViewPrototype { agent: &mut Agent, this_value: Value, arguments: ArgumentsList, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { let byte_offset = arguments.get(0); // 2. If littleEndian is not present, set littleEndian to false. @@ -398,7 +398,7 @@ impl DataViewPrototype { agent: &mut Agent, this_value: Value, arguments: ArgumentsList, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { let byte_offset = arguments.get(0); // 2. If littleEndian is not present, set littleEndian to false. @@ -414,7 +414,7 @@ impl DataViewPrototype { agent: &mut Agent, this_value: Value, arguments: ArgumentsList, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { let byte_offset = arguments.get(0); let value = arguments.get(1); @@ -429,7 +429,7 @@ impl DataViewPrototype { agent: &mut Agent, this_value: Value, arguments: ArgumentsList, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { let byte_offset = arguments.get(0); let value = arguments.get(1); @@ -444,7 +444,7 @@ impl DataViewPrototype { agent: &mut Agent, this_value: Value, arguments: ArgumentsList, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { let byte_offset = arguments.get(0); let value = arguments.get(1); @@ -460,7 +460,7 @@ impl DataViewPrototype { agent: &mut Agent, this_value: Value, arguments: ArgumentsList, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { let byte_offset = arguments.get(0); let value = arguments.get(1); @@ -476,7 +476,7 @@ impl DataViewPrototype { agent: &mut Agent, this_value: Value, arguments: ArgumentsList, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { let byte_offset = arguments.get(0); let value = arguments.get(1); @@ -490,7 +490,7 @@ impl DataViewPrototype { agent: &mut Agent, this_value: Value, arguments: ArgumentsList, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { let byte_offset = arguments.get(0); let value = arguments.get(1); @@ -506,7 +506,7 @@ impl DataViewPrototype { agent: &mut Agent, this_value: Value, arguments: ArgumentsList, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { let byte_offset = arguments.get(0); let value = arguments.get(1); @@ -522,7 +522,7 @@ impl DataViewPrototype { agent: &mut Agent, this_value: Value, arguments: ArgumentsList, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { let byte_offset = arguments.get(0); let value = arguments.get(1); @@ -536,7 +536,7 @@ impl DataViewPrototype { agent: &mut Agent, this_value: Value, arguments: ArgumentsList, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { let byte_offset = arguments.get(0); let value = arguments.get(1); @@ -552,7 +552,7 @@ impl DataViewPrototype { agent: &mut Agent, this_value: Value, arguments: ArgumentsList, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { let byte_offset = arguments.get(0); let value = arguments.get(1); diff --git a/nova_vm/src/ecmascript/builtins/structured_data/json_object.rs b/nova_vm/src/ecmascript/builtins/structured_data/json_object.rs index 38f61df0b..f34563a0e 100644 --- a/nova_vm/src/ecmascript/builtins/structured_data/json_object.rs +++ b/nova_vm/src/ecmascript/builtins/structured_data/json_object.rs @@ -92,7 +92,7 @@ impl JSONObject { agent: &mut Agent, _this_value: Value, arguments: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { let text = arguments.get(0); let reviver = arguments.get(1); @@ -136,9 +136,12 @@ impl JSONObject { if let Some(reviver) = is_callable(reviver, gc.nogc()) { let reviver = reviver.bind(gc.nogc()); // a. Let root be OrdinaryObjectCreate(%Object.prototype%). - let Object::Object(root) = - ordinary_object_create_with_intrinsics(agent, Some(ProtoIntrinsics::Object), None) - else { + let Object::Object(root) = ordinary_object_create_with_intrinsics( + agent, + Some(ProtoIntrinsics::Object), + None, + gc.nogc(), + ) else { unreachable!() }; @@ -170,7 +173,7 @@ impl JSONObject { _agent: &mut Agent, _this_value: Value, _arguments: ArgumentsList, - _gc: GcScope<'_, '_>, + _gc: GcScope, ) -> JsResult { todo!(); } @@ -213,7 +216,7 @@ impl JSONObject { /// > lexically preceding values for the same key shall be overwritten. fn internalize_json_property<'a>( agent: &mut Agent, - holder: Scoped<'a, Object>, + holder: Scoped<'a, Object<'static>>, name: Scoped<'a, PropertyKey<'static>>, reviver: Scoped<'a, Function<'static>>, mut gc: GcScope<'_, 'a>, @@ -317,11 +320,7 @@ fn internalize_json_property<'a>( ) } -pub(crate) fn value_from_json( - agent: &mut Agent, - json: &sonic_rs::Value, - gc: NoGcScope<'_, '_>, -) -> Value { +pub(crate) fn value_from_json(agent: &mut Agent, json: &sonic_rs::Value, gc: NoGcScope) -> Value { match json.get_type() { sonic_rs::JsonType::Null => Value::Null, sonic_rs::JsonType::Boolean => Value::Boolean(json.is_true()), @@ -342,9 +341,12 @@ pub(crate) fn value_from_json( } sonic_rs::JsonType::Object => { let json_object = json.as_object().unwrap(); - let Object::Object(object) = - ordinary_object_create_with_intrinsics(agent, Some(ProtoIntrinsics::Object), None) - else { + let Object::Object(object) = ordinary_object_create_with_intrinsics( + agent, + Some(ProtoIntrinsics::Object), + None, + gc, + ) else { unreachable!() }; for (key, value) in json_object.iter() { diff --git a/nova_vm/src/ecmascript/builtins/structured_data/shared_array_buffer_objects/shared_array_buffer_constructor.rs b/nova_vm/src/ecmascript/builtins/structured_data/shared_array_buffer_objects/shared_array_buffer_constructor.rs index 574898642..81f37b573 100644 --- a/nova_vm/src/ecmascript/builtins/structured_data/shared_array_buffer_objects/shared_array_buffer_constructor.rs +++ b/nova_vm/src/ecmascript/builtins/structured_data/shared_array_buffer_objects/shared_array_buffer_constructor.rs @@ -44,7 +44,7 @@ impl SharedArrayBufferConstructor { _this_value: Value, _arguments: ArgumentsList, _new_target: Option, - _gc: GcScope<'_, '_>, + _gc: GcScope, ) -> JsResult { todo!() } @@ -53,7 +53,7 @@ impl SharedArrayBufferConstructor { _agent: &mut Agent, _this_value: Value, _arguments: ArgumentsList, - _gc: GcScope<'_, '_>, + _gc: GcScope, ) -> JsResult { todo!() } diff --git a/nova_vm/src/ecmascript/builtins/structured_data/shared_array_buffer_objects/shared_array_buffer_prototype.rs b/nova_vm/src/ecmascript/builtins/structured_data/shared_array_buffer_objects/shared_array_buffer_prototype.rs index f53d1d5be..61a23ab64 100644 --- a/nova_vm/src/ecmascript/builtins/structured_data/shared_array_buffer_objects/shared_array_buffer_prototype.rs +++ b/nova_vm/src/ecmascript/builtins/structured_data/shared_array_buffer_objects/shared_array_buffer_prototype.rs @@ -61,7 +61,7 @@ impl SharedArrayBufferPrototype { _agent: &mut Agent, _this_value: Value, _: ArgumentsList, - _gc: GcScope<'_, '_>, + _gc: GcScope, ) -> JsResult { todo!() } @@ -70,7 +70,7 @@ impl SharedArrayBufferPrototype { _agent: &mut Agent, _this_value: Value, _: ArgumentsList, - _gc: GcScope<'_, '_>, + _gc: GcScope, ) -> JsResult { todo!() } @@ -79,7 +79,7 @@ impl SharedArrayBufferPrototype { _agent: &mut Agent, _this_value: Value, _: ArgumentsList, - _gc: GcScope<'_, '_>, + _gc: GcScope, ) -> JsResult { todo!() } @@ -88,7 +88,7 @@ impl SharedArrayBufferPrototype { _agent: &mut Agent, _this_value: Value, _: ArgumentsList, - _gc: GcScope<'_, '_>, + _gc: GcScope, ) -> JsResult { todo!() } @@ -97,7 +97,7 @@ impl SharedArrayBufferPrototype { _agent: &mut Agent, _this_value: Value, _: ArgumentsList, - _gc: GcScope<'_, '_>, + _gc: GcScope, ) -> JsResult { todo!() } diff --git a/nova_vm/src/ecmascript/builtins/text_processing/regexp_objects/regexp_constructor.rs b/nova_vm/src/ecmascript/builtins/text_processing/regexp_objects/regexp_constructor.rs index 93060e6d3..a8913482d 100644 --- a/nova_vm/src/ecmascript/builtins/text_processing/regexp_objects/regexp_constructor.rs +++ b/nova_vm/src/ecmascript/builtins/text_processing/regexp_objects/regexp_constructor.rs @@ -49,7 +49,7 @@ impl RegExpConstructor { _this_value: Value, _arguments: ArgumentsList, _new_target: Option, - _gc: GcScope<'_, '_>, + _gc: GcScope, ) -> JsResult { todo!(); } @@ -58,7 +58,7 @@ impl RegExpConstructor { _: &mut Agent, this_value: Value, _: ArgumentsList, - _gc: GcScope<'_, '_>, + _gc: GcScope, ) -> JsResult { Ok(this_value) } diff --git a/nova_vm/src/ecmascript/builtins/text_processing/regexp_objects/regexp_prototype.rs b/nova_vm/src/ecmascript/builtins/text_processing/regexp_objects/regexp_prototype.rs index 64ca39aa4..4946435da 100644 --- a/nova_vm/src/ecmascript/builtins/text_processing/regexp_objects/regexp_prototype.rs +++ b/nova_vm/src/ecmascript/builtins/text_processing/regexp_objects/regexp_prototype.rs @@ -166,7 +166,7 @@ impl RegExpPrototype { _agent: &mut Agent, _this_value: Value, _: ArgumentsList, - _gc: GcScope<'_, '_>, + _gc: GcScope, ) -> JsResult { todo!() } @@ -175,7 +175,7 @@ impl RegExpPrototype { _agent: &mut Agent, _this_value: Value, _: ArgumentsList, - _gc: GcScope<'_, '_>, + _gc: GcScope, ) -> JsResult { todo!() } @@ -185,7 +185,7 @@ impl RegExpPrototype { agent: &mut Agent, this_value: Value, _: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { // 1. Let R be the this value. let r = this_value; @@ -332,7 +332,7 @@ impl RegExpPrototype { _agent: &mut Agent, _this_value: Value, _: ArgumentsList, - _gc: GcScope<'_, '_>, + _gc: GcScope, ) -> JsResult { todo!() } @@ -341,7 +341,7 @@ impl RegExpPrototype { _agent: &mut Agent, _this_value: Value, _: ArgumentsList, - _gc: GcScope<'_, '_>, + _gc: GcScope, ) -> JsResult { todo!() } @@ -350,7 +350,7 @@ impl RegExpPrototype { _agent: &mut Agent, _this_value: Value, _: ArgumentsList, - _gc: GcScope<'_, '_>, + _gc: GcScope, ) -> JsResult { todo!() } @@ -359,7 +359,7 @@ impl RegExpPrototype { _agent: &mut Agent, _this_value: Value, _: ArgumentsList, - _gc: GcScope<'_, '_>, + _gc: GcScope, ) -> JsResult { todo!() } @@ -368,7 +368,7 @@ impl RegExpPrototype { _agent: &mut Agent, _this_value: Value, _: ArgumentsList, - _gc: GcScope<'_, '_>, + _gc: GcScope, ) -> JsResult { todo!() } @@ -377,7 +377,7 @@ impl RegExpPrototype { _agent: &mut Agent, _this_value: Value, _: ArgumentsList, - _gc: GcScope<'_, '_>, + _gc: GcScope, ) -> JsResult { todo!() } @@ -386,7 +386,7 @@ impl RegExpPrototype { _agent: &mut Agent, _this_value: Value, _: ArgumentsList, - _gc: GcScope<'_, '_>, + _gc: GcScope, ) -> JsResult { todo!() } @@ -395,7 +395,7 @@ impl RegExpPrototype { _agent: &mut Agent, _this_value: Value, _: ArgumentsList, - _gc: GcScope<'_, '_>, + _gc: GcScope, ) -> JsResult { todo!() } @@ -404,7 +404,7 @@ impl RegExpPrototype { _agent: &mut Agent, _this_value: Value, _: ArgumentsList, - _gc: GcScope<'_, '_>, + _gc: GcScope, ) -> JsResult { todo!() } @@ -413,7 +413,7 @@ impl RegExpPrototype { _agent: &mut Agent, _this_value: Value, _: ArgumentsList, - _gc: GcScope<'_, '_>, + _gc: GcScope, ) -> JsResult { todo!() } @@ -422,7 +422,7 @@ impl RegExpPrototype { _agent: &mut Agent, _this_value: Value, _: ArgumentsList, - _gc: GcScope<'_, '_>, + _gc: GcScope, ) -> JsResult { todo!() } @@ -431,7 +431,7 @@ impl RegExpPrototype { _agent: &mut Agent, _this_value: Value, _: ArgumentsList, - _gc: GcScope<'_, '_>, + _gc: GcScope, ) -> JsResult { todo!() } @@ -447,7 +447,7 @@ impl RegExpPrototype { agent: &mut Agent, this_value: Value, _: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { // 1. Let R be the this value. // 2. If R is not an Object, throw a TypeError exception. @@ -499,7 +499,7 @@ impl RegExpPrototype { _agent: &mut Agent, _this_value: Value, _: ArgumentsList, - _gc: GcScope<'_, '_>, + _gc: GcScope, ) -> JsResult { todo!() } @@ -508,7 +508,7 @@ impl RegExpPrototype { _agent: &mut Agent, _this_value: Value, _: ArgumentsList, - _gc: GcScope<'_, '_>, + _gc: GcScope, ) -> JsResult { todo!() } diff --git a/nova_vm/src/ecmascript/builtins/text_processing/regexp_objects/regexp_string_iterator_prototype.rs b/nova_vm/src/ecmascript/builtins/text_processing/regexp_objects/regexp_string_iterator_prototype.rs index 1bb7e0482..020d0ea93 100644 --- a/nova_vm/src/ecmascript/builtins/text_processing/regexp_objects/regexp_string_iterator_prototype.rs +++ b/nova_vm/src/ecmascript/builtins/text_processing/regexp_objects/regexp_string_iterator_prototype.rs @@ -30,7 +30,7 @@ impl RegExpStringIteratorPrototype { _agent: &mut Agent, _this_value: Value, _arguments: ArgumentsList, - _gc: GcScope<'_, '_>, + _gc: GcScope, ) -> JsResult { todo!(); } diff --git a/nova_vm/src/ecmascript/builtins/text_processing/string_objects/string_constructor.rs b/nova_vm/src/ecmascript/builtins/text_processing/string_objects/string_constructor.rs index 964c0ba8a..c96900ca2 100644 --- a/nova_vm/src/ecmascript/builtins/text_processing/string_objects/string_constructor.rs +++ b/nova_vm/src/ecmascript/builtins/text_processing/string_objects/string_constructor.rs @@ -62,7 +62,7 @@ impl StringConstructor { _this_value: Value, arguments: ArgumentsList, new_target: Option, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { // 1. If value is not present, then let s = if arguments.is_empty() { @@ -93,13 +93,16 @@ impl StringConstructor { Function::try_from(new_target).unwrap(), ProtoIntrinsics::String, gc.reborrow(), - )?; + )? + .map(|p| p.unbind()) + .map(|p| p.bind(gc.nogc())); // StringCreate: Returns a String exotic object. // 1. Let S be MakeBasicObject(ยซ [[Prototype]], [[Extensible]], [[StringData]] ยป). let s = PrimitiveObject::try_from(ordinary_object_create_with_intrinsics( agent, Some(ProtoIntrinsics::String), prototype, + gc.nogc(), )) .unwrap(); @@ -127,7 +130,7 @@ impl StringConstructor { agent: &mut Agent, _this_value: Value, code_units: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { // 1. Let result be the empty String. // 2. For each element next of codeUnits, do @@ -166,7 +169,7 @@ impl StringConstructor { _agent: &mut Agent, _this_value: Value, _arguments: ArgumentsList, - _gc: GcScope<'_, '_>, + _gc: GcScope, ) -> JsResult { // 1. Let result be the empty String. // 2. For each element next of codePoints, do @@ -184,7 +187,7 @@ impl StringConstructor { _agent: &mut Agent, _this_value: Value, _arguments: ArgumentsList, - _gc: GcScope<'_, '_>, + _gc: GcScope, ) -> JsResult { todo!(); } diff --git a/nova_vm/src/ecmascript/builtins/text_processing/string_objects/string_iterator_objects.rs b/nova_vm/src/ecmascript/builtins/text_processing/string_objects/string_iterator_objects.rs index 29a9e4986..504dbaaef 100644 --- a/nova_vm/src/ecmascript/builtins/text_processing/string_objects/string_iterator_objects.rs +++ b/nova_vm/src/ecmascript/builtins/text_processing/string_objects/string_iterator_objects.rs @@ -30,7 +30,7 @@ impl StringIteratorPrototype { _agent: &mut Agent, _this_value: Value, _arguments: ArgumentsList, - _gc: GcScope<'_, '_>, + _gc: GcScope, ) -> JsResult { todo!(); } diff --git a/nova_vm/src/ecmascript/builtins/text_processing/string_objects/string_prototype.rs b/nova_vm/src/ecmascript/builtins/text_processing/string_objects/string_prototype.rs index e965ed95b..20a304a92 100644 --- a/nova_vm/src/ecmascript/builtins/text_processing/string_objects/string_prototype.rs +++ b/nova_vm/src/ecmascript/builtins/text_processing/string_objects/string_prototype.rs @@ -264,7 +264,7 @@ impl StringPrototype { agent: &mut Agent, this_value: Value, args: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { let pos = args.get(0); let (s, relative_index) = @@ -306,7 +306,7 @@ impl StringPrototype { agent: &mut Agent, this_value: Value, args: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { let pos = args.get(0); let (s, position) = if let (Ok(s), Value::Integer(position)) = @@ -340,7 +340,7 @@ impl StringPrototype { agent: &mut Agent, this_value: Value, args: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { let pos = args.get(0); let (s, position) = if let (Ok(s), Value::Integer(position)) = @@ -375,7 +375,7 @@ impl StringPrototype { agent: &mut Agent, this_value: Value, args: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { let pos = args.get(0); let (s, position) = if let (Ok(s), Value::Integer(position)) = @@ -414,7 +414,7 @@ impl StringPrototype { agent: &mut Agent, this_value: Value, args: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { let nogc = gc.nogc(); let (s, args) = if let Ok(s) = String::try_from(this_value) { @@ -473,7 +473,7 @@ impl StringPrototype { agent: &mut Agent, this_value: Value, args: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { let search_string = args.get(0); let end_position = args.get(1); @@ -562,7 +562,7 @@ impl StringPrototype { agent: &mut Agent, this_value: Value, args: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { let search_string = args.get(0); let position = args.get(1); @@ -636,7 +636,7 @@ impl StringPrototype { agent: &mut Agent, this_value: Value, args: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { let search_string = args.get(0); let position = args.get(1); @@ -702,7 +702,7 @@ impl StringPrototype { agent: &mut Agent, this_value: Value, _: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { // 1. Let O be ? RequireObjectCoercible(this value). let o = require_object_coercible(agent, this_value, gc.nogc())?; @@ -730,7 +730,7 @@ impl StringPrototype { agent: &mut Agent, this_value: Value, args: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { let search_string = args.get(0); let position = args.get(1); @@ -823,7 +823,7 @@ impl StringPrototype { _agent: &mut Agent, _this_value: Value, _: ArgumentsList, - _gc: GcScope<'_, '_>, + _gc: GcScope, ) -> JsResult { todo!() } @@ -832,7 +832,7 @@ impl StringPrototype { _agent: &mut Agent, _this_value: Value, _: ArgumentsList, - _gc: GcScope<'_, '_>, + _gc: GcScope, ) -> JsResult { todo!() } @@ -841,7 +841,7 @@ impl StringPrototype { _agent: &mut Agent, _this_value: Value, _: ArgumentsList, - _gc: GcScope<'_, '_>, + _gc: GcScope, ) -> JsResult { todo!() } @@ -851,7 +851,7 @@ impl StringPrototype { agent: &mut Agent, this_value: Value, arguments: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { let form = arguments.get(0); @@ -902,7 +902,7 @@ impl StringPrototype { agent: &mut Agent, this_value: Value, arguments: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { let max_length = arguments.get(0); let fill_string = arguments.get(1); @@ -919,7 +919,7 @@ impl StringPrototype { agent: &mut Agent, this_value: Value, arguments: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { let max_length = arguments.get(0); let fill_string = arguments.get(1); @@ -936,7 +936,7 @@ impl StringPrototype { agent: &mut Agent, this_value: Value, arguments: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { let count = arguments.get(0); @@ -998,7 +998,7 @@ impl StringPrototype { agent: &mut Agent, this_value: Value, args: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { // 1. Let O be ? RequireObjectCoercible(this value). let o = require_object_coercible(agent, this_value, gc.nogc())?; @@ -1102,7 +1102,7 @@ impl StringPrototype { agent: &mut Agent, this_value: Value, args: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { // 1. Let O be ? RequireObjectCoercible(this value). let o = require_object_coercible(agent, this_value, gc.nogc())?; @@ -1240,7 +1240,7 @@ impl StringPrototype { _agent: &mut Agent, _this_value: Value, _: ArgumentsList, - _gc: GcScope<'_, '_>, + _gc: GcScope, ) -> JsResult { todo!() } @@ -1249,7 +1249,7 @@ impl StringPrototype { agent: &mut Agent, this_value: Value, args: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { // 1. Let O be ? RequireObjectCoercible(this value). let o = require_object_coercible(agent, this_value, gc.nogc())?; @@ -1335,7 +1335,7 @@ impl StringPrototype { agent: &mut Agent, this_value: Value, args: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { // 1. Let O be ? RequireObjectCoercible(this value). let o = require_object_coercible(agent, this_value, gc.nogc())?; @@ -1445,7 +1445,7 @@ impl StringPrototype { agent: &mut Agent, this_value: Value, args: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { // 1. Let O be ? RequireObjectCoercible(this value). let o = require_object_coercible(agent, this_value, gc.nogc())?; @@ -1509,7 +1509,7 @@ impl StringPrototype { agent: &mut Agent, this_value: Value, args: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { let nogc = gc.nogc(); let start = args.get(0).bind(nogc); @@ -1585,7 +1585,7 @@ impl StringPrototype { agent: &mut Agent, this_value: Value, _: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { // 1. Let O be ? RequireObjectCoercible(this value). let o: Value = require_object_coercible(agent, this_value, gc.nogc())?; @@ -1604,7 +1604,7 @@ impl StringPrototype { agent: &mut Agent, this_value: Value, _: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { // 1. Let O be ? RequireObjectCoercible(this value). let o = require_object_coercible(agent, this_value, gc.nogc())?; @@ -1624,7 +1624,7 @@ impl StringPrototype { agent: &mut Agent, this_value: Value, _: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { // 1. Let O be ? RequireObjectCoercible(this value). let o = require_object_coercible(agent, this_value, gc.nogc())?; @@ -1644,7 +1644,7 @@ impl StringPrototype { agent: &mut Agent, this_value: Value, _: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { // 1. Let O be ? RequireObjectCoercible(this value). let o = require_object_coercible(agent, this_value, gc.nogc())?; @@ -1663,7 +1663,7 @@ impl StringPrototype { agent: &mut Agent, this_value: Value, _: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { // 1. Let O be ? RequireObjectCoercible(this value). let o = require_object_coercible(agent, this_value, gc.nogc())?; @@ -1693,7 +1693,7 @@ impl StringPrototype { agent: &mut Agent, this_value: Value, _: ArgumentsList, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { // 1. Let S be the this value. // 2. Return ? TrimString(S, start+end). @@ -1705,7 +1705,7 @@ impl StringPrototype { agent: &mut Agent, value: Value, trim_where: TrimWhere, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { // 1. Let str be ? RequireObjectCoercible(string). let str = require_object_coercible(agent, value, gc.nogc())?; @@ -1744,7 +1744,7 @@ impl StringPrototype { agent: &mut Agent, this_value: Value, _: ArgumentsList, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { // 1. Let S be the this value. // 2. Return ? TrimString(S, end). @@ -1756,7 +1756,7 @@ impl StringPrototype { agent: &mut Agent, this_value: Value, _: ArgumentsList, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { // 1. Let S be the this value. // 2. Return ? TrimString(S, start). @@ -1772,7 +1772,7 @@ impl StringPrototype { agent: &mut Agent, this_value: Value, _: ArgumentsList, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { // 1. Return ? ThisStringValue(this value). this_string_value(agent, this_value, gc.nogc()).map(|string| string.into_value()) @@ -1782,7 +1782,7 @@ impl StringPrototype { _agent: &mut Agent, _this_value: Value, _: ArgumentsList, - _gc: GcScope<'_, '_>, + _gc: GcScope, ) -> JsResult { todo!() } @@ -1861,7 +1861,7 @@ fn string_padding_builtins_impl( max_length: Value, fill_string: Value, placement_start: bool, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { // 1. Let S be ? ToString(O). let mut s = to_string(agent, o, gc.reborrow())?.unbind().bind(gc.nogc()); diff --git a/nova_vm/src/ecmascript/builtins/typed_array.rs b/nova_vm/src/ecmascript/builtins/typed_array.rs index 1e8ca78f5..68093f3b3 100644 --- a/nova_vm/src/ecmascript/builtins/typed_array.rs +++ b/nova_vm/src/ecmascript/builtins/typed_array.rs @@ -188,8 +188,8 @@ impl IntoValue for TypedArray<'_> { } } -impl IntoObject for TypedArray<'_> { - fn into_object(self) -> Object { +impl<'a> IntoObject<'a> for TypedArray<'a> { + fn into_object(self) -> Object<'a> { self.into() } } @@ -212,7 +212,7 @@ impl From> for Value { } } -impl From> for Object { +impl<'a> From> for Object<'a> { fn from(val: TypedArray) -> Self { match val.unbind() { TypedArray::Int8Array(idx) => Object::Int8Array(idx), @@ -285,7 +285,7 @@ impl IndexMut> for Vec> { } } -impl InternalSlots for TypedArray<'_> { +impl<'a> InternalSlots<'a> for TypedArray<'a> { #[inline(always)] fn get_backing_object(self, agent: &Agent) -> Option> { agent[self].object_index @@ -298,7 +298,7 @@ impl InternalSlots for TypedArray<'_> { .is_none()); } - fn internal_prototype(self, agent: &Agent) -> Option { + fn internal_prototype(self, agent: &Agent) -> Option> { if let Some(object_index) = agent[self].object_index { object_index.internal_prototype(agent) } else { @@ -321,7 +321,7 @@ impl InternalSlots for TypedArray<'_> { } } -impl InternalMethods for TypedArray<'_> {} +impl<'a> InternalMethods<'a> for TypedArray<'a> {} impl TryFrom for TypedArray<'_> { type Error = (); diff --git a/nova_vm/src/ecmascript/builtins/weak_map.rs b/nova_vm/src/ecmascript/builtins/weak_map.rs index b909924fa..c91571216 100644 --- a/nova_vm/src/ecmascript/builtins/weak_map.rs +++ b/nova_vm/src/ecmascript/builtins/weak_map.rs @@ -71,8 +71,8 @@ impl IntoValue for WeakMap<'_> { } } -impl IntoObject for WeakMap<'_> { - fn into_object(self) -> Object { +impl<'a> IntoObject<'a> for WeakMap<'a> { + fn into_object(self) -> Object<'a> { self.into() } } @@ -83,13 +83,13 @@ impl From> for Value { } } -impl From> for Object { +impl<'a> From> for Object<'a> { fn from(val: WeakMap) -> Self { Object::WeakMap(val.unbind()) } } -impl InternalSlots for WeakMap<'_> { +impl<'a> InternalSlots<'a> for WeakMap<'a> { const DEFAULT_PROTOTYPE: ProtoIntrinsics = ProtoIntrinsics::WeakMap; #[inline(always)] @@ -105,7 +105,7 @@ impl InternalSlots for WeakMap<'_> { } } -impl InternalMethods for WeakMap<'_> {} +impl<'a> InternalMethods<'a> for WeakMap<'a> {} impl Index> for Agent { type Output = WeakMapHeapData; diff --git a/nova_vm/src/ecmascript/builtins/weak_ref.rs b/nova_vm/src/ecmascript/builtins/weak_ref.rs index e3f57ca5b..338dc74d6 100644 --- a/nova_vm/src/ecmascript/builtins/weak_ref.rs +++ b/nova_vm/src/ecmascript/builtins/weak_ref.rs @@ -70,8 +70,8 @@ impl IntoValue for WeakRef<'_> { } } -impl IntoObject for WeakRef<'_> { - fn into_object(self) -> Object { +impl<'a> IntoObject<'a> for WeakRef<'a> { + fn into_object(self) -> Object<'a> { self.into() } } @@ -82,13 +82,13 @@ impl From> for Value { } } -impl From> for Object { +impl<'a> From> for Object<'a> { fn from(val: WeakRef) -> Self { Object::WeakRef(val.unbind()) } } -impl InternalSlots for WeakRef<'_> { +impl<'a> InternalSlots<'a> for WeakRef<'a> { const DEFAULT_PROTOTYPE: ProtoIntrinsics = ProtoIntrinsics::WeakRef; #[inline(always)] @@ -104,7 +104,7 @@ impl InternalSlots for WeakRef<'_> { } } -impl InternalMethods for WeakRef<'_> {} +impl<'a> InternalMethods<'a> for WeakRef<'a> {} impl Index> for Agent { type Output = WeakRefHeapData; diff --git a/nova_vm/src/ecmascript/builtins/weak_set.rs b/nova_vm/src/ecmascript/builtins/weak_set.rs index 1fd64e39c..4afc2a4d2 100644 --- a/nova_vm/src/ecmascript/builtins/weak_set.rs +++ b/nova_vm/src/ecmascript/builtins/weak_set.rs @@ -71,8 +71,8 @@ impl IntoValue for WeakSet<'_> { } } -impl IntoObject for WeakSet<'_> { - fn into_object(self) -> Object { +impl<'a> IntoObject<'a> for WeakSet<'a> { + fn into_object(self) -> Object<'a> { self.into() } } @@ -83,13 +83,13 @@ impl From> for Value { } } -impl From> for Object { +impl<'a> From> for Object<'a> { fn from(val: WeakSet) -> Self { Object::WeakSet(val.unbind()) } } -impl InternalSlots for WeakSet<'_> { +impl<'a> InternalSlots<'a> for WeakSet<'a> { const DEFAULT_PROTOTYPE: ProtoIntrinsics = ProtoIntrinsics::WeakSet; #[inline(always)] @@ -105,7 +105,7 @@ impl InternalSlots for WeakSet<'_> { } } -impl InternalMethods for WeakSet<'_> {} +impl<'a> InternalMethods<'a> for WeakSet<'a> {} impl HeapMarkAndSweep for WeakSetHeapData { fn mark_values(&self, queues: &mut WorkQueues) { diff --git a/nova_vm/src/ecmascript/execution/agent.rs b/nova_vm/src/ecmascript/execution/agent.rs index 791f10e5a..bd46fc7d1 100644 --- a/nova_vm/src/ecmascript/execution/agent.rs +++ b/nova_vm/src/ecmascript/execution/agent.rs @@ -65,7 +65,7 @@ impl Job { self.realm } - pub fn run(&self, agent: &mut Agent, gc: GcScope<'_, '_>) -> JsResult<()> { + pub fn run(&self, agent: &mut Agent, gc: GcScope) -> JsResult<()> { let mut pushed_context = false; if let Some(realm) = self.realm { if agent.current_realm_id() != realm { @@ -184,8 +184,12 @@ impl GcAgent { /// [`GcAgent::remove_realm`] is called. pub fn create_realm( &mut self, - create_global_object: Option Object>, - create_global_this_value: Option Object>, + create_global_object: Option< + impl for<'a> FnOnce(&mut Agent, GcScope<'a, '_>) -> Object<'a>, + >, + create_global_this_value: Option< + impl for<'a> FnOnce(&mut Agent, GcScope<'a, '_>) -> Object<'a>, + >, initialize_global_object: Option, ) -> RealmRoot { let realm = self.agent.create_realm( @@ -294,8 +298,12 @@ impl Agent { /// This is intended for usage within BuiltinFunction calls. pub fn create_realm( &mut self, - create_global_object: Option Object>, - create_global_this_value: Option Object>, + create_global_object: Option< + impl for<'a> FnOnce(&mut Agent, GcScope<'a, '_>) -> Object<'a>, + >, + create_global_this_value: Option< + impl for<'a> FnOnce(&mut Agent, GcScope<'a, '_>) -> Object<'a>, + >, initialize_global_object: Option, ) -> RealmIdentifier { let (mut gc, mut scope) = unsafe { GcScope::create_root() }; diff --git a/nova_vm/src/ecmascript/execution/environments.rs b/nova_vm/src/ecmascript/execution/environments.rs index a5c01e7a4..d5b87e938 100644 --- a/nova_vm/src/ecmascript/execution/environments.rs +++ b/nova_vm/src/ecmascript/execution/environments.rs @@ -223,7 +223,7 @@ impl EnvironmentIndex { self, agent: &mut Agent, name: String, - gc: NoGcScope<'_, '_>, + gc: NoGcScope, ) -> TryResult { match self { EnvironmentIndex::Declarative(idx) => TryResult::Continue(idx.has_binding(agent, name)), @@ -241,7 +241,7 @@ impl EnvironmentIndex { self, agent: &mut Agent, name: String, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { match self { EnvironmentIndex::Declarative(idx) => Ok(idx.has_binding(agent, name)), @@ -261,7 +261,7 @@ impl EnvironmentIndex { agent: &mut Agent, name: String, is_deletable: bool, - gc: NoGcScope<'_, '_>, + gc: NoGcScope, ) -> TryResult> { match self { EnvironmentIndex::Declarative(idx) => { @@ -291,7 +291,7 @@ impl EnvironmentIndex { agent: &mut Agent, name: String, is_deletable: bool, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult<()> { match self { EnvironmentIndex::Declarative(idx) => { @@ -355,7 +355,7 @@ impl EnvironmentIndex { agent: &mut Agent, name: String, value: Value, - gc: NoGcScope<'_, '_>, + gc: NoGcScope, ) -> TryResult> { match self { EnvironmentIndex::Declarative(idx) => { @@ -382,7 +382,7 @@ impl EnvironmentIndex { agent: &mut Agent, name: String, value: Value, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult<()> { match self { EnvironmentIndex::Declarative(idx) => { @@ -411,7 +411,7 @@ impl EnvironmentIndex { name: String, value: Value, is_strict: bool, - gc: NoGcScope<'_, '_>, + gc: NoGcScope, ) -> TryResult> { match self { EnvironmentIndex::Declarative(idx) => { @@ -442,7 +442,7 @@ impl EnvironmentIndex { name: String, value: Value, is_strict: bool, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult<()> { match self { EnvironmentIndex::Declarative(idx) => { @@ -474,7 +474,7 @@ impl EnvironmentIndex { agent: &mut Agent, name: String, is_strict: bool, - gc: NoGcScope<'_, '_>, + gc: NoGcScope, ) -> TryResult> { match self { EnvironmentIndex::Declarative(idx) => { @@ -502,7 +502,7 @@ impl EnvironmentIndex { agent: &mut Agent, name: String, is_strict: bool, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { match self { EnvironmentIndex::Declarative(idx) => { @@ -526,7 +526,7 @@ impl EnvironmentIndex { self, agent: &mut Agent, name: String, - gc: NoGcScope<'_, '_>, + gc: NoGcScope, ) -> TryResult> { match self { EnvironmentIndex::Declarative(idx) => { @@ -552,7 +552,7 @@ impl EnvironmentIndex { self, agent: &mut Agent, name: String, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { match self { EnvironmentIndex::Declarative(idx) => Ok(idx.delete_binding(agent, name)), diff --git a/nova_vm/src/ecmascript/execution/environments/declarative_environment.rs b/nova_vm/src/ecmascript/execution/environments/declarative_environment.rs index b25e71d55..6a5521f6c 100644 --- a/nova_vm/src/ecmascript/execution/environments/declarative_environment.rs +++ b/nova_vm/src/ecmascript/execution/environments/declarative_environment.rs @@ -382,7 +382,7 @@ impl DeclarativeEnvironmentIndex { /// /// The WithBaseObject concrete method of a Declarative Environment Record /// envRec takes no arguments and returns undefined. - pub(crate) fn with_base_object(self) -> Option { + pub(crate) fn with_base_object(self) -> Option> { // 1. Return undefined. None } diff --git a/nova_vm/src/ecmascript/execution/environments/function_environment.rs b/nova_vm/src/ecmascript/execution/environments/function_environment.rs index b974b0027..39525608b 100644 --- a/nova_vm/src/ecmascript/execution/environments/function_environment.rs +++ b/nova_vm/src/ecmascript/execution/environments/function_environment.rs @@ -60,7 +60,7 @@ pub(crate) struct FunctionEnvironment { /// internal method, \[\[NewTarget\]\] is the value of the /// \[\[Construct\]\] newTarget parameter. Otherwise, its value is /// undefined. - pub(crate) new_target: Option, + pub(crate) new_target: Option>, /// Function Environment Records support all of the Declarative Environment /// Record methods listed in Table 16 and share the same specifications for @@ -135,7 +135,7 @@ pub(crate) fn new_function_environment( this_binding_status, // 5. Set env.[[NewTarget]] to newTarget. - new_target, + new_target: new_target.map(|f| f.unbind()), // 6. Set env.[[OuterEnv]] to F.[[Environment]]. declarative_environment, @@ -362,7 +362,7 @@ impl FunctionEnvironmentIndex { } /// ### [9.1.1.1.10 WithBaseObject ( )](https://tc39.es/ecma262/#sec-declarative-environment-records-withbaseobject) - pub(crate) fn with_base_object(self) -> Option { + pub(crate) fn with_base_object(self) -> Option> { // 1. Return undefined. None } @@ -445,11 +445,11 @@ impl FunctionEnvironmentIndex { /// The GetSuperBase concrete method of a Function Environment Record /// envRec takes no arguments and returns either a normal completion /// containing either an Object, null, or undefined. - pub(crate) fn get_super_base( + pub(crate) fn get_super_base<'a>( self, agent: &mut Agent, - gc: NoGcScope<'_, '_>, - ) -> Option> { + gc: NoGcScope<'a, '_>, + ) -> Option>> { let env_rec: &FunctionEnvironment = &agent[self]; // 1. Let home be envRec.[[FunctionObject]].[[HomeObject]]. diff --git a/nova_vm/src/ecmascript/execution/environments/global_environment.rs b/nova_vm/src/ecmascript/execution/environments/global_environment.rs index 711622208..c91d25aca 100644 --- a/nova_vm/src/ecmascript/execution/environments/global_environment.rs +++ b/nova_vm/src/ecmascript/execution/environments/global_environment.rs @@ -51,7 +51,7 @@ pub struct GlobalEnvironment { /// /// The value returned by this in global scope. Hosts may provide any /// ECMAScript Object value. - pub(crate) global_this_value: Object, + pub(crate) global_this_value: Object<'static>, /// ### \[\[DeclarativeRecord\]\] /// @@ -95,7 +95,7 @@ impl GlobalEnvironment { object_record, // 5. Set env.[[GlobalThisValue]] to thisValue. - global_this_value: this_value, + global_this_value: this_value.unbind(), // 6. Set env.[[DeclarativeRecord]] to dclRec. declarative_record, @@ -157,7 +157,7 @@ impl GlobalEnvironmentIndex { self, agent: &mut Agent, name: String, - gc: NoGcScope<'_, '_>, + gc: NoGcScope, ) -> TryResult { let env_rec = &agent[self]; // 1. Let DclRec be envRec.[[DeclarativeRecord]]. @@ -182,7 +182,7 @@ impl GlobalEnvironmentIndex { self, agent: &mut Agent, name: String, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { let env_rec = &agent[self]; // 1. Let DclRec be envRec.[[DeclarativeRecord]]. @@ -272,7 +272,7 @@ impl GlobalEnvironmentIndex { agent: &mut Agent, name: String, value: Value, - gc: NoGcScope<'_, '_>, + gc: NoGcScope, ) -> TryResult> { let env_rec = &agent[self]; // 1. Let DclRec be envRec.[[DeclarativeRecord]]. @@ -304,7 +304,7 @@ impl GlobalEnvironmentIndex { agent: &mut Agent, name: String, value: Value, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult<()> { let env_rec = &agent[self]; // 1. Let DclRec be envRec.[[DeclarativeRecord]]. @@ -339,7 +339,7 @@ impl GlobalEnvironmentIndex { name: String, value: Value, is_strict: bool, - gc: NoGcScope<'_, '_>, + gc: NoGcScope, ) -> TryResult> { let env_rec = &agent[self]; // 1. Let DclRec be envRec.[[DeclarativeRecord]]. @@ -372,7 +372,7 @@ impl GlobalEnvironmentIndex { name: String, value: Value, is_strict: bool, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult<()> { let env_rec = &agent[self]; // 1. Let DclRec be envRec.[[DeclarativeRecord]]. @@ -404,7 +404,7 @@ impl GlobalEnvironmentIndex { agent: &mut Agent, n: String, s: bool, - gc: NoGcScope<'_, '_>, + gc: NoGcScope, ) -> TryResult> { let env_rec = &agent[self]; // 1. Let DclRec be envRec.[[DeclarativeRecord]]. @@ -436,7 +436,7 @@ impl GlobalEnvironmentIndex { agent: &mut Agent, n: String, s: bool, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { let env_rec = &agent[self]; // 1. Let DclRec be envRec.[[DeclarativeRecord]]. @@ -463,7 +463,7 @@ impl GlobalEnvironmentIndex { self, agent: &mut Agent, name: String, - gc: NoGcScope<'_, '_>, + gc: NoGcScope, ) -> TryResult> { let env_rec = &agent[self]; // 1. Let DclRec be envRec.[[DeclarativeRecord]]. @@ -510,7 +510,7 @@ impl GlobalEnvironmentIndex { self, agent: &mut Agent, name: String, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { let env_rec = &agent[self]; // 1. Let DclRec be envRec.[[DeclarativeRecord]]. @@ -573,7 +573,7 @@ impl GlobalEnvironmentIndex { /// /// The WithBaseObject concrete method of a Global Environment Record /// envRec takes no arguments and returns undefined. - pub(crate) fn with_base_object(self) -> Option { + pub(crate) fn with_base_object(self) -> Option> { // 1. Return undefined. None } @@ -583,10 +583,10 @@ impl GlobalEnvironmentIndex { /// The GetThisBinding concrete method of a Global Environment Record /// envRec takes no arguments and returns a normal completion containing an /// Object. - pub(crate) fn get_this_binding(self, agent: &Agent) -> Object { + pub(crate) fn get_this_binding<'a>(self, agent: &Agent, gc: NoGcScope<'a, '_>) -> Object<'a> { let env_rec = &agent[self]; // 1. Return envRec.[[GlobalThisValue]]. - env_rec.global_this_value + env_rec.global_this_value.bind(gc) } /// ### [9.1.1.4.12 HasVarDeclaration ( N )](https://tc39.es/ecma262/#sec-hasvardeclaration) @@ -631,7 +631,7 @@ impl GlobalEnvironmentIndex { self, agent: &mut Agent, name: String, - gc: NoGcScope<'_, '_>, + gc: NoGcScope, ) -> TryResult { let env_rec = &agent[self]; // 1. Let ObjRec be envRec.[[ObjectRecord]]. @@ -661,7 +661,7 @@ impl GlobalEnvironmentIndex { self, agent: &mut Agent, name: String, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { let env_rec = &agent[self]; // 1. Let ObjRec be envRec.[[ObjectRecord]]. @@ -692,7 +692,7 @@ impl GlobalEnvironmentIndex { self, agent: &mut Agent, name: String, - gc: NoGcScope<'_, '_>, + gc: NoGcScope, ) -> TryResult { let env_rec = &agent[self]; // 1. Let ObjRec be envRec.[[ObjectRecord]]. @@ -723,7 +723,7 @@ impl GlobalEnvironmentIndex { self, agent: &mut Agent, name: String, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { let env_rec = &agent[self]; // 1. Let ObjRec be envRec.[[ObjectRecord]]. @@ -753,7 +753,7 @@ impl GlobalEnvironmentIndex { self, agent: &mut Agent, name: String, - gc: NoGcScope<'_, '_>, + gc: NoGcScope, ) -> TryResult { let env_rec = &agent[self]; // 1. Let ObjRec be envRec.[[ObjectRecord]]. @@ -792,7 +792,7 @@ impl GlobalEnvironmentIndex { self, agent: &mut Agent, name: String, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { let env_rec = &agent[self]; // 1. Let ObjRec be envRec.[[ObjectRecord]]. @@ -834,7 +834,7 @@ impl GlobalEnvironmentIndex { agent: &mut Agent, name: String, is_deletable: bool, - gc: NoGcScope<'_, '_>, + gc: NoGcScope, ) -> TryResult> { let env_rec = &agent[self]; // 1. Let ObjRec be envRec.[[ObjectRecord]]. @@ -881,7 +881,7 @@ impl GlobalEnvironmentIndex { agent: &mut Agent, name: String, is_deletable: bool, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult<()> { let env_rec = &agent[self]; // 1. Let ObjRec be envRec.[[ObjectRecord]]. @@ -925,7 +925,7 @@ impl GlobalEnvironmentIndex { name: String, value: Value, d: bool, - gc: NoGcScope<'_, '_>, + gc: NoGcScope, ) -> TryResult> { let env_rec = &agent[self]; // 1. Let ObjRec be envRec.[[ObjectRecord]]. @@ -996,7 +996,7 @@ impl GlobalEnvironmentIndex { name: String, value: Value, d: bool, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult<()> { let env_rec = &agent[self]; // 1. Let ObjRec be envRec.[[ObjectRecord]]. diff --git a/nova_vm/src/ecmascript/execution/environments/object_environment.rs b/nova_vm/src/ecmascript/execution/environments/object_environment.rs index a38485daf..f709f79c8 100644 --- a/nova_vm/src/ecmascript/execution/environments/object_environment.rs +++ b/nova_vm/src/ecmascript/execution/environments/object_environment.rs @@ -40,7 +40,7 @@ pub struct ObjectEnvironment { /// ### \[\[BindingObject\]\] /// /// The binding object of this Environment Record. - pub(crate) binding_object: Object, + pub(crate) binding_object: Object<'static>, /// ### \[\[IsWithEnvironment\]\] /// @@ -68,7 +68,7 @@ impl ObjectEnvironment { // 1. Let env be a new Object Environment Record. ObjectEnvironment { // 2. Set env.[[BindingObject]] to O. - binding_object, + binding_object: binding_object.unbind(), // 3. Set env.[[IsWithEnvironment]] to W. is_with_environment, // 4. Set env.[[OuterEnv]] to E. @@ -111,7 +111,7 @@ impl ObjectEnvironmentIndex { self, agent: &mut Agent, n: String, - gc: NoGcScope<'_, '_>, + gc: NoGcScope, ) -> TryResult { let env_rec = &agent[self]; // 1. Let bindingObject be envRec.[[BindingObject]]. @@ -158,7 +158,7 @@ impl ObjectEnvironmentIndex { self, agent: &mut Agent, n: String, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { let env_rec = &agent[self]; // 1. Let bindingObject be envRec.[[BindingObject]]. @@ -209,7 +209,7 @@ impl ObjectEnvironmentIndex { agent: &mut Agent, n: String, d: bool, - gc: NoGcScope<'_, '_>, + gc: NoGcScope, ) -> TryResult> { let env_rec = &agent[self]; // 1. Let bindingObject be envRec.[[BindingObject]]. @@ -252,7 +252,7 @@ impl ObjectEnvironmentIndex { agent: &mut Agent, n: String, d: bool, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult<()> { let env_rec = &agent[self]; // 1. Let bindingObject be envRec.[[BindingObject]]. @@ -299,7 +299,7 @@ impl ObjectEnvironmentIndex { agent: &mut Agent, n: String, v: Value, - gc: NoGcScope<'_, '_>, + gc: NoGcScope, ) -> TryResult> { // 1. Perform ? envRec.SetMutableBinding(N, V, false). // 2. Return UNUSED. @@ -324,7 +324,7 @@ impl ObjectEnvironmentIndex { agent: &mut Agent, n: String, v: Value, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult<()> { // 1. Perform ? envRec.SetMutableBinding(N, V, false). self.set_mutable_binding(agent, n, v, false, gc)?; @@ -354,7 +354,7 @@ impl ObjectEnvironmentIndex { n: String, v: Value, s: bool, - gc: NoGcScope<'_, '_>, + gc: NoGcScope, ) -> TryResult> { let env_rec = &agent[self]; // 1. Let bindingObject be envRec.[[BindingObject]]. @@ -396,7 +396,7 @@ impl ObjectEnvironmentIndex { n: String, v: Value, s: bool, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult<()> { let env_rec = &agent[self]; // 1. Let bindingObject be envRec.[[BindingObject]]. @@ -436,7 +436,7 @@ impl ObjectEnvironmentIndex { agent: &mut Agent, n: String, s: bool, - gc: NoGcScope<'_, '_>, + gc: NoGcScope, ) -> TryResult> { let env_rec = &agent[self]; // 1. Let bindingObject be envRec.[[BindingObject]]. @@ -479,7 +479,7 @@ impl ObjectEnvironmentIndex { agent: &mut Agent, n: String, s: bool, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { let env_rec = &agent[self]; // 1. Let bindingObject be envRec.[[BindingObject]]. @@ -520,7 +520,7 @@ impl ObjectEnvironmentIndex { self, agent: &mut Agent, name: String, - gc: NoGcScope<'_, '_>, + gc: NoGcScope, ) -> TryResult { let env_rec = &agent[self]; // 1. Let bindingObject be envRec.[[BindingObject]]. @@ -541,7 +541,7 @@ impl ObjectEnvironmentIndex { self, agent: &mut Agent, name: String, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { let env_rec = &agent[self]; // 1. Let bindingObject be envRec.[[BindingObject]]. diff --git a/nova_vm/src/ecmascript/execution/execution_context.rs b/nova_vm/src/ecmascript/execution/execution_context.rs index b4f92293a..3c6afd276 100644 --- a/nova_vm/src/ecmascript/execution/execution_context.rs +++ b/nova_vm/src/ecmascript/execution/execution_context.rs @@ -8,6 +8,7 @@ use crate::{ scripts_and_modules::{source_code::SourceCode, ScriptOrModule}, types::*, }, + engine::context::NoGcScope, heap::{CompactionLists, HeapMarkAndSweep, WorkQueues}, }; @@ -159,9 +160,9 @@ impl HeapMarkAndSweep for ExecutionContext { /// The abstract operation GetGlobalObject takes no arguments and returns an /// Object. It returns the global object used by the currently running /// execution context. -pub(crate) fn get_global_object(agent: &Agent) -> Object { +pub(crate) fn get_global_object<'a>(agent: &Agent, gc: NoGcScope<'a, '_>) -> Object<'a> { // 1. Let currentRealm be the current Realm Record. let current_realm = agent.current_realm(); // 2. Return currentRealm.[[GlobalObject]]. - current_realm.global_object + current_realm.global_object.bind(gc) } diff --git a/nova_vm/src/ecmascript/execution/realm.rs b/nova_vm/src/ecmascript/execution/realm.rs index d1fd4f735..17872a754 100644 --- a/nova_vm/src/ecmascript/execution/realm.rs +++ b/nova_vm/src/ecmascript/execution/realm.rs @@ -131,7 +131,7 @@ pub struct Realm { /// ### \[\[GlobalObject]] /// /// The global object for this realm. - pub(crate) global_object: Object, + pub(crate) global_object: Object<'static>, /// ### \[\[GlobalEnv]] /// @@ -297,7 +297,7 @@ pub(crate) fn set_realm_global_object( let this_value = this_value.unwrap_or(global_object); // 4. Set realmRec.[[GlobalObject]] to globalObj. - agent[realm_id].global_object = global_object; + agent[realm_id].global_object = global_object.unbind(); // 5. Let newGlobalEnv be NewGlobalEnvironment(globalObj, thisValue). let new_global_env = GlobalEnvironment::new(agent, global_object, this_value); @@ -318,11 +318,11 @@ pub(crate) fn set_realm_global_object( /// The abstract operation SetDefaultGlobalBindings takes argument realmRec (a /// Realm Record) and returns either a normal completion containing an Object /// or a throw completion. -pub(crate) fn set_default_global_bindings( +pub(crate) fn set_default_global_bindings<'a>( agent: &mut Agent, realm_id: RealmIdentifier, - mut gc: GcScope<'_, '_>, -) -> JsResult { + mut gc: GcScope<'a, '_>, +) -> JsResult> { // 1. Let global be realmRec.[[GlobalObject]]. let global = agent[realm_id].global_object; @@ -340,7 +340,12 @@ pub(crate) fn set_default_global_bindings( let global_env = agent[realm_id].global_env; let desc = PropertyDescriptor { - value: Some(global_env.unwrap().get_this_binding(agent).into_value()), + value: Some( + global_env + .unwrap() + .get_this_binding(agent, gc.nogc()) + .into_value(), + ), ..Default::default() }; @@ -1067,10 +1072,12 @@ pub(crate) fn set_default_global_bindings( /// ### [9.6 InitializeHostDefinedRealm ( )](https://tc39.es/ecma262/#sec-initializehostdefinedrealm) pub(crate) fn initialize_host_defined_realm( agent: &mut Agent, - create_global_object: Option) -> Object>, - create_global_this_value: Option) -> Object>, - initialize_global_object: Option)>, - mut gc: GcScope<'_, '_>, + create_global_object: Option FnOnce(&mut Agent, GcScope<'a, '_>) -> Object<'a>>, + create_global_this_value: Option< + impl for<'a> FnOnce(&mut Agent, GcScope<'a, '_>) -> Object<'a>, + >, + initialize_global_object: Option, + mut gc: GcScope, ) { // 1. Let realm be CreateRealm(). let realm = create_realm(agent, gc.nogc()); @@ -1098,7 +1105,9 @@ pub(crate) fn initialize_host_defined_realm( // let global be such an object created in a host-defined manner. // Otherwise, let global be undefined, indicating that an ordinary object should be created as the global object. let global = create_global_this_value - .map(|create_global_this_value| create_global_this_value(agent, gc.reborrow())); + .map(|create_global_this_value| create_global_this_value(agent, gc.reborrow())) + .map(|g| g.unbind()) + .map(|g| g.scope(agent, gc.nogc())); // 8. If the host requires that the this binding in realm's global scope return an object other than the global object, // let thisValue be such an object created in a host-defined manner. @@ -1107,23 +1116,27 @@ pub(crate) fn initialize_host_defined_realm( create_global_object.map(|create_global_object| create_global_object(agent, gc.reborrow())); // 9. Perform SetRealmGlobalObject(realm, global, thisValue). - set_realm_global_object(agent, realm, global, this_value); + set_realm_global_object(agent, realm, global.map(|g| g.get(agent)), this_value); // 10. Let globalObj be ? SetDefaultGlobalBindings(realm). - let global_object = set_default_global_bindings(agent, realm, gc.reborrow()).unwrap(); + let global_object = set_default_global_bindings(agent, realm, gc.reborrow()) + .unwrap() + .unbind() + .bind(gc.nogc()); // 11. Create any host-defined global object properties on globalObj. if let Some(initialize_global_object) = initialize_global_object { - initialize_global_object(agent, global_object, gc.reborrow()); + initialize_global_object(agent, global_object.unbind(), gc.reborrow()); }; // 12. Return UNUSED. } -pub(crate) fn initialize_default_realm(agent: &mut Agent, gc: GcScope<'_, '_>) { - let create_global_object: Option) -> Object> = None; - let create_global_this_value: Option) -> Object> = None; - let initialize_global_object: Option)> = None; +pub(crate) fn initialize_default_realm(agent: &mut Agent, gc: GcScope) { + let create_global_object: Option fn(&mut Agent, GcScope<'a, '_>) -> Object<'a>> = None; + let create_global_this_value: Option fn(&mut Agent, GcScope<'a, '_>) -> Object<'a>> = + None; + let initialize_global_object: Option = None; initialize_host_defined_realm( agent, create_global_object, diff --git a/nova_vm/src/ecmascript/execution/realm/intrinsics.rs b/nova_vm/src/ecmascript/execution/realm/intrinsics.rs index 1aa3ae73c..3d48b7c72 100644 --- a/nova_vm/src/ecmascript/execution/realm/intrinsics.rs +++ b/nova_vm/src/ecmascript/execution/realm/intrinsics.rs @@ -368,7 +368,7 @@ impl Intrinsics { pub(crate) fn get_intrinsic_default_proto( &self, intrinsic_default_proto: ProtoIntrinsics, - ) -> Object { + ) -> Object<'static> { match intrinsic_default_proto { ProtoIntrinsics::Array => self.array_prototype().into(), #[cfg(feature = "array-buffer")] diff --git a/nova_vm/src/ecmascript/scripts_and_modules/script.rs b/nova_vm/src/ecmascript/scripts_and_modules/script.rs index 999785522..fdd7fba73 100644 --- a/nova_vm/src/ecmascript/scripts_and_modules/script.rs +++ b/nova_vm/src/ecmascript/scripts_and_modules/script.rs @@ -248,11 +248,7 @@ pub fn parse_script( /// The abstract operation ScriptEvaluation takes argument scriptRecord (a /// Script Record) and returns either a normal completion containing an /// ECMAScript language value or an abrupt completion. -pub fn script_evaluation( - agent: &mut Agent, - script: Script, - mut gc: GcScope<'_, '_>, -) -> JsResult { +pub fn script_evaluation(agent: &mut Agent, script: Script, mut gc: GcScope) -> JsResult { let realm_id = script.realm; let is_strict_mode = script.ecmascript_code.is_strict(); let source_code = script.source_code; @@ -342,7 +338,7 @@ pub(crate) fn global_declaration_instantiation( agent: &mut Agent, script: ScriptIdentifier, env: GlobalEnvironmentIndex, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult<()> { // 11. Let script be scriptRecord.[[ECMAScriptCode]]. // SAFETY: Analysing the script cannot cause the environment to move even though we change other parts of the Heap. @@ -356,8 +352,7 @@ pub(crate) fn global_declaration_instantiation( // long as the Script is alive in the heap as they are not reallocated. // Thus in effect VarScopedDeclaration<'_> is valid for the duration // of the global_declaration_instantiation call. - let script = - unsafe { std::mem::transmute::<&Program<'_>, &'static Program<'static>>(script) }; + let script = unsafe { std::mem::transmute::<&Program, &'static Program<'static>>(script) }; // 1. Let lexNames be the LexicallyDeclaredNames of script. let lex_names = script_lexically_declared_names(script); // 2. Let varNames be the VarDeclaredNames of script. @@ -1060,7 +1055,7 @@ mod test { const LENGTH: u8 = 1; const BEHAVIOUR: Behaviour = Behaviour::Regular( - |_: &mut Agent, _: Value, arguments_list: ArgumentsList, _: GcScope<'_, '_>| { + |_: &mut Agent, _: Value, arguments_list: ArgumentsList, _: GcScope| { let arg_0 = arguments_list.get(0); if Value::Boolean(true) == arg_0 { Ok(Value::from(3)) diff --git a/nova_vm/src/ecmascript/scripts_and_modules/source_code.rs b/nova_vm/src/ecmascript/scripts_and_modules/source_code.rs index 6528ce850..181604f9f 100644 --- a/nova_vm/src/ecmascript/scripts_and_modules/source_code.rs +++ b/nova_vm/src/ecmascript/scripts_and_modules/source_code.rs @@ -116,7 +116,7 @@ impl SourceCode { } // SAFETY: Caller guarantees that they will drop the Program before // SourceCode can be garbage collected. - let program = unsafe { std::mem::transmute::, Program<'static>>(program) }; + let program = unsafe { std::mem::transmute::>(program) }; let source_code = agent.heap.create(SourceCodeHeapData { source: source.unbind(), allocator, diff --git a/nova_vm/src/ecmascript/syntax_directed_operations/class_definitions.rs b/nova_vm/src/ecmascript/syntax_directed_operations/class_definitions.rs index 3943844d5..1a4aeab0a 100644 --- a/nova_vm/src/ecmascript/syntax_directed_operations/class_definitions.rs +++ b/nova_vm/src/ecmascript/syntax_directed_operations/class_definitions.rs @@ -17,11 +17,12 @@ use crate::{ engine::{context::GcScope, unwrap_try}, }; -pub(crate) fn base_class_default_constructor( +pub(crate) fn base_class_default_constructor<'a>( agent: &mut Agent, new_target: Object, - mut gc: GcScope<'_, '_>, -) -> JsResult { + mut gc: GcScope<'a, '_>, +) -> JsResult> { + let new_target = new_target.bind(gc.nogc()); // ii. If NewTarget is undefined, throw a TypeError exception. // Note: We've already checked this at an earlier level. @@ -36,23 +37,27 @@ pub(crate) fn base_class_default_constructor( // 2. Let result be ? OrdinaryCreateFromConstructor(NewTarget, "%Object.prototype%"). let result = ordinary_create_from_constructor( agent, - Function::try_from(new_target).unwrap(), + Function::try_from(new_target.unbind()).unwrap(), ProtoIntrinsics::Object, gc.reborrow(), - )?; + )? + .unbind() + .bind(gc.nogc()); + let scoped_result = result.scope(agent, gc.nogc()); // vi. Perform ? InitializeInstanceElements(result, F). - initialize_instance_elements(agent, result, f.get(agent), gc)?; + initialize_instance_elements(agent, result.unbind(), f.get(agent), gc.reborrow())?; // vii. Return result. - Ok(result) + Ok(scoped_result.get(agent).bind(gc.into_nogc())) } -pub(crate) fn derived_class_default_constructor( +pub(crate) fn derived_class_default_constructor<'a>( agent: &mut Agent, args: ArgumentsList, new_target: Object, - mut gc: GcScope<'_, '_>, -) -> JsResult { + mut gc: GcScope<'a, '_>, +) -> JsResult> { + let new_target = new_target.bind(gc.nogc()); // i. Let args be the List of arguments that was passed to this function by [[Call]] or [[Construct]]. // ii. If NewTarget is undefined, throw a TypeError exception. // Note: We've already checked this at an earlier level. @@ -80,14 +85,17 @@ pub(crate) fn derived_class_default_constructor( // 4. Let result be ? Construct(func, args, NewTarget). let result = construct( agent, - func, + func.unbind(), Some(args), - Some(Function::try_from(new_target).unwrap()), + Some(Function::try_from(new_target.unbind()).unwrap()), gc.reborrow(), - )?; + )? + .unbind() + .bind(gc.nogc()); + let scoped_result = result.scope(agent, gc.nogc()); // vi. Perform ? InitializeInstanceElements(result, F). - initialize_instance_elements(agent, result, f.get(agent), gc)?; + initialize_instance_elements(agent, result.unbind(), f.get(agent), gc.reborrow())?; // vii. Return result. - Ok(result) + Ok(scoped_result.get(agent).bind(gc.into_nogc())) } diff --git a/nova_vm/src/ecmascript/syntax_directed_operations/function_definitions.rs b/nova_vm/src/ecmascript/syntax_directed_operations/function_definitions.rs index c0f53a4fa..f46e74cbb 100644 --- a/nova_vm/src/ecmascript/syntax_directed_operations/function_definitions.rs +++ b/nova_vm/src/ecmascript/syntax_directed_operations/function_definitions.rs @@ -134,7 +134,7 @@ pub(crate) fn instantiate_ordinary_function_object<'a>( set_function_name(agent, f, pk_name, None, gc); // 5. Perform MakeConstructor(F). if !function.r#async && !function.generator { - make_constructor(agent, f, None, None); + make_constructor(agent, f, None, None, gc); } if function.generator { @@ -162,6 +162,7 @@ pub(crate) fn instantiate_ordinary_function_object<'a>( .generator_prototype() .into_object() }), + gc, ); // 6. Perform ! DefinePropertyOrThrow(F, "prototype", PropertyDescriptor { unwrap_try(try_define_property_or_throw( @@ -240,7 +241,7 @@ pub(crate) fn instantiate_ordinary_function_expression<'a>( set_function_name(agent, closure, name, None, gc); // 7. Perform MakeConstructor(closure). if !function.expression.get().r#async && !function.expression.get().generator { - make_constructor(agent, closure, None, None); + make_constructor(agent, closure, None, None, gc); } // 8. Return closure. closure @@ -284,7 +285,7 @@ pub(crate) fn evaluate_function_body( agent: &mut Agent, function_object: ECMAScriptFunction, arguments_list: ArgumentsList, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { let function_object = function_object.bind(gc.nogc()); // 1. Perform ? FunctionDeclarationInstantiation(functionObject, argumentsList). @@ -381,7 +382,7 @@ pub(crate) fn evaluate_generator_body( agent: &mut Agent, function_object: ECMAScriptFunction, arguments_list: ArgumentsList, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { let function_object = function_object.bind(gc.nogc()); // 1. Perform ? FunctionDeclarationInstantiation(functionObject, argumentsList). @@ -401,7 +402,10 @@ pub(crate) fn evaluate_generator_body( function_object.into_function().unbind(), ProtoIntrinsics::Generator, gc.reborrow(), - )?; + )? + .unbind(); + let gc = gc.into_nogc(); + let generator = generator.bind(gc); let Object::Generator(generator) = generator else { unreachable!() }; @@ -409,7 +413,7 @@ pub(crate) fn evaluate_generator_body( // 4. Perform GeneratorStart(G, FunctionBody). // SAFETY: We're alive so SourceCode must be too. let data = CompileFunctionBodyData::new(agent, scoped_function_object.get(agent)); - let executable = Executable::compile_function_body(agent, data, gc.nogc()); + let executable = Executable::compile_function_body(agent, data, gc); agent[generator].generator_state = Some(GeneratorState::Suspended { vm_or_args: VmOrArguments::Arguments(arguments_list.0.into()), executable, diff --git a/nova_vm/src/ecmascript/types/language/function.rs b/nova_vm/src/ecmascript/types/language/function.rs index b764d81a9..dc1653b4a 100644 --- a/nova_vm/src/ecmascript/types/language/function.rs +++ b/nova_vm/src/ecmascript/types/language/function.rs @@ -75,8 +75,8 @@ impl IntoValue for Function<'_> { } } -impl IntoObject for Function<'_> { - fn into_object(self) -> Object { +impl<'a> IntoObject<'a> for Function<'a> { + fn into_object(self) -> Object<'a> { self.into() } } @@ -94,9 +94,9 @@ impl<'a> From> for Function<'a> { } } -impl TryFrom for Function<'_> { +impl<'a> TryFrom> for Function<'a> { type Error = (); - fn try_from(value: Object) -> Result { + fn try_from(value: Object<'a>) -> Result { match value { Object::BoundFunction(d) => Ok(Function::BoundFunction(d)), Object::BuiltinFunction(d) => Ok(Function::BuiltinFunction(d)), @@ -138,8 +138,8 @@ impl TryFrom for Function<'_> { } } -impl From> for Object { - fn from(value: Function) -> Self { +impl<'a> From> for Object<'a> { + fn from(value: Function<'a>) -> Self { match value { Function::BoundFunction(d) => Object::from(d), Function::BuiltinFunction(d) => Object::from(d), @@ -219,7 +219,7 @@ impl<'a> Function<'a> { } } -impl InternalSlots for Function<'_> { +impl<'a> InternalSlots<'a> for Function<'a> { const DEFAULT_PROTOTYPE: ProtoIntrinsics = ProtoIntrinsics::Function; fn create_backing_object(self, _: &mut Agent) -> OrdinaryObject<'static> { @@ -271,12 +271,12 @@ impl InternalSlots for Function<'_> { } } -impl InternalMethods for Function<'_> { - fn try_get_prototype_of( +impl<'a> InternalMethods<'a> for Function<'a> { + fn try_get_prototype_of<'gc>( self, agent: &mut Agent, - gc: NoGcScope<'_, '_>, - ) -> TryResult> { + gc: NoGcScope<'gc, '_>, + ) -> TryResult>> { match self { Function::BoundFunction(x) => x.try_get_prototype_of(agent, gc), Function::BuiltinFunction(x) => x.try_get_prototype_of(agent, gc), @@ -293,7 +293,7 @@ impl InternalMethods for Function<'_> { self, agent: &mut Agent, prototype: Option, - gc: NoGcScope<'_, '_>, + gc: NoGcScope, ) -> TryResult { match self { Function::BoundFunction(x) => x.try_set_prototype_of(agent, prototype, gc), @@ -309,7 +309,7 @@ impl InternalMethods for Function<'_> { } } - fn try_is_extensible(self, agent: &mut Agent, gc: NoGcScope<'_, '_>) -> TryResult { + fn try_is_extensible(self, agent: &mut Agent, gc: NoGcScope) -> TryResult { match self { Function::BoundFunction(x) => x.try_is_extensible(agent, gc), Function::BuiltinFunction(x) => x.try_is_extensible(agent, gc), @@ -322,7 +322,7 @@ impl InternalMethods for Function<'_> { } } - fn try_prevent_extensions(self, agent: &mut Agent, gc: NoGcScope<'_, '_>) -> TryResult { + fn try_prevent_extensions(self, agent: &mut Agent, gc: NoGcScope) -> TryResult { match self { Function::BoundFunction(x) => x.try_prevent_extensions(agent, gc), Function::BuiltinFunction(x) => x.try_prevent_extensions(agent, gc), @@ -339,7 +339,7 @@ impl InternalMethods for Function<'_> { self, agent: &mut Agent, property_key: PropertyKey, - gc: NoGcScope<'_, '_>, + gc: NoGcScope, ) -> TryResult> { match self { Function::BoundFunction(x) => x.try_get_own_property(agent, property_key, gc), @@ -362,7 +362,7 @@ impl InternalMethods for Function<'_> { agent: &mut Agent, property_key: PropertyKey, property_descriptor: PropertyDescriptor, - gc: NoGcScope<'_, '_>, + gc: NoGcScope, ) -> TryResult { match self { Function::BoundFunction(x) => { @@ -390,7 +390,7 @@ impl InternalMethods for Function<'_> { self, agent: &mut Agent, property_key: PropertyKey, - gc: NoGcScope<'_, '_>, + gc: NoGcScope, ) -> TryResult { match self { Function::BoundFunction(x) => x.try_has_property(agent, property_key, gc), @@ -410,7 +410,7 @@ impl InternalMethods for Function<'_> { self, agent: &mut Agent, property_key: PropertyKey, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { match self { Function::BoundFunction(x) => x.internal_has_property(agent, property_key, gc), @@ -433,7 +433,7 @@ impl InternalMethods for Function<'_> { agent: &mut Agent, property_key: PropertyKey, receiver: Value, - gc: NoGcScope<'_, '_>, + gc: NoGcScope, ) -> TryResult { match self { Function::BoundFunction(x) => x.try_get(agent, property_key, receiver, gc), @@ -454,7 +454,7 @@ impl InternalMethods for Function<'_> { agent: &mut Agent, property_key: PropertyKey, receiver: Value, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { match self { Function::BoundFunction(x) => x.internal_get(agent, property_key, receiver, gc), @@ -478,7 +478,7 @@ impl InternalMethods for Function<'_> { property_key: PropertyKey, value: Value, receiver: Value, - gc: NoGcScope<'_, '_>, + gc: NoGcScope, ) -> TryResult { match self { Function::BoundFunction(x) => x.try_set(agent, property_key, value, receiver, gc), @@ -502,7 +502,7 @@ impl InternalMethods for Function<'_> { property_key: PropertyKey, value: Value, receiver: Value, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { match self { Function::BoundFunction(x) => x.internal_set(agent, property_key, value, receiver, gc), @@ -528,7 +528,7 @@ impl InternalMethods for Function<'_> { self, agent: &mut Agent, property_key: PropertyKey, - gc: NoGcScope<'_, '_>, + gc: NoGcScope, ) -> TryResult { match self { Function::BoundFunction(x) => x.try_delete(agent, property_key, gc), @@ -542,11 +542,11 @@ impl InternalMethods for Function<'_> { } } - fn try_own_property_keys<'a>( + fn try_own_property_keys<'gc>( self, agent: &mut Agent, - gc: NoGcScope<'a, '_>, - ) -> TryResult>> { + gc: NoGcScope<'gc, '_>, + ) -> TryResult>> { match self { Function::BoundFunction(x) => x.try_own_property_keys(agent, gc), Function::BuiltinFunction(x) => x.try_own_property_keys(agent, gc), @@ -564,7 +564,7 @@ impl InternalMethods for Function<'_> { agent: &mut Agent, this_argument: Value, arguments_list: ArgumentsList, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { match self { Function::BoundFunction(x) => x.internal_call(agent, this_argument, arguments_list, gc), @@ -586,13 +586,13 @@ impl InternalMethods for Function<'_> { } } - fn internal_construct( + fn internal_construct<'gc>( self, agent: &mut Agent, arguments_list: ArgumentsList, new_target: Function, - gc: GcScope<'_, '_>, - ) -> JsResult { + gc: GcScope<'gc, '_>, + ) -> JsResult> { match self { Function::BoundFunction(x) => { x.internal_construct(agent, arguments_list, new_target, gc) @@ -650,7 +650,7 @@ impl Function<'_> { agent: &mut Agent, this_argument: Value, args: &[Value], - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { self.internal_call(agent, this_argument, ArgumentsList(args), gc) } diff --git a/nova_vm/src/ecmascript/types/language/function/into_function.rs b/nova_vm/src/ecmascript/types/language/function/into_function.rs index eb9c063f4..2c596ad30 100644 --- a/nova_vm/src/ecmascript/types/language/function/into_function.rs +++ b/nova_vm/src/ecmascript/types/language/function/into_function.rs @@ -23,7 +23,7 @@ use crate::{ pub trait IntoFunction<'a> where - Self: Sized + Copy + IntoObject, + Self: 'a + Sized + Copy + IntoObject<'a>, { fn into_function(self) -> Function<'a>; } @@ -32,7 +32,7 @@ where /// These are used when the function hasn't had a backing object created. pub(crate) trait FunctionInternalProperties<'a> where - Self: IntoObject + IntoFunction<'a> + InternalSlots + InternalMethods, + Self: IntoObject<'a> + IntoFunction<'a> + InternalSlots<'a> + InternalMethods<'a>, { /// Value of the 'name' property. fn get_name(self, agent: &Agent) -> String<'static>; @@ -112,7 +112,7 @@ pub(crate) fn function_internal_define_own_property<'a>( agent: &mut Agent, property_key: PropertyKey, property_descriptor: PropertyDescriptor, - gc: NoGcScope<'_, '_>, + gc: NoGcScope, ) -> bool { let backing_object = func .get_backing_object(agent) @@ -124,7 +124,7 @@ pub(crate) fn function_try_has_property<'a>( func: impl FunctionInternalProperties<'a>, agent: &mut Agent, property_key: PropertyKey, - gc: NoGcScope<'_, '_>, + gc: NoGcScope, ) -> TryResult { if let Some(backing_object) = func.get_backing_object(agent) { backing_object.try_has_property(agent, property_key, gc) @@ -144,7 +144,7 @@ pub(crate) fn function_internal_has_property<'a>( func: impl FunctionInternalProperties<'a>, agent: &mut Agent, property_key: PropertyKey, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { let property_key = property_key.bind(gc.nogc()); if let Some(backing_object) = func.get_backing_object(agent) { @@ -156,7 +156,9 @@ pub(crate) fn function_internal_has_property<'a>( } else { let parent = unwrap_try(func.try_get_prototype_of(agent, gc.nogc())); if let Some(parent) = parent { - parent.internal_has_property(agent, property_key.unbind(), gc) + parent + .unbind() + .internal_has_property(agent, property_key.unbind(), gc) } else { Ok(false) } @@ -168,7 +170,7 @@ pub(crate) fn function_try_get<'a>( agent: &mut Agent, property_key: PropertyKey, receiver: Value, - gc: NoGcScope<'_, '_>, + gc: NoGcScope, ) -> TryResult { if let Some(backing_object) = func.get_backing_object(agent) { backing_object.try_get(agent, property_key, receiver, gc) @@ -189,7 +191,7 @@ pub(crate) fn function_internal_get<'a>( agent: &mut Agent, property_key: PropertyKey, receiver: Value, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { let property_key = property_key.bind(gc.nogc()); if let Some(backing_object) = func.get_backing_object(agent) { @@ -202,7 +204,9 @@ pub(crate) fn function_internal_get<'a>( // Note: Getting a function's prototype never calls JavaScript. let parent = unwrap_try(func.try_get_prototype_of(agent, gc.nogc())); if let Some(parent) = parent { - parent.internal_get(agent, property_key.unbind(), receiver, gc) + parent + .unbind() + .internal_get(agent, property_key.unbind(), receiver, gc) } else { Ok(Value::Undefined) } @@ -215,7 +219,7 @@ pub(crate) fn function_try_set<'a>( property_key: PropertyKey, value: Value, receiver: Value, - gc: NoGcScope<'_, '_>, + gc: NoGcScope, ) -> TryResult { if let Some(backing_object) = func.get_backing_object(agent) { backing_object.try_set(agent, property_key, value, receiver, gc) @@ -235,7 +239,7 @@ pub(crate) fn function_internal_set<'a>( property_key: PropertyKey, value: Value, receiver: Value, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { let property_key = property_key.bind(gc.nogc()); if let Some(backing_object) = func.get_backing_object(agent) { @@ -261,7 +265,7 @@ pub(crate) fn function_internal_delete<'a>( func: impl FunctionInternalProperties<'a>, agent: &mut Agent, property_key: PropertyKey, - gc: NoGcScope<'_, '_>, + gc: NoGcScope, ) -> bool { if let Some(backing_object) = func.get_backing_object(agent) { unwrap_try(backing_object.try_delete(agent, property_key, gc)) diff --git a/nova_vm/src/ecmascript/types/language/object.rs b/nova_vm/src/ecmascript/types/language/object.rs index deddf5e95..797833f23 100644 --- a/nova_vm/src/ecmascript/types/language/object.rs +++ b/nova_vm/src/ecmascript/types/language/object.rs @@ -108,162 +108,164 @@ pub use property_storage::PropertyStorage; /// In Nova #[derive(Debug, Clone, Copy, PartialEq, Eq)] #[repr(u8)] -pub enum Object { - Object(OrdinaryObject<'static>) = OBJECT_DISCRIMINANT, - BoundFunction(BoundFunction<'static>) = BOUND_FUNCTION_DISCRIMINANT, - BuiltinFunction(BuiltinFunction<'static>) = BUILTIN_FUNCTION_DISCRIMINANT, - ECMAScriptFunction(ECMAScriptFunction<'static>) = ECMASCRIPT_FUNCTION_DISCRIMINANT, +pub enum Object<'a> { + Object(OrdinaryObject<'a>) = OBJECT_DISCRIMINANT, + BoundFunction(BoundFunction<'a>) = BOUND_FUNCTION_DISCRIMINANT, + BuiltinFunction(BuiltinFunction<'a>) = BUILTIN_FUNCTION_DISCRIMINANT, + ECMAScriptFunction(ECMAScriptFunction<'a>) = ECMASCRIPT_FUNCTION_DISCRIMINANT, BuiltinGeneratorFunction = BUILTIN_GENERATOR_FUNCTION_DISCRIMINANT, - BuiltinConstructorFunction(BuiltinConstructorFunction<'static>) = + BuiltinConstructorFunction(BuiltinConstructorFunction<'a>) = BUILTIN_CONSTRUCTOR_FUNCTION_DISCRIMINANT, - BuiltinPromiseResolvingFunction(BuiltinPromiseResolvingFunction<'static>) = + BuiltinPromiseResolvingFunction(BuiltinPromiseResolvingFunction<'a>) = BUILTIN_PROMISE_RESOLVING_FUNCTION_DISCRIMINANT, BuiltinPromiseCollectorFunction = BUILTIN_PROMISE_COLLECTOR_FUNCTION_DISCRIMINANT, BuiltinProxyRevokerFunction = BUILTIN_PROXY_REVOKER_FUNCTION, - PrimitiveObject(PrimitiveObject<'static>) = PRIMITIVE_OBJECT_DISCRIMINANT, - Arguments(OrdinaryObject<'static>) = ARGUMENTS_DISCRIMINANT, - Array(Array<'static>) = ARRAY_DISCRIMINANT, + PrimitiveObject(PrimitiveObject<'a>) = PRIMITIVE_OBJECT_DISCRIMINANT, + Arguments(OrdinaryObject<'a>) = ARGUMENTS_DISCRIMINANT, + Array(Array<'a>) = ARRAY_DISCRIMINANT, #[cfg(feature = "array-buffer")] - ArrayBuffer(ArrayBuffer<'static>) = ARRAY_BUFFER_DISCRIMINANT, + ArrayBuffer(ArrayBuffer<'a>) = ARRAY_BUFFER_DISCRIMINANT, #[cfg(feature = "array-buffer")] - DataView(DataView<'static>) = DATA_VIEW_DISCRIMINANT, + DataView(DataView<'a>) = DATA_VIEW_DISCRIMINANT, #[cfg(feature = "date")] - Date(Date<'static>) = DATE_DISCRIMINANT, - Error(Error<'static>) = ERROR_DISCRIMINANT, - FinalizationRegistry(FinalizationRegistry<'static>) = FINALIZATION_REGISTRY_DISCRIMINANT, - Map(Map<'static>) = MAP_DISCRIMINANT, - Promise(Promise<'static>) = PROMISE_DISCRIMINANT, - Proxy(Proxy<'static>) = PROXY_DISCRIMINANT, + Date(Date<'a>) = DATE_DISCRIMINANT, + Error(Error<'a>) = ERROR_DISCRIMINANT, + FinalizationRegistry(FinalizationRegistry<'a>) = FINALIZATION_REGISTRY_DISCRIMINANT, + Map(Map<'a>) = MAP_DISCRIMINANT, + Promise(Promise<'a>) = PROMISE_DISCRIMINANT, + Proxy(Proxy<'a>) = PROXY_DISCRIMINANT, #[cfg(feature = "regexp")] - RegExp(RegExp<'static>) = REGEXP_DISCRIMINANT, - Set(Set<'static>) = SET_DISCRIMINANT, + RegExp(RegExp<'a>) = REGEXP_DISCRIMINANT, + Set(Set<'a>) = SET_DISCRIMINANT, #[cfg(feature = "shared-array-buffer")] - SharedArrayBuffer(SharedArrayBuffer<'static>) = SHARED_ARRAY_BUFFER_DISCRIMINANT, + SharedArrayBuffer(SharedArrayBuffer<'a>) = SHARED_ARRAY_BUFFER_DISCRIMINANT, #[cfg(feature = "weak-refs")] - WeakMap(WeakMap<'static>) = WEAK_MAP_DISCRIMINANT, + WeakMap(WeakMap<'a>) = WEAK_MAP_DISCRIMINANT, #[cfg(feature = "weak-refs")] - WeakRef(WeakRef<'static>) = WEAK_REF_DISCRIMINANT, + WeakRef(WeakRef<'a>) = WEAK_REF_DISCRIMINANT, #[cfg(feature = "weak-refs")] - WeakSet(WeakSet<'static>) = WEAK_SET_DISCRIMINANT, + WeakSet(WeakSet<'a>) = WEAK_SET_DISCRIMINANT, #[cfg(feature = "array-buffer")] - Int8Array(TypedArrayIndex<'static>) = INT_8_ARRAY_DISCRIMINANT, + Int8Array(TypedArrayIndex<'a>) = INT_8_ARRAY_DISCRIMINANT, #[cfg(feature = "array-buffer")] - Uint8Array(TypedArrayIndex<'static>) = UINT_8_ARRAY_DISCRIMINANT, + Uint8Array(TypedArrayIndex<'a>) = UINT_8_ARRAY_DISCRIMINANT, #[cfg(feature = "array-buffer")] - Uint8ClampedArray(TypedArrayIndex<'static>) = UINT_8_CLAMPED_ARRAY_DISCRIMINANT, + Uint8ClampedArray(TypedArrayIndex<'a>) = UINT_8_CLAMPED_ARRAY_DISCRIMINANT, #[cfg(feature = "array-buffer")] - Int16Array(TypedArrayIndex<'static>) = INT_16_ARRAY_DISCRIMINANT, + Int16Array(TypedArrayIndex<'a>) = INT_16_ARRAY_DISCRIMINANT, #[cfg(feature = "array-buffer")] - Uint16Array(TypedArrayIndex<'static>) = UINT_16_ARRAY_DISCRIMINANT, + Uint16Array(TypedArrayIndex<'a>) = UINT_16_ARRAY_DISCRIMINANT, #[cfg(feature = "array-buffer")] - Int32Array(TypedArrayIndex<'static>) = INT_32_ARRAY_DISCRIMINANT, + Int32Array(TypedArrayIndex<'a>) = INT_32_ARRAY_DISCRIMINANT, #[cfg(feature = "array-buffer")] - Uint32Array(TypedArrayIndex<'static>) = UINT_32_ARRAY_DISCRIMINANT, + Uint32Array(TypedArrayIndex<'a>) = UINT_32_ARRAY_DISCRIMINANT, #[cfg(feature = "array-buffer")] - BigInt64Array(TypedArrayIndex<'static>) = BIGINT_64_ARRAY_DISCRIMINANT, + BigInt64Array(TypedArrayIndex<'a>) = BIGINT_64_ARRAY_DISCRIMINANT, #[cfg(feature = "array-buffer")] - BigUint64Array(TypedArrayIndex<'static>) = BIGUINT_64_ARRAY_DISCRIMINANT, + BigUint64Array(TypedArrayIndex<'a>) = BIGUINT_64_ARRAY_DISCRIMINANT, #[cfg(feature = "array-buffer")] - Float32Array(TypedArrayIndex<'static>) = FLOAT_32_ARRAY_DISCRIMINANT, + Float32Array(TypedArrayIndex<'a>) = FLOAT_32_ARRAY_DISCRIMINANT, #[cfg(feature = "array-buffer")] - Float64Array(TypedArrayIndex<'static>) = FLOAT_64_ARRAY_DISCRIMINANT, + Float64Array(TypedArrayIndex<'a>) = FLOAT_64_ARRAY_DISCRIMINANT, AsyncFromSyncIterator = ASYNC_FROM_SYNC_ITERATOR_DISCRIMINANT, AsyncIterator = ASYNC_ITERATOR_DISCRIMINANT, Iterator = ITERATOR_DISCRIMINANT, - ArrayIterator(ArrayIterator<'static>) = ARRAY_ITERATOR_DISCRIMINANT, - SetIterator(SetIterator<'static>) = SET_ITERATOR_DISCRIMINANT, - MapIterator(MapIterator<'static>) = MAP_ITERATOR_DISCRIMINANT, - Generator(Generator<'static>) = GENERATOR_DISCRIMINANT, - Module(Module<'static>) = MODULE_DISCRIMINANT, - EmbedderObject(EmbedderObject<'static>) = EMBEDDER_OBJECT_DISCRIMINANT, + ArrayIterator(ArrayIterator<'a>) = ARRAY_ITERATOR_DISCRIMINANT, + SetIterator(SetIterator<'a>) = SET_ITERATOR_DISCRIMINANT, + MapIterator(MapIterator<'a>) = MAP_ITERATOR_DISCRIMINANT, + Generator(Generator<'a>) = GENERATOR_DISCRIMINANT, + Module(Module<'a>) = MODULE_DISCRIMINANT, + EmbedderObject(EmbedderObject<'a>) = EMBEDDER_OBJECT_DISCRIMINANT, } #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] pub struct OrdinaryObject<'a>(pub(crate) ObjectIndex<'a>); -impl IntoValue for Object { +impl IntoValue for Object<'_> { fn into_value(self) -> Value { match self { - Object::Object(data) => Value::Object(data), - Object::BoundFunction(data) => Value::BoundFunction(data), - Object::BuiltinFunction(data) => Value::BuiltinFunction(data), - Object::ECMAScriptFunction(data) => Value::ECMAScriptFunction(data), + Object::Object(data) => Value::Object(data.unbind()), + Object::BoundFunction(data) => Value::BoundFunction(data.unbind()), + Object::BuiltinFunction(data) => Value::BuiltinFunction(data.unbind()), + Object::ECMAScriptFunction(data) => Value::ECMAScriptFunction(data.unbind()), Object::BuiltinGeneratorFunction => todo!(), - Object::BuiltinConstructorFunction(data) => Value::BuiltinConstructorFunction(data), + Object::BuiltinConstructorFunction(data) => { + Value::BuiltinConstructorFunction(data.unbind()) + } Object::BuiltinPromiseResolvingFunction(data) => { - Value::BuiltinPromiseResolvingFunction(data) + Value::BuiltinPromiseResolvingFunction(data.unbind()) } Object::BuiltinPromiseCollectorFunction => todo!(), Object::BuiltinProxyRevokerFunction => todo!(), - Object::PrimitiveObject(data) => Value::PrimitiveObject(data), - Object::Arguments(data) => Value::Arguments(data), - Object::Array(data) => Value::Array(data), + Object::PrimitiveObject(data) => Value::PrimitiveObject(data.unbind()), + Object::Arguments(data) => Value::Arguments(data.unbind()), + Object::Array(data) => Value::Array(data.unbind()), #[cfg(feature = "array-buffer")] - Object::ArrayBuffer(data) => Value::ArrayBuffer(data), + Object::ArrayBuffer(data) => Value::ArrayBuffer(data.unbind()), #[cfg(feature = "array-buffer")] - Object::DataView(data) => Value::DataView(data), + Object::DataView(data) => Value::DataView(data.unbind()), #[cfg(feature = "date")] - Object::Date(data) => Value::Date(data), - Object::Error(data) => Value::Error(data), - Object::FinalizationRegistry(data) => Value::FinalizationRegistry(data), - Object::Map(data) => Value::Map(data), - Object::Promise(data) => Value::Promise(data), - Object::Proxy(data) => Value::Proxy(data), + Object::Date(data) => Value::Date(data.unbind()), + Object::Error(data) => Value::Error(data.unbind()), + Object::FinalizationRegistry(data) => Value::FinalizationRegistry(data.unbind()), + Object::Map(data) => Value::Map(data.unbind()), + Object::Promise(data) => Value::Promise(data.unbind()), + Object::Proxy(data) => Value::Proxy(data.unbind()), #[cfg(feature = "regexp")] - Object::RegExp(data) => Value::RegExp(data), - Object::Set(data) => Value::Set(data), + Object::RegExp(data) => Value::RegExp(data.unbind()), + Object::Set(data) => Value::Set(data.unbind()), #[cfg(feature = "shared-array-buffer")] - Object::SharedArrayBuffer(data) => Value::SharedArrayBuffer(data), + Object::SharedArrayBuffer(data) => Value::SharedArrayBuffer(data.unbind()), #[cfg(feature = "weak-refs")] - Object::WeakMap(data) => Value::WeakMap(data), + Object::WeakMap(data) => Value::WeakMap(data.unbind()), #[cfg(feature = "weak-refs")] - Object::WeakRef(data) => Value::WeakRef(data), + Object::WeakRef(data) => Value::WeakRef(data.unbind()), #[cfg(feature = "weak-refs")] - Object::WeakSet(data) => Value::WeakSet(data), + Object::WeakSet(data) => Value::WeakSet(data.unbind()), #[cfg(feature = "array-buffer")] - Object::Int8Array(data) => Value::Int8Array(data), + Object::Int8Array(data) => Value::Int8Array(data.unbind()), #[cfg(feature = "array-buffer")] - Object::Uint8Array(data) => Value::Uint8Array(data), + Object::Uint8Array(data) => Value::Uint8Array(data.unbind()), #[cfg(feature = "array-buffer")] - Object::Uint8ClampedArray(data) => Value::Uint8ClampedArray(data), + Object::Uint8ClampedArray(data) => Value::Uint8ClampedArray(data.unbind()), #[cfg(feature = "array-buffer")] - Object::Int16Array(data) => Value::Int16Array(data), + Object::Int16Array(data) => Value::Int16Array(data.unbind()), #[cfg(feature = "array-buffer")] - Object::Uint16Array(data) => Value::Uint16Array(data), + Object::Uint16Array(data) => Value::Uint16Array(data.unbind()), #[cfg(feature = "array-buffer")] - Object::Int32Array(data) => Value::Int32Array(data), + Object::Int32Array(data) => Value::Int32Array(data.unbind()), #[cfg(feature = "array-buffer")] - Object::Uint32Array(data) => Value::Uint32Array(data), + Object::Uint32Array(data) => Value::Uint32Array(data.unbind()), #[cfg(feature = "array-buffer")] - Object::BigInt64Array(data) => Value::BigInt64Array(data), + Object::BigInt64Array(data) => Value::BigInt64Array(data.unbind()), #[cfg(feature = "array-buffer")] - Object::BigUint64Array(data) => Value::BigUint64Array(data), + Object::BigUint64Array(data) => Value::BigUint64Array(data.unbind()), #[cfg(feature = "array-buffer")] - Object::Float32Array(data) => Value::Float32Array(data), + Object::Float32Array(data) => Value::Float32Array(data.unbind()), #[cfg(feature = "array-buffer")] - Object::Float64Array(data) => Value::Float64Array(data), + Object::Float64Array(data) => Value::Float64Array(data.unbind()), Object::AsyncFromSyncIterator => todo!(), Object::AsyncIterator => todo!(), Object::Iterator => todo!(), - Object::ArrayIterator(data) => Value::ArrayIterator(data), - Object::SetIterator(data) => Value::SetIterator(data), - Object::MapIterator(data) => Value::MapIterator(data), - Object::Generator(data) => Value::Generator(data), - Object::Module(data) => Value::Module(data), - Object::EmbedderObject(data) => Value::EmbedderObject(data), + Object::ArrayIterator(data) => Value::ArrayIterator(data.unbind()), + Object::SetIterator(data) => Value::SetIterator(data.unbind()), + Object::MapIterator(data) => Value::MapIterator(data.unbind()), + Object::Generator(data) => Value::Generator(data.unbind()), + Object::Module(data) => Value::Module(data.unbind()), + Object::EmbedderObject(data) => Value::EmbedderObject(data.unbind()), } } } -impl IntoObject for Object { +impl<'a> IntoObject<'a> for Object<'a> { #[inline(always)] - fn into_object(self) -> Object { + fn into_object(self) -> Object<'a> { self } } -impl IntoObject for OrdinaryObject<'_> { - fn into_object(self) -> Object { +impl<'a> IntoObject<'a> for OrdinaryObject<'a> { + fn into_object(self) -> Object<'a> { self.into() } } @@ -274,7 +276,7 @@ impl IntoValue for OrdinaryObject<'_> { } } -impl From> for Object { +impl<'a> From> for Object<'a> { fn from(value: OrdinaryObject<'_>) -> Self { Self::Object(value.unbind()) } @@ -303,11 +305,11 @@ impl TryFrom for OrdinaryObject<'_> { } } -impl TryFrom for OrdinaryObject<'_> { +impl<'a> TryFrom> for OrdinaryObject<'a> { type Error = (); #[inline] - fn try_from(value: Object) -> Result { + fn try_from(value: Object<'a>) -> Result { match value { Object::Object(data) => Ok(data), _ => Err(()), @@ -315,7 +317,7 @@ impl TryFrom for OrdinaryObject<'_> { } } -impl InternalSlots for OrdinaryObject<'_> { +impl<'a> InternalSlots<'a> for OrdinaryObject<'a> { #[inline(always)] fn get_backing_object(self, _: &Agent) -> Option> { Some(self.unbind()) @@ -337,12 +339,12 @@ impl InternalSlots for OrdinaryObject<'_> { agent[self.unbind()].extensible = value; } - fn internal_prototype(self, agent: &Agent) -> Option { + fn internal_prototype(self, agent: &Agent) -> Option> { agent[self.unbind()].prototype } fn internal_set_prototype(self, agent: &mut Agent, prototype: Option) { - agent[self.unbind()].prototype = prototype; + agent[self.unbind()].prototype = prototype.map(|p| p.unbind()); } } @@ -387,94 +389,96 @@ impl<'a> OrdinaryObject<'a> { } } -impl<'a> From> for Object { +impl<'a> From> for Object<'a> { fn from(value: ObjectIndex<'a>) -> Self { let value: OrdinaryObject<'a> = value.into(); Object::Object(value.unbind()) } } -impl From> for Object { +impl<'a> From> for Object<'a> { fn from(value: BoundFunction) -> Self { Object::BoundFunction(value.unbind()) } } -impl From for Value { +impl From> for Value { fn from(value: Object) -> Self { match value { - Object::Object(data) => Value::Object(data), - Object::BoundFunction(data) => Value::BoundFunction(data), - Object::BuiltinFunction(data) => Value::BuiltinFunction(data), - Object::ECMAScriptFunction(data) => Value::ECMAScriptFunction(data), + Object::Object(data) => Value::Object(data.unbind()), + Object::BoundFunction(data) => Value::BoundFunction(data.unbind()), + Object::BuiltinFunction(data) => Value::BuiltinFunction(data.unbind()), + Object::ECMAScriptFunction(data) => Value::ECMAScriptFunction(data.unbind()), Object::BuiltinGeneratorFunction => Value::BuiltinGeneratorFunction, - Object::BuiltinConstructorFunction(data) => Value::BuiltinConstructorFunction(data), + Object::BuiltinConstructorFunction(data) => { + Value::BuiltinConstructorFunction(data.unbind()) + } Object::BuiltinPromiseResolvingFunction(data) => { - Value::BuiltinPromiseResolvingFunction(data) + Value::BuiltinPromiseResolvingFunction(data.unbind()) } Object::BuiltinPromiseCollectorFunction => Value::BuiltinPromiseCollectorFunction, Object::BuiltinProxyRevokerFunction => Value::BuiltinProxyRevokerFunction, - Object::PrimitiveObject(data) => Value::PrimitiveObject(data), - Object::Arguments(data) => Value::Arguments(data), - Object::Array(data) => Value::Array(data), + Object::PrimitiveObject(data) => Value::PrimitiveObject(data.unbind()), + Object::Arguments(data) => Value::Arguments(data.unbind()), + Object::Array(data) => Value::Array(data.unbind()), #[cfg(feature = "array-buffer")] - Object::ArrayBuffer(data) => Value::ArrayBuffer(data), + Object::ArrayBuffer(data) => Value::ArrayBuffer(data.unbind()), #[cfg(feature = "array-buffer")] - Object::DataView(data) => Value::DataView(data), + Object::DataView(data) => Value::DataView(data.unbind()), #[cfg(feature = "date")] - Object::Date(data) => Value::Date(data), - Object::Error(data) => Value::Error(data), - Object::FinalizationRegistry(data) => Value::FinalizationRegistry(data), - Object::Map(data) => Value::Map(data), - Object::Promise(data) => Value::Promise(data), - Object::Proxy(data) => Value::Proxy(data), + Object::Date(data) => Value::Date(data.unbind()), + Object::Error(data) => Value::Error(data.unbind()), + Object::FinalizationRegistry(data) => Value::FinalizationRegistry(data.unbind()), + Object::Map(data) => Value::Map(data.unbind()), + Object::Promise(data) => Value::Promise(data.unbind()), + Object::Proxy(data) => Value::Proxy(data.unbind()), #[cfg(feature = "regexp")] - Object::RegExp(data) => Value::RegExp(data), - Object::Set(data) => Value::Set(data), + Object::RegExp(data) => Value::RegExp(data.unbind()), + Object::Set(data) => Value::Set(data.unbind()), #[cfg(feature = "shared-array-buffer")] - Object::SharedArrayBuffer(data) => Value::SharedArrayBuffer(data), + Object::SharedArrayBuffer(data) => Value::SharedArrayBuffer(data.unbind()), #[cfg(feature = "weak-refs")] - Object::WeakMap(data) => Value::WeakMap(data), + Object::WeakMap(data) => Value::WeakMap(data.unbind()), #[cfg(feature = "weak-refs")] - Object::WeakRef(data) => Value::WeakRef(data), + Object::WeakRef(data) => Value::WeakRef(data.unbind()), #[cfg(feature = "weak-refs")] - Object::WeakSet(data) => Value::WeakSet(data), + Object::WeakSet(data) => Value::WeakSet(data.unbind()), #[cfg(feature = "array-buffer")] - Object::Int8Array(data) => Value::Int8Array(data), + Object::Int8Array(data) => Value::Int8Array(data.unbind()), #[cfg(feature = "array-buffer")] - Object::Uint8Array(data) => Value::Uint8Array(data), + Object::Uint8Array(data) => Value::Uint8Array(data.unbind()), #[cfg(feature = "array-buffer")] - Object::Uint8ClampedArray(data) => Value::Uint8ClampedArray(data), + Object::Uint8ClampedArray(data) => Value::Uint8ClampedArray(data.unbind()), #[cfg(feature = "array-buffer")] - Object::Int16Array(data) => Value::Int16Array(data), + Object::Int16Array(data) => Value::Int16Array(data.unbind()), #[cfg(feature = "array-buffer")] - Object::Uint16Array(data) => Value::Uint16Array(data), + Object::Uint16Array(data) => Value::Uint16Array(data.unbind()), #[cfg(feature = "array-buffer")] - Object::Int32Array(data) => Value::Int32Array(data), + Object::Int32Array(data) => Value::Int32Array(data.unbind()), #[cfg(feature = "array-buffer")] - Object::Uint32Array(data) => Value::Uint32Array(data), + Object::Uint32Array(data) => Value::Uint32Array(data.unbind()), #[cfg(feature = "array-buffer")] - Object::BigInt64Array(data) => Value::BigInt64Array(data), + Object::BigInt64Array(data) => Value::BigInt64Array(data.unbind()), #[cfg(feature = "array-buffer")] - Object::BigUint64Array(data) => Value::BigUint64Array(data), + Object::BigUint64Array(data) => Value::BigUint64Array(data.unbind()), #[cfg(feature = "array-buffer")] - Object::Float32Array(data) => Value::Float32Array(data), + Object::Float32Array(data) => Value::Float32Array(data.unbind()), #[cfg(feature = "array-buffer")] - Object::Float64Array(data) => Value::Float64Array(data), + Object::Float64Array(data) => Value::Float64Array(data.unbind()), Object::AsyncFromSyncIterator => Value::AsyncFromSyncIterator, Object::AsyncIterator => Value::AsyncIterator, Object::Iterator => Value::Iterator, - Object::ArrayIterator(data) => Value::ArrayIterator(data), - Object::SetIterator(data) => Value::SetIterator(data), - Object::MapIterator(data) => Value::MapIterator(data), - Object::Generator(data) => Value::Generator(data), - Object::Module(data) => Value::Module(data), - Object::EmbedderObject(data) => Value::EmbedderObject(data), + Object::ArrayIterator(data) => Value::ArrayIterator(data.unbind()), + Object::SetIterator(data) => Value::SetIterator(data.unbind()), + Object::MapIterator(data) => Value::MapIterator(data.unbind()), + Object::Generator(data) => Value::Generator(data.unbind()), + Object::Module(data) => Value::Module(data.unbind()), + Object::EmbedderObject(data) => Value::EmbedderObject(data.unbind()), } } } -impl TryFrom for Object { +impl TryFrom for Object<'_> { type Error = (); fn try_from(value: Value) -> Result { match value { @@ -560,12 +564,12 @@ impl TryFrom for Object { } } -impl Object { +impl<'a> Object<'a> { /// Unbind this Object from its current lifetime. This is necessary to use /// the Object as a parameter in a call that can perform garbage /// collection. - pub fn unbind(self) -> Self { - self + pub fn unbind(self) -> Object<'static> { + unsafe { std::mem::transmute::>(self) } } // Bind this Object to the garbage collection lifetime. This enables Rust's @@ -577,28 +581,28 @@ impl Object { // let object = object.bind(&gc); // ``` // to make sure that the unbound Object cannot be used after binding. - pub const fn bind(self, _: NoGcScope<'_, '_>) -> Self { - self + pub const fn bind<'gc>(self, _: NoGcScope<'gc, '_>) -> Object<'gc> { + unsafe { std::mem::transmute::>(self) } } pub fn scope<'scope>( self, agent: &mut Agent, gc: NoGcScope<'_, 'scope>, - ) -> Scoped<'scope, Object> { - Scoped::new(agent, self, gc) + ) -> Scoped<'scope, Object<'static>> { + Scoped::new(agent, self.unbind(), gc) } pub fn into_value(self) -> Value { self.into() } - pub fn property_storage(self) -> PropertyStorage { + pub fn property_storage(self) -> PropertyStorage<'a> { PropertyStorage::new(self) } } -impl Hash for Object { +impl Hash for Object<'_> { fn hash(&self, state: &mut H) { core::mem::discriminant(self).hash(state); match self { @@ -671,7 +675,7 @@ impl Hash for Object { } } -impl InternalSlots for Object { +impl<'a> InternalSlots<'a> for Object<'a> { fn get_backing_object(self, _: &Agent) -> Option> { unreachable!("Object should not try to access its backing object"); } @@ -854,7 +858,7 @@ impl InternalSlots for Object { } } - fn internal_prototype(self, agent: &Agent) -> Option { + fn internal_prototype(self, agent: &Agent) -> Option> { match self { Object::Object(data) => data.internal_prototype(agent), Object::Array(data) => data.internal_prototype(agent), @@ -1027,12 +1031,12 @@ impl InternalSlots for Object { } } -impl InternalMethods for Object { - fn try_get_prototype_of( +impl<'a> InternalMethods<'a> for Object<'a> { + fn try_get_prototype_of<'gc>( self, agent: &mut Agent, - gc: NoGcScope<'_, '_>, - ) -> TryResult> { + gc: NoGcScope<'gc, '_>, + ) -> TryResult>> { match self { Object::Object(data) => data.try_get_prototype_of(agent, gc), Object::Array(data) => data.try_get_prototype_of(agent, gc), @@ -1122,11 +1126,11 @@ impl InternalMethods for Object { } } - fn internal_get_prototype_of( + fn internal_get_prototype_of<'gc>( self, agent: &mut Agent, - gc: GcScope<'_, '_>, - ) -> JsResult> { + gc: GcScope<'gc, '_>, + ) -> JsResult>> { match self { Object::Object(data) => data.internal_get_prototype_of(agent, gc), Object::Array(data) => data.internal_get_prototype_of(agent, gc), @@ -1224,7 +1228,7 @@ impl InternalMethods for Object { self, agent: &mut Agent, prototype: Option, - gc: NoGcScope<'_, '_>, + gc: NoGcScope, ) -> TryResult { match self { Object::Object(data) => data.try_set_prototype_of(agent, prototype, gc), @@ -1325,7 +1329,7 @@ impl InternalMethods for Object { self, agent: &mut Agent, prototype: Option, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { match self { Object::Object(data) => data.internal_set_prototype_of(agent, prototype, gc), @@ -1426,7 +1430,7 @@ impl InternalMethods for Object { } } - fn try_is_extensible(self, agent: &mut Agent, gc: NoGcScope<'_, '_>) -> TryResult { + fn try_is_extensible(self, agent: &mut Agent, gc: NoGcScope) -> TryResult { match self { Object::Object(data) => data.try_is_extensible(agent, gc), Object::Array(data) => data.try_is_extensible(agent, gc), @@ -1506,7 +1510,7 @@ impl InternalMethods for Object { } } - fn internal_is_extensible(self, agent: &mut Agent, gc: GcScope<'_, '_>) -> JsResult { + fn internal_is_extensible(self, agent: &mut Agent, gc: GcScope) -> JsResult { match self { Object::Object(data) => data.internal_is_extensible(agent, gc), Object::Array(data) => data.internal_is_extensible(agent, gc), @@ -1598,7 +1602,7 @@ impl InternalMethods for Object { } } - fn try_prevent_extensions(self, agent: &mut Agent, gc: NoGcScope<'_, '_>) -> TryResult { + fn try_prevent_extensions(self, agent: &mut Agent, gc: NoGcScope) -> TryResult { match self { Object::Object(data) => data.try_prevent_extensions(agent, gc), Object::Array(data) => data.try_prevent_extensions(agent, gc), @@ -1690,7 +1694,7 @@ impl InternalMethods for Object { } } - fn internal_prevent_extensions(self, agent: &mut Agent, gc: GcScope<'_, '_>) -> JsResult { + fn internal_prevent_extensions(self, agent: &mut Agent, gc: GcScope) -> JsResult { match self { Object::Object(data) => data.internal_prevent_extensions(agent, gc), Object::Array(data) => data.internal_prevent_extensions(agent, gc), @@ -1788,7 +1792,7 @@ impl InternalMethods for Object { self, agent: &mut Agent, property_key: PropertyKey, - gc: NoGcScope<'_, '_>, + gc: NoGcScope, ) -> TryResult> { match self { Object::Object(data) => data.try_get_own_property(agent, property_key, gc), @@ -1891,7 +1895,7 @@ impl InternalMethods for Object { self, agent: &mut Agent, property_key: PropertyKey, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult> { match self { Object::Object(data) => data.internal_get_own_property(agent, property_key, gc), @@ -2002,7 +2006,7 @@ impl InternalMethods for Object { agent: &mut Agent, property_key: PropertyKey, property_descriptor: PropertyDescriptor, - gc: NoGcScope<'_, '_>, + gc: NoGcScope, ) -> TryResult { match self { Object::Object(idx) => { @@ -2183,7 +2187,7 @@ impl InternalMethods for Object { agent: &mut Agent, property_key: PropertyKey, property_descriptor: PropertyDescriptor, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { match self { Object::Object(idx) => { @@ -2343,7 +2347,7 @@ impl InternalMethods for Object { self, agent: &mut Agent, property_key: PropertyKey, - gc: NoGcScope<'_, '_>, + gc: NoGcScope, ) -> TryResult { match self { Object::Object(data) => data.try_has_property(agent, property_key, gc), @@ -2444,7 +2448,7 @@ impl InternalMethods for Object { self, agent: &mut Agent, property_key: PropertyKey, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { match self { Object::Object(data) => data.internal_has_property(agent, property_key, gc), @@ -2548,7 +2552,7 @@ impl InternalMethods for Object { agent: &mut Agent, property_key: PropertyKey, receiver: Value, - gc: NoGcScope<'_, '_>, + gc: NoGcScope, ) -> TryResult { match self { Object::Object(data) => data.try_get(agent, property_key, receiver, gc), @@ -2650,7 +2654,7 @@ impl InternalMethods for Object { agent: &mut Agent, property_key: PropertyKey, receiver: Value, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { match self { Object::Object(data) => data.internal_get(agent, property_key, receiver, gc), @@ -2757,7 +2761,7 @@ impl InternalMethods for Object { property_key: PropertyKey, value: Value, receiver: Value, - gc: NoGcScope<'_, '_>, + gc: NoGcScope, ) -> TryResult { match self { Object::Object(data) => data.try_set(agent, property_key, value, receiver, gc), @@ -2870,7 +2874,7 @@ impl InternalMethods for Object { property_key: PropertyKey, value: Value, receiver: Value, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { match self { Object::Object(data) => data.internal_set(agent, property_key, value, receiver, gc), @@ -3013,7 +3017,7 @@ impl InternalMethods for Object { self, agent: &mut Agent, property_key: PropertyKey, - gc: NoGcScope<'_, '_>, + gc: NoGcScope, ) -> TryResult { match self { Object::Object(data) => data.try_delete(agent, property_key, gc), @@ -3112,7 +3116,7 @@ impl InternalMethods for Object { self, agent: &mut Agent, property_key: PropertyKey, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { match self { Object::Object(data) => data.internal_delete(agent, property_key, gc), @@ -3209,11 +3213,11 @@ impl InternalMethods for Object { } } - fn try_own_property_keys<'a>( + fn try_own_property_keys<'gc>( self, agent: &mut Agent, - gc: NoGcScope<'a, '_>, - ) -> TryResult>> { + gc: NoGcScope<'gc, '_>, + ) -> TryResult>> { match self { Object::Object(data) => data.try_own_property_keys(agent, gc), Object::Array(data) => data.try_own_property_keys(agent, gc), @@ -3406,7 +3410,7 @@ impl InternalMethods for Object { agent: &mut Agent, this_value: Value, arguments_list: ArgumentsList, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { match self { Object::BoundFunction(data) => { @@ -3423,13 +3427,13 @@ impl InternalMethods for Object { } } - fn internal_construct( + fn internal_construct<'gc>( self, agent: &mut Agent, arguments_list: ArgumentsList, new_target: Function, - gc: GcScope<'_, '_>, - ) -> JsResult { + gc: GcScope<'gc, '_>, + ) -> JsResult> { match self { Object::BoundFunction(data) => { data.internal_construct(agent, arguments_list, new_target, gc) @@ -3445,7 +3449,7 @@ impl InternalMethods for Object { } } -impl HeapMarkAndSweep for Object { +impl HeapMarkAndSweep for Object<'static> { fn mark_values(&self, queues: &mut WorkQueues) { match self { Object::Object(data) => data.mark_values(queues), @@ -3617,203 +3621,99 @@ impl Rootable for OrdinaryObject<'static> { } } -impl Rootable for Object { - type RootRepr = HeapRootRef; +impl TryFrom for Object<'_> { + type Error = (); - fn to_root_repr(value: Self) -> Result { + fn try_from(value: HeapRootData) -> Result { match value { - Self::Object(ordinary_object) => Err(HeapRootData::Object(ordinary_object)), - Self::BoundFunction(bound_function) => Err(HeapRootData::BoundFunction(bound_function)), - Self::BuiltinFunction(builtin_function) => { - Err(HeapRootData::BuiltinFunction(builtin_function)) - } - Self::ECMAScriptFunction(ecmascript_function) => { - Err(HeapRootData::ECMAScriptFunction(ecmascript_function)) - } - Self::BuiltinGeneratorFunction => Err(HeapRootData::BuiltinGeneratorFunction), - Self::BuiltinConstructorFunction(builtin_constructor_function) => Err( - HeapRootData::BuiltinConstructorFunction(builtin_constructor_function), - ), - Self::BuiltinPromiseResolvingFunction(builtin_promise_resolving_function) => Err( - HeapRootData::BuiltinPromiseResolvingFunction(builtin_promise_resolving_function), - ), - Self::BuiltinPromiseCollectorFunction => { - Err(HeapRootData::BuiltinPromiseCollectorFunction) - } - Self::BuiltinProxyRevokerFunction => Err(HeapRootData::BuiltinProxyRevokerFunction), - Self::PrimitiveObject(primitive_object) => { - Err(HeapRootData::PrimitiveObject(primitive_object)) - } - Self::Arguments(ordinary_object) => Err(HeapRootData::Arguments(ordinary_object)), - Self::Array(array) => Err(HeapRootData::Array(array)), - #[cfg(feature = "array-buffer")] - Self::ArrayBuffer(array_buffer) => Err(HeapRootData::ArrayBuffer(array_buffer)), - #[cfg(feature = "array-buffer")] - Self::DataView(data_view) => Err(HeapRootData::DataView(data_view)), - #[cfg(feature = "date")] - Self::Date(date) => Err(HeapRootData::Date(date)), - Self::Error(error) => Err(HeapRootData::Error(error)), - Self::FinalizationRegistry(finalization_registry) => { - Err(HeapRootData::FinalizationRegistry(finalization_registry)) - } - Self::Map(map) => Err(HeapRootData::Map(map)), - Self::Promise(promise) => Err(HeapRootData::Promise(promise)), - Self::Proxy(proxy) => Err(HeapRootData::Proxy(proxy)), - #[cfg(feature = "regexp")] - Self::RegExp(reg_exp) => Err(HeapRootData::RegExp(reg_exp)), - Self::Set(set) => Err(HeapRootData::Set(set)), - #[cfg(feature = "shared-array-buffer")] - Self::SharedArrayBuffer(shared_array_buffer) => { - Err(HeapRootData::SharedArrayBuffer(shared_array_buffer)) - } - #[cfg(feature = "weak-refs")] - Self::WeakMap(weak_map) => Err(HeapRootData::WeakMap(weak_map)), - #[cfg(feature = "weak-refs")] - Self::WeakRef(weak_ref) => Err(HeapRootData::WeakRef(weak_ref)), - #[cfg(feature = "weak-refs")] - Self::WeakSet(weak_set) => Err(HeapRootData::WeakSet(weak_set)), - #[cfg(feature = "array-buffer")] - Self::Int8Array(base_index) => Err(HeapRootData::Int8Array(base_index)), - #[cfg(feature = "array-buffer")] - Self::Uint8Array(base_index) => Err(HeapRootData::Uint8Array(base_index)), - #[cfg(feature = "array-buffer")] - Self::Uint8ClampedArray(base_index) => Err(HeapRootData::Uint8ClampedArray(base_index)), - #[cfg(feature = "array-buffer")] - Self::Int16Array(base_index) => Err(HeapRootData::Int16Array(base_index)), - #[cfg(feature = "array-buffer")] - Self::Uint16Array(base_index) => Err(HeapRootData::Uint16Array(base_index)), - #[cfg(feature = "array-buffer")] - Self::Int32Array(base_index) => Err(HeapRootData::Int32Array(base_index)), - #[cfg(feature = "array-buffer")] - Self::Uint32Array(base_index) => Err(HeapRootData::Uint32Array(base_index)), - #[cfg(feature = "array-buffer")] - Self::BigInt64Array(base_index) => Err(HeapRootData::BigInt64Array(base_index)), - #[cfg(feature = "array-buffer")] - Self::BigUint64Array(base_index) => Err(HeapRootData::BigUint64Array(base_index)), - #[cfg(feature = "array-buffer")] - Self::Float32Array(base_index) => Err(HeapRootData::Float32Array(base_index)), - #[cfg(feature = "array-buffer")] - Self::Float64Array(base_index) => Err(HeapRootData::Float64Array(base_index)), - Self::AsyncFromSyncIterator => Err(HeapRootData::AsyncFromSyncIterator), - Self::AsyncIterator => Err(HeapRootData::AsyncIterator), - Self::Iterator => Err(HeapRootData::Iterator), - Self::ArrayIterator(array_iterator) => Err(HeapRootData::ArrayIterator(array_iterator)), - Self::SetIterator(set_iterator) => Err(HeapRootData::SetIterator(set_iterator)), - Self::MapIterator(map_iterator) => Err(HeapRootData::MapIterator(map_iterator)), - Self::Generator(generator) => Err(HeapRootData::Generator(generator)), - Self::Module(module) => Err(HeapRootData::Module(module)), - Self::EmbedderObject(embedder_object) => { - Err(HeapRootData::EmbedderObject(embedder_object)) - } - } - } - - #[inline] - fn from_root_repr(value: &Self::RootRepr) -> Result { - Err(*value) - } - - #[inline] - fn from_heap_ref(heap_ref: HeapRootRef) -> Self::RootRepr { - heap_ref - } - - fn from_heap_data(heap_data: HeapRootData) -> Option { - match heap_data { - HeapRootData::String(_) => None, - HeapRootData::Symbol(_) => None, - HeapRootData::Number(_) => None, - HeapRootData::BigInt(_) => None, - HeapRootData::Object(ordinary_object) => Some(Self::Object(ordinary_object)), - HeapRootData::BoundFunction(bound_function) => { - Some(Self::BoundFunction(bound_function)) - } + HeapRootData::String(_) => Err(()), + HeapRootData::Symbol(_) => Err(()), + HeapRootData::Number(_) => Err(()), + HeapRootData::BigInt(_) => Err(()), + HeapRootData::Object(ordinary_object) => Ok(Self::Object(ordinary_object)), + HeapRootData::BoundFunction(bound_function) => Ok(Self::BoundFunction(bound_function)), HeapRootData::BuiltinFunction(builtin_function) => { - Some(Self::BuiltinFunction(builtin_function)) + Ok(Self::BuiltinFunction(builtin_function)) } HeapRootData::ECMAScriptFunction(ecmascript_function) => { - Some(Self::ECMAScriptFunction(ecmascript_function)) + Ok(Self::ECMAScriptFunction(ecmascript_function)) } - HeapRootData::BuiltinGeneratorFunction => Some(Self::BuiltinGeneratorFunction), - HeapRootData::BuiltinConstructorFunction(builtin_constructor_function) => Some( + HeapRootData::BuiltinGeneratorFunction => Ok(Self::BuiltinGeneratorFunction), + HeapRootData::BuiltinConstructorFunction(builtin_constructor_function) => Ok( Self::BuiltinConstructorFunction(builtin_constructor_function), ), HeapRootData::BuiltinPromiseResolvingFunction(builtin_promise_resolving_function) => { - Some(Self::BuiltinPromiseResolvingFunction( + Ok(Self::BuiltinPromiseResolvingFunction( builtin_promise_resolving_function, )) } HeapRootData::BuiltinPromiseCollectorFunction => { - Some(Self::BuiltinPromiseCollectorFunction) + Ok(Self::BuiltinPromiseCollectorFunction) } - HeapRootData::BuiltinProxyRevokerFunction => Some(Self::BuiltinProxyRevokerFunction), + HeapRootData::BuiltinProxyRevokerFunction => Ok(Self::BuiltinProxyRevokerFunction), HeapRootData::PrimitiveObject(primitive_object) => { - Some(Self::PrimitiveObject(primitive_object)) + Ok(Self::PrimitiveObject(primitive_object)) } - HeapRootData::Arguments(ordinary_object) => Some(Self::Arguments(ordinary_object)), - HeapRootData::Array(array) => Some(Self::Array(array)), + HeapRootData::Arguments(ordinary_object) => Ok(Self::Arguments(ordinary_object)), + HeapRootData::Array(array) => Ok(Self::Array(array)), #[cfg(feature = "array-buffer")] - HeapRootData::ArrayBuffer(array_buffer) => Some(Self::ArrayBuffer(array_buffer)), + HeapRootData::ArrayBuffer(array_buffer) => Ok(Self::ArrayBuffer(array_buffer)), #[cfg(feature = "array-buffer")] - HeapRootData::DataView(data_view) => Some(Self::DataView(data_view)), + HeapRootData::DataView(data_view) => Ok(Self::DataView(data_view)), #[cfg(feature = "date")] - HeapRootData::Date(date) => Some(Self::Date(date)), - HeapRootData::Error(error) => Some(Self::Error(error)), + HeapRootData::Date(date) => Ok(Self::Date(date)), + HeapRootData::Error(error) => Ok(Self::Error(error)), HeapRootData::FinalizationRegistry(finalization_registry) => { - Some(Self::FinalizationRegistry(finalization_registry)) + Ok(Self::FinalizationRegistry(finalization_registry)) } - HeapRootData::Map(map) => Some(Self::Map(map)), - HeapRootData::Promise(promise) => Some(Self::Promise(promise)), - HeapRootData::Proxy(proxy) => Some(Self::Proxy(proxy)), + HeapRootData::Map(map) => Ok(Self::Map(map)), + HeapRootData::Promise(promise) => Ok(Self::Promise(promise)), + HeapRootData::Proxy(proxy) => Ok(Self::Proxy(proxy)), #[cfg(feature = "regexp")] - HeapRootData::RegExp(reg_exp) => Some(Self::RegExp(reg_exp)), - HeapRootData::Set(set) => Some(Self::Set(set)), + HeapRootData::RegExp(reg_exp) => Ok(Self::RegExp(reg_exp)), + HeapRootData::Set(set) => Ok(Self::Set(set)), #[cfg(feature = "shared-array-buffer")] HeapRootData::SharedArrayBuffer(shared_array_buffer) => { - Some(Self::SharedArrayBuffer(shared_array_buffer)) + Ok(Self::SharedArrayBuffer(shared_array_buffer)) } #[cfg(feature = "weak-refs")] - HeapRootData::WeakMap(weak_map) => Some(Self::WeakMap(weak_map)), + HeapRootData::WeakMap(weak_map) => Ok(Self::WeakMap(weak_map)), #[cfg(feature = "weak-refs")] - HeapRootData::WeakRef(weak_ref) => Some(Self::WeakRef(weak_ref)), + HeapRootData::WeakRef(weak_ref) => Ok(Self::WeakRef(weak_ref)), #[cfg(feature = "weak-refs")] - HeapRootData::WeakSet(weak_set) => Some(Self::WeakSet(weak_set)), + HeapRootData::WeakSet(weak_set) => Ok(Self::WeakSet(weak_set)), #[cfg(feature = "array-buffer")] - HeapRootData::Int8Array(base_index) => Some(Self::Int8Array(base_index)), + HeapRootData::Int8Array(base_index) => Ok(Self::Int8Array(base_index)), #[cfg(feature = "array-buffer")] - HeapRootData::Uint8Array(base_index) => Some(Self::Uint8Array(base_index)), + HeapRootData::Uint8Array(base_index) => Ok(Self::Uint8Array(base_index)), #[cfg(feature = "array-buffer")] - HeapRootData::Uint8ClampedArray(base_index) => { - Some(Self::Uint8ClampedArray(base_index)) - } + HeapRootData::Uint8ClampedArray(base_index) => Ok(Self::Uint8ClampedArray(base_index)), #[cfg(feature = "array-buffer")] - HeapRootData::Int16Array(base_index) => Some(Self::Int16Array(base_index)), + HeapRootData::Int16Array(base_index) => Ok(Self::Int16Array(base_index)), #[cfg(feature = "array-buffer")] - HeapRootData::Uint16Array(base_index) => Some(Self::Uint16Array(base_index)), + HeapRootData::Uint16Array(base_index) => Ok(Self::Uint16Array(base_index)), #[cfg(feature = "array-buffer")] - HeapRootData::Int32Array(base_index) => Some(Self::Int32Array(base_index)), + HeapRootData::Int32Array(base_index) => Ok(Self::Int32Array(base_index)), #[cfg(feature = "array-buffer")] - HeapRootData::Uint32Array(base_index) => Some(Self::Uint32Array(base_index)), + HeapRootData::Uint32Array(base_index) => Ok(Self::Uint32Array(base_index)), #[cfg(feature = "array-buffer")] - HeapRootData::BigInt64Array(base_index) => Some(Self::BigInt64Array(base_index)), + HeapRootData::BigInt64Array(base_index) => Ok(Self::BigInt64Array(base_index)), #[cfg(feature = "array-buffer")] - HeapRootData::BigUint64Array(base_index) => Some(Self::BigUint64Array(base_index)), + HeapRootData::BigUint64Array(base_index) => Ok(Self::BigUint64Array(base_index)), #[cfg(feature = "array-buffer")] - HeapRootData::Float32Array(base_index) => Some(Self::Float32Array(base_index)), + HeapRootData::Float32Array(base_index) => Ok(Self::Float32Array(base_index)), #[cfg(feature = "array-buffer")] - HeapRootData::Float64Array(base_index) => Some(Self::Float64Array(base_index)), - HeapRootData::AsyncFromSyncIterator => Some(Self::AsyncFromSyncIterator), - HeapRootData::AsyncIterator => Some(Self::AsyncIterator), - HeapRootData::Iterator => Some(Self::Iterator), - HeapRootData::ArrayIterator(array_iterator) => { - Some(Self::ArrayIterator(array_iterator)) - } - HeapRootData::SetIterator(set_iterator) => Some(Self::SetIterator(set_iterator)), - HeapRootData::MapIterator(map_iterator) => Some(Self::MapIterator(map_iterator)), - HeapRootData::Generator(generator) => Some(Self::Generator(generator)), - HeapRootData::Module(module) => Some(Self::Module(module)), + HeapRootData::Float64Array(base_index) => Ok(Self::Float64Array(base_index)), + HeapRootData::AsyncFromSyncIterator => Ok(Self::AsyncFromSyncIterator), + HeapRootData::AsyncIterator => Ok(Self::AsyncIterator), + HeapRootData::Iterator => Ok(Self::Iterator), + HeapRootData::ArrayIterator(array_iterator) => Ok(Self::ArrayIterator(array_iterator)), + HeapRootData::SetIterator(set_iterator) => Ok(Self::SetIterator(set_iterator)), + HeapRootData::MapIterator(map_iterator) => Ok(Self::MapIterator(map_iterator)), + HeapRootData::Generator(generator) => Ok(Self::Generator(generator)), + HeapRootData::Module(module) => Ok(Self::Module(module)), HeapRootData::EmbedderObject(embedder_object) => { - Some(Self::EmbedderObject(embedder_object)) + Ok(Self::EmbedderObject(embedder_object)) } // Note: Do not use _ => Err(()) to make sure any added // HeapRootData Value variants cause compile errors if not handled. } diff --git a/nova_vm/src/ecmascript/types/language/object/data.rs b/nova_vm/src/ecmascript/types/language/object/data.rs index 9cb2a06d9..00f8cb9f6 100644 --- a/nova_vm/src/ecmascript/types/language/object/data.rs +++ b/nova_vm/src/ecmascript/types/language/object/data.rs @@ -11,7 +11,7 @@ use crate::{ #[derive(Debug, Clone, Copy)] pub struct ObjectHeapData { pub extensible: bool, - pub prototype: Option, + pub prototype: Option>, pub keys: ElementsVector, pub values: ElementsVector, } diff --git a/nova_vm/src/ecmascript/types/language/object/internal_methods.rs b/nova_vm/src/ecmascript/types/language/object/internal_methods.rs index 81a1f5594..bb529e716 100644 --- a/nova_vm/src/ecmascript/types/language/object/internal_methods.rs +++ b/nova_vm/src/ecmascript/types/language/object/internal_methods.rs @@ -25,9 +25,9 @@ use crate::{ }; /// ### [6.1.7.2 Object Internal Methods and Internal Slots](https://tc39.es/ecma262/#sec-object-internal-methods-and-internal-slots) -pub trait InternalMethods +pub trait InternalMethods<'a> where - Self: std::fmt::Debug + Sized + Clone + Copy + Into + InternalSlots, + Self: 'a + std::fmt::Debug + Sized + Clone + Copy + Into> + InternalSlots<'a>, { /// ## Infallible \[\[GetPrototypeOf\]\] /// @@ -36,11 +36,11 @@ where /// method cannot be completed without calling into JavaScript, then `None` /// is returned. It is preferable to call this method first and only call /// the main method if this returns None. - fn try_get_prototype_of( + fn try_get_prototype_of<'gc>( self, agent: &mut Agent, - gc: NoGcScope<'_, '_>, - ) -> TryResult> { + gc: NoGcScope<'gc, '_>, + ) -> TryResult>> { TryResult::Continue(match self.get_backing_object(agent) { Some(backing_object) => ordinary_get_prototype_of(agent, backing_object, gc), None => self.internal_prototype(agent), @@ -48,16 +48,16 @@ where } /// ## \[\[GetPrototypeOf\]\] - fn internal_get_prototype_of( + fn internal_get_prototype_of<'gc>( self, agent: &mut Agent, // Note: Because of Proxies, this can trigger GC. - gc: GcScope<'_, '_>, - ) -> JsResult> { + gc: GcScope<'gc, '_>, + ) -> JsResult>> { // Note: ordinary_get_prototype_of cannot call JS or trigger // GC: No object should ever have a try_proto method that can // return None while also using this default impl. - Ok(unwrap_try(self.try_get_prototype_of(agent, gc.nogc()))) + Ok(unwrap_try(self.try_get_prototype_of(agent, gc.into_nogc()))) } /// ## Infallible \[\[SetPrototypeOf\]\] @@ -71,7 +71,7 @@ where self, agent: &mut Agent, prototype: Option, - _gc: NoGcScope<'_, '_>, + _gc: NoGcScope, ) -> TryResult { TryResult::Continue(ordinary_set_prototype_of( agent, @@ -86,7 +86,7 @@ where agent: &mut Agent, // Note: Because of Proxies, this can trigger GC. prototype: Option, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { match self.try_set_prototype_of(agent, prototype, gc.into_nogc()) { TryResult::Continue(t) => Ok(t), @@ -105,7 +105,7 @@ where self, agent: &mut Agent, // Note: Because of Proxies, this can call JS. - _gc: NoGcScope<'_, '_>, + _gc: NoGcScope, ) -> TryResult { // 1. Return OrdinaryIsExtensible(O). TryResult::Continue(match self.get_backing_object(agent) { @@ -119,7 +119,7 @@ where self, agent: &mut Agent, // Note: Because of Proxies, this can call JS. - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { Ok(unwrap_try(self.try_is_extensible(agent, gc.into_nogc()))) } @@ -131,7 +131,7 @@ where /// method cannot be completed without calling into JavaScript, then `None` /// is returned. It is preferable to call this method first and only call /// the main method if this returns None. - fn try_prevent_extensions(self, agent: &mut Agent, _gc: NoGcScope<'_, '_>) -> TryResult { + fn try_prevent_extensions(self, agent: &mut Agent, _gc: NoGcScope) -> TryResult { // 1. Return OrdinaryPreventExtensions(O). TryResult::Continue(match self.get_backing_object(agent) { Some(backing_object) => ordinary_prevent_extensions(agent, backing_object), @@ -143,7 +143,7 @@ where } /// ## \[\[PreventExtensions\]\] - fn internal_prevent_extensions(self, agent: &mut Agent, gc: GcScope<'_, '_>) -> JsResult { + fn internal_prevent_extensions(self, agent: &mut Agent, gc: GcScope) -> JsResult { Ok(unwrap_try( self.try_prevent_extensions(agent, gc.into_nogc()), )) @@ -160,7 +160,7 @@ where self, agent: &mut Agent, property_key: PropertyKey, - _gc: NoGcScope<'_, '_>, + _gc: NoGcScope, ) -> TryResult> { // 1. Return OrdinaryGetOwnProperty(O, P). TryResult::Continue(match self.get_backing_object(agent) { @@ -174,7 +174,7 @@ where self, agent: &mut Agent, property_key: PropertyKey, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult> { Ok(unwrap_try(self.try_get_own_property( agent, @@ -195,7 +195,7 @@ where agent: &mut Agent, property_key: PropertyKey, property_descriptor: PropertyDescriptor, - gc: NoGcScope<'_, '_>, + gc: NoGcScope, ) -> TryResult { let backing_object = self .get_backing_object(agent) @@ -215,7 +215,7 @@ where agent: &mut Agent, property_key: PropertyKey, property_descriptor: PropertyDescriptor, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { Ok(unwrap_try(self.try_define_own_property( agent, @@ -236,7 +236,7 @@ where self, agent: &mut Agent, property_key: PropertyKey, - gc: NoGcScope<'_, '_>, + gc: NoGcScope, ) -> TryResult { // 1. Return ? OrdinaryHasProperty(O, P). match self.get_backing_object(agent) { @@ -264,7 +264,7 @@ where self, agent: &mut Agent, property_key: PropertyKey, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { let property_key = property_key.bind(gc.nogc()); // 1. Return ? OrdinaryHasProperty(O, P). @@ -280,7 +280,9 @@ where // 4. If parent is not null, then if let Some(parent) = parent { // a. Return ? parent.[[HasProperty]](P). - parent.internal_has_property(agent, property_key.get(agent), gc) + parent + .unbind() + .internal_has_property(agent, property_key.get(agent), gc) } else { // 5. Return false. Ok(false) @@ -301,7 +303,7 @@ where agent: &mut Agent, property_key: PropertyKey, receiver: Value, - gc: NoGcScope<'_, '_>, + gc: NoGcScope, ) -> TryResult { // 1. Return ? OrdinaryGet(O, P, Receiver). match self.get_backing_object(agent) { @@ -327,7 +329,7 @@ where agent: &mut Agent, property_key: PropertyKey, receiver: Value, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { let property_key = property_key.bind(gc.nogc()); // 1. Return ? OrdinaryGet(O, P, Receiver). @@ -344,7 +346,9 @@ where }; // c. Return ? parent.[[Get]](P, Receiver). - parent.internal_get(agent, property_key.get(agent), receiver, gc) + parent + .unbind() + .internal_get(agent, property_key.get(agent), receiver, gc) } } } @@ -362,7 +366,7 @@ where property_key: PropertyKey, value: Value, receiver: Value, - gc: NoGcScope<'_, '_>, + gc: NoGcScope, ) -> TryResult { // 1. Return ? OrdinarySet(O, P, V, Receiver). ordinary_try_set(agent, self.into_object(), property_key, value, receiver, gc) @@ -375,7 +379,7 @@ where property_key: PropertyKey, value: Value, receiver: Value, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { // 1. Return ? OrdinarySet(O, P, V, Receiver). ordinary_set(agent, self.into_object(), property_key, value, receiver, gc) @@ -392,7 +396,7 @@ where self, agent: &mut Agent, property_key: PropertyKey, - gc: NoGcScope<'_, '_>, + gc: NoGcScope, ) -> TryResult { // 1. Return ? OrdinaryDelete(O, P). TryResult::Continue(match self.get_backing_object(agent) { @@ -406,7 +410,7 @@ where self, agent: &mut Agent, property_key: PropertyKey, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { Ok(unwrap_try(self.try_delete( agent, @@ -422,11 +426,11 @@ where /// method cannot be completed without calling into JavaScript, then `None` /// is returned. It is preferable to call this method first and only call /// the main method if this returns None. - fn try_own_property_keys<'a>( + fn try_own_property_keys<'gc>( self, agent: &mut Agent, - gc: NoGcScope<'a, '_>, - ) -> TryResult>> { + gc: NoGcScope<'gc, '_>, + ) -> TryResult>> { // 1. Return OrdinaryOwnPropertyKeys(O). TryResult::Continue(match self.get_backing_object(agent) { Some(backing_object) => ordinary_own_property_keys(agent, backing_object, gc), @@ -435,11 +439,11 @@ where } /// ## \[\[OwnPropertyKeys\]\] - fn internal_own_property_keys<'a>( + fn internal_own_property_keys<'gc>( self, agent: &mut Agent, - gc: GcScope<'a, '_>, - ) -> JsResult>> { + gc: GcScope<'gc, '_>, + ) -> JsResult>> { Ok(unwrap_try( self.try_own_property_keys(agent, gc.into_nogc()), )) @@ -451,19 +455,19 @@ where _agent: &mut Agent, _this_value: Value, _arguments_list: ArgumentsList, - _gc: GcScope<'_, '_>, + _gc: GcScope, ) -> JsResult { unreachable!() } /// ## \[\[Construct\]\] - fn internal_construct( + fn internal_construct<'gc>( self, _agent: &mut Agent, _arguments_list: ArgumentsList, _new_target: Function, - _gc: GcScope<'_, '_>, - ) -> JsResult { + _gc: GcScope<'gc, '_>, + ) -> JsResult> { unreachable!() } } diff --git a/nova_vm/src/ecmascript/types/language/object/internal_slots.rs b/nova_vm/src/ecmascript/types/language/object/internal_slots.rs index b00c08a48..2e8093d42 100644 --- a/nova_vm/src/ecmascript/types/language/object/internal_slots.rs +++ b/nova_vm/src/ecmascript/types/language/object/internal_slots.rs @@ -9,9 +9,9 @@ use crate::{ }; /// ### [10.1 Ordinary Object Internal Methods and Internal Slots](https://tc39.es/ecma262/#sec-ordinary-object-internal-methods-and-internal-slots) -pub trait InternalSlots +pub trait InternalSlots<'a> where - Self: Sized + Copy + Into + IntoObject, + Self: 'a + Sized + Copy + Into> + IntoObject<'a>, { /// Default prototype of the object; this is used by /// [OrdinaryObjectInternalSlots::internal_prototype]. @@ -78,7 +78,7 @@ where /// All ordinary objects have an internal slot called \[\[Prototype\]\]. /// The value of this internal slot is either null or an object and is used /// for implementing inheritance. - fn internal_prototype(self, agent: &Agent) -> Option { + fn internal_prototype(self, agent: &Agent) -> Option> { if let Some(backing_object) = self.get_backing_object(agent) { backing_object.internal_prototype(agent) } else { diff --git a/nova_vm/src/ecmascript/types/language/object/into_object.rs b/nova_vm/src/ecmascript/types/language/object/into_object.rs index 04c7bf3dc..859ecbe55 100644 --- a/nova_vm/src/ecmascript/types/language/object/into_object.rs +++ b/nova_vm/src/ecmascript/types/language/object/into_object.rs @@ -6,9 +6,9 @@ use crate::ecmascript::types::language::into_value::IntoValue; use super::Object; -pub trait IntoObject +pub trait IntoObject<'a> where - Self: Sized + Copy + IntoValue, + Self: 'a + Sized + Copy + IntoValue, { - fn into_object(self) -> Object; + fn into_object(self) -> Object<'a>; } diff --git a/nova_vm/src/ecmascript/types/language/object/property_storage.rs b/nova_vm/src/ecmascript/types/language/object/property_storage.rs index 4e287b4de..655ecd52e 100644 --- a/nova_vm/src/ecmascript/types/language/object/property_storage.rs +++ b/nova_vm/src/ecmascript/types/language/object/property_storage.rs @@ -16,14 +16,14 @@ use crate::{ use super::{Object, ObjectHeapData, PropertyKey}; #[derive(Debug, Clone, Copy)] -pub struct PropertyStorage(Object); +pub struct PropertyStorage<'a>(Object<'a>); -impl PropertyStorage { - pub fn new(object: Object) -> Self { +impl<'a> PropertyStorage<'a> { + pub fn new(object: Object<'a>) -> Self { Self(object) } - fn into_object(self) -> Object { + fn into_object(self) -> Object<'a> { self.0 } diff --git a/nova_vm/src/ecmascript/types/language/value.rs b/nova_vm/src/ecmascript/types/language/value.rs index dd936657f..c81473f37 100644 --- a/nova_vm/src/ecmascript/types/language/value.rs +++ b/nova_vm/src/ecmascript/types/language/value.rs @@ -368,7 +368,7 @@ impl Value { // let value = value.bind(&gc); // ``` // to make sure that the unbound Value cannot be used after binding. - pub fn bind(self, _gc: NoGcScope<'_, '_>) -> Self { + pub fn bind(self, _gc: NoGcScope) -> Self { self } @@ -380,7 +380,7 @@ impl Value { Scoped::new(agent, self.unbind(), gc) } - pub fn from_str(agent: &mut Agent, str: &str, gc: NoGcScope<'_, '_>) -> Value { + pub fn from_str(agent: &mut Agent, str: &str, gc: NoGcScope) -> Value { String::from_str(agent, str, gc).into_value() } @@ -392,7 +392,7 @@ impl Value { String::from_static_str(agent, str, gc).into_value() } - pub fn from_f64(agent: &mut Agent, value: f64, gc: NoGcScope<'_, '_>) -> Value { + pub fn from_f64(agent: &mut Agent, value: f64, gc: NoGcScope) -> Value { Number::from_f64(agent, value, gc).into_value() } @@ -539,19 +539,19 @@ impl Value { to_numeric(agent, self, gc) } - pub fn to_int32(self, agent: &mut Agent, gc: GcScope<'_, '_>) -> JsResult { + pub fn to_int32(self, agent: &mut Agent, gc: GcScope) -> JsResult { to_int32(agent, self, gc) } - pub fn to_uint32(self, agent: &mut Agent, gc: GcScope<'_, '_>) -> JsResult { + pub fn to_uint32(self, agent: &mut Agent, gc: GcScope) -> JsResult { to_uint32(agent, self, gc) } - pub fn to_int16(self, agent: &mut Agent, gc: GcScope<'_, '_>) -> JsResult { + pub fn to_int16(self, agent: &mut Agent, gc: GcScope) -> JsResult { to_int16(agent, self, gc) } - pub fn to_uint16(self, agent: &mut Agent, gc: GcScope<'_, '_>) -> JsResult { + pub fn to_uint16(self, agent: &mut Agent, gc: GcScope) -> JsResult { to_uint16(agent, self, gc) } @@ -602,7 +602,7 @@ impl Value { } /// ### [โ„](https://tc39.es/ecma262/#%E2%84%9D) - pub fn to_real(self, agent: &mut Agent, gc: GcScope<'_, '_>) -> JsResult { + pub fn to_real(self, agent: &mut Agent, gc: GcScope) -> JsResult { Ok(match self { Value::Number(n) => agent[n], Value::Integer(i) => i.into_i64() as f64, diff --git a/nova_vm/src/ecmascript/types/spec/property_descriptor.rs b/nova_vm/src/ecmascript/types/spec/property_descriptor.rs index 00f0caf41..151640faa 100644 --- a/nova_vm/src/ecmascript/types/spec/property_descriptor.rs +++ b/nova_vm/src/ecmascript/types/spec/property_descriptor.rs @@ -231,7 +231,7 @@ impl PropertyDescriptor { pub fn to_property_descriptor( agent: &mut Agent, obj: Value, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { // 1. If Obj is not an Object, throw a TypeError exception. let Ok(obj) = Object::try_from(obj) else { @@ -383,7 +383,7 @@ impl PropertyDescriptor { pub(crate) fn try_to_property_descriptor( agent: &mut Agent, obj: Value, - gc: NoGcScope<'_, '_>, + gc: NoGcScope, ) -> TryResult> { // 1. If Obj is not an Object, throw a TypeError exception. let Ok(obj) = Object::try_from(obj) else { diff --git a/nova_vm/src/ecmascript/types/spec/reference.rs b/nova_vm/src/ecmascript/types/spec/reference.rs index 26c28db30..b17c1361d 100644 --- a/nova_vm/src/ecmascript/types/spec/reference.rs +++ b/nova_vm/src/ecmascript/types/spec/reference.rs @@ -126,7 +126,7 @@ pub(crate) fn is_private_reference(_: &Reference) -> bool { pub(crate) fn get_value( agent: &mut Agent, reference: &Reference, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { let referenced_name = reference.referenced_name.bind(gc.nogc()); match reference.base { @@ -243,7 +243,7 @@ pub(crate) fn put_value( agent: &mut Agent, v: &Reference, w: Value, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult<()> { // 1. If V is not a Reference Record, throw a ReferenceError exception. // 2. If IsUnresolvableReference(V) is true, then @@ -261,10 +261,10 @@ pub(crate) fn put_value( )); } // b. Let globalObj be GetGlobalObject(). - let global_obj = get_global_object(agent); + let global_obj = get_global_object(agent, gc.nogc()); // c. Perform ? Set(globalObj, V.[[ReferencedName]], W, false). let referenced_name = v.referenced_name; - set(agent, global_obj, referenced_name, w, false, gc)?; + set(agent, global_obj.unbind(), referenced_name, w, false, gc)?; // d. Return UNUSED. Ok(()) } else if is_property_reference(v) { @@ -283,11 +283,17 @@ pub(crate) fn put_value( // c. Let succeeded be ? baseObj.[[Set]](V.[[ReferencedName]], W, GetThisValue(V)). let this_value = get_this_value(v); let referenced_name = v.referenced_name; + let scoped_base_obj = base_obj.scope(agent, gc.nogc()); let succeeded = - base_obj.internal_set(agent, referenced_name, w, this_value, gc.reborrow())?; + base_obj + .unbind() + .internal_set(agent, referenced_name, w, this_value, gc.reborrow())?; if !succeeded && v.strict { // d. If succeeded is false and V.[[Strict]] is true, throw a TypeError exception. - let base_obj_repr = base_obj.into_value().string_repr(agent, gc.reborrow()); + let base_obj_repr = scoped_base_obj + .get(agent) + .into_value() + .string_repr(agent, gc.reborrow()); let error_message = format!( "Could not set property '{}' of {}.", referenced_name.as_display(agent), @@ -344,7 +350,7 @@ pub(crate) fn try_put_value<'a>( ))); } // b. Let globalObj be GetGlobalObject(). - let global_obj = get_global_object(agent); + let global_obj = get_global_object(agent, gc); // c. Perform ? Set(globalObj, V.[[ReferencedName]], W, false). let referenced_name = v.referenced_name; if let Err(err) = try_set(agent, global_obj, referenced_name, w, false, gc)? { @@ -416,7 +422,7 @@ pub(crate) fn initialize_referenced_binding( agent: &mut Agent, v: Reference, w: Value, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult<()> { // 1. Assert: IsUnresolvableReference(V) is false. debug_assert!(!is_unresolvable_reference(&v)); diff --git a/nova_vm/src/engine/bytecode/iterator.rs b/nova_vm/src/engine/bytecode/iterator.rs index 50a93d59b..014a24ee4 100644 --- a/nova_vm/src/engine/bytecode/iterator.rs +++ b/nova_vm/src/engine/bytecode/iterator.rs @@ -45,7 +45,7 @@ impl VmIterator { // let number = number.bind(&gc); // ``` // to make sure that the unbound VmIterator cannot be used after binding. - pub const fn bind(self, _: NoGcScope<'_, '_>) -> VmIterator { + pub const fn bind(self, _: NoGcScope) -> VmIterator { self } @@ -58,7 +58,7 @@ impl VmIterator { pub(super) fn step_value( &mut self, agent: &mut Agent, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult> { match self { VmIterator::ObjectProperties(iter) => { @@ -144,11 +144,7 @@ impl VmIterator { /// Iterator Record or a throw completion. /// /// This method version performs the SYNC version of the method. - pub(super) fn from_value( - agent: &mut Agent, - value: Value, - mut gc: GcScope<'_, '_>, - ) -> JsResult { + pub(super) fn from_value(agent: &mut Agent, value: Value, mut gc: GcScope) -> JsResult { // a. Let method be ? GetMethod(obj, %Symbol.iterator%). let method = get_method( agent, @@ -189,7 +185,7 @@ impl VmIterator { #[derive(Debug)] pub(super) struct ObjectPropertiesIterator { - object: Object, + object: Object<'static>, object_was_visited: bool, visited_keys: Vec>, remaining_keys: VecDeque>, @@ -198,7 +194,7 @@ pub(super) struct ObjectPropertiesIterator { impl ObjectPropertiesIterator { pub(super) fn new(object: Object) -> Self { Self { - object, + object: object.unbind(), object_was_visited: false, visited_keys: Default::default(), remaining_keys: Default::default(), @@ -210,10 +206,12 @@ impl ObjectPropertiesIterator { agent: &mut Agent, mut gc: GcScope<'a, '_>, ) -> JsResult>> { + let object = self.object.scope(agent, gc.nogc()); loop { - let object = self.object; if !self.object_was_visited { - let keys = object.internal_own_property_keys(agent, gc.reborrow())?; + let keys = object + .get(agent) + .internal_own_property_keys(agent, gc.reborrow())?; for key in keys { if let PropertyKey::Symbol(_) = key { continue; @@ -229,7 +227,9 @@ impl ObjectPropertiesIterator { continue; } // TODO: Properly handle potential GC. - let desc = object.internal_get_own_property(agent, r, gc.reborrow())?; + let desc = object + .get(agent) + .internal_get_own_property(agent, r, gc.reborrow())?; if let Some(desc) = desc { self.visited_keys.push(r); if desc.enumerable == Some(true) { @@ -238,10 +238,12 @@ impl ObjectPropertiesIterator { } } // TODO: Properly handle potential GC. - let prototype = object.internal_get_prototype_of(agent, gc.reborrow())?; + let prototype = object + .get(agent) + .internal_get_prototype_of(agent, gc.reborrow())?; if let Some(prototype) = prototype { self.object_was_visited = false; - self.object = prototype; + self.object = prototype.unbind(); } else { return Ok(None); } @@ -264,11 +266,7 @@ impl ArrayValuesIterator { } } - pub(super) fn next( - &mut self, - agent: &mut Agent, - gc: GcScope<'_, '_>, - ) -> JsResult> { + pub(super) fn next(&mut self, agent: &mut Agent, gc: GcScope) -> JsResult> { // b. Repeat, let array = self.array; // iv. Let indexNumber be ๐”ฝ(index). diff --git a/nova_vm/src/engine/bytecode/vm.rs b/nova_vm/src/engine/bytecode/vm.rs index d42e7251e..fb98d4a7d 100644 --- a/nova_vm/src/engine/bytecode/vm.rs +++ b/nova_vm/src/engine/bytecode/vm.rs @@ -156,7 +156,7 @@ impl SuspendedVm { agent: &mut Agent, executable: Executable, value: Value, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> ExecutionResult { let vm = Vm::from_suspended(self); vm.resume(agent, executable, value, gc) @@ -167,7 +167,7 @@ impl SuspendedVm { agent: &mut Agent, executable: Executable, err: Value, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> ExecutionResult { // Optimisation: Avoid unsuspending the Vm if we're just going to throw // out of it immediately. @@ -224,7 +224,7 @@ impl<'a> Vm { agent: &mut Agent, executable: Executable, arguments: Option<&[Value]>, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> ExecutionResult { let mut vm = Vm::new(); @@ -258,7 +258,7 @@ impl<'a> Vm { agent: &mut Agent, executable: Executable, value: Value, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> ExecutionResult { self.result = Some(value); self.inner_execute(agent, executable, gc) @@ -269,7 +269,7 @@ impl<'a> Vm { agent: &mut Agent, executable: Executable, err: Value, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> ExecutionResult { let err = JsError::new(err); if !self.handle_error(agent, err) { @@ -441,7 +441,9 @@ impl<'a> Vm { vm.result = Some(match env_rec { EnvironmentIndex::Declarative(_) => unreachable!(), EnvironmentIndex::Function(idx) => idx.get_this_binding(agent, gc.nogc())?, - EnvironmentIndex::Global(idx) => idx.get_this_binding(agent).into_value(), + EnvironmentIndex::Global(idx) => { + idx.get_this_binding(agent, gc.nogc()).into_value() + } EnvironmentIndex::Object(_) => unreachable!(), }); } @@ -838,6 +840,7 @@ impl<'a> Vm { agent, Some(ProtoIntrinsics::Object), None, + gc.nogc(), ); vm.stack.push(object.into()) } @@ -1018,7 +1021,7 @@ impl<'a> Vm { } set_function_name(agent, function, name, None, gc.nogc()); if !function_expression.r#async && !function_expression.generator { - make_constructor(agent, function, None, None); + make_constructor(agent, function, None, None, gc.nogc()); } if function_expression.generator { @@ -1036,6 +1039,7 @@ impl<'a> Vm { .generator_prototype() .into_object(), ), + gc.nogc(), ); // 8. Perform ! DefinePropertyOrThrow(F, "prototype", PropertyDescriptor { [[Value]]: prototype, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false }). unwrap_try(try_define_property_or_throw( @@ -1124,7 +1128,7 @@ impl<'a> Vm { agent[function].compiled_bytecode = Some(compiled_bytecode); } set_function_name(agent, function, class_name.into(), None, gc.nogc()); - make_constructor(agent, function, Some(false), Some(proto)); + make_constructor(agent, function, Some(false), Some(proto), gc.nogc()); agent[function].ecmascript_function.home_object = Some(proto.into_object()); agent[function].ecmascript_function.constructor_status = if has_constructor_parent || is_null_derived_class { @@ -1406,11 +1410,13 @@ impl<'a> Vm { // 6. Let result be ? Construct(func, argList, newTarget). let result = construct( agent, - func, + func.unbind(), Some(ArgumentsList(&arg_list)), Some(new_target), gc.reborrow(), - )?; + )? + .unbind() + .bind(gc.nogc()); // 7. Let thisER be GetThisEnvironment(). let EnvironmentIndex::Function(this_er) = get_this_environment(agent) else { unreachable!(); @@ -1826,7 +1832,14 @@ impl<'a> Vm { None }; let object = to_object(agent, vm.stack.pop().unwrap(), gc.nogc())?; - execute_simple_object_binding(agent, vm, executable, object, env, gc.reborrow())? + execute_simple_object_binding( + agent, + vm, + executable, + object.unbind(), + env, + gc.reborrow(), + )? } Instruction::BindingPatternBind | Instruction::BindingPatternBindNamed @@ -1885,7 +1898,7 @@ impl<'a> Vm { // TODO: Is this relevant? // i. Set ref.[[ReferencedName]] to ? ToPropertyKey(ref.[[ReferencedName]]). // e. Let deleteStatus be ? baseObj.[[Delete]](ref.[[ReferencedName]]). - let delete_status = base_obj.internal_delete( + let delete_status = base_obj.unbind().internal_delete( agent, refer.referenced_name, gc.reborrow(), @@ -2018,8 +2031,9 @@ impl<'a> Vm { let Some(VmIterator::SliceIterator(slice)) = vm.iterator_stack.last() else { unreachable!() }; - vm.result = - Some(create_unmapped_arguments_object(agent, slice.get(), gc).into_value()); + vm.result = Some( + create_unmapped_arguments_object(agent, slice.get(), gc.nogc()).into_value(), + ); } other => todo!("{other:?}"), } @@ -2057,7 +2071,7 @@ fn apply_string_or_numeric_binary_operator( lval: Value, op_text: BinaryOperator, rval: Value, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { let mut lnum: Numeric; let rnum: Numeric; @@ -2322,7 +2336,7 @@ pub(crate) fn instanceof_operator( agent: &mut Agent, value: impl IntoValue, target: impl IntoValue, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult { // 1. If target is not an Object, throw a TypeError exception. let Ok(target) = Object::try_from(target.into_value()) else { diff --git a/nova_vm/src/engine/bytecode/vm/binding_methods.rs b/nova_vm/src/engine/bytecode/vm/binding_methods.rs index 154e9d62b..2ce0dd43e 100644 --- a/nova_vm/src/engine/bytecode/vm/binding_methods.rs +++ b/nova_vm/src/engine/bytecode/vm/binding_methods.rs @@ -28,7 +28,7 @@ pub(super) fn execute_simple_array_binding( executable: Executable, mut iterator: VmIterator, environment: Option, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult<()> { let mut iterator_is_done = false; @@ -132,8 +132,9 @@ pub(super) fn execute_simple_object_binding( executable: Executable, object: Object, environment: Option, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult<()> { + let object = object.scope(agent, gc.nogc()); let mut excluded_names = AHashSet::new(); loop { @@ -158,7 +159,12 @@ pub(super) fn execute_simple_object_binding( let property_key = property_key.unbind(); let lhs = resolve_binding(agent, binding_id.unbind(), environment, gc.reborrow())? .unbind(); - let v = get(agent, object, property_key.unbind(), gc.reborrow())?; + let v = get( + agent, + object.get(agent), + property_key.unbind(), + gc.reborrow(), + )?; if environment.is_none() { put_value(agent, &lhs, v, gc.reborrow())?; } else { @@ -176,7 +182,12 @@ pub(super) fn execute_simple_object_binding( }; excluded_names.insert(property_key.unbind()); - let v = get(agent, object, property_key.unbind(), gc.reborrow())?; + let v = get( + agent, + object.get(agent), + property_key.unbind(), + gc.reborrow(), + )?; execute_nested_simple_binding( agent, vm, @@ -198,7 +209,7 @@ pub(super) fn execute_simple_object_binding( // 3. Perform ? CopyDataProperties(restObj, value, excludedNames). let rest_obj = copy_data_properties_into_object( agent, - object, + object.get(agent), &excluded_names, gc.reborrow(), )? @@ -225,7 +236,7 @@ pub(super) fn execute_nested_simple_binding( executable: Executable, value: Value, environment: Option, - mut gc: GcScope<'_, '_>, + mut gc: GcScope, ) -> JsResult<()> { let instr = executable.get_instruction(agent, &mut vm.ip).unwrap(); match instr.kind { @@ -242,7 +253,14 @@ pub(super) fn execute_nested_simple_binding( } Instruction::BeginSimpleObjectBindingPattern => { let object = to_object(agent, value, gc.nogc())?; - execute_simple_object_binding(agent, vm, executable, object, environment, gc.reborrow()) + execute_simple_object_binding( + agent, + vm, + executable, + object.unbind(), + environment, + gc.reborrow(), + ) } _ => unreachable!(), } diff --git a/nova_vm/src/engine/rootable.rs b/nova_vm/src/engine/rootable.rs index cbccc1829..b1ff0c63d 100644 --- a/nova_vm/src/engine/rootable.rs +++ b/nova_vm/src/engine/rootable.rs @@ -142,7 +142,7 @@ mod private { impl RootableSealed for Module<'_> {} impl RootableSealed for Number<'_> {} impl RootableSealed for Numeric<'_> {} - impl RootableSealed for Object {} + impl RootableSealed for Object<'_> {} impl RootableSealed for OrdinaryObject<'_> {} impl RootableSealed for Primitive<'_> {} impl RootableSealed for PrimitiveObject<'_> {} @@ -194,7 +194,9 @@ pub trait Rootable: std::fmt::Debug + Copy + RootableSealed { } // Blanket impl for Objects -impl> Rootable for T { +impl<'a, T: std::fmt::Debug + RootableSealed + IntoObject<'a> + TryFrom> Rootable + for T +{ type RootRepr = HeapRootRef; #[inline] @@ -315,9 +317,9 @@ pub enum HeapRootData { // these in alphabetical order. } -impl From for HeapRootData { +impl From> for HeapRootData { #[inline] - fn from(value: Object) -> Self { + fn from(value: Object<'static>) -> Self { match value { Object::Object(ordinary_object) => Self::Object(ordinary_object), Object::BoundFunction(bound_function) => Self::BoundFunction(bound_function), diff --git a/nova_vm/src/engine/rootable/global.rs b/nova_vm/src/engine/rootable/global.rs index b20530263..d62406fa1 100644 --- a/nova_vm/src/engine/rootable/global.rs +++ b/nova_vm/src/engine/rootable/global.rs @@ -74,7 +74,7 @@ impl Global { /// Access the rooted value from inside this Global without releasing the /// Global. - pub fn get(&self, agent: &mut Agent, _: GcScope<'_, '_>) -> T { + pub fn get(&self, agent: &mut Agent, _: GcScope) -> T { let heap_ref = match T::from_root_repr(&self.0) { Ok(value) => { // The value didn't need rooting @@ -100,7 +100,7 @@ impl Global { /// original Global and the cloned one must be explicitly released before /// the rooted value can be garbage collected. #[must_use] - pub fn clone(&self, agent: &mut Agent, gc: GcScope<'_, '_>) -> Self { + pub fn clone(&self, agent: &mut Agent, gc: GcScope) -> Self { let value = self.get(agent, gc); Self::new(agent, value) } diff --git a/nova_vm/src/heap.rs b/nova_vm/src/heap.rs index d0f8cd428..46e74ba28 100644 --- a/nova_vm/src/heap.rs +++ b/nova_vm/src/heap.rs @@ -404,7 +404,7 @@ impl Heap { extensible: true, keys, values, - prototype: Some(prototype), + prototype: Some(prototype.unbind()), }; self.objects.push(Some(object_data)); ObjectIndex::last(&self.objects).into() diff --git a/nova_vm/src/heap/heap_gc.rs b/nova_vm/src/heap/heap_gc.rs index 5cab202a1..789de7c8c 100644 --- a/nova_vm/src/heap/heap_gc.rs +++ b/nova_vm/src/heap/heap_gc.rs @@ -71,7 +71,7 @@ use crate::{ pub fn heap_gc( agent: &mut Agent, root_realms: &mut [Option], - gc: GcScope<'_, '_>, + gc: GcScope, ) { let Agent { heap, @@ -1003,7 +1003,7 @@ fn sweep( agent: &mut Agent, bits: &HeapBits, root_realms: &mut [Option], - _: GcScope<'_, '_>, + _: GcScope, ) { let compactions = CompactionLists::create_from_bits(bits); diff --git a/nova_vm/src/heap/indexes.rs b/nova_vm/src/heap/indexes.rs index 525389c38..e93da4dd3 100644 --- a/nova_vm/src/heap/indexes.rs +++ b/nova_vm/src/heap/indexes.rs @@ -42,7 +42,7 @@ use crate::{ StringHeapData, SymbolHeapData, Value, }, }, - engine::context::GcToken, + engine::context::{GcToken, NoGcScope}, }; use core::fmt::Debug; use std::{ @@ -228,6 +228,28 @@ pub type WeakRefIndex<'a> = BaseIndex<'a, WeakRefHeapData>; #[cfg(feature = "weak-refs")] pub type WeakSetIndex<'a> = BaseIndex<'a, WeakSetHeapData>; +impl TypedArrayIndex<'_> { + /// Unbind this TypedArrayIndex from its current lifetime. This is necessary to use + /// the TypedArrayIndex as a parameter in a call that can perform garbage + /// collection. + pub fn unbind(self) -> TypedArrayIndex<'static> { + unsafe { std::mem::transmute::>(self) } + } + + // Bind this TypedArrayIndex to the garbage collection lifetime. This enables Rust's + // borrow checker to verify that your TypedArrayIndexs cannot not be invalidated by + // garbage collection being performed. + // + // This function is best called with the form + // ```rs + // let ta_idx = ta_idx.bind(&gc); + // ``` + // to make sure that the unbound TypedArrayIndex cannot be used after binding. + pub const fn bind<'gc>(self, _: NoGcScope<'gc, '_>) -> TypedArrayIndex<'gc> { + unsafe { std::mem::transmute::>(self) } + } +} + // Implement Default for ElementIndex: This is done to support Default // constructor of ElementsVector. impl Default for ElementIndex { diff --git a/nova_vm/tests/garbage_collection_tests.rs b/nova_vm/tests/garbage_collection_tests.rs index 329d390d5..9eed0076d 100644 --- a/nova_vm/tests/garbage_collection_tests.rs +++ b/nova_vm/tests/garbage_collection_tests.rs @@ -12,7 +12,7 @@ use nova_vm::{ engine::context::GcScope, }; -fn initialize_global_object(agent: &mut Agent, global: Object, gc: GcScope<'_, '_>) { +fn initialize_global_object(agent: &mut Agent, global: Object, gc: GcScope) { use nova_vm::ecmascript::{ builtins::{create_builtin_function, ArgumentsList, Behaviour, BuiltinFunctionArgs}, execution::JsResult, @@ -24,7 +24,7 @@ fn initialize_global_object(agent: &mut Agent, global: Object, gc: GcScope<'_, ' agent: &mut Agent, _this: Value, args: ArgumentsList, - gc: GcScope<'_, '_>, + gc: GcScope, ) -> JsResult { if args.len() == 0 { println!(); @@ -77,8 +77,9 @@ fn garbage_collection_tests() { fs::read_to_string(d.clone()).expect("Should have been able to read the file"); let mut agent = GcAgent::new(Options::default(), &DefaultHostHooks); - let create_global_object: Option) -> Object> = None; - let create_global_this_value: Option) -> Object> = None; + let create_global_object: Option fn(&mut Agent, GcScope<'a, '_>) -> Object<'a>> = None; + let create_global_this_value: Option fn(&mut Agent, GcScope<'a, '_>) -> Object<'a>> = + None; let realm = agent.create_realm( create_global_object, create_global_this_value,