Closed RugolettoRomuald closed 3 months ago
here's the solution I finally came up with:
it(`user fire on move end`, async () => {
// Arrange
let playerBotDistance = 0
let nbFireCall = 0
const isolate = new Isolate()
const context = await isolate.createContext()
await context.global.set('global', context.global.derefInto()) // allows you to define function in 'context.eval'
await context.global.set('fire', () => nbFireCall += 1)
await context.global.set('__move', new Reference(async (distance: number) => {
playerBotDistance += distance // updates common game elements
await promiseUtils.waitDelay(1000) // waits 1000ms to mock async stuffs
return Promise.resolve()
}))
await context.eval(`
(async () => {
global.move = (() => {
const internalFn = __move
delete __move
return async function (distance, callback) {
await internalFn.applySyncPromise(undefined, [distance])
callback?.()
}
})()
})()
`)
await context.eval(`delete global`) // removes access to global before running user code
// Act
const untrustedUserCode = await context.eval(`
(() => {
function onMoveEnd() {
fire()
}
move(21, onMoveEnd)
})
`, { reference: true })
await untrustedUserCode.apply(undefined, [])
// Assert
chai.assert.equal(playerBotDistance, 21)
chai.assert.equal(nbFireCall, 1)
})
Hi ! First at all, thank-you for this library !
My real use case
For the purposes of my project, I've wrapped it into a VM class in which I authorize certain functions by using a bridge pattern. Everything works fine until I run into this problem:
In the preceding code, I'd like the
move
function to call theonMoveEnd
function only if my user has declared it in his robot's code. However, myget
function timeout šSimple tests to highlight the problem
So I wrote some tests that use IsolateVM outside my wrapper to highlight my problem, see below :
As you can see, if I get the reference to the increment function from the nodejs context, I can apply it. Otherwise, I'm stuck at the first step and can't even get the reference to the increment function.
Work around until a better solution
I can work around the problem by executing an intermediate function like below, but it seems strange to have to use this kind of strategy.