tsc-ts 0.1.0 → 0.1.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 +7 -1
- package/dist/api/compiler/ast.d.ts +15 -3
- package/dist/api/compiler/ast.js +36 -15
- package/dist/api/compiler/checker-classes.js +2 -1
- package/dist/api/compiler/checker-contextual.d.ts +20 -0
- package/dist/api/compiler/checker-contextual.js +111 -1
- package/dist/api/compiler/checker-expressions.js +14 -1
- package/dist/api/compiler/checker-grammar.d.ts +39 -4
- package/dist/api/compiler/checker-grammar.js +239 -75
- package/dist/api/compiler/checker-heritage.js +20 -14
- package/dist/api/compiler/checker-jsx.js +2 -1
- package/dist/api/compiler/checker-modules.js +4 -2
- package/dist/api/compiler/checker-source-file.js +1 -1
- package/dist/api/compiler/checker-type-factory.js +70 -19
- package/dist/api/compiler/checker-type-nodes.d.ts +1 -1
- package/dist/api/compiler/checker-type-nodes.js +5 -5
- package/dist/api/compiler/checker-unused.js +15 -10
- package/dist/api/compiler/checker.d.ts +7 -1
- package/dist/api/compiler/checker.js +14 -4
- package/dist/api/compiler/compile-program.d.ts +5 -0
- package/dist/api/compiler/compile-program.js +8 -0
- package/dist/api/compiler/expr-record.d.ts +11 -0
- package/dist/api/compiler/expr-record.js +53 -0
- package/dist/api/compiler/file-loader.d.ts +5 -0
- package/dist/api/compiler/file-loader.js +7 -0
- package/dist/api/compiler/identifier-name.d.ts +9 -0
- package/dist/api/compiler/identifier-name.js +10 -0
- package/dist/api/compiler/jsdoc.js +4 -2
- package/dist/api/compiler/parser.d.ts +2 -1
- package/dist/api/compiler/parser.js +10 -8
- package/dist/api/compiler/printer/factory.js +3 -2
- package/dist/api/compiler/printer/printer.js +3 -2
- package/dist/api/compiler/program-checker.d.ts +18 -0
- package/dist/api/compiler/program-checker.js +27 -0
- package/dist/api/compiler/reparser.js +4 -3
- package/dist/api/compiler/scanner.d.ts +8 -0
- package/dist/api/compiler/scanner.js +58 -42
- package/dist/api/compiler/shared-results.d.ts +376 -143
- package/dist/api/compiler/shared-results.js +1550 -773
- package/dist/api/compiler/transformers/declarations.js +2 -1
- package/package.json +15 -10
- package/src/compiler/ast.ts +39 -15
- package/src/compiler/cgroup.ts +157 -0
- package/src/compiler/checker-classes.ts +2 -1
- package/src/compiler/checker-contextual.ts +104 -0
- package/src/compiler/checker-expressions.ts +16 -1
- package/src/compiler/checker-grammar.ts +247 -88
- package/src/compiler/checker-heritage.ts +31 -17
- package/src/compiler/checker-jsx.ts +2 -1
- package/src/compiler/checker-modules.ts +4 -2
- package/src/compiler/checker-source-file.ts +1 -1
- package/src/compiler/checker-type-factory.ts +67 -21
- package/src/compiler/checker-type-nodes.ts +5 -5
- package/src/compiler/checker-unused.ts +13 -8
- package/src/compiler/checker.ts +15 -4
- package/src/compiler/compile-program.ts +8 -0
- package/src/compiler/decoder.ts +2 -1
- package/src/compiler/doctor-report.ts +133 -0
- package/src/compiler/expr-record.ts +59 -0
- package/src/compiler/file-loader.ts +8 -0
- package/src/compiler/identifier-name.ts +13 -0
- package/src/compiler/jsdoc.ts +4 -2
- package/src/compiler/parallel-check.ts +364 -146
- package/src/compiler/parallel-emit.ts +3 -3
- package/src/compiler/parse-thread.ts +24 -2
- package/src/compiler/parser.ts +10 -8
- package/src/compiler/printer/factory.ts +3 -2
- package/src/compiler/printer/printer.ts +4 -2
- package/src/compiler/program-checker.ts +28 -0
- package/src/compiler/reparser.ts +7 -3
- package/src/compiler/run-config.ts +1383 -0
- package/src/compiler/run-record-read.ts +87 -0
- package/src/compiler/run-records.ts +575 -0
- package/src/compiler/scanner.ts +57 -41
- package/src/compiler/shared-results.ts +1626 -896
- package/src/compiler/thread-entry.ts +3 -1
- package/src/compiler/transformers/declarations.ts +2 -1
- package/src/compiler/tsc-build.ts +64 -6
- package/src/compiler/tsc-cli.ts +33 -4
- package/src/compiler/tsc-compile.ts +223 -9
- package/src/compiler/tsc-watch.ts +25 -4
|
@@ -15,12 +15,12 @@
|
|
|
15
15
|
* thread's checker finds every diagnostic but those of declaration emit.
|
|
16
16
|
*/
|
|
17
17
|
import type { Worker } from 'node:worker_threads';
|
|
18
|
-
import { availableParallelism } from 'node:os';
|
|
19
18
|
import { publish } from '@scriptc/threads';
|
|
20
19
|
import { lastNodeIdValue, type SourceFile } from './ast.js';
|
|
21
20
|
import { JavaScriptEmitter, type OutputWriter } from './compile-program.js';
|
|
22
21
|
import type { Diagnostic, DiagnosticFile } from './diagnostics.js';
|
|
23
22
|
import { EmitOnly, EmitResult, sourceFileMayBeEmitted } from './emitter.js';
|
|
23
|
+
import { availableCpus } from './cgroup.js';
|
|
24
24
|
import {
|
|
25
25
|
CheckerResult,
|
|
26
26
|
packResult,
|
|
@@ -78,7 +78,7 @@ export function emitThreads(
|
|
|
78
78
|
emitKinds: readonly number[] | undefined = undefined,
|
|
79
79
|
): number {
|
|
80
80
|
if (parallelEmit.spawn === undefined || singleThreaded === true) return 0;
|
|
81
|
-
const cpus =
|
|
81
|
+
const cpus = availableCpus();
|
|
82
82
|
if (cpus < 2) return 0;
|
|
83
83
|
const files = program.getSourceFiles();
|
|
84
84
|
let text = 0;
|
|
@@ -220,7 +220,7 @@ const maxDeclarationThreadCheckers = 8;
|
|
|
220
220
|
* from 1 to 8 checkers, about even at 12, and 32-38% slower at 16. It also needs a CPU of its own.
|
|
221
221
|
*/
|
|
222
222
|
export function declarationThreadPays(checkers: number): boolean {
|
|
223
|
-
return checkers <= maxDeclarationThreadCheckers && checkers <
|
|
223
|
+
return checkers <= maxDeclarationThreadCheckers && checkers < availableCpus();
|
|
224
224
|
}
|
|
225
225
|
|
|
226
226
|
/**
|
|
@@ -6,10 +6,11 @@
|
|
|
6
6
|
import { publish } from '@scriptc/threads';
|
|
7
7
|
import { type ExternalModuleIndicatorOptions, ParseOptions, ScriptKind, type SourceFile } from './ast.js';
|
|
8
8
|
import { bindSourceFile } from './binder.js';
|
|
9
|
+
import { checkGrammarSourceFileInParseThread } from './checker-grammar.js';
|
|
9
10
|
import { useThreadTextCaches } from './diagnostics.js';
|
|
10
11
|
import { CompilerHost, FileLoader } from './file-loader.js';
|
|
11
12
|
import { computeHash } from './incremental.js';
|
|
12
|
-
import { isIncremental } from './options.js';
|
|
13
|
+
import { type CompilerOptions, isIncremental } from './options.js';
|
|
13
14
|
import type { FileSystem } from './file-system.js';
|
|
14
15
|
import {
|
|
15
16
|
fileSize,
|
|
@@ -29,6 +30,18 @@ class PreparingHost extends CompilerHost {
|
|
|
29
30
|
prepared: PreparedFile[] = [];
|
|
30
31
|
/** Whether the files' build info versions are computed (an incremental program). */
|
|
31
32
|
computesVersions = false;
|
|
33
|
+
/**
|
|
34
|
+
* Whether the files the loader parses here run their grammar checks before they are published. The
|
|
35
|
+
* walk is the checker's, run off the checking threads (checker-grammar.ts).
|
|
36
|
+
*/
|
|
37
|
+
grammarChecks = true;
|
|
38
|
+
/** The program's options, which the grammar checks of a file are given. */
|
|
39
|
+
readonly options: CompilerOptions;
|
|
40
|
+
|
|
41
|
+
constructor(fs: FileSystem, currentDirectory: string, defaultLibraryPath: string, options: CompilerOptions) {
|
|
42
|
+
super(fs, currentDirectory, defaultLibraryPath);
|
|
43
|
+
this.options = options;
|
|
44
|
+
}
|
|
32
45
|
readMs = 0;
|
|
33
46
|
parseMs = 0;
|
|
34
47
|
bindMs = 0;
|
|
@@ -49,6 +62,12 @@ class PreparingHost extends CompilerHost {
|
|
|
49
62
|
);
|
|
50
63
|
const t2 = timeline ? performance.now() : 0;
|
|
51
64
|
bindSourceFile(file);
|
|
65
|
+
// The checker does not check the declaration files `skipLibCheck` names, so it does not walk their
|
|
66
|
+
// grammar either. The walk reads the metadata the loader computed for the file, which is the one the
|
|
67
|
+
// checking thread reads it with, so it looks up no package.json the load has not looked up.
|
|
68
|
+
const metadata = this.loadingSourceFileMetadata;
|
|
69
|
+
if (this.grammarChecks && metadata !== undefined && !(this.options.skipLibCheck === true && file.isDeclarationFile))
|
|
70
|
+
checkGrammarSourceFileInParseThread(file, this.options, metadata);
|
|
52
71
|
// Published now, while its nodes are in cache: the chunk's publish (`ParseThread.load`) then skips
|
|
53
72
|
// them, where walking the whole chunk's files at once reads each node from memory again.
|
|
54
73
|
publish(file);
|
|
@@ -85,11 +104,14 @@ export class ParseThread {
|
|
|
85
104
|
private sentPackageJsons = 0;
|
|
86
105
|
|
|
87
106
|
constructor(config: ParsedCommandLine, fs: FileSystem, currentDirectory: string, defaultLibraryPath: string) {
|
|
88
|
-
this.host = new PreparingHost(fs, currentDirectory, defaultLibraryPath);
|
|
107
|
+
this.host = new PreparingHost(fs, currentDirectory, defaultLibraryPath, config.options);
|
|
89
108
|
// The versions of an incremental program's files are computed here rather than one after another
|
|
90
109
|
// on the main thread (programToSnapshot, incremental.ts).
|
|
91
110
|
this.host.computesVersions = isIncremental(config.options);
|
|
92
111
|
this.loader = new FileLoader(this.host, config);
|
|
112
|
+
// A program that does not check has no grammar diagnostics to report. An incremental program checks
|
|
113
|
+
// the files a change affects and parses all of them, so the walk stays with the checker there.
|
|
114
|
+
this.host.grammarChecks = config.options.noCheck !== true && !isIncremental(config.options);
|
|
93
115
|
// The files this thread loads are published with their chunk: text caches it computes later (of
|
|
94
116
|
// declaration files, which the parser leaves out) go to copies.
|
|
95
117
|
useThreadTextCaches();
|
package/src/compiler/parser.ts
CHANGED
|
@@ -202,6 +202,7 @@ import {
|
|
|
202
202
|
newCallExpression,
|
|
203
203
|
newPropertyAssignment,
|
|
204
204
|
} from './ast.js';
|
|
205
|
+
import { IdentifierName } from './identifier-name.js';
|
|
205
206
|
import {
|
|
206
207
|
OperatorPrecedence,
|
|
207
208
|
canHaveDecorators,
|
|
@@ -3038,7 +3039,7 @@ export class Parser extends ScannerErrorReporter {
|
|
|
3038
3039
|
identifierName = name;
|
|
3039
3040
|
} else {
|
|
3040
3041
|
this.parseErrorAt(skipTrivia(this.sourceText, name.pos), name.end, Diagnostics.Identifier_expected);
|
|
3041
|
-
identifierName = this.newIdentifier('');
|
|
3042
|
+
identifierName = this.newIdentifier(new IdentifierName(''));
|
|
3042
3043
|
this.finishNode(identifierName, name.pos);
|
|
3043
3044
|
}
|
|
3044
3045
|
return this.checkJSSyntax(this.finishNode(new ImportSpecifier(isTypeOnly, propertyName, identifierName), pos));
|
|
@@ -3559,12 +3560,12 @@ export class Parser extends ScannerErrorReporter {
|
|
|
3559
3560
|
* A new identifier of the class `use` calls for. Callers create it after the identifier's token, so
|
|
3560
3561
|
* for an element name the current token tells a shorthand property from an assignment or a method.
|
|
3561
3562
|
*/
|
|
3562
|
-
newIdentifier(
|
|
3563
|
+
newIdentifier(name: IdentifierName, use: IdentifierUse = IdentifierUse.Reference): Identifier {
|
|
3563
3564
|
this.identifierCount++;
|
|
3564
|
-
if (text === 'await') this.statementHasAwaitIdentifier = true;
|
|
3565
|
+
if (name.text === 'await') this.statementHasAwaitIdentifier = true;
|
|
3565
3566
|
if (use === IdentifierUse.Name || (use === IdentifierUse.ElementName && this.isElementNameEnd()))
|
|
3566
|
-
return new Identifier(
|
|
3567
|
-
return new ReferenceIdentifier(
|
|
3567
|
+
return new Identifier(name);
|
|
3568
|
+
return new ReferenceIdentifier(name);
|
|
3568
3569
|
}
|
|
3569
3570
|
|
|
3570
3571
|
/** Whether the current token ends an object literal element name that is not a shorthand property. */
|
|
@@ -3574,7 +3575,7 @@ export class Parser extends ScannerErrorReporter {
|
|
|
3574
3575
|
}
|
|
3575
3576
|
|
|
3576
3577
|
createMissingIdentifier(use: IdentifierUse = IdentifierUse.Reference): Identifier {
|
|
3577
|
-
const result = this.newIdentifier('', use);
|
|
3578
|
+
const result = this.newIdentifier(new IdentifierName(''), use);
|
|
3578
3579
|
this.finishNode(result, this.nodePos());
|
|
3579
3580
|
return result;
|
|
3580
3581
|
}
|
|
@@ -4971,7 +4972,7 @@ export class Parser extends ScannerErrorReporter {
|
|
|
4971
4972
|
// An unclosed opening element took its parent's closing element: restructure
|
|
4972
4973
|
// (<div>(...<span>...</div>)) into (<div>(...<span>...</>)</div>). The parent reports it.
|
|
4973
4974
|
const end = (lastChild as JsxElement).children.end;
|
|
4974
|
-
const missingIdentifier = this.finishNodeWithEnd(this.newIdentifier(''), end, end);
|
|
4975
|
+
const missingIdentifier = this.finishNodeWithEnd(this.newIdentifier(new IdentifierName('')), end, end);
|
|
4975
4976
|
const newClosingElement = new JsxClosingElement(missingIdentifier);
|
|
4976
4977
|
this.finishNodeWithEnd(newClosingElement, end, end);
|
|
4977
4978
|
const newLast = new JsxElement(
|
|
@@ -6091,10 +6092,11 @@ export class Parser extends ScannerErrorReporter {
|
|
|
6091
6092
|
if (isIdentifier) {
|
|
6092
6093
|
const pos = this.scanner.hasPrecedingJSDocLeadingAsterisks() ? this.scanner.getTokenStart() : this.nodePos();
|
|
6093
6094
|
const text = this.scanner.getIdentifierValue();
|
|
6095
|
+
const name = this.scanner.getIdentifierName();
|
|
6094
6096
|
const record = this.scanner.recordIdentifierValue(text);
|
|
6095
6097
|
this.nextTokenWithoutCheck();
|
|
6096
6098
|
if (record) this.identifierTexts.push(text);
|
|
6097
|
-
const result = this.newIdentifier(
|
|
6099
|
+
const result = this.newIdentifier(name, use);
|
|
6098
6100
|
this.finishNode(result, pos);
|
|
6099
6101
|
return result;
|
|
6100
6102
|
}
|
|
@@ -70,6 +70,7 @@ import {
|
|
|
70
70
|
} from './helpers.js';
|
|
71
71
|
import { formatGeneratedName, isMemberName, nodeIsSynthesized } from './utilities.js';
|
|
72
72
|
import { OuterExpressionKinds, isOuterExpression, outerExpressionOperand } from '../transformers/utilities.js';
|
|
73
|
+
import { IdentifierName } from '../identifier-name.js';
|
|
73
74
|
|
|
74
75
|
/**
|
|
75
76
|
* The node factory of an emit context. The context is the factory (`EmitContext` extends it), so the two are one
|
|
@@ -108,7 +109,7 @@ export abstract class NodeFactory extends NodeFactoryBase {
|
|
|
108
109
|
}
|
|
109
110
|
|
|
110
111
|
cloneIdentifier(node: Identifier): Identifier {
|
|
111
|
-
return this.cloneNode(node, new Identifier(node.
|
|
112
|
+
return this.cloneNode(node, new Identifier(node.identifierName));
|
|
112
113
|
}
|
|
113
114
|
|
|
114
115
|
createNodeList(nodes: Node[]): NodeList {
|
|
@@ -132,7 +133,7 @@ export abstract class NodeFactory extends NodeFactoryBase {
|
|
|
132
133
|
}
|
|
133
134
|
|
|
134
135
|
createIdentifier(text: string): Identifier {
|
|
135
|
-
return this.created(new Identifier(text));
|
|
136
|
+
return this.created(new Identifier(new IdentifierName(text)));
|
|
136
137
|
}
|
|
137
138
|
|
|
138
139
|
createKeywordExpression(kind: SyntaxKind): KeywordExpression {
|
|
@@ -660,7 +660,8 @@ export class Printer extends NameGeneratorHost {
|
|
|
660
660
|
case SyntaxKind.PrivateIdentifier:
|
|
661
661
|
case SyntaxKind.JsxNamespacedName:
|
|
662
662
|
// Its text either way: the source text, or the text of a node from elsewhere.
|
|
663
|
-
if (this.textIsSourceText(node))
|
|
663
|
+
if (this.textIsSourceText(node))
|
|
664
|
+
return node instanceof Identifier ? node.text : (node as PrivateIdentifier).text;
|
|
664
665
|
if (!canUseSourceFile || !this.isInCurrentSourceFile(node)) {
|
|
665
666
|
if (node instanceof Identifier) return node.text;
|
|
666
667
|
if (node instanceof PrivateIdentifier) return node.text;
|
|
@@ -691,7 +692,8 @@ export class Printer extends NameGeneratorHost {
|
|
|
691
692
|
if (!(node instanceof Identifier) && !(node instanceof PrivateIdentifier)) return false;
|
|
692
693
|
if ((node.flags & (NodeFlags.Reparsed | NodeFlags.JSDoc | NodeFlags.ReparserTransformedLiteral)) !== 0)
|
|
693
694
|
return false;
|
|
694
|
-
|
|
695
|
+
// Natively an identifier's text is read through its name, and a private identifier's from its field.
|
|
696
|
+
const text = node instanceof Identifier ? node.text : (node as PrivateIdentifier).text;
|
|
695
697
|
const source = this.sourceText;
|
|
696
698
|
const end = node.end;
|
|
697
699
|
const start = end - text.length;
|
|
@@ -248,6 +248,28 @@ export class CheckedProgram {
|
|
|
248
248
|
this.reportingChecker = undefined;
|
|
249
249
|
}
|
|
250
250
|
|
|
251
|
+
/** Adds the counts a checker thread sent (`CheckerResult.counts`): types, instantiations, symbols. */
|
|
252
|
+
addCheckerCounts(counts: readonly number[]): void {
|
|
253
|
+
if (counts.length < 3) return;
|
|
254
|
+
this.threadTypeCount += counts[0]!;
|
|
255
|
+
this.threadInstantiations += counts[1]!;
|
|
256
|
+
this.threadSymbolCount += counts[2]!;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
/**
|
|
260
|
+
* The types, instantiations and transient symbols of every checker of the program: this thread's and
|
|
261
|
+
* the checker threads', as tsgo's `Program.TypeCount`, `InstantiationCount` and `SymbolCount` add them up.
|
|
262
|
+
* Reading them doesn't create this thread's checker.
|
|
263
|
+
*/
|
|
264
|
+
checkerCounts(): { types: number; instantiations: number; symbols: number } {
|
|
265
|
+
const own = this.reportingChecker;
|
|
266
|
+
return {
|
|
267
|
+
types: (own === undefined ? 0 : own.typeCount) + this.threadTypeCount,
|
|
268
|
+
instantiations: (own === undefined ? 0 : own.totalInstantiations) + this.threadInstantiations,
|
|
269
|
+
symbols: (own === undefined ? 0 : own.symbolCount) + this.threadSymbolCount,
|
|
270
|
+
};
|
|
271
|
+
}
|
|
272
|
+
|
|
251
273
|
getBindDiagnostics(file: SourceFile | undefined): Diagnostic[] {
|
|
252
274
|
return this.collect(file, (f) => f.bindDiagnostics);
|
|
253
275
|
}
|
|
@@ -272,6 +294,12 @@ export class CheckedProgram {
|
|
|
272
294
|
*/
|
|
273
295
|
referenceThreads = 1;
|
|
274
296
|
readonly parallelGlobalDiagnostics: Diagnostic[] = [];
|
|
297
|
+
/** The types checker threads created (`CheckerResult.counts`), which `--diagnostics` adds to `checker`'s. */
|
|
298
|
+
threadTypeCount = 0;
|
|
299
|
+
/** The instantiations checker threads made. */
|
|
300
|
+
threadInstantiations = 0;
|
|
301
|
+
/** The transient symbols checker threads created. */
|
|
302
|
+
threadSymbolCount = 0;
|
|
275
303
|
/**
|
|
276
304
|
* Whether the semantic diagnostics of a file include the global diagnostics its checker found while
|
|
277
305
|
* checking it, as an incremental program caches them (IncrementalProgram). Such a program doesn't report
|
package/src/compiler/reparser.ts
CHANGED
|
@@ -98,6 +98,7 @@ import { Diagnostics } from './diagnostic-messages.js';
|
|
|
98
98
|
import type { Parser } from './parser.js';
|
|
99
99
|
import { SyntaxKind } from './syntax-kind.js';
|
|
100
100
|
import { TokenFlags } from './types.js';
|
|
101
|
+
import { IdentifierName } from './identifier-name.js';
|
|
101
102
|
|
|
102
103
|
/** Sets the parent of every node in a subtree. */
|
|
103
104
|
class ParentInChildrenSetter extends NodeVisitor {
|
|
@@ -360,7 +361,7 @@ export class Reparser {
|
|
|
360
361
|
const param = params[pi]!;
|
|
361
362
|
let parameter: ParameterDeclaration;
|
|
362
363
|
if (param instanceof JSDocThisTag) {
|
|
363
|
-
const thisIdent = new Identifier('this');
|
|
364
|
+
const thisIdent = new Identifier(new IdentifierName('this'));
|
|
364
365
|
thisIdent.pos = (param as JSDocThisTag).pos;
|
|
365
366
|
thisIdent.end = (param as JSDocThisTag).end;
|
|
366
367
|
thisIdent.flags = p.contextFlags | NodeFlags.Reparsed;
|
|
@@ -387,7 +388,10 @@ export class Reparser {
|
|
|
387
388
|
let name: Node = (param as JSDocParameterOrPropertyTag).name;
|
|
388
389
|
if (name instanceof Identifier && !isValidIdentifier((name as Identifier).text)) {
|
|
389
390
|
// Replace invalid characters with `_`, or use `_N` for an empty name, for a valid parameter name.
|
|
390
|
-
name = this.addTransformedReparse(
|
|
391
|
+
name = this.addTransformedReparse(
|
|
392
|
+
new Identifier(new IdentifierName(sanitizeIdentifier((name as Identifier).text, pi))),
|
|
393
|
+
name,
|
|
394
|
+
);
|
|
391
395
|
} else {
|
|
392
396
|
name = this.addDeepCloneReparse(name);
|
|
393
397
|
}
|
|
@@ -611,7 +615,7 @@ export class Reparser {
|
|
|
611
615
|
const thisParam = new ParameterDeclaration(
|
|
612
616
|
undefined,
|
|
613
617
|
undefined,
|
|
614
|
-
new Identifier('this'),
|
|
618
|
+
new Identifier(new IdentifierName('this')),
|
|
615
619
|
undefined,
|
|
616
620
|
undefined,
|
|
617
621
|
undefined,
|