Search code examples
rustwasm-bindgen

Why is my member variable not getting updated


here is a callback that is triggered every time a webrtc channel is opened

it is wrapped inside an impl named Peer.This contain a member variable of type i16 named num_channel_opened setted to a default of 0.

#[wasm_bindgen]
#[derive(Clone)]
struct Peer {
  num_channel_opened:i16
}

#[wasm_bindgen]
impl Peer {
  /* ... */
  fn new() {
    /* ... */
  }

  fn on_channel_opened () {
    /* ... */
  }
  /* ... */
}

here is my listener function

  fn on_channel_opened ( &self ) -> Closure<dyn FnMut(Event)>{
    let mut selfCell = Rc::new(RefCell::new( self.clone() ) );
    Closure::wrap( Box::new( move |ev: Event |  {
        let mut selfClone = selfCell.clone();
        (*selfClone).borrow_mut().num_channels_opened += 1;
        console_warn!("number of channel opened {:?}", ( *selfClone ).borrow().num_channels_opened );
        }
    }) as Box<dyn FnMut(Event)> )
  }

I have three channels and I was hoping that the variable would get incremented on each channel opening. Instead of that I always get 1 the previous value is not persistent. How can I make this value persistent. The equivalent in javascript would be

class Peer {
  num_channels_opened = 0;
  peer;

  constructor () {
    this.peer = new RTCPeerConnection();
    //create channels
    //wait to receive remote channels
    //attach on_channel_opened to received remote channels
        //this would look like
        //channel.onopen = this.on_channel_opened;
  }

  on_channel_opened = () => {
    this.num_channel_opened++;
    console.log( this.num_channel_opened ) // 1, 2, 3...N channels
  }
}

Solution

  • You're cloning self in on_channel_opened and then modifying the clone instead of the original. In order to behave like javascript, you should use Rc everywhere, e.g.:

    struct Peer {
       num_channel_opened: i16,
    }
    
    impl Peer {
       
       fn new() -> Rc<RefCell<Peer>> {
          Rc::new(RefCell::new (Peer { num_channel_opened: 1, }))
       }
    
       fn on_channel_opened ( self, this: Rc<RefCell<Self>>) -> Closure<dyn FnMut(Event)> {
          let that = Rc::clone (&this);
          Closure::wrap (Box::new (move |ev: Event|  {
             that.borrow_mut().num_channels_opened += 1;
             console_warn!("number of channel opened {:?}", that.borrow().num_channels_opened);
          }
       }) as Box<dyn FnMut(Event)>)
    }