poe-code 6.0.0 → 7.0.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.
@@ -0,0 +1,90 @@
1
+ export function* boundIdentifiers(pattern) {
2
+ switch (pattern.type) {
3
+ case "Identifier":
4
+ yield pattern;
5
+ return;
6
+ case "AssignmentPattern":
7
+ yield* boundIdentifiers(pattern.left);
8
+ return;
9
+ case "RestElement":
10
+ yield* boundIdentifiers(pattern.argument);
11
+ return;
12
+ case "ArrayPattern":
13
+ for (const element of pattern.elements) {
14
+ if (element !== null)
15
+ yield* boundIdentifiers(element);
16
+ }
17
+ return;
18
+ case "ObjectPattern":
19
+ for (const property of pattern.properties) {
20
+ yield* boundIdentifiers(property.type === "RestElement" ? property : property.value);
21
+ }
22
+ return;
23
+ case "MemberExpression":
24
+ return;
25
+ }
26
+ }
27
+ export function containsParameterExpression(pattern) {
28
+ switch (pattern.type) {
29
+ case "AssignmentPattern":
30
+ case "MemberExpression":
31
+ return true;
32
+ case "RestElement":
33
+ return containsParameterExpression(pattern.argument);
34
+ case "ArrayPattern":
35
+ return pattern.elements.some((element) => element !== null && containsParameterExpression(element));
36
+ case "ObjectPattern":
37
+ return pattern.properties.some((property) => property.type === "RestElement"
38
+ ? containsParameterExpression(property.argument)
39
+ : property.computed || containsParameterExpression(property.value));
40
+ case "Identifier":
41
+ return false;
42
+ }
43
+ }
44
+ export function* hoistedVarDeclarations(nodes) {
45
+ for (const node of nodes) {
46
+ switch (node.type) {
47
+ case "VariableDeclaration":
48
+ if (node.kind === "var")
49
+ yield node;
50
+ break;
51
+ case "BlockStatement":
52
+ yield* hoistedVarDeclarations(node.body);
53
+ break;
54
+ case "IfStatement":
55
+ yield* hoistedVarDeclarations([node.consequent]);
56
+ if (node.alternate !== undefined)
57
+ yield* hoistedVarDeclarations([node.alternate]);
58
+ break;
59
+ case "ForStatement":
60
+ if (node.init?.type === "VariableDeclaration")
61
+ yield* hoistedVarDeclarations([node.init]);
62
+ yield* hoistedVarDeclarations([node.body]);
63
+ break;
64
+ case "ForInStatement":
65
+ case "ForOfStatement":
66
+ if (node.left.type === "VariableDeclaration")
67
+ yield* hoistedVarDeclarations([node.left]);
68
+ yield* hoistedVarDeclarations([node.body]);
69
+ break;
70
+ case "WhileStatement":
71
+ case "DoWhileStatement":
72
+ yield* hoistedVarDeclarations([node.body]);
73
+ break;
74
+ case "TryStatement":
75
+ yield* hoistedVarDeclarations([node.block]);
76
+ if (node.handler !== undefined)
77
+ yield* hoistedVarDeclarations([node.handler.body]);
78
+ if (node.finalizer !== undefined)
79
+ yield* hoistedVarDeclarations([node.finalizer]);
80
+ break;
81
+ case "SwitchStatement":
82
+ for (const switchCase of node.cases)
83
+ yield* hoistedVarDeclarations(switchCase.consequent);
84
+ break;
85
+ case "ExportNamedDeclaration":
86
+ yield* hoistedVarDeclarations([node.declaration]);
87
+ break;
88
+ }
89
+ }
90
+ }
@@ -1,3 +1,4 @@
1
+ import { boundIdentifiers } from "./bindings.js";
1
2
  import { tokenize } from "./tokenizer.js";
2
3
  import { assignIds } from "./assign-ids.js";
3
4
  import { formatParseError } from "./format-error.js";
@@ -104,8 +105,11 @@ class Parser {
104
105
  loopDepth = 0;
105
106
  generatorBody = false;
106
107
  scopes = [new Map()];
108
+ functionScopes = new WeakSet();
109
+ varNames = new WeakMap();
107
110
  constructor(tokens) {
108
111
  this.tokens = tokens;
112
+ this.functionScopes.add(this.scopes[0]);
109
113
  }
110
114
  parseTopLevel() {
111
115
  if (this.isExportToken(this.currentToken())) {
@@ -244,8 +248,14 @@ class Parser {
244
248
  return undefined;
245
249
  }
246
250
  finishArrowFunctionExpression(start, isAsync, params) {
251
+ this.withScope(() => {
252
+ for (const param of params) {
253
+ for (const identifier of boundIdentifiers(param))
254
+ this.declareBinding(identifier);
255
+ }
256
+ });
247
257
  this.expectPunctuator("=>");
248
- const body = this.parseArrowFunctionBody();
258
+ const body = this.parseArrowFunctionBody(params);
249
259
  return {
250
260
  type: "ArrowFunctionExpression",
251
261
  async: isAsync,
@@ -284,15 +294,27 @@ class Parser {
284
294
  this.conditionalExpressionDepth -= 1;
285
295
  }
286
296
  }
287
- parseArrowFunctionBody() {
297
+ parseArrowFunctionBody(params) {
288
298
  if (this.currentToken().type === "punctuator" && this.currentToken().value === "{") {
289
- return this.withFunctionContext(false, () => this.parseBlockStatement());
299
+ return this.withFunctionContext(false, () => this.parseBlockStatement(params));
290
300
  }
291
301
  return this.withFunctionContext(false, () => this.parseExpression().node);
292
302
  }
293
- parseBlockStatement() {
303
+ parseBlockStatement(params, catchParam) {
294
304
  const start = this.expectPunctuator("{");
295
- return this.withScope(() => this.parseBlockStatementBody(start));
305
+ return this.withScope(() => {
306
+ for (const param of params ?? []) {
307
+ for (const identifier of boundIdentifiers(param)) {
308
+ this.declareBinding(identifier, "parameter");
309
+ }
310
+ }
311
+ if (catchParam !== undefined) {
312
+ for (const identifier of boundIdentifiers(catchParam)) {
313
+ this.declareBinding(identifier, catchParam.type === "Identifier" ? "catch" : "lexical");
314
+ }
315
+ }
316
+ return this.parseBlockStatementBody(start);
317
+ }, params !== undefined);
296
318
  }
297
319
  parseBlockStatementBody(start) {
298
320
  const body = [];
@@ -819,7 +841,7 @@ class Parser {
819
841
  param = this.parseBindingTarget();
820
842
  this.expectPunctuator(")");
821
843
  }
822
- const body = this.parseBlockStatement();
844
+ const body = this.parseBlockStatement(undefined, param);
823
845
  return {
824
846
  type: "CatchClause",
825
847
  param,
@@ -840,6 +862,11 @@ class Parser {
840
862
  if (kindToken.value !== "var") {
841
863
  this.declarePatternBindings(declarator.id);
842
864
  }
865
+ else {
866
+ for (const identifier of boundIdentifiers(declarator.id)) {
867
+ this.declareVarBinding(identifier);
868
+ }
869
+ }
843
870
  declarations.push(declarator);
844
871
  const comma = this.consumePunctuator(",");
845
872
  if (comma === undefined) {
@@ -861,18 +888,18 @@ class Parser {
861
888
  throw new Error(`async function* is not supported at line ${asyncToken.start.line}, column ${asyncToken.start.column}.`);
862
889
  }
863
890
  const id = this.parseBindingIdentifier();
864
- this.declareBinding(id);
891
+ this.declareBinding(id, "function");
865
892
  const params = this.withScope(() => {
866
893
  const parsedParams = this.parseArrowParameters();
867
894
  for (const param of parsedParams) {
868
- for (const identifier of collectBindingIdentifiers(param)) {
895
+ for (const identifier of boundIdentifiers(param)) {
869
896
  this.declareBinding(identifier);
870
897
  }
871
898
  }
872
899
  return parsedParams;
873
900
  });
874
901
  const generator = generatorToken !== undefined;
875
- const body = this.withFunctionContext(generator, () => this.parseBlockStatement());
902
+ const body = this.withFunctionContext(generator, () => this.parseBlockStatement(params));
876
903
  return {
877
904
  type: "FunctionDeclaration",
878
905
  async: asyncToken !== undefined,
@@ -1809,14 +1836,14 @@ class Parser {
1809
1836
  const params = this.withScope(() => {
1810
1837
  const parsedParams = this.parseArrowParameters();
1811
1838
  for (const param of parsedParams) {
1812
- for (const identifier of collectBindingIdentifiers(param)) {
1839
+ for (const identifier of boundIdentifiers(param)) {
1813
1840
  this.declareBinding(identifier);
1814
1841
  }
1815
1842
  }
1816
1843
  return parsedParams;
1817
1844
  });
1818
1845
  const generator = generatorToken !== undefined;
1819
- const body = this.withFunctionContext(generator, () => this.parseBlockStatement());
1846
+ const body = this.withFunctionContext(generator, () => this.parseBlockStatement(params));
1820
1847
  return {
1821
1848
  type: "FunctionExpression",
1822
1849
  async: asyncToken !== undefined,
@@ -2071,13 +2098,13 @@ class Parser {
2071
2098
  const params = this.withScope(() => {
2072
2099
  const parsedParams = this.parseArrowParameters();
2073
2100
  for (const param of parsedParams) {
2074
- for (const identifier of collectBindingIdentifiers(param)) {
2101
+ for (const identifier of boundIdentifiers(param)) {
2075
2102
  this.declareBinding(identifier);
2076
2103
  }
2077
2104
  }
2078
2105
  return parsedParams;
2079
2106
  });
2080
- const body = this.withFunctionContext(false, () => this.parseBlockStatement());
2107
+ const body = this.withFunctionContext(false, () => this.parseBlockStatement(params));
2081
2108
  return {
2082
2109
  type: "FunctionExpression",
2083
2110
  async: asyncToken !== undefined,
@@ -2524,8 +2551,11 @@ class Parser {
2524
2551
  this.breakableDepth -= 1;
2525
2552
  }
2526
2553
  }
2527
- withScope(callback) {
2528
- this.scopes.push(new Map());
2554
+ withScope(callback, functionBody = false) {
2555
+ const scope = new Map();
2556
+ if (functionBody)
2557
+ this.functionScopes.add(scope);
2558
+ this.scopes.push(scope);
2529
2559
  try {
2530
2560
  return callback();
2531
2561
  }
@@ -2534,19 +2564,40 @@ class Parser {
2534
2564
  }
2535
2565
  }
2536
2566
  declarePatternBindings(pattern) {
2537
- for (const identifier of collectBindingIdentifiers(pattern)) {
2567
+ for (const identifier of boundIdentifiers(pattern)) {
2538
2568
  this.declareBinding(identifier);
2539
2569
  }
2540
2570
  }
2541
- declareBinding(identifier) {
2571
+ declareBinding(identifier, kind = "lexical") {
2542
2572
  const scope = this.scopes[this.scopes.length - 1];
2543
2573
  if (scope === undefined) {
2544
2574
  return;
2545
2575
  }
2546
- if (scope.has(identifier.name)) {
2576
+ const existing = scope.get(identifier.name);
2577
+ const variableFunction = kind === "function" && this.functionScopes.has(scope);
2578
+ if ((existing !== undefined &&
2579
+ !(variableFunction && (existing === "function" || existing === "parameter"))) ||
2580
+ (!variableFunction && this.varNames.get(scope)?.has(identifier.name))) {
2547
2581
  throw new Error(`Cannot redeclare binding '${identifier.name}' at line ${identifier.span.start.line}, column ${identifier.span.start.column}.`);
2548
2582
  }
2549
- scope.set(identifier.name, identifier.span.start);
2583
+ scope.set(identifier.name, kind);
2584
+ }
2585
+ declareVarBinding(identifier) {
2586
+ for (let index = this.scopes.length - 1; index >= 0; index--) {
2587
+ const scope = this.scopes[index];
2588
+ const existing = scope.get(identifier.name);
2589
+ if (existing === "lexical" || (existing === "function" && !this.functionScopes.has(scope))) {
2590
+ throw new Error(`Cannot redeclare binding '${identifier.name}' at line ${identifier.span.start.line}, column ${identifier.span.start.column}.`);
2591
+ }
2592
+ let names = this.varNames.get(scope);
2593
+ if (names === undefined) {
2594
+ names = new Set();
2595
+ this.varNames.set(scope, names);
2596
+ }
2597
+ names.add(identifier.name);
2598
+ if (this.functionScopes.has(scope))
2599
+ return;
2600
+ }
2550
2601
  }
2551
2602
  consumePunctuator(value) {
2552
2603
  const token = this.currentToken();
@@ -2638,24 +2689,6 @@ function createIdentifierName(token) {
2638
2689
  span: createTokenSpan(token)
2639
2690
  };
2640
2691
  }
2641
- function collectBindingIdentifiers(pattern) {
2642
- switch (pattern.type) {
2643
- case "Identifier":
2644
- return [pattern];
2645
- case "MemberExpression":
2646
- return [];
2647
- case "AssignmentPattern":
2648
- return collectBindingIdentifiers(pattern.left);
2649
- case "RestElement":
2650
- return collectBindingIdentifiers(pattern.argument);
2651
- case "ArrayPattern":
2652
- return pattern.elements.flatMap((element) => element === null ? [] : collectBindingIdentifiers(element));
2653
- case "ObjectPattern":
2654
- return pattern.properties.flatMap((property) => property.type === "RestElement"
2655
- ? collectBindingIdentifiers(property)
2656
- : collectBindingIdentifiers(property.value));
2657
- }
2658
- }
2659
2692
  function createLoopLabelFields(labels) {
2660
2693
  if (labels === undefined || labels.length === 0) {
2661
2694
  return {};
@@ -1,5 +1,5 @@
1
1
  export declare const DUMP_FORMAT_VERSION = 1;
2
- export declare const EXECUTION_SEMANTICS = "jobs-v2";
2
+ export declare const EXECUTION_SEMANTICS = "jobs-v3";
3
3
  export type DumpableSnapshot = {
4
4
  sourceHash: string;
5
5
  [key: string]: unknown;
@@ -1,5 +1,5 @@
1
1
  export const DUMP_FORMAT_VERSION = 1;
2
- export const EXECUTION_SEMANTICS = "jobs-v2";
2
+ export const EXECUTION_SEMANTICS = "jobs-v3";
3
3
  import { assertSnapshotGraphDepth } from "../graph-depth.js";
4
4
  import { getSandboxArgumentEntries, isSandboxArguments } from "../interp/arguments.js";
5
5
  import { serializeArguments } from "./arguments.js";
@@ -1,13 +0,0 @@
1
- import { type SourceSpan } from "../../parse/parser.js";
2
- export type Diagnostic = {
3
- code: "AS-AWAIT-NON-PROMISE";
4
- severity: "warning";
5
- message: string;
6
- filename: string;
7
- line: number;
8
- column: number;
9
- span: SourceSpan;
10
- };
11
- export declare function AS_AWAIT_NON_PROMISE(source: string, options?: {
12
- filename?: string;
13
- }): Diagnostic[];
@@ -1,301 +0,0 @@
1
- import { parseModule } from "../../parse/parser.js";
2
- export function AS_AWAIT_NON_PROMISE(source, options = {}) {
3
- return new ASAwaitNonPromiseScanner(options.filename ?? "<input>").scan(source);
4
- }
5
- class ASAwaitNonPromiseScanner {
6
- filename;
7
- diagnostics = [];
8
- constructor(filename) {
9
- this.filename = filename;
10
- }
11
- scan(source) {
12
- this.visitModule(parseModule(source, this.filename));
13
- return this.diagnostics;
14
- }
15
- visitModule(node) {
16
- for (const statement of node.body) {
17
- this.visitStatement(statement);
18
- }
19
- }
20
- visitStatement(node) {
21
- switch (node.type) {
22
- case "FunctionDeclaration":
23
- this.visitArrowFunction(node);
24
- return;
25
- case "BlockStatement":
26
- this.visitBlockStatement(node);
27
- return;
28
- case "ExpressionStatement":
29
- this.visitExpression(node.expression);
30
- return;
31
- case "IfStatement":
32
- this.visitIfStatement(node);
33
- return;
34
- case "ForStatement":
35
- this.visitForStatement(node);
36
- return;
37
- case "ForInStatement":
38
- case "ForOfStatement":
39
- this.visitForOfStatement(node);
40
- return;
41
- case "WhileStatement":
42
- case "DoWhileStatement":
43
- this.visitWhileStatement(node);
44
- return;
45
- case "TryStatement":
46
- this.visitTryStatement(node);
47
- return;
48
- case "VariableDeclaration":
49
- this.visitVariableDeclaration(node);
50
- return;
51
- case "ReturnStatement":
52
- this.visitReturnStatement(node);
53
- return;
54
- case "ThrowStatement":
55
- this.visitThrowStatement(node);
56
- return;
57
- case "ExportNamedDeclaration":
58
- this.visitVariableDeclaration(node.declaration);
59
- return;
60
- case "ExportDefaultDeclaration":
61
- this.visitExpression(node.declaration);
62
- return;
63
- case "ImportDeclaration":
64
- case "BreakStatement":
65
- case "ContinueStatement":
66
- return;
67
- }
68
- }
69
- visitBlockStatement(node) {
70
- for (const statement of node.body) {
71
- this.visitStatement(statement);
72
- }
73
- }
74
- visitIfStatement(node) {
75
- this.visitExpression(node.test);
76
- this.visitStatement(node.consequent);
77
- if (node.alternate !== undefined) {
78
- this.visitStatement(node.alternate);
79
- }
80
- }
81
- visitForStatement(node) {
82
- if (node.init !== undefined) {
83
- if (node.init.type === "VariableDeclaration") {
84
- this.visitVariableDeclaration(node.init);
85
- }
86
- else {
87
- this.visitExpression(node.init);
88
- }
89
- }
90
- if (node.test !== undefined) {
91
- this.visitExpression(node.test);
92
- }
93
- if (node.update !== undefined) {
94
- this.visitExpression(node.update);
95
- }
96
- this.visitStatement(node.body);
97
- }
98
- visitForOfStatement(node) {
99
- if (node.left.type === "VariableDeclaration") {
100
- this.visitVariableDeclaration(node.left);
101
- }
102
- this.visitExpression(node.right);
103
- this.visitStatement(node.body);
104
- }
105
- visitWhileStatement(node) {
106
- this.visitExpression(node.test);
107
- this.visitStatement(node.body);
108
- }
109
- visitTryStatement(node) {
110
- this.visitBlockStatement(node.block);
111
- if (node.handler !== undefined) {
112
- this.visitCatchClause(node.handler);
113
- }
114
- if (node.finalizer !== undefined) {
115
- this.visitBlockStatement(node.finalizer);
116
- }
117
- }
118
- visitCatchClause(node) {
119
- this.visitBlockStatement(node.body);
120
- }
121
- visitVariableDeclaration(node) {
122
- for (const declarator of node.declarations) {
123
- this.visitVariableDeclarator(declarator);
124
- }
125
- }
126
- visitVariableDeclarator(node) {
127
- if (node.init !== undefined) {
128
- this.visitExpression(node.init);
129
- }
130
- }
131
- visitReturnStatement(node) {
132
- if (node.argument !== undefined) {
133
- this.visitExpression(node.argument);
134
- }
135
- }
136
- visitThrowStatement(node) {
137
- this.visitExpression(node.argument);
138
- }
139
- visitExpression(node) {
140
- switch (node.type) {
141
- case "YieldExpression":
142
- if (node.argument !== undefined) {
143
- this.visitExpression(node.argument);
144
- }
145
- return;
146
- case "FunctionExpression":
147
- case "ArrowFunctionExpression":
148
- this.visitArrowFunction(node);
149
- return;
150
- case "AwaitExpression":
151
- this.visitAwaitExpression(node);
152
- return;
153
- case "ArrayExpression":
154
- this.visitArrayExpression(node);
155
- return;
156
- case "ObjectExpression":
157
- this.visitObjectExpression(node);
158
- return;
159
- case "UnaryExpression":
160
- this.visitUnaryExpression(node);
161
- return;
162
- case "BinaryExpression":
163
- case "LogicalExpression":
164
- this.visitBinaryLikeExpression(node);
165
- return;
166
- case "ConditionalExpression":
167
- this.visitConditionalExpression(node);
168
- return;
169
- case "MemberExpression":
170
- this.visitMemberExpression(node);
171
- return;
172
- case "AssignmentExpression":
173
- this.visitAssignmentExpression(node);
174
- return;
175
- case "CallExpression":
176
- this.visitCallExpression(node);
177
- return;
178
- case "TemplateLiteral":
179
- this.visitTemplateLiteral(node);
180
- return;
181
- case "TaggedTemplateExpression":
182
- this.visitTaggedTemplateExpression(node);
183
- return;
184
- case "Identifier":
185
- case "BooleanLiteral":
186
- case "MetaProperty":
187
- case "NullLiteral":
188
- case "NumericLiteral":
189
- case "RegexLiteral":
190
- case "StringLiteral":
191
- case "UndefinedLiteral":
192
- return;
193
- }
194
- }
195
- visitArrowFunction(node) {
196
- if (node.body.type === "BlockStatement") {
197
- this.visitBlockStatement(node.body);
198
- return;
199
- }
200
- this.visitExpression(node.body);
201
- }
202
- visitAwaitExpression(node) {
203
- if (isKnownNonPromiseExpression(node.argument)) {
204
- this.report(node.argument.span);
205
- }
206
- this.visitExpression(node.argument);
207
- }
208
- visitArrayExpression(node) {
209
- for (const element of node.elements) {
210
- if (element.type === "SpreadElement") {
211
- this.visitExpression(element.argument);
212
- continue;
213
- }
214
- this.visitExpression(element);
215
- }
216
- }
217
- visitObjectExpression(node) {
218
- for (const property of node.properties) {
219
- if (property.type === "SpreadElement") {
220
- this.visitExpression(property.argument);
221
- continue;
222
- }
223
- this.visitProperty(property);
224
- }
225
- }
226
- visitProperty(node) {
227
- if (node.computed) {
228
- this.visitExpression(node.key);
229
- }
230
- this.visitExpression(node.value);
231
- }
232
- visitUnaryExpression(node) {
233
- this.visitExpression(node.argument);
234
- }
235
- visitBinaryLikeExpression(node) {
236
- this.visitExpression(node.left);
237
- this.visitExpression(node.right);
238
- }
239
- visitConditionalExpression(node) {
240
- this.visitExpression(node.test);
241
- this.visitExpression(node.consequent);
242
- this.visitExpression(node.alternate);
243
- }
244
- visitMemberExpression(node) {
245
- this.visitExpression(node.object);
246
- if (node.computed) {
247
- this.visitExpression(node.property);
248
- }
249
- }
250
- visitAssignmentExpression(node) {
251
- this.visitExpression(node.right);
252
- }
253
- visitCallExpression(node) {
254
- this.visitExpression(node.callee);
255
- for (const argument of node.arguments) {
256
- if (argument.type === "SpreadElement") {
257
- this.visitExpression(argument.argument);
258
- continue;
259
- }
260
- this.visitExpression(argument);
261
- }
262
- }
263
- visitTemplateLiteral(node) {
264
- for (const expression of node.expressions) {
265
- this.visitExpression(expression);
266
- }
267
- }
268
- visitTaggedTemplateExpression(node) {
269
- this.visitExpression(node.tag);
270
- this.visitTemplateLiteral(node.quasi);
271
- }
272
- report(span) {
273
- this.diagnostics.push({
274
- code: "AS-AWAIT-NON-PROMISE",
275
- severity: "warning",
276
- message: "Awaiting a known non-promise value has no effect.",
277
- filename: this.filename,
278
- line: span.start.line,
279
- column: span.start.column,
280
- span
281
- });
282
- }
283
- }
284
- function isKnownNonPromiseExpression(node) {
285
- switch (node.type) {
286
- case "FunctionExpression":
287
- case "ArrowFunctionExpression":
288
- case "ArrayExpression":
289
- case "BinaryExpression":
290
- case "BooleanLiteral":
291
- case "NullLiteral":
292
- case "NumericLiteral":
293
- case "ObjectExpression":
294
- case "StringLiteral":
295
- case "TemplateLiteral":
296
- case "UnaryExpression":
297
- return true;
298
- default:
299
- return false;
300
- }
301
- }
@@ -1,13 +0,0 @@
1
- import { type SourceSpan } from "../../parse/parser.js";
2
- export type Diagnostic = {
3
- code: "AS008";
4
- severity: "error";
5
- message: string;
6
- filename: string;
7
- line: number;
8
- column: number;
9
- span: SourceSpan;
10
- };
11
- export declare function AS008(source: string, options?: {
12
- filename?: string;
13
- }): Diagnostic[];