mirror of
https://github.com/denoland/deno.git
synced 2024-11-25 15:29:32 -05:00
9c5928b5aa
This commit fixes and edge case, where testing/benching code could pledge new permission set before restoring the previous pledge. Appropriate panics were added and tests that assert that process is killed in case of "recursive pledge".
117 lines
3 KiB
Rust
117 lines
3 KiB
Rust
use crate::tools::bench::BenchEvent;
|
|
use deno_core::error::generic_error;
|
|
use deno_core::error::AnyError;
|
|
use deno_core::op;
|
|
use deno_core::Extension;
|
|
use deno_core::ModuleSpecifier;
|
|
use deno_core::OpState;
|
|
use deno_runtime::permissions::create_child_permissions;
|
|
use deno_runtime::permissions::ChildPermissionsArg;
|
|
use deno_runtime::permissions::Permissions;
|
|
use std::time;
|
|
use tokio::sync::mpsc::UnboundedSender;
|
|
use uuid::Uuid;
|
|
|
|
pub fn init(sender: UnboundedSender<BenchEvent>, unstable: bool) -> Extension {
|
|
Extension::builder()
|
|
.ops(vec![
|
|
op_pledge_test_permissions::decl(),
|
|
op_restore_test_permissions::decl(),
|
|
op_get_bench_origin::decl(),
|
|
op_dispatch_bench_event::decl(),
|
|
op_bench_now::decl(),
|
|
op_bench_check_unstable::decl(),
|
|
])
|
|
.state(move |state| {
|
|
state.put(sender.clone());
|
|
state.put(Unstable(unstable));
|
|
Ok(())
|
|
})
|
|
.build()
|
|
}
|
|
|
|
pub struct Unstable(pub bool);
|
|
|
|
fn check_unstable(state: &OpState, api_name: &str) {
|
|
let unstable = state.borrow::<Unstable>();
|
|
|
|
if !unstable.0 {
|
|
eprintln!(
|
|
"Unstable API '{}'. The --unstable flag must be provided.",
|
|
api_name
|
|
);
|
|
std::process::exit(70);
|
|
}
|
|
}
|
|
|
|
#[op]
|
|
fn op_bench_check_unstable(state: &mut OpState) -> Result<(), AnyError> {
|
|
check_unstable(state, "Deno.bench");
|
|
Ok(())
|
|
}
|
|
|
|
#[derive(Clone)]
|
|
struct PermissionsHolder(Uuid, Permissions);
|
|
|
|
#[op]
|
|
pub fn op_pledge_test_permissions(
|
|
state: &mut OpState,
|
|
args: ChildPermissionsArg,
|
|
) -> Result<Uuid, AnyError> {
|
|
let token = Uuid::new_v4();
|
|
let parent_permissions = state.borrow_mut::<Permissions>();
|
|
let worker_permissions = create_child_permissions(parent_permissions, args)?;
|
|
let parent_permissions = parent_permissions.clone();
|
|
|
|
if state.try_take::<PermissionsHolder>().is_some() {
|
|
panic!("pledge test permissions called before restoring previous pledge");
|
|
}
|
|
|
|
state.put::<PermissionsHolder>(PermissionsHolder(token, parent_permissions));
|
|
|
|
// NOTE: This call overrides current permission set for the worker
|
|
state.put::<Permissions>(worker_permissions);
|
|
|
|
Ok(token)
|
|
}
|
|
|
|
#[op]
|
|
pub fn op_restore_test_permissions(
|
|
state: &mut OpState,
|
|
token: Uuid,
|
|
) -> Result<(), AnyError> {
|
|
if let Some(permissions_holder) = state.try_take::<PermissionsHolder>() {
|
|
if token != permissions_holder.0 {
|
|
panic!("restore test permissions token does not match the stored token");
|
|
}
|
|
|
|
let permissions = permissions_holder.1;
|
|
state.put::<Permissions>(permissions);
|
|
Ok(())
|
|
} else {
|
|
Err(generic_error("no permissions to restore"))
|
|
}
|
|
}
|
|
|
|
#[op]
|
|
fn op_get_bench_origin(state: &mut OpState) -> Result<String, AnyError> {
|
|
Ok(state.borrow::<ModuleSpecifier>().to_string())
|
|
}
|
|
|
|
#[op]
|
|
fn op_dispatch_bench_event(
|
|
state: &mut OpState,
|
|
event: BenchEvent,
|
|
) -> Result<(), AnyError> {
|
|
let sender = state.borrow::<UnboundedSender<BenchEvent>>().clone();
|
|
sender.send(event).ok();
|
|
|
|
Ok(())
|
|
}
|
|
|
|
#[op]
|
|
fn op_bench_now(state: &mut OpState) -> Result<u64, AnyError> {
|
|
let ns = state.borrow::<time::Instant>().elapsed().as_nanos();
|
|
let ns_u64 = u64::try_from(ns)?;
|
|
Ok(ns_u64)
|
|
}
|