Repository: parcel-bundler/parcel
File: crates/node-bindings/src/helpers/js_callable/js_callable.rs (Rust)

Code before:

  /// Call JavaScript function and discard return value
  pub fn call<Return: Send + 'static>(
    &self,
    map_params: impl FnOnce(&Env) -> napi::Result<Vec<JsUnknown>> + Send + 'static,
  ) -> napi::Result<()> {
    if self.initial_thread == std::thread::current().id() {
      self.call_local(map_params)
    } else {
      self.call_thread(map_params)
    }
  }

  pub fn call_with_return<Return: Send + 'static>(
    &self,
    map_params: impl FnOnce(&Env) -> napi::Result<Vec<JsUnknown>> + Send + 'static,
    map_return: impl Fn(&Env, JsUnknown) -> napi::Result<Return> + Send + 'static,
  ) -> napi::Result<Return> {
    if self.initial_thread == std::thread::current().id() {
      self.call_local_with_return(map_params, map_return)
    } else {
      self.call_thread_with_return(map_params, map_return)
    }
  }

  pub fn call_local(
    &self,
    map_params: impl FnOnce(&Env) -> napi::Result<Vec<JsUnknown>> + Send + 'static,
  ) -> napi::Result<()> {
    self.call_local_with_return(map_params, |_, _| Ok(()))
  }

  pub fn call_local_with_return<Return: Send + 'static>(
    &self,
    map_params: impl FnOnce(&Env) -> napi::Result<Vec<JsUnknown>> + Send + 'static,
    map_return: impl Fn(&Env, JsUnknown) -> napi::Result<Return> + Send + 'static,
  ) -> napi::Result<Return> {
    let (callback, env) = get_local_function(&self.callback)?.unwrap();

    let params = map_params(&env)?;
    let returned = callback.call(None, &params)?;
    map_return(&env, returned)
  }

  pub fn call_thread(
    &self,
    map_params: impl FnOnce(&Env) -> napi::Result<Vec<JsUnknown>> + Send + 'static,
  ) -> napi::Result<()> {
    self.tsfn.call(
      Box::new(map_params),
      ThreadsafeFunctionCallMode::NonBlocking,

Review comment (suggestion):
I don't think we have any use-cases that require calling JS threads from Rust that runs on the main JavaScript thread.

Code after:
    &self,
    map_params: impl FnOnce(&Env) -> napi::Result<Vec<JsUnknown>> + 'static,
  ) -> napi::Result<()> {
    #[cfg(debug_assertions)]
    if self.initial_thread == std::thread::current().id() {
      return Err(napi::Error::from_reason(
        "Cannot run threadsafe function on main thread",
      ));
    }

    self.tsfn.call(
      Box::new(map_params),
      ThreadsafeFunctionCallMode::NonBlocking,
    );

    Ok(())
  }

  pub fn call_serde<Params>(&self, params: Params) -> napi::Result<()>
  where
    Params: Serialize + Send + Sync + 'static,
  {
    self.call(map_params_serde(params))
  }

  /// Call JavaScript function and handle the return value
  pub fn call_with_return<Return>(
    &self,
    map_params: impl FnOnce(&Env) -> napi::Result<Vec<JsUnknown>> + 'static,
    map_return: impl Fn(&Env, JsUnknown) -> napi::Result<Return> + 'static,
  ) -> napi::Result<Return>
  where
    Return: Send + 'static,
  {
    #[cfg(debug_assertions)]
    if self.initial_thread == std::thread::current().id() {
      return Err(napi::Error::from_reason(
        "Cannot run threadsafe function on main thread",
      ));
    }

    let (tx, rx) = channel();

    self.tsfn.call_with_return_value(
      Box::new(map_params),
      ThreadsafeFunctionCallMode::NonBlocking,
      move |JsValue(value, env)| {
        if value.is_promise()? {
          let result: JsObject = value.try_into()?;
          let then: JsFunction = result.get_named_property("then")?;