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
|
@@ -14,6 +14,7 @@ import { DiagnosticContext, canProduceDiagnostics, createDiagnosticForNode, decl
|
|
|
14
14
|
import { DeclarationTracker } from './declarations-tracker.js';
|
|
15
15
|
import { Transformer } from './transformer.js';
|
|
16
16
|
import { declarationCount, getDeclarations } from '../symbol.js';
|
|
17
|
+
import { IdentifierName } from '../identifier-name.js';
|
|
17
18
|
export class DeclarationTransformer extends Transformer {
|
|
18
19
|
host;
|
|
19
20
|
options;
|
|
@@ -1357,7 +1358,7 @@ export class DeclarationTransformer extends Transformer {
|
|
|
1357
1358
|
keyword === 79 /* SyntaxKind.Identifier */ ||
|
|
1358
1359
|
keyword === 89 /* SyntaxKind.DefaultKeyword */) {
|
|
1359
1360
|
// A parse tree node, so names it uses are resolved where it's written.
|
|
1360
|
-
const identifier = new Identifier(text);
|
|
1361
|
+
const identifier = new Identifier(new IdentifierName(text));
|
|
1361
1362
|
identifier.parent = name.parent;
|
|
1362
1363
|
return identifier;
|
|
1363
1364
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tsc-ts",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"description": "The TypeScript 7 compiler, ported to TypeScript and compiled to a native executable.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"repository": {
|
|
@@ -28,19 +28,24 @@
|
|
|
28
28
|
},
|
|
29
29
|
"./package.json": "./package.json"
|
|
30
30
|
},
|
|
31
|
-
"
|
|
32
|
-
"@scriptc/threads": "0.4.
|
|
31
|
+
"peerDependencies": {
|
|
32
|
+
"@scriptc/threads": "0.4.8"
|
|
33
|
+
},
|
|
34
|
+
"peerDependenciesMeta": {
|
|
35
|
+
"@scriptc/threads": {
|
|
36
|
+
"optional": true
|
|
37
|
+
}
|
|
33
38
|
},
|
|
34
39
|
"engines": {
|
|
35
40
|
"node": ">=20"
|
|
36
41
|
},
|
|
37
42
|
"optionalDependencies": {
|
|
38
|
-
"@tsc-ts/darwin-arm64": "0.1.
|
|
39
|
-
"@tsc-ts/darwin-x64": "0.1.
|
|
40
|
-
"@tsc-ts/linux-arm64-gnu": "0.1.
|
|
41
|
-
"@tsc-ts/linux-arm64-musl": "0.1.
|
|
42
|
-
"@tsc-ts/linux-x64-gnu": "0.1.
|
|
43
|
-
"@tsc-ts/linux-x64-musl": "0.1.
|
|
44
|
-
"@tsc-ts/win32-x64-msvc": "0.1.
|
|
43
|
+
"@tsc-ts/darwin-arm64": "0.1.2",
|
|
44
|
+
"@tsc-ts/darwin-x64": "0.1.2",
|
|
45
|
+
"@tsc-ts/linux-arm64-gnu": "0.1.2",
|
|
46
|
+
"@tsc-ts/linux-arm64-musl": "0.1.2",
|
|
47
|
+
"@tsc-ts/linux-x64-gnu": "0.1.2",
|
|
48
|
+
"@tsc-ts/linux-x64-musl": "0.1.2",
|
|
49
|
+
"@tsc-ts/win32-x64-msvc": "0.1.2"
|
|
45
50
|
}
|
|
46
51
|
}
|
package/src/compiler/ast.ts
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
// Every node extends `Node`. Child fields are typed by category (`Expression`, `TypeNode`, …),
|
|
4
4
|
// which are aliases of `Node`; narrow with the `is*` guards in ast-utilities.ts or `instanceof`.
|
|
5
5
|
import type { ProgramLifetime } from '@scriptc/types';
|
|
6
|
+
import { IdentifierName } from './identifier-name.js';
|
|
6
7
|
import { SyntaxKind } from './syntax-kind.js';
|
|
7
8
|
import { type CommentDirective, type CommentRange, type LanguageVariant, TokenFlags } from './types.js';
|
|
8
9
|
import { type Diagnostic, DiagnosticFile } from './diagnostics.js';
|
|
@@ -208,9 +209,14 @@ export abstract class NodeVisitor {
|
|
|
208
209
|
}
|
|
209
210
|
}
|
|
210
211
|
|
|
211
|
-
// Native builds store `pos`, `end` and `id` as 32-bit integers when every write provably stores
|
|
212
|
-
// int32, so writes of values the compiler can't bound (parameters, the id counter) are
|
|
213
|
-
// with `| 0`; the values are always int32.
|
|
212
|
+
// Native builds store `pos`, `end` and `id` as 32-bit integers when every write provably stores
|
|
213
|
+
// an int32, so writes of values the compiler can't bound (parameters, the id counter) are
|
|
214
|
+
// coerced with `| 0`; the values are always int32.
|
|
215
|
+
//
|
|
216
|
+
// The fields of a node that the public API's node types declare are stored fields, not values
|
|
217
|
+
// computed from or packed into another field: a native build copies the stored fields of a node
|
|
218
|
+
// into a record when API code narrows one (`node as StringLiteralLike`), and a field behind an
|
|
219
|
+
// accessor is not copied.
|
|
214
220
|
export abstract class Node implements ProgramLifetime {
|
|
215
221
|
readonly kind: SyntaxKind;
|
|
216
222
|
flags: NodeFlags;
|
|
@@ -449,11 +455,15 @@ export class Token extends Node {
|
|
|
449
455
|
}
|
|
450
456
|
|
|
451
457
|
export class Identifier extends Node {
|
|
452
|
-
|
|
458
|
+
readonly identifierName: IdentifierName;
|
|
453
459
|
|
|
454
|
-
constructor(
|
|
460
|
+
constructor(name: IdentifierName) {
|
|
455
461
|
super(SyntaxKind.Identifier);
|
|
456
|
-
this.
|
|
462
|
+
this.identifierName = name;
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
get text(): string {
|
|
466
|
+
return this.identifierName.text;
|
|
457
467
|
}
|
|
458
468
|
|
|
459
469
|
forEachChild(_v: NodeVisitor): boolean {
|
|
@@ -467,7 +477,7 @@ export class Identifier extends Node {
|
|
|
467
477
|
}
|
|
468
478
|
|
|
469
479
|
copy(): Identifier {
|
|
470
|
-
const node = new Identifier(this.
|
|
480
|
+
const node = new Identifier(this.identifierName);
|
|
471
481
|
node.flags = this.flags;
|
|
472
482
|
node.pos = this.pos;
|
|
473
483
|
node.end = this.end;
|
|
@@ -484,13 +494,13 @@ export class ReferenceIdentifier extends Identifier {
|
|
|
484
494
|
// Set by the binder.
|
|
485
495
|
flowNode: FlowNode | undefined;
|
|
486
496
|
|
|
487
|
-
constructor(
|
|
488
|
-
super(
|
|
497
|
+
constructor(name: IdentifierName) {
|
|
498
|
+
super(name);
|
|
489
499
|
this.flowNode = undefined;
|
|
490
500
|
}
|
|
491
501
|
|
|
492
502
|
copy(): Identifier {
|
|
493
|
-
const node = new ReferenceIdentifier(this.
|
|
503
|
+
const node = new ReferenceIdentifier(this.identifierName);
|
|
494
504
|
node.flags = this.flags;
|
|
495
505
|
node.pos = this.pos;
|
|
496
506
|
node.end = this.end;
|
|
@@ -8239,6 +8249,7 @@ export const emptyCommentDirectives: readonly CommentDirective[] = [];
|
|
|
8239
8249
|
export const emptyPragmas: readonly Pragma[] = [];
|
|
8240
8250
|
export const emptyFileReferences: readonly FileReference[] = [];
|
|
8241
8251
|
export const emptyPatternAmbientModules: readonly PatternAmbientModule[] = [];
|
|
8252
|
+
const emptyNumbers: readonly number[] = [];
|
|
8242
8253
|
|
|
8243
8254
|
/** `list` with `item` appended: a new array when `list` is empty (it may be shared), else `list` itself. */
|
|
8244
8255
|
export function appendToList<T>(list: readonly T[], item: T): readonly T[] {
|
|
@@ -8315,6 +8326,14 @@ export class SourceFile extends Node {
|
|
|
8315
8326
|
/** UMD exports from `export as namespace N`. */
|
|
8316
8327
|
globalExports: SymbolTable | undefined;
|
|
8317
8328
|
|
|
8329
|
+
// Set by the grammar checks of a parse thread (checker-grammar.ts).
|
|
8330
|
+
/** The diagnostics the parse thread's grammar walk reported for this file. */
|
|
8331
|
+
grammarDiagnostics: Diagnostic[] | undefined;
|
|
8332
|
+
/** The nodes of this file whose grammar check needs the checker, in tree order. */
|
|
8333
|
+
grammarResidualNodes: Node[] | undefined;
|
|
8334
|
+
/** The blocks and statements that reported a statement in an ambient context. */
|
|
8335
|
+
grammarAmbientReports: readonly number[];
|
|
8336
|
+
|
|
8318
8337
|
constructor(
|
|
8319
8338
|
fileName: string,
|
|
8320
8339
|
path: string,
|
|
@@ -8368,6 +8387,9 @@ export class SourceFile extends Node {
|
|
|
8368
8387
|
this.symbolCount = 0;
|
|
8369
8388
|
this.patternAmbientModules = emptyPatternAmbientModules;
|
|
8370
8389
|
this.globalExports = undefined;
|
|
8390
|
+
this.grammarDiagnostics = undefined;
|
|
8391
|
+
this.grammarResidualNodes = undefined;
|
|
8392
|
+
this.grammarAmbientReports = emptyNumbers;
|
|
8371
8393
|
}
|
|
8372
8394
|
|
|
8373
8395
|
forEachChild(v: NodeVisitor): boolean {
|
|
@@ -8417,20 +8439,22 @@ export class PatternAmbientModule {
|
|
|
8417
8439
|
readonly text: string;
|
|
8418
8440
|
readonly starIndex: number;
|
|
8419
8441
|
readonly symbol: Symbol;
|
|
8442
|
+
/** The part of `text` before `starIndex`, kept so a match does not copy it. */
|
|
8443
|
+
readonly prefix: string;
|
|
8444
|
+
/** The part of `text` after `starIndex`, kept so a match does not copy it. */
|
|
8445
|
+
readonly suffix: string;
|
|
8420
8446
|
|
|
8421
8447
|
constructor(text: string, starIndex: number, symbol: Symbol) {
|
|
8422
8448
|
this.text = text;
|
|
8423
8449
|
this.starIndex = starIndex;
|
|
8424
8450
|
this.symbol = symbol;
|
|
8451
|
+
this.prefix = text.substring(0, starIndex);
|
|
8452
|
+
this.suffix = text.substring(starIndex + 1);
|
|
8425
8453
|
}
|
|
8426
8454
|
|
|
8427
8455
|
matches(candidate: string): boolean {
|
|
8428
|
-
const text = this.text;
|
|
8429
|
-
const star = this.starIndex;
|
|
8430
8456
|
return (
|
|
8431
|
-
candidate.length >= text.length - 1 &&
|
|
8432
|
-
candidate.startsWith(text.substring(0, star)) &&
|
|
8433
|
-
candidate.endsWith(text.substring(star + 1))
|
|
8457
|
+
candidate.length >= this.text.length - 1 && candidate.startsWith(this.prefix) && candidate.endsWith(this.suffix)
|
|
8434
8458
|
);
|
|
8435
8459
|
}
|
|
8436
8460
|
}
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
// The limits the process's cgroup puts on the machine a run sees: the whole CPUs its CPU quota allows
|
|
2
|
+
// and the smallest memory limit of its cgroup and that cgroup's ancestors. `os.availableParallelism()`
|
|
3
|
+
// already lowers its count to a quota of one CPU or more; the native runtime's count ignores a quota
|
|
4
|
+
// below one, which truncates to no CPUs there and falls back to the affinity mask, so the quota is read
|
|
5
|
+
// here too. The memory limit only sometimes reaches `process.constrainedMemory()` (libuv reads the
|
|
6
|
+
// process's own cgroup, and scriptc's runtime only the root of the cgroup mount, which is the process's
|
|
7
|
+
// own cgroup only inside a cgroup namespace).
|
|
8
|
+
import { readFileSync } from 'node:fs';
|
|
9
|
+
import { availableParallelism } from 'node:os';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* The CPUs this process may run on: `os.availableParallelism()`, lowered to the whole CPUs its cgroup
|
|
13
|
+
* quota allows (`cgroupCpuQuota`). Where the runtime already applies the quota this returns the same
|
|
14
|
+
* count; a quota below one CPU, which the native runtime's count ignores, lowers it to one. The text and
|
|
15
|
+
* root parameters are for the tests.
|
|
16
|
+
*/
|
|
17
|
+
export function availableCpus(membershipText: string = readMembership(), root: string = '/sys/fs/cgroup'): number {
|
|
18
|
+
const cpus = Math.max(1, availableParallelism());
|
|
19
|
+
const quota = cgroupCpuQuota(membershipText, root);
|
|
20
|
+
return quota > 0 && quota < cpus ? quota : cpus;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* The whole CPUs this process's cgroup and its ancestors allow, or 0 where there is none or it is
|
|
25
|
+
* unknown: `cpu.max` under cgroup v2, `cpu.cfs_quota_us` and `cpu.cfs_period_us` under v1. A quota
|
|
26
|
+
* below one CPU counts as one, the least a run can use. The text and root parameters are for the tests.
|
|
27
|
+
*/
|
|
28
|
+
export function cgroupCpuQuota(membershipText: string = readMembership(), root: string = '/sys/fs/cgroup'): number {
|
|
29
|
+
let quota = 0;
|
|
30
|
+
const lower = (value: number): void => {
|
|
31
|
+
if (value > 0 && (quota === 0 || value < quota)) quota = value;
|
|
32
|
+
};
|
|
33
|
+
forEachCgroupDirectory(membershipText, root, '', (directory) => {
|
|
34
|
+
lower(cpuMaxValue(directory + '/cpu.max'));
|
|
35
|
+
});
|
|
36
|
+
forEachCgroupDirectory(membershipText, root, 'cpu', (directory) => {
|
|
37
|
+
// The kernel's default period, for a mount that lost the file but kept its quota.
|
|
38
|
+
const period = numberIn(directory + '/cpu.cfs_period_us') || 100_000;
|
|
39
|
+
lower(wholeCpus(numberIn(directory + '/cpu.cfs_quota_us'), period));
|
|
40
|
+
});
|
|
41
|
+
return quota;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* The smallest memory limit of this process's cgroup and its ancestors (Linux), or 0 where there is
|
|
46
|
+
* none or it is unknown: `memory.max` and `memory.high` under cgroup v2, `memory.limit_in_bytes` under
|
|
47
|
+
* v1. The text and root parameters are for the tests.
|
|
48
|
+
*/
|
|
49
|
+
export function cgroupMemoryLimit(membershipText: string = readMembership(), root: string = '/sys/fs/cgroup'): number {
|
|
50
|
+
let limit = 0;
|
|
51
|
+
const lower = (value: number): void => {
|
|
52
|
+
if (value > 0 && (limit === 0 || value < limit)) limit = value;
|
|
53
|
+
};
|
|
54
|
+
forEachCgroupDirectory(membershipText, root, '', (directory) => {
|
|
55
|
+
lower(memoryLimitValue(directory + '/memory.max'));
|
|
56
|
+
lower(memoryLimitValue(directory + '/memory.high'));
|
|
57
|
+
});
|
|
58
|
+
forEachCgroupDirectory(membershipText, root, 'memory', (directory) => {
|
|
59
|
+
lower(memoryLimitValue(directory + '/memory.limit_in_bytes'));
|
|
60
|
+
});
|
|
61
|
+
return limit;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Calls `visit` with the directory of this process's cgroup for `controller` and of each of its
|
|
66
|
+
* ancestors, deepest first: the unified hierarchy for `''` (cgroup v2, whose line lists no
|
|
67
|
+
* controllers), or the controller's own mount for a v1 line that lists it.
|
|
68
|
+
*/
|
|
69
|
+
function forEachCgroupDirectory(
|
|
70
|
+
membershipText: string,
|
|
71
|
+
root: string,
|
|
72
|
+
controller: string,
|
|
73
|
+
visit: (directory: string) => void,
|
|
74
|
+
): void {
|
|
75
|
+
for (const line of membershipText.split('\n')) {
|
|
76
|
+
// "0::/path" (v2), "N:cpu:/path" or "N:cpu,cpuacct:/path" (v1).
|
|
77
|
+
const first = line.indexOf(':');
|
|
78
|
+
const second = line.indexOf(':', first + 1);
|
|
79
|
+
if (first < 0 || second < 0) continue;
|
|
80
|
+
const controllers = line.substring(first + 1, second);
|
|
81
|
+
const path = line.substring(second + 1);
|
|
82
|
+
if (controller === '') {
|
|
83
|
+
if (controllers !== '') continue;
|
|
84
|
+
forEachAncestor(path, (directory) => visit(root + directory));
|
|
85
|
+
} else if (controllers.split(',').indexOf(controller) >= 0) {
|
|
86
|
+
forEachAncestor(path, (directory) => visit(root + '/' + controller + directory));
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Calls `visit` with `path` and each of its ancestors, deepest first ("/a/b/c", "/a/b", "/a", ""): a
|
|
93
|
+
* cgroup's limits apply to every process below it, in cgroup v1 as in v2.
|
|
94
|
+
*/
|
|
95
|
+
function forEachAncestor(path: string, visit: (directory: string) => void): void {
|
|
96
|
+
for (let directory = path; ; directory = directory.substring(0, directory.lastIndexOf('/'))) {
|
|
97
|
+
visit(directory === '/' ? '' : directory);
|
|
98
|
+
if (directory === '' || directory.lastIndexOf('/') < 0) break;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/** `/proc/self/cgroup`, or an empty text where it cannot be read (no cgroup limits). */
|
|
103
|
+
function readMembership(): string {
|
|
104
|
+
try {
|
|
105
|
+
return readFileSync('/proc/self/cgroup', 'utf8');
|
|
106
|
+
} catch {
|
|
107
|
+
return '';
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* The whole CPUs a cgroup v2 quota file allows, or 0 for `max`, an unreadable file or no number:
|
|
113
|
+
* `cpu.max` holds "MAX PERIOD" in microseconds.
|
|
114
|
+
*/
|
|
115
|
+
function cpuMaxValue(file: string): number {
|
|
116
|
+
let text: string;
|
|
117
|
+
try {
|
|
118
|
+
text = readFileSync(file, 'utf8').trim();
|
|
119
|
+
} catch {
|
|
120
|
+
return 0;
|
|
121
|
+
}
|
|
122
|
+
if (text === '' || text === 'max') return 0;
|
|
123
|
+
const parts = text.split(/\s+/).map(Number);
|
|
124
|
+
return wholeCpus(parts[0]!, parts[1] ?? 100_000);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/** A cgroup memory limit file's value in bytes, or 0 for `max`, an unreadable file or no number. */
|
|
128
|
+
function memoryLimitValue(file: string): number {
|
|
129
|
+
let text: string;
|
|
130
|
+
try {
|
|
131
|
+
text = readFileSync(file, 'utf8').trim();
|
|
132
|
+
} catch {
|
|
133
|
+
return 0;
|
|
134
|
+
}
|
|
135
|
+
if (text === '' || text === 'max') return 0;
|
|
136
|
+
const value = Number(text);
|
|
137
|
+
// cgroup v1 reports no limit as a page-aligned value near 2^63.
|
|
138
|
+
return Number.isFinite(value) && value > 0 && value < 2 ** 62 ? value : 0;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/** A file's number, or 0 where it cannot be read or holds none (a v1 quota of -1 is no quota). */
|
|
142
|
+
function numberIn(file: string): number {
|
|
143
|
+
let text: string;
|
|
144
|
+
try {
|
|
145
|
+
text = readFileSync(file, 'utf8').trim();
|
|
146
|
+
} catch {
|
|
147
|
+
return 0;
|
|
148
|
+
}
|
|
149
|
+
const value = Number(text);
|
|
150
|
+
return Number.isFinite(value) && value > 0 ? value : 0;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/** The whole CPUs `quota` microseconds per `period` microseconds allow, at least one where there is one. */
|
|
154
|
+
function wholeCpus(quota: number, period: number): number {
|
|
155
|
+
if (!Number.isFinite(quota) || !Number.isFinite(period) || quota <= 0 || period <= 0) return 0;
|
|
156
|
+
return Math.max(1, Math.floor(quota / period));
|
|
157
|
+
}
|
|
@@ -107,6 +107,7 @@ import {
|
|
|
107
107
|
} from './checker-heritage.js';
|
|
108
108
|
import { checkDecorators, getFirstTransformableStaticClassElement } from './checker-decorators.js';
|
|
109
109
|
import { getTypeOfNode } from './checker-services.js';
|
|
110
|
+
import { IdentifierName } from './identifier-name.js';
|
|
110
111
|
|
|
111
112
|
export function checkClassDeclaration(c: Checker, node: Node): void {
|
|
112
113
|
checkClassLikeDeclaration(c, node);
|
|
@@ -588,7 +589,7 @@ function newThisPropertyReference(symbol: Symbol, container: Node, flowNode: Flo
|
|
|
588
589
|
const name = symbol.name;
|
|
589
590
|
let accessName: Node;
|
|
590
591
|
if (name.startsWith('\ufffe#')) accessName = new PrivateIdentifier(name.substring(name.indexOf('@') + 1));
|
|
591
|
-
else accessName = new Identifier(name);
|
|
592
|
+
else accessName = new Identifier(new IdentifierName(name));
|
|
592
593
|
const thisExpression = new KeywordExpression(SyntaxKind.ThisKeyword);
|
|
593
594
|
const reference = new PropertyAccessExpression(thisExpression, undefined, accessName, NodeFlags.None);
|
|
594
595
|
thisExpression.parent = reference;
|
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
type Node,
|
|
8
8
|
type ParameterDeclaration,
|
|
9
9
|
type PropertyAssignment,
|
|
10
|
+
getArguments,
|
|
10
11
|
getInitializer,
|
|
11
12
|
getName,
|
|
12
13
|
getParameters,
|
|
@@ -224,6 +225,109 @@ export function findContextualNode(c: Checker, node: Node, includeCaches: boolea
|
|
|
224
225
|
return -1;
|
|
225
226
|
}
|
|
226
227
|
|
|
228
|
+
/**
|
|
229
|
+
* The id of the contextual type in force for `node`, or -1 if the node's contextual type is not on
|
|
230
|
+
* the stack. A key built from -1 can't tell a check under a contextual type that was not pushed from
|
|
231
|
+
* a check with no contextual type, so callers record nothing under -1.
|
|
232
|
+
*/
|
|
233
|
+
export function getContextualTypeId(c: Checker, node: Node): number {
|
|
234
|
+
const index = findContextualNode(c, node, true);
|
|
235
|
+
if (index < 0) return -1;
|
|
236
|
+
const t = c.inferenceCaches.contextualTypes[index];
|
|
237
|
+
return t === undefined ? -1 : t.id;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
/**
|
|
241
|
+
* Whether a check of `node` has no contextual type and no inference context, so its type is a
|
|
242
|
+
* function of the node and the check mode alone: the node is not on the contextual stack, no
|
|
243
|
+
* inference context contains it, and its parent gives it no contextual type. The parents answered
|
|
244
|
+
* here are the ones `getContextualTypeEx` returns `undefined` for without computing anything; a
|
|
245
|
+
* parent it computes a type for is not answered, so the result is never "yes" for a check that
|
|
246
|
+
* could have a contextual type.
|
|
247
|
+
*
|
|
248
|
+
* Types computed inside a flow loop are provisional (the checker does not cache them either), so a
|
|
249
|
+
* check in a loop is not context-free. The same holds while a reduce label is in force, as when
|
|
250
|
+
* flow analysis revisits a `finally` block with the antecedents of one outgoing path: the flow
|
|
251
|
+
* state differs from the one the earlier check of the block saw.
|
|
252
|
+
*/
|
|
253
|
+
export function isCheckedWithoutContextualType(c: Checker, node: Node): boolean {
|
|
254
|
+
if (c.flowLoopStack.length !== 0) return false;
|
|
255
|
+
if (c.flowReduceLabels.length !== 0) return false;
|
|
256
|
+
if (findContextualNode(c, node, true) >= 0) return false;
|
|
257
|
+
if (getInferenceContext(c, node) !== undefined) return false;
|
|
258
|
+
const parent = node.parent;
|
|
259
|
+
if (parent === undefined) return true;
|
|
260
|
+
switch (parent.kind) {
|
|
261
|
+
case SyntaxKind.VariableDeclaration:
|
|
262
|
+
case SyntaxKind.Parameter:
|
|
263
|
+
case SyntaxKind.PropertyDeclaration:
|
|
264
|
+
case SyntaxKind.PropertySignature:
|
|
265
|
+
case SyntaxKind.BindingElement:
|
|
266
|
+
// Only the initializer is contextually typed by the declaration.
|
|
267
|
+
return getInitializer(parent) !== node;
|
|
268
|
+
case SyntaxKind.CallExpression:
|
|
269
|
+
case SyntaxKind.NewExpression: {
|
|
270
|
+
// Only the arguments are contextually typed by the parameters; the callee is not.
|
|
271
|
+
const args = getArguments(parent);
|
|
272
|
+
if (args !== undefined) {
|
|
273
|
+
for (const arg of args.nodes) if (arg === node) return false;
|
|
274
|
+
}
|
|
275
|
+
return true;
|
|
276
|
+
}
|
|
277
|
+
case SyntaxKind.ObjectLiteralExpression:
|
|
278
|
+
// Only a method takes the property's contextual type.
|
|
279
|
+
return node.kind !== SyntaxKind.MethodDeclaration;
|
|
280
|
+
case SyntaxKind.BinaryExpression: {
|
|
281
|
+
const binary = parent as BinaryExpression;
|
|
282
|
+
if (binary.type !== undefined) return false;
|
|
283
|
+
switch (binary.operatorToken.kind) {
|
|
284
|
+
case SyntaxKind.EqualsToken:
|
|
285
|
+
case SyntaxKind.AmpersandAmpersandEqualsToken:
|
|
286
|
+
case SyntaxKind.BarBarEqualsToken:
|
|
287
|
+
case SyntaxKind.QuestionQuestionEqualsToken:
|
|
288
|
+
return node !== binary.right;
|
|
289
|
+
case SyntaxKind.BarBarToken:
|
|
290
|
+
case SyntaxKind.QuestionQuestionToken:
|
|
291
|
+
case SyntaxKind.AmpersandAmpersandToken:
|
|
292
|
+
case SyntaxKind.CommaToken:
|
|
293
|
+
return false;
|
|
294
|
+
}
|
|
295
|
+
return true;
|
|
296
|
+
}
|
|
297
|
+
case SyntaxKind.ConditionalExpression: {
|
|
298
|
+
const conditional = parent as ConditionalExpression;
|
|
299
|
+
return node !== conditional.whenTrue && node !== conditional.whenFalse;
|
|
300
|
+
}
|
|
301
|
+
case SyntaxKind.TemplateSpan: {
|
|
302
|
+
// Only a tagged template types its spans.
|
|
303
|
+
const template = parent.parent!;
|
|
304
|
+
return template.parent === undefined || template.parent.kind !== SyntaxKind.TaggedTemplateExpression;
|
|
305
|
+
}
|
|
306
|
+
case SyntaxKind.ArrowFunction:
|
|
307
|
+
case SyntaxKind.ReturnStatement:
|
|
308
|
+
case SyntaxKind.YieldExpression:
|
|
309
|
+
case SyntaxKind.AwaitExpression:
|
|
310
|
+
case SyntaxKind.Decorator:
|
|
311
|
+
case SyntaxKind.AsExpression:
|
|
312
|
+
case SyntaxKind.TypeAssertionExpression:
|
|
313
|
+
case SyntaxKind.SatisfiesExpression:
|
|
314
|
+
case SyntaxKind.ExportAssignment:
|
|
315
|
+
case SyntaxKind.PropertyAssignment:
|
|
316
|
+
case SyntaxKind.ShorthandPropertyAssignment:
|
|
317
|
+
case SyntaxKind.SpreadAssignment:
|
|
318
|
+
case SyntaxKind.ArrayLiteralExpression:
|
|
319
|
+
case SyntaxKind.ParenthesizedExpression:
|
|
320
|
+
case SyntaxKind.NonNullExpression:
|
|
321
|
+
case SyntaxKind.JsxExpression:
|
|
322
|
+
case SyntaxKind.JsxAttribute:
|
|
323
|
+
case SyntaxKind.JsxSpreadAttribute:
|
|
324
|
+
case SyntaxKind.JsxOpeningElement:
|
|
325
|
+
case SyntaxKind.JsxSelfClosingElement:
|
|
326
|
+
return false;
|
|
327
|
+
}
|
|
328
|
+
return true;
|
|
329
|
+
}
|
|
330
|
+
|
|
227
331
|
export function pushInferenceContext(c: Checker, node: Node, context: InferenceContext | undefined): void {
|
|
228
332
|
const caches = c.inferenceCaches;
|
|
229
333
|
const depth = caches.inferenceDepth;
|
|
@@ -238,7 +238,11 @@ import {
|
|
|
238
238
|
getNarrowedTypeOfSymbol,
|
|
239
239
|
} from './checker-narrowing.js';
|
|
240
240
|
import { getFlowTypeOfAutoTypedProperty, getThisTypeOfAssignedFunction } from './checker-javascript.js';
|
|
241
|
-
import {
|
|
241
|
+
import {
|
|
242
|
+
checkExpressionWithContextualType,
|
|
243
|
+
getThisTypeOfObjectLiteralMember,
|
|
244
|
+
isCheckedWithoutContextualType,
|
|
245
|
+
} from './checker-contextual.js';
|
|
242
246
|
|
|
243
247
|
import {
|
|
244
248
|
ContextFlags,
|
|
@@ -264,6 +268,16 @@ export function checkExpression(c: Checker, node: Node): Type {
|
|
|
264
268
|
}
|
|
265
269
|
|
|
266
270
|
export function checkExpressionEx(c: Checker, node: Node, checkMode: CheckMode): Type {
|
|
271
|
+
// A completed check of this node under this mode answers this one when the check has no
|
|
272
|
+
// contextual type and no inference context: the checker's state only grew since, so this check
|
|
273
|
+
// would produce the type the completed one produced, report the diagnostics it reported and
|
|
274
|
+
// defer the nodes it deferred. Those diagnostics are equal to ones already reported and a node
|
|
275
|
+
// is deferred at most once, so serving the completed type changes neither.
|
|
276
|
+
const recordable = isCheckedWithoutContextualType(c, node);
|
|
277
|
+
if (recordable) {
|
|
278
|
+
const recorded = c.exprCheckRecord.get(node.id, checkMode);
|
|
279
|
+
if (recorded !== undefined) return recorded;
|
|
280
|
+
}
|
|
267
281
|
const saveCurrentNode = c.currentNode;
|
|
268
282
|
c.currentNode = node;
|
|
269
283
|
c.instantiationCount = 0;
|
|
@@ -275,6 +289,7 @@ export function checkExpressionEx(c: Checker, node: Node, checkMode: CheckMode):
|
|
|
275
289
|
);
|
|
276
290
|
if (isConstEnumObjectTypeLocal(t)) checkConstEnumAccess(c, node, t);
|
|
277
291
|
c.currentNode = saveCurrentNode;
|
|
292
|
+
if (recordable) c.exprCheckRecord.set(node.id, checkMode, t);
|
|
278
293
|
return t;
|
|
279
294
|
}
|
|
280
295
|
|