Repository: denoland/deno
File: ext/ffi/dlfcn.rs (Rust)

Code before:
        .map(ForeignSymbol::ForeignFunction)
    }
  }
}

#[derive(Deserialize, Debug)]
pub struct FfiLoadArgs {
  path: String,
  symbols: HashMap<String, ForeignSymbol>,
}

#[op2]
pub fn op_ffi_load<'scope, FP>(
  scope: &mut v8::HandleScope<'scope>,
  state: &mut OpState,
  #[serde] args: FfiLoadArgs,
) -> Result<v8::Local<'scope, v8::Value>, DlfcnError>
where
  FP: FfiPermissions + 'static,
{
  let permissions = state.borrow_mut::<FP>();
  let path = permissions.check_partial_with_path(&args.path)?;

  let lib = Library::open(&path).map_err(|e| {
    dlopen2::Error::OpeningLibraryError(std::io::Error::new(
      std::io::ErrorKind::Other,
      format_error(e, &path),
    ))
  })?;
  let mut resource = DynamicLibraryResource {
    lib,
    symbols: HashMap::new(),
  };
  let obj = v8::Object::new(scope);

  for (symbol_key, foreign_symbol) in args.symbols {
    match foreign_symbol {
      ForeignSymbol::ForeignStatic(_) => {
        // No-op: Statics will be handled separately and are not part of the Rust-side resource.
      }
      ForeignSymbol::ForeignFunction(foreign_fn) => 'register_symbol: {
        let symbol = match &foreign_fn.name {
          Some(symbol) => symbol,
          None => &symbol_key,
        };
        // By default, Err returned by this function does not tell
        // which symbol wasn't exported. So we'll modify the error
        // message to include the name of symbol.
        let fn_ptr =
          // SAFETY: The obtained T symbol is the size of a pointer.
          match unsafe { resource.lib.symbol::<*const c_void>(symbol) } {

Review comment (suggestion):
This was holding a mutable OpState borrow across the `make_cppgc_object` call which borrows again. It panics with latest deno_core version.

Code after:
      ForeignFunction::deserialize(ValueDeserializer::<D::Error>::new(value))
        .map(ForeignSymbol::ForeignFunction)
    }
  }
}

#[derive(Deserialize, Debug)]
pub struct FfiLoadArgs {
  path: String,
  symbols: HashMap<String, ForeignSymbol>,
}

#[op2]
pub fn op_ffi_load<'scope, FP>(
  scope: &mut v8::HandleScope<'scope>,
  state: Rc<RefCell<OpState>>,
  #[serde] args: FfiLoadArgs,
) -> Result<v8::Local<'scope, v8::Value>, DlfcnError>
where
  FP: FfiPermissions + 'static,
{
  let path = {
    let mut state = state.borrow_mut();
    let permissions = state.borrow_mut::<FP>();
    permissions.check_partial_with_path(&args.path)?
  };

  let lib = Library::open(&path).map_err(|e| {
    dlopen2::Error::OpeningLibraryError(std::io::Error::new(
      std::io::ErrorKind::Other,
      format_error(e, &path),
    ))
  })?;
  let mut resource = DynamicLibraryResource {
    lib,
    symbols: HashMap::new(),
  };
  let obj = v8::Object::new(scope);

  for (symbol_key, foreign_symbol) in args.symbols {
    match foreign_symbol {
      ForeignSymbol::ForeignStatic(_) => {
        // No-op: Statics will be handled separately and are not part of the Rust-side resource.
      }
      ForeignSymbol::ForeignFunction(foreign_fn) => 'register_symbol: {
        let symbol = match &foreign_fn.name {
          Some(symbol) => symbol,
          None => &symbol_key,
        };
        // By default, Err returned by this function does not tell
        // which symbol wasn't exported. So we'll modify the error