summaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
Diffstat (limited to 'core')
-rw-r--r--core/async_cancel.rs25
-rw-r--r--core/async_cell.rs34
-rw-r--r--core/bindings.rs4
-rw-r--r--core/inspector.rs13
-rw-r--r--core/modules.rs1
-rw-r--r--core/ops.rs2
-rw-r--r--core/ops_metrics.rs5
-rw-r--r--core/resources.rs2
-rw-r--r--core/runtime.rs5
9 files changed, 86 insertions, 5 deletions
diff --git a/core/async_cancel.rs b/core/async_cancel.rs
index cf338174d..55ab8f4d1 100644
--- a/core/async_cancel.rs
+++ b/core/async_cancel.rs
@@ -302,13 +302,19 @@ mod internal {
Some((head, rc)) => {
// Register this `Cancelable` node with a `CancelHandle` head node.
assert_ne!(self, head);
+ // TODO(piscisaureus): safety comment
+ #[allow(clippy::undocumented_unsafe_blocks)]
let self_inner = unsafe { &mut *self.inner.get() };
+ // TODO(piscisaureus): safety comment
+ #[allow(clippy::undocumented_unsafe_blocks)]
let head_inner = unsafe { &mut *head.inner.get() };
self_inner.link(waker, head_inner, rc)
}
None => {
// This `Cancelable` has already been linked to a `CancelHandle` head
// node; just update our stored `Waker` if necessary.
+ // TODO(piscisaureus): safety comment
+ #[allow(clippy::undocumented_unsafe_blocks)]
let inner = unsafe { &mut *self.inner.get() };
inner.update_waker(waker)
}
@@ -316,11 +322,15 @@ mod internal {
}
pub fn cancel(&self) {
+ // TODO(piscisaureus): safety comment
+ #[allow(clippy::undocumented_unsafe_blocks)]
let inner = unsafe { &mut *self.inner.get() };
inner.cancel();
}
pub fn is_canceled(&self) -> bool {
+ // TODO(piscisaureus): safety comment
+ #[allow(clippy::undocumented_unsafe_blocks)]
let inner = unsafe { &mut *self.inner.get() };
inner.is_canceled()
}
@@ -337,6 +347,8 @@ mod internal {
impl Drop for Node {
fn drop(&mut self) {
+ // TODO(piscisaureus): safety comment
+ #[allow(clippy::undocumented_unsafe_blocks)]
let inner = unsafe { &mut *self.inner.get() };
inner.unlink();
}
@@ -392,6 +404,8 @@ mod internal {
prev: next_prev_nn,
..
} => {
+ // TODO(piscisaureus): safety comment
+ #[allow(clippy::undocumented_unsafe_blocks)]
let prev = unsafe { &mut *next_prev_nn.as_ptr() };
match prev {
NodeInner::Linked {
@@ -444,10 +458,14 @@ mod internal {
if prev_nn == next_nn {
// There were only two nodes in this chain; after unlinking ourselves
// the other node is no longer linked.
+ // TODO(piscisaureus): safety comment
+ #[allow(clippy::undocumented_unsafe_blocks)]
let other = unsafe { prev_nn.as_mut() };
*other = NodeInner::Unlinked;
} else {
// The chain had more than two nodes.
+ // TODO(piscisaureus): safety comment
+ #[allow(clippy::undocumented_unsafe_blocks)]
match unsafe { prev_nn.as_mut() } {
NodeInner::Linked {
next: prev_next_nn, ..
@@ -456,6 +474,8 @@ mod internal {
}
_ => unreachable!(),
}
+ // TODO(piscisaureus): safety comment
+ #[allow(clippy::undocumented_unsafe_blocks)]
match unsafe { next_nn.as_mut() } {
NodeInner::Linked {
prev: next_prev_nn, ..
@@ -473,6 +493,8 @@ mod internal {
fn cancel(&mut self) {
let mut head_nn = NonNull::from(self);
+ // TODO(piscisaureus): safety comment
+ #[allow(clippy::undocumented_unsafe_blocks)]
// Mark the head node as canceled.
let mut item_nn =
match replace(unsafe { head_nn.as_mut() }, NodeInner::Canceled) {
@@ -487,6 +509,8 @@ mod internal {
// Cancel all item nodes in the chain, waking each stored `Waker`.
while item_nn != head_nn {
+ // TODO(piscisaureus): safety comment
+ #[allow(clippy::undocumented_unsafe_blocks)]
match replace(unsafe { item_nn.as_mut() }, NodeInner::Canceled) {
NodeInner::Linked {
kind: NodeKind::Item { waker },
@@ -745,6 +769,7 @@ mod tests {
assert!(Rc::get_mut(&mut cancel_handle).is_some());
let mut future = pending::<Never>().or_cancel(&cancel_handle);
+ // SAFETY: `Cancelable` pins the future
let future = unsafe { Pin::new_unchecked(&mut future) };
// There are two `Rc<CancelHandle>` references now, so this fails.
diff --git a/core/async_cell.rs b/core/async_cell.rs
index 8798861cf..ea6cac831 100644
--- a/core/async_cell.rs
+++ b/core/async_cell.rs
@@ -157,12 +157,16 @@ impl<T: 'static> RcRef<T> {
map_fn: F,
) -> RcRef<T> {
let RcRef::<S> { rc, value } = source.into();
+ // TODO(piscisaureus): safety comment
+ #[allow(clippy::undocumented_unsafe_blocks)]
let value = map_fn(unsafe { &*value });
RcRef { rc, value }
}
pub(crate) fn split(rc_ref: &Self) -> (&T, &Rc<dyn Any>) {
let &Self { ref rc, value } = rc_ref;
+ // TODO(piscisaureus): safety comment
+ #[allow(clippy::undocumented_unsafe_blocks)]
(unsafe { &*value }, rc)
}
}
@@ -206,7 +210,11 @@ impl<T: 'static> From<&Rc<T>> for RcRef<T> {
impl<T> Deref for RcRef<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
- unsafe { &*self.value }
+ // TODO(piscisaureus): safety comment
+ #[allow(clippy::undocumented_unsafe_blocks)]
+ unsafe {
+ &*self.value
+ }
}
}
@@ -260,6 +268,8 @@ mod internal {
// Don't allow synchronous borrows to cut in line; if there are any
// enqueued waiters, return `None`, even if the current borrow is a shared
// one and the requested borrow is too.
+ // TODO(piscisaureus): safety comment
+ #[allow(clippy::undocumented_unsafe_blocks)]
let waiters = unsafe { &mut *cell_ref.waiters.as_ptr() };
if waiters.is_empty() {
// There are no enqueued waiters, but it is still possible that the cell
@@ -288,6 +298,8 @@ mod internal {
let waiter = Waiter::new(M::borrow_mode());
let turn = self.turn.get();
let index = {
+ // TODO(piscisaureus): safety comment
+ #[allow(clippy::undocumented_unsafe_blocks)]
let waiters = unsafe { &mut *self.waiters.as_ptr() };
waiters.push_back(Some(waiter));
waiters.len() - 1
@@ -315,6 +327,8 @@ mod internal {
Poll::Ready(())
} else {
// This waiter is still in line and has not yet been woken.
+ // TODO(piscisaureus): safety comment
+ #[allow(clippy::undocumented_unsafe_blocks)]
let waiters = unsafe { &mut *self.waiters.as_ptr() };
// Sanity check: id cannot be higher than the last queue element.
assert!(id < turn + waiters.len());
@@ -330,6 +344,8 @@ mod internal {
fn wake_waiters(&self) {
let mut borrow_count = self.borrow_count.get();
+ // TODO(piscisaureus): safety comment
+ #[allow(clippy::undocumented_unsafe_blocks)]
let waiters = unsafe { &mut *self.waiters.as_ptr() };
let mut turn = self.turn.get();
@@ -379,6 +395,8 @@ mod internal {
self.drop_borrow::<M>();
} else {
// This waiter is still in the queue, take it out and leave a "hole".
+ // TODO(piscisaureus): safety comment
+ #[allow(clippy::undocumented_unsafe_blocks)]
let waiters = unsafe { &mut *self.waiters.as_ptr() };
waiters[id - turn].take().unwrap();
}
@@ -411,6 +429,8 @@ mod internal {
type Output = AsyncBorrowImpl<T, M>;
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
ready!(self.cell.as_ref().unwrap().poll_waiter::<M>(self.id, cx));
+ // TODO(piscisaureus): safety comment
+ #[allow(clippy::undocumented_unsafe_blocks)]
let self_mut = unsafe { Pin::get_unchecked_mut(self) };
let cell = self_mut.cell.take().unwrap();
Poll::Ready(AsyncBorrowImpl::<T, M>::new(cell))
@@ -448,7 +468,11 @@ mod internal {
impl<T, M: BorrowModeTrait> Deref for AsyncBorrowImpl<T, M> {
type Target = T;
fn deref(&self) -> &Self::Target {
- unsafe { &*self.cell.as_ptr() }
+ // TODO(piscisaureus): safety comment
+ #[allow(clippy::undocumented_unsafe_blocks)]
+ unsafe {
+ &*self.cell.as_ptr()
+ }
}
}
@@ -466,7 +490,11 @@ mod internal {
impl<T> DerefMut for AsyncBorrowImpl<T, Exclusive> {
fn deref_mut(&mut self) -> &mut Self::Target {
- unsafe { &mut *self.cell.as_ptr() }
+ // TODO(piscisaureus): safety comment
+ #[allow(clippy::undocumented_unsafe_blocks)]
+ unsafe {
+ &mut *self.cell.as_ptr()
+ }
}
}
diff --git a/core/bindings.rs b/core/bindings.rs
index 5681ded31..a88e54af7 100644
--- a/core/bindings.rs
+++ b/core/bindings.rs
@@ -147,6 +147,7 @@ pub extern "C" fn host_import_module_dynamically_callback(
specifier: v8::Local<v8::String>,
import_assertions: v8::Local<v8::FixedArray>,
) -> *mut v8::Promise {
+ // SAFETY: `CallbackScope` can be safely constructed from `Local<Context>`
let scope = &mut unsafe { v8::CallbackScope::new(context) };
// NOTE(bartlomieju): will crash for non-UTF-8 specifier
@@ -253,6 +254,7 @@ pub extern "C" fn host_initialize_import_meta_object_callback(
module: v8::Local<v8::Module>,
meta: v8::Local<v8::Object>,
) {
+ // SAFETY: `CallbackScope` can be safely constructed from `Local<Context>`
let scope = &mut unsafe { v8::CallbackScope::new(context) };
let module_map_rc = JsRuntime::module_map(scope);
let module_map = module_map_rc.borrow();
@@ -274,6 +276,7 @@ pub extern "C" fn host_initialize_import_meta_object_callback(
pub extern "C" fn promise_reject_callback(message: v8::PromiseRejectMessage) {
use v8::PromiseRejectEvent::*;
+ // SAFETY: `CallbackScope` can be safely constructed from `&PromiseRejectMessage`
let scope = &mut unsafe { v8::CallbackScope::new(&message) };
let state_rc = JsRuntime::state(scope);
@@ -418,6 +421,7 @@ pub fn module_resolve_callback<'s>(
import_assertions: v8::Local<'s, v8::FixedArray>,
referrer: v8::Local<'s, v8::Module>,
) -> Option<v8::Local<'s, v8::Module>> {
+ // SAFETY: `CallbackScope` can be safely constructed from `Local<Context>`
let scope = &mut unsafe { v8::CallbackScope::new(context) };
let module_map_rc = JsRuntime::module_map(scope);
diff --git a/core/inspector.rs b/core/inspector.rs
index 26855acdf..bec22d257 100644
--- a/core/inspector.rs
+++ b/core/inspector.rs
@@ -485,6 +485,8 @@ impl task::ArcWake for InspectorWaker {
_isolate: &mut v8::Isolate,
arg: *mut c_void,
) {
+ // SAFETY: `InspectorWaker` is owned by `JsRuntimeInspector`, so the
+ // pointer to the latter is valid as long as waker is alive.
let inspector = unsafe { &*(arg as *mut JsRuntimeInspector) };
let _ = inspector.poll_sessions(None);
}
@@ -521,6 +523,8 @@ impl InspectorSession {
let v8_channel = v8::inspector::ChannelBase::new::<Self>();
let mut v8_inspector = v8_inspector_rc.borrow_mut();
let v8_inspector_ptr = v8_inspector.as_mut().unwrap();
+ // TODO(piscisaureus): safety comment
+ #[allow(clippy::undocumented_unsafe_blocks)]
let v8_session = v8_inspector_ptr.connect(
Self::CONTEXT_GROUP_ID,
// Todo(piscisaureus): V8Inspector::connect() should require that
@@ -544,6 +548,8 @@ impl InspectorSession {
msg: String,
) {
let msg = v8::inspector::StringView::from(msg.as_bytes());
+ // SAFETY: `InspectorSession` is the only owner of `v8_session_ptr`, so
+ // the pointer is valid for as long the struct.
unsafe {
(*v8_session_ptr).dispatch_protocol_message(msg);
};
@@ -731,6 +737,9 @@ impl LocalInspectorSession {
fn new_box_with<T>(new_fn: impl FnOnce(*mut T) -> T) -> Box<T> {
let b = Box::new(MaybeUninit::<T>::uninit());
let p = Box::into_raw(b) as *mut T;
- unsafe { ptr::write(p, new_fn(p)) };
- unsafe { Box::from_raw(p) }
+ // SAFETY: memory layout for `T` is ensured on first line of this function
+ unsafe {
+ ptr::write(p, new_fn(p));
+ Box::from_raw(p)
+ }
}
diff --git a/core/modules.rs b/core/modules.rs
index e86fdbf73..aec8c498f 100644
--- a/core/modules.rs
+++ b/core/modules.rs
@@ -122,6 +122,7 @@ fn json_module_evaluation_steps<'a>(
context: v8::Local<'a, v8::Context>,
module: v8::Local<v8::Module>,
) -> Option<v8::Local<'a, v8::Value>> {
+ // SAFETY: `CallbackScope` can be safely constructed from `Local<Context>`
let scope = &mut unsafe { v8::CallbackScope::new(context) };
let tc_scope = &mut v8::TryCatch::new(scope);
let module_map = tc_scope
diff --git a/core/ops.rs b/core/ops.rs
index a2833e811..3d0d0ec70 100644
--- a/core/ops.rs
+++ b/core/ops.rs
@@ -63,6 +63,8 @@ impl<T> Future for OpCall<T> {
self: std::pin::Pin<&mut Self>,
cx: &mut std::task::Context<'_>,
) -> std::task::Poll<Self::Output> {
+ // TODO(piscisaureus): safety comment
+ #[allow(clippy::undocumented_unsafe_blocks)]
let inner = unsafe { &mut self.get_unchecked_mut().0 };
let mut pinned = Pin::new(inner);
ready!(pinned.as_mut().poll(cx));
diff --git a/core/ops_metrics.rs b/core/ops_metrics.rs
index b068aa0ee..aa3ff503b 100644
--- a/core/ops_metrics.rs
+++ b/core/ops_metrics.rs
@@ -56,12 +56,17 @@ impl OpsTracker {
#[allow(clippy::mut_from_ref)]
#[inline]
fn ops_mut(&self) -> &mut Vec<OpMetrics> {
+ // SAFETY: `OpsTracker` is created after registering ops so it is guaranteed
+ // that that `ops` will be initialized.
unsafe { &mut *self.ops.get() }
}
#[allow(clippy::mut_from_ref)]
#[inline]
fn metrics_mut(&self, id: OpId) -> &mut OpMetrics {
+ // SAFETY: `OpsTracker` is created after registering ops, and ops
+ // cannot be unregistered during runtime, so it is guaranteed that `id`
+ // is not causing out-of-bound access.
unsafe { self.ops_mut().get_unchecked_mut(id) }
}
diff --git a/core/resources.rs b/core/resources.rs
index ae4ef7394..a4bb3607d 100644
--- a/core/resources.rs
+++ b/core/resources.rs
@@ -77,6 +77,8 @@ impl dyn Resource {
pub fn downcast_rc<'a, T: Resource>(self: &'a Rc<Self>) -> Option<&'a Rc<T>> {
if self.is::<T>() {
let ptr = self as *const Rc<_> as *const Rc<T>;
+ // TODO(piscisaureus): safety comment
+ #[allow(clippy::undocumented_unsafe_blocks)]
Some(unsafe { &*ptr })
} else {
None
diff --git a/core/runtime.rs b/core/runtime.rs
index f82f06207..7cb556fd3 100644
--- a/core/runtime.rs
+++ b/core/runtime.rs
@@ -333,6 +333,9 @@ impl JsRuntime {
assert!(options.startup_snapshot.is_none());
let mut creator =
v8::SnapshotCreator::new(Some(&bindings::EXTERNAL_REFERENCES));
+ // SAFETY: `get_owned_isolate` is unsafe because it may only be called
+ // once. This is the only place we call this function, so this call is
+ // safe.
let isolate = unsafe { creator.get_owned_isolate() };
let mut isolate = JsRuntime::setup_isolate(isolate);
{
@@ -1028,6 +1031,8 @@ extern "C" fn near_heap_limit_callback<F>(
where
F: FnMut(usize, usize) -> usize,
{
+ // SAFETY: The data is a pointer to the Rust callback function. It is stored
+ // in `JsRuntime::allocations` and thus is guaranteed to outlive the isolate.
let callback = unsafe { &mut *(data as *mut F) };
callback(current_heap_limit, initial_heap_limit)
}