Repository: denoland/deno
Pull request: fix(ext/web): make CompressionResource garbage collectable


Changed files:
filename: ext/web/compression.rs
patch: @@ -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)]
@@ -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)),
@@ -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()))?;
@@ -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()))
@@ -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),
   }
 }