├── test ├── fixtures │ ├── basic │ │ ├── index.js │ │ └── index.json │ ├── module │ │ ├── index.js │ │ └── index.json │ ├── stage3 │ │ ├── index.js │ │ └── index.json │ ├── jsx │ │ ├── index.js │ │ └── index.json │ ├── script │ │ ├── index.js │ │ └── index.json │ ├── stage3-and-jsx │ │ ├── index.js │ │ └── index.json │ └── values │ │ ├── index.js │ │ └── index.json └── index.js ├── .npmrc ├── .prettierignore ├── .gitignore ├── .editorconfig ├── index.js ├── .github └── workflows │ ├── bb.yml │ └── main.yml ├── tsconfig.json ├── license ├── package.json ├── lib └── index.js └── readme.md /test/fixtures/basic/index.js: -------------------------------------------------------------------------------- 1 | console.log(1) 2 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | ignore-scripts=true 2 | package-lock=false 3 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | coverage/ 2 | *.md 3 | test/fixtures/ 4 | -------------------------------------------------------------------------------- /test/fixtures/module/index.js: -------------------------------------------------------------------------------- 1 | export function theAnswer() { 2 | return 42 3 | } 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | *.d.ts 3 | *.log 4 | coverage/ 5 | node_modules/ 6 | yarn.lock 7 | -------------------------------------------------------------------------------- /test/fixtures/stage3/index.js: -------------------------------------------------------------------------------- 1 | class W { 2 | static x = 0 3 | #y() {} 4 | z = 0 5 | } 6 | -------------------------------------------------------------------------------- /test/fixtures/jsx/index.js: -------------------------------------------------------------------------------- 1 | var w = {} 2 | 3 | console.log( 4 | <> 5 | 6 | 7 | ) 8 | -------------------------------------------------------------------------------- /test/fixtures/script/index.js: -------------------------------------------------------------------------------- 1 | module.exports = theAnswer 2 | 3 | function theAnswer() { 4 | return 42 5 | } 6 | -------------------------------------------------------------------------------- /test/fixtures/stage3-and-jsx/index.js: -------------------------------------------------------------------------------- 1 | class W { 2 | static x = (<>y) 3 | #y() {} 4 | z = () 5 | } 6 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = space 5 | indent_size = 2 6 | end_of_line = lf 7 | charset = utf-8 8 | trim_trailing_whitespace = true 9 | insert_final_newline = true 10 | -------------------------------------------------------------------------------- /test/fixtures/values/index.js: -------------------------------------------------------------------------------- 1 | console.log(1) 2 | 3 | console.log('string') 4 | 5 | console.log(true) 6 | 7 | console.log(null) 8 | 9 | console.log(undefined) 10 | 11 | console.log(/(?:)/) 12 | 13 | console.log(0n) 14 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @typedef {import('./lib/index.js').Options} Options 3 | * @typedef {import('./lib/index.js').Version} Version 4 | * @typedef {import('./lib/index.js').Plugin} Plugin 5 | * @typedef {import('./lib/index.js').Value} Value 6 | */ 7 | 8 | export {fromJs} from './lib/index.js' 9 | -------------------------------------------------------------------------------- /.github/workflows/bb.yml: -------------------------------------------------------------------------------- 1 | name: bb 2 | on: 3 | issues: 4 | types: [opened, reopened, edited, closed, labeled, unlabeled] 5 | pull_request_target: 6 | types: [opened, reopened, edited, closed, labeled, unlabeled] 7 | jobs: 8 | main: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: unifiedjs/beep-boop-beta@main 12 | with: 13 | repo-token: ${{secrets.GITHUB_TOKEN}} 14 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "checkJs": true, 4 | "customConditions": ["development"], 5 | "declaration": true, 6 | "emitDeclarationOnly": true, 7 | "exactOptionalPropertyTypes": true, 8 | "lib": ["es2022"], 9 | "module": "node16", 10 | "strict": true, 11 | "target": "es2022" 12 | }, 13 | "exclude": ["coverage/", "node_modules/", "test/fixtures/"], 14 | "include": ["**/*.js"] 15 | } 16 | -------------------------------------------------------------------------------- /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | name: main 2 | on: 3 | - pull_request 4 | - push 5 | jobs: 6 | main: 7 | name: ${{matrix.node}} 8 | runs-on: ubuntu-latest 9 | steps: 10 | - uses: actions/checkout@v3 11 | - uses: actions/setup-node@v3 12 | with: 13 | node-version: ${{matrix.node}} 14 | - run: npm install 15 | - run: npm test 16 | - uses: codecov/codecov-action@v3 17 | strategy: 18 | matrix: 19 | node: 20 | - lts/gallium 21 | - node 22 | -------------------------------------------------------------------------------- /license: -------------------------------------------------------------------------------- 1 | (The MIT License) 2 | 3 | Copyright (c) 2022 Titus Wormer 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining 6 | a copy of this software and associated documentation files (the 7 | 'Software'), to deal in the Software without restriction, including 8 | without limitation the rights to use, copy, modify, merge, publish, 9 | distribute, sublicense, and/or sell copies of the Software, and to 10 | permit persons to whom the Software is furnished to do so, subject to 11 | the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be 14 | included in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 20 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 21 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 22 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "esast-util-from-js", 3 | "version": "2.0.1", 4 | "description": "estree (and esast) utility to parse from JavaScript", 5 | "license": "MIT", 6 | "keywords": [ 7 | "unist", 8 | "estree", 9 | "estree-util", 10 | "esast", 11 | "esast-util", 12 | "util", 13 | "utility", 14 | "js", 15 | "parse", 16 | "tokenize", 17 | "acorn" 18 | ], 19 | "repository": "syntax-tree/esast-util-from-js", 20 | "bugs": "https://github.com/syntax-tree/esast-util-from-js/issues", 21 | "funding": { 22 | "type": "opencollective", 23 | "url": "https://opencollective.com/unified" 24 | }, 25 | "author": "Titus Wormer (https://wooorm.com)", 26 | "contributors": [ 27 | "Titus Wormer (https://wooorm.com)" 28 | ], 29 | "sideEffects": false, 30 | "type": "module", 31 | "exports": "./index.js", 32 | "files": [ 33 | "lib/", 34 | "index.d.ts", 35 | "index.js" 36 | ], 37 | "dependencies": { 38 | "@types/estree-jsx": "^1.0.0", 39 | "acorn": "^8.0.0", 40 | "esast-util-from-estree": "^2.0.0", 41 | "vfile-message": "^4.0.0" 42 | }, 43 | "devDependencies": { 44 | "@types/node": "^20.0.0", 45 | "acorn-stage3": "^4.0.0", 46 | "c8": "^8.0.0", 47 | "prettier": "^3.0.0", 48 | "remark-cli": "^11.0.0", 49 | "remark-preset-wooorm": "^9.0.0", 50 | "type-coverage": "^2.0.0", 51 | "typescript": "^5.0.0", 52 | "xo": "^0.55.0" 53 | }, 54 | "scripts": { 55 | "prepack": "npm run build && npm run format", 56 | "build": "tsc --build --clean && tsc --build && type-coverage", 57 | "format": "remark . -qfo && prettier . -w --log-level warn && xo --fix", 58 | "test-api": "node --conditions development test/index.js", 59 | "test-coverage": "c8 --100 --reporter lcov npm run test-api", 60 | "test": "npm run build && npm run format && npm run test-coverage" 61 | }, 62 | "prettier": { 63 | "bracketSpacing": false, 64 | "semi": false, 65 | "singleQuote": true, 66 | "tabWidth": 2, 67 | "trailingComma": "none", 68 | "useTabs": false 69 | }, 70 | "remarkConfig": { 71 | "plugins": [ 72 | "remark-preset-wooorm" 73 | ] 74 | }, 75 | "typeCoverage": { 76 | "atLeast": 100, 77 | "detail": true, 78 | "ignoreCatch": true, 79 | "strict": true 80 | }, 81 | "xo": { 82 | "ignore": [ 83 | "test/fixtures/" 84 | ], 85 | "prettier": true, 86 | "rules": { 87 | "no-await-in-loop": "off" 88 | } 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /test/fixtures/basic/index.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "Program", 3 | "body": [ 4 | { 5 | "type": "ExpressionStatement", 6 | "expression": { 7 | "type": "CallExpression", 8 | "callee": { 9 | "type": "MemberExpression", 10 | "object": { 11 | "type": "Identifier", 12 | "name": "console", 13 | "position": { 14 | "start": { 15 | "line": 1, 16 | "column": 1, 17 | "offset": 0 18 | }, 19 | "end": { 20 | "line": 1, 21 | "column": 8, 22 | "offset": 7 23 | } 24 | } 25 | }, 26 | "property": { 27 | "type": "Identifier", 28 | "name": "log", 29 | "position": { 30 | "start": { 31 | "line": 1, 32 | "column": 9, 33 | "offset": 8 34 | }, 35 | "end": { 36 | "line": 1, 37 | "column": 12, 38 | "offset": 11 39 | } 40 | } 41 | }, 42 | "computed": false, 43 | "optional": false, 44 | "position": { 45 | "start": { 46 | "line": 1, 47 | "column": 1, 48 | "offset": 0 49 | }, 50 | "end": { 51 | "line": 1, 52 | "column": 12, 53 | "offset": 11 54 | } 55 | } 56 | }, 57 | "arguments": [ 58 | { 59 | "type": "Literal", 60 | "value": 1, 61 | "position": { 62 | "start": { 63 | "line": 1, 64 | "column": 13, 65 | "offset": 12 66 | }, 67 | "end": { 68 | "line": 1, 69 | "column": 14, 70 | "offset": 13 71 | } 72 | } 73 | } 74 | ], 75 | "optional": false, 76 | "position": { 77 | "start": { 78 | "line": 1, 79 | "column": 1, 80 | "offset": 0 81 | }, 82 | "end": { 83 | "line": 1, 84 | "column": 15, 85 | "offset": 14 86 | } 87 | } 88 | }, 89 | "position": { 90 | "start": { 91 | "line": 1, 92 | "column": 1, 93 | "offset": 0 94 | }, 95 | "end": { 96 | "line": 1, 97 | "column": 15, 98 | "offset": 14 99 | } 100 | } 101 | } 102 | ], 103 | "sourceType": "script", 104 | "comments": [], 105 | "position": { 106 | "start": { 107 | "line": 1, 108 | "column": 1, 109 | "offset": 0 110 | }, 111 | "end": { 112 | "line": 2, 113 | "column": 1, 114 | "offset": 15 115 | } 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /test/fixtures/module/index.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "Program", 3 | "body": [ 4 | { 5 | "type": "ExportNamedDeclaration", 6 | "declaration": { 7 | "type": "FunctionDeclaration", 8 | "id": { 9 | "type": "Identifier", 10 | "name": "theAnswer", 11 | "position": { 12 | "start": { 13 | "line": 1, 14 | "column": 17, 15 | "offset": 16 16 | }, 17 | "end": { 18 | "line": 1, 19 | "column": 26, 20 | "offset": 25 21 | } 22 | } 23 | }, 24 | "expression": false, 25 | "generator": false, 26 | "async": false, 27 | "params": [], 28 | "body": { 29 | "type": "BlockStatement", 30 | "body": [ 31 | { 32 | "type": "ReturnStatement", 33 | "argument": { 34 | "type": "Literal", 35 | "value": 42, 36 | "position": { 37 | "start": { 38 | "line": 2, 39 | "column": 10, 40 | "offset": 39 41 | }, 42 | "end": { 43 | "line": 2, 44 | "column": 12, 45 | "offset": 41 46 | } 47 | } 48 | }, 49 | "position": { 50 | "start": { 51 | "line": 2, 52 | "column": 3, 53 | "offset": 32 54 | }, 55 | "end": { 56 | "line": 2, 57 | "column": 12, 58 | "offset": 41 59 | } 60 | } 61 | } 62 | ], 63 | "position": { 64 | "start": { 65 | "line": 1, 66 | "column": 29, 67 | "offset": 28 68 | }, 69 | "end": { 70 | "line": 3, 71 | "column": 2, 72 | "offset": 43 73 | } 74 | } 75 | }, 76 | "position": { 77 | "start": { 78 | "line": 1, 79 | "column": 8, 80 | "offset": 7 81 | }, 82 | "end": { 83 | "line": 3, 84 | "column": 2, 85 | "offset": 43 86 | } 87 | } 88 | }, 89 | "specifiers": [], 90 | "source": null, 91 | "position": { 92 | "start": { 93 | "line": 1, 94 | "column": 1, 95 | "offset": 0 96 | }, 97 | "end": { 98 | "line": 3, 99 | "column": 2, 100 | "offset": 43 101 | } 102 | } 103 | } 104 | ], 105 | "sourceType": "module", 106 | "comments": [], 107 | "position": { 108 | "start": { 109 | "line": 1, 110 | "column": 1, 111 | "offset": 0 112 | }, 113 | "end": { 114 | "line": 4, 115 | "column": 1, 116 | "offset": 44 117 | } 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /lib/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @typedef {typeof import('acorn').Parser} ParserClass 3 | * @typedef {import('acorn').Position} Position 4 | * @typedef {import('estree-jsx').Comment} Comment 5 | * @typedef {import('estree-jsx').Program} Program 6 | */ 7 | 8 | /** 9 | * @typedef {Uint8Array | string} Value 10 | * Input value 11 | * 12 | * When a typed array, must be UTF-8. 13 | * 14 | * @typedef AcornErrorFields 15 | * Extra fields in acorn errors. 16 | * @property {number} pos 17 | * Index. 18 | * @property {Position} loc 19 | * Acorn position. 20 | * 21 | * @typedef {Error & AcornErrorFields} AcornError 22 | * Acorn error. 23 | * 24 | * @callback Plugin 25 | * Acorn plugin. 26 | * @param {ParserClass} Parser 27 | * Base parser class. 28 | * @returns {ParserClass} 29 | * Resulting parser class. 30 | * 31 | * @typedef {2015 | 2016 | 2017 | 2018 | 2019 | 2020 | 2021 | 2022 | 2023 | 'latest'} Version 32 | * JavaScript version. 33 | * 34 | * `'latest'` is equivalent to the latest supported year. 35 | * 36 | * @typedef Options 37 | * Configuration. 38 | * @property {Version | null | undefined} [version='latest'] 39 | * JavaScript version (year between 2015 and 2023 or `'latest'`, 40 | * default: `'latest'`). 41 | * 42 | * When a number, must be a year in the range `2015` and `2023` (both 43 | * including). 44 | * `'latest'` is the same as passing the latest supported year. 45 | * 46 | * > ☢️ **Danger**: `'latest'` is a sliding thing, you could consider it as 47 | * > breaking semver. 48 | * > Pass an actual year to lock that down. 49 | * @property {boolean | null | undefined} [module=false] 50 | * Whether this is a module (ESM) or a script (default: `false`). 51 | * @property {boolean | null | undefined} [allowReturnOutsideFunction=false] 52 | * Whether a return statement is allowed in the top scope (default: `false`). 53 | * @property {boolean | null | undefined} [allowImportExportEverywhere=false] 54 | * Whether import/export statements are allowed in the every scope (default: 55 | * `false`). 56 | * @property {boolean | null | undefined} [allowAwaitOutsideFunction] 57 | * Whether `await` is allowed in the top scope (default: `version >= 2022`). 58 | * @property {boolean | null | undefined} [allowSuperOutsideMethod=false] 59 | * Whether `super` is allowed outside methods (default: `false`). 60 | * @property {boolean | null | undefined} [allowHashBang=false] 61 | * Whether a shell hasbang is allowed (default: `false`). 62 | * @property {Array | null | undefined} [plugins=[]] 63 | * List of acorn plugins (default: `[]`); examples are `acorn-jsx` and 64 | * `acorn-stage3`. 65 | */ 66 | 67 | import {Parser} from 'acorn' 68 | import {fromEstree} from 'esast-util-from-estree' 69 | import {VFileMessage} from 'vfile-message' 70 | 71 | /** 72 | * Parse JavaScript to an esast. 73 | * 74 | * @param {Value} value 75 | * Serialized JavaScript to parse. 76 | * @param {Options | null | undefined} [options] 77 | * Configuration (optional). 78 | * @returns {Program} 79 | * Program node (as esast). 80 | */ 81 | export function fromJs(value, options) { 82 | const options_ = options || {} 83 | /** @type {ParserClass} */ 84 | let parser = Parser 85 | /** @type {Array} */ 86 | const comments = [] 87 | /** @type {Program} */ 88 | let tree 89 | 90 | if (options_.plugins) { 91 | parser = parser.extend(...options_.plugins) 92 | } 93 | 94 | const text = 95 | typeof value === 'string' 96 | ? value.toString() 97 | : new TextDecoder().decode(value) 98 | 99 | try { 100 | // @ts-expect-error: Acorn looks enough like estree. 101 | tree = parser.parse(text, { 102 | ecmaVersion: options_.version || 'latest', 103 | sourceType: options_.module ? 'module' : 'script', 104 | allowReturnOutsideFunction: 105 | options_.allowReturnOutsideFunction || undefined, 106 | allowImportExportEverywhere: 107 | options_.allowImportExportEverywhere || undefined, 108 | allowAwaitOutsideFunction: 109 | options_.allowAwaitOutsideFunction || undefined, 110 | allowHashBang: options_.allowHashBang || undefined, 111 | allowSuperOutsideMethod: options_.allowSuperOutsideMethod || undefined, 112 | locations: true, 113 | // @ts-expect-error: Acorn looks enough like estree. 114 | onComment: comments 115 | }) 116 | } catch (error) { 117 | const cause = /** @type {AcornError} */ (error) 118 | 119 | const message = new VFileMessage('Could not parse JavaScript with Acorn', { 120 | cause, 121 | place: { 122 | line: cause.loc.line, 123 | column: cause.loc.column + 1, 124 | offset: cause.pos 125 | }, 126 | ruleId: 'acorn', 127 | source: 'esast-util-from-js' 128 | }) 129 | 130 | message.url = 'https://github.com/syntax-tree/esast-util-from-js#throws' 131 | 132 | throw message 133 | } 134 | 135 | tree.comments = comments 136 | 137 | return fromEstree(tree) 138 | } 139 | -------------------------------------------------------------------------------- /test/fixtures/script/index.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "Program", 3 | "body": [ 4 | { 5 | "type": "ExpressionStatement", 6 | "expression": { 7 | "type": "AssignmentExpression", 8 | "operator": "=", 9 | "left": { 10 | "type": "MemberExpression", 11 | "object": { 12 | "type": "Identifier", 13 | "name": "module", 14 | "position": { 15 | "start": { 16 | "line": 1, 17 | "column": 1, 18 | "offset": 0 19 | }, 20 | "end": { 21 | "line": 1, 22 | "column": 7, 23 | "offset": 6 24 | } 25 | } 26 | }, 27 | "property": { 28 | "type": "Identifier", 29 | "name": "exports", 30 | "position": { 31 | "start": { 32 | "line": 1, 33 | "column": 8, 34 | "offset": 7 35 | }, 36 | "end": { 37 | "line": 1, 38 | "column": 15, 39 | "offset": 14 40 | } 41 | } 42 | }, 43 | "computed": false, 44 | "optional": false, 45 | "position": { 46 | "start": { 47 | "line": 1, 48 | "column": 1, 49 | "offset": 0 50 | }, 51 | "end": { 52 | "line": 1, 53 | "column": 15, 54 | "offset": 14 55 | } 56 | } 57 | }, 58 | "right": { 59 | "type": "Identifier", 60 | "name": "theAnswer", 61 | "position": { 62 | "start": { 63 | "line": 1, 64 | "column": 18, 65 | "offset": 17 66 | }, 67 | "end": { 68 | "line": 1, 69 | "column": 27, 70 | "offset": 26 71 | } 72 | } 73 | }, 74 | "position": { 75 | "start": { 76 | "line": 1, 77 | "column": 1, 78 | "offset": 0 79 | }, 80 | "end": { 81 | "line": 1, 82 | "column": 27, 83 | "offset": 26 84 | } 85 | } 86 | }, 87 | "position": { 88 | "start": { 89 | "line": 1, 90 | "column": 1, 91 | "offset": 0 92 | }, 93 | "end": { 94 | "line": 1, 95 | "column": 27, 96 | "offset": 26 97 | } 98 | } 99 | }, 100 | { 101 | "type": "FunctionDeclaration", 102 | "id": { 103 | "type": "Identifier", 104 | "name": "theAnswer", 105 | "position": { 106 | "start": { 107 | "line": 3, 108 | "column": 10, 109 | "offset": 37 110 | }, 111 | "end": { 112 | "line": 3, 113 | "column": 19, 114 | "offset": 46 115 | } 116 | } 117 | }, 118 | "expression": false, 119 | "generator": false, 120 | "async": false, 121 | "params": [], 122 | "body": { 123 | "type": "BlockStatement", 124 | "body": [ 125 | { 126 | "type": "ReturnStatement", 127 | "argument": { 128 | "type": "Literal", 129 | "value": 42, 130 | "position": { 131 | "start": { 132 | "line": 4, 133 | "column": 10, 134 | "offset": 60 135 | }, 136 | "end": { 137 | "line": 4, 138 | "column": 12, 139 | "offset": 62 140 | } 141 | } 142 | }, 143 | "position": { 144 | "start": { 145 | "line": 4, 146 | "column": 3, 147 | "offset": 53 148 | }, 149 | "end": { 150 | "line": 4, 151 | "column": 12, 152 | "offset": 62 153 | } 154 | } 155 | } 156 | ], 157 | "position": { 158 | "start": { 159 | "line": 3, 160 | "column": 22, 161 | "offset": 49 162 | }, 163 | "end": { 164 | "line": 5, 165 | "column": 2, 166 | "offset": 64 167 | } 168 | } 169 | }, 170 | "position": { 171 | "start": { 172 | "line": 3, 173 | "column": 1, 174 | "offset": 28 175 | }, 176 | "end": { 177 | "line": 5, 178 | "column": 2, 179 | "offset": 64 180 | } 181 | } 182 | } 183 | ], 184 | "sourceType": "script", 185 | "comments": [], 186 | "position": { 187 | "start": { 188 | "line": 1, 189 | "column": 1, 190 | "offset": 0 191 | }, 192 | "end": { 193 | "line": 6, 194 | "column": 1, 195 | "offset": 65 196 | } 197 | } 198 | } 199 | -------------------------------------------------------------------------------- /test/fixtures/stage3/index.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "Program", 3 | "body": [ 4 | { 5 | "type": "ClassDeclaration", 6 | "id": { 7 | "type": "Identifier", 8 | "name": "W", 9 | "position": { 10 | "start": { 11 | "line": 1, 12 | "column": 7, 13 | "offset": 6 14 | }, 15 | "end": { 16 | "line": 1, 17 | "column": 8, 18 | "offset": 7 19 | } 20 | } 21 | }, 22 | "superClass": null, 23 | "body": { 24 | "type": "ClassBody", 25 | "body": [ 26 | { 27 | "type": "FieldDefinition", 28 | "static": true, 29 | "computed": false, 30 | "key": { 31 | "type": "Identifier", 32 | "name": "x", 33 | "position": { 34 | "start": { 35 | "line": 2, 36 | "column": 10, 37 | "offset": 19 38 | }, 39 | "end": { 40 | "line": 2, 41 | "column": 11, 42 | "offset": 20 43 | } 44 | } 45 | }, 46 | "value": { 47 | "type": "Literal", 48 | "value": 0, 49 | "position": { 50 | "start": { 51 | "line": 2, 52 | "column": 14, 53 | "offset": 23 54 | }, 55 | "end": { 56 | "line": 2, 57 | "column": 15, 58 | "offset": 24 59 | } 60 | } 61 | }, 62 | "position": { 63 | "start": { 64 | "line": 2, 65 | "column": 3, 66 | "offset": 12 67 | }, 68 | "end": { 69 | "line": 2, 70 | "column": 15, 71 | "offset": 24 72 | } 73 | } 74 | }, 75 | { 76 | "type": "MethodDefinition", 77 | "static": false, 78 | "computed": false, 79 | "key": { 80 | "type": "PrivateName", 81 | "name": "y", 82 | "position": { 83 | "start": { 84 | "line": 3, 85 | "column": 3, 86 | "offset": 27 87 | }, 88 | "end": { 89 | "line": 3, 90 | "column": 5, 91 | "offset": 29 92 | } 93 | } 94 | }, 95 | "kind": "method", 96 | "value": { 97 | "type": "FunctionExpression", 98 | "id": null, 99 | "expression": false, 100 | "generator": false, 101 | "async": false, 102 | "params": [], 103 | "body": { 104 | "type": "BlockStatement", 105 | "body": [], 106 | "position": { 107 | "start": { 108 | "line": 3, 109 | "column": 8, 110 | "offset": 32 111 | }, 112 | "end": { 113 | "line": 3, 114 | "column": 10, 115 | "offset": 34 116 | } 117 | } 118 | }, 119 | "position": { 120 | "start": { 121 | "line": 3, 122 | "column": 5, 123 | "offset": 29 124 | }, 125 | "end": { 126 | "line": 3, 127 | "column": 10, 128 | "offset": 34 129 | } 130 | } 131 | }, 132 | "position": { 133 | "start": { 134 | "line": 3, 135 | "column": 3, 136 | "offset": 27 137 | }, 138 | "end": { 139 | "line": 3, 140 | "column": 10, 141 | "offset": 34 142 | } 143 | } 144 | }, 145 | { 146 | "type": "FieldDefinition", 147 | "computed": false, 148 | "key": { 149 | "type": "Identifier", 150 | "name": "z", 151 | "position": { 152 | "start": { 153 | "line": 4, 154 | "column": 3, 155 | "offset": 37 156 | }, 157 | "end": { 158 | "line": 4, 159 | "column": 4, 160 | "offset": 38 161 | } 162 | } 163 | }, 164 | "value": { 165 | "type": "Literal", 166 | "value": 0, 167 | "position": { 168 | "start": { 169 | "line": 4, 170 | "column": 7, 171 | "offset": 41 172 | }, 173 | "end": { 174 | "line": 4, 175 | "column": 8, 176 | "offset": 42 177 | } 178 | } 179 | }, 180 | "position": { 181 | "start": { 182 | "line": 4, 183 | "column": 3, 184 | "offset": 37 185 | }, 186 | "end": { 187 | "line": 4, 188 | "column": 8, 189 | "offset": 42 190 | } 191 | } 192 | } 193 | ], 194 | "position": { 195 | "start": { 196 | "line": 1, 197 | "column": 9, 198 | "offset": 8 199 | }, 200 | "end": { 201 | "line": 5, 202 | "column": 2, 203 | "offset": 44 204 | } 205 | } 206 | }, 207 | "position": { 208 | "start": { 209 | "line": 1, 210 | "column": 1, 211 | "offset": 0 212 | }, 213 | "end": { 214 | "line": 5, 215 | "column": 2, 216 | "offset": 44 217 | } 218 | } 219 | } 220 | ], 221 | "sourceType": "script", 222 | "comments": [], 223 | "position": { 224 | "start": { 225 | "line": 1, 226 | "column": 1, 227 | "offset": 0 228 | }, 229 | "end": { 230 | "line": 6, 231 | "column": 1, 232 | "offset": 45 233 | } 234 | } 235 | } 236 | -------------------------------------------------------------------------------- /test/fixtures/stage3-and-jsx/index.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "Program", 3 | "body": [ 4 | { 5 | "type": "ClassDeclaration", 6 | "id": { 7 | "type": "Identifier", 8 | "name": "W", 9 | "position": { 10 | "start": { 11 | "line": 1, 12 | "column": 7, 13 | "offset": 6 14 | }, 15 | "end": { 16 | "line": 1, 17 | "column": 8, 18 | "offset": 7 19 | } 20 | } 21 | }, 22 | "superClass": null, 23 | "body": { 24 | "type": "ClassBody", 25 | "body": [ 26 | { 27 | "type": "FieldDefinition", 28 | "static": true, 29 | "computed": false, 30 | "key": { 31 | "type": "Identifier", 32 | "name": "x", 33 | "position": { 34 | "start": { 35 | "line": 2, 36 | "column": 10, 37 | "offset": 19 38 | }, 39 | "end": { 40 | "line": 2, 41 | "column": 11, 42 | "offset": 20 43 | } 44 | } 45 | }, 46 | "value": { 47 | "type": "JSXFragment", 48 | "openingFragment": { 49 | "type": "JSXOpeningFragment", 50 | "position": { 51 | "start": { 52 | "line": 2, 53 | "column": 15, 54 | "offset": 24 55 | }, 56 | "end": { 57 | "line": 2, 58 | "column": 17, 59 | "offset": 26 60 | } 61 | } 62 | }, 63 | "closingFragment": { 64 | "type": "JSXClosingFragment", 65 | "position": { 66 | "start": { 67 | "line": 2, 68 | "column": 18, 69 | "offset": 27 70 | }, 71 | "end": { 72 | "line": 2, 73 | "column": 21, 74 | "offset": 30 75 | } 76 | } 77 | }, 78 | "children": [ 79 | { 80 | "type": "JSXText", 81 | "value": "y", 82 | "position": { 83 | "start": { 84 | "line": 2, 85 | "column": 17, 86 | "offset": 26 87 | }, 88 | "end": { 89 | "line": 2, 90 | "column": 18, 91 | "offset": 27 92 | } 93 | } 94 | } 95 | ], 96 | "position": { 97 | "start": { 98 | "line": 2, 99 | "column": 15, 100 | "offset": 24 101 | }, 102 | "end": { 103 | "line": 2, 104 | "column": 21, 105 | "offset": 30 106 | } 107 | } 108 | }, 109 | "position": { 110 | "start": { 111 | "line": 2, 112 | "column": 3, 113 | "offset": 12 114 | }, 115 | "end": { 116 | "line": 2, 117 | "column": 22, 118 | "offset": 31 119 | } 120 | } 121 | }, 122 | { 123 | "type": "MethodDefinition", 124 | "static": false, 125 | "computed": false, 126 | "key": { 127 | "type": "PrivateName", 128 | "name": "y", 129 | "position": { 130 | "start": { 131 | "line": 3, 132 | "column": 3, 133 | "offset": 34 134 | }, 135 | "end": { 136 | "line": 3, 137 | "column": 5, 138 | "offset": 36 139 | } 140 | } 141 | }, 142 | "kind": "method", 143 | "value": { 144 | "type": "FunctionExpression", 145 | "id": null, 146 | "expression": false, 147 | "generator": false, 148 | "async": false, 149 | "params": [], 150 | "body": { 151 | "type": "BlockStatement", 152 | "body": [], 153 | "position": { 154 | "start": { 155 | "line": 3, 156 | "column": 8, 157 | "offset": 39 158 | }, 159 | "end": { 160 | "line": 3, 161 | "column": 10, 162 | "offset": 41 163 | } 164 | } 165 | }, 166 | "position": { 167 | "start": { 168 | "line": 3, 169 | "column": 5, 170 | "offset": 36 171 | }, 172 | "end": { 173 | "line": 3, 174 | "column": 10, 175 | "offset": 41 176 | } 177 | } 178 | }, 179 | "position": { 180 | "start": { 181 | "line": 3, 182 | "column": 3, 183 | "offset": 34 184 | }, 185 | "end": { 186 | "line": 3, 187 | "column": 10, 188 | "offset": 41 189 | } 190 | } 191 | }, 192 | { 193 | "type": "FieldDefinition", 194 | "computed": false, 195 | "key": { 196 | "type": "Identifier", 197 | "name": "z", 198 | "position": { 199 | "start": { 200 | "line": 4, 201 | "column": 3, 202 | "offset": 44 203 | }, 204 | "end": { 205 | "line": 4, 206 | "column": 4, 207 | "offset": 45 208 | } 209 | } 210 | }, 211 | "value": { 212 | "type": "JSXElement", 213 | "openingElement": { 214 | "type": "JSXOpeningElement", 215 | "attributes": [], 216 | "name": { 217 | "type": "JSXIdentifier", 218 | "name": "x", 219 | "position": { 220 | "start": { 221 | "line": 4, 222 | "column": 9, 223 | "offset": 50 224 | }, 225 | "end": { 226 | "line": 4, 227 | "column": 10, 228 | "offset": 51 229 | } 230 | } 231 | }, 232 | "selfClosing": true, 233 | "position": { 234 | "start": { 235 | "line": 4, 236 | "column": 8, 237 | "offset": 49 238 | }, 239 | "end": { 240 | "line": 4, 241 | "column": 13, 242 | "offset": 54 243 | } 244 | } 245 | }, 246 | "closingElement": null, 247 | "children": [], 248 | "position": { 249 | "start": { 250 | "line": 4, 251 | "column": 8, 252 | "offset": 49 253 | }, 254 | "end": { 255 | "line": 4, 256 | "column": 13, 257 | "offset": 54 258 | } 259 | } 260 | }, 261 | "position": { 262 | "start": { 263 | "line": 4, 264 | "column": 3, 265 | "offset": 44 266 | }, 267 | "end": { 268 | "line": 4, 269 | "column": 14, 270 | "offset": 55 271 | } 272 | } 273 | } 274 | ], 275 | "position": { 276 | "start": { 277 | "line": 1, 278 | "column": 9, 279 | "offset": 8 280 | }, 281 | "end": { 282 | "line": 5, 283 | "column": 2, 284 | "offset": 57 285 | } 286 | } 287 | }, 288 | "position": { 289 | "start": { 290 | "line": 1, 291 | "column": 1, 292 | "offset": 0 293 | }, 294 | "end": { 295 | "line": 5, 296 | "column": 2, 297 | "offset": 57 298 | } 299 | } 300 | } 301 | ], 302 | "sourceType": "script", 303 | "comments": [], 304 | "position": { 305 | "start": { 306 | "line": 1, 307 | "column": 1, 308 | "offset": 0 309 | }, 310 | "end": { 311 | "line": 6, 312 | "column": 1, 313 | "offset": 58 314 | } 315 | } 316 | } 317 | -------------------------------------------------------------------------------- /test/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @typedef {import('esast-util-from-js').Plugin} Plugin 3 | */ 4 | 5 | import assert from 'node:assert/strict' 6 | import fs from 'node:fs/promises' 7 | import process from 'node:process' 8 | import test from 'node:test' 9 | import jsx from 'acorn-jsx' 10 | // @ts-expect-error: untyped. 11 | import stage3 from 'acorn-stage3' 12 | import {fromJs} from 'esast-util-from-js' 13 | 14 | test('fromJs', async function (t) { 15 | await t.test('should expose the public api', async function () { 16 | assert.deepEqual(Object.keys(await import('esast-util-from-js')).sort(), [ 17 | 'fromJs' 18 | ]) 19 | }) 20 | 21 | await t.test('should work', async function () { 22 | assert.deepEqual(fromJs('1 + "2"'), { 23 | type: 'Program', 24 | body: [ 25 | { 26 | type: 'ExpressionStatement', 27 | expression: { 28 | type: 'BinaryExpression', 29 | left: { 30 | type: 'Literal', 31 | value: 1, 32 | position: { 33 | start: {line: 1, column: 1, offset: 0}, 34 | end: {line: 1, column: 2, offset: 1} 35 | } 36 | }, 37 | operator: '+', 38 | right: { 39 | type: 'Literal', 40 | value: '2', 41 | position: { 42 | start: {line: 1, column: 5, offset: 4}, 43 | end: {line: 1, column: 8, offset: 7} 44 | } 45 | }, 46 | position: { 47 | start: {line: 1, column: 1, offset: 0}, 48 | end: {line: 1, column: 8, offset: 7} 49 | } 50 | }, 51 | position: { 52 | start: {line: 1, column: 1, offset: 0}, 53 | end: {line: 1, column: 8, offset: 7} 54 | } 55 | } 56 | ], 57 | sourceType: 'script', 58 | comments: [], 59 | position: { 60 | start: {line: 1, column: 1, offset: 0}, 61 | end: {line: 1, column: 8, offset: 7} 62 | } 63 | }) 64 | }) 65 | 66 | await t.test( 67 | 'should fail on an import w/o `module: true`', 68 | async function () { 69 | assert.throws(function () { 70 | fromJs('import "a"') 71 | }, /Could not parse JavaScript with Acorn/) 72 | } 73 | ) 74 | 75 | await t.test('should support an import w/ `module: true`', async function () { 76 | assert.deepEqual(fromJs('import "a"', {module: true}), { 77 | type: 'Program', 78 | body: [ 79 | { 80 | type: 'ImportDeclaration', 81 | specifiers: [], 82 | source: { 83 | type: 'Literal', 84 | value: 'a', 85 | position: { 86 | start: {line: 1, column: 8, offset: 7}, 87 | end: {line: 1, column: 11, offset: 10} 88 | } 89 | }, 90 | position: { 91 | start: {line: 1, column: 1, offset: 0}, 92 | end: {line: 1, column: 11, offset: 10} 93 | } 94 | } 95 | ], 96 | sourceType: 'module', 97 | comments: [], 98 | position: { 99 | start: {line: 1, column: 1, offset: 0}, 100 | end: {line: 1, column: 11, offset: 10} 101 | } 102 | }) 103 | }) 104 | 105 | await t.test('should support a plugin', async function () { 106 | assert.deepEqual(fromJs('', {plugins: [jsx()]}), { 107 | type: 'Program', 108 | body: [ 109 | { 110 | type: 'ExpressionStatement', 111 | expression: { 112 | type: 'JSXElement', 113 | openingElement: { 114 | type: 'JSXOpeningElement', 115 | attributes: [], 116 | name: { 117 | type: 'JSXIdentifier', 118 | name: 'x', 119 | position: { 120 | start: {line: 1, column: 2, offset: 1}, 121 | end: {line: 1, column: 3, offset: 2} 122 | } 123 | }, 124 | selfClosing: true, 125 | position: { 126 | start: {line: 1, column: 1, offset: 0}, 127 | end: {line: 1, column: 6, offset: 5} 128 | } 129 | }, 130 | closingElement: null, 131 | children: [], 132 | position: { 133 | start: {line: 1, column: 1, offset: 0}, 134 | end: {line: 1, column: 6, offset: 5} 135 | } 136 | }, 137 | position: { 138 | start: {line: 1, column: 1, offset: 0}, 139 | end: {line: 1, column: 6, offset: 5} 140 | } 141 | } 142 | ], 143 | sourceType: 'script', 144 | comments: [], 145 | position: { 146 | start: {line: 1, column: 1, offset: 0}, 147 | end: {line: 1, column: 6, offset: 5} 148 | } 149 | }) 150 | }) 151 | 152 | await t.test('should support `options.allowHashBang`', async function () { 153 | assert.deepEqual(fromJs('#!/bin/sh\n1', {allowHashBang: true}), { 154 | type: 'Program', 155 | body: [ 156 | { 157 | type: 'ExpressionStatement', 158 | expression: { 159 | type: 'Literal', 160 | value: 1, 161 | position: { 162 | start: {line: 2, column: 1, offset: 10}, 163 | end: {line: 2, column: 2, offset: 11} 164 | } 165 | }, 166 | position: { 167 | start: {line: 2, column: 1, offset: 10}, 168 | end: {line: 2, column: 2, offset: 11} 169 | } 170 | } 171 | ], 172 | sourceType: 'script', 173 | comments: [ 174 | { 175 | type: 'Line', 176 | value: '/bin/sh', 177 | position: { 178 | start: {line: 1, column: 1, offset: 0}, 179 | end: {line: 1, column: 10, offset: 9} 180 | } 181 | } 182 | ], 183 | position: { 184 | start: {line: 1, column: 1, offset: 0}, 185 | end: {line: 2, column: 2, offset: 11} 186 | } 187 | }) 188 | }) 189 | 190 | await t.test('should support empty typed arrays', async function () { 191 | assert.deepEqual(fromJs(new Uint8Array()), { 192 | type: 'Program', 193 | body: [], 194 | sourceType: 'script', 195 | comments: [], 196 | position: { 197 | start: {line: 1, column: 1, offset: 0}, 198 | end: {line: 1, column: 1, offset: 0} 199 | } 200 | }) 201 | }) 202 | 203 | await t.test('should support typed arrays', async function () { 204 | assert.deepEqual(fromJs(new TextEncoder().encode('let a = 1')), { 205 | type: 'Program', 206 | body: [ 207 | { 208 | type: 'VariableDeclaration', 209 | declarations: [ 210 | { 211 | type: 'VariableDeclarator', 212 | id: { 213 | type: 'Identifier', 214 | name: 'a', 215 | position: { 216 | start: {line: 1, column: 5, offset: 4}, 217 | end: {line: 1, column: 6, offset: 5} 218 | } 219 | }, 220 | init: { 221 | type: 'Literal', 222 | value: 1, 223 | position: { 224 | start: {line: 1, column: 9, offset: 8}, 225 | end: {line: 1, column: 10, offset: 9} 226 | } 227 | }, 228 | position: { 229 | start: {line: 1, column: 5, offset: 4}, 230 | end: {line: 1, column: 10, offset: 9} 231 | } 232 | } 233 | ], 234 | kind: 'let', 235 | position: { 236 | start: {line: 1, column: 1, offset: 0}, 237 | end: {line: 1, column: 10, offset: 9} 238 | } 239 | } 240 | ], 241 | sourceType: 'script', 242 | comments: [], 243 | position: { 244 | start: {line: 1, column: 1, offset: 0}, 245 | end: {line: 1, column: 10, offset: 9} 246 | } 247 | }) 248 | }) 249 | }) 250 | 251 | test('fixtures', async function (t) { 252 | const base = new URL('fixtures/', import.meta.url) 253 | const filenames = await fs.readdir(base) 254 | const tests = filenames.filter(function (d) { 255 | return d.charAt(0) !== '.' 256 | }) 257 | 258 | let index = -1 259 | while (++index < tests.length) { 260 | const filename = tests[index] 261 | 262 | await t.test(filename, async function () { 263 | const valueUrl = new URL(filename + '/index.js', base) 264 | const treeUrl = new URL(filename + '/index.json', base) 265 | const value = String(await fs.readFile(valueUrl)) 266 | const parts = filename.split('-') 267 | const module = parts.includes('module') 268 | /** @type {Array} */ 269 | const plugins = [] 270 | 271 | if (parts.includes('jsx')) { 272 | plugins.push(jsx()) 273 | } 274 | 275 | if (parts.includes('stage3')) { 276 | plugins.push(stage3) 277 | } 278 | 279 | const actual = fromJs(value, {module, plugins}) 280 | /** @type {string} */ 281 | let expected 282 | 283 | try { 284 | if ('UPDATE' in process.env) { 285 | throw new Error('Update') 286 | } 287 | 288 | expected = JSON.parse(String(await fs.readFile(treeUrl))) 289 | } catch { 290 | // New fixture. 291 | expected = JSON.stringify(actual, undefined, 2) + '\n' 292 | await fs.writeFile(treeUrl, expected) 293 | } 294 | 295 | assert.deepEqual(actual, expected) 296 | }) 297 | } 298 | }) 299 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # esast-util-from-js 2 | 3 | [![Build][build-badge]][build] 4 | [![Coverage][coverage-badge]][coverage] 5 | [![Downloads][downloads-badge]][downloads] 6 | [![Size][size-badge]][size] 7 | [![Sponsors][sponsors-badge]][collective] 8 | [![Backers][backers-badge]][collective] 9 | [![Chat][chat-badge]][chat] 10 | 11 | [esast][] (and [estree][]) utility to parse trees from JavaScript. 12 | 13 | ## Contents 14 | 15 | * [What is this?](#what-is-this) 16 | * [When should I use this?](#when-should-i-use-this) 17 | * [Install](#install) 18 | * [Use](#use) 19 | * [API](#api) 20 | * [`fromJs(value[, options])`](#fromjsvalue-options) 21 | * [`Options`](#options) 22 | * [`Plugin`](#plugin) 23 | * [`Value`](#value) 24 | * [`Version`](#version-1) 25 | * [Types](#types) 26 | * [Compatibility](#compatibility) 27 | * [Contribute](#contribute) 28 | * [License](#license) 29 | 30 | ## What is this? 31 | 32 | This package is a utility that turns a string of JavaScript into an esast 33 | (estree with some extra cleanliness) syntax tree. 34 | 35 | ## When should I use this? 36 | 37 | You can use this utility when you want to deal with ASTs of JavaScript 38 | combined with other [unist][] and [`vfile`][vfile] things. 39 | You can use [`acorn`][acorn] itself if you don’t care about unified. 40 | 41 | The utility [`estree-util-to-js`][estree-util-to-js] does the inverse of this 42 | utility. 43 | It turns the tree into a string of JavaScript. 44 | 45 | ## Install 46 | 47 | This package is [ESM only][esm]. 48 | In Node.js (version 16+), install with [npm][]: 49 | 50 | ```sh 51 | npm install esast-util-from-js 52 | ``` 53 | 54 | In Deno with [`esm.sh`][esmsh]: 55 | 56 | ```js 57 | import {fromJs} from 'https://esm.sh/esast-util-from-js@2' 58 | ``` 59 | 60 | In browsers with [`esm.sh`][esmsh]: 61 | 62 | ```html 63 | 66 | ``` 67 | 68 | ## Use 69 | 70 | ```js 71 | import fs from 'node:fs/promises' 72 | import {fromJs} from 'esast-util-from-js' 73 | 74 | const tree = fromJs(await fs.readFile('example.js'), {module: true}) 75 | 76 | console.log(tree) 77 | ``` 78 | 79 | Yields: 80 | 81 | ```js 82 | { 83 | type: 'Program', 84 | body: [ 85 | { 86 | type: 'ImportDeclaration', 87 | specifiers: [Array], 88 | source: [Object], 89 | position: [Object] 90 | }, 91 | { 92 | type: 'ImportDeclaration', 93 | specifiers: [Array], 94 | source: [Object], 95 | position: [Object] 96 | }, 97 | { 98 | type: 'VariableDeclaration', 99 | declarations: [Array], 100 | kind: 'const', 101 | position: [Object] 102 | }, 103 | { 104 | type: 'ExpressionStatement', 105 | expression: [Object], 106 | position: [Object] 107 | } 108 | ], 109 | sourceType: 'module', 110 | comments: [], 111 | position: { 112 | start: {line: 1, column: 1, offset: 0}, 113 | end: {line: 7, column: 1, offset: 157} 114 | } 115 | } 116 | ``` 117 | 118 | ## API 119 | 120 | This package exports the identifier [`fromJs`][api-from-js]. 121 | There is no default export. 122 | 123 | ### `fromJs(value[, options])` 124 | 125 | Parse JavaScript to an esast. 126 | 127 | ###### Parameters 128 | 129 | * `value` ([`Value`][api-value]) 130 | — serialized JavaScript to parse 131 | * `options` ([`Options`][api-options], optional) 132 | — configuration 133 | 134 | ###### Returns 135 | 136 | Tree ([`Node`][node]). 137 | 138 | ###### Throws 139 | 140 | When the JavaScript cannot be parsed with `acorn`, a 141 | [`VFileMessage`][vfile-message] is thrown. 142 | 143 | This can for example happen when passing modern syntax (you could maybe use a 144 | newer `version`, or it might be that the syntax is not yet supported), or just 145 | otherwise invalid JavaScript (you might need a plugin). 146 | 147 | ### `Options` 148 | 149 | Configuration (TypeScript type). 150 | 151 | ##### Fields 152 | 153 | ###### `version` 154 | 155 | JavaScript version ([`Version`][api-version], default: `'latest'`). 156 | 157 | When a number, must be a year in the range `2015` and `2023` (both including). 158 | `'latest'` is the same as passing the latest supported year. 159 | 160 | > ☢️ **Danger**: `'latest'` is a sliding thing, you could consider it as 161 | > breaking semver. 162 | > Pass an actual year to lock that down. 163 | 164 | ###### `module` 165 | 166 | Whether this is a module (ESM) or a script (`boolean`, default: `false`). 167 | 168 | ###### `allowReturnOutsideFunction` 169 | 170 | Whether a return statement is allowed in the top scope (`boolean`, default: 171 | `false`). 172 | 173 | ###### `allowImportExportEverywhere` 174 | 175 | Whether import/export statements are allowed in the every scope (`boolean`, 176 | default: `false`). 177 | 178 | ###### `allowAwaitOutsideFunction` 179 | 180 | Whether `await` is allowed in the top scope (`boolean`, default: depends). 181 | Defaults to `version >= 2022`. 182 | 183 | ###### `allowSuperOutsideMethod` 184 | 185 | Whether `super` is allowed outside methods (`boolean`, default: `false`). 186 | 187 | ###### `allowHashBang` 188 | 189 | Whether a shell hasbang is allowed (`boolean`, default: `false`). 190 | 191 | ###### `plugins` 192 | 193 | List of acorn plugins ([`Array`][api-plugin], default: `[]`). 194 | Examples are [`acorn-jsx`][acorn-jsx] and [`acorn-stage3`][acorn-stage3]. 195 | 196 | ### `Plugin` 197 | 198 | Acorn plugin (TypeScript type). 199 | 200 | ###### Type 201 | 202 | ```ts 203 | type Plugin = (Parser: ParserClass) => ParserClass 204 | ``` 205 | 206 | ### `Value` 207 | 208 | Input value (TypeScript type). 209 | 210 | When a typed array, must be UTF-8. 211 | 212 | ###### Type 213 | 214 | ```ts 215 | type Value = Uint8Array | string 216 | ``` 217 | 218 | ### `Version` 219 | 220 | JavaScript version (TypeScript type). 221 | 222 | `'latest'` is equivalent to the latest supported year. 223 | 224 | ###### Type 225 | 226 | ```ts 227 | type Version = 2015 | 2016 | 2017 | 2018 | 2019 | 2020 | 2021 | 2022 | 2023 | 'latest' 228 | ``` 229 | 230 | ## Types 231 | 232 | This package is fully typed with [TypeScript][]. 233 | It exports the additional types [`Options`][api-options], 234 | [`Plugin`][api-plugin], 235 | [`Value`][api-value], and 236 | [`Version`][api-version]. 237 | 238 | ## Compatibility 239 | 240 | Projects maintained by the unified collective are compatible with maintained 241 | versions of Node.js. 242 | 243 | When we cut a new major release, we drop support for unmaintained versions of 244 | Node. 245 | This means we try to keep the current release line, `esast-util-from-js@^2`, 246 | compatible with Node.js 16. 247 | 248 | ## Contribute 249 | 250 | See [`contributing.md`][contributing] in [`syntax-tree/.github`][health] for 251 | ways to get started. 252 | See [`support.md`][support] for ways to get help. 253 | 254 | This project has a [code of conduct][coc]. 255 | By interacting with this repository, organization, or community you agree to 256 | abide by its terms. 257 | 258 | ## License 259 | 260 | [MIT][license] © [Titus Wormer][author] 261 | 262 | 263 | 264 | [build-badge]: https://github.com/syntax-tree/esast-util-from-js/workflows/main/badge.svg 265 | 266 | [build]: https://github.com/syntax-tree/esast-util-from-js/actions 267 | 268 | [coverage-badge]: https://img.shields.io/codecov/c/github/syntax-tree/esast-util-from-js.svg 269 | 270 | [coverage]: https://codecov.io/github/syntax-tree/esast-util-from-js 271 | 272 | [downloads-badge]: https://img.shields.io/npm/dm/esast-util-from-js.svg 273 | 274 | [downloads]: https://www.npmjs.com/package/esast-util-from-js 275 | 276 | [size-badge]: https://img.shields.io/badge/dynamic/json?label=minzipped%20size&query=$.size.compressedSize&url=https://deno.bundlejs.com/?q=esast-util-from-js 277 | 278 | [size]: https://bundlejs.com/?q=esast-util-from-js 279 | 280 | [sponsors-badge]: https://opencollective.com/unified/sponsors/badge.svg 281 | 282 | [backers-badge]: https://opencollective.com/unified/backers/badge.svg 283 | 284 | [collective]: https://opencollective.com/unified 285 | 286 | [chat-badge]: https://img.shields.io/badge/chat-discussions-success.svg 287 | 288 | [chat]: https://github.com/syntax-tree/unist/discussions 289 | 290 | [npm]: https://docs.npmjs.com/cli/install 291 | 292 | [esm]: https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c 293 | 294 | [esmsh]: https://esm.sh 295 | 296 | [typescript]: https://www.typescriptlang.org 297 | 298 | [license]: license 299 | 300 | [author]: https://wooorm.com 301 | 302 | [health]: https://github.com/syntax-tree/.github 303 | 304 | [contributing]: https://github.com/syntax-tree/.github/blob/main/contributing.md 305 | 306 | [support]: https://github.com/syntax-tree/.github/blob/main/support.md 307 | 308 | [coc]: https://github.com/syntax-tree/.github/blob/main/code-of-conduct.md 309 | 310 | [esast]: https://github.com/syntax-tree/esast 311 | 312 | [node]: https://github.com/syntax-tree/esast#node 313 | 314 | [estree]: https://github.com/estree/estree 315 | 316 | [unist]: https://github.com/syntax-tree/unist 317 | 318 | [vfile]: https://github.com/vfile/vfile 319 | 320 | [acorn]: https://github.com/acornjs/acorn 321 | 322 | [acorn-jsx]: https://github.com/acornjs/acorn-jsx 323 | 324 | [acorn-stage3]: https://github.com/acornjs/acorn-stage3 325 | 326 | [estree-util-to-js]: https://github.com/syntax-tree/estree-util-to-js 327 | 328 | [vfile-message]: https://github.com/vfile/vfile-message 329 | 330 | [api-from-js]: #fromjsvalue-options 331 | 332 | [api-options]: #options 333 | 334 | [api-plugin]: #plugin 335 | 336 | [api-value]: #value 337 | 338 | [api-version]: #version-1 339 | -------------------------------------------------------------------------------- /test/fixtures/jsx/index.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "Program", 3 | "body": [ 4 | { 5 | "type": "VariableDeclaration", 6 | "declarations": [ 7 | { 8 | "type": "VariableDeclarator", 9 | "id": { 10 | "type": "Identifier", 11 | "name": "w", 12 | "position": { 13 | "start": { 14 | "line": 1, 15 | "column": 5, 16 | "offset": 4 17 | }, 18 | "end": { 19 | "line": 1, 20 | "column": 6, 21 | "offset": 5 22 | } 23 | } 24 | }, 25 | "init": { 26 | "type": "ObjectExpression", 27 | "properties": [], 28 | "position": { 29 | "start": { 30 | "line": 1, 31 | "column": 9, 32 | "offset": 8 33 | }, 34 | "end": { 35 | "line": 1, 36 | "column": 11, 37 | "offset": 10 38 | } 39 | } 40 | }, 41 | "position": { 42 | "start": { 43 | "line": 1, 44 | "column": 5, 45 | "offset": 4 46 | }, 47 | "end": { 48 | "line": 1, 49 | "column": 11, 50 | "offset": 10 51 | } 52 | } 53 | } 54 | ], 55 | "kind": "var", 56 | "position": { 57 | "start": { 58 | "line": 1, 59 | "column": 1, 60 | "offset": 0 61 | }, 62 | "end": { 63 | "line": 1, 64 | "column": 11, 65 | "offset": 10 66 | } 67 | } 68 | }, 69 | { 70 | "type": "ExpressionStatement", 71 | "expression": { 72 | "type": "CallExpression", 73 | "callee": { 74 | "type": "MemberExpression", 75 | "object": { 76 | "type": "Identifier", 77 | "name": "console", 78 | "position": { 79 | "start": { 80 | "line": 3, 81 | "column": 1, 82 | "offset": 12 83 | }, 84 | "end": { 85 | "line": 3, 86 | "column": 8, 87 | "offset": 19 88 | } 89 | } 90 | }, 91 | "property": { 92 | "type": "Identifier", 93 | "name": "log", 94 | "position": { 95 | "start": { 96 | "line": 3, 97 | "column": 9, 98 | "offset": 20 99 | }, 100 | "end": { 101 | "line": 3, 102 | "column": 12, 103 | "offset": 23 104 | } 105 | } 106 | }, 107 | "computed": false, 108 | "optional": false, 109 | "position": { 110 | "start": { 111 | "line": 3, 112 | "column": 1, 113 | "offset": 12 114 | }, 115 | "end": { 116 | "line": 3, 117 | "column": 12, 118 | "offset": 23 119 | } 120 | } 121 | }, 122 | "arguments": [ 123 | { 124 | "type": "JSXFragment", 125 | "openingFragment": { 126 | "type": "JSXOpeningFragment", 127 | "position": { 128 | "start": { 129 | "line": 4, 130 | "column": 3, 131 | "offset": 27 132 | }, 133 | "end": { 134 | "line": 4, 135 | "column": 5, 136 | "offset": 29 137 | } 138 | } 139 | }, 140 | "closingFragment": { 141 | "type": "JSXClosingFragment", 142 | "position": { 143 | "start": { 144 | "line": 6, 145 | "column": 3, 146 | "offset": 57 147 | }, 148 | "end": { 149 | "line": 6, 150 | "column": 6, 151 | "offset": 60 152 | } 153 | } 154 | }, 155 | "children": [ 156 | { 157 | "type": "JSXText", 158 | "value": "\n ", 159 | "position": { 160 | "start": { 161 | "line": 4, 162 | "column": 5, 163 | "offset": 29 164 | }, 165 | "end": { 166 | "line": 5, 167 | "column": 5, 168 | "offset": 34 169 | } 170 | } 171 | }, 172 | { 173 | "type": "JSXElement", 174 | "openingElement": { 175 | "type": "JSXOpeningElement", 176 | "attributes": [ 177 | { 178 | "type": "JSXAttribute", 179 | "name": { 180 | "type": "JSXIdentifier", 181 | "name": "y", 182 | "position": { 183 | "start": { 184 | "line": 5, 185 | "column": 8, 186 | "offset": 37 187 | }, 188 | "end": { 189 | "line": 5, 190 | "column": 9, 191 | "offset": 38 192 | } 193 | } 194 | }, 195 | "value": null, 196 | "position": { 197 | "start": { 198 | "line": 5, 199 | "column": 8, 200 | "offset": 37 201 | }, 202 | "end": { 203 | "line": 5, 204 | "column": 9, 205 | "offset": 38 206 | } 207 | } 208 | }, 209 | { 210 | "type": "JSXAttribute", 211 | "name": { 212 | "type": "JSXIdentifier", 213 | "name": "z", 214 | "position": { 215 | "start": { 216 | "line": 5, 217 | "column": 10, 218 | "offset": 39 219 | }, 220 | "end": { 221 | "line": 5, 222 | "column": 11, 223 | "offset": 40 224 | } 225 | } 226 | }, 227 | "value": { 228 | "type": "JSXExpressionContainer", 229 | "expression": { 230 | "type": "Literal", 231 | "value": 1, 232 | "position": { 233 | "start": { 234 | "line": 5, 235 | "column": 13, 236 | "offset": 42 237 | }, 238 | "end": { 239 | "line": 5, 240 | "column": 14, 241 | "offset": 43 242 | } 243 | } 244 | }, 245 | "position": { 246 | "start": { 247 | "line": 5, 248 | "column": 12, 249 | "offset": 41 250 | }, 251 | "end": { 252 | "line": 5, 253 | "column": 15, 254 | "offset": 44 255 | } 256 | } 257 | }, 258 | "position": { 259 | "start": { 260 | "line": 5, 261 | "column": 10, 262 | "offset": 39 263 | }, 264 | "end": { 265 | "line": 5, 266 | "column": 15, 267 | "offset": 44 268 | } 269 | } 270 | }, 271 | { 272 | "type": "JSXSpreadAttribute", 273 | "argument": { 274 | "type": "Identifier", 275 | "name": "w", 276 | "position": { 277 | "start": { 278 | "line": 5, 279 | "column": 20, 280 | "offset": 49 281 | }, 282 | "end": { 283 | "line": 5, 284 | "column": 21, 285 | "offset": 50 286 | } 287 | } 288 | }, 289 | "position": { 290 | "start": { 291 | "line": 5, 292 | "column": 16, 293 | "offset": 45 294 | }, 295 | "end": { 296 | "line": 5, 297 | "column": 22, 298 | "offset": 51 299 | } 300 | } 301 | } 302 | ], 303 | "name": { 304 | "type": "JSXIdentifier", 305 | "name": "x", 306 | "position": { 307 | "start": { 308 | "line": 5, 309 | "column": 6, 310 | "offset": 35 311 | }, 312 | "end": { 313 | "line": 5, 314 | "column": 7, 315 | "offset": 36 316 | } 317 | } 318 | }, 319 | "selfClosing": true, 320 | "position": { 321 | "start": { 322 | "line": 5, 323 | "column": 5, 324 | "offset": 34 325 | }, 326 | "end": { 327 | "line": 5, 328 | "column": 25, 329 | "offset": 54 330 | } 331 | } 332 | }, 333 | "closingElement": null, 334 | "children": [], 335 | "position": { 336 | "start": { 337 | "line": 5, 338 | "column": 5, 339 | "offset": 34 340 | }, 341 | "end": { 342 | "line": 5, 343 | "column": 25, 344 | "offset": 54 345 | } 346 | } 347 | }, 348 | { 349 | "type": "JSXText", 350 | "value": "\n ", 351 | "position": { 352 | "start": { 353 | "line": 5, 354 | "column": 25, 355 | "offset": 54 356 | }, 357 | "end": { 358 | "line": 6, 359 | "column": 3, 360 | "offset": 57 361 | } 362 | } 363 | } 364 | ], 365 | "position": { 366 | "start": { 367 | "line": 4, 368 | "column": 3, 369 | "offset": 27 370 | }, 371 | "end": { 372 | "line": 6, 373 | "column": 6, 374 | "offset": 60 375 | } 376 | } 377 | } 378 | ], 379 | "optional": false, 380 | "position": { 381 | "start": { 382 | "line": 3, 383 | "column": 1, 384 | "offset": 12 385 | }, 386 | "end": { 387 | "line": 7, 388 | "column": 2, 389 | "offset": 62 390 | } 391 | } 392 | }, 393 | "position": { 394 | "start": { 395 | "line": 3, 396 | "column": 1, 397 | "offset": 12 398 | }, 399 | "end": { 400 | "line": 7, 401 | "column": 2, 402 | "offset": 62 403 | } 404 | } 405 | } 406 | ], 407 | "sourceType": "script", 408 | "comments": [], 409 | "position": { 410 | "start": { 411 | "line": 1, 412 | "column": 1, 413 | "offset": 0 414 | }, 415 | "end": { 416 | "line": 8, 417 | "column": 1, 418 | "offset": 63 419 | } 420 | } 421 | } 422 | -------------------------------------------------------------------------------- /test/fixtures/values/index.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "Program", 3 | "body": [ 4 | { 5 | "type": "ExpressionStatement", 6 | "expression": { 7 | "type": "CallExpression", 8 | "callee": { 9 | "type": "MemberExpression", 10 | "object": { 11 | "type": "Identifier", 12 | "name": "console", 13 | "position": { 14 | "start": { 15 | "line": 1, 16 | "column": 1, 17 | "offset": 0 18 | }, 19 | "end": { 20 | "line": 1, 21 | "column": 8, 22 | "offset": 7 23 | } 24 | } 25 | }, 26 | "property": { 27 | "type": "Identifier", 28 | "name": "log", 29 | "position": { 30 | "start": { 31 | "line": 1, 32 | "column": 9, 33 | "offset": 8 34 | }, 35 | "end": { 36 | "line": 1, 37 | "column": 12, 38 | "offset": 11 39 | } 40 | } 41 | }, 42 | "computed": false, 43 | "optional": false, 44 | "position": { 45 | "start": { 46 | "line": 1, 47 | "column": 1, 48 | "offset": 0 49 | }, 50 | "end": { 51 | "line": 1, 52 | "column": 12, 53 | "offset": 11 54 | } 55 | } 56 | }, 57 | "arguments": [ 58 | { 59 | "type": "Literal", 60 | "value": 1, 61 | "position": { 62 | "start": { 63 | "line": 1, 64 | "column": 13, 65 | "offset": 12 66 | }, 67 | "end": { 68 | "line": 1, 69 | "column": 14, 70 | "offset": 13 71 | } 72 | } 73 | } 74 | ], 75 | "optional": false, 76 | "position": { 77 | "start": { 78 | "line": 1, 79 | "column": 1, 80 | "offset": 0 81 | }, 82 | "end": { 83 | "line": 1, 84 | "column": 15, 85 | "offset": 14 86 | } 87 | } 88 | }, 89 | "position": { 90 | "start": { 91 | "line": 1, 92 | "column": 1, 93 | "offset": 0 94 | }, 95 | "end": { 96 | "line": 1, 97 | "column": 15, 98 | "offset": 14 99 | } 100 | } 101 | }, 102 | { 103 | "type": "ExpressionStatement", 104 | "expression": { 105 | "type": "CallExpression", 106 | "callee": { 107 | "type": "MemberExpression", 108 | "object": { 109 | "type": "Identifier", 110 | "name": "console", 111 | "position": { 112 | "start": { 113 | "line": 3, 114 | "column": 1, 115 | "offset": 16 116 | }, 117 | "end": { 118 | "line": 3, 119 | "column": 8, 120 | "offset": 23 121 | } 122 | } 123 | }, 124 | "property": { 125 | "type": "Identifier", 126 | "name": "log", 127 | "position": { 128 | "start": { 129 | "line": 3, 130 | "column": 9, 131 | "offset": 24 132 | }, 133 | "end": { 134 | "line": 3, 135 | "column": 12, 136 | "offset": 27 137 | } 138 | } 139 | }, 140 | "computed": false, 141 | "optional": false, 142 | "position": { 143 | "start": { 144 | "line": 3, 145 | "column": 1, 146 | "offset": 16 147 | }, 148 | "end": { 149 | "line": 3, 150 | "column": 12, 151 | "offset": 27 152 | } 153 | } 154 | }, 155 | "arguments": [ 156 | { 157 | "type": "Literal", 158 | "value": "string", 159 | "position": { 160 | "start": { 161 | "line": 3, 162 | "column": 13, 163 | "offset": 28 164 | }, 165 | "end": { 166 | "line": 3, 167 | "column": 21, 168 | "offset": 36 169 | } 170 | } 171 | } 172 | ], 173 | "optional": false, 174 | "position": { 175 | "start": { 176 | "line": 3, 177 | "column": 1, 178 | "offset": 16 179 | }, 180 | "end": { 181 | "line": 3, 182 | "column": 22, 183 | "offset": 37 184 | } 185 | } 186 | }, 187 | "position": { 188 | "start": { 189 | "line": 3, 190 | "column": 1, 191 | "offset": 16 192 | }, 193 | "end": { 194 | "line": 3, 195 | "column": 22, 196 | "offset": 37 197 | } 198 | } 199 | }, 200 | { 201 | "type": "ExpressionStatement", 202 | "expression": { 203 | "type": "CallExpression", 204 | "callee": { 205 | "type": "MemberExpression", 206 | "object": { 207 | "type": "Identifier", 208 | "name": "console", 209 | "position": { 210 | "start": { 211 | "line": 5, 212 | "column": 1, 213 | "offset": 39 214 | }, 215 | "end": { 216 | "line": 5, 217 | "column": 8, 218 | "offset": 46 219 | } 220 | } 221 | }, 222 | "property": { 223 | "type": "Identifier", 224 | "name": "log", 225 | "position": { 226 | "start": { 227 | "line": 5, 228 | "column": 9, 229 | "offset": 47 230 | }, 231 | "end": { 232 | "line": 5, 233 | "column": 12, 234 | "offset": 50 235 | } 236 | } 237 | }, 238 | "computed": false, 239 | "optional": false, 240 | "position": { 241 | "start": { 242 | "line": 5, 243 | "column": 1, 244 | "offset": 39 245 | }, 246 | "end": { 247 | "line": 5, 248 | "column": 12, 249 | "offset": 50 250 | } 251 | } 252 | }, 253 | "arguments": [ 254 | { 255 | "type": "Literal", 256 | "value": true, 257 | "position": { 258 | "start": { 259 | "line": 5, 260 | "column": 13, 261 | "offset": 51 262 | }, 263 | "end": { 264 | "line": 5, 265 | "column": 17, 266 | "offset": 55 267 | } 268 | } 269 | } 270 | ], 271 | "optional": false, 272 | "position": { 273 | "start": { 274 | "line": 5, 275 | "column": 1, 276 | "offset": 39 277 | }, 278 | "end": { 279 | "line": 5, 280 | "column": 18, 281 | "offset": 56 282 | } 283 | } 284 | }, 285 | "position": { 286 | "start": { 287 | "line": 5, 288 | "column": 1, 289 | "offset": 39 290 | }, 291 | "end": { 292 | "line": 5, 293 | "column": 18, 294 | "offset": 56 295 | } 296 | } 297 | }, 298 | { 299 | "type": "ExpressionStatement", 300 | "expression": { 301 | "type": "CallExpression", 302 | "callee": { 303 | "type": "MemberExpression", 304 | "object": { 305 | "type": "Identifier", 306 | "name": "console", 307 | "position": { 308 | "start": { 309 | "line": 7, 310 | "column": 1, 311 | "offset": 58 312 | }, 313 | "end": { 314 | "line": 7, 315 | "column": 8, 316 | "offset": 65 317 | } 318 | } 319 | }, 320 | "property": { 321 | "type": "Identifier", 322 | "name": "log", 323 | "position": { 324 | "start": { 325 | "line": 7, 326 | "column": 9, 327 | "offset": 66 328 | }, 329 | "end": { 330 | "line": 7, 331 | "column": 12, 332 | "offset": 69 333 | } 334 | } 335 | }, 336 | "computed": false, 337 | "optional": false, 338 | "position": { 339 | "start": { 340 | "line": 7, 341 | "column": 1, 342 | "offset": 58 343 | }, 344 | "end": { 345 | "line": 7, 346 | "column": 12, 347 | "offset": 69 348 | } 349 | } 350 | }, 351 | "arguments": [ 352 | { 353 | "type": "Literal", 354 | "value": null, 355 | "position": { 356 | "start": { 357 | "line": 7, 358 | "column": 13, 359 | "offset": 70 360 | }, 361 | "end": { 362 | "line": 7, 363 | "column": 17, 364 | "offset": 74 365 | } 366 | } 367 | } 368 | ], 369 | "optional": false, 370 | "position": { 371 | "start": { 372 | "line": 7, 373 | "column": 1, 374 | "offset": 58 375 | }, 376 | "end": { 377 | "line": 7, 378 | "column": 18, 379 | "offset": 75 380 | } 381 | } 382 | }, 383 | "position": { 384 | "start": { 385 | "line": 7, 386 | "column": 1, 387 | "offset": 58 388 | }, 389 | "end": { 390 | "line": 7, 391 | "column": 18, 392 | "offset": 75 393 | } 394 | } 395 | }, 396 | { 397 | "type": "ExpressionStatement", 398 | "expression": { 399 | "type": "CallExpression", 400 | "callee": { 401 | "type": "MemberExpression", 402 | "object": { 403 | "type": "Identifier", 404 | "name": "console", 405 | "position": { 406 | "start": { 407 | "line": 9, 408 | "column": 1, 409 | "offset": 77 410 | }, 411 | "end": { 412 | "line": 9, 413 | "column": 8, 414 | "offset": 84 415 | } 416 | } 417 | }, 418 | "property": { 419 | "type": "Identifier", 420 | "name": "log", 421 | "position": { 422 | "start": { 423 | "line": 9, 424 | "column": 9, 425 | "offset": 85 426 | }, 427 | "end": { 428 | "line": 9, 429 | "column": 12, 430 | "offset": 88 431 | } 432 | } 433 | }, 434 | "computed": false, 435 | "optional": false, 436 | "position": { 437 | "start": { 438 | "line": 9, 439 | "column": 1, 440 | "offset": 77 441 | }, 442 | "end": { 443 | "line": 9, 444 | "column": 12, 445 | "offset": 88 446 | } 447 | } 448 | }, 449 | "arguments": [ 450 | { 451 | "type": "Identifier", 452 | "name": "undefined", 453 | "position": { 454 | "start": { 455 | "line": 9, 456 | "column": 13, 457 | "offset": 89 458 | }, 459 | "end": { 460 | "line": 9, 461 | "column": 22, 462 | "offset": 98 463 | } 464 | } 465 | } 466 | ], 467 | "optional": false, 468 | "position": { 469 | "start": { 470 | "line": 9, 471 | "column": 1, 472 | "offset": 77 473 | }, 474 | "end": { 475 | "line": 9, 476 | "column": 23, 477 | "offset": 99 478 | } 479 | } 480 | }, 481 | "position": { 482 | "start": { 483 | "line": 9, 484 | "column": 1, 485 | "offset": 77 486 | }, 487 | "end": { 488 | "line": 9, 489 | "column": 23, 490 | "offset": 99 491 | } 492 | } 493 | }, 494 | { 495 | "type": "ExpressionStatement", 496 | "expression": { 497 | "type": "CallExpression", 498 | "callee": { 499 | "type": "MemberExpression", 500 | "object": { 501 | "type": "Identifier", 502 | "name": "console", 503 | "position": { 504 | "start": { 505 | "line": 11, 506 | "column": 1, 507 | "offset": 101 508 | }, 509 | "end": { 510 | "line": 11, 511 | "column": 8, 512 | "offset": 108 513 | } 514 | } 515 | }, 516 | "property": { 517 | "type": "Identifier", 518 | "name": "log", 519 | "position": { 520 | "start": { 521 | "line": 11, 522 | "column": 9, 523 | "offset": 109 524 | }, 525 | "end": { 526 | "line": 11, 527 | "column": 12, 528 | "offset": 112 529 | } 530 | } 531 | }, 532 | "computed": false, 533 | "optional": false, 534 | "position": { 535 | "start": { 536 | "line": 11, 537 | "column": 1, 538 | "offset": 101 539 | }, 540 | "end": { 541 | "line": 11, 542 | "column": 12, 543 | "offset": 112 544 | } 545 | } 546 | }, 547 | "arguments": [ 548 | { 549 | "type": "Literal", 550 | "regex": { 551 | "pattern": "(?:)", 552 | "flags": "" 553 | }, 554 | "position": { 555 | "start": { 556 | "line": 11, 557 | "column": 13, 558 | "offset": 113 559 | }, 560 | "end": { 561 | "line": 11, 562 | "column": 19, 563 | "offset": 119 564 | } 565 | } 566 | } 567 | ], 568 | "optional": false, 569 | "position": { 570 | "start": { 571 | "line": 11, 572 | "column": 1, 573 | "offset": 101 574 | }, 575 | "end": { 576 | "line": 11, 577 | "column": 20, 578 | "offset": 120 579 | } 580 | } 581 | }, 582 | "position": { 583 | "start": { 584 | "line": 11, 585 | "column": 1, 586 | "offset": 101 587 | }, 588 | "end": { 589 | "line": 11, 590 | "column": 20, 591 | "offset": 120 592 | } 593 | } 594 | }, 595 | { 596 | "type": "ExpressionStatement", 597 | "expression": { 598 | "type": "CallExpression", 599 | "callee": { 600 | "type": "MemberExpression", 601 | "object": { 602 | "type": "Identifier", 603 | "name": "console", 604 | "position": { 605 | "start": { 606 | "line": 13, 607 | "column": 1, 608 | "offset": 122 609 | }, 610 | "end": { 611 | "line": 13, 612 | "column": 8, 613 | "offset": 129 614 | } 615 | } 616 | }, 617 | "property": { 618 | "type": "Identifier", 619 | "name": "log", 620 | "position": { 621 | "start": { 622 | "line": 13, 623 | "column": 9, 624 | "offset": 130 625 | }, 626 | "end": { 627 | "line": 13, 628 | "column": 12, 629 | "offset": 133 630 | } 631 | } 632 | }, 633 | "computed": false, 634 | "optional": false, 635 | "position": { 636 | "start": { 637 | "line": 13, 638 | "column": 1, 639 | "offset": 122 640 | }, 641 | "end": { 642 | "line": 13, 643 | "column": 12, 644 | "offset": 133 645 | } 646 | } 647 | }, 648 | "arguments": [ 649 | { 650 | "type": "Literal", 651 | "bigint": "0", 652 | "position": { 653 | "start": { 654 | "line": 13, 655 | "column": 13, 656 | "offset": 134 657 | }, 658 | "end": { 659 | "line": 13, 660 | "column": 15, 661 | "offset": 136 662 | } 663 | } 664 | } 665 | ], 666 | "optional": false, 667 | "position": { 668 | "start": { 669 | "line": 13, 670 | "column": 1, 671 | "offset": 122 672 | }, 673 | "end": { 674 | "line": 13, 675 | "column": 16, 676 | "offset": 137 677 | } 678 | } 679 | }, 680 | "position": { 681 | "start": { 682 | "line": 13, 683 | "column": 1, 684 | "offset": 122 685 | }, 686 | "end": { 687 | "line": 13, 688 | "column": 16, 689 | "offset": 137 690 | } 691 | } 692 | } 693 | ], 694 | "sourceType": "script", 695 | "comments": [], 696 | "position": { 697 | "start": { 698 | "line": 1, 699 | "column": 1, 700 | "offset": 0 701 | }, 702 | "end": { 703 | "line": 14, 704 | "column": 1, 705 | "offset": 138 706 | } 707 | } 708 | } 709 | --------------------------------------------------------------------------------