@globocom/backstage-functions-sandbox
Advanced tools
Comparing version 0.5.3 to 0.5.5
@@ -13,2 +13,3 @@ const vm = require('vm'); | ||
const errors = require('./errors'); | ||
const SandboxInternalException = require('./SandboxInternalException'); | ||
@@ -68,5 +69,6 @@ const systemConsole = console; | ||
this.config = config || {}; | ||
this.activeTimers = [] | ||
} | ||
createEmptyContext(backstageOptions, prefix = null, extraEnv = null, console = null) { | ||
createEmptyContext(backstageOptions, prefix = null, extraEnv = null, console = null, objsList={}) { | ||
const exports = {}; | ||
@@ -99,3 +101,12 @@ | ||
this.context.Buffer = Buffer; | ||
this.context.setTimeout = setTimeout; | ||
this.context.setTimeout = (func, delay) => { | ||
const timeoutId = setTimeout(func, delay); | ||
objsList.timerList.push(timeoutId) | ||
return timeoutId | ||
} | ||
this.context.setInterval = (func, interval) => { | ||
const intervalId = setInterval(func, interval); | ||
objsList.intervalList.push(intervalId) | ||
return intervalId | ||
} | ||
this.context.clearTimeout = clearTimeout; | ||
@@ -121,3 +132,4 @@ this.context.exports = exports; | ||
const script = new vm.Script(text, { filename, displayErrors: false, lineOffset: -1 }); | ||
const context = this.createEmptyContext({}, prefix || filename, null, console); | ||
let objsCounter = { intervalList: [], timerList: []} | ||
const context = this.createEmptyContext({}, prefix || filename, null, console, objsCounter); | ||
script.runInContext(context, { timeout: this.syncTimeout }); | ||
@@ -135,11 +147,30 @@ } catch (e) { | ||
compileCode(filename, code) { | ||
const text = encapsulateCode(this, code + codeFoot); | ||
try{ | ||
const text = encapsulateCode(this, code + codeFoot); | ||
return new vm.Script(text, { | ||
filename, | ||
displayErrors: true, | ||
timeout: this.syncTimeout, | ||
}); | ||
}catch(e){ | ||
throw new SandboxInternalException(e) | ||
} | ||
} | ||
return new vm.Script(text, { | ||
filename, | ||
displayErrors: true, | ||
timeout: this.syncTimeout, | ||
}); | ||
hasPendingObjects(objsList) { | ||
return (objsList.timerList.length > 0) || (objsList.intervalList.length > 0); | ||
} | ||
finishPendingObjects(objsList) { | ||
if (!objsList) return; | ||
if (objsList.timerList) { | ||
objsList.timerList.forEach((timeoutId) => clearTimeout(timeoutId)); | ||
} | ||
if (objsList.intervalList) { | ||
objsList.intervalList.forEach((intervalId) => clearInterval(intervalId)); | ||
} | ||
} | ||
runScript(script, req, { prefix, env, console, span } = {}) { | ||
@@ -167,2 +198,3 @@ return new Promise((accept, reject) => { | ||
const sandboxRes = new Response({ callback }); | ||
let objsList = { intervalList: [], timerList: []} | ||
const context = this.createEmptyContext({ | ||
@@ -172,26 +204,33 @@ request: sandboxReq, | ||
span, | ||
}, prefix, env, console); | ||
}, prefix, env, console, objsList); | ||
const vmDomain = domain.create(); | ||
vmDomain.on('error', (err) => { | ||
callback(err); | ||
this.finishPendingObjects(objsList) | ||
callback(new SandboxInternalException(err)); | ||
}); | ||
vmDomain.run(() => { | ||
const result = script.runInContext(context, { | ||
timeout: this.syncTimeout, | ||
displayErrors: false, | ||
lineOffset: -1, | ||
try{ | ||
vmDomain.run(() => { | ||
const result = script.runInContext(context, { | ||
timeout: this.syncTimeout, | ||
displayErrors: false, | ||
lineOffset: -1, | ||
}); | ||
if (result && result.constructor.name === 'Promise') { | ||
result | ||
.then((body) => { | ||
this.finishPendingObjects(objsList) | ||
sandboxRes.send(body); | ||
}) | ||
.catch((err) => { | ||
callback(err); | ||
}); | ||
return | ||
} | ||
this.finishPendingObjects(objsList) | ||
}); | ||
if (result && result.constructor.name === 'Promise') { | ||
result | ||
.then((body) => { | ||
sandboxRes.send(body); | ||
}) | ||
.catch((err) => { | ||
callback(err); | ||
}); | ||
} | ||
}); | ||
}catch(e){ | ||
throw new SandboxInternalException(e) | ||
} | ||
}); | ||
@@ -198,0 +237,0 @@ } |
{ | ||
"name": "@globocom/backstage-functions-sandbox", | ||
"version": "0.5.3", | ||
"version": "0.5.5", | ||
"description": "Sandbox for Backstage functions", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
@@ -69,3 +69,3 @@ const expect = require('chai').expect; | ||
it('should return context with setTimeout', () => { | ||
expect(context.setTimeout).to.equal(setTimeout); | ||
expect(context.setTimeout).to.exist; | ||
}); | ||
@@ -141,3 +141,3 @@ | ||
expect(result.error).to.be.eql('SyntaxError: Unexpected token }'); | ||
expect(result.error).to.be.eql('SyntaxError: Unexpected token \'}\''); | ||
expect(result.stack).to.be.eql(''); | ||
@@ -301,26 +301,2 @@ }); | ||
describe('when code has an error in anonymous function', () => { | ||
it('should resolve promise as rejected', (done) => { | ||
const filename = 'test.js'; | ||
const code = ` | ||
function main(req, res) { | ||
setTimeout(() => { | ||
throw new Error('An error'); | ||
}, 10); | ||
} | ||
`; | ||
const script = testSandbox.compileCode(filename, code); | ||
testSandbox | ||
.runScript(script, {}) | ||
.then(() => { | ||
done(new Error('It is expected an error')); | ||
}, (error) => { | ||
expect(error.message).to.be.eql('An error'); | ||
done(); | ||
}) | ||
.catch(err => done(err)); | ||
}); | ||
}); | ||
describe('when code has an not declared variable', () => { | ||
@@ -327,0 +303,0 @@ it('should resolve promise as rejected by "strict mode"', (done) => { |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
46793
29
1193