Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

evaljs

Package Overview
Dependencies
Maintainers
1
Versions
11
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

evaljs - npm Package Compare versions

Comparing version 0.2.0 to 0.3.0

382

index.js
"use strict";
//TODO:
//- scan blocks for declaration statements before executing incl. handle
// undefined + maybe es5 reference errors in strict mode
//- SwitchStatement
//- LabeledStatement -> including use in break/continue

@@ -36,19 +33,21 @@ //-> TESTS

function Environment(scopesOrGlobalObj) {
if (!Array.isArray(scopesOrGlobalObj)) {
scopesOrGlobalObj = [scopesOrGlobalObj];
function Environment(globalObjects) {
if (!Array.isArray(globalObjects)) {
globalObjects = [globalObjects];
}
var parent;
scopesOrGlobalObj.forEach(function (vars) {
parent = createScope(vars, parent);
globalObjects.forEach(function (vars) {
parent = createVarStore(parent, vars);
});
// the topmost scope is our current scope
this._curScope = parent;
this._globalObj = scopesOrGlobalObj[0];
// the topmost store is our current store
this._curVarStore = parent;
this._curDeclarations = [];
this._globalObj = globalObjects[0];
this._curThis = this._globalObj;
this._boundGen = this.gen.bind(this);
this._boundGen = this._gen.bind(this);
}
function createScope(vars, parent) {
function createVarStore(parent, vars) {
vars = vars || {};
return {

@@ -61,36 +60,44 @@ parent: parent,

Environment.prototype.gen = function (node) {
var resp = this._gen(node);
addDeclarationsToStore(this._curDeclarations, this._curVarStore);
this._curDeclarations = [];
return resp;
};
Environment.prototype._gen = function (node) {
return ({
BinaryExpression: this.genBinExpr,
LogicalExpression: this.genBinExpr,
UnaryExpression: this.genUnaryExpr,
UpdateExpression: this.genUpdExpr,
ObjectExpression: this.genObjExpr,
ArrayExpression: this.genArrExpr,
CallExpression: this.genCallExpr,
NewExpression: this.genNewExpr,
MemberExpression: this.genMemExpr,
ThisExpression: this.genThisExpr,
SequenceExpression: this.genSeqExpr,
Literal: this.genLit,
Identifier: this.genIdent,
AssignmentExpression: this.genAssignExpr,
FunctionDeclaration: this.genFuncDecl,
VariableDeclaration: this.genVarDecl,
BlockStatement: this.genProgram,
Program: this.genProgram,
ExpressionStatement: this.genExprStmt,
EmptyStatement: this.genEmptyStmt,
ReturnStatement: this.genRetStmt,
FunctionExpression: this.genFuncExpr,
IfStatement: this.genIfStmt,
ConditionalExpression: this.genIfStmt,
ForStatement: this.genLoopStmt,
WhileStatement: this.genLoopStmt,
DoWhileStatement: this.genDoWhileStmt,
ForInStatement: this.genForInStmt,
WithStatement: this.genWithStmt,
ThrowStatement: this.genThrowStmt,
TryStatement: this.genTryStmt,
ContinueStatement: this.genContStmt,
BreakStatement: this.genBreakStmt,
BinaryExpression: this._genBinExpr,
LogicalExpression: this._genBinExpr,
UnaryExpression: this._genUnaryExpr,
UpdateExpression: this._genUpdExpr,
ObjectExpression: this._genObjExpr,
ArrayExpression: this._genArrExpr,
CallExpression: this._genCallExpr,
NewExpression: this._genNewExpr,
MemberExpression: this._genMemExpr,
ThisExpression: this._genThisExpr,
SequenceExpression: this._genSeqExpr,
Literal: this._genLit,
Identifier: this._genIdent,
AssignmentExpression: this._genAssignExpr,
FunctionDeclaration: this._genFuncDecl,
VariableDeclaration: this._genVarDecl,
BlockStatement: this._genProgram,
Program: this._genProgram,
ExpressionStatement: this._genExprStmt,
EmptyStatement: this._genEmptyStmt,
ReturnStatement: this._genRetStmt,
FunctionExpression: this._genFuncExpr,
IfStatement: this._genIfStmt,
ConditionalExpression: this._genIfStmt,
ForStatement: this._genLoopStmt,
WhileStatement: this._genLoopStmt,
DoWhileStatement: this._genDoWhileStmt,
ForInStatement: this._genForInStmt,
WithStatement: this._genWithStmt,
ThrowStatement: this._genThrowStmt,
TryStatement: this._genTryStmt,
ContinueStatement: this._genContStmt,
BreakStatement: this._genBreakStmt,
SwitchStatement: this._genSwitchStmt,
}[node.type] || function () {

@@ -102,3 +109,3 @@ console.warn("Not implemented yet: " + node.type);

Environment.prototype.genBinExpr = function (node) {
Environment.prototype._genBinExpr = function (node) {
var cmp = {

@@ -131,4 +138,4 @@ '==': function (a, b) {return a == b; },

var left = this.gen(node.left);
var right = this.gen(node.right);
var left = this._gen(node.left);
var right = this._gen(node.right);
return function () {

@@ -139,3 +146,3 @@ return cmp(left(), right());

Environment.prototype.genUnaryExpr = function (node) {
Environment.prototype._genUnaryExpr = function (node) {
var op = {

@@ -151,3 +158,3 @@ '-': function (a) {return -a; },

}[node.operator];
var argument = this.gen(node.argument);
var argument = this._gen(node.argument);

@@ -159,3 +166,3 @@ return function () {

Environment.prototype.genObjExpr = function (node) {
Environment.prototype._genObjExpr = function (node) {
//TODO property.kind: don't assume init when it can also be set/get

@@ -170,3 +177,3 @@ var self = this;

key: key,
getVal: self.gen(property.value)
getVal: self._gen(property.value)
});

@@ -184,3 +191,3 @@ });

Environment.prototype.genArrExpr = function (node) {
Environment.prototype._genArrExpr = function (node) {
var items = node.elements.map(this._boundGen);

@@ -197,3 +204,3 @@ return function () {

} else {
key = this.gen(node)();
key = this._gen(node)();
}

@@ -203,3 +210,3 @@ return function () {return key; };

Environment.prototype.genCallExpr = function (node) {
Environment.prototype._genCallExpr = function (node) {
var self = this;

@@ -216,5 +223,5 @@

} else {
callee = self.gen(node.callee);
callee = self._gen(node.callee);
}
var args = node.arguments.map(self.gen.bind(self));
var args = node.arguments.map(self._gen.bind(self));
return function () {

@@ -225,4 +232,4 @@ return callee().apply(self._globalObj, args.map(execute));

Environment.prototype.genNewExpr = function (node) {
var callee = this.gen(node.callee);
Environment.prototype._genNewExpr = function (node) {
var callee = this._gen(node.callee);
var args = node.arguments.map(this._boundGen);

@@ -239,4 +246,4 @@ return function () {

Environment.prototype.genMemExpr = function (node) {
var obj = this.gen(node.object);
Environment.prototype._genMemExpr = function (node) {
var obj = this._gen(node.object);
var property = this._memExprProperty(node);

@@ -249,6 +256,6 @@ return function () {

Environment.prototype._memExprProperty = function (node) {
return node.computed ? this.gen(node.property) : this._objKey(node.property);
return node.computed ? this._gen(node.property) : this._objKey(node.property);
};
Environment.prototype.genThisExpr = function () {
Environment.prototype._genThisExpr = function () {
var self = this;

@@ -258,3 +265,3 @@ return function () {return self._curThis; };

Environment.prototype.genSeqExpr = function (node) {
Environment.prototype._genSeqExpr = function (node) {
var exprs = node.expressions.map(this._boundGen);

@@ -270,3 +277,3 @@ return function () {

Environment.prototype.genUpdExpr = function (node) {
Environment.prototype._genUpdExpr = function (node) {
var update = {

@@ -287,5 +294,5 @@ '--true': function (obj, name) {return --obj[name]; },

if (node.type === 'Identifier') {
return this._getScopeVars.bind(this, node.name);
return this._getVarStore.bind(this, node.name);
} else if (node.type === 'MemberExpression') {
return this.gen(node.object);
return this._gen(node.object);
} else {

@@ -308,3 +315,3 @@ console.warn("Unknown _genObj() type: " + node.type);

Environment.prototype.genLit = function (node) {
Environment.prototype._genLit = function (node) {
return function () {

@@ -315,22 +322,22 @@ return node.value;

Environment.prototype.genIdent = function (node) {
Environment.prototype._genIdent = function (node) {
var self = this;
return function () {
return self._getScopeVars(node.name)[node.name];
return self._getVarStore(node.name)[node.name];
};
};
Environment.prototype._getScopeVars = function (name) {
var scope = this._curScope;
Environment.prototype._getVarStore = function (name) {
var store = this._curVarStore;
do {
if (scope.vars.hasOwnProperty(name)) {
return scope.vars;
if (store.vars.hasOwnProperty(name)) {
return store.vars;
}
} while ((scope = scope.parent));
} while ((store = store.parent));
// global scope if no other scope has been found
return this._globalObject;
// global object as fallback
return this._globalObj;
};
Environment.prototype.genAssignExpr = function (node) {
Environment.prototype._genAssignExpr = function (node) {
var setter = {

@@ -352,3 +359,3 @@ '=': function (obj, name, val) {return (obj[name] = val); },

var name = this._genName(node.left);
var val = this.gen(node.right);
var val = this._gen(node.right);
return function () {

@@ -359,34 +366,46 @@ return setter(obj(), name(), val());

Environment.prototype.genFuncDecl = function (node) {
var self = this;
var func = self.genFuncExpr(node);
return function () {
self._curScope.vars[node.id.name] = func();
};
Environment.prototype._genFuncDecl = function (node) {
this._curDeclarations.push(node.id.name);
node.type = 'FunctionExpression';
return this._gen({
type: 'AssignmentExpression',
operator: '=',
left: node.id,
right: node
});
};
Environment.prototype.genVarDecl = function (node) {
var self = this;
var decls = node.declarations.map(function (decl) {
return {
name: decl.id.name,
getVal: decl.init ? self.gen(decl.init) : noop,
};
Environment.prototype._genVarDecl = function (node) {
var assignments = [];
for (var i = 0; i < node.declarations.length; i++) {
var decl = node.declarations[i];
this._curDeclarations.push(decl.id.name);
if (decl.init) {
assignments.push({
type: 'AssignmentExpression',
operator: '=',
left: decl.id,
right: decl.init
});
}
}
return this._gen({
type: 'BlockStatement',
body: assignments
});
return function () {
decls.forEach(function (decl) {
self._curScope.vars[decl.name] = decl.getVal();
});
};
};
Environment.prototype.genFuncExpr = function (node) {
Environment.prototype._genFuncExpr = function (node) {
var self = this;
self._curScope = createScope({}, self._curScope);
var body = self.gen(node.body);
// reset scope
var scope = self._curScope;
self._curScope = scope.parent;
var oldDeclarations = self._curDeclarations;
self._curDeclarations = [];
var body = self._gen(node.body);
var declarations = self._curDeclarations;
self._curDeclarations = oldDeclarations;
// reset var store
return function () {
var parent = self._curVarStore;
return function () {

@@ -399,12 +418,15 @@ // build arguments object

}
scope.vars.arguments = args;
// add function args to scope
var varStore = createVarStore(parent);
addDeclarationsToStore(declarations, varStore);
varStore.vars.arguments = args;
// add function args to var store
node.params.forEach(function (param, i) {
scope.vars[param.name] = args[i];
varStore.vars[param.name] = args[i];
});
// switch interpreter 'stack'
var oldScope = self._curScope;
var oldStore = self._curVarStore;
var oldThis = self._curThis;
self._curScope = scope;
self._curVarStore = varStore;
self._curThis = this;

@@ -417,3 +439,3 @@

self._curThis = oldThis;
self._curScope = oldScope;
self._curVarStore = oldStore;

@@ -427,6 +449,14 @@ if (result instanceof Return) {

Environment.prototype.genProgram = function (node) {
function addDeclarationsToStore(declarations, varStore) {
for (var i = 0; i < declarations.length; i++) {
if (!varStore.vars.hasOwnProperty(declarations[i])) {
varStore.vars[declarations[i]] = undefined;
}
}
}
Environment.prototype._genProgram = function (node) {
var self = this;
var stmtClosures = node.body.map(function (stmt) {
return self.gen(stmt);
return self._gen(stmt);
});

@@ -446,12 +476,12 @@ return function () {

Environment.prototype.genExprStmt = function (node) {
return this.gen(node.expression);
Environment.prototype._genExprStmt = function (node) {
return this._gen(node.expression);
};
Environment.prototype.genEmptyStmt = function () {
Environment.prototype._genEmptyStmt = function () {
return noop;
};
Environment.prototype.genRetStmt = function (node) {
var arg = this.gen(node.argument);
Environment.prototype._genRetStmt = function (node) {
var arg = this._gen(node.argument);
return function () {

@@ -462,6 +492,6 @@ return new Return(arg());

Environment.prototype.genIfStmt = function (node) {
var test = this.gen(node.test);
var consequent = this.gen(node.consequent);
var alternate = node.alternate ? this.gen(node.alternate) : noop;
Environment.prototype._genIfStmt = function (node) {
var test = this._gen(node.test);
var consequent = this._gen(node.consequent);
var alternate = node.alternate ? this._gen(node.alternate) : noop;

@@ -473,9 +503,9 @@ return function () {

Environment.prototype.genLoopStmt = function (node, body) {
var init = node.init ? this.gen(node.init) : noop;
var test = node.test ? this.gen(node.test) : function () {
Environment.prototype._genLoopStmt = function (node, body) {
var init = node.init ? this._gen(node.init) : noop;
var test = node.test ? this._gen(node.test) : function () {
return true;
};
var update = node.update ? this.gen(node.update) : noop;
body = body || this.gen(node.body);
var update = node.update ? this._gen(node.update) : noop;
body = body || this._gen(node.body);

@@ -501,5 +531,5 @@ return function () {

Environment.prototype.genDoWhileStmt = function (node) {
var body = this.gen(node.body);
var loop = this.genLoopStmt(node, body);
Environment.prototype._genDoWhileStmt = function (node) {
var body = this._gen(node.body);
var loop = this._genLoopStmt(node, body);

@@ -512,7 +542,7 @@ return function () {

Environment.prototype.genForInStmt = function (node) {
Environment.prototype._genForInStmt = function (node) {
/* var self = this;
var left = self.gen(node.left);
var right = self.gen(node.right);
var body = self.gen(node.body);
var left = self._gen(node.left);
var right = self._gen(node.right);
var body = self._gen(node.body);

@@ -526,3 +556,3 @@ var left = node.left;

for (x in right()) {
self.genAssignExpr({
self._genAssignExpr({
left: left,

@@ -541,11 +571,10 @@ right: {

Environment.prototype.genWithStmt = function (node) {
Environment.prototype._genWithStmt = function (node) {
var self = this;
var obj = self.gen(node.object);
var body = self.gen(node.body);
var obj = self._gen(node.object);
var body = self._gen(node.body);
return function () {
var prevScope = self._curScope;
self._curScope = createScope(obj(), prevScope);
self._curVarStore = createVarStore(self._curVarStore, obj());
var result = body();
self._curScope = prevScope;
self._curVarStore = self._curVarStore.parent;
return result;

@@ -555,4 +584,4 @@ };

Environment.prototype.genThrowStmt = function (node) {
var arg = this.gen(node.argument);
Environment.prototype._genThrowStmt = function (node) {
var arg = this._gen(node.argument);
return function () {

@@ -563,6 +592,6 @@ throw arg();

Environment.prototype.genTryStmt = function (node) {
var block = this.gen(node.block);
Environment.prototype._genTryStmt = function (node) {
var block = this._gen(node.block);
var handler = this._genCatchHandler(node.handler);
var finalizer = node.finalizer ? this.gen(node.finalizer) : null;
var finalizer = node.finalizer ? this._gen(node.finalizer) : null;

@@ -588,8 +617,8 @@ return function () {

var self = this;
var body = self.gen(node.body);
var body = self._gen(node.body);
return function (err) {
var old = self._curScope[node.param.name];
self._curScope[node.param.name] = err;
var old = self._curVarStore.vars[node.param.name];
self._curVarStore.vars[node.param.name] = err;
var resp = body();
self._curScope[node.param.name] = old;
self._curVarStore.vars[node.param.name] = old;

@@ -600,21 +629,62 @@ return resp;

Environment.prototype.genContStmt = function () {
Environment.prototype._genContStmt = function () {
return function () {return Continue; };
};
Environment.prototype.genBreakStmt = function () {
Environment.prototype._genBreakStmt = function () {
return function () {return Break; };
};
Environment.prototype._genSwitchStmt = function (node) {
var self = this;
var discriminant = self._gen(node.discriminant);
var cases = node.cases.map(function (curCase) {
return {
test: curCase.test ? self._gen(curCase.test) : null,
code: self._genProgram({body: curCase.consequent})
};
});
return function () {
var foundMatch = false;
var discriminantVal = discriminant();
var resp, defaultCase;
for (var i = 0; i < cases.length; i++) {
var curCase = cases[i];
if (!foundMatch) {
if (!curCase.test) {
defaultCase = curCase;
continue;
}
if (discriminantVal !== curCase.test()) {
continue;
}
foundMatch = true;
}
// foundMatch is guaranteed to be true here
var newResp = curCase.code();
if (newResp === Break) {
return resp;
}
resp = newResp;
if (resp === Continue || resp instanceof Return) {
return resp;
}
}
if (!foundMatch && defaultCase) {
return defaultCase.code();
}
};
};
exports.Environment = Environment;
var evaling = false;
exports.evaluate = function (code) {
var ast = parse(code);
evaling = true;
var env = new Environment(global);
var resp = env.gen(ast)();
evaling = false;
return resp;
};
console.log(exports.evaluate("2 + 1"));
//console.log(exports.evaluate("1 + 1"));
{
"name": "evaljs",
"version": "0.2.0",
"version": "0.3.0",
"description": "A JavaScript interpreter written in JavaScript",

@@ -5,0 +5,0 @@ "main": "index.js",

@@ -10,4 +10,2 @@ eval.js

ATTENTION: THIS IS A WORK-IN-PROGRESS
Why?

@@ -60,2 +58,9 @@ ----

Is it complete?
---------------
No labeled statements; no nice error handling; there are probably bugs.
That said, it can run itself so it's supported subset of JS is usable.
PRs welcome!
How slow is it?

@@ -62,0 +67,0 @@ ---------------

@@ -9,2 +9,8 @@ "use strict";

var env = new evaljs.Environment([{console: console}]);
env.gen(parse(code))();
//index.js
var code = fs.readFileSync('index.js', {encoding: 'UTF-8'});
var envGlobal = {console: console, Array: Array, Error: Error, Object: Object};

@@ -11,0 +17,0 @@ envGlobal.global = global;

@@ -6,3 +6,6 @@ // not strict, 'cause we need to parse the with statement

/* jshint -W027 */
// missing break statements in switch statements are ok
/* jshint -W086 */
/*
var op = {

@@ -93,3 +96,17 @@ '+': function (a, b) {return a + b; }

/*
console.log(function () {
var x = 4;
console.log(1);
if (x) {
console.log(2);
for (var i = 0; i < 3; i++) {
console.log(3);
return x;
console.log(5);
}
console.log(6);
}
console.log(7);
}());
*/
var x = 2;

@@ -99,2 +116,3 @@ switch (x) {

console.log(1);
//falls through
case 2:

@@ -104,8 +122,46 @@ console.log(2);

console.log(3);
break
break;
case 4:
console.log(4);
default:
console.log(5);
}
*/
switch (x) {
case 1:
console.log(1);
default:
console.log(2);
}
switch (x) {
case 2:
console.log(3);
break;
default:
console.log(4);
}
switch (x) {
case 2:
console.log(5);
default:
console.log(6);
}
switch (x) {
default:
console.log(7);
case 2:
console.log(8);
}
switch (x) {
default:
console.log(9);
break;
case 2:
console.log(10);
}
/*

@@ -122,16 +178,1 @@ for (var key in {a: 1, b: 2}) {

/*jshint ignore:end*/
console.log(function () {
var x = 4;
console.log(1);
if (x) {
console.log(2);
for (var i = 0; i < 3; i++) {
console.log(3);
return x;
console.log(5);
}
console.log(6);
}
console.log(7);
}());
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc