hermes-parser 0.5.0 → 0.8.0

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.
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Copyright (c) Facebook, Inc. and its affiliates.
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
3
  *
4
4
  * This source code is licensed under the MIT license found in the
5
5
  * LICENSE file in the root directory of this source tree.
@@ -21,6 +21,9 @@ import type {HermesNode} from './HermesAST';
21
21
  import type {ParserOptions} from './ParserOptions';
22
22
 
23
23
  import HermesASTAdapter from './HermesASTAdapter';
24
+ import {getModuleDocblock} from './getModuleDocblock';
25
+
26
+ declare var BigInt: ?(value: $FlowFixMe) => mixed;
24
27
 
25
28
  export default class HermesToESTreeAdapter extends HermesASTAdapter {
26
29
  +code: string;
@@ -43,6 +46,9 @@ export default class HermesToESTreeAdapter extends HermesASTAdapter {
43
46
  };
44
47
 
45
48
  node.range = [loc.rangeStart, loc.rangeEnd];
49
+
50
+ delete node.start;
51
+ delete node.end;
46
52
  }
47
53
 
48
54
  mapNode(node: HermesNode): HermesNode {
@@ -55,13 +61,18 @@ export default class HermesToESTreeAdapter extends HermesASTAdapter {
55
61
  case 'BooleanLiteral':
56
62
  case 'StringLiteral':
57
63
  case 'NumericLiteral':
64
+ case 'JSXStringLiteral':
58
65
  return this.mapSimpleLiteral(node);
66
+ case 'BigIntLiteral':
67
+ return this.mapBigIntLiteral(node);
59
68
  case 'RegExpLiteral':
60
69
  return this.mapRegExpLiteral(node);
61
70
  case 'Empty':
62
71
  return this.mapEmpty(node);
63
72
  case 'TemplateElement':
64
73
  return this.mapTemplateElement(node);
74
+ case 'BigIntLiteralTypeAnnotation':
75
+ return this.mapBigIntLiteralTypeAnnotation(node);
65
76
  case 'GenericTypeAnnotation':
66
77
  return this.mapGenericTypeAnnotation(node);
67
78
  case 'ImportDeclaration':
@@ -74,9 +85,22 @@ export default class HermesToESTreeAdapter extends HermesASTAdapter {
74
85
  return this.mapExportNamedDeclaration(node);
75
86
  case 'ExportAllDeclaration':
76
87
  return this.mapExportAllDeclaration(node);
88
+ case 'Property':
89
+ return this.mapProperty(node);
90
+ case 'FunctionDeclaration':
91
+ case 'FunctionExpression':
92
+ case 'ArrowFunctionExpression':
93
+ return this.mapFunction(node);
77
94
  case 'PrivateName':
95
+ return this.mapPrivateName(node);
96
+ case 'ClassProperty':
78
97
  case 'ClassPrivateProperty':
79
- return this.mapPrivateProperty(node);
98
+ return this.mapClassProperty(node);
99
+ case 'MemberExpression':
100
+ case 'OptionalMemberExpression':
101
+ case 'CallExpression':
102
+ case 'OptionalCallExpression':
103
+ return this.mapChainExpression(node);
80
104
  default:
81
105
  return this.mapNodeDefault(node);
82
106
  }
@@ -86,22 +110,65 @@ export default class HermesToESTreeAdapter extends HermesASTAdapter {
86
110
  node = this.mapNodeDefault(node);
87
111
  node.sourceType = this.getSourceType();
88
112
 
113
+ node.docblock = getModuleDocblock(node);
114
+
89
115
  return node;
90
116
  }
91
117
 
92
118
  mapSimpleLiteral(node: HermesNode): HermesNode {
93
- node.type = 'Literal';
94
- node.raw = this.code.slice(node.range[0], node.range[1]);
119
+ return {
120
+ type: 'Literal',
121
+ loc: node.loc,
122
+ range: node.range,
123
+ value: node.value,
124
+ raw: this.code.slice(node.range[0], node.range[1]),
125
+ literalType: (() => {
126
+ switch (node.type) {
127
+ case 'NullLiteral':
128
+ return 'null';
95
129
 
96
- return node;
130
+ case 'BooleanLiteral':
131
+ return 'boolean';
132
+
133
+ case 'StringLiteral':
134
+ case 'JSXStringLiteral':
135
+ return 'string';
136
+
137
+ case 'NumericLiteral':
138
+ return 'numeric';
139
+
140
+ case 'BigIntLiteral':
141
+ return 'bigint';
142
+
143
+ case 'RegExpLiteral':
144
+ return 'regexp';
145
+ }
146
+ return null;
147
+ })(),
148
+ };
97
149
  }
98
150
 
99
- mapNullLiteral(node: HermesNode): HermesNode {
100
- node.type = 'Literal';
101
- node.value = null;
102
- node.raw = this.code.slice(node.range[0], node.range[1]);
151
+ mapBigIntLiteral(node: HermesNode): HermesNode {
152
+ const newNode = this.mapSimpleLiteral(node);
153
+ const bigint = node.bigint
154
+ // estree spec is to not have a trailing `n` on this property
155
+ // https://github.com/estree/estree/blob/db962bb417a97effcfe9892f87fbb93c81a68584/es2020.md#bigintliteral
156
+ .replace(/n$/, '')
157
+ // `BigInt` doesn't accept numeric separator and `bigint` property should not include numeric separator
158
+ .replace(/_/, '');
159
+ return {
160
+ ...newNode,
161
+ // coerce the string to a bigint value if supported by the environment
162
+ value: typeof BigInt === 'function' ? BigInt(bigint) : null,
163
+ bigint,
164
+ };
165
+ }
103
166
 
104
- return node;
167
+ mapNullLiteral(node: HermesNode): HermesNode {
168
+ return {
169
+ ...this.mapSimpleLiteral(node),
170
+ value: null,
171
+ };
105
172
  }
106
173
 
107
174
  mapRegExpLiteral(node: HermesNode): HermesNode {
@@ -116,11 +183,8 @@ export default class HermesToESTreeAdapter extends HermesASTAdapter {
116
183
  }
117
184
 
118
185
  return {
119
- type: 'Literal',
120
- loc: node.loc,
121
- range: node.range,
186
+ ...this.mapSimpleLiteral(node),
122
187
  value,
123
- raw: this.code.slice(node.range[0], node.range[1]),
124
188
  regex: {
125
189
  pattern,
126
190
  flags,
@@ -128,6 +192,11 @@ export default class HermesToESTreeAdapter extends HermesASTAdapter {
128
192
  };
129
193
  }
130
194
 
195
+ mapBigIntLiteralTypeAnnotation(node: HermesNode): HermesNode {
196
+ node.value = null;
197
+ return node;
198
+ }
199
+
131
200
  mapTemplateElement(node: HermesNode): HermesNode {
132
201
  return {
133
202
  type: 'TemplateElement',
@@ -144,7 +213,7 @@ export default class HermesToESTreeAdapter extends HermesASTAdapter {
144
213
  mapGenericTypeAnnotation(node: HermesNode): HermesNode {
145
214
  // Convert simple `this` generic type to ThisTypeAnnotation
146
215
  if (
147
- node.typeParameters === null &&
216
+ node.typeParameters == null &&
148
217
  node.id.type === 'Identifier' &&
149
218
  node.id.name === 'this'
150
219
  ) {
@@ -158,6 +227,17 @@ export default class HermesToESTreeAdapter extends HermesASTAdapter {
158
227
  return this.mapNodeDefault(node);
159
228
  }
160
229
 
230
+ mapProperty(nodeUnprocessed: HermesNode): HermesNode {
231
+ const node = this.mapNodeDefault(nodeUnprocessed);
232
+
233
+ if (node.value.type === 'FunctionExpression') {
234
+ node.value.loc.start = node.key.loc.end;
235
+ node.value.range[0] = node.key.range[1];
236
+ }
237
+
238
+ return node;
239
+ }
240
+
161
241
  mapComment(node: HermesNode): HermesNode {
162
242
  if (node.type === 'CommentBlock') {
163
243
  node.type = 'Block';
@@ -167,4 +247,191 @@ export default class HermesToESTreeAdapter extends HermesASTAdapter {
167
247
 
168
248
  return node;
169
249
  }
250
+
251
+ mapFunction(nodeUnprocessed: HermesNode): HermesNode {
252
+ const node = this.mapNodeDefault(nodeUnprocessed);
253
+
254
+ switch (node.type) {
255
+ case 'FunctionDeclaration':
256
+ case 'FunctionExpression':
257
+ node.expression = false;
258
+ return node;
259
+
260
+ case 'ArrowFunctionExpression':
261
+ node.expression = node.body.type !== 'BlockStatement';
262
+ return node;
263
+ }
264
+
265
+ return node;
266
+ }
267
+
268
+ mapChainExpression(nodeUnprocessed: HermesNode): HermesNode {
269
+ /*
270
+ NOTE - In the below comments `MemberExpression` and `CallExpression`
271
+ are completely interchangable. For terseness we just reference
272
+ one each time.
273
+ */
274
+
275
+ /*
276
+ Hermes uses the old babel-style AST:
277
+ ```
278
+ (one?.two).three?.four;
279
+ ^^^^^^^^^^^^^^^^^^^^^^ OptionalMemberExpression
280
+ ^^^^^^^^^^^^^^^^ MemberExpression
281
+ ^^^^^^^^ OptionalMemberExpression
282
+ ```
283
+
284
+ We need to convert it to the ESTree representation:
285
+ ```
286
+ (one?.two).three?.four;
287
+ ^^^^^^^^^^^^^^^^^^^^^^ ChainExpression
288
+ ^^^^^^^^^^^^^^^^^^^^^^ MemberExpression[optional = true]
289
+ ^^^^^^^^^^^^^^^^ MemberExpression[optional = false]
290
+ ^^^^^^^^ ChainExpression
291
+ ^^^^^^^^ MemberExpression[optional = true]
292
+ ```
293
+
294
+ We do this by converting the AST and its children (depth first), and then unwrapping
295
+ the resulting AST as appropriate.
296
+
297
+ Put another way:
298
+ 1) traverse to the leaf
299
+ 2) if the current node is an `OptionalMemberExpression`:
300
+ a) if the `.object` is a `ChainExpression`:
301
+ i) unwrap the child (`node.object = child.expression`)
302
+ b) convert this node to a `MemberExpression[optional = true]`
303
+ c) wrap this node (`node = ChainExpression[expression = node]`)
304
+ 3) if the current node is a `MembedExpression`:
305
+ a) convert this node to a `MemberExpression[optional = true]`
306
+ */
307
+
308
+ const node = this.mapNodeDefault(nodeUnprocessed);
309
+
310
+ const {child, childKey, isOptional} = ((): {
311
+ child: HermesNode,
312
+ childKey: string,
313
+ isOptional: boolean,
314
+ } => {
315
+ const isOptional: boolean = node.optional === true;
316
+ if (node.type.endsWith('MemberExpression')) {
317
+ return {
318
+ child: node.object,
319
+ childKey: 'object',
320
+ isOptional,
321
+ };
322
+ } else if (node.type.endsWith('CallExpression')) {
323
+ return {
324
+ child: node.callee,
325
+ childKey: 'callee',
326
+ isOptional,
327
+ };
328
+ } else {
329
+ return {
330
+ child: node.expression,
331
+ childKey: 'expression',
332
+ isOptional: false,
333
+ };
334
+ }
335
+ })();
336
+
337
+ const isChildUnwrappable =
338
+ child.type === 'ChainExpression' &&
339
+ // (x?.y).z is semantically different to `x?.y.z`.
340
+ // In the un-parenthesised case `.z` is only executed if and only if `x?.y` returns a non-nullish value.
341
+ // In the parenthesised case, `.z` is **always** executed, regardless of the return of `x?.y`.
342
+ // As such the AST is different between the two cases.
343
+ //
344
+ // In the hermes AST - any member part of a non-short-circuited optional chain is represented with `OptionalMemberExpression`
345
+ // so if we see a `MemberExpression`, then we know we've hit a parenthesis boundary.
346
+ node.type !== 'MemberExpression' &&
347
+ node.type !== 'CallExpression';
348
+
349
+ if (node.type.startsWith('Optional')) {
350
+ node.type = node.type.replace('Optional', '');
351
+ node.optional = isOptional;
352
+ } else {
353
+ node.optional = false;
354
+ }
355
+
356
+ if (!isChildUnwrappable && !isOptional) {
357
+ return node;
358
+ }
359
+
360
+ if (isChildUnwrappable) {
361
+ const newChild = child.expression;
362
+ node[childKey] = newChild;
363
+ }
364
+
365
+ return {
366
+ type: 'ChainExpression',
367
+ expression: node,
368
+ loc: node.loc,
369
+ range: node.range,
370
+ };
371
+ }
372
+
373
+ mapClassProperty(nodeUnprocessed: HermesNode): HermesNode {
374
+ const node = this.mapNodeDefault(nodeUnprocessed);
375
+
376
+ const key = (() => {
377
+ if (node.type === 'ClassPrivateProperty') {
378
+ const key = this.mapNodeDefault(node.key);
379
+ return {
380
+ type: 'PrivateIdentifier',
381
+ name: key.name,
382
+ range: key.range,
383
+ loc: key.loc,
384
+ };
385
+ }
386
+
387
+ return node.key;
388
+ })();
389
+
390
+ return {
391
+ ...node,
392
+ computed: node.type === 'ClassPrivateProperty' ? false : node.computed,
393
+ key,
394
+ type: 'PropertyDefinition',
395
+ };
396
+ }
397
+
398
+ mapPrivateName(node: HermesNode): HermesNode {
399
+ return {
400
+ type: 'PrivateIdentifier',
401
+ name: node.id.name,
402
+ // estree the location refers to the entire string including the hash token
403
+ range: node.range,
404
+ loc: node.loc,
405
+ };
406
+ }
407
+
408
+ mapExportNamedDeclaration(nodeUnprocessed: HermesNode): HermesNode {
409
+ const node = super.mapExportNamedDeclaration(nodeUnprocessed);
410
+
411
+ const namespaceSpecifier = node.specifiers.find(
412
+ spec => spec.type === 'ExportNamespaceSpecifier',
413
+ );
414
+ if (namespaceSpecifier != null) {
415
+ if (node.specifiers.length !== 1) {
416
+ // this should already a hermes parser error - but let's be absolutely sure we're aligned with the spec
417
+ throw new Error('Cannot use an export all with any other specifiers');
418
+ }
419
+ return {
420
+ type: 'ExportAllDeclaration',
421
+ source: node.source,
422
+ exportKind: node.exportKind ?? 'value',
423
+ exported: namespaceSpecifier.exported,
424
+ range: node.range,
425
+ loc: node.loc,
426
+ };
427
+ }
428
+
429
+ return node;
430
+ }
431
+
432
+ mapExportAllDeclaration(nodeUnprocessed: HermesNode): HermesNode {
433
+ const node = super.mapExportAllDeclaration(nodeUnprocessed);
434
+ node.exported = node.exported ?? null;
435
+ return node;
436
+ }
170
437
  }
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Copyright (c) Facebook, Inc. and its affiliates.
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
3
  *
4
4
  * This source code is licensed under the MIT license found in the
5
5
  * LICENSE file in the root directory of this source tree.
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Copyright (c) Facebook, Inc. and its affiliates.
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
3
  *
4
4
  * This source code is licensed under the MIT license found in the
5
5
  * LICENSE file in the root directory of this source tree.
@@ -7,17 +7,22 @@
7
7
  *
8
8
  * @format
9
9
  */
10
+ // lint directives to let us do some basic validation of generated files
11
+
12
+ /* eslint no-undef: 'error', no-unused-vars: ['error', {vars: "local"}], no-redeclare: 'error' */
13
+
14
+ /* global $NonMaybeType, $Partial, $ReadOnly, $ReadOnlyArray */
10
15
  'use strict';
11
16
 
12
17
  Object.defineProperty(exports, "__esModule", {
13
18
  value: true
14
19
  });
15
20
  exports.NODE_LIST_CHILD = exports.NODE_CHILD = exports.HERMES_AST_VISITOR_KEYS = void 0;
16
- var NODE_CHILD = 'Node';
21
+ const NODE_CHILD = 'Node';
17
22
  exports.NODE_CHILD = NODE_CHILD;
18
- var NODE_LIST_CHILD = 'NodeList';
23
+ const NODE_LIST_CHILD = 'NodeList';
19
24
  exports.NODE_LIST_CHILD = NODE_LIST_CHILD;
20
- var HERMES_AST_VISITOR_KEYS = {
25
+ const HERMES_AST_VISITOR_KEYS = {
21
26
  AnyTypeAnnotation: {},
22
27
  ArrayExpression: {
23
28
  elements: 'NodeList'
@@ -48,6 +53,8 @@ var HERMES_AST_VISITOR_KEYS = {
48
53
  AwaitExpression: {
49
54
  argument: 'Node'
50
55
  },
56
+ BigIntLiteral: {},
57
+ BigIntLiteralTypeAnnotation: {},
51
58
  BinaryExpression: {
52
59
  left: 'Node',
53
60
  right: 'Node'
@@ -70,6 +77,9 @@ var HERMES_AST_VISITOR_KEYS = {
70
77
  param: 'Node',
71
78
  body: 'Node'
72
79
  },
80
+ ChainExpression: {
81
+ expression: 'Node'
82
+ },
73
83
  ClassBody: {
74
84
  body: 'NodeList'
75
85
  },
@@ -78,7 +88,7 @@ var HERMES_AST_VISITOR_KEYS = {
78
88
  typeParameters: 'Node',
79
89
  superClass: 'Node',
80
90
  superTypeParameters: 'Node',
81
- "implements": 'NodeList',
91
+ implements: 'NodeList',
82
92
  decorators: 'NodeList',
83
93
  body: 'Node'
84
94
  },
@@ -87,7 +97,7 @@ var HERMES_AST_VISITOR_KEYS = {
87
97
  typeParameters: 'Node',
88
98
  superClass: 'Node',
89
99
  superTypeParameters: 'Node',
90
- "implements": 'NodeList',
100
+ implements: 'NodeList',
91
101
  decorators: 'NodeList',
92
102
  body: 'Node'
93
103
  },
@@ -95,18 +105,6 @@ var HERMES_AST_VISITOR_KEYS = {
95
105
  id: 'Node',
96
106
  typeParameters: 'Node'
97
107
  },
98
- ClassPrivateProperty: {
99
- key: 'Node',
100
- value: 'Node',
101
- variance: 'Node',
102
- typeAnnotation: 'Node'
103
- },
104
- ClassProperty: {
105
- key: 'Node',
106
- value: 'Node',
107
- variance: 'Node',
108
- typeAnnotation: 'Node'
109
- },
110
108
  ConditionalExpression: {
111
109
  test: 'Node',
112
110
  alternate: 'Node',
@@ -119,8 +117,8 @@ var HERMES_AST_VISITOR_KEYS = {
119
117
  DeclareClass: {
120
118
  id: 'Node',
121
119
  typeParameters: 'Node',
122
- "extends": 'NodeList',
123
- "implements": 'NodeList',
120
+ extends: 'NodeList',
121
+ implements: 'NodeList',
124
122
  mixins: 'NodeList',
125
123
  body: 'Node'
126
124
  },
@@ -142,7 +140,7 @@ var HERMES_AST_VISITOR_KEYS = {
142
140
  DeclareInterface: {
143
141
  id: 'Node',
144
142
  typeParameters: 'Node',
145
- "extends": 'NodeList',
143
+ extends: 'NodeList',
146
144
  body: 'Node'
147
145
  },
148
146
  DeclareModule: {
@@ -205,6 +203,7 @@ var HERMES_AST_VISITOR_KEYS = {
205
203
  },
206
204
  ExistsTypeAnnotation: {},
207
205
  ExportAllDeclaration: {
206
+ exported: 'Node',
208
207
  source: 'Node'
209
208
  },
210
209
  ExportDefaultDeclaration: {
@@ -215,9 +214,6 @@ var HERMES_AST_VISITOR_KEYS = {
215
214
  specifiers: 'NodeList',
216
215
  source: 'Node'
217
216
  },
218
- ExportNamespaceSpecifier: {
219
- exported: 'Node'
220
- },
221
217
  ExportSpecifier: {
222
218
  exported: 'Node',
223
219
  local: 'Node'
@@ -259,7 +255,7 @@ var HERMES_AST_VISITOR_KEYS = {
259
255
  },
260
256
  FunctionTypeAnnotation: {
261
257
  params: 'NodeList',
262
- "this": 'Node',
258
+ this: 'Node',
263
259
  returnType: 'Node',
264
260
  rest: 'Node',
265
261
  typeParameters: 'Node'
@@ -311,7 +307,7 @@ var HERMES_AST_VISITOR_KEYS = {
311
307
  InterfaceDeclaration: {
312
308
  id: 'Node',
313
309
  typeParameters: 'Node',
314
- "extends": 'NodeList',
310
+ extends: 'NodeList',
315
311
  body: 'Node'
316
312
  },
317
313
  InterfaceExtends: {
@@ -319,7 +315,7 @@ var HERMES_AST_VISITOR_KEYS = {
319
315
  typeParameters: 'Node'
320
316
  },
321
317
  InterfaceTypeAnnotation: {
322
- "extends": 'NodeList',
318
+ extends: 'NodeList',
323
319
  body: 'Node'
324
320
  },
325
321
  IntersectionTypeAnnotation: {
@@ -442,22 +438,11 @@ var HERMES_AST_VISITOR_KEYS = {
442
438
  impltype: 'Node',
443
439
  supertype: 'Node'
444
440
  },
445
- OptionalCallExpression: {
446
- callee: 'Node',
447
- typeArguments: 'Node',
448
- arguments: 'NodeList'
449
- },
450
441
  OptionalIndexedAccessType: {
451
442
  objectType: 'Node',
452
443
  indexType: 'Node'
453
444
  },
454
- OptionalMemberExpression: {
455
- object: 'Node',
456
- property: 'Node'
457
- },
458
- PrivateName: {
459
- id: 'Node'
460
- },
445
+ PrivateIdentifier: {},
461
446
  Program: {
462
447
  body: 'NodeList'
463
448
  },
@@ -465,6 +450,12 @@ var HERMES_AST_VISITOR_KEYS = {
465
450
  key: 'Node',
466
451
  value: 'Node'
467
452
  },
453
+ PropertyDefinition: {
454
+ key: 'Node',
455
+ value: 'Node',
456
+ variance: 'Node',
457
+ typeAnnotation: 'Node'
458
+ },
468
459
  QualifiedTypeIdentifier: {
469
460
  qualification: 'Node',
470
461
  id: 'Node'
@@ -535,7 +526,7 @@ var HERMES_AST_VISITOR_KEYS = {
535
526
  TypeParameter: {
536
527
  bound: 'Node',
537
528
  variance: 'Node',
538
- "default": 'Node'
529
+ default: 'Node'
539
530
  },
540
531
  TypeParameterDeclaration: {
541
532
  params: 'NodeList'
@@ -593,6 +584,30 @@ var HERMES_AST_VISITOR_KEYS = {
593
584
  returnType: 'Node',
594
585
  typeParameters: 'NodeList'
595
586
  },
596
- Import: {}
587
+ Import: {},
588
+ ClassProperty: {
589
+ key: 'Node',
590
+ value: 'Node',
591
+ variance: 'Node',
592
+ typeAnnotation: 'Node'
593
+ },
594
+ ClassPrivateProperty: {
595
+ key: 'Node',
596
+ value: 'Node',
597
+ variance: 'Node',
598
+ typeAnnotation: 'Node'
599
+ },
600
+ PrivateName: {
601
+ id: 'Node'
602
+ },
603
+ OptionalCallExpression: {
604
+ callee: 'Node',
605
+ typeArguments: 'Node',
606
+ arguments: 'NodeList'
607
+ },
608
+ OptionalMemberExpression: {
609
+ object: 'Node',
610
+ property: 'Node'
611
+ }
597
612
  };
598
613
  exports.HERMES_AST_VISITOR_KEYS = HERMES_AST_VISITOR_KEYS;
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Copyright (c) Facebook, Inc. and its affiliates.
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
3
  *
4
4
  * This source code is licensed under the MIT license found in the
5
5
  * LICENSE file in the root directory of this source tree.