- Notifications
You must be signed in to change notification settings - Fork53
🏖️ The safer and faster ECMA5.1 interpreter written by JavaScript
License
sablejs/sablejs
Folders and files
| Name | Name | Last commit message | Last commit date | |
|---|---|---|---|---|
Repository files navigation
🎉 sablejs 2.0 will be opening all the code, pleaseclick to learn more about our milestone and goals.
English |简体中文
The safer and faster ECMA5.1 interpreter written by JavaScript, it can be used:
- Sandbox (like Figma Plugin Sandbox, but better and easier to use);
- Protect JavaScript source code via AOT compiling to opcode.
sablejs covered ~95%test262 es5-tests cases, it can be safely used in production.
sablejs includes the Compiler and Interpreter independently, so we removed the related dynamic api from the spec (seeLimits 1). In short, you need to compile your JavaScript code with sablejs cli before you run it.
Suppose we have the following code infib.js:
functionfib(n){returnn<2 ?n :fib(n-1)+fib(n-2);}varstart=Date.now();console.log("[INFO] fib: "+fib(30));console.log("[INFO] time consuming: "+(Date.now()-start)+"ms");
> npm i sablejs -g> sablejs -i fib.js -o output# get output file that contains base64 string
sablejs cli includes the following commands:
Usage: sablejs [options]Options: -v, --vers output the current version -i, --input<path> compile input filepath -o, --output<path> compile output filepath -j --json don't do Base64 compress, output simple json result -s, --slient don't output log -h, --help
> npm install sablejs --saveor you can import to your html directly
<scriptsrc="https://cdn.jsdelivr.net/npm/sablejs@1.0.8/runtime.js"></script>
constVM=require("sablejs/runtime")();// import console.log function to vm callconstvm=newVM();constvGlobal=vm.getGlobal();constvConsole=vm.createObject();constvLog=vm.createFunction("log",function(){consttemp=[];for(leti=0;i<arguments.length;i++){temp.push(vm.asString(arguments[i]));}console.log(...temp);returnvm.createUndefined();});vm.setProperty(vConsole,"log",vLog);vm.setProperty(vGlobal,"console",vConsole);(async()=>{constresp=awaitfetch("<output url>");constdata=awaitresp.text();vm.run(data);vm.destroy();})();
constVM=require("sablejs/runtime")();constfs=require("fs");// import console.log function to vm callconstvm=newVM();constvGlobal=vm.getGlobal();constvConsole=vm.createObject();constvLog=vm.createFunction("log",function(){consttemp=[];for(leti=0;i<arguments.length;i++){temp.push(vm.asString(arguments[i]));}console.log(...temp);returnvm.createUndefined();});vm.setProperty(vConsole,"log",vLog);vm.setProperty(vGlobal,"console",vConsole);// please run: sablejs -i fib.js -o outputvm.run(fs.readFileSync("./output").toString());vm.destroy();
- VM.prototype.run(source, isSimpleJSON)
- source: String - the compiled result via sablejs compiler
- isSimpleJSON: Boolean - if be true, you should use
-jto make compiler output simple json result, default false. return:undefined
Initialize the VM and execute the compiled source code.
constVM=require('sablejs/runtime')();constvm=newVM();// source should be base64 string via sablejs compilingvm.run(`<compiled source string>`);
- VM.prototype.getGlobal()
return:Value
Returns theglobal in the VM, which is similar to thewindow in browser and theglobal in Node.js.
constglobal=vm.getGlobal();
- VM.prototype.createUndefined()
returnValue
Create anundefined boxed type.
constvUndefined=vm.createUndefined();
- VM.prototype.createNull()
return:Value
Create annull boxed type.
constvNull=vm.createNull();
- VM.prototype.createBoolean(bool)
- bool: Boolean
returnValue
Create anbool boxed type.
constvBoolean=vm.createBoolean(true);
- VM.prototype.createNumber(num)
- num: Number
returnValue
Create annumber boxed type.
constvNumber=vm.createNumber(1024);
- VM.prototype.createString(str)
- str: String
returnValue
Create anstring boxed type.
constvString=vm.createString('Hello World!');
- VM.prototype.createObject()
returnValue
Create anobject boxed type.
constvObject=vm.createObject();
- VM.prototype.createArray(length)
- length: Number | undefined
returnValue
Create anarray boxed type.
constvArray1=vm.createArray();// orconstvArray2=vm.createArray(128);
- VM.prototype.createFunction(name, func)
- name: String
- func: Function
returnValue
Create anfuncntion boxed type. It receives a function name and the specific implementation of the function. Both thefunction parameter andthis are boxed types infunc.
constvFunction=vm.createFunction("trim",function(str){// this is the undefined or new's instannce boxed type// str maybe the string boxed type, we need to check it});
- VM.prototype.createError(message)
- message: String | undefined
returnValue
Create anerror boxed type.
constvError1=vm.createError();// orconstvError2=vm.createError("unknown error");
- VM.prototype.createRegExp(pattern, flags)
- pattern: String
- flags: String | undefined
returnValue
Create anregexp boxed type.
constvRegExp=vm.createRegExp("\\w+","ig");
- VM.prototype.createDate()
returnValue
Create andate boxed type.
constvDate=vm.createDate();
- VM.prototype.isUndefined(value)
- value: Value
returnBoolean
Used to determine if the type isundefinend.
constvUndefined=vm.createUndefined();if(vm.isUndefined(vUndefined)){// ...}
- VM.prototype.isNull(value)
- value: Value
returnBoolean
Used to determine if the type isnull.
constvNull=vm.createNull();if(vm.isNull(vNull)){// ...}
- VM.prototype.isBoolean(value)
- value: Value
returnBoolean
Used to determine if the type isbool.
constvBoolean=vm.createBoolean(true);if(vm.isBoolean(vBoolean)){// ...}
- VM.prototype.isNumber(value)
- value: Value
returnBoolean
Used to determine if the type isnumber.
constvNumber=vm.createNumber(1024);if(vm.isNumber(vNumber)){// ...}
- VM.prototype.isString(value)
- value: Value
returnBoolean
Used to determine if the type isstring.
constvString=vm.createString("Hello World!");if(vm.isString(vString)){// ...}
- VM.prototype.isObject(value)
- value: Value
returnBoolean
Used to determine if the type isobject.
constvObject=vm.createObject();constvArray=vm.createArray();if(vm.isObject(vObject)&&vm.isObject(vArray)){// ...}
- VM.prototype.isArray(value)
- value: Value
returnBoolean
Used to determine if the type isarray.
constvArray=vm.createArray();if(vm.isArray(vArray)){// ...}
- VM.prototype.isFunction(value)
- value: Value
returnBoolean
Used to determine if the type isfunction.
constvFunction=vm.createFunction("log",function(){});if(vm.isFunction(vFunction)){// ...}
- VM.prototype.isError(value)
- value: Value
returnBoolean
Used to determine if the type iserror.
constvError=vm.createError('unknown error');if(vm.isError(vError)){// ...}
- VM.prototype.isRegExp(value)
- value: Value
returnBoolean
Used to determine if the type isregexp.
constvRegExp=vm.createRegExp("\\w+","ig");if(vm.isRegExp(vRegExp)){// ...}
- VM.prototype.isDate(value)
- value: Value
returnBoolean
Used to determine if the type isdate.
constvDate=vm.createDate();if(vm.isDate(vDate)){// ...}
- VM.prototype.asUndefined(value)
- value: Value
returnundefined
Convertingundefined boxed type toplain undefined value.
constvUndefined=vm.createUndefined();vm.asUndefined(vUndefined)===undefined;
- VM.prototype.asNull(value)
- value: Value
returnnull
Convertingnull boxed type toplain null value.
constvNull=vm.createNull();vm.asNull(vNull)===null;
- VM.prototype.asBoolean(value)
- value: Value
returnBoolean
Convertingbool boxed type toplain bool value.
constvBoolean=vm.createBoolean(true);constboolean=vm.asBoolean(vBoolean);if(boolean===true){// ...}
- VM.prototype.asNumber(value)
- value: Value
returnNumber
Convertingnumber boxed type toplain number value.
constvNumber=vm.createNumber(1024);constnumber=vm.asNumber(vNumber);if(number===1024){// ...}
- VM.prototype.asString(value)
- value: Value
returnString
Convertingstring boxed type toplain string value.
constvString=vm.createString('Hello World!');conststring=vm.asString(vString);if(string==='Hello World!'){// ...}
- VM.prototype.asObject(value)
- value: Value
returnObject
Convertingobject boxed type toinner object value.
constvObject=vm.createFunction("asObject",function(){});constobject=vm.asObject(vObject);if(object.type===12){// ...}
- VM.prototype.instanceof(lval, rval)
- lval: Value
- rval: Value
returnBoolean
Equivalent to theinstanceof keyword.
constglobal=vm.getGlobal();constvDateFunc=vm.getProperty(global,"Date");constvDate=vm.createDate();if(vm.instanceof(vDate,vDateFunc)){// ...}
- VM.prototype.typeof(value)
- value: Value
returnString
Equivalent to thetypeof keyword.
constvString=vm.createString('Hello World!');if(vm.typeof(vString)==="string"){// ...}
- VM.prototype.getProperty(value, name)
- value: Value
- name: String
returnValue
Get the value of the property of the object. Return is a property boxed type.
constglobal=vm.getGlobal();constvPrint=vm.getProperty(global,"print");if(vm.isFunction(vPrint)){// ...}
- VM.prototype.setProperty(value, name, property)
- value: Value
- name: String
- property: Value
returnValue
Assigning the property to object. Return is a property boxed type.
constglobal=vm.getGlobal();constconsole=vm.createObject();constlog=vm.createFunction("log",function(){// console.log impl});vm.setProperty(console,"log",log);vm.setProperty(global,"console",console);
- VM.prototype.deleteProperty(value, name)
- value: Value
- name: String
returnBoolean
Delete the property of object.
constglobal=vm.getGlobal();vm.deleteProperty(global,"print");constvPrint=vm.getProperty(global,"print");if(vm.isUndefined(vPrint)){// ...}
- VM.prototype.defineProperty(value, name, desc)
- value: Value
- name: String
- desc: Object
returnValue
Equivalent to theObject.defineProperty function.
constvObject=vm.createObject();vm.defineProperty(vObject,"name",{value:vm.createString("sablejs"),});constgetter=vm.createFunction("getter",function(){returnvm.createNumber("101");});constsetter=vm.createFunction("setter",function(age){vm.setProperty(this,"__age__",age);});vm.defineProperty(vObject,"age",{enumerable:false,get:getter,set:setter,});
- VM.prototype.getPrototype(value)
- value: Value
returnValue
Get the prototype of object.
constglobal=vm.getGlobal();constvStringFunc=vm.getProperty(global,"String");if(!vm.isUndefined(vStringFunc)){constvTrimStart=vm.createFunction("trimStart",function(){conststr=vm.asString(this);returnvm.createString(str);});constvStringFuncProto=vm.getPrototype(vStringFunc);vm.setProperty(vStringFuncProto,"trimStart",vTrimStart);}
- VM.prototype.setPrototype(value, prototype)
- value: Value
- prototype: Value
returnValue
Set the prototype of object.
constvA=vm.createFunction("A",function(){});constvObject=vm.createObject();vm.setProperty(vObject,'name',vm.createString('Hello World!'));vm.setPrototype(vA,vObject);
- VM.prototype.throw(value)
- value: Value
returnundefined
Equivalent to thethrow keyword.
constvError=vm.createError('unknown error');vm.throw(vError);
- VM.prototype.new(func[, arg1, arg2, arg3...])
- func: Value
- arg: Value
returnValue
Equivalent to thenew keyword.
constvA=vm.createFunction('A',function(name){vm.setProperty(this,'name',name);});vm.new(vA,vm.createString("A"));
- VM.prototype.call(func, thisPtr[, arg1, arg2, arg3...])
- func: Value
- thisPtr: Value | undefined
- arg: Value
returnValue
Equivalent to theFunction.prototype.call function.
constvLog=vm.createFunction('log',function(){consttemp=[];for(leti=0;i<arguments.length;i++){temp.push(vm.asString(arguments[i]));}console.log(...temp);// '1', 1, false});vm.call(vLog,vm.createUndefined(),vm.createString('1'),vm.createNumber(1),vm.createBoolean(false));
- VM.prototype.destroy
returnundefined
Destroy the VM instance.
vm.destroy();
sablejs may be the fastest interpreter written in JavaScript (using v8 benchmark suites):
Benchmark Enviorment:
- Node.js v12.19.0
- Golang 1.15.6
- GCC 5.4.0 -O3
- 2.4 GHz Intel Core i9
- MacOS Mojave 10.14.6 (18G6032)
| sablejs | sval | eval5 | quickjs-wasm | goja | |
|---|---|---|---|---|---|
| Language | JavaScript | JavaScript | JavaScript | C + WebAssembly | Golang |
| Richards | 110 | 24.9 | 24.7 | 376 | 208 |
| Crypto | 114 | 24.6 | 20.2 | 400 | 104 |
| RayTrace | 258 | 92.2 | 98.5 | 471 | 294 |
| NavierStokes | 183 | 35.9 | 49.8 | 665 | 191 |
| DeltaBlue | 120 | 35.3 | 29.5 | 402 | 276 |
| Total score | 148 | 37.3 | 37.3 | 452 | 202 |
| Baseline | 1 | ▼ 2.96 | ▼ 2.96 | ▲ 2.05 | ▲ 0.36 |
| File Size(KB) | 216 | 152 | 134 | 434 | - |
| Gzip Size(KB) | 29 | 40 | 34 | 245 | - |
- Dynamic execution by
evalandFunctionis forbidden, but passing literal string/number/null and undefined is allowed (the interpreter doesn't contain any compiler).
eval("print('Hello World!')");// it's okeval("var "+"a=1");// it's okvarstr="Hello World!";eval("print('"+str+"')");// throw SyntaxErrorFunction("a","b","return a+b");// it's oknewFunction("a","b","return a+b");// it's okvarstr="return a+b";Function("a","b",str);// throw SyntaxErrornewFunction("a","b",str);// throw SyntaxError
- The browser environment relies on native browser functions such as
btoa/unescape/decodeURIComponent, etc. if you need support for IE9 or below, you need to add shims.
- cax2sablejs - Canvas2D rendering engine for sablejs
- ajax2sablejs - A tiny and simple ajax for sablejs
sablejs JavaScript Engine
Copyright (c) 2020-Now ErosZhao
Permission is hereby granted, free of charge, to any person obtaining a copyof this software and associated documentation files (the "Software"), to dealin the Software without restriction, including without limitation the rightsto use, copy, modify, merge, publish, distribute, sublicense, and/or sellcopies of the Software, and to permit persons to whom the Software isfurnished to do so, subject to the following conditions:
Non-profit projects of individuals or organizations and commercial projects withcommercial authorization of the author.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS ORIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALLTHE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHERLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS INTHE SOFTWARE.
About
🏖️ The safer and faster ECMA5.1 interpreter written by JavaScript
Topics
Resources
License
Uh oh!
There was an error while loading.Please reload this page.
Stars
Watchers
Forks
Contributors4
Uh oh!
There was an error while loading.Please reload this page.
