Module @ibyar/expressions - v3.1.0

Ibyar Expression

NPM Version NPM Downloads LICENSE lerna GitHub contributors

	Your Mirror Dimension in the javascript world.

Ibyar expression, is a JavaScript expression parsing and evaluation. and template expression evaluation, with stack and scope.

  • this package has no dependance, can work on both (Node.js) and any Web Browsers, that support modules and class syntax
  • An 100% spec compliant ES2022 JavaScript toolchain
npm i --save @ibyar/expressions
yarn add @ibyar/expressions
import { JavaScriptParser, Scope, Stack } from '@ibyar/expressions';

const source = `
let { x, y } = {x: 5, y: 55};
const z = x / y;
console.log({x, y, z});
const alex = { firstName: 'alex', lastName: 'jon', age: 30 };
alex.fullName = function(){ return this.firstName + ' ' + this.lastName;};
console.log(alex.fullName());
console.log(alex.fullName.toString());
setTimeout(() => console.log('setTimeout', alex), 500);
const sara = { firstName: 'sara', lastName: 'jon', age: 28, [Symbol.toStringTag]: 'SARA'};
console.log(sara['age']);
console.log('toStringTag', Object.prototype.toString.call(sara));
console.log('compare', sara.age <=> alex.age);
console.log('older', sara.age >? alex.age);
console.log('younger', sara.age <? alex.age);
console.log('typeof', typeof alex);
console.log('typeof', typeof alex.age);
console.log('regex 1', /regex/g.test('reg'));
console.log('regex 2', /regex/g.test('regex'));
`
+
'let stringLiteralExample = `${alex.firstName} and ${sara.firstName} are friends`; console.log({stringLiteralExample});'
+
`
function latex(str) {
return { "cooked": str[0], "raw": str.raw[0] }
}
`
+
'let taggedStringLiteral = latex`Hi\n${2+3}!`; console.log({taggedStringLiteral});'
;

const pipeSource = `
const add = (arg1, arg2) => arg1 + arg2;
a
|> function(s) {return s;}
|> (c => b = c + 1)
|> add(?, 2)
|> add(3, ?)
|> console.log:4:5;`;

const ast = JavaScriptParser.parse(source + pipeSource);
const esTree = ast.toJSON();
const esTreeString = JSON.stringify(ast, void 0, 2);
console.log({ esTree, esTreeString });
const context = {
Promise,
setTimeout,
console,
Symbol,
Object
};
const stack = Stack.for(context);
const globalScope = Scope.functionScopeFor({
a: 7,
b: undefined
});
stack.pushScope(globalScope);
ast.get(stack);
console.log(
'from global context values: x: %s, y: %s',
globalScope.getContext().x,
globalScope.getContext().y
);
console.log(
globalScope.getContext()
);
  • V8 JavaScript engine to parse js source code.
  • for now this parser does not provide any info about SourceLocation
  • class expression
  • Import/Export module
  • Custom Factory Builder to convert the code to ESTree directly or to executable expression node
Operator type Individual operators
member . []
call / create instance () new
negation/increment ! ~ - + ++ -- typeof void delete
multiply/divide * / % ** %%
addition/subtraction + -
bitwise shift << >> >>>
relational < <= > >= >? <? <=> in instanceof
equality == != === !==
bitwise-and &
bitwise-xor ^
bitwise-or |
logical-and &&
logical-or ||
conditional ?:
pipeline |>
assignment = += -= *= **= /= %= <<= >>= >>>= &= ^= |= &&= ||= ??= >?= <?= %%=
comma ,

non-ecma operator are %% >? <? <=> >?= <?= %%=

  • support angular-like syntax and partial operator for a call syntax:
x |> methodName1:arg2:arg3
|> methodName2(arg1, ?, ...arg3);


function add(x, y, z) { return x + y + z };
const a = 88;
const b = 99;
const c = 11;
const z = a |> add:b:c; // === add(a, b, c)
function map(num){
return { number: num };
}
function plus(num1){
return function(num2){
return num1 + num2;
};
}
function add(x, y) { return x + y };
const a = 88, b = 11;
b |> function(x) { console.log(x); return x; }
|> x => { console.log(x); return x; }
|> (x => x + 10)
|> plus(a)
|> add(99, ?)
|> add : 88 : ?
|> add : ? : 77
|> map

1- create stack:

import { Scope, Stack } from '@ibyar/expressions';

const stack1 = new Stack();

// OR

const scope1 = new Scope<{x: number, y: number}>( {x: 8, y: 6});
const scope2 = Scope.for({z: 9});

const stack2 = new Stack([scope1, scope2]);

2- any of the previous stacks, does not provide and public api like Math, String, .... you need to provide these values to the stack, the stack work as a sandbox, isolated from the js-VM.

import { ReadOnlyScope } from '@ibyar/expressions';

stack1.pushScope(ReadOnlyScope.for({
Math: {
E: Math.E,
LN10: Math.LN10,
LN2: Math.LN2,
LOG10E: Math.LOG10E,
LOG2E: Math.LOG2E,
PI: Math.PI,
SQRT1_2: Math.SQRT1_2,
SQRT2: Math.SQRT2,

abs: Math.abs,
acos: Math.acos,
asin: Math.asin,
atan: Math.atan,
atan2: Math.atan2,
ceil: Math.ceil,
....
},
// or
Math,
// another object
Array: {
// in js a statement like `let x = new Array()` will throw exception.
isArray: Array.isArray,
},

Array, // `let x = new Array()` no Error.


parseFloat,
parseInt,
String,
console,
}));
so now you can write js code the use these as identifier

3- the stack is ready to use with expression 4- try to parse an expression like let x = 'data'; console.log(x);.

import { JavaScriptParser } from '@ibyar/expressions';

const ast = JavaScriptParser.parse(`let x = 'data'; console.log(x);`);

// use get method to execute an expression and return a value if available.

ast.get(stack1);
// it should print 'data' on the console

5- you can visit the ast

import { expressionVisitor, VariableDeclaration } from '@ibyar/expressions';

expressionVisitor.visit(ast, (expression, type, control) => {
if (type === 'VariableDeclaration') {
const kind = (expression as VariableDeclaration).getKind();

....
}
});

reactive scope is used to

import { JavaScriptParser, ReactiveScope, Stack } from '@ibyar/expressions';

// parse JS code
const ast = JavaScriptParser.parse(`
const x = 'Hello';
const y = "World";

let z = x + ' ' + y + '!';
z = 123 + 456;
z = (x + ' ' + y).toUpperCase();
z = 'Reactive Scope is Awesome!!';

`);

// create reactive scope, can listen to changes of variables
const reactiveScope = ReactiveScope.blockScope();


// listen for changes of 'z' variable
const zSubscription = reactiveScope.subscribe('z', (nz, oz) => {
console.log('new value of Z = ' + nz, 'old value of Z = ' + oz);
});

// listen for changes of 'z' const
const xSubscription = reactiveScope.subscribe('x', (nx, ox) => {
console.log('new value of X = ' + nx, 'old value of X = ' + ox);
});

// create stack
const stack = new Stack(reactiveScope);

// execute js code
ast.get(stack);

// unsubscribe from all created ScopeSubscription
zSubscription.unsubscribe();
xSubscription.unsubscribe();

Enumerations

AllowLabelledFunctionStatement
ClassLiteralPropertyKind
FunctionBodyType
FunctionKind
FunctionNameValidity
FunctionSyntaxKind
LanguageMode
ObjectLiteralPropertyKind
ParseFunctionFlag
ParsingArrowHeadFlag
PreParserIdentifierType
PropertyKind
PropertyPosition
StaticFlag
SubFunctionKind
VariableDeclarationContext
VariableMode

Classes

AbstractDefinition
AbstractExpressionNode
AbstractParser
AccessorProperty
ArrayExpression
ArrayPattern
ArrowFunctionExpression
AssignmentExpression
AssignmentPattern
AwaitExpression
AwaitPromise
BinaryExpression
BindExpression
BlockStatement
BreakStatement
CallExpression
CatchClauseNode
ChainExpression
Class
ClassBody
ClassDeclaration
ClassExpression
ClassLiteralProperty
CommentExpression
Computed
ConditionalExpression
ContinueStatement
DebuggerStatement
Decorator
DefaultExpression
DoWhileNode
EmptyStatement
ExpressionStatement
ExpressionVisitor
ForAwaitOfNode
ForInNode
ForNode
ForOfNode
FunctionDeclaration
FunctionExpression
GroupingExpression
Identifier
IfStatement
InfixExpressionNode
JavaScriptInlineParser
JavaScriptParser
LabeledStatement
Lazy
Literal
LogicalExpression
MemberExpression
MetaProperty
MethodDefinition
ModuleScope
ModuleScopeResolver
NewExpression
ObjectExpression
ObjectLiteralProperty
ObjectPattern
PipelineExpression
PreTemplateLiteral
PrivateIdentifier
Program
Property
PropertyDefinition
PropertyKindInfo
ReactiveControlScope
ReactiveNode
ReactiveScope
ReadOnlyScope
ReadOnlySignal
RestElement
ReturnStatement
ReturnValue
Scope
ScopeProxyHandler
ScopeSubscription
SequenceExpression
Signal
SignalScope
SpreadElement
Stack
StaticBlock
Super
SwitchCase
SwitchStatement
TaggedTemplateExpression
TemplateLiteral
TemplateLiteralExpressionNode
TemplateStringLiteral
TerminateReturnType
ThisExpression
ThrowStatement
Token
TokenExpression
TokenStream
TokenStreamer
TokenStreamImpl
TryCatchNode
UnaryExpression
UpdateExpression
ValueChangeObserver
VariableDeclarationNode
VariableDeclarator
WebModuleScope
WhileNode
WithStatement
YieldDelegateValue
YieldExpression
YieldValue

Interfaces

AsyncIterableInfo
AwaitPromiseInfo
CanFindScope
ControlScope
DeclarationExpression
EvaluateNode
EvaluateType
ExpressionNodConstructor
ExpressionNode
ModuleContext
ModuleImport
ModuleSourceProvider
Position
ResolverConfig
SourceLocation
VisitorControl

Type Aliases

AssignmentOperator
BinaryOperator
ClassInfo
CleanupFn
CleanupRegister
Context
DeclarationType
EvaluateCallback
ExpressionEventMap
ExpressionEventPath
ExpressionEventPathBracketNotation
ExpressionEventPathDotNotation
ForDeclaration
FunctionInfo
HoistableDeclaration
InlineParserOptions
LexicalDeclaration
LogicalOperator
MethodDefinitionKind
NodeDeserializer
NodeJsonType
NodeType
ParserOptions
PositionMark
ProgramSourceType
Range
RangeOrVoid
RevocableProxy
SignalDestroyRef
TerminateType
UnaryOperator
UpdateOperator
ValueChangedCallback
VisitNodeType
VisitorCallback

Variables

expressionVisitor
IdentifierPartRegex
IdentifierRegex
IdentifierStartRegex

Functions

bindsSuper
classPropertyKindFor
createClassInfo
createProxyForContext
createRevocableProxyForContext
createRootURL
deserialize
deserializeNode
Deserializer
findReactiveScopeByEventMap
findScopeByEventMap
functionKind2String
functionKindFor
functionKindForImpl
getDeserializerType
getLanguageMode
getVariableMode
hasBindingHook
isAccessor
isAccessorFunction
isArrowFunction
isAsyncFunction
isAsyncGeneratorFunction
isAsyncModule
isAwaitAsIdentifierDisallowed
isBaseConstructor
isClassConstructor
isClassMembersInitializerFunction
isComputed
isConciseMethod
isConstructable
isDefaultConstructor
isDerivedConstructor
isGeneratorFunction
isGetterFunction
isInRange
isLazy
isModule
isReactive
isReadOnlySignal
isResumableFunction
isSetterFunction
isSignal
isSloppy
isStatic
isStrict
isStrictFunctionWithoutPrototype
methodKindFor
serializeNode