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

jintr

Package Overview
Dependencies
Maintainers
1
Versions
19
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

jintr - npm Package Compare versions

Comparing version 1.1.0 to 1.2.0

dist/nodes/TemplateLiteral.d.ts

11

dist/main.d.ts

@@ -12,8 +12,13 @@ import Visitor from './visitor.js';

scope: Map<string, any>;
constructor(input: string);
constructor();
defineObject<T>(name: string, obj: T): void;
/**
* Interprets the program.
* Generates an AST from the input.
*/
parseScript(input: string): import("../acorn.js").ExtendNode<import("estree").Program>;
/**
* Evaluates the program.
* @returns The result of the last statement in the program.
*/
interpret(): any;
evaluate(input: string): any;
}

@@ -15,59 +15,54 @@ var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {

import { parse } from 'acorn';
import { JinterError } from './utils/index.js';
export default class Jinter {
constructor(input) {
_Jinter_ast.set(this, void 0);
const program = parse(input, { ecmaVersion: 2020 });
__classPrivateFieldSet(this, _Jinter_ast, program.body, "f");
this.visitor = new Visitor(__classPrivateFieldGet(this, _Jinter_ast, "f"));
constructor() {
_Jinter_ast.set(this, []);
this.visitor = new Visitor();
this.scope = this.visitor.scope;
this.scope.set('print', (args) => console.log(...args));
this.visitor.on('console', (node, visitor) => {
this.defineObject('console', console);
this.defineObject('Math', Math);
this.defineObject('String', String);
this.defineObject('Array', Array);
this.defineObject('Date', Date);
}
defineObject(name, obj) {
this.visitor.on(name, (node, visitor) => {
if (node.type === 'Identifier')
return console;
return obj;
if (node.type === 'CallExpression' && node.callee.type === 'MemberExpression') {
const prop = visitor.visitNode(node.callee.property);
const args = node.arguments.map((arg) => visitor.visitNode(arg));
const console_prop = console[prop];
if (!console_prop)
return 'proceed';
return console_prop(...args);
const callable = obj[prop];
if (!callable)
return '__continue_exec';
return callable.apply(obj, args);
}
return 'proceed';
return '__continue_exec';
});
this.visitor.on('Math', (node, visitor) => {
if (node.type === 'Identifier')
return Math;
if (node.type === 'CallExpression' && node.callee.type === 'MemberExpression') {
const prop = visitor.visitNode(node.callee.property);
const args = node.arguments.map((arg) => visitor.visitNode(arg));
const math_prop = Math[prop];
if (!math_prop)
return 'proceed';
return math_prop(...args);
}
return 'proceed';
});
this.visitor.on('String', (node, visitor) => {
if (node.type === 'Identifier')
return String;
if (node.type === 'CallExpression' && node.callee.type === 'MemberExpression') {
const prop = visitor.visitNode(node.callee.property);
const args = node.arguments.map((arg) => visitor.visitNode(arg));
const string_prop = String[prop];
if (!string_prop)
return 'proceed';
return string_prop(args);
}
return 'proceed';
});
this.visitor.on('Date', (node) => {
if (node.type === 'Identifier')
return Date;
});
}
/**
* Interprets the program.
* Generates an AST from the input.
*/
parseScript(input) {
try {
return parse(input, { ecmaVersion: 2020 });
}
catch (e) {
throw new JinterError(e.message);
}
}
/**
* Evaluates the program.
* @returns The result of the last statement in the program.
*/
interpret() {
evaluate(input) {
try {
const program = parse(input, { ecmaVersion: 2020 });
__classPrivateFieldSet(this, _Jinter_ast, program.body, "f");
}
catch (e) {
throw new JinterError(e.message);
}
this.visitor.setAST(__classPrivateFieldGet(this, _Jinter_ast, "f"));
return this.visitor.run();

@@ -74,0 +69,0 @@ }

@@ -6,4 +6,5 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {

};
var _CallExpression_instances, _CallExpression_throwError;
var _CallExpression_instances, _CallExpression_throwError, _CallExpression_getCalleeString;
import BaseJSNode from './BaseJSNode.js';
import { JinterError } from '../utils/index.js';
export default class CallExpression extends BaseJSNode {

@@ -27,3 +28,3 @@ constructor() {

const cb = this.visitor.listeners[exp_object](this.node, this.visitor);
if (cb !== 'proceed') {
if (cb !== '__continue_exec') {
return cb;

@@ -35,3 +36,3 @@ }

const cb = this.visitor.listeners[exp_property](this.node, this.visitor);
if (cb !== 'proceed') {
if (cb !== '__continue_exec') {
return cb;

@@ -47,2 +48,4 @@ }

const args = this.node.arguments.map((arg) => this.visitor.visitNode(arg));
if (!obj)
__classPrivateFieldGet(this, _CallExpression_instances, "m", _CallExpression_throwError).call(this);
if (typeof obj[prop] !== 'function')

@@ -62,8 +65,6 @@ __classPrivateFieldGet(this, _CallExpression_instances, "m", _CallExpression_throwError).call(this);

_CallExpression_instances = new WeakSet(), _CallExpression_throwError = function _CallExpression_throwError() {
if (this.node.callee.type === 'MemberExpression') {
throw new Error(`${this.node.callee.object.type === 'Identifier' ? this.node.callee.object.name : '<object>'}.${this.node.callee.property.type === 'Identifier' ? this.node.callee.property.name : '?'} is not a function`);
if (this.node.callee.type === 'MemberExpression' || this.node.callee.type === 'Identifier') {
const callee_string = __classPrivateFieldGet(this, _CallExpression_instances, "m", _CallExpression_getCalleeString).call(this, this.node.callee);
throw new JinterError(`${callee_string} is not a function`);
}
else if (this.node.callee.type === 'Identifier') {
throw new Error(`${this.node.callee.name} is not a function`);
}
else if (this.node.callee.type === 'SequenceExpression') {

@@ -91,4 +92,14 @@ const call = [];

call.push(')');
throw new Error(`${call.join('')} is not a function`);
throw new JinterError(`${call.join('')} is not a function`);
}
}, _CallExpression_getCalleeString = function _CallExpression_getCalleeString(node) {
if (node.type === 'Identifier') {
return node.name;
}
else if (node.type === 'MemberExpression') {
const object_string = __classPrivateFieldGet(this, _CallExpression_instances, "m", _CallExpression_getCalleeString).call(this, node.object);
const property_string = node.computed ? `[${this.visitor.getName(node.property) || '...'}]` : `.${this.visitor.getName(node.property)}`;
return `${object_string}${property_string}`;
}
return '<unknown>';
};

@@ -95,0 +106,0 @@ class Builtins {

@@ -6,3 +6,3 @@ import BaseJSNode from './BaseJSNode.js';

const cb = this.visitor.listeners[this.node.name](this.node, this.visitor);
if (cb !== 'proceed') {
if (cb !== '__continue_exec') {
return cb;

@@ -9,0 +9,0 @@ }

@@ -27,2 +27,3 @@ export { default as ArrayExpression } from './ArrayExpression.js';

export { default as SwitchStatement } from './SwitchStatement.js';
export { default as TemplateLiteral } from './TemplateLiteral.js';
export { default as ThisExpression } from './ThisExpression.js';

@@ -29,0 +30,0 @@ export { default as ThrowStatement } from './ThrowStatement.js';

@@ -28,2 +28,3 @@ // This file is auto-generated by ./scripts/build-nodes-map.js.

export { default as SwitchStatement } from './SwitchStatement.js';
export { default as TemplateLiteral } from './TemplateLiteral.js';
export { default as ThisExpression } from './ThisExpression.js';

@@ -30,0 +31,0 @@ export { default as ThrowStatement } from './ThrowStatement.js';

@@ -10,3 +10,3 @@ import BaseJSNode from './BaseJSNode.js';

const cb = this.visitor.listeners[prop](this.node, this.visitor);
if (cb !== 'proceed') {
if (cb !== '__continue_exec') {
return cb;

@@ -13,0 +13,0 @@ }

@@ -6,4 +6,4 @@ import BaseJSNode from './BaseJSNode.js';

const args = this.node.arguments.map((arg) => this.visitor.visitNode(arg));
return new callee(args);
return args.length ? new callee(args) : new callee();
}
}

@@ -11,1 +11,5 @@ import ESTree from 'estree';

}
export declare class JinterError extends Error {
info?: any;
constructor(message: string, info?: any);
}
export const namedFunction = (name, fn) => Object.defineProperty(fn, 'name', { value: name });
export class JinterError extends Error {
constructor(message, info) {
super(message);
if (info) {
this.info = info;
}
}
}

@@ -11,3 +11,3 @@ import type { Node } from 'estree';

ast: Node[];
constructor(ast: Node[]);
setAST(ast: Node[]): void;
run(): any;

@@ -14,0 +14,0 @@ /**

@@ -9,6 +9,9 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {

export default class Visitor {
constructor(ast) {
constructor() {
_Visitor_instances.add(this);
this.scope = new Map();
this.listeners = {};
this.ast = [];
}
setAST(ast) {
this.ast = ast;

@@ -15,0 +18,0 @@ }

{
"name": "jintr",
"version": "1.1.0",
"version": "1.2.0",
"description": "A tiny JavaScript interpreter written in TypeScript.",

@@ -5,0 +5,0 @@ "type": "module",

@@ -21,3 +21,3 @@ [actions]: https://github.com/LuanRT/Jinter/actions

- [API](#api)
- [`interpret()`](#interpret)
- [`evaluate(input: string)`](#evaluateinput-string)
- [`visitor`](#visitor)

@@ -47,17 +47,31 @@ - [`scope`](#scope)

const jinter = new Jinter(code);
jinter.interpret();
const jinter = new Jinter();
jinter.evaluate(code);
```
---
Inject your own functions and variables into the interpreter:
Inject your own functions, objects, etc:
```ts
// ...
import { Jinter } from 'jintr';
jinter.visitor.on('println', (node, visitor) => {
if (node.type === 'CallExpression' && node.callee.type === 'MemberExpression') {
const args = node.arguments.map((arg) => visitor.visitNode(arg));
return console.log(...args);
const jinter = new Jinter();
const code = `
console.log(new SomeClass().a);
console.log('hello'.toArray());
function myFn() {
console.log('[myFn]: Who called me?');
}
});
myFn();
`;
class SomeClass {
constructor() {
this.a = 'this is a test';
}
}
jinter.defineObject('SomeClass', SomeClass);
// Ex: str.toArray();

@@ -67,13 +81,14 @@ jinter.visitor.on('toArray', (node, visitor) => {

const obj = visitor.visitNode(node.callee.object);
return obj.split('');
}
return obj.split('');
}
});
// Or you can just intercept access to specific nodes;
jinter.visitor.on('myFn', (node, visitor) => {
console.info('MyFn node just got accessed:', node);
return 'proceed'; // tells the interpreter to continue execution
// Intercept function calls
jinter.visitor.on('myFn', (node) => {
if (node.type == 'CallExpression')
console.info('myFn was called!');
return '__continue_exec';
});
jinter.interpret();
jinter.evaluate(code);
```

@@ -84,9 +99,9 @@

## API
* Jinter(code: string)
* [`interpret()`](#interpret)
* Jinter()
* [`evaluate(input: string)`](#evaluate)
* [`visitor`](#visitor)
* [`scope`](#scope)
### `interpret()`
Interprets the code passed to the constructor.
### `evaluate(input: string)`
Evaluates the given JavaScript code.

@@ -93,0 +108,0 @@ ### `visitor`

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

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