1 import {hasOwn, isArray} from "./util.js"
2 import {SourceLocation} from "./locutil.js"
4 // A second argument must be given to configure the parser process.
5 // These options are recognized (only `ecmaVersion` is required):
7 export const defaultOptions = {
8 // `ecmaVersion` indicates the ECMAScript version to parse. Must be
9 // either 3, 5, 6 (or 2015), 7 (2016), 8 (2017), 9 (2018), 10
10 // (2019), 11 (2020), 12 (2021), 13 (2022), or `"latest"` (the
11 // latest version the library supports). This influences support
12 // for strict mode, the set of reserved words, and support for
13 // new syntax features.
15 // `sourceType` indicates the mode the code should be parsed in.
16 // Can be either `"script"` or `"module"`. This influences global
17 // strict mode and parsing of `import` and `export` declarations.
19 // `onInsertedSemicolon` can be a callback that will be called
20 // when a semicolon is automatically inserted. It will be passed
21 // the position of the comma as an offset, and if `locations` is
22 // enabled, it is given the location as a `{line, column}` object
23 // as second argument.
24 onInsertedSemicolon: null,
25 // `onTrailingComma` is similar to `onInsertedSemicolon`, but for
27 onTrailingComma: null,
28 // By default, reserved words are only enforced if ecmaVersion >= 5.
29 // Set `allowReserved` to a boolean value to explicitly turn this on
30 // an off. When this option has the value "never", reserved words
31 // and keywords can also not be used as property names.
33 // When enabled, a return at the top level is not considered an
35 allowReturnOutsideFunction: false,
36 // When enabled, import/export statements are not constrained to
37 // appearing at the top of the program, and an import.meta expression
38 // in a script isn't considered an error.
39 allowImportExportEverywhere: false,
40 // By default, await identifiers are allowed to appear at the top-level scope only if ecmaVersion >= 2022.
41 // When enabled, await identifiers are allowed to appear at the top-level scope,
42 // but they are still not allowed in non-async functions.
43 allowAwaitOutsideFunction: null,
44 // When enabled, super identifiers are not constrained to
45 // appearing in methods and do not raise an error when they appear elsewhere.
46 allowSuperOutsideMethod: null,
47 // When enabled, hashbang directive in the beginning of file
48 // is allowed and treated as a line comment.
50 // When `locations` is on, `loc` properties holding objects with
51 // `start` and `end` properties in `{line, column}` form (with
52 // line being 1-based and column 0-based) will be attached to the
55 // A function can be passed as `onToken` option, which will
56 // cause Acorn to call that function with object in the same
57 // format as tokens returned from `tokenizer().getToken()`. Note
58 // that you are not allowed to call the parser from the
59 // callback—that will corrupt its internal state.
61 // A function can be passed as `onComment` option, which will
62 // cause Acorn to call that function with `(block, text, start,
63 // end)` parameters whenever a comment is skipped. `block` is a
64 // boolean indicating whether this is a block (`/* */`) comment,
65 // `text` is the content of the comment, and `start` and `end` are
66 // character offsets that denote the start and end of the comment.
67 // When the `locations` option is on, two more parameters are
68 // passed, the full `{line, column}` locations of the start and
69 // end of the comments. Note that you are not allowed to call the
70 // parser from the callback—that will corrupt its internal state.
72 // Nodes have their start and end characters offsets recorded in
73 // `start` and `end` properties (directly on the node, rather than
74 // the `loc` object, which holds line/column data. To also add a
75 // [semi-standardized][range] `range` property holding a `[start,
76 // end]` array with the same numbers, set the `ranges` option to
79 // [range]: https://bugzilla.mozilla.org/show_bug.cgi?id=745678
81 // It is possible to parse multiple files into a single AST by
82 // passing the tree produced by parsing the first file as
83 // `program` option in subsequent parses. This will add the
84 // toplevel forms of the parsed file to the `Program` (top) node
85 // of an existing parse tree.
87 // When `locations` is on, you can pass this to record the source
88 // file in every node's `loc` object.
90 // This value, if given, is stored in every node, whether
91 // `locations` is on or off.
92 directSourceFile: null,
93 // When enabled, parenthesized expressions are represented by
94 // (non-standard) ParenthesizedExpression nodes
98 // Interpret and default an options object
100 let warnedAboutEcmaVersion = false
102 export function getOptions(opts) {
105 for (let opt in defaultOptions)
106 options[opt] = opts && hasOwn(opts, opt) ? opts[opt] : defaultOptions[opt]
108 if (options.ecmaVersion === "latest") {
109 options.ecmaVersion = 1e8
110 } else if (options.ecmaVersion == null) {
111 if (!warnedAboutEcmaVersion && typeof console === "object" && console.warn) {
112 warnedAboutEcmaVersion = true
113 console.warn("Since Acorn 8.0.0, options.ecmaVersion is required.\nDefaulting to 2020, but this will stop working in the future.")
115 options.ecmaVersion = 11
116 } else if (options.ecmaVersion >= 2015) {
117 options.ecmaVersion -= 2009
120 if (options.allowReserved == null)
121 options.allowReserved = options.ecmaVersion < 5
123 if (isArray(options.onToken)) {
124 let tokens = options.onToken
125 options.onToken = (token) => tokens.push(token)
127 if (isArray(options.onComment))
128 options.onComment = pushComment(options, options.onComment)
133 function pushComment(options, array) {
134 return function(block, text, start, end, startLoc, endLoc) {
136 type: block ? "Block" : "Line",
141 if (options.locations)
142 comment.loc = new SourceLocation(this, startLoc, endLoc)
144 comment.range = [start, end]