boa: Calling a function that mutates itself causes borrow panic

This is caused when we call a function we borrow the function object and we do not release the hold until function ends. see GcObject::call / GcObject::construct

To Reproduce Steps to reproduce the issue, or JavaScript code that causes this failure.

function x() {
	x.y = 3;
}
x();

Expected behavior Not panic and x to have a property y with value 3

Actual behavior Panics:

thread 'main' panicked at 'Object already borrowed: BorrowMutError', boa/src/builtins/object/gcobject.rs:41:9

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Reactions: 1
  • Comments: 18 (8 by maintainers)

Most upvoted comments

Ok now it works 🥳. I thought with NLL it would get dropped before the function returns

Ok so i took an another look and i think we need to clone the body here but just cloning the body does not fix the issue. I just called body.clone().run().

That is only one half of the problem the next is to release the borrow a nicer way of doing this is to create a enum

enum FunctionBody {
	BuiltIn(NativeFunction),
	Ordinary(RcStatememtList),
}

and return it in the if expression https://github.com/dvtkrlbs/boa/blob/0fc8052f4ee8bc79ee3df265b855f66b421f641e/boa/src/builtins/object/gcobject.rs#L68 then match on it outside of the borrow.

Got it thank you for the help. I probably should look at it tomorrow.

Than i cant even call run method (i thought Rc was just a wrapper type) it cant find most of the methods of the StatementList. I dont know i might just missing something i am kinda tired.

we need to implement Deref trait on the RcStatementlist:

use std::ops::Deref;
impl Deref for RcStatementlist {
	type Target = Statementlist;
	fn deref(&self) -> &Self::Target {
		self.0
	}
}

The std::rc::Rc implements Deref, but our wrapper type (RcStatementlist) does not. Check RcString/RcSymbol/RcBigInt for more information/examples since its very similar.

i can try to fix this issue