{"id":16666863,"url":"https://github.com/smelukov/estel","last_synced_at":"2025-04-09T19:16:55.386Z","repository":{"id":80898708,"uuid":"87552345","full_name":"smelukov/estel","owner":"smelukov","description":"ESTree AST interpreter with dynamic analyzing","archived":false,"fork":false,"pushed_at":"2017-04-14T21:23:58.000Z","size":77,"stargazers_count":11,"open_issues_count":6,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-04-09T19:16:49.371Z","etag":null,"topics":["ast","ecmascript","estree","javascript","parser","processor"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/smelukov.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-04-07T14:01:38.000Z","updated_at":"2024-11-29T18:43:29.000Z","dependencies_parsed_at":"2023-04-20T14:01:46.454Z","dependency_job_id":null,"html_url":"https://github.com/smelukov/estel","commit_stats":null,"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/smelukov%2Festel","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/smelukov%2Festel/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/smelukov%2Festel/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/smelukov%2Festel/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/smelukov","download_url":"https://codeload.github.com/smelukov/estel/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248094988,"owners_count":21046770,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ast","ecmascript","estree","javascript","parser","processor"],"created_at":"2024-10-12T11:12:15.002Z","updated_at":"2025-04-09T19:16:55.377Z","avatar_url":"https://github.com/smelukov.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![NPM version](https://img.shields.io/npm/v/estel.svg)](https://www.npmjs.com/package/estel)\n[![Build Status](https://travis-ci.org/smelukov/estel.svg?branch=master)](https://travis-ci.org/smelukov/estel)\n[![Coverage Status](https://coveralls.io/repos/github/smelukov/estel/badge.svg?branch=master)](https://coveralls.io/github/smelukov/estel?branch=master)\n\n**Estel** is [ESTree](https://github.com/estree/estree) AST interpreter with dynamic analyzing.\n\n## Install\n\n```\n\u003e npm install estel\n```\n\n## Usage\n\n```js\nlet estel = require('estel');\nlet parser = require('esprima');\n\nlet scope = new estel.Scope();\nlet ast = parser.parse(`\n    let number = 10;\n    let obj = {\n        someProp: number,\n        fn(a, b) {\n          return this.someProp + a + b;\n        }\n    };\n    let value = obj.fn(1, 2);\n`);\n\nestel.processNames(ast, scope);\nestel.processValues(ast);\n\nlet numberRef = scope.getReference('number');\nlet valueRef = scope.getReference('value');\n\nconsole.log(scope.getOwnReferenceNames()); // ['number', 'obj', 'value']\nconsole.log(numberRef.value); // 10\nconsole.log(valueRef.value); // 13\n```\n\nAny parser that produces [ESTree](https://github.com/estree/estree) compatible AST may to be used:\n- [acorn](https://github.com/ternjs/acorn)\n- [esprima](https://github.com/jquery/esprima)\n- [espree](https://github.com/eslint/espree)\n\n## Scopes\n\nScope is a place where the variables is defined.\n\nEstel supports `var`, `let` and `const` definition:\n\n```js\nlet ast = parser.parse(`\n    var someVar;\n    let someLet;\n    const someConst = 1;\n    \n    if(true) {\n        var anotherVar;\n        let anotherLet;\n        const anotherConst = 2;\n        function someFn() {}\n    }\n`);\n\nestel.processNames(ast, scope);\n\nlet ifScope = scope.scopes[0];\n\nconsole.log(scope.getOwnReferenceNames()); // ['someVar', 'someLet', 'someConst', 'anotherVar', 'someFn']\nconsole.log(ifScope.getOwnReferenceNames()); // ['anotherLet', 'anotherConst']\n```\n\n## Objects\n\nEstel supports object creation and manipulation:\n\n```js\nlet ast = parser.parse(`\n    let obj = { prop1: { prop2: { prop3: 1 } } };\n    let a = obj.prop1.prop2.prop3;\n    \n    delete obj.prop1.prop2.prop3;\n    obj.prop1.prop2.prop4 = 10\n    \n    let b = obj.prop1.prop2.prop3;\n    let c = obj.prop1.prop2.prop4;\n`);\n\nestel.processNames(ast, scope);\nestel.processValues(ast);\n\nconsole.log(scope.getReference('a').value); // 1\nconsole.log(scope.getReference('b').value); // undefined\nconsole.log(scope.getReference('c').value); // 10\n```\n\n## Operators\n\nEstel supports basic ECMAScript [operators](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Expressions_and_Operators):\n\n```js\nlet ast = parser.parse(`\n    let a = 0;\n    a++; a++;\n    let b = 0 || a;\n    let c = a || 10;\n    let d = a \u0026\u0026 10;\n`);\n\nestel.processNames(ast, scope);\nestel.processValues(ast);\n\nconsole.log(scope.getReference('a').value); // 2\nconsole.log(scope.getReference('b').value); // 2\nconsole.log(scope.getReference('c').value); // 2\nconsole.log(scope.getReference('d').value); // 10\n```\n\n## Functions\n\n```js\nlet ast = parser.parse(`\n    function fn(a, b) {\n        return a + b;\n    }\n    \n    var result = fn(1, 2);\n`);\n\nestel.processNames(ast, scope);\nestel.processValues(ast);\n\nconsole.log(scope.getReference('result').value); // 3\n```\n\n### Arguments\n\nEstel supports `arguments` variable inside a function:\n\n```js\nlet ast = parser.parse(`\n    function fn(a, b) {\n        return arguments[0] + arguments[1];\n    }\n    \n    var result = fn(1, 2);\n`);\n\nestel.processNames(ast, scope);\nestel.processValues(ast);\n\nconsole.log(scope.getReference('result').value); // 3\n```\n\n### this\n\nEstel supports resolving of `this` keyword in simple cases:\n\n```js\nlet ast = parser.parse(`\n    function fn(a, b) {\n        return this.someProp + a + b;\n    }\n    let obj1 = { someProp: 10, fn };\n    let obj2 = { someProp: 20, fn };\n    let result1 = obj1.fn(1, 2);\n    let result2 = obj2.fn(3, 4);\n`);\n\nestel.processNames(ast, scope);\nestel.processValues(ast);\n\nconsole.log(scope.getReference('result1').value); // 13\nconsole.log(scope.getReference('result2').value); // 27\n```\n\n### Closure\n\nEstel supports scope closure:\n\n```js\nlet ast = parser.parse(`\n    function fn(a) {\n        return function() { return ++a };\n    }\n    let counter = fn(1);\n    let result1 = counter();\n    let result2 = counter();\n`);\n\nestel.processNames(ast, scope);\nestel.processValues(ast);\n\nconsole.log(scope.getReference('result1').value); // 2\nconsole.log(scope.getReference('result2').value); // 3\n```\n\n### Arrow function\n\nEstel supports arrow functions (no own `this` and `arguments`):\n\n```js\nlet ast = parser.parse(`\n    function fn(a, b) {\n        return () =\u003e this.someProp + arguments[0] + arguments[1];\n    }\n    let obj1 = { someProp: 10, fn };\n    let obj2 = { someProp: 20, fn };\n    let wrapper1 = obj1.fn(1, 2);\n    let wrapper2 = obj2.fn(3, 4);\n    let result1 = wrapper1();\n    let result2 = wrapper2();\n`);\n\nestel.processNames(ast, scope);\nestel.processValues(ast);\n\nconsole.log(scope.getReference('result1').value); // 13\nconsole.log(scope.getReference('result2').value); // 27\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsmelukov%2Festel","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsmelukov%2Festel","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsmelukov%2Festel/lists"}