trufflesuite / truffle-require

Executed a Javascript module within a Truffle context
7 stars 9 forks source link

Unexpected behavior with truffle exec when requiring modules #16

Open dordille opened 6 years ago

dordille commented 6 years ago

Using vm.runInNewContext can cause some unexpected behavior for developers when requiring modules. This can happen whenever a module interacts with an global provided by V8 that is not explicitly provided by the context. I've included some example code that demonstrates the issue.

module.js

module.exports = function(obj) {
  console.log(Object.getPrototypeOf(obj) === Object.prototype)
}

exec.js

module.exports = function() {
  var a = {};
  console.log(Object.getPrototypeOf(a) === Object.prototype)
  require('./module.js')(a)
}

Running the exec script with truffle exec exec.js you'll see that true is logged following by false. This happens because runInNewContext injects a new instance of Object, however because require is defined outside of the context it causes all module code to run outside of the vm context.

I'm not sure I understand the motivation for running code in a new context. The user is already required to provide an exported function with this library, so the truffle context could be passed as an argument to this function rather than running in a new context. This would of course break backwards compatibility, but might be something worth considering for a future version of truffle.

A non bc fix could be to inject the entire global context into the vm context.

As is, I'm going to require all the truffle code myself in my exec script, I mostly am making this issue for documentation purposes, as the issue took a while to debug. For reference this issue came up when trying to use googleapis/nodejs-firestore, the library performs the prototype check when saving documents.