hermes-parser 0.10.1 → 0.11.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.
- package/dist/HermesParser.js +2 -2
- package/dist/HermesParser.js.flow +2 -0
- package/dist/HermesParserNodeDeserializers.js +149 -5
- package/dist/HermesParserWASM.js +1 -1
- package/dist/HermesParserWASM.js.flow +2 -2
- package/dist/HermesToBabelAdapter.js +53 -0
- package/dist/HermesToBabelAdapter.js.flow +56 -0
- package/dist/ParserOptions.js.flow +1 -0
- package/dist/generated/ESTreeVisitorKeys.js +15 -1
- package/dist/generated/ParserVisitorKeys.js +69 -1
- package/package.json +3 -2
|
@@ -40,8 +40,8 @@ type HermesParserWASM = $ReadOnly<{
|
|
|
40
40
|
(
|
|
41
41
|
'hermesParse',
|
|
42
42
|
'number',
|
|
43
|
-
['number', 'number', 'number', 'number', 'number'],
|
|
44
|
-
): (number, number, CBoolean, CBoolean, CBoolean) => number,
|
|
43
|
+
['number', 'number', 'number', 'number', 'number', 'number'],
|
|
44
|
+
): (number, number, CBoolean, CBoolean, CBoolean, CBoolean) => number,
|
|
45
45
|
('hermesParseResult_free', 'void', ['number']): number => void,
|
|
46
46
|
('hermesParseResult_getError', 'string', ['number']): number => string,
|
|
47
47
|
('hermesParseResult_getErrorLine', 'number', ['number']): number => number,
|
|
@@ -107,6 +107,12 @@ class HermesToBabelAdapter extends _HermesASTAdapter.default {
|
|
|
107
107
|
|
|
108
108
|
case 'IndexedAccessType':
|
|
109
109
|
case 'OptionalIndexedAccessType':
|
|
110
|
+
case 'KeyofTypeAnnotation':
|
|
111
|
+
case 'ConditionalType':
|
|
112
|
+
case 'InferType':
|
|
113
|
+
case 'TupleTypeLabeledElement':
|
|
114
|
+
case 'TupleTypeSpreadElement':
|
|
115
|
+
case 'ObjectTypeMappedTypeProperty':
|
|
110
116
|
return this.mapUnsupportedTypeAnnotation(node);
|
|
111
117
|
|
|
112
118
|
case 'BigIntLiteral':
|
|
@@ -118,6 +124,21 @@ class HermesToBabelAdapter extends _HermesASTAdapter.default {
|
|
|
118
124
|
case 'BigIntTypeAnnotation':
|
|
119
125
|
return this.mapBigIntTypeAnnotation(node);
|
|
120
126
|
|
|
127
|
+
case 'TypeofTypeAnnotation':
|
|
128
|
+
return this.mapTypeofTypeAnnotation(node);
|
|
129
|
+
|
|
130
|
+
case 'QualifiedTypeofIdentifier':
|
|
131
|
+
return this.mapQualifiedTypeofIdentifier(node);
|
|
132
|
+
|
|
133
|
+
case 'DeclareVariable':
|
|
134
|
+
return this.mapDeclareVariable(node);
|
|
135
|
+
|
|
136
|
+
case 'DeclareEnum':
|
|
137
|
+
return this.mapDeclareEnum(node);
|
|
138
|
+
|
|
139
|
+
case 'JSXElement':
|
|
140
|
+
return this.mapJSXElement(node);
|
|
141
|
+
|
|
121
142
|
default:
|
|
122
143
|
return this.mapNodeDefault(node);
|
|
123
144
|
}
|
|
@@ -509,6 +530,38 @@ class HermesToBabelAdapter extends _HermesASTAdapter.default {
|
|
|
509
530
|
return node;
|
|
510
531
|
}
|
|
511
532
|
|
|
533
|
+
mapTypeofTypeAnnotation(nodeUnprocessed) {
|
|
534
|
+
nodeUnprocessed.argument = {
|
|
535
|
+
type: 'GenericTypeAnnotation',
|
|
536
|
+
id: nodeUnprocessed.argument,
|
|
537
|
+
typeParameters: null,
|
|
538
|
+
loc: nodeUnprocessed.argument.loc
|
|
539
|
+
};
|
|
540
|
+
return this.mapNodeDefault(nodeUnprocessed);
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
mapQualifiedTypeofIdentifier(nodeUnprocessed) {
|
|
544
|
+
nodeUnprocessed.type = 'QualifiedTypeIdentifier';
|
|
545
|
+
return this.mapNodeDefault(nodeUnprocessed);
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
mapDeclareVariable(nodeUnprocessed) {
|
|
549
|
+
delete nodeUnprocessed.kind;
|
|
550
|
+
return this.mapNodeDefault(nodeUnprocessed);
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
mapDeclareEnum(nodeUnprocessed) {
|
|
554
|
+
nodeUnprocessed.id.typeAnnotation = this.mapUnsupportedTypeAnnotation(nodeUnprocessed.body);
|
|
555
|
+
delete nodeUnprocessed.body;
|
|
556
|
+
nodeUnprocessed.type = 'DeclareVariable';
|
|
557
|
+
return this.mapDeclareVariable(nodeUnprocessed);
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
mapJSXElement(nodeUnprocessed) {
|
|
561
|
+
delete nodeUnprocessed.openingElement.typeArguments;
|
|
562
|
+
return this.mapNodeDefault(nodeUnprocessed);
|
|
563
|
+
}
|
|
564
|
+
|
|
512
565
|
}
|
|
513
566
|
|
|
514
567
|
exports.default = HermesToBabelAdapter;
|
|
@@ -79,6 +79,12 @@ export default class HermesToBabelAdapter extends HermesASTAdapter {
|
|
|
79
79
|
return this.mapFunction(node);
|
|
80
80
|
case 'IndexedAccessType':
|
|
81
81
|
case 'OptionalIndexedAccessType':
|
|
82
|
+
case 'KeyofTypeAnnotation':
|
|
83
|
+
case 'ConditionalType':
|
|
84
|
+
case 'InferType':
|
|
85
|
+
case 'TupleTypeLabeledElement':
|
|
86
|
+
case 'TupleTypeSpreadElement':
|
|
87
|
+
case 'ObjectTypeMappedTypeProperty':
|
|
82
88
|
return this.mapUnsupportedTypeAnnotation(node);
|
|
83
89
|
case 'BigIntLiteral':
|
|
84
90
|
return this.mapBigIntLiteral(node);
|
|
@@ -86,6 +92,16 @@ export default class HermesToBabelAdapter extends HermesASTAdapter {
|
|
|
86
92
|
return this.mapBigIntLiteralTypeAnnotation(node);
|
|
87
93
|
case 'BigIntTypeAnnotation':
|
|
88
94
|
return this.mapBigIntTypeAnnotation(node);
|
|
95
|
+
case 'TypeofTypeAnnotation':
|
|
96
|
+
return this.mapTypeofTypeAnnotation(node);
|
|
97
|
+
case 'QualifiedTypeofIdentifier':
|
|
98
|
+
return this.mapQualifiedTypeofIdentifier(node);
|
|
99
|
+
case 'DeclareVariable':
|
|
100
|
+
return this.mapDeclareVariable(node);
|
|
101
|
+
case 'DeclareEnum':
|
|
102
|
+
return this.mapDeclareEnum(node);
|
|
103
|
+
case 'JSXElement':
|
|
104
|
+
return this.mapJSXElement(node);
|
|
89
105
|
default:
|
|
90
106
|
return this.mapNodeDefault(node);
|
|
91
107
|
}
|
|
@@ -487,4 +503,44 @@ export default class HermesToBabelAdapter extends HermesASTAdapter {
|
|
|
487
503
|
|
|
488
504
|
return node;
|
|
489
505
|
}
|
|
506
|
+
|
|
507
|
+
mapTypeofTypeAnnotation(nodeUnprocessed: HermesNode): HermesNode {
|
|
508
|
+
nodeUnprocessed.argument = {
|
|
509
|
+
type: 'GenericTypeAnnotation',
|
|
510
|
+
id: nodeUnprocessed.argument,
|
|
511
|
+
typeParameters: null,
|
|
512
|
+
loc: nodeUnprocessed.argument.loc,
|
|
513
|
+
};
|
|
514
|
+
|
|
515
|
+
return this.mapNodeDefault(nodeUnprocessed);
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
mapQualifiedTypeofIdentifier(nodeUnprocessed: HermesNode): HermesNode {
|
|
519
|
+
nodeUnprocessed.type = 'QualifiedTypeIdentifier';
|
|
520
|
+
|
|
521
|
+
return this.mapNodeDefault(nodeUnprocessed);
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
mapDeclareVariable(nodeUnprocessed: HermesNode): HermesNode {
|
|
525
|
+
delete nodeUnprocessed.kind;
|
|
526
|
+
|
|
527
|
+
return this.mapNodeDefault(nodeUnprocessed);
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
mapDeclareEnum(nodeUnprocessed: HermesNode): HermesNode {
|
|
531
|
+
nodeUnprocessed.id.typeAnnotation = this.mapUnsupportedTypeAnnotation(
|
|
532
|
+
nodeUnprocessed.body,
|
|
533
|
+
);
|
|
534
|
+
|
|
535
|
+
delete nodeUnprocessed.body;
|
|
536
|
+
|
|
537
|
+
nodeUnprocessed.type = 'DeclareVariable';
|
|
538
|
+
|
|
539
|
+
return this.mapDeclareVariable(nodeUnprocessed);
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
mapJSXElement(nodeUnprocessed: HermesNode): HermesNode {
|
|
543
|
+
delete nodeUnprocessed.openingElement.typeArguments;
|
|
544
|
+
return this.mapNodeDefault(nodeUnprocessed);
|
|
545
|
+
}
|
|
490
546
|
}
|
|
@@ -12,6 +12,7 @@ export type ParserOptions = {
|
|
|
12
12
|
allowReturnOutsideFunction?: boolean,
|
|
13
13
|
babel?: boolean,
|
|
14
14
|
flow?: 'all' | 'detect',
|
|
15
|
+
enableExperimentalComponentSyntax?: boolean,
|
|
15
16
|
sourceFilename?: string,
|
|
16
17
|
sourceType?: 'module' | 'script' | 'unambiguous',
|
|
17
18
|
tokens?: boolean,
|
|
@@ -44,11 +44,18 @@ module.exports = {
|
|
|
44
44
|
ClassDeclaration: ['id', 'typeParameters', 'superClass', 'superTypeParameters', 'implements', 'decorators', 'body'],
|
|
45
45
|
ClassExpression: ['id', 'typeParameters', 'superClass', 'superTypeParameters', 'implements', 'decorators', 'body'],
|
|
46
46
|
ClassImplements: ['id', 'typeParameters'],
|
|
47
|
+
ComponentDeclaration: ['id', 'params', 'body', 'typeParameters', 'returnType'],
|
|
48
|
+
ComponentParameter: ['name', 'local'],
|
|
49
|
+
ComponentTypeAnnotation: ['params', 'rest', 'typeParameters', 'returnType'],
|
|
50
|
+
ComponentTypeParameter: ['name', 'typeAnnotation'],
|
|
47
51
|
ConditionalExpression: ['test', 'consequent', 'alternate'],
|
|
52
|
+
ConditionalTypeAnnotation: ['checkType', 'extendsType', 'trueType', 'falseType'],
|
|
48
53
|
ContinueStatement: ['label'],
|
|
49
54
|
DebuggerStatement: [],
|
|
50
55
|
DeclareClass: ['id', 'typeParameters', 'extends', 'implements', 'mixins', 'body'],
|
|
56
|
+
DeclareComponent: ['id', 'params', 'rest', 'typeParameters', 'returnType'],
|
|
51
57
|
DeclaredPredicate: ['value'],
|
|
58
|
+
DeclareEnum: ['id', 'body'],
|
|
52
59
|
DeclareExportAllDeclaration: ['source'],
|
|
53
60
|
DeclareExportDeclaration: ['declaration', 'specifiers', 'source'],
|
|
54
61
|
DeclareFunction: ['id', 'predicate'],
|
|
@@ -94,6 +101,7 @@ module.exports = {
|
|
|
94
101
|
ImportSpecifier: ['imported', 'local'],
|
|
95
102
|
IndexedAccessType: ['objectType', 'indexType'],
|
|
96
103
|
InferredPredicate: [],
|
|
104
|
+
InferTypeAnnotation: ['typeParameter'],
|
|
97
105
|
InterfaceDeclaration: ['id', 'typeParameters', 'extends', 'body'],
|
|
98
106
|
InterfaceExtends: ['id', 'typeParameters'],
|
|
99
107
|
InterfaceTypeAnnotation: ['extends', 'body'],
|
|
@@ -108,11 +116,12 @@ module.exports = {
|
|
|
108
116
|
JSXIdentifier: [],
|
|
109
117
|
JSXMemberExpression: ['object', 'property'],
|
|
110
118
|
JSXNamespacedName: ['namespace', 'name'],
|
|
111
|
-
JSXOpeningElement: ['name', 'attributes'],
|
|
119
|
+
JSXOpeningElement: ['name', 'attributes', 'typeArguments'],
|
|
112
120
|
JSXOpeningFragment: [],
|
|
113
121
|
JSXSpreadAttribute: ['argument'],
|
|
114
122
|
JSXSpreadChild: ['expression'],
|
|
115
123
|
JSXText: [],
|
|
124
|
+
KeyofTypeAnnotation: ['argument'],
|
|
116
125
|
LabeledStatement: ['label', 'body'],
|
|
117
126
|
LogicalExpression: ['left', 'right'],
|
|
118
127
|
MemberExpression: ['object', 'property'],
|
|
@@ -130,6 +139,7 @@ module.exports = {
|
|
|
130
139
|
ObjectTypeCallProperty: ['value'],
|
|
131
140
|
ObjectTypeIndexer: ['id', 'key', 'value', 'variance'],
|
|
132
141
|
ObjectTypeInternalSlot: ['id', 'value'],
|
|
142
|
+
ObjectTypeMappedTypeProperty: ['keyTparam', 'propType', 'sourceType', 'variance'],
|
|
133
143
|
ObjectTypeProperty: ['key', 'value', 'variance'],
|
|
134
144
|
ObjectTypeSpreadProperty: ['argument'],
|
|
135
145
|
OpaqueType: ['id', 'typeParameters', 'impltype', 'supertype'],
|
|
@@ -139,6 +149,7 @@ module.exports = {
|
|
|
139
149
|
Property: ['key', 'value'],
|
|
140
150
|
PropertyDefinition: ['key', 'value', 'variance', 'typeAnnotation', 'tsModifiers'],
|
|
141
151
|
QualifiedTypeIdentifier: ['qualification', 'id'],
|
|
152
|
+
QualifiedTypeofIdentifier: ['qualification', 'id'],
|
|
142
153
|
RestElement: ['argument'],
|
|
143
154
|
ReturnStatement: ['argument'],
|
|
144
155
|
SequenceExpression: ['expressions'],
|
|
@@ -157,6 +168,8 @@ module.exports = {
|
|
|
157
168
|
ThrowStatement: ['argument'],
|
|
158
169
|
TryStatement: ['block', 'handler', 'finalizer'],
|
|
159
170
|
TupleTypeAnnotation: ['types'],
|
|
171
|
+
TupleTypeLabeledElement: ['label', 'elementType', 'variance'],
|
|
172
|
+
TupleTypeSpreadElement: ['label', 'typeAnnotation'],
|
|
160
173
|
TypeAlias: ['id', 'typeParameters', 'right'],
|
|
161
174
|
TypeAnnotation: ['typeAnnotation'],
|
|
162
175
|
TypeCastExpression: ['expression', 'typeAnnotation'],
|
|
@@ -164,6 +177,7 @@ module.exports = {
|
|
|
164
177
|
TypeParameter: ['bound', 'variance', 'default'],
|
|
165
178
|
TypeParameterDeclaration: ['params'],
|
|
166
179
|
TypeParameterInstantiation: ['params'],
|
|
180
|
+
TypePredicate: ['parameterName', 'typeAnnotation'],
|
|
167
181
|
UnaryExpression: ['argument'],
|
|
168
182
|
UnionTypeAnnotation: ['types'],
|
|
169
183
|
UpdateExpression: ['argument'],
|
|
@@ -113,11 +113,38 @@ const HERMES_AST_VISITOR_KEYS = {
|
|
|
113
113
|
id: 'Node',
|
|
114
114
|
typeParameters: 'Node'
|
|
115
115
|
},
|
|
116
|
+
ComponentDeclaration: {
|
|
117
|
+
id: 'Node',
|
|
118
|
+
params: 'NodeList',
|
|
119
|
+
body: 'Node',
|
|
120
|
+
typeParameters: 'Node',
|
|
121
|
+
returnType: 'Node'
|
|
122
|
+
},
|
|
123
|
+
ComponentParameter: {
|
|
124
|
+
name: 'Node',
|
|
125
|
+
local: 'Node'
|
|
126
|
+
},
|
|
127
|
+
ComponentTypeAnnotation: {
|
|
128
|
+
params: 'NodeList',
|
|
129
|
+
rest: 'Node',
|
|
130
|
+
typeParameters: 'Node',
|
|
131
|
+
returnType: 'Node'
|
|
132
|
+
},
|
|
133
|
+
ComponentTypeParameter: {
|
|
134
|
+
name: 'Node',
|
|
135
|
+
typeAnnotation: 'Node'
|
|
136
|
+
},
|
|
116
137
|
ConditionalExpression: {
|
|
117
138
|
test: 'Node',
|
|
118
139
|
alternate: 'Node',
|
|
119
140
|
consequent: 'Node'
|
|
120
141
|
},
|
|
142
|
+
ConditionalTypeAnnotation: {
|
|
143
|
+
checkType: 'Node',
|
|
144
|
+
extendsType: 'Node',
|
|
145
|
+
trueType: 'Node',
|
|
146
|
+
falseType: 'Node'
|
|
147
|
+
},
|
|
121
148
|
ContinueStatement: {
|
|
122
149
|
label: 'Node'
|
|
123
150
|
},
|
|
@@ -130,9 +157,20 @@ const HERMES_AST_VISITOR_KEYS = {
|
|
|
130
157
|
mixins: 'NodeList',
|
|
131
158
|
body: 'Node'
|
|
132
159
|
},
|
|
160
|
+
DeclareComponent: {
|
|
161
|
+
id: 'Node',
|
|
162
|
+
params: 'NodeList',
|
|
163
|
+
rest: 'Node',
|
|
164
|
+
typeParameters: 'Node',
|
|
165
|
+
returnType: 'Node'
|
|
166
|
+
},
|
|
133
167
|
DeclaredPredicate: {
|
|
134
168
|
value: 'Node'
|
|
135
169
|
},
|
|
170
|
+
DeclareEnum: {
|
|
171
|
+
id: 'Node',
|
|
172
|
+
body: 'Node'
|
|
173
|
+
},
|
|
136
174
|
DeclareExportAllDeclaration: {
|
|
137
175
|
source: 'Node'
|
|
138
176
|
},
|
|
@@ -312,6 +350,9 @@ const HERMES_AST_VISITOR_KEYS = {
|
|
|
312
350
|
indexType: 'Node'
|
|
313
351
|
},
|
|
314
352
|
InferredPredicate: {},
|
|
353
|
+
InferTypeAnnotation: {
|
|
354
|
+
typeParameter: 'Node'
|
|
355
|
+
},
|
|
315
356
|
InterfaceDeclaration: {
|
|
316
357
|
id: 'Node',
|
|
317
358
|
typeParameters: 'Node',
|
|
@@ -362,7 +403,8 @@ const HERMES_AST_VISITOR_KEYS = {
|
|
|
362
403
|
},
|
|
363
404
|
JSXOpeningElement: {
|
|
364
405
|
name: 'Node',
|
|
365
|
-
attributes: 'NodeList'
|
|
406
|
+
attributes: 'NodeList',
|
|
407
|
+
typeArguments: 'Node'
|
|
366
408
|
},
|
|
367
409
|
JSXOpeningFragment: {},
|
|
368
410
|
JSXSpreadAttribute: {
|
|
@@ -372,6 +414,9 @@ const HERMES_AST_VISITOR_KEYS = {
|
|
|
372
414
|
expression: 'Node'
|
|
373
415
|
},
|
|
374
416
|
JSXText: {},
|
|
417
|
+
KeyofTypeAnnotation: {
|
|
418
|
+
argument: 'Node'
|
|
419
|
+
},
|
|
375
420
|
LabeledStatement: {
|
|
376
421
|
label: 'Node',
|
|
377
422
|
body: 'Node'
|
|
@@ -432,6 +477,12 @@ const HERMES_AST_VISITOR_KEYS = {
|
|
|
432
477
|
id: 'Node',
|
|
433
478
|
value: 'Node'
|
|
434
479
|
},
|
|
480
|
+
ObjectTypeMappedTypeProperty: {
|
|
481
|
+
keyTparam: 'Node',
|
|
482
|
+
propType: 'Node',
|
|
483
|
+
sourceType: 'Node',
|
|
484
|
+
variance: 'Node'
|
|
485
|
+
},
|
|
435
486
|
ObjectTypeProperty: {
|
|
436
487
|
key: 'Node',
|
|
437
488
|
value: 'Node',
|
|
@@ -469,6 +520,10 @@ const HERMES_AST_VISITOR_KEYS = {
|
|
|
469
520
|
qualification: 'Node',
|
|
470
521
|
id: 'Node'
|
|
471
522
|
},
|
|
523
|
+
QualifiedTypeofIdentifier: {
|
|
524
|
+
qualification: 'Node',
|
|
525
|
+
id: 'Node'
|
|
526
|
+
},
|
|
472
527
|
RegExpLiteral: {},
|
|
473
528
|
RestElement: {
|
|
474
529
|
argument: 'Node'
|
|
@@ -517,6 +572,15 @@ const HERMES_AST_VISITOR_KEYS = {
|
|
|
517
572
|
TupleTypeAnnotation: {
|
|
518
573
|
types: 'NodeList'
|
|
519
574
|
},
|
|
575
|
+
TupleTypeLabeledElement: {
|
|
576
|
+
label: 'Node',
|
|
577
|
+
elementType: 'Node',
|
|
578
|
+
variance: 'Node'
|
|
579
|
+
},
|
|
580
|
+
TupleTypeSpreadElement: {
|
|
581
|
+
label: 'Node',
|
|
582
|
+
typeAnnotation: 'Node'
|
|
583
|
+
},
|
|
520
584
|
TypeAlias: {
|
|
521
585
|
id: 'Node',
|
|
522
586
|
typeParameters: 'Node',
|
|
@@ -543,6 +607,10 @@ const HERMES_AST_VISITOR_KEYS = {
|
|
|
543
607
|
TypeParameterInstantiation: {
|
|
544
608
|
params: 'NodeList'
|
|
545
609
|
},
|
|
610
|
+
TypePredicate: {
|
|
611
|
+
parameterName: 'Node',
|
|
612
|
+
typeAnnotation: 'Node'
|
|
613
|
+
},
|
|
546
614
|
UnaryExpression: {
|
|
547
615
|
argument: 'Node'
|
|
548
616
|
},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "hermes-parser",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.11.0",
|
|
4
4
|
"description": "A JavaScript parser built from the Hermes engine",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"license": "MIT",
|
|
@@ -9,10 +9,11 @@
|
|
|
9
9
|
"url": "git@github.com:facebook/hermes.git"
|
|
10
10
|
},
|
|
11
11
|
"dependencies": {
|
|
12
|
-
"hermes-estree": "0.
|
|
12
|
+
"hermes-estree": "0.11.0"
|
|
13
13
|
},
|
|
14
14
|
"devDependencies": {
|
|
15
15
|
"@babel/parser": "7.7.4",
|
|
16
|
+
"@babel/types": "7.7.4",
|
|
16
17
|
"espree": "9.3.2"
|
|
17
18
|
},
|
|
18
19
|
"files": [
|