Repository: swc-project/swc
File: crates/swc_plugin_runner/src/transform_executor.rs (Rust)

Code before:
                    panic!("Should able to allocate memory for the size of {serialized_len}")
                })
            },
        );

        let returned_ptr_result = self.instance.transform(
            guest_program_ptr.0,
            guest_program_ptr.1,
            unresolved_mark.as_u32(),
            should_enable_comments_proxy,
        )?;

        // Copy guest's memory into host, construct serialized struct from raw
        // bytes.
        let transformed_result = &(*self.transform_result.lock());
        let ret = PluginSerializedBytes::from_bytes(transformed_result.clone());

        let ret = if returned_ptr_result == 0 {
            Ok(ret)
        } else {
            let err: PluginError = ret.deserialize()?.into_inner();
            match err {
                PluginError::SizeInteropFailure(msg) => Err(anyhow!(
                    "Failed to convert pointer size to calculate: {msg}"
                )),
                PluginError::Deserialize(msg) | PluginError::Serialize(msg) => {
                    Err(anyhow!("{msg}"))
                }
                _ => Err(anyhow!(
                    "Unexpected error occurred while running plugin transform"
                )),
            }
        };

        self.instance
            .caller()?
            .free(guest_program_ptr.0, guest_program_ptr.1)?;
        self.instance.cleanup()?;

        ret
    }

    /**
     * Check compile-time version of AST schema between the plugin and
     * the host. Returns true if it's compatible, false otherwise.
     *
     * Host should appropriately handle if plugin is not compatible to the
     * current runtime.
     */
    #[allow(unreachable_code)]
    pub fn is_transform_schema_compatible(&mut self) -> Result<(), Error> {

Review comment (bug):
The `Arc::try_unwrap` may fail even after dropping `self.instance` because the instance's import object closures hold cloned references to `transform_env`, which in turn holds a clone of the `transform_result` Arc. The instance's `Drop` implementation and the `cleanup()` method (which has a default no-op implementation) don't guarantee that these closures are released. Consider keeping the original `.lock().clone()` approach, or ensure the runtime implementation properly releases all import object closures during cleanup/drop.
```suggestion
        // Instead of trying to unwrap the Arc, clone the inner value.
        let transformed_result = self.transform_result.lock().clone();
```

Code after:
                    panic!("Should able to allocate memory for the size of {serialized_len}")
                })
            },
        );

        let returned_ptr_result = self.instance.transform(
            guest_program_ptr.0,
            guest_program_ptr.1,
            unresolved_mark.as_u32(),
            should_enable_comments_proxy,
        )?;

        self.instance
            .caller()?
            .free(guest_program_ptr.0, guest_program_ptr.1)?;
        self.instance.cleanup()?;

        // Construct serialized struct from raw bytes.
        // Since we have finished transformation, it's safe to fetch the data from
        // Arc<Mutex<T>>
        drop(self.instance);
        let transformed_result = Arc::try_unwrap(self.transform_result)
            .map_err(|_| {
                anyhow!("Failed to unwrap Arc: other references to transform_result exist")
            })?
            .into_inner();
        let ret = PluginSerializedBytes::from_bytes(transformed_result);

        let ret = if returned_ptr_result == 0 {
            Ok(ret)
        } else {
            let err: PluginError = ret.deserialize()?.into_inner();
            match err {
                PluginError::SizeInteropFailure(msg) => Err(anyhow!(
                    "Failed to convert pointer size to calculate: {msg}"
                )),
                PluginError::Deserialize(msg) | PluginError::Serialize(msg) => {
                    Err(anyhow!("{msg}"))
                }
                _ => Err(anyhow!(
                    "Unexpected error occurred while running plugin transform"
                )),
            }
        };

        ret
    }

    /**
     * Check compile-time version of AST schema between the plugin and
     * the host. Returns true if it's compatible, false otherwise.