Skip to content

Commit

Permalink
fix(ext/web): make CompressionResource garbage collectable (#24884)
Browse files Browse the repository at this point in the history
  • Loading branch information
littledivy authored Aug 6, 2024
1 parent 646de0f commit f0cd2c4
Showing 1 changed file with 25 additions and 35 deletions.
60 changes: 25 additions & 35 deletions ext/web/compression.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,20 @@
use deno_core::error::type_error;
use deno_core::error::AnyError;
use deno_core::op2;
use deno_core::OpState;
use deno_core::Resource;
use deno_core::ResourceId;
use deno_core::ToJsBuffer;
use flate2::write::DeflateDecoder;
use flate2::write::DeflateEncoder;
use flate2::write::GzDecoder;
use flate2::write::GzEncoder;
use flate2::write::ZlibDecoder;
use flate2::write::ZlibEncoder;
use flate2::Compression;
use std::borrow::Cow;
use std::cell::RefCell;
use std::io::Write;
use std::rc::Rc;

#[derive(Debug)]
struct CompressionResource(RefCell<Inner>);
struct CompressionResource(RefCell<Option<Inner>>);

impl deno_core::GarbageCollected for CompressionResource {}

/// https://wicg.github.io/compression/#supported-formats
#[derive(Debug)]
Expand All @@ -33,19 +29,12 @@ enum Inner {
GzEncoder(GzEncoder<Vec<u8>>),
}

impl Resource for CompressionResource {
fn name(&self) -> Cow<str> {
"compression".into()
}
}

#[op2(fast)]
#[smi]
#[op2]
#[cppgc]
pub fn op_compression_new(
state: &mut OpState,
#[string] format: &str,
is_decoder: bool,
) -> ResourceId {
) -> Result<CompressionResource, AnyError> {
let w = Vec::new();
let inner = match (format, is_decoder) {
("deflate", true) => Inner::DeflateDecoder(ZlibDecoder::new(w)),
Expand All @@ -60,21 +49,21 @@ pub fn op_compression_new(
("gzip", false) => {
Inner::GzEncoder(GzEncoder::new(w, Compression::default()))
}
_ => unreachable!(),
_ => return Err(type_error("Unsupported format")),
};
let resource = CompressionResource(RefCell::new(inner));
state.resource_table.add(resource)
Ok(CompressionResource(RefCell::new(Some(inner))))
}

#[op2]
#[serde]
#[buffer]
pub fn op_compression_write(
state: &mut OpState,
#[smi] rid: ResourceId,
#[cppgc] resource: &CompressionResource,
#[anybuffer] input: &[u8],
) -> Result<ToJsBuffer, AnyError> {
let resource = state.resource_table.get::<CompressionResource>(rid)?;
) -> Result<Vec<u8>, AnyError> {
let mut inner = resource.0.borrow_mut();
let inner = inner
.as_mut()
.ok_or_else(|| type_error("resource is closed"))?;
let out: Vec<u8> = match &mut *inner {
Inner::DeflateDecoder(d) => {
d.write_all(input).map_err(|e| type_error(e.to_string()))?;
Expand Down Expand Up @@ -108,19 +97,20 @@ pub fn op_compression_write(
}
}
.collect();
Ok(out.into())
Ok(out)
}

#[op2]
#[serde]
#[buffer]
pub fn op_compression_finish(
state: &mut OpState,
#[smi] rid: ResourceId,
#[cppgc] resource: &CompressionResource,
report_errors: bool,
) -> Result<ToJsBuffer, AnyError> {
let resource = state.resource_table.take::<CompressionResource>(rid)?;
let resource = Rc::try_unwrap(resource).unwrap();
let inner = resource.0.into_inner();
) -> Result<Vec<u8>, AnyError> {
let inner = resource
.0
.borrow_mut()
.take()
.ok_or_else(|| type_error("resource is closed"))?;
let out = match inner {
Inner::DeflateDecoder(d) => {
d.finish().map_err(|e| type_error(e.to_string()))
Expand All @@ -142,9 +132,9 @@ pub fn op_compression_finish(
if report_errors {
Err(err)
} else {
Ok(Vec::with_capacity(0).into())
Ok(Vec::with_capacity(0))
}
}
Ok(out) => Ok(out.into()),
Ok(out) => Ok(out),
}
}

0 comments on commit f0cd2c4

Please sign in to comment.