feat: Implement Isolate::remove_slot (#769)

This commit is contained in:
Rami Sabbagh 2021-09-09 01:41:50 +03:00 committed by GitHub
parent b33d6ff5d3
commit 16708359bc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 60 additions and 0 deletions

View File

@ -445,6 +445,13 @@ impl Isolate {
.is_none()
}
/// Removes the embedder data added with `set_slot()` and returns it if it exists.
pub fn remove_slot<T: 'static>(&mut self) -> Option<T> {
let b = self.get_annex_mut().slots.remove(&TypeId::of::<T>())?;
let v: T = *b.downcast::<T>().unwrap();
Some(v)
}
/// Sets this isolate as the entered one for the current thread.
/// Saves the previously entered one (if any), so that it can be
/// restored when exiting. Re-entering an isolate is allowed.

View File

@ -163,3 +163,56 @@ fn slots_layer2() {
drop(es_isolate);
assert_eq!(drop_count.load(Ordering::SeqCst), 2);
}
// General test for the slots system, not specific for the Deno pattern.
struct TestState(i32);
#[test]
fn slots_general_1() {
let mut core_isolate = CoreIsolate::new(Rc::new(AtomicUsize::new(0)));
// Set a value in the slots system.
let first_add = core_isolate.set_slot::<TestState>(TestState(0));
// Verify that this was the first time a value of this type was added.
assert!(first_add);
let second_add = core_isolate.set_slot::<TestState>(TestState(1));
// Verify that the set operation cause an existing value to be replaced and dropped.
assert!(!second_add);
// Increase the value stored.
core_isolate.get_slot_mut::<TestState>().unwrap().0 += 5;
// Verify the value has changed,
// and that it was really replaced (if it were not, the result would be 5).
assert_eq!(core_isolate.get_slot::<TestState>().unwrap().0, 6);
// Remove the value out of the slot.
let value = core_isolate.remove_slot::<TestState>().unwrap();
// Verify that we got the proper value.
assert_eq!(value.0, 6);
// Verify that the slot is empty now.
assert!(core_isolate.remove_slot::<TestState>().is_none());
}
#[test]
fn slots_general_2() {
let drop_count = Rc::new(AtomicUsize::new(0));
let mut core_isolate = CoreIsolate::new(drop_count.clone());
let state: CoreIsolateState =
core_isolate.remove_slot::<CoreIsolateState>().unwrap();
drop(core_isolate);
// The state should not be dropped with the isolate because we own it now.
assert_eq!(drop_count.load(Ordering::SeqCst), 0);
// We're dropping it now on purpose.
drop(state);
assert_eq!(drop_count.load(Ordering::SeqCst), 1);
}