Skip to content

Commit 058cb91

Browse files
authored
Merge pull request #30970 from Microsoft/incrementalLateSymbol
When adding resolvedMembers ensure lateBoundSymbol is added whether it was previously checked or not
2 parents b9145f9 + 0c18d03 commit 058cb91

File tree

13 files changed

+387
-4
lines changed

13 files changed

+387
-4
lines changed

src/compiler/checker.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6714,11 +6714,12 @@ namespace ts {
67146714
const links = getSymbolLinks(symbol);
67156715
if (!links.lateSymbol && some(symbol.declarations, hasLateBindableName)) {
67166716
// force late binding of members/exports. This will set the late-bound symbol
6717+
const parent = getMergedSymbol(symbol.parent)!;
67176718
if (some(symbol.declarations, hasStaticModifier)) {
6718-
getExportsOfSymbol(symbol.parent!);
6719+
getExportsOfSymbol(parent);
67196720
}
67206721
else {
6721-
getMembersOfSymbol(symbol.parent!);
6722+
getMembersOfSymbol(parent);
67226723
}
67236724
}
67246725
return links.lateSymbol || (links.lateSymbol = symbol);

src/testRunner/tsconfig.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@
9292
"unittests/tsbuild/amdModulesWithOut.ts",
9393
"unittests/tsbuild/emptyFiles.ts",
9494
"unittests/tsbuild/graphOrdering.ts",
95+
"unittests/tsbuild/lateBoundSymbol.ts",
9596
"unittests/tsbuild/missingExtendedFile.ts",
9697
"unittests/tsbuild/outFile.ts",
9798
"unittests/tsbuild/referencesWithRootDirInParent.ts",

src/testRunner/unittests/tsbuild/helpers.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -285,8 +285,10 @@ Mismatch Actual(path, actual, expected): ${JSON.stringify(arrayFrom(mapDefinedIt
285285
let newFs: vfs.FileSystem;
286286
let actualReadFileMap: Map<number>;
287287
let host: fakes.SolutionBuilderHost;
288+
let beforeBuildTime: number;
289+
let afterBuildTime: number;
288290
before(() => {
289-
assert.equal(fs.statSync(lastProjectOutputJs).mtimeMs, firstBuildTime, "First build timestamp is correct");
291+
beforeBuildTime = fs.statSync(lastProjectOutputJs).mtimeMs;
290292
tick();
291293
newFs = fs.shadow();
292294
tick();
@@ -298,13 +300,17 @@ Mismatch Actual(path, actual, expected): ${JSON.stringify(arrayFrom(mapDefinedIt
298300
expectedBuildInfoFilesForSectionBaselines,
299301
modifyFs: incrementalModifyFs,
300302
}));
301-
assert.equal(newFs.statSync(lastProjectOutputJs).mtimeMs, time(), "Second build timestamp is correct");
303+
afterBuildTime = newFs.statSync(lastProjectOutputJs).mtimeMs;
302304
});
303305
after(() => {
304306
newFs = undefined!;
305307
actualReadFileMap = undefined!;
306308
host = undefined!;
307309
});
310+
it("verify build output times", () => {
311+
assert.equal(beforeBuildTime, firstBuildTime, "First build timestamp is correct");
312+
assert.equal(afterBuildTime, time(), "Second build timestamp is correct");
313+
});
308314
if (!baselineOnly || verifyDiagnostics) {
309315
it(`verify diagnostics`, () => {
310316
host.assertDiagnosticMessages(...(incrementalExpectedDiagnostics || emptyArray));
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
namespace ts {
2+
describe("unittests:: tsbuild:: lateBoundSymbol:: interface is merged and contains late bound member", () => {
3+
let projFs: vfs.FileSystem;
4+
const { time, tick } = getTime();
5+
before(() => {
6+
projFs = loadProjectFromDisk("tests/projects/lateBoundSymbol", time);
7+
});
8+
after(() => {
9+
projFs = undefined!; // Release the contents
10+
});
11+
12+
verifyTsbuildOutput({
13+
scenario: "interface is merged and contains late bound member",
14+
projFs: () => projFs,
15+
time,
16+
tick,
17+
proj: "lateBoundSymbol",
18+
rootNames: ["/src/tsconfig.json"],
19+
expectedMapFileNames: emptyArray,
20+
lastProjectOutputJs: "/src/src/main.js",
21+
outputFiles: [
22+
"/src/src/hkt.js",
23+
"/src/src/main.js",
24+
"/src/tsconfig.tsbuildinfo",
25+
],
26+
initialBuild: {
27+
modifyFs: noop,
28+
expectedDiagnostics: [
29+
getExpectedDiagnosticForProjectsInBuild("src/tsconfig.json"),
30+
[Diagnostics.Project_0_is_out_of_date_because_output_file_1_does_not_exist, "src/tsconfig.json", "src/src/hkt.js"],
31+
[Diagnostics.Building_project_0, "/src/tsconfig.json"]
32+
]
33+
},
34+
incrementalDtsUnchangedBuild: {
35+
modifyFs: fs => replaceText(fs, "/src/src/main.ts", "const x = 10;", ""),
36+
expectedDiagnostics: [
37+
getExpectedDiagnosticForProjectsInBuild("src/tsconfig.json"),
38+
[Diagnostics.Project_0_is_out_of_date_because_oldest_output_1_is_older_than_newest_input_2, "src/tsconfig.json", "src/src/hkt.js", "src/src/main.ts"],
39+
[Diagnostics.Building_project_0, "/src/tsconfig.json"],
40+
[Diagnostics.Updating_unchanged_output_timestamps_of_project_0, "/src/tsconfig.json"]
41+
]
42+
},
43+
baselineOnly: true,
44+
verifyDiagnostics: true
45+
});
46+
});
47+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
//// [/src/src/main.js]
2+
"use strict";
3+
exports.__esModule = true;
4+
var sym = Symbol();
5+
6+
7+
//// [/src/src/main.ts]
8+
import { HKT } from "./hkt";
9+
10+
const sym = Symbol();
11+
12+
declare module "./hkt" {
13+
interface HKT<T> {
14+
[sym]: { a: T }
15+
}
16+
}
17+
18+
type A = HKT<number>[typeof sym];
19+
20+
//// [/src/tsconfig.tsbuildinfo]
21+
{
22+
"program": {
23+
"fileInfos": {
24+
"/lib/lib.es5.d.ts": {
25+
"version": "/lib/lib.es5.d.ts",
26+
"signature": "/lib/lib.es5.d.ts"
27+
},
28+
"/lib/lib.es2015.d.ts": {
29+
"version": "/lib/lib.es2015.d.ts",
30+
"signature": "/lib/lib.es2015.d.ts"
31+
},
32+
"/lib/lib.es2015.core.d.ts": {
33+
"version": "/lib/lib.es2015.core.d.ts",
34+
"signature": "/lib/lib.es2015.core.d.ts"
35+
},
36+
"/lib/lib.es2015.collection.d.ts": {
37+
"version": "/lib/lib.es2015.collection.d.ts",
38+
"signature": "/lib/lib.es2015.collection.d.ts"
39+
},
40+
"/lib/lib.es2015.generator.d.ts": {
41+
"version": "/lib/lib.es2015.generator.d.ts",
42+
"signature": "/lib/lib.es2015.generator.d.ts"
43+
},
44+
"/lib/lib.es2015.iterable.d.ts": {
45+
"version": "/lib/lib.es2015.iterable.d.ts",
46+
"signature": "/lib/lib.es2015.iterable.d.ts"
47+
},
48+
"/lib/lib.es2015.promise.d.ts": {
49+
"version": "/lib/lib.es2015.promise.d.ts",
50+
"signature": "/lib/lib.es2015.promise.d.ts"
51+
},
52+
"/lib/lib.es2015.proxy.d.ts": {
53+
"version": "/lib/lib.es2015.proxy.d.ts",
54+
"signature": "/lib/lib.es2015.proxy.d.ts"
55+
},
56+
"/lib/lib.es2015.reflect.d.ts": {
57+
"version": "/lib/lib.es2015.reflect.d.ts",
58+
"signature": "/lib/lib.es2015.reflect.d.ts"
59+
},
60+
"/lib/lib.es2015.symbol.d.ts": {
61+
"version": "/lib/lib.es2015.symbol.d.ts",
62+
"signature": "/lib/lib.es2015.symbol.d.ts"
63+
},
64+
"/lib/lib.es2015.symbol.wellknown.d.ts": {
65+
"version": "/lib/lib.es2015.symbol.wellknown.d.ts",
66+
"signature": "/lib/lib.es2015.symbol.wellknown.d.ts"
67+
},
68+
"/src/src/hkt.ts": {
69+
"version": "675797797",
70+
"signature": "2373810515"
71+
},
72+
"/src/src/main.ts": {
73+
"version": "-27494779858",
74+
"signature": "-7779857705"
75+
}
76+
},
77+
"options": {
78+
"rootDir": "/src/src",
79+
"lib": [
80+
"lib.es2015.d.ts"
81+
],
82+
"incremental": true,
83+
"configFilePath": "/src/tsconfig.json"
84+
},
85+
"referencedMap": {
86+
"/src/src/main.ts": [
87+
"/src/src/hkt.ts"
88+
]
89+
},
90+
"exportedModulesMap": {
91+
"/src/src/main.ts": [
92+
"/src/src/hkt.ts"
93+
]
94+
},
95+
"semanticDiagnosticsPerFile": [
96+
"/lib/lib.es2015.collection.d.ts",
97+
"/lib/lib.es2015.core.d.ts",
98+
"/lib/lib.es2015.d.ts",
99+
"/lib/lib.es2015.generator.d.ts",
100+
"/lib/lib.es2015.iterable.d.ts",
101+
"/lib/lib.es2015.promise.d.ts",
102+
"/lib/lib.es2015.proxy.d.ts",
103+
"/lib/lib.es2015.reflect.d.ts",
104+
"/lib/lib.es2015.symbol.d.ts",
105+
"/lib/lib.es2015.symbol.wellknown.d.ts",
106+
"/lib/lib.es5.d.ts",
107+
"/src/src/hkt.ts",
108+
"/src/src/main.ts"
109+
]
110+
},
111+
"version": "FakeTSVersion"
112+
}
113+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
//// [/src/src/hkt.js]
2+
"use strict";
3+
exports.__esModule = true;
4+
5+
6+
//// [/src/src/main.js]
7+
"use strict";
8+
exports.__esModule = true;
9+
var sym = Symbol();
10+
var x = 10;
11+
12+
13+
//// [/src/tsconfig.tsbuildinfo]
14+
{
15+
"program": {
16+
"fileInfos": {
17+
"/lib/lib.es5.d.ts": {
18+
"version": "/lib/lib.es5.d.ts",
19+
"signature": "/lib/lib.es5.d.ts"
20+
},
21+
"/lib/lib.es2015.d.ts": {
22+
"version": "/lib/lib.es2015.d.ts",
23+
"signature": "/lib/lib.es2015.d.ts"
24+
},
25+
"/lib/lib.es2015.core.d.ts": {
26+
"version": "/lib/lib.es2015.core.d.ts",
27+
"signature": "/lib/lib.es2015.core.d.ts"
28+
},
29+
"/lib/lib.es2015.collection.d.ts": {
30+
"version": "/lib/lib.es2015.collection.d.ts",
31+
"signature": "/lib/lib.es2015.collection.d.ts"
32+
},
33+
"/lib/lib.es2015.generator.d.ts": {
34+
"version": "/lib/lib.es2015.generator.d.ts",
35+
"signature": "/lib/lib.es2015.generator.d.ts"
36+
},
37+
"/lib/lib.es2015.iterable.d.ts": {
38+
"version": "/lib/lib.es2015.iterable.d.ts",
39+
"signature": "/lib/lib.es2015.iterable.d.ts"
40+
},
41+
"/lib/lib.es2015.promise.d.ts": {
42+
"version": "/lib/lib.es2015.promise.d.ts",
43+
"signature": "/lib/lib.es2015.promise.d.ts"
44+
},
45+
"/lib/lib.es2015.proxy.d.ts": {
46+
"version": "/lib/lib.es2015.proxy.d.ts",
47+
"signature": "/lib/lib.es2015.proxy.d.ts"
48+
},
49+
"/lib/lib.es2015.reflect.d.ts": {
50+
"version": "/lib/lib.es2015.reflect.d.ts",
51+
"signature": "/lib/lib.es2015.reflect.d.ts"
52+
},
53+
"/lib/lib.es2015.symbol.d.ts": {
54+
"version": "/lib/lib.es2015.symbol.d.ts",
55+
"signature": "/lib/lib.es2015.symbol.d.ts"
56+
},
57+
"/lib/lib.es2015.symbol.wellknown.d.ts": {
58+
"version": "/lib/lib.es2015.symbol.wellknown.d.ts",
59+
"signature": "/lib/lib.es2015.symbol.wellknown.d.ts"
60+
},
61+
"/src/src/hkt.ts": {
62+
"version": "675797797",
63+
"signature": "2373810515"
64+
},
65+
"/src/src/main.ts": {
66+
"version": "-28387946490",
67+
"signature": "-7779857705"
68+
}
69+
},
70+
"options": {
71+
"rootDir": "/src/src",
72+
"lib": [
73+
"lib.es2015.d.ts"
74+
],
75+
"incremental": true,
76+
"configFilePath": "/src/tsconfig.json"
77+
},
78+
"referencedMap": {
79+
"/src/src/main.ts": [
80+
"/src/src/hkt.ts"
81+
]
82+
},
83+
"exportedModulesMap": {
84+
"/src/src/main.ts": [
85+
"/src/src/hkt.ts"
86+
]
87+
},
88+
"semanticDiagnosticsPerFile": [
89+
"/lib/lib.es2015.collection.d.ts",
90+
"/lib/lib.es2015.core.d.ts",
91+
"/lib/lib.es2015.d.ts",
92+
"/lib/lib.es2015.generator.d.ts",
93+
"/lib/lib.es2015.iterable.d.ts",
94+
"/lib/lib.es2015.promise.d.ts",
95+
"/lib/lib.es2015.proxy.d.ts",
96+
"/lib/lib.es2015.reflect.d.ts",
97+
"/lib/lib.es2015.symbol.d.ts",
98+
"/lib/lib.es2015.symbol.wellknown.d.ts",
99+
"/lib/lib.es5.d.ts",
100+
"/src/src/hkt.ts",
101+
"/src/src/main.ts"
102+
]
103+
},
104+
"version": "FakeTSVersion"
105+
}
106+
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
//// [uniqueSymbolAssignmentOnGlobalAugmentationSuceeds.ts]
2+
const FOO_SYMBOL = Symbol('Foo');
3+
4+
declare global {
5+
interface Promise<T> {
6+
[FOO_SYMBOL]?: number;
7+
}
8+
}
9+
10+
export function foo<T>(p: Promise<T>) {
11+
p[FOO_SYMBOL] = 3;
12+
}
13+
14+
//// [uniqueSymbolAssignmentOnGlobalAugmentationSuceeds.js]
15+
const FOO_SYMBOL = Symbol('Foo');
16+
export function foo(p) {
17+
p[FOO_SYMBOL] = 3;
18+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
=== tests/cases/compiler/uniqueSymbolAssignmentOnGlobalAugmentationSuceeds.ts ===
2+
const FOO_SYMBOL = Symbol('Foo');
3+
>FOO_SYMBOL : Symbol(FOO_SYMBOL, Decl(uniqueSymbolAssignmentOnGlobalAugmentationSuceeds.ts, 0, 5))
4+
>Symbol : Symbol(Symbol, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --))
5+
6+
declare global {
7+
>global : Symbol(global, Decl(uniqueSymbolAssignmentOnGlobalAugmentationSuceeds.ts, 0, 33))
8+
9+
interface Promise<T> {
10+
>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(uniqueSymbolAssignmentOnGlobalAugmentationSuceeds.ts, 2, 16))
11+
>T : Symbol(T, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(uniqueSymbolAssignmentOnGlobalAugmentationSuceeds.ts, 3, 22))
12+
13+
[FOO_SYMBOL]?: number;
14+
>[FOO_SYMBOL] : Symbol(Promise[FOO_SYMBOL], Decl(uniqueSymbolAssignmentOnGlobalAugmentationSuceeds.ts, 3, 26))
15+
>FOO_SYMBOL : Symbol(FOO_SYMBOL, Decl(uniqueSymbolAssignmentOnGlobalAugmentationSuceeds.ts, 0, 5))
16+
}
17+
}
18+
19+
export function foo<T>(p: Promise<T>) {
20+
>foo : Symbol(foo, Decl(uniqueSymbolAssignmentOnGlobalAugmentationSuceeds.ts, 6, 1))
21+
>T : Symbol(T, Decl(uniqueSymbolAssignmentOnGlobalAugmentationSuceeds.ts, 8, 20))
22+
>p : Symbol(p, Decl(uniqueSymbolAssignmentOnGlobalAugmentationSuceeds.ts, 8, 23))
23+
>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(uniqueSymbolAssignmentOnGlobalAugmentationSuceeds.ts, 2, 16))
24+
>T : Symbol(T, Decl(uniqueSymbolAssignmentOnGlobalAugmentationSuceeds.ts, 8, 20))
25+
26+
p[FOO_SYMBOL] = 3;
27+
>p : Symbol(p, Decl(uniqueSymbolAssignmentOnGlobalAugmentationSuceeds.ts, 8, 23))
28+
>FOO_SYMBOL : Symbol(FOO_SYMBOL, Decl(uniqueSymbolAssignmentOnGlobalAugmentationSuceeds.ts, 0, 5))
29+
}

0 commit comments

Comments
 (0)