summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuca Casonato <hello@lcas.dev>2023-04-06 00:14:16 +0200
committerGitHub <noreply@github.com>2023-04-06 00:14:16 +0200
commit36e8c8dfd759458aa735f79f5cc7cd346c727914 (patch)
treeca8065958c406c02a8daa56f5056a658c813839f
parentee15b49845b9cbe1f8ea75372091931fa460ad0d (diff)
feat(core): sync io ops in core (#18603)
This commit adds op_read_sync and op_write_sync to core. These ops are similar to op_read and op_write, but they are synchronous. Just like the async ops, they operate on generic `deno_core::Resource` objects. These now have new `read_byob_sync` and `write_sync` methods, with default implementations throwing "NotSupported" errors, just like the async counterparts. There are no `write_all` or `read` equivalents, because the optimizations they unlock are not useful in synchronous contexts.
-rw-r--r--core/01_core.js2
-rw-r--r--core/lib.deno_core.d.ts10
-rw-r--r--core/ops_builtin.rs23
-rw-r--r--core/resources.rs12
-rw-r--r--ext/io/12_io.js16
-rw-r--r--ext/io/lib.rs68
6 files changed, 77 insertions, 54 deletions
diff --git a/core/01_core.js b/core/01_core.js
index c46c30070..ab54316e5 100644
--- a/core/01_core.js
+++ b/core/01_core.js
@@ -412,6 +412,8 @@
readAll: opAsync.bind(null, "op_read_all"),
write: opAsync.bind(null, "op_write"),
writeAll: opAsync.bind(null, "op_write_all"),
+ readSync: (rid, buffer) => ops.op_read_sync(rid, buffer),
+ writeSync: (rid, buffer) => ops.op_write_sync(rid, buffer),
shutdown: opAsync.bind(null, "op_shutdown"),
print: (msg, isErr) => ops.op_print(msg, isErr),
setMacrotaskCallback: (fn) => ops.op_set_macrotask_callback(fn),
diff --git a/core/lib.deno_core.d.ts b/core/lib.deno_core.d.ts
index b238bd6b3..7f3ea2a19 100644
--- a/core/lib.deno_core.d.ts
+++ b/core/lib.deno_core.d.ts
@@ -61,6 +61,16 @@ declare namespace Deno {
function writeAll(rid: number, buf: Uint8Array): Promise<void>;
/**
+ * Synchronously read from a (stream) resource that implements readSync().
+ */
+ function readSync(rid: number, buf: Uint8Array): number;
+
+ /**
+ * Synchronously write to a (stream) resource that implements writeSync().
+ */
+ function writeSync(rid: number, buf: Uint8Array): number;
+
+ /**
* Print a message to stdout or stderr
*/
function print(message: string, is_err?: boolean): void;
diff --git a/core/ops_builtin.rs b/core/ops_builtin.rs
index 668b44bc3..7f9c48e01 100644
--- a/core/ops_builtin.rs
+++ b/core/ops_builtin.rs
@@ -33,6 +33,8 @@ crate::extension!(
op_read,
op_read_all,
op_write,
+ op_read_sync,
+ op_write_sync,
op_write_all,
op_shutdown,
op_metrics,
@@ -279,6 +281,27 @@ async fn op_write(
Ok(resp.nwritten() as u32)
}
+#[op(fast)]
+fn op_read_sync(
+ state: &mut OpState,
+ rid: ResourceId,
+ data: &mut [u8],
+) -> Result<u32, Error> {
+ let resource = state.resource_table.get_any(rid)?;
+ resource.read_byob_sync(data).map(|n| n as u32)
+}
+
+#[op]
+fn op_write_sync(
+ state: &mut OpState,
+ rid: ResourceId,
+ data: &[u8],
+) -> Result<u32, Error> {
+ let resource = state.resource_table.get_any(rid)?;
+ let nwritten = resource.write_sync(data)?;
+ Ok(nwritten as u32)
+}
+
#[op]
async fn op_write_all(
state: Rc<RefCell<OpState>>,
diff --git a/core/resources.rs b/core/resources.rs
index 5bec68481..6ca86e10b 100644
--- a/core/resources.rs
+++ b/core/resources.rs
@@ -154,6 +154,18 @@ pub trait Resource: Any + 'static {
})
}
+ /// The same as [`read_byob()`][Resource::read_byob], but synchronous.
+ fn read_byob_sync(&self, data: &mut [u8]) -> Result<usize, Error> {
+ _ = data;
+ Err(not_supported())
+ }
+
+ /// The same as [`write()`][Resource::write], but synchronous.
+ fn write_sync(&self, data: &[u8]) -> Result<usize, Error> {
+ _ = data;
+ Err(not_supported())
+ }
+
/// The shutdown method can be used to asynchronously close the resource. It
/// is not automatically called when the resource is dropped or closed.
///
diff --git a/ext/io/12_io.js b/ext/io/12_io.js
index 2a825e7f6..1bb8f9fba 100644
--- a/ext/io/12_io.js
+++ b/ext/io/12_io.js
@@ -93,27 +93,19 @@ function* iterSync(
}
function readSync(rid, buffer) {
- if (buffer.length === 0) {
- return 0;
- }
-
- const nread = ops.op_read_sync(rid, buffer);
-
+ if (buffer.length === 0) return 0;
+ const nread = core.readSync(rid, buffer);
return nread === 0 ? null : nread;
}
async function read(rid, buffer) {
- if (buffer.length === 0) {
- return 0;
- }
-
+ if (buffer.length === 0) return 0;
const nread = await core.read(rid, buffer);
-
return nread === 0 ? null : nread;
}
function writeSync(rid, data) {
- return ops.op_write_sync(rid, data);
+ return core.writeSync(rid, data);
}
function write(rid, data) {
diff --git a/ext/io/lib.rs b/ext/io/lib.rs
index 2f2e62c11..69f8c9da5 100644
--- a/ext/io/lib.rs
+++ b/ext/io/lib.rs
@@ -78,7 +78,6 @@ pub static STDERR_HANDLE: Lazy<StdFile> = Lazy::new(|| {
deno_core::extension!(deno_io,
deps = [ deno_web ],
- ops = [op_read_sync, op_write_sync],
esm = [ "12_io.js" ],
options = {
stdio: Option<Stdio>,
@@ -454,7 +453,7 @@ impl StdFileResource {
}
fn with_inner_and_metadata<TResult>(
- self: Rc<Self>,
+ &self,
action: impl FnOnce(
&mut StdFileResourceInner,
&Arc<Mutex<FileMetadata>>,
@@ -471,10 +470,7 @@ impl StdFileResource {
}
}
- async fn with_inner_blocking_task<F, R: Send + 'static>(
- self: Rc<Self>,
- action: F,
- ) -> R
+ async fn with_inner_blocking_task<F, R: Send + 'static>(&self, action: F) -> R
where
F: FnOnce(&mut StdFileResourceInner) -> R + Send + 'static,
{
@@ -540,6 +536,14 @@ impl StdFileResource {
.await
}
+ fn read_byob_sync(&self, buf: &mut [u8]) -> Result<usize, AnyError> {
+ self.with_inner_and_metadata(|inner, _| inner.read(buf).map_err(Into::into))
+ }
+
+ fn write_sync(&self, data: &[u8]) -> Result<usize, AnyError> {
+ self.with_inner_and_metadata(|inner, _| inner.write_and_maybe_flush(data))
+ }
+
fn with_resource<F, R>(
state: &mut OpState,
rid: ResourceId,
@@ -632,7 +636,7 @@ impl Resource for StdFileResource {
Box::pin(async move {
let vec = vec![0; limit];
let buf = BufMutView::from(vec);
- let (nread, buf) = self.read_byob(buf).await?;
+ let (nread, buf) = StdFileResource::read_byob(self, buf).await?;
let mut vec = buf.unwrap_vec();
if vec.len() != nread {
vec.truncate(nread);
@@ -645,17 +649,29 @@ impl Resource for StdFileResource {
self: Rc<Self>,
buf: deno_core::BufMutView,
) -> AsyncResult<(usize, deno_core::BufMutView)> {
- Box::pin(self.read_byob(buf))
+ Box::pin(StdFileResource::read_byob(self, buf))
}
fn write(
self: Rc<Self>,
view: deno_core::BufView,
) -> AsyncResult<deno_core::WriteOutcome> {
- Box::pin(self.write(view))
+ Box::pin(StdFileResource::write(self, view))
}
+
fn write_all(self: Rc<Self>, view: deno_core::BufView) -> AsyncResult<()> {
- Box::pin(self.write_all(view))
+ Box::pin(StdFileResource::write_all(self, view))
+ }
+
+ fn write_sync(&self, data: &[u8]) -> Result<usize, deno_core::anyhow::Error> {
+ StdFileResource::write_sync(self, data)
+ }
+
+ fn read_byob_sync(
+ &self,
+ data: &mut [u8],
+ ) -> Result<usize, deno_core::anyhow::Error> {
+ StdFileResource::read_byob_sync(self, data)
}
#[cfg(unix)]
@@ -684,35 +700,3 @@ pub fn op_print(
})
})
}
-
-#[op(fast)]
-fn op_read_sync(
- state: &mut OpState,
- rid: u32,
- buf: &mut [u8],
-) -> Result<u32, AnyError> {
- StdFileResource::with_resource(state, rid, move |resource| {
- resource.with_inner_and_metadata(|inner, _| {
- inner
- .read(buf)
- .map(|n: usize| n as u32)
- .map_err(AnyError::from)
- })
- })
-}
-
-#[op(fast)]
-fn op_write_sync(
- state: &mut OpState,
- rid: u32,
- buf: &mut [u8],
-) -> Result<u32, AnyError> {
- StdFileResource::with_resource(state, rid, move |resource| {
- resource.with_inner_and_metadata(|inner, _| {
- inner
- .write_and_maybe_flush(buf)
- .map(|nwritten: usize| nwritten as u32)
- .map_err(AnyError::from)
- })
- })
-}