@willbooster/tree-sitter-javascript 1.0.7 → 1.0.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/grammar.js CHANGED
@@ -8,6 +8,46 @@
8
8
  /// <reference types="tree-sitter-cli/dsl" />
9
9
  // @ts-check
10
10
 
11
+ // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Lexical_grammar#reserved_words
12
+ const RESERVED_WORDS = [
13
+ 'break',
14
+ 'case',
15
+ 'catch',
16
+ 'class',
17
+ 'const',
18
+ 'continue',
19
+ 'debugger',
20
+ 'default',
21
+ 'delete',
22
+ 'do',
23
+ 'else',
24
+ 'export',
25
+ 'extends',
26
+ 'false',
27
+ 'finally',
28
+ 'for',
29
+ 'function',
30
+ 'if',
31
+ 'import',
32
+ 'in',
33
+ 'instanceof',
34
+ 'new',
35
+ 'null',
36
+ 'return',
37
+ 'super',
38
+ 'switch',
39
+ 'this',
40
+ 'throw',
41
+ 'true',
42
+ 'try',
43
+ 'typeof',
44
+ 'var',
45
+ 'void',
46
+ 'while',
47
+ 'with',
48
+ ];
49
+ const NAMED_RESERVED_WORDS = new Set(['this', 'super', 'true', 'false', 'null']);
50
+
11
51
  // oxlint-disable-next-line unicorn/prefer-module -- This package is CommonJS, so tree-sitter loads grammar.js as CommonJS.
12
52
  module.exports = grammar({
13
53
  name: 'javascript',
@@ -34,44 +74,7 @@ module.exports = grammar({
34
74
  extras: ($) => [$.comment, $.html_comment, /[\s\p{Zs}\uFEFF\u2028\u2029\u2060\u200B]/u],
35
75
 
36
76
  reserved: {
37
- // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Lexical_grammar#reserved_words
38
- global: () => [
39
- 'break',
40
- 'case',
41
- 'catch',
42
- 'class',
43
- 'const',
44
- 'continue',
45
- 'debugger',
46
- 'default',
47
- 'delete',
48
- 'do',
49
- 'else',
50
- 'export',
51
- 'extends',
52
- 'false',
53
- 'finally',
54
- 'for',
55
- 'function',
56
- 'if',
57
- 'import',
58
- 'in',
59
- 'instanceof',
60
- 'new',
61
- 'null',
62
- 'return',
63
- 'super',
64
- 'switch',
65
- 'this',
66
- 'throw',
67
- 'true',
68
- 'try',
69
- 'typeof',
70
- 'var',
71
- 'void',
72
- 'while',
73
- 'with',
74
- ],
77
+ global: () => RESERVED_WORDS,
75
78
  properties: () => [],
76
79
  },
77
80
 
@@ -129,6 +132,7 @@ module.exports = grammar({
129
132
  ],
130
133
 
131
134
  conflicts: ($) => [
135
+ [$._local_export_specifier, $._module_export_name],
132
136
  [$.primary_expression, $._property_name],
133
137
  [$.primary_expression, $.await_expression],
134
138
  [$.primary_expression, $.await_expression, $._property_name],
@@ -167,7 +171,7 @@ module.exports = grammar({
167
171
  seq('*', $._from_clause),
168
172
  seq($.namespace_export, $._from_clause),
169
173
  seq($.export_clause, $._from_clause),
170
- $.export_clause
174
+ alias($._local_export_clause, $.export_clause)
171
175
  ),
172
176
  $._semicolon
173
177
  ),
@@ -188,7 +192,22 @@ module.exports = grammar({
188
192
  export_specifier: ($) =>
189
193
  seq(field('name', $._module_export_name), optional(seq('as', field('alias', $._module_export_name)))),
190
194
 
191
- _module_export_name: ($) => choice($.identifier, $.string, 'default'),
195
+ // Without a `from` clause, each name refers to a local binding, which cannot be a reserved word.
196
+ _local_export_clause: ($) =>
197
+ seq('{', commaSep(alias($._local_export_specifier, $.export_specifier)), optional(','), '}'),
198
+
199
+ _local_export_specifier: ($) =>
200
+ seq(field('name', choice($.identifier, $.string)), optional(seq('as', field('alias', $._module_export_name)))),
201
+
202
+ // Reserved words are listed as keywords rather than allowed through the property word set, because the word set
203
+ // would also apply to the local bindings that share these positions until `as` or `from` (e.g. `import { if }`).
204
+ _module_export_name: ($) =>
205
+ choice(
206
+ $.identifier,
207
+ $.string,
208
+ // `this`, `super`, `true`, `false`, and `null` are named rules, and a bare string would make them non-terminals.
209
+ alias(choice(...RESERVED_WORDS.map((word) => (NAMED_RESERVED_WORDS.has(word) ? $[word] : word))), $.identifier)
210
+ ),
192
211
 
193
212
  declaration: ($) =>
194
213
  choice(
@@ -273,7 +292,14 @@ module.exports = grammar({
273
292
  seq(field('kind', choice('let', 'const')), commaSep1($.variable_declarator), $._semicolon),
274
293
 
275
294
  using_declaration: ($) =>
276
- seq(field('kind', choice('using', seq('await', 'using'))), commaSep1($.variable_declarator), $._semicolon),
295
+ seq(
296
+ field('kind', choice('using', seq('await', 'using'))),
297
+ commaSep1(alias($._using_declarator, $.variable_declarator)),
298
+ $._semicolon
299
+ ),
300
+
301
+ _using_declarator: ($) =>
302
+ seq(field('name', choice($.identifier, alias('of', $.identifier))), optional($._initializer)),
277
303
 
278
304
  variable_declarator: ($) =>
279
305
  seq(
@@ -301,31 +327,46 @@ module.exports = grammar({
301
327
  seq(
302
328
  'for',
303
329
  '(',
304
- choice(
305
- field(
306
- 'initializer',
307
- choice(
308
- alias($.for_lexical_declaration, $.lexical_declaration),
309
- alias($.for_variable_declaration, $.variable_declaration)
310
- )
311
- ),
312
- seq(field('initializer', $._expressions), ';'),
313
- field('initializer', $.empty_statement)
314
- ),
315
- field('condition', choice(seq($._expressions, ';'), $.empty_statement)),
330
+ $._for_initializer,
331
+ $._for_condition,
316
332
  field('increment', optional($._expressions)),
317
333
  ')',
318
334
  field('body', $.statement)
319
335
  ),
320
336
 
337
+ // Extracted into rules because tree-sitter expands a `choice` written inline in the `seq` above into one production
338
+ // per alternative, each repeating the parse states of the rest of the header (about 30 KB of Wasm). They are hidden
339
+ // so that `initializer` and `condition` stay fields of `for_statement` and no node type is added.
340
+ _for_initializer: ($) =>
341
+ choice(
342
+ field(
343
+ 'initializer',
344
+ choice(
345
+ alias($.for_lexical_declaration, $.lexical_declaration),
346
+ alias($.for_variable_declaration, $.variable_declaration),
347
+ alias($._for_using_declaration, $.using_declaration)
348
+ )
349
+ ),
350
+ seq(field('initializer', $._expressions), ';'),
351
+ field('initializer', $.empty_statement)
352
+ ),
353
+
354
+ _for_condition: ($) => field('condition', choice(seq($._expressions, ';'), $.empty_statement)),
355
+
321
356
  // ECMAScript inserts no semicolon inside a for header, so these declarations end only with `;`. Accepting an
322
357
  // automatic semicolon there made `for (let x\n of y)` ambiguous until `of`, and an incremental reparse could
323
- // reuse a declaration built when that ambiguity was resolved differently. The rules are visible and only used
324
- // through aliases: a hidden rule would make `for_statement` inherit their `kind` field.
358
+ // reuse a declaration built when that ambiguity was resolved differently.
325
359
  for_lexical_declaration: ($) => seq(field('kind', choice('let', 'const')), commaSep1($.variable_declarator), ';'),
326
360
 
327
361
  for_variable_declaration: ($) => seq('var', commaSep1($.variable_declarator), ';'),
328
362
 
363
+ _for_using_declaration: ($) =>
364
+ seq(
365
+ field('kind', choice('using', seq('await', 'using'))),
366
+ commaSep1(alias($._using_declarator, $.variable_declarator)),
367
+ ';'
368
+ ),
369
+
329
370
  for_in_statement: ($) => seq('for', optional('await'), $._for_header, field('body', $.statement)),
330
371
 
331
372
  _for_header: ($) =>
@@ -344,7 +385,7 @@ module.exports = grammar({
344
385
  ),
345
386
  seq(
346
387
  field('kind', choice('using', seq('await', 'using'))),
347
- field('left', choice($.identifier, alias('of', $.identifier), $._destructuring_pattern))
388
+ field('left', choice($.identifier, alias('of', $.identifier)))
348
389
  )
349
390
  ),
350
391
  field('operator', choice('in', 'of')),
@@ -547,15 +588,18 @@ module.exports = grammar({
547
588
 
548
589
  jsx_identifier: () => /[a-zA-Z_$][a-zA-Z\d_$]*-[a-zA-Z\d_$-]*/,
549
590
 
550
- _jsx_identifier: ($) => choice(alias($.jsx_identifier, $.identifier), $.identifier),
591
+ _jsx_identifier: ($) => choice(alias($.jsx_identifier, $.identifier), reserved('properties', $.identifier)),
551
592
 
552
593
  nested_identifier: ($) =>
553
594
  prec(
554
595
  'member',
555
596
  seq(
556
- field('object', choice($.identifier, alias($.nested_identifier, $.member_expression))),
597
+ field(
598
+ 'object',
599
+ choice(reserved('properties', $.identifier), alias($.nested_identifier, $.member_expression))
600
+ ),
557
601
  '.',
558
- field('property', alias($.identifier, $.property_identifier))
602
+ field('property', alias(reserved('properties', $.identifier), $.property_identifier))
559
603
  )
560
604
  ),
561
605
 
@@ -1130,7 +1174,7 @@ module.exports = grammar({
1130
1174
 
1131
1175
  computed_property_name: ($) => seq('[', $.expression, ']'),
1132
1176
 
1133
- _reserved_identifier: () => choice('get', 'set', 'async', 'await', 'static', 'export', 'let'),
1177
+ _reserved_identifier: () => choice('get', 'set', 'async', 'await', 'static', 'export', 'let', 'using'),
1134
1178
 
1135
1179
  _semicolon: ($) => choice($._automatic_semicolon, ';'),
1136
1180
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@willbooster/tree-sitter-javascript",
3
- "version": "1.0.7",
3
+ "version": "1.0.9",
4
4
  "description": "JavaScript grammar for tree-sitter",
5
5
  "keywords": [
6
6
  "incremental",
@@ -202,3 +202,17 @@
202
202
  "with"
203
203
  "yield"
204
204
  ] @keyword
205
+
206
+ ; `default` as a module export name is an identifier node.
207
+ (export_specifier
208
+ name: (identifier) @keyword
209
+ (#eq? @keyword "default"))
210
+ (export_specifier
211
+ alias: (identifier) @keyword
212
+ (#eq? @keyword "default"))
213
+ (import_specifier
214
+ name: (identifier) @keyword
215
+ (#eq? @keyword "default"))
216
+ (namespace_export
217
+ (identifier) @keyword
218
+ (#eq? @keyword "default"))
@@ -1094,10 +1094,6 @@
1094
1094
  "multiple": false,
1095
1095
  "required": false,
1096
1096
  "types": [
1097
- {
1098
- "type": "default",
1099
- "named": false
1100
- },
1101
1097
  {
1102
1098
  "type": "identifier",
1103
1099
  "named": true
@@ -1112,10 +1108,6 @@
1112
1108
  "multiple": false,
1113
1109
  "required": true,
1114
1110
  "types": [
1115
- {
1116
- "type": "default",
1117
- "named": false
1118
- },
1119
1111
  {
1120
1112
  "type": "identifier",
1121
1113
  "named": true
@@ -1459,6 +1451,10 @@
1459
1451
  "type": "sequence_expression",
1460
1452
  "named": true
1461
1453
  },
1454
+ {
1455
+ "type": "using_declaration",
1456
+ "named": true
1457
+ },
1462
1458
  {
1463
1459
  "type": "variable_declaration",
1464
1460
  "named": true
@@ -1727,10 +1723,6 @@
1727
1723
  "multiple": false,
1728
1724
  "required": true,
1729
1725
  "types": [
1730
- {
1731
- "type": "default",
1732
- "named": false
1733
- },
1734
1726
  {
1735
1727
  "type": "identifier",
1736
1728
  "named": true
@@ -2186,7 +2178,7 @@
2186
2178
  "fields": {},
2187
2179
  "children": {
2188
2180
  "multiple": false,
2189
- "required": false,
2181
+ "required": true,
2190
2182
  "types": [
2191
2183
  {
2192
2184
  "type": "identifier",
Binary file
package/tree-sitter.json CHANGED
@@ -16,7 +16,7 @@
16
16
  }
17
17
  ],
18
18
  "metadata": {
19
- "version": "1.0.7",
19
+ "version": "1.0.9",
20
20
  "license": "MIT",
21
21
  "description": "JavaScript grammar for tree-sitter",
22
22
  "authors": [