oxc-parser 0.72.0 → 0.72.2

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/README.md CHANGED
@@ -18,6 +18,7 @@ If you need all ASTs in the same with-TS-properties format, use the `astType: 't
18
18
 
19
19
  The only differences between Oxc's AST and ESTree / TS-ESTree are:
20
20
 
21
+ - Support for Stage 3 [decorators](https://github.com/tc39/proposal-decorators).
21
22
  - Support for Stage 3 ECMA features [`import defer`](https://github.com/tc39/proposal-defer-import-eval)
22
23
  and [`import source`](https://github.com/tc39/proposal-source-phase-imports).
23
24
  - In TS-ESTree AST, `import.defer(...)` and `import.source(...)` are represented as an `ImportExpression`
package/bindings.js CHANGED
@@ -390,6 +390,7 @@ module.exports.ExportLocalNameKind = nativeBinding.ExportLocalNameKind
390
390
  module.exports.getBufferOffset = nativeBinding.getBufferOffset
391
391
  module.exports.ImportNameKind = nativeBinding.ImportNameKind
392
392
  module.exports.parseAsync = nativeBinding.parseAsync
393
+ module.exports.parseAsyncRaw = nativeBinding.parseAsyncRaw
393
394
  module.exports.parseSync = nativeBinding.parseSync
394
395
  module.exports.parseSyncRaw = nativeBinding.parseSyncRaw
395
396
  module.exports.rawTransferSupported = nativeBinding.rawTransferSupported
@@ -123,12 +123,12 @@ function deserializeObjectProperty(pos) {
123
123
  type: 'Property',
124
124
  start: deserializeU32(pos),
125
125
  end: deserializeU32(pos + 4),
126
+ kind: deserializePropertyKind(pos + 40),
127
+ key: deserializePropertyKey(pos + 8),
128
+ value: deserializeExpression(pos + 24),
126
129
  method: deserializeBool(pos + 41),
127
130
  shorthand: deserializeBool(pos + 42),
128
131
  computed: deserializeBool(pos + 43),
129
- key: deserializePropertyKey(pos + 8),
130
- value: deserializeExpression(pos + 24),
131
- kind: deserializePropertyKind(pos + 40),
132
132
  };
133
133
  }
134
134
 
@@ -137,8 +137,8 @@ function deserializeTemplateLiteral(pos) {
137
137
  type: 'TemplateLiteral',
138
138
  start: deserializeU32(pos),
139
139
  end: deserializeU32(pos + 4),
140
- expressions: deserializeVecExpression(pos + 32),
141
140
  quasis: deserializeVecTemplateElement(pos + 8),
141
+ expressions: deserializeVecExpression(pos + 32),
142
142
  };
143
143
  }
144
144
 
@@ -178,8 +178,8 @@ function deserializeComputedMemberExpression(pos) {
178
178
  end: deserializeU32(pos + 4),
179
179
  object: deserializeExpression(pos + 8),
180
180
  property: deserializeExpression(pos + 24),
181
- computed: true,
182
181
  optional: deserializeBool(pos + 40),
182
+ computed: true,
183
183
  };
184
184
  }
185
185
 
@@ -190,8 +190,8 @@ function deserializeStaticMemberExpression(pos) {
190
190
  end: deserializeU32(pos + 4),
191
191
  object: deserializeExpression(pos + 8),
192
192
  property: deserializeIdentifierName(pos + 24),
193
- computed: false,
194
193
  optional: deserializeBool(pos + 48),
194
+ computed: false,
195
195
  };
196
196
  }
197
197
 
@@ -202,8 +202,8 @@ function deserializePrivateFieldExpression(pos) {
202
202
  end: deserializeU32(pos + 4),
203
203
  object: deserializeExpression(pos + 8),
204
204
  property: deserializePrivateIdentifier(pos + 24),
205
- computed: false,
206
205
  optional: deserializeBool(pos + 48),
206
+ computed: false,
207
207
  };
208
208
  }
209
209
 
@@ -264,8 +264,8 @@ function deserializeUnaryExpression(pos) {
264
264
  start: deserializeU32(pos),
265
265
  end: deserializeU32(pos + 4),
266
266
  operator: deserializeUnaryOperator(pos + 24),
267
- prefix: true,
268
267
  argument: deserializeExpression(pos + 8),
268
+ prefix: true,
269
269
  };
270
270
  }
271
271
 
@@ -386,12 +386,12 @@ function deserializeAssignmentTargetPropertyIdentifier(pos) {
386
386
  type: 'Property',
387
387
  start,
388
388
  end,
389
+ kind: 'init',
390
+ key,
391
+ value,
389
392
  method: false,
390
393
  shorthand: true,
391
394
  computed: false,
392
- key,
393
- value,
394
- kind: 'init',
395
395
  };
396
396
  }
397
397
 
@@ -400,12 +400,12 @@ function deserializeAssignmentTargetPropertyProperty(pos) {
400
400
  type: 'Property',
401
401
  start: deserializeU32(pos),
402
402
  end: deserializeU32(pos + 4),
403
+ kind: 'init',
404
+ key: deserializePropertyKey(pos + 8),
405
+ value: deserializeAssignmentTargetMaybeDefault(pos + 24),
403
406
  method: false,
404
407
  shorthand: false,
405
408
  computed: deserializeBool(pos + 40),
406
- key: deserializePropertyKey(pos + 8),
407
- value: deserializeAssignmentTargetMaybeDefault(pos + 24),
408
- kind: 'init',
409
409
  };
410
410
  }
411
411
 
@@ -486,8 +486,8 @@ function deserializeVariableDeclaration(pos) {
486
486
  type: 'VariableDeclaration',
487
487
  start: deserializeU32(pos),
488
488
  end: deserializeU32(pos + 4),
489
- declarations: deserializeVecVariableDeclarator(pos + 8),
490
489
  kind: deserializeVariableDeclarationKind(pos + 32),
490
+ declarations: deserializeVecVariableDeclarator(pos + 8),
491
491
  };
492
492
  }
493
493
 
@@ -636,8 +636,8 @@ function deserializeSwitchCase(pos) {
636
636
  type: 'SwitchCase',
637
637
  start: deserializeU32(pos),
638
638
  end: deserializeU32(pos + 4),
639
- consequent: deserializeVecStatement(pos + 24),
640
639
  test: deserializeOptionExpression(pos + 8),
640
+ consequent: deserializeVecStatement(pos + 24),
641
641
  };
642
642
  }
643
643
 
@@ -646,8 +646,8 @@ function deserializeLabeledStatement(pos) {
646
646
  type: 'LabeledStatement',
647
647
  start: deserializeU32(pos),
648
648
  end: deserializeU32(pos + 4),
649
- body: deserializeStatement(pos + 32),
650
649
  label: deserializeLabelIdentifier(pos + 8),
650
+ body: deserializeStatement(pos + 32),
651
651
  };
652
652
  }
653
653
 
@@ -728,12 +728,12 @@ function deserializeBindingProperty(pos) {
728
728
  type: 'Property',
729
729
  start: deserializeU32(pos),
730
730
  end: deserializeU32(pos + 4),
731
+ kind: 'init',
732
+ key: deserializePropertyKey(pos + 8),
733
+ value: deserializeBindingPattern(pos + 24),
731
734
  method: false,
732
735
  shorthand: deserializeBool(pos + 56),
733
736
  computed: deserializeBool(pos + 57),
734
- key: deserializePropertyKey(pos + 8),
735
- value: deserializeBindingPattern(pos + 24),
736
- kind: 'init',
737
737
  };
738
738
  }
739
739
 
@@ -765,11 +765,11 @@ function deserializeFunction(pos) {
765
765
  start: deserializeU32(pos),
766
766
  end: deserializeU32(pos + 4),
767
767
  id: deserializeOptionBindingIdentifier(pos + 8),
768
- expression: false,
769
768
  generator: deserializeBool(pos + 85),
770
769
  async: deserializeBool(pos + 86),
771
770
  params,
772
771
  body: deserializeOptionBoxFunctionBody(pos + 72),
772
+ expression: false,
773
773
  };
774
774
  }
775
775
 
@@ -809,12 +809,12 @@ function deserializeArrowFunctionExpression(pos) {
809
809
  type: 'ArrowFunctionExpression',
810
810
  start: deserializeU32(pos),
811
811
  end: deserializeU32(pos + 4),
812
- id: null,
813
812
  expression,
814
- generator: false,
815
813
  async: deserializeBool(pos + 45),
816
814
  params: deserializeBoxFormalParameters(pos + 16),
817
815
  body: expression ? body.body[0].expression : body,
816
+ id: null,
817
+ generator: false,
818
818
  };
819
819
  }
820
820
 
@@ -833,6 +833,7 @@ function deserializeClass(pos) {
833
833
  type: deserializeClassType(pos + 132),
834
834
  start: deserializeU32(pos),
835
835
  end: deserializeU32(pos + 4),
836
+ decorators: deserializeVecDecorator(pos + 8),
836
837
  id: deserializeOptionBindingIdentifier(pos + 32),
837
838
  superClass: deserializeOptionExpression(pos + 72),
838
839
  body: deserializeBoxClassBody(pos + 120),
@@ -853,11 +854,12 @@ function deserializeMethodDefinition(pos) {
853
854
  type: deserializeMethodDefinitionType(pos + 56),
854
855
  start: deserializeU32(pos),
855
856
  end: deserializeU32(pos + 4),
856
- static: deserializeBool(pos + 59),
857
- computed: deserializeBool(pos + 58),
857
+ decorators: deserializeVecDecorator(pos + 8),
858
858
  key: deserializePropertyKey(pos + 32),
859
- kind: deserializeMethodDefinitionKind(pos + 57),
860
859
  value: deserializeBoxFunction(pos + 48),
860
+ kind: deserializeMethodDefinitionKind(pos + 57),
861
+ computed: deserializeBool(pos + 58),
862
+ static: deserializeBool(pos + 59),
861
863
  };
862
864
  }
863
865
 
@@ -866,10 +868,11 @@ function deserializePropertyDefinition(pos) {
866
868
  type: deserializePropertyDefinitionType(pos + 72),
867
869
  start: deserializeU32(pos),
868
870
  end: deserializeU32(pos + 4),
869
- static: deserializeBool(pos + 74),
870
- computed: deserializeBool(pos + 73),
871
+ decorators: deserializeVecDecorator(pos + 8),
871
872
  key: deserializePropertyKey(pos + 32),
872
873
  value: deserializeOptionExpression(pos + 56),
874
+ computed: deserializeBool(pos + 73),
875
+ static: deserializeBool(pos + 74),
873
876
  };
874
877
  }
875
878
 
@@ -896,6 +899,7 @@ function deserializeAccessorProperty(pos) {
896
899
  type: deserializeAccessorPropertyType(pos + 72),
897
900
  start: deserializeU32(pos),
898
901
  end: deserializeU32(pos + 4),
902
+ decorators: deserializeVecDecorator(pos + 8),
899
903
  key: deserializePropertyKey(pos + 32),
900
904
  value: deserializeOptionExpression(pos + 56),
901
905
  computed: deserializeBool(pos + 73),
@@ -924,8 +928,8 @@ function deserializeImportDeclaration(pos) {
924
928
  end: deserializeU32(pos + 4),
925
929
  specifiers,
926
930
  source: deserializeStringLiteral(pos + 32),
927
- attributes: withClause === null ? [] : withClause.attributes,
928
931
  phase: deserializeOptionImportPhase(pos + 88),
932
+ attributes: withClause === null ? [] : withClause.attributes,
929
933
  };
930
934
  }
931
935
 
@@ -1142,8 +1146,8 @@ function deserializeJSXElement(pos) {
1142
1146
  start: deserializeU32(pos),
1143
1147
  end: deserializeU32(pos + 4),
1144
1148
  openingElement,
1145
- closingElement,
1146
1149
  children: deserializeVecJSXChild(pos + 16),
1150
+ closingElement,
1147
1151
  };
1148
1152
  }
1149
1153
 
@@ -1152,8 +1156,8 @@ function deserializeJSXOpeningElement(pos) {
1152
1156
  type: 'JSXOpeningElement',
1153
1157
  start: deserializeU32(pos),
1154
1158
  end: deserializeU32(pos + 4),
1155
- attributes: deserializeVecJSXAttributeItem(pos + 32),
1156
1159
  name: deserializeJSXElementName(pos + 8),
1160
+ attributes: deserializeVecJSXAttributeItem(pos + 32),
1157
1161
  selfClosing: false,
1158
1162
  };
1159
1163
  }
@@ -1173,8 +1177,8 @@ function deserializeJSXFragment(pos) {
1173
1177
  start: deserializeU32(pos),
1174
1178
  end: deserializeU32(pos + 4),
1175
1179
  openingFragment: deserializeJSXOpeningFragment(pos + 8),
1176
- closingFragment: deserializeJSXClosingFragment(pos + 40),
1177
1180
  children: deserializeVecJSXChild(pos + 16),
1181
+ closingFragment: deserializeJSXClosingFragment(pos + 40),
1178
1182
  };
1179
1183
  }
1180
1184
 
@@ -1285,8 +1289,8 @@ function deserializeTSThisParameter(pos) {
1285
1289
  type: 'Identifier',
1286
1290
  start: deserializeU32(pos),
1287
1291
  end: deserializeU32(pos + 4),
1288
- name: 'this',
1289
1292
  decorators: [],
1293
+ name: 'this',
1290
1294
  optional: false,
1291
1295
  typeAnnotation: deserializeOptionBoxTSTypeAnnotation(pos + 16),
1292
1296
  };
@@ -1319,8 +1323,8 @@ function deserializeTSEnumMember(pos) {
1319
1323
  start: deserializeU32(pos),
1320
1324
  end: deserializeU32(pos + 4),
1321
1325
  id: deserializeTSEnumMemberName(pos + 8),
1322
- computed: deserializeU8(pos + 8) > 1,
1323
1326
  initializer: deserializeOptionExpression(pos + 24),
1327
+ computed: deserializeU8(pos + 8) > 1,
1324
1328
  };
1325
1329
  }
1326
1330
 
@@ -1760,8 +1764,8 @@ function deserializeTSIndexSignatureName(pos) {
1760
1764
  type: 'Identifier',
1761
1765
  start: deserializeU32(pos),
1762
1766
  end: deserializeU32(pos + 4),
1763
- name: deserializeStr(pos + 8),
1764
1767
  decorators: [],
1768
+ name: deserializeStr(pos + 8),
1765
1769
  optional: false,
1766
1770
  typeAnnotation: deserializeBoxTSTypeAnnotation(pos + 24),
1767
1771
  };
@@ -1913,19 +1917,19 @@ function deserializeTSConstructorType(pos) {
1913
1917
  }
1914
1918
 
1915
1919
  function deserializeTSMappedType(pos) {
1920
+ const typeParameter = deserializeBoxTSTypeParameter(pos + 8);
1916
1921
  let optional = deserializeOptionTSMappedTypeModifierOperator(pos + 52);
1917
1922
  if (optional === null) optional = false;
1918
- const typeParameter = deserializeBoxTSTypeParameter(pos + 8);
1919
1923
  return {
1920
1924
  type: 'TSMappedType',
1921
1925
  start: deserializeU32(pos),
1922
1926
  end: deserializeU32(pos + 4),
1927
+ key: typeParameter.name,
1928
+ constraint: typeParameter.constraint,
1923
1929
  nameType: deserializeOptionTSType(pos + 16),
1924
1930
  typeAnnotation: deserializeOptionTSType(pos + 32),
1925
1931
  optional,
1926
1932
  readonly: deserializeOptionTSMappedTypeModifierOperator(pos + 53),
1927
- key: typeParameter.name,
1928
- constraint: typeParameter.constraint,
1929
1933
  };
1930
1934
  }
1931
1935
 
@@ -73,8 +73,8 @@ function deserializeIdentifierName(pos) {
73
73
  type: 'Identifier',
74
74
  start: deserializeU32(pos),
75
75
  end: deserializeU32(pos + 4),
76
- name: deserializeStr(pos + 8),
77
76
  decorators: [],
77
+ name: deserializeStr(pos + 8),
78
78
  optional: false,
79
79
  typeAnnotation: null,
80
80
  };
@@ -85,8 +85,8 @@ function deserializeIdentifierReference(pos) {
85
85
  type: 'Identifier',
86
86
  start: deserializeU32(pos),
87
87
  end: deserializeU32(pos + 4),
88
- name: deserializeStr(pos + 8),
89
88
  decorators: [],
89
+ name: deserializeStr(pos + 8),
90
90
  optional: false,
91
91
  typeAnnotation: null,
92
92
  };
@@ -97,8 +97,8 @@ function deserializeBindingIdentifier(pos) {
97
97
  type: 'Identifier',
98
98
  start: deserializeU32(pos),
99
99
  end: deserializeU32(pos + 4),
100
- name: deserializeStr(pos + 8),
101
100
  decorators: [],
101
+ name: deserializeStr(pos + 8),
102
102
  optional: false,
103
103
  typeAnnotation: null,
104
104
  };
@@ -109,8 +109,8 @@ function deserializeLabelIdentifier(pos) {
109
109
  type: 'Identifier',
110
110
  start: deserializeU32(pos),
111
111
  end: deserializeU32(pos + 4),
112
- name: deserializeStr(pos + 8),
113
112
  decorators: [],
113
+ name: deserializeStr(pos + 8),
114
114
  optional: false,
115
115
  typeAnnotation: null,
116
116
  };
@@ -151,12 +151,12 @@ function deserializeObjectProperty(pos) {
151
151
  type: 'Property',
152
152
  start: deserializeU32(pos),
153
153
  end: deserializeU32(pos + 4),
154
+ kind: deserializePropertyKind(pos + 40),
155
+ key: deserializePropertyKey(pos + 8),
156
+ value: deserializeExpression(pos + 24),
154
157
  method: deserializeBool(pos + 41),
155
158
  shorthand: deserializeBool(pos + 42),
156
159
  computed: deserializeBool(pos + 43),
157
- key: deserializePropertyKey(pos + 8),
158
- value: deserializeExpression(pos + 24),
159
- kind: deserializePropertyKind(pos + 40),
160
160
  optional: false,
161
161
  };
162
162
  }
@@ -166,8 +166,8 @@ function deserializeTemplateLiteral(pos) {
166
166
  type: 'TemplateLiteral',
167
167
  start: deserializeU32(pos),
168
168
  end: deserializeU32(pos + 4),
169
- expressions: deserializeVecExpression(pos + 32),
170
169
  quasis: deserializeVecTemplateElement(pos + 8),
170
+ expressions: deserializeVecExpression(pos + 32),
171
171
  };
172
172
  }
173
173
 
@@ -177,8 +177,8 @@ function deserializeTaggedTemplateExpression(pos) {
177
177
  start: deserializeU32(pos),
178
178
  end: deserializeU32(pos + 4),
179
179
  tag: deserializeExpression(pos + 8),
180
- quasi: deserializeTemplateLiteral(pos + 32),
181
180
  typeArguments: deserializeOptionBoxTSTypeParameterInstantiation(pos + 24),
181
+ quasi: deserializeTemplateLiteral(pos + 32),
182
182
  };
183
183
  }
184
184
 
@@ -208,8 +208,8 @@ function deserializeComputedMemberExpression(pos) {
208
208
  end: deserializeU32(pos + 4),
209
209
  object: deserializeExpression(pos + 8),
210
210
  property: deserializeExpression(pos + 24),
211
- computed: true,
212
211
  optional: deserializeBool(pos + 40),
212
+ computed: true,
213
213
  };
214
214
  }
215
215
 
@@ -220,8 +220,8 @@ function deserializeStaticMemberExpression(pos) {
220
220
  end: deserializeU32(pos + 4),
221
221
  object: deserializeExpression(pos + 8),
222
222
  property: deserializeIdentifierName(pos + 24),
223
- computed: false,
224
223
  optional: deserializeBool(pos + 48),
224
+ computed: false,
225
225
  };
226
226
  }
227
227
 
@@ -232,8 +232,8 @@ function deserializePrivateFieldExpression(pos) {
232
232
  end: deserializeU32(pos + 4),
233
233
  object: deserializeExpression(pos + 8),
234
234
  property: deserializePrivateIdentifier(pos + 24),
235
- computed: false,
236
235
  optional: deserializeBool(pos + 48),
236
+ computed: false,
237
237
  };
238
238
  }
239
239
 
@@ -243,9 +243,9 @@ function deserializeCallExpression(pos) {
243
243
  start: deserializeU32(pos),
244
244
  end: deserializeU32(pos + 4),
245
245
  callee: deserializeExpression(pos + 8),
246
+ typeArguments: deserializeOptionBoxTSTypeParameterInstantiation(pos + 24),
246
247
  arguments: deserializeVecArgument(pos + 32),
247
248
  optional: deserializeBool(pos + 56),
248
- typeArguments: deserializeOptionBoxTSTypeParameterInstantiation(pos + 24),
249
249
  };
250
250
  }
251
251
 
@@ -255,8 +255,8 @@ function deserializeNewExpression(pos) {
255
255
  start: deserializeU32(pos),
256
256
  end: deserializeU32(pos + 4),
257
257
  callee: deserializeExpression(pos + 8),
258
- arguments: deserializeVecArgument(pos + 32),
259
258
  typeArguments: deserializeOptionBoxTSTypeParameterInstantiation(pos + 24),
259
+ arguments: deserializeVecArgument(pos + 32),
260
260
  };
261
261
  }
262
262
 
@@ -296,8 +296,8 @@ function deserializeUnaryExpression(pos) {
296
296
  start: deserializeU32(pos),
297
297
  end: deserializeU32(pos + 4),
298
298
  operator: deserializeUnaryOperator(pos + 24),
299
- prefix: true,
300
299
  argument: deserializeExpression(pos + 8),
300
+ prefix: true,
301
301
  };
302
302
  }
303
303
 
@@ -364,8 +364,8 @@ function deserializeArrayAssignmentTarget(pos) {
364
364
  type: 'ArrayPattern',
365
365
  start: deserializeU32(pos),
366
366
  end: deserializeU32(pos + 4),
367
- elements,
368
367
  decorators: [],
368
+ elements,
369
369
  optional: false,
370
370
  typeAnnotation: null,
371
371
  };
@@ -379,8 +379,8 @@ function deserializeObjectAssignmentTarget(pos) {
379
379
  type: 'ObjectPattern',
380
380
  start: deserializeU32(pos),
381
381
  end: deserializeU32(pos + 4),
382
- properties,
383
382
  decorators: [],
383
+ properties,
384
384
  optional: false,
385
385
  typeAnnotation: null,
386
386
  };
@@ -391,8 +391,8 @@ function deserializeAssignmentTargetRest(pos) {
391
391
  type: 'RestElement',
392
392
  start: deserializeU32(pos),
393
393
  end: deserializeU32(pos + 4),
394
- argument: deserializeAssignmentTarget(pos + 8),
395
394
  decorators: [],
395
+ argument: deserializeAssignmentTarget(pos + 8),
396
396
  optional: false,
397
397
  typeAnnotation: null,
398
398
  value: null,
@@ -404,9 +404,9 @@ function deserializeAssignmentTargetWithDefault(pos) {
404
404
  type: 'AssignmentPattern',
405
405
  start: deserializeU32(pos),
406
406
  end: deserializeU32(pos + 4),
407
+ decorators: [],
407
408
  left: deserializeAssignmentTarget(pos + 8),
408
409
  right: deserializeExpression(pos + 24),
409
- decorators: [],
410
410
  optional: false,
411
411
  typeAnnotation: null,
412
412
  };
@@ -434,12 +434,12 @@ function deserializeAssignmentTargetPropertyIdentifier(pos) {
434
434
  type: 'Property',
435
435
  start,
436
436
  end,
437
+ kind: 'init',
438
+ key,
439
+ value,
437
440
  method: false,
438
441
  shorthand: true,
439
442
  computed: false,
440
- key,
441
- value,
442
- kind: 'init',
443
443
  optional: false,
444
444
  };
445
445
  }
@@ -449,12 +449,12 @@ function deserializeAssignmentTargetPropertyProperty(pos) {
449
449
  type: 'Property',
450
450
  start: deserializeU32(pos),
451
451
  end: deserializeU32(pos + 4),
452
+ kind: 'init',
453
+ key: deserializePropertyKey(pos + 8),
454
+ value: deserializeAssignmentTargetMaybeDefault(pos + 24),
452
455
  method: false,
453
456
  shorthand: false,
454
457
  computed: deserializeBool(pos + 40),
455
- key: deserializePropertyKey(pos + 8),
456
- value: deserializeAssignmentTargetMaybeDefault(pos + 24),
457
- kind: 'init',
458
458
  optional: false,
459
459
  };
460
460
  }
@@ -536,8 +536,8 @@ function deserializeVariableDeclaration(pos) {
536
536
  type: 'VariableDeclaration',
537
537
  start: deserializeU32(pos),
538
538
  end: deserializeU32(pos + 4),
539
- declarations: deserializeVecVariableDeclarator(pos + 8),
540
539
  kind: deserializeVariableDeclarationKind(pos + 32),
540
+ declarations: deserializeVecVariableDeclarator(pos + 8),
541
541
  declare: deserializeBool(pos + 33),
542
542
  };
543
543
  }
@@ -689,8 +689,8 @@ function deserializeSwitchCase(pos) {
689
689
  type: 'SwitchCase',
690
690
  start: deserializeU32(pos),
691
691
  end: deserializeU32(pos + 4),
692
- consequent: deserializeVecStatement(pos + 24),
693
692
  test: deserializeOptionExpression(pos + 8),
693
+ consequent: deserializeVecStatement(pos + 24),
694
694
  };
695
695
  }
696
696
 
@@ -699,8 +699,8 @@ function deserializeLabeledStatement(pos) {
699
699
  type: 'LabeledStatement',
700
700
  start: deserializeU32(pos),
701
701
  end: deserializeU32(pos + 4),
702
- body: deserializeStatement(pos + 32),
703
702
  label: deserializeLabelIdentifier(pos + 8),
703
+ body: deserializeStatement(pos + 32),
704
704
  };
705
705
  }
706
706
 
@@ -763,9 +763,9 @@ function deserializeAssignmentPattern(pos) {
763
763
  type: 'AssignmentPattern',
764
764
  start: deserializeU32(pos),
765
765
  end: deserializeU32(pos + 4),
766
+ decorators: [],
766
767
  left: deserializeBindingPattern(pos + 8),
767
768
  right: deserializeExpression(pos + 40),
768
- decorators: [],
769
769
  optional: false,
770
770
  typeAnnotation: null,
771
771
  };
@@ -779,8 +779,8 @@ function deserializeObjectPattern(pos) {
779
779
  type: 'ObjectPattern',
780
780
  start: deserializeU32(pos),
781
781
  end: deserializeU32(pos + 4),
782
- properties,
783
782
  decorators: [],
783
+ properties,
784
784
  optional: false,
785
785
  typeAnnotation: null,
786
786
  };
@@ -791,12 +791,12 @@ function deserializeBindingProperty(pos) {
791
791
  type: 'Property',
792
792
  start: deserializeU32(pos),
793
793
  end: deserializeU32(pos + 4),
794
+ kind: 'init',
795
+ key: deserializePropertyKey(pos + 8),
796
+ value: deserializeBindingPattern(pos + 24),
794
797
  method: false,
795
798
  shorthand: deserializeBool(pos + 56),
796
799
  computed: deserializeBool(pos + 57),
797
- key: deserializePropertyKey(pos + 8),
798
- value: deserializeBindingPattern(pos + 24),
799
- kind: 'init',
800
800
  optional: false,
801
801
  };
802
802
  }
@@ -809,8 +809,8 @@ function deserializeArrayPattern(pos) {
809
809
  type: 'ArrayPattern',
810
810
  start: deserializeU32(pos),
811
811
  end: deserializeU32(pos + 4),
812
- elements,
813
812
  decorators: [],
813
+ elements,
814
814
  optional: false,
815
815
  typeAnnotation: null,
816
816
  };
@@ -821,8 +821,8 @@ function deserializeBindingRestElement(pos) {
821
821
  type: 'RestElement',
822
822
  start: deserializeU32(pos),
823
823
  end: deserializeU32(pos + 4),
824
- argument: deserializeBindingPattern(pos + 8),
825
824
  decorators: [],
825
+ argument: deserializeBindingPattern(pos + 8),
826
826
  optional: false,
827
827
  typeAnnotation: null,
828
828
  value: null,
@@ -838,14 +838,14 @@ function deserializeFunction(pos) {
838
838
  start: deserializeU32(pos),
839
839
  end: deserializeU32(pos + 4),
840
840
  id: deserializeOptionBindingIdentifier(pos + 8),
841
- expression: false,
842
841
  generator: deserializeBool(pos + 85),
843
842
  async: deserializeBool(pos + 86),
844
- params,
845
- body: deserializeOptionBoxFunctionBody(pos + 72),
846
843
  declare: deserializeBool(pos + 87),
847
844
  typeParameters: deserializeOptionBoxTSTypeParameterDeclaration(pos + 40),
845
+ params,
848
846
  returnType: deserializeOptionBoxTSTypeAnnotation(pos + 64),
847
+ body: deserializeOptionBoxFunctionBody(pos + 72),
848
+ expression: false,
849
849
  };
850
850
  }
851
851
 
@@ -915,14 +915,14 @@ function deserializeArrowFunctionExpression(pos) {
915
915
  type: 'ArrowFunctionExpression',
916
916
  start: deserializeU32(pos),
917
917
  end: deserializeU32(pos + 4),
918
- id: null,
919
918
  expression,
920
- generator: false,
921
919
  async: deserializeBool(pos + 45),
922
- params: deserializeBoxFormalParameters(pos + 16),
923
- body: expression ? body.body[0].expression : body,
924
920
  typeParameters: deserializeOptionBoxTSTypeParameterDeclaration(pos + 8),
921
+ params: deserializeBoxFormalParameters(pos + 16),
925
922
  returnType: deserializeOptionBoxTSTypeAnnotation(pos + 24),
923
+ body: expression ? body.body[0].expression : body,
924
+ id: null,
925
+ generator: false,
926
926
  };
927
927
  }
928
928
 
@@ -941,13 +941,13 @@ function deserializeClass(pos) {
941
941
  type: deserializeClassType(pos + 132),
942
942
  start: deserializeU32(pos),
943
943
  end: deserializeU32(pos + 4),
944
- id: deserializeOptionBindingIdentifier(pos + 32),
945
- superClass: deserializeOptionExpression(pos + 72),
946
- body: deserializeBoxClassBody(pos + 120),
947
944
  decorators: deserializeVecDecorator(pos + 8),
945
+ id: deserializeOptionBindingIdentifier(pos + 32),
948
946
  typeParameters: deserializeOptionBoxTSTypeParameterDeclaration(pos + 64),
947
+ superClass: deserializeOptionExpression(pos + 72),
949
948
  superTypeArguments: deserializeOptionBoxTSTypeParameterInstantiation(pos + 88),
950
949
  implements: deserializeVecTSClassImplements(pos + 96),
950
+ body: deserializeBoxClassBody(pos + 120),
951
951
  abstract: deserializeBool(pos + 133),
952
952
  declare: deserializeBool(pos + 134),
953
953
  };
@@ -980,12 +980,12 @@ function deserializeMethodDefinition(pos) {
980
980
  type: deserializeMethodDefinitionType(pos + 56),
981
981
  start: deserializeU32(pos),
982
982
  end: deserializeU32(pos + 4),
983
- static: deserializeBool(pos + 59),
984
- computed: deserializeBool(pos + 58),
983
+ decorators: deserializeVecDecorator(pos + 8),
985
984
  key,
986
- kind,
987
985
  value: deserializeBoxFunction(pos + 48),
988
- decorators: deserializeVecDecorator(pos + 8),
986
+ kind,
987
+ computed: deserializeBool(pos + 58),
988
+ static: deserializeBool(pos + 59),
989
989
  override: deserializeBool(pos + 60),
990
990
  optional: deserializeBool(pos + 61),
991
991
  accessibility: deserializeOptionTSAccessibility(pos + 62),
@@ -997,17 +997,17 @@ function deserializePropertyDefinition(pos) {
997
997
  type: deserializePropertyDefinitionType(pos + 72),
998
998
  start: deserializeU32(pos),
999
999
  end: deserializeU32(pos + 4),
1000
- static: deserializeBool(pos + 74),
1001
- computed: deserializeBool(pos + 73),
1000
+ decorators: deserializeVecDecorator(pos + 8),
1002
1001
  key: deserializePropertyKey(pos + 32),
1002
+ typeAnnotation: deserializeOptionBoxTSTypeAnnotation(pos + 48),
1003
1003
  value: deserializeOptionExpression(pos + 56),
1004
- decorators: deserializeVecDecorator(pos + 8),
1004
+ computed: deserializeBool(pos + 73),
1005
+ static: deserializeBool(pos + 74),
1005
1006
  declare: deserializeBool(pos + 75),
1006
1007
  override: deserializeBool(pos + 76),
1007
1008
  optional: deserializeBool(pos + 77),
1008
1009
  definite: deserializeBool(pos + 78),
1009
1010
  readonly: deserializeBool(pos + 79),
1010
- typeAnnotation: deserializeOptionBoxTSTypeAnnotation(pos + 48),
1011
1011
  accessibility: deserializeOptionTSAccessibility(pos + 80),
1012
1012
  };
1013
1013
  }
@@ -1035,18 +1035,18 @@ function deserializeAccessorProperty(pos) {
1035
1035
  type: deserializeAccessorPropertyType(pos + 72),
1036
1036
  start: deserializeU32(pos),
1037
1037
  end: deserializeU32(pos + 4),
1038
+ decorators: deserializeVecDecorator(pos + 8),
1038
1039
  key: deserializePropertyKey(pos + 32),
1039
1040
  typeAnnotation: deserializeOptionBoxTSTypeAnnotation(pos + 48),
1040
1041
  value: deserializeOptionExpression(pos + 56),
1041
1042
  computed: deserializeBool(pos + 73),
1042
1043
  static: deserializeBool(pos + 74),
1043
- decorators: deserializeVecDecorator(pos + 8),
1044
+ override: deserializeBool(pos + 75),
1044
1045
  definite: deserializeBool(pos + 76),
1045
1046
  accessibility: deserializeOptionTSAccessibility(pos + 77),
1047
+ declare: false,
1046
1048
  optional: false,
1047
- override: deserializeBool(pos + 75),
1048
1049
  readonly: false,
1049
- declare: false,
1050
1050
  };
1051
1051
  }
1052
1052
 
@@ -1071,8 +1071,8 @@ function deserializeImportDeclaration(pos) {
1071
1071
  end: deserializeU32(pos + 4),
1072
1072
  specifiers,
1073
1073
  source: deserializeStringLiteral(pos + 32),
1074
- attributes: withClause === null ? [] : withClause.attributes,
1075
1074
  phase: deserializeOptionImportPhase(pos + 88),
1075
+ attributes: withClause === null ? [] : withClause.attributes,
1076
1076
  importKind: deserializeImportOrExportKind(pos + 89),
1077
1077
  };
1078
1078
  }
@@ -1131,8 +1131,8 @@ function deserializeExportNamedDeclaration(pos) {
1131
1131
  declaration: deserializeOptionDeclaration(pos + 8),
1132
1132
  specifiers: deserializeVecExportSpecifier(pos + 24),
1133
1133
  source: deserializeOptionStringLiteral(pos + 48),
1134
- attributes: withClause === null ? [] : withClause.attributes,
1135
1134
  exportKind: deserializeImportOrExportKind(pos + 104),
1135
+ attributes: withClause === null ? [] : withClause.attributes,
1136
1136
  };
1137
1137
  }
1138
1138
 
@@ -1295,8 +1295,8 @@ function deserializeJSXElement(pos) {
1295
1295
  start: deserializeU32(pos),
1296
1296
  end: deserializeU32(pos + 4),
1297
1297
  openingElement,
1298
- closingElement,
1299
1298
  children: deserializeVecJSXChild(pos + 16),
1299
+ closingElement,
1300
1300
  };
1301
1301
  }
1302
1302
 
@@ -1305,10 +1305,10 @@ function deserializeJSXOpeningElement(pos) {
1305
1305
  type: 'JSXOpeningElement',
1306
1306
  start: deserializeU32(pos),
1307
1307
  end: deserializeU32(pos + 4),
1308
- attributes: deserializeVecJSXAttributeItem(pos + 32),
1309
1308
  name: deserializeJSXElementName(pos + 8),
1310
- selfClosing: false,
1311
1309
  typeArguments: deserializeOptionBoxTSTypeParameterInstantiation(pos + 24),
1310
+ attributes: deserializeVecJSXAttributeItem(pos + 32),
1311
+ selfClosing: false,
1312
1312
  };
1313
1313
  }
1314
1314
 
@@ -1327,8 +1327,8 @@ function deserializeJSXFragment(pos) {
1327
1327
  start: deserializeU32(pos),
1328
1328
  end: deserializeU32(pos + 4),
1329
1329
  openingFragment: deserializeJSXOpeningFragment(pos + 8),
1330
- closingFragment: deserializeJSXClosingFragment(pos + 40),
1331
1330
  children: deserializeVecJSXChild(pos + 16),
1331
+ closingFragment: deserializeJSXClosingFragment(pos + 40),
1332
1332
  };
1333
1333
  }
1334
1334
 
@@ -1437,8 +1437,8 @@ function deserializeTSThisParameter(pos) {
1437
1437
  type: 'Identifier',
1438
1438
  start: deserializeU32(pos),
1439
1439
  end: deserializeU32(pos + 4),
1440
- name: 'this',
1441
1440
  decorators: [],
1441
+ name: 'this',
1442
1442
  optional: false,
1443
1443
  typeAnnotation: deserializeOptionBoxTSTypeAnnotation(pos + 16),
1444
1444
  };
@@ -1471,8 +1471,8 @@ function deserializeTSEnumMember(pos) {
1471
1471
  start: deserializeU32(pos),
1472
1472
  end: deserializeU32(pos + 4),
1473
1473
  id: deserializeTSEnumMemberName(pos + 8),
1474
- computed: deserializeU8(pos + 8) > 1,
1475
1474
  initializer: deserializeOptionExpression(pos + 24),
1475
+ computed: deserializeU8(pos + 8) > 1,
1476
1476
  };
1477
1477
  }
1478
1478
 
@@ -1912,8 +1912,8 @@ function deserializeTSIndexSignatureName(pos) {
1912
1912
  type: 'Identifier',
1913
1913
  start: deserializeU32(pos),
1914
1914
  end: deserializeU32(pos + 4),
1915
- name: deserializeStr(pos + 8),
1916
1915
  decorators: [],
1916
+ name: deserializeStr(pos + 8),
1917
1917
  optional: false,
1918
1918
  typeAnnotation: deserializeBoxTSTypeAnnotation(pos + 24),
1919
1919
  };
@@ -2065,19 +2065,19 @@ function deserializeTSConstructorType(pos) {
2065
2065
  }
2066
2066
 
2067
2067
  function deserializeTSMappedType(pos) {
2068
+ const typeParameter = deserializeBoxTSTypeParameter(pos + 8);
2068
2069
  let optional = deserializeOptionTSMappedTypeModifierOperator(pos + 52);
2069
2070
  if (optional === null) optional = false;
2070
- const typeParameter = deserializeBoxTSTypeParameter(pos + 8);
2071
2071
  return {
2072
2072
  type: 'TSMappedType',
2073
2073
  start: deserializeU32(pos),
2074
2074
  end: deserializeU32(pos + 4),
2075
+ key: typeParameter.name,
2076
+ constraint: typeParameter.constraint,
2075
2077
  nameType: deserializeOptionTSType(pos + 16),
2076
2078
  typeAnnotation: deserializeOptionTSType(pos + 32),
2077
2079
  optional,
2078
2080
  readonly: deserializeOptionTSMappedTypeModifierOperator(pos + 53),
2079
- key: typeParameter.name,
2080
- constraint: typeParameter.constraint,
2081
2081
  };
2082
2082
  }
2083
2083
 
package/index.d.ts CHANGED
@@ -139,6 +139,38 @@ export interface OxcError {
139
139
  */
140
140
  export declare function parseAsync(filename: string, sourceText: string, options?: ParserOptions | undefined | null): Promise<ParseResult>
141
141
 
142
+ /**
143
+ * Parse AST into provided `Uint8Array` buffer, asynchronously.
144
+ *
145
+ * Note: This function can be slower than `parseSyncRaw` due to the overhead of spawning a thread.
146
+ *
147
+ * Source text must be written into the start of the buffer, and its length (in UTF-8 bytes)
148
+ * provided as `source_len`.
149
+ *
150
+ * This function will parse the source, and write the AST into the buffer, starting at the end.
151
+ *
152
+ * It also writes to the very end of the buffer the offset of `Program` within the buffer.
153
+ *
154
+ * Caller can deserialize data from the buffer on JS side.
155
+ *
156
+ * # SAFETY
157
+ *
158
+ * Caller must ensure:
159
+ * * Source text is written into start of the buffer.
160
+ * * Source text's UTF-8 byte length is `source_len`.
161
+ * * The 1st `source_len` bytes of the buffer comprises a valid UTF-8 string.
162
+ * * Contents of buffer must not be mutated by caller until the `AsyncTask` returned by this
163
+ * function resolves.
164
+ *
165
+ * If source text is originally a JS string on JS side, and converted to a buffer with
166
+ * `Buffer.from(str)` or `new TextEncoder().encode(str)`, this guarantees it's valid UTF-8.
167
+ *
168
+ * # Panics
169
+ *
170
+ * Panics if source text is too long, or AST takes more memory than is available in the buffer.
171
+ */
172
+ export declare function parseAsyncRaw(filename: string, buffer: Uint8Array, sourceLen: number, options?: ParserOptions | undefined | null): Promise<unknown>
173
+
142
174
  export interface ParserOptions {
143
175
  /** Treat the source text as `js`, `jsx`, `ts`, or `tsx`. */
144
176
  lang?: 'js' | 'jsx' | 'ts' | 'tsx'
@@ -176,7 +208,7 @@ export interface ParserOptions {
176
208
  export declare function parseSync(filename: string, sourceText: string, options?: ParserOptions | undefined | null): ParseResult
177
209
 
178
210
  /**
179
- * Parses AST into provided `Uint8Array` buffer.
211
+ * Parse AST into provided `Uint8Array` buffer, synchronously.
180
212
  *
181
213
  * Source text must be written into the start of the buffer, and its length (in UTF-8 bytes)
182
214
  * provided as `source_len`.
package/index.js CHANGED
@@ -1,3 +1,4 @@
1
+ const { availableParallelism } = require('node:os');
1
2
  const bindings = require('./bindings.js');
2
3
  const { wrap } = require('./wrap.cjs');
3
4
 
@@ -9,20 +10,137 @@ module.exports.ImportNameKind = bindings.ImportNameKind;
9
10
  module.exports.parseWithoutReturn = bindings.parseWithoutReturn;
10
11
  module.exports.Severity = bindings.Severity;
11
12
 
12
- module.exports.parseAsync = async function parseAsync(...args) {
13
- return wrap(await bindings.parseAsync(...args));
13
+ module.exports.parseAsync = async function parseAsync(filename, sourceText, options) {
14
+ if (options?.experimentalRawTransfer) return await parseAsyncRaw(filename, sourceText, options);
15
+ return wrap(await bindings.parseAsync(filename, sourceText, options));
14
16
  };
15
17
 
16
18
  module.exports.parseSync = function parseSync(filename, sourceText, options) {
17
- if (options?.experimentalRawTransfer) {
18
- return parseSyncRaw(filename, sourceText, options);
19
- }
19
+ if (options?.experimentalRawTransfer) return parseSyncRaw(filename, sourceText, options);
20
20
  return wrap(bindings.parseSync(filename, sourceText, options));
21
21
  };
22
22
 
23
- let buffer, encoder, deserializeJS, deserializeTS;
24
-
25
23
  function parseSyncRaw(filename, sourceText, options) {
24
+ const { buffer, sourceByteLen, options: optionsAmended } = prepareRaw(sourceText, options);
25
+ bindings.parseSyncRaw(filename, buffer, sourceByteLen, optionsAmended);
26
+ return deserialize(buffer, sourceText, sourceByteLen);
27
+ }
28
+
29
+ // User should not schedule more async tasks than there are available CPUs, as it hurts performance,
30
+ // but it's a common mistake in async JS code to do exactly that.
31
+ //
32
+ // That anti-pattern looks like this when applied to Oxc:
33
+ //
34
+ // ```js
35
+ // const asts = await Promise.all(
36
+ // files.map(
37
+ // async (filename) => {
38
+ // const sourceText = await fs.readFile(filename, 'utf8');
39
+ // const ast = await oxc.parseAsync(filename, sourceText);
40
+ // return ast;
41
+ // }
42
+ // )
43
+ // );
44
+ // ```
45
+ //
46
+ // In most cases, that'd just result in a bit of degraded performance, and higher memory use because
47
+ // of loading sources into memory prematurely.
48
+ //
49
+ // However, raw transfer uses a 6 GiB buffer for each parsing operation.
50
+ // Most of the memory pages in those buffers are never touched, so this does not consume a huge amount
51
+ // of physical memory, but it does still consume virtual memory.
52
+ //
53
+ // If we allowed creating a large number of 6 GiB buffers simultaneously, it would quickly consume
54
+ // virtual memory space and risk memory exhaustion. The code above would exhaust all of bottom half
55
+ // (heap) of 48-bit virtual memory space if `files.length >= 21_845`. This is not a number which
56
+ // is unrealistic in real world code.
57
+ //
58
+ // To guard against this possibility, we implement a simple queue.
59
+ // No more than `os.availableParallelism()` files can be parsed simultaneously, and any further calls to
60
+ // `parseAsyncRaw` will be put in a queue, to execute once other tasks complete.
61
+ let availableCores = availableParallelism();
62
+ const queue = [];
63
+
64
+ async function parseAsyncRaw(filename, sourceText, options) {
65
+ // Wait for a free CPU core if all CPUs are currently busy.
66
+ //
67
+ // Note: `availableCores` is NOT decremented if have to wait in the queue first,
68
+ // and NOT incremented when parsing completes and it runs next task in the queue.
69
+ //
70
+ // This is to avoid a race condition if `parseAsyncRaw` is called during the microtick in between
71
+ // `resolve` being called below, and the promise resolving here. In that case the new task could
72
+ // start running, and then the promise resolves, and the queued task also starts running.
73
+ // We'd then have `availableParallelism() + 1` tasks running simultaneously. Potentially, this could
74
+ // happen repeatedly, with the number of tasks running simultaneously ever-increasing.
75
+ if (availableCores === 0) {
76
+ // All CPU cores are busy. Put this task in queue and wait for capacity to become available.
77
+ await new Promise((resolve, _) => {
78
+ queue.push(resolve);
79
+ });
80
+ } else {
81
+ // A CPU core is available. Mark core as busy, and run parsing now.
82
+ availableCores--;
83
+ }
84
+
85
+ // Parse
86
+ const { buffer, sourceByteLen, options: optionsAmended } = prepareRaw(sourceText, options);
87
+ await bindings.parseAsyncRaw(filename, buffer, sourceByteLen, optionsAmended);
88
+ const ret = deserialize(buffer, sourceText, sourceByteLen);
89
+
90
+ // Free the CPU core
91
+ if (queue.length > 0) {
92
+ // Some further tasks waiting in queue. Run the next one.
93
+ // Do not increment `availableCores` (see above).
94
+ const resolve = queue.shift();
95
+ resolve();
96
+ } else {
97
+ // No tasks waiting in queue. This CPU is now free.
98
+ availableCores++;
99
+ }
100
+
101
+ return ret;
102
+ }
103
+
104
+ const ONE_GIB = 1 << 30,
105
+ TWO_GIB = ONE_GIB * 2,
106
+ SIX_GIB = ONE_GIB * 6;
107
+
108
+ // We keep a cache of buffers for raw transfer, so we can reuse them as much as possible.
109
+ //
110
+ // When processing multiple files, it's ideal if can reuse an existing buffer, as it's more likely to
111
+ // be warm in CPU cache, it avoids allocations, and it saves work for the garbage collector.
112
+ //
113
+ // However, we also don't want to keep a load of large buffers around indefinitely using up memory,
114
+ // if they're not going to be used again.
115
+ //
116
+ // We have no knowledge of what pattern over time user may process files in (could be lots in quick
117
+ // succession, or more occasionally in a long-running process). So we try to use flexible caching
118
+ // strategy which is adaptable to many usage patterns.
119
+ //
120
+ // We use a 2-tier cache.
121
+ // Tier 1 uses strong references, tier 2 uses weak references.
122
+ //
123
+ // When parsing is complete and the buffer is no longer in use, push it to `buffers` (tier 1 cache).
124
+ // Set a timer to clear the cache when no activity for 10 seconds.
125
+ //
126
+ // When the timer expires, move all the buffers from tier 1 cache into `oldBuffers` (tier 2).
127
+ // They are stored there as `WeakRef`s, so the garbage collector is free to reclaim them.
128
+ //
129
+ // On the next call to `parseSync` or `parseAsync`, promote any buffers in tier 2 cache which were not
130
+ // already garbage collected back into tier 1 cache. This is on assumption that parsing one file
131
+ // indicates parsing as a whole is an ongoing process, and there will likely be further calls to
132
+ // `parseSync` / `parseAsync` in future.
133
+ //
134
+ // The weak tier 2 cache is because V8 does not necessarily free memory as soon as it's able to be
135
+ // freed. We don't want to block it from freeing memory, but if it's not done that yet, there's no
136
+ // point creating a new buffer, when one already exists.
137
+ const CLEAR_BUFFERS_TIMEOUT = 10_000; // 10 seconds
138
+ const buffers = [], oldBuffers = [];
139
+
140
+ let encoder = null, deserializeJS = null, deserializeTS = null, clearBuffersTimeout = null;
141
+
142
+ // Get a buffer (from cache if possible), copy source text into it, and amend options object
143
+ function prepareRaw(sourceText, options) {
26
144
  if (!rawTransferSupported()) {
27
145
  throw new Error(
28
146
  '`experimentalRawTransfer` option is not supported on 32-bit or big-endian systems, ' +
@@ -31,39 +149,52 @@ function parseSyncRaw(filename, sourceText, options) {
31
149
  }
32
150
 
33
151
  // Delete `experimentalRawTransfer` option
34
- let experimentalRawTransfer;
35
- ({ experimentalRawTransfer, ...options } = options);
152
+ let _;
153
+ ({ experimentalRawTransfer: _, ...options } = options);
36
154
 
37
- // Create buffer and `TextEncoder`
38
- if (!buffer) {
39
- buffer = createBuffer();
40
- encoder = new TextEncoder();
155
+ // Cancel timeout for clearing buffers
156
+ if (clearBuffersTimeout !== null) {
157
+ clearTimeout(clearBuffersTimeout);
158
+ clearBuffersTimeout = null;
41
159
  }
42
160
 
161
+ // Revive any discarded buffers which have not yet been garbage collected
162
+ if (oldBuffers.length > 0) {
163
+ const revivedBuffers = [];
164
+ for (let oldBuffer of oldBuffers) {
165
+ oldBuffer = oldBuffer.deref();
166
+ if (oldBuffer !== undefined) revivedBuffers.push(oldBuffer);
167
+ }
168
+ oldBuffers.length = 0;
169
+ if (revivedBuffers.length > 0) buffers.unshift(...revivedBuffers);
170
+ }
171
+
172
+ // Reuse existing buffer, or create a new one
173
+ const buffer = buffers.length > 0 ? buffers.pop() : createBuffer();
174
+
175
+ // Get/create `TextEncoder`
176
+ if (encoder === null) encoder = new TextEncoder();
177
+
43
178
  // Write source into start of buffer.
44
179
  // `TextEncoder` cannot write into a `Uint8Array` larger than 1 GiB,
45
180
  // so create a view into buffer of this size to write into.
46
181
  const sourceBuffer = new Uint8Array(buffer.buffer, buffer.byteOffset, ONE_GIB);
47
182
  const { read, written: sourceByteLen } = encoder.encodeInto(sourceText, sourceBuffer);
48
- if (read !== sourceText.length) {
49
- throw new Error('Failed to write source text into buffer');
50
- }
51
-
52
- // Parse
53
- bindings.parseSyncRaw(filename, buffer, sourceByteLen, options);
183
+ if (read !== sourceText.length) throw new Error('Failed to write source text into buffer');
54
184
 
55
- // Deserialize.
56
- // We cannot lazily deserialize in the getters, because the buffer might be re-used to parse
57
- // another file before the getter is called.
185
+ return { buffer, sourceByteLen, options };
186
+ }
58
187
 
59
- // (2 * 1024 * 1024 * 1024 - 12)
60
- const astTypeFlagPos = 2147483636;
61
- let isJsAst = buffer[astTypeFlagPos] === 0;
188
+ // Deserialize AST from buffer
189
+ function deserialize(buffer, sourceText, sourceByteLen) {
190
+ // 2147483636 = (2 * 1024 * 1024 * 1024) - 12
191
+ // i.e. 12 bytes from end of 2 GiB buffer
192
+ const isJsAst = buffer[2147483636] === 0;
62
193
 
63
194
  // Lazy load deserializer, and deserialize buffer to JS objects
64
195
  let data;
65
196
  if (isJsAst) {
66
- if (!deserializeJS) deserializeJS = require('./generated/deserialize/js.js');
197
+ if (deserializeJS === null) deserializeJS = require('./generated/deserialize/js.js');
67
198
  data = deserializeJS(buffer, sourceText, sourceByteLen);
68
199
 
69
200
  // Add a line comment for hashbang
@@ -72,12 +203,22 @@ function parseSyncRaw(filename, sourceText, options) {
72
203
  data.comments.unshift({ type: 'Line', value: hashbang.value, start: hashbang.start, end: hashbang.end });
73
204
  }
74
205
  } else {
75
- if (!deserializeTS) deserializeTS = require('./generated/deserialize/ts.js');
206
+ if (deserializeTS === null) deserializeTS = require('./generated/deserialize/ts.js');
76
207
  data = deserializeTS(buffer, sourceText, sourceByteLen);
77
208
  // Note: Do not add line comment for hashbang, to match `@typescript-eslint/parser`.
78
209
  // See https://github.com/oxc-project/oxc/blob/ea784f5f082e4c53c98afde9bf983afd0b95e44e/napi/parser/src/lib.rs#L106-L130
79
210
  }
80
211
 
212
+ // Return buffer to cache, to be reused
213
+ buffers.push(buffer);
214
+
215
+ // Set timer to clear buffers
216
+ if (clearBuffersTimeout !== null) clearTimeout(clearBuffersTimeout);
217
+ clearBuffersTimeout = setTimeout(clearBuffersCache, CLEAR_BUFFERS_TIMEOUT);
218
+ clearBuffersTimeout.unref();
219
+
220
+ // We cannot lazily deserialize in the getters, because the buffer might be re-used to parse
221
+ // another file before the getter is called.
81
222
  return {
82
223
  get program() {
83
224
  return data.program;
@@ -94,9 +235,16 @@ function parseSyncRaw(filename, sourceText, options) {
94
235
  };
95
236
  }
96
237
 
97
- const ONE_GIB = 1 << 30,
98
- TWO_GIB = ONE_GIB * 2,
99
- SIX_GIB = ONE_GIB * 6;
238
+ // Downgrade buffers in tier 1 cache (`buffers`) to tier 2 (`oldBuffers`),
239
+ // so they can be garbage collected
240
+ function clearBuffersCache() {
241
+ clearBuffersTimeout = null;
242
+
243
+ for (const buffer of buffers) {
244
+ oldBuffers.push(new WeakRef(buffer));
245
+ }
246
+ buffers.length = 0;
247
+ }
100
248
 
101
249
  // Create a `Uint8Array` which is 2 GiB in size, with its start aligned on 4 GiB.
102
250
  //
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "oxc-parser",
3
- "version": "0.72.0",
3
+ "version": "0.72.2",
4
4
  "main": "index.js",
5
5
  "browser": "wasm.mjs",
6
6
  "engines": {
@@ -39,15 +39,15 @@
39
39
  "access": "public"
40
40
  },
41
41
  "dependencies": {
42
- "@oxc-project/types": "^0.72.0"
42
+ "@oxc-project/types": "^0.72.2"
43
43
  },
44
44
  "devDependencies": {
45
45
  "@codspeed/vitest-plugin": "^4.0.0",
46
46
  "@napi-rs/wasm-runtime": "^0.2.7",
47
- "@vitest/browser": "3.1.3",
47
+ "@vitest/browser": "3.1.4",
48
48
  "esbuild": "^0.25.0",
49
49
  "playwright": "^1.51.0",
50
- "vitest": "3.1.3",
50
+ "vitest": "3.1.4",
51
51
  "typescript": "5.8.3"
52
52
  },
53
53
  "napi": {
@@ -77,20 +77,20 @@
77
77
  "dtsHeaderFile": "header.js"
78
78
  },
79
79
  "optionalDependencies": {
80
- "@oxc-parser/binding-win32-x64-msvc": "0.72.0",
81
- "@oxc-parser/binding-win32-arm64-msvc": "0.72.0",
82
- "@oxc-parser/binding-linux-x64-gnu": "0.72.0",
83
- "@oxc-parser/binding-linux-x64-musl": "0.72.0",
84
- "@oxc-parser/binding-freebsd-x64": "0.72.0",
85
- "@oxc-parser/binding-linux-arm64-gnu": "0.72.0",
86
- "@oxc-parser/binding-linux-arm64-musl": "0.72.0",
87
- "@oxc-parser/binding-linux-arm-gnueabihf": "0.72.0",
88
- "@oxc-parser/binding-linux-arm-musleabihf": "0.72.0",
89
- "@oxc-parser/binding-linux-s390x-gnu": "0.72.0",
90
- "@oxc-parser/binding-linux-riscv64-gnu": "0.72.0",
91
- "@oxc-parser/binding-darwin-x64": "0.72.0",
92
- "@oxc-parser/binding-darwin-arm64": "0.72.0",
93
- "@oxc-parser/binding-wasm32-wasi": "0.72.0"
80
+ "@oxc-parser/binding-win32-x64-msvc": "0.72.2",
81
+ "@oxc-parser/binding-win32-arm64-msvc": "0.72.2",
82
+ "@oxc-parser/binding-linux-x64-gnu": "0.72.2",
83
+ "@oxc-parser/binding-linux-x64-musl": "0.72.2",
84
+ "@oxc-parser/binding-freebsd-x64": "0.72.2",
85
+ "@oxc-parser/binding-linux-arm64-gnu": "0.72.2",
86
+ "@oxc-parser/binding-linux-arm64-musl": "0.72.2",
87
+ "@oxc-parser/binding-linux-arm-gnueabihf": "0.72.2",
88
+ "@oxc-parser/binding-linux-arm-musleabihf": "0.72.2",
89
+ "@oxc-parser/binding-linux-s390x-gnu": "0.72.2",
90
+ "@oxc-parser/binding-linux-riscv64-gnu": "0.72.2",
91
+ "@oxc-parser/binding-darwin-x64": "0.72.2",
92
+ "@oxc-parser/binding-darwin-arm64": "0.72.2",
93
+ "@oxc-parser/binding-wasm32-wasi": "0.72.2"
94
94
  },
95
95
  "scripts": {
96
96
  "build-dev": "napi build --platform --js bindings.js",