mirror of
https://github.com/denoland/deno.git
synced 2025-03-03 09:31:22 -05:00
docs(core): document several concepts around JsRuntime and ops (#7897)
This commit is contained in:
parent
5f7c80986f
commit
6162807a7e
3 changed files with 96 additions and 1 deletions
48
core/ops.rs
48
core/ops.rs
|
@ -31,6 +31,7 @@ pub enum Op {
|
|||
NotFound,
|
||||
}
|
||||
|
||||
/// Maintains the resources and ops inside a JS runtime.
|
||||
pub struct OpState {
|
||||
pub resource_table: crate::ResourceTable,
|
||||
pub op_table: OpTable,
|
||||
|
@ -151,6 +152,29 @@ fn op_table() {
|
|||
)
|
||||
}
|
||||
|
||||
/// Creates an op that passes data synchronously using JSON.
|
||||
///
|
||||
/// The provided function `op_fn` has the following parameters:
|
||||
/// * `&mut OpState`: the op state, can be used to read/write resources in the runtime from an op.
|
||||
/// * `Value`: the JSON value that is passed to the Rust function.
|
||||
/// * `&mut [ZeroCopyBuf]`: raw bytes passed along, usually not needed if the JSON value is used.
|
||||
///
|
||||
/// `op_fn` returns a JSON value, which is directly returned to JavaScript.
|
||||
///
|
||||
/// When registering an op like this...
|
||||
/// ```ignore
|
||||
/// let mut runtime = JsRuntime::new(...);
|
||||
/// runtime.register_op("hello", deno_core::json_op_sync(Self::hello_op));
|
||||
/// ```
|
||||
///
|
||||
/// ...it can be invoked from JS using the provided name, for example:
|
||||
/// ```js
|
||||
/// Deno.core.ops();
|
||||
/// let result = Deno.core.jsonOpSync("function_name", args);
|
||||
/// ```
|
||||
///
|
||||
/// The `Deno.core.ops()` statement is needed once before any op calls, for initialization.
|
||||
/// A more complete example is available in the examples directory.
|
||||
pub fn json_op_sync<F>(op_fn: F) -> Box<OpFn>
|
||||
where
|
||||
F: Fn(&mut OpState, Value, &mut [ZeroCopyBuf]) -> Result<Value, AnyError>
|
||||
|
@ -166,6 +190,30 @@ where
|
|||
})
|
||||
}
|
||||
|
||||
/// Creates an op that passes data asynchronously using JSON.
|
||||
///
|
||||
/// The provided function `op_fn` has the following parameters:
|
||||
/// * `Rc<RefCell<OpState>`: the op state, can be used to read/write resources in the runtime from an op.
|
||||
/// * `Value`: the JSON value that is passed to the Rust function.
|
||||
/// * `BufVec`: raw bytes passed along, usually not needed if the JSON value is used.
|
||||
///
|
||||
/// `op_fn` returns a future, whose output is a JSON value. This value will be asynchronously
|
||||
/// returned to JavaScript.
|
||||
///
|
||||
/// When registering an op like this...
|
||||
/// ```ignore
|
||||
/// let mut runtime = JsRuntime::new(...);
|
||||
/// runtime.register_op("hello", deno_core::json_op_async(Self::hello_op));
|
||||
/// ```
|
||||
///
|
||||
/// ...it can be invoked from JS using the provided name, for example:
|
||||
/// ```js
|
||||
/// Deno.core.ops();
|
||||
/// let future = Deno.core.jsonOpAsync("function_name", args);
|
||||
/// ```
|
||||
///
|
||||
/// The `Deno.core.ops()` statement is needed once before any op calls, for initialization.
|
||||
/// A more complete example is available in the examples directory.
|
||||
pub fn json_op_async<F, R>(op_fn: F) -> Box<OpFn>
|
||||
where
|
||||
F: Fn(Rc<RefCell<OpState>>, Value, BufVec) -> R + 'static,
|
||||
|
|
|
@ -10,13 +10,21 @@ use std::any::Any;
|
|||
use std::collections::HashMap;
|
||||
|
||||
/// ResourceId is Deno's version of a file descriptor. ResourceId is also referred
|
||||
/// to as rid in the code base.
|
||||
/// to as `rid` in the code base.
|
||||
pub type ResourceId = u32;
|
||||
|
||||
/// These store Deno's file descriptors. These are not necessarily the operating
|
||||
/// system ones.
|
||||
type ResourceMap = HashMap<ResourceId, (String, Box<dyn Any>)>;
|
||||
|
||||
/// Map-like data structure storing Deno's resources (equivalent to file descriptors).
|
||||
///
|
||||
/// Provides basic methods for element access. A resource can be of any type.
|
||||
/// Different types of resources can be stored in the same map, and provided
|
||||
/// with a name for description.
|
||||
///
|
||||
/// Each resource is identified through a _resource ID (rid)_, which acts as
|
||||
/// the key in the map.
|
||||
#[derive(Default)]
|
||||
pub struct ResourceTable {
|
||||
map: ResourceMap,
|
||||
|
@ -24,15 +32,22 @@ pub struct ResourceTable {
|
|||
}
|
||||
|
||||
impl ResourceTable {
|
||||
/// Checks if the given resource ID is contained.
|
||||
pub fn has(&self, rid: ResourceId) -> bool {
|
||||
self.map.contains_key(&rid)
|
||||
}
|
||||
|
||||
/// Returns a shared reference to a resource.
|
||||
///
|
||||
/// Returns `None`, if `rid` is not stored or has a type different from `T`.
|
||||
pub fn get<T: Any>(&self, rid: ResourceId) -> Option<&T> {
|
||||
let (_, resource) = self.map.get(&rid)?;
|
||||
resource.downcast_ref::<T>()
|
||||
}
|
||||
|
||||
/// Returns a mutable reference to a resource.
|
||||
///
|
||||
/// Returns `None`, if `rid` is not stored or has a type different from `T`.
|
||||
pub fn get_mut<T: Any>(&mut self, rid: ResourceId) -> Option<&mut T> {
|
||||
let (_, resource) = self.map.get_mut(&rid)?;
|
||||
resource.downcast_mut::<T>()
|
||||
|
@ -45,6 +60,12 @@ impl ResourceTable {
|
|||
next_rid as ResourceId
|
||||
}
|
||||
|
||||
/// Inserts a resource, taking ownership of it.
|
||||
///
|
||||
/// The resource type is erased at runtime and must be statically known
|
||||
/// when retrieving it through `get()`.
|
||||
///
|
||||
/// Returns a unique resource ID, which acts as a key for this resource.
|
||||
pub fn add(&mut self, name: &str, resource: Box<dyn Any>) -> ResourceId {
|
||||
let rid = self.next_rid();
|
||||
let r = self.map.insert(rid, (name.to_string(), resource));
|
||||
|
@ -52,6 +73,10 @@ impl ResourceTable {
|
|||
rid
|
||||
}
|
||||
|
||||
/// Returns a map of resource IDs to names.
|
||||
///
|
||||
/// The name is the one specified during `add()`. To access resources themselves,
|
||||
/// use the `get()` or `get_mut()` functions.
|
||||
pub fn entries(&self) -> HashMap<ResourceId, String> {
|
||||
self
|
||||
.map
|
||||
|
@ -66,6 +91,13 @@ impl ResourceTable {
|
|||
self.map.remove(&rid).map(|(_name, _resource)| ())
|
||||
}
|
||||
|
||||
/// Removes the resource identified by `rid` and returns it.
|
||||
///
|
||||
/// When the provided `rid` is stored, the associated resource will be removed.
|
||||
/// Otherwise, nothing happens and `None` is returned.
|
||||
///
|
||||
/// If the type `T` matches the resource's type, the resource will be returned.
|
||||
/// If the type mismatches, `None` is returned, but the resource is still removed.
|
||||
pub fn remove<T: Any>(&mut self, rid: ResourceId) -> Option<Box<T>> {
|
||||
if let Some((_name, resource)) = self.map.remove(&rid) {
|
||||
let res = match resource.downcast::<T>() {
|
||||
|
|
|
@ -191,6 +191,7 @@ pub struct RuntimeOptions {
|
|||
}
|
||||
|
||||
impl JsRuntime {
|
||||
/// Only constructor, configuration is done through `options`.
|
||||
pub fn new(mut options: RuntimeOptions) -> Self {
|
||||
static DENO_INIT: Once = Once::new();
|
||||
DENO_INIT.call_once(|| {
|
||||
|
@ -320,6 +321,8 @@ impl JsRuntime {
|
|||
}
|
||||
}
|
||||
|
||||
/// Returns the runtime's op state, which can be used to maintain ops
|
||||
/// and access resources between op calls.
|
||||
pub fn op_state(&mut self) -> Rc<RefCell<OpState>> {
|
||||
let state_rc = Self::state(self.v8_isolate());
|
||||
let state = state_rc.borrow();
|
||||
|
@ -328,6 +331,9 @@ impl JsRuntime {
|
|||
|
||||
/// Executes traditional JavaScript code (traditional = not ES modules)
|
||||
///
|
||||
/// The execution takes place on the current global context, so it is possible
|
||||
/// to maintain local JS state and invoke this method multiple times.
|
||||
///
|
||||
/// `AnyError` can be downcast to a type that exposes additional information
|
||||
/// about the V8 exception. By default this type is `JsError`, however it may
|
||||
/// be a different type if `RuntimeOptions::js_error_create_fn` has been set.
|
||||
|
@ -391,6 +397,15 @@ impl JsRuntime {
|
|||
snapshot
|
||||
}
|
||||
|
||||
/// Registers an op that can be called from JavaScript.
|
||||
///
|
||||
/// The _op_ mechanism allows to expose Rust functions to the JS runtime,
|
||||
/// which can be called using the provided `name`.
|
||||
///
|
||||
/// This function provides byte-level bindings. To pass data via JSON, the
|
||||
/// following functions can be passed as an argument for `op_fn`:
|
||||
/// * [json_op_sync()](fn.json_op_sync.html)
|
||||
/// * [json_op_async()](fn.json_op_async.html)
|
||||
pub fn register_op<F>(&mut self, name: &str, op_fn: F) -> OpId
|
||||
where
|
||||
F: Fn(Rc<RefCell<OpState>>, BufVec) -> Op + 'static,
|
||||
|
|
Loading…
Add table
Reference in a new issue