2018-01-07 16:18:58 +01:00
|
|
|
'use strict';
|
|
|
|
|
2018-07-03 20:34:21 +02:00
|
|
|
/**
|
|
|
|
* Controller for maintaining and running sandboxed code as sent by the API.
|
|
|
|
*/
|
2018-01-07 16:18:58 +01:00
|
|
|
class VMController
|
|
|
|
{
|
|
|
|
constructor( driver ) {
|
|
|
|
|
|
|
|
this.driver = driver;
|
|
|
|
this.runningCode = ';';
|
|
|
|
this.runningVmScript = false;
|
|
|
|
this.previousTime = 0;
|
|
|
|
this.delta = 0;
|
|
|
|
this.sandbox = {};
|
|
|
|
this.vm = null;
|
2018-01-10 19:58:48 +01:00
|
|
|
this.runNextFrame = false;
|
2018-01-07 16:18:58 +01:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2018-07-03 20:34:21 +02:00
|
|
|
/**
|
|
|
|
* Current running code
|
|
|
|
*/
|
2018-01-07 16:18:58 +01:00
|
|
|
getRunningCode() {
|
|
|
|
return this.runningCode;
|
|
|
|
}
|
|
|
|
|
2018-07-03 20:34:21 +02:00
|
|
|
/**
|
|
|
|
* Compile step one, assign sandbox and set the runningScript
|
|
|
|
*/
|
2018-01-07 16:18:58 +01:00
|
|
|
compileScript( script ) {
|
|
|
|
|
|
|
|
let { NodeVM, VMScript } = require( 'vm2' );
|
|
|
|
|
|
|
|
this.resetSandbox();
|
|
|
|
this.runningCode = script;
|
|
|
|
this.vm = new NodeVM( {
|
|
|
|
'console': 'inherit',
|
|
|
|
'sandbox': this.sandbox
|
|
|
|
} );
|
|
|
|
|
|
|
|
this.runningVmScript = new VMScript( this.runningCode );
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2018-07-03 20:34:21 +02:00
|
|
|
/**
|
|
|
|
* Reset the sandbox of available properties to keep things secure between script frames.
|
|
|
|
* Every frame and compilation will have it's own new sandbox.
|
|
|
|
*/
|
2018-01-07 16:18:58 +01:00
|
|
|
resetSandbox() {
|
2018-01-10 19:58:48 +01:00
|
|
|
this.previousTime = this.getTimeData();
|
2018-01-09 21:31:40 +01:00
|
|
|
let matrixSize = this.driver.getSize();
|
|
|
|
|
2018-01-07 16:18:58 +01:00
|
|
|
this.sandbox = {
|
2018-01-10 19:58:48 +01:00
|
|
|
'sandbox': {},
|
2018-01-09 21:31:40 +01:00
|
|
|
'WIDTH': matrixSize.width,
|
|
|
|
'HEIGHT': matrixSize.height,
|
|
|
|
|
2018-01-10 19:03:07 +01:00
|
|
|
'clear': this.driver.clear.bind( this.driver ),
|
2018-01-09 21:31:40 +01:00
|
|
|
'setBrightness': this.driver.setBrightness.bind( this.driver ),
|
|
|
|
'getBrightness': this.driver.getBrightness.bind( this.driver ),
|
|
|
|
'setPixel': this.driver.setPixel.bind( this.driver ),
|
|
|
|
'getPixel': this.driver.getPixel.bind( this.driver ),
|
|
|
|
'drawLine': this.driver.drawLine.bind( this.driver ),
|
|
|
|
'drawRect': this.driver.drawRect.bind( this.driver ),
|
|
|
|
'drawRectFilled': this.driver.drawRectFilled.bind( this.driver ),
|
|
|
|
'drawCircle': this.driver.drawCircle.bind( this.driver ),
|
|
|
|
'write': this.driver.write.bind( this.driver ),
|
|
|
|
|
2018-06-27 19:33:13 +02:00
|
|
|
'getDelta': this.getDelta.bind( this ),
|
2018-01-10 19:58:48 +01:00
|
|
|
'run': this.run.bind( this )
|
2018-01-07 16:18:58 +01:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2018-07-03 20:34:21 +02:00
|
|
|
/**
|
|
|
|
* Initialize compilation, next frame calculation and delta time calculation
|
|
|
|
*/
|
2018-01-07 16:18:58 +01:00
|
|
|
runScript( ) {
|
|
|
|
|
2018-06-27 19:33:13 +02:00
|
|
|
let deltaLocal = 0;
|
2018-01-07 16:18:58 +01:00
|
|
|
let tmd = this.getTimeData();
|
|
|
|
|
2018-06-27 19:33:13 +02:00
|
|
|
deltaLocal = tmd - this.previousTime;
|
2018-01-10 19:58:48 +01:00
|
|
|
|
|
|
|
this.previousTime = tmd;
|
2018-01-07 16:18:58 +01:00
|
|
|
|
2018-06-27 19:33:13 +02:00
|
|
|
this.delta = deltaLocal / 1000000;
|
2018-01-07 16:18:58 +01:00
|
|
|
|
|
|
|
this.vm.run( this.runningVmScript, 'pixdisp-sandbox.js' );
|
|
|
|
|
2018-01-10 19:58:48 +01:00
|
|
|
if ( this.runNextFrame === true ) {
|
|
|
|
this.runNextFrame = false;
|
2018-06-27 19:33:13 +02:00
|
|
|
setTimeout( this.runScript.bind( this ), 1000 / 60 );
|
2018-01-10 19:58:48 +01:00
|
|
|
}
|
2018-01-07 16:18:58 +01:00
|
|
|
}
|
|
|
|
|
2018-07-03 20:34:21 +02:00
|
|
|
/**
|
|
|
|
* Calculate the time passed
|
|
|
|
*/
|
2018-01-07 16:18:58 +01:00
|
|
|
getTimeData() {
|
|
|
|
let hrTime = process.hrtime();
|
|
|
|
return hrTime[ 0 ] * 1000000 + hrTime[ 1 ] / 1000;
|
|
|
|
}
|
|
|
|
|
|
|
|
getDriver() {
|
|
|
|
return this.driver;
|
|
|
|
}
|
|
|
|
|
|
|
|
getDelta() {
|
|
|
|
return this.delta;
|
|
|
|
}
|
2018-01-10 19:58:48 +01:00
|
|
|
|
|
|
|
run() {
|
|
|
|
this.runNextFrame = true;
|
|
|
|
}
|
2018-01-07 16:18:58 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
exports.VMController = VMController;
|