├── .github └── workflows │ ├── bb.yml │ └── main.yml ├── .gitignore ├── .npmrc ├── logo.svg ├── package.json └── readme.md /.github/workflows/bb.yml: -------------------------------------------------------------------------------- 1 | jobs: 2 | main: 3 | runs-on: ubuntu-latest 4 | steps: 5 | - uses: unifiedjs/beep-boop-beta@main 6 | with: 7 | repo-token: ${{secrets.GITHUB_TOKEN}} 8 | name: bb 9 | on: 10 | issues: 11 | types: [closed, edited, labeled, opened, reopened, unlabeled] 12 | pull_request_target: 13 | types: [closed, edited, labeled, opened, reopened, unlabeled] 14 | -------------------------------------------------------------------------------- /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | jobs: 2 | main: 3 | runs-on: ubuntu-latest 4 | steps: 5 | - uses: actions/checkout@v4 6 | - uses: actions/setup-node@v4 7 | with: 8 | node-version: node 9 | - run: npm install 10 | - run: npm test 11 | name: main 12 | on: 13 | - pull_request 14 | - push 15 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | *.log 3 | node_modules/ 4 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | ignore-scripts=true 2 | package-lock=false 3 | -------------------------------------------------------------------------------- /logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "author": "Titus Wormer (https://wooorm.com)", 3 | "bugs": "https://github.com/syntax-tree/esast/issues", 4 | "contributors": [ 5 | "Titus Wormer (https://wooorm.com)" 6 | ], 7 | "description": "ecmascript abstract syntax tree", 8 | "devDependencies": { 9 | "remark-cli": "^12.0.0", 10 | "remark-preset-wooorm": "^10.0.0" 11 | }, 12 | "keywords": [], 13 | "license": "MIT", 14 | "private": true, 15 | "remarkConfig": { 16 | "plugins": [ 17 | "preset-wooorm" 18 | ] 19 | }, 20 | "repository": "syntax-tree/esast", 21 | "scripts": { 22 | "format": "remark --frail --output --quiet -- .", 23 | "test": "npm run format" 24 | }, 25 | "version": "1.0.0" 26 | } 27 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # [![esast][logo]][site] 4 | 5 | **E**CMA**S**cript **A**bstract **S**yntax **T**ree format. 6 | 7 | *** 8 | 9 | **esast** is a specification for representing [JavaScript][] as an abstract 10 | [syntax tree][syntax-tree]. 11 | It implements the **[unist][]** spec. 12 | 13 | This document may not be released. 14 | See [releases][] for released documents. 15 | The latest released version is [`1.0.0`][latest]. 16 | 17 | ## Contents 18 | 19 | * [Introduction](#introduction) 20 | * [Where this specification fits](#where-this-specification-fits) 21 | * [ESTree](#estree) 22 | * [Nodes](#nodes) 23 | * [`Node`](#node) 24 | * [`RegExpLiteral`](#regexpliteral) 25 | * [`BigIntLiteral`](#bigintliteral) 26 | * [Recommendations](#recommendations) 27 | * [Glossary](#glossary) 28 | * [List of utilities](#list-of-utilities) 29 | * [References](#references) 30 | * [Security](#security) 31 | * [Related](#related) 32 | * [Contribute](#contribute) 33 | * [Acknowledgments](#acknowledgments) 34 | * [License](#license) 35 | 36 | ## Introduction 37 | 38 | This document defines a format for representing ECMAScript as an [abstract 39 | syntax tree][syntax-tree]. 40 | Development of esast started in February 2021. 41 | This specification is written in a [Web IDL][webidl]-like grammar. 42 | 43 | ### Where this specification fits 44 | 45 | esast extends [unist][], 46 | a format for syntax trees, 47 | to benefit from its [ecosystem of utilities][utilities]. 48 | There is one important difference with other implementations of unist: children 49 | are added at fields other than the `children` array and the `children` field is 50 | not used. 51 | 52 | esast relates to [ESTree][] in that the first is a superset of the latter. 53 | Any tool that accepts an ESTree also supports esast. 54 | 55 | esast relates to [JavaScript][], 56 | other than that it represents it, 57 | in that it has an [ecosystem of utilities][list-of-utilities] for working with 58 | compliantsyntax trees in JavaScript. 59 | However, 60 | esast is not limited to JavaScript and can be used in other programming 61 | languages. 62 | 63 | esast relates to the [unified][] project in that esast syntax trees are used 64 | throughout its ecosystem. 65 | 66 | ### ESTree 67 | 68 | ESTree is great but it is missing some things: 69 | 70 | * trees can’t be roundtripped through `JSON.parse(JSON.stringify(s))`, 71 | leading to cache troubles 72 | * columns are 0-indexed, 73 | whereas most text editors display 1-indexed columns, 74 | leading to a tiny discrepancy or some math to display warnings 75 | * there is no recommendation for range-based positional info, 76 | leading implementations to scatter them in different places 77 | * there is no safe space for metadata, 78 | leading implementations to scatter them in different places 79 | * there are no recommendations for how to handle JSX, 80 | comments, 81 | or raw values 82 | 83 | These are minor nits, 84 | which is why esast is a superset. 85 | 86 | ## Nodes 87 | 88 | ### `Node` 89 | 90 | ```idl 91 | extend interface Node <: UnistNode {} 92 | ``` 93 | 94 | All esast nodes inherit from unist’s [Node][unist-node] and are otherwise the 95 | same as their ESTree counterparts, 96 | with the exception of `RegExpLiteral` and `BigIntLiteral`. 97 | 98 | ### `RegExpLiteral` 99 | 100 | The `regex` field on 101 | [`RegExpLiteral`](https://github.com/estree/estree/blob/master/es5.md#regexpliteral) 102 | must be used whereas the `value` field of such literals should be `null` and 103 | must be ignored. 104 | 105 | ### `BigIntLiteral` 106 | 107 | The `bigint` field on 108 | [`BigIntLiteral`](https://github.com/estree/estree/blob/master/es2020.md#bigintliteral) 109 | must be used whereas the `value` field of such literals should be `null` and 110 | must be ignored. 111 | 112 | ## Recommendations 113 | 114 | For JSX, 115 | follow the 116 | [JSX extension](https://github.com/facebook/jsx/blob/master/AST.md) 117 | maintained in `facebook/jsx`. 118 | 119 | For type annotations, 120 | follow the 121 | [Type annotations extension](https://github.com/estree/estree/blob/master/extensions/type-annotations.md) 122 | maintained in `estree/estree`. 123 | 124 | `raw` fields (added by most parsers) should not be used: they create an extra 125 | source of truth, 126 | which is often not maintained. 127 | 128 | `start`, 129 | `end`, 130 | and `range` fields should not be used. 131 | 132 | `comments` should not be added on nodes other that `Program`. 133 | When adding comments, 134 | use the `'Block'` (for `/**/`) or `'Line'` (for `//`) types. 135 | Do not use `leading` or `trailing` fields on comment nodes. 136 | 137 | `tokens` should not be used. 138 | 139 | ## Glossary 140 | 141 | See the [unist glossary][glossary] but note of the following deviating terms. 142 | 143 | ###### Child 144 | 145 | Node X is **child** of node Y, 146 | if X is either referenced directly or referenced in an array at a field on 147 | node Y. 148 | 149 | ###### Sibling 150 | 151 | Node X is a **sibling** of node Y, 152 | if X and Y have the same parent (if any) and X and Y are both referenced in an 153 | array at a field on node Y. 154 | 155 | ## List of utilities 156 | 157 | See the [unist list of utilities][utilities] for more utilities. 158 | 159 | * [`estree-util-attach-comments`](https://github.com/syntax-tree/estree-util-attach-comments) 160 | — attach comments to estree nodes 161 | * [`estree-util-build-jsx`](https://github.com/syntax-tree/estree-util-build-jsx) 162 | — transform JSX to function calls 163 | * [`estree-util-is-identifier-name`](https://github.com/syntax-tree/estree-util-is-identifier-name) 164 | — check if something can be an identifier name 165 | * [`estree-util-value-to-estree`](https://github.com/remcohaszing/estree-util-value-to-estree) 166 | — convert a JavaScript value to an estree expression 167 | * [`estree-util-to-js`](https://github.com/syntax-tree/estree-util-to-js) 168 | — serialize as JavaScript 169 | * [`estree-util-visit`](https://github.com/syntax-tree/estree-util-visit) 170 | — visit nodes 171 | * [`esast-util-from-estree`](https://github.com/syntax-tree/esast-util-from-estree) 172 | — transform from estree 173 | * [`esast-util-from-js`](https://github.com/syntax-tree/esast-util-from-js) 174 | — parse from JavaScript 175 | 176 | Please use either `estree-util-` (if it works with all ESTrees, 177 | preferred) 178 | or `esast-util-` (if it uses on esast specific features) as a prefix. 179 | 180 | See also the [`estree`](https://github.com/search?q=topic%3Aestree\&s=stars\&o=desc) 181 | topic on GitHub. 182 | 183 | ## References 184 | 185 | * **unist**: 186 | [Universal Syntax Tree][unist]. 187 | T. Wormer; et al. 188 | * **JavaScript**: 189 | [ECMAScript Language Specification][javascript]. 190 | Ecma International. 191 | * **JSON** 192 | [The JavaScript Object Notation (JSON) Data Interchange Format][json], 193 | T. Bray. 194 | IETF. 195 | * **Web IDL**: 196 | [Web IDL][webidl], 197 | C. McCormack. 198 | W3C. 199 | 200 | ## Security 201 | 202 | As esast represents JS, 203 | and JS can open you up to a bunch of problems, 204 | esast is also unsafe. 205 | Always be careful with user input. 206 | 207 | ## Related 208 | 209 | * [hast](https://github.com/syntax-tree/hast) — HTML 210 | * [mdast](https://github.com/syntax-tree/mdast) — Markdown 211 | * [nlcst](https://github.com/syntax-tree/nlcst) — Natural language 212 | * [xast](https://github.com/syntax-tree/xast) — XML 213 | 214 | ## Contribute 215 | 216 | See [`contributing.md`][contributing] in [`syntax-tree/.github`][health] for 217 | ways to get started. 218 | See [`support.md`][support] for ways to get help. 219 | Ideas for new utilities and tools can be posted in [`syntax-tree/ideas`][ideas]. 220 | 221 | A curated list of awesome `syntax-tree`, 222 | unist, 223 | mdast, 224 | esast, 225 | xast, 226 | and nlcst resources can be found in [awesome syntax-tree][awesome]. 227 | 228 | This project has a [code of conduct][coc]. 229 | By interacting with this repository, 230 | organization, 231 | or community you agree to abide by its terms. 232 | 233 | ## Acknowledgments 234 | 235 | The initial release of this project was authored by 236 | **[@wooorm](https://github.com/wooorm)**. 237 | 238 | ## License 239 | 240 | [CC-BY-4.0][license] © [Titus Wormer][author] 241 | 242 | 243 | 244 | [health]: https://github.com/syntax-tree/.github 245 | 246 | [contributing]: https://github.com/syntax-tree/.github/blob/HEAD/contributing.md 247 | 248 | [support]: https://github.com/syntax-tree/.github/blob/HEAD/support.md 249 | 250 | [coc]: https://github.com/syntax-tree/.github/blob/HEAD/code-of-conduct.md 251 | 252 | [awesome]: https://github.com/syntax-tree/awesome-syntax-tree 253 | 254 | [ideas]: https://github.com/syntax-tree/ideas 255 | 256 | [license]: https://creativecommons.org/licenses/by/4.0/ 257 | 258 | [author]: https://wooorm.com 259 | 260 | [logo]: https://raw.githubusercontent.com/syntax-tree/esast/0164416/logo.svg?sanitize=true 261 | 262 | [site]: https://unifiedjs.com 263 | 264 | [releases]: https://github.com/syntax-tree/esast/releases 265 | 266 | [latest]: https://github.com/syntax-tree/esast/releases/tag/2.3.0 267 | 268 | [list-of-utilities]: #list-of-utilities 269 | 270 | [unist]: https://github.com/syntax-tree/unist 271 | 272 | [syntax-tree]: https://github.com/syntax-tree/unist#syntax-tree 273 | 274 | [javascript]: https://www.ecma-international.org/ecma-262/9.0/index.html 275 | 276 | [json]: https://tools.ietf.org/html/rfc7159 277 | 278 | [webidl]: https://heycam.github.io/webidl/ 279 | 280 | [glossary]: https://github.com/syntax-tree/unist#glossary 281 | 282 | [utilities]: https://github.com/syntax-tree/unist#list-of-utilities 283 | 284 | [unified]: https://github.com/unifiedjs/unified 285 | 286 | [estree]: https://github.com/estree/estree 287 | 288 | [unist-node]: https://github.com/syntax-tree/unist#node 289 | --------------------------------------------------------------------------------