Skip to content

Commit 08cb0b2

Browse files
Serialize (noncontextual) keyword named namespace members with export declarations in both declaration emitters (#38982)
* fix(38750): create unique names for keywords and re-export them with original names * Serialize (noncontextual) keyword named namespace members with export declarations in both declaration emitters * Add exhaustive keyword emit test for js declaration emitter and fix it up Co-authored-by: Alexander T <[email protected]>
1 parent 58330d0 commit 08cb0b2

File tree

43 files changed

+3067
-134
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+3067
-134
lines changed

src/compiler/checker.ts

+107-73
Large diffs are not rendered by default.

src/compiler/transformers/declarations.ts

+22-4
Original file line numberDiff line numberDiff line change
@@ -1180,18 +1180,36 @@ namespace ts {
11801180
fakespace.parent = enclosingDeclaration as SourceFile | NamespaceDeclaration;
11811181
fakespace.locals = createSymbolTable(props);
11821182
fakespace.symbol = props[0].parent!;
1183-
const declarations = mapDefined(props, p => {
1183+
const exportMappings: [Identifier, string][] = [];
1184+
const declarations: (VariableStatement | ExportDeclaration)[] = mapDefined(props, p => {
11841185
if (!isPropertyAccessExpression(p.valueDeclaration)) {
11851186
return undefined; // TODO GH#33569: Handle element access expressions that created late bound names (rather than silently omitting them)
11861187
}
11871188
getSymbolAccessibilityDiagnostic = createGetSymbolAccessibilityDiagnosticForNode(p.valueDeclaration);
11881189
const type = resolver.createTypeOfDeclaration(p.valueDeclaration, fakespace, declarationEmitNodeBuilderFlags, symbolTracker);
11891190
getSymbolAccessibilityDiagnostic = oldDiag;
1190-
const varDecl = createVariableDeclaration(unescapeLeadingUnderscores(p.escapedName), type, /*initializer*/ undefined);
1191-
return createVariableStatement(/*modifiers*/ undefined, createVariableDeclarationList([varDecl]));
1191+
const nameStr = unescapeLeadingUnderscores(p.escapedName);
1192+
const isNonContextualKeywordName = isStringANonContextualKeyword(nameStr);
1193+
const name = isNonContextualKeywordName ? getGeneratedNameForNode(p.valueDeclaration) : createIdentifier(nameStr);
1194+
if (isNonContextualKeywordName) {
1195+
exportMappings.push([name, nameStr]);
1196+
}
1197+
const varDecl = createVariableDeclaration(name, type, /*initializer*/ undefined);
1198+
return createVariableStatement(isNonContextualKeywordName ? undefined : [createToken(SyntaxKind.ExportKeyword)], createVariableDeclarationList([varDecl]));
11921199
});
1200+
if (!exportMappings.length) {
1201+
forEach(declarations, d => d.modifiers = undefined);
1202+
}
1203+
else {
1204+
declarations.push(createExportDeclaration(
1205+
/*decorators*/ undefined,
1206+
/*modifiers*/ undefined,
1207+
createNamedExports(map(exportMappings, ([gen, exp]) => {
1208+
return createExportSpecifier(gen, exp);
1209+
}))
1210+
));
1211+
}
11931212
const namespaceDecl = createModuleDeclaration(/*decorators*/ undefined, ensureModifiers(input), input.name!, createModuleBlock(declarations), NodeFlags.Namespace);
1194-
11951213
if (!hasEffectiveModifier(clean, ModifierFlags.Default)) {
11961214
return [clean, namespaceDecl];
11971215
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
//// [declarationEmitFunctionKeywordProp.ts]
2+
function foo() {}
3+
foo.null = true;
4+
5+
function bar() {}
6+
bar.async = true;
7+
bar.normal = false;
8+
9+
function baz() {}
10+
baz.class = true;
11+
baz.normal = false;
12+
13+
//// [declarationEmitFunctionKeywordProp.js]
14+
function foo() { }
15+
foo["null"] = true;
16+
function bar() { }
17+
bar.async = true;
18+
bar.normal = false;
19+
function baz() { }
20+
baz["class"] = true;
21+
baz.normal = false;
22+
23+
24+
//// [declarationEmitFunctionKeywordProp.d.ts]
25+
declare function foo(): void;
26+
declare namespace foo {
27+
var _a: boolean;
28+
export { _a as null };
29+
}
30+
declare function bar(): void;
31+
declare namespace bar {
32+
var async: boolean;
33+
var normal: boolean;
34+
}
35+
declare function baz(): void;
36+
declare namespace baz {
37+
var _a: boolean;
38+
export var normal: boolean;
39+
export { _a as class };
40+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
=== tests/cases/compiler/declarationEmitFunctionKeywordProp.ts ===
2+
function foo() {}
3+
>foo : Symbol(foo, Decl(declarationEmitFunctionKeywordProp.ts, 0, 0), Decl(declarationEmitFunctionKeywordProp.ts, 0, 17))
4+
5+
foo.null = true;
6+
>foo.null : Symbol(foo.null, Decl(declarationEmitFunctionKeywordProp.ts, 0, 17))
7+
>foo : Symbol(foo, Decl(declarationEmitFunctionKeywordProp.ts, 0, 0), Decl(declarationEmitFunctionKeywordProp.ts, 0, 17))
8+
>null : Symbol(foo.null, Decl(declarationEmitFunctionKeywordProp.ts, 0, 17))
9+
10+
function bar() {}
11+
>bar : Symbol(bar, Decl(declarationEmitFunctionKeywordProp.ts, 1, 16), Decl(declarationEmitFunctionKeywordProp.ts, 3, 17), Decl(declarationEmitFunctionKeywordProp.ts, 4, 17))
12+
13+
bar.async = true;
14+
>bar.async : Symbol(bar.async, Decl(declarationEmitFunctionKeywordProp.ts, 3, 17))
15+
>bar : Symbol(bar, Decl(declarationEmitFunctionKeywordProp.ts, 1, 16), Decl(declarationEmitFunctionKeywordProp.ts, 3, 17), Decl(declarationEmitFunctionKeywordProp.ts, 4, 17))
16+
>async : Symbol(bar.async, Decl(declarationEmitFunctionKeywordProp.ts, 3, 17))
17+
18+
bar.normal = false;
19+
>bar.normal : Symbol(bar.normal, Decl(declarationEmitFunctionKeywordProp.ts, 4, 17))
20+
>bar : Symbol(bar, Decl(declarationEmitFunctionKeywordProp.ts, 1, 16), Decl(declarationEmitFunctionKeywordProp.ts, 3, 17), Decl(declarationEmitFunctionKeywordProp.ts, 4, 17))
21+
>normal : Symbol(bar.normal, Decl(declarationEmitFunctionKeywordProp.ts, 4, 17))
22+
23+
function baz() {}
24+
>baz : Symbol(baz, Decl(declarationEmitFunctionKeywordProp.ts, 5, 19), Decl(declarationEmitFunctionKeywordProp.ts, 7, 17), Decl(declarationEmitFunctionKeywordProp.ts, 8, 17))
25+
26+
baz.class = true;
27+
>baz.class : Symbol(baz.class, Decl(declarationEmitFunctionKeywordProp.ts, 7, 17))
28+
>baz : Symbol(baz, Decl(declarationEmitFunctionKeywordProp.ts, 5, 19), Decl(declarationEmitFunctionKeywordProp.ts, 7, 17), Decl(declarationEmitFunctionKeywordProp.ts, 8, 17))
29+
>class : Symbol(baz.class, Decl(declarationEmitFunctionKeywordProp.ts, 7, 17))
30+
31+
baz.normal = false;
32+
>baz.normal : Symbol(baz.normal, Decl(declarationEmitFunctionKeywordProp.ts, 8, 17))
33+
>baz : Symbol(baz, Decl(declarationEmitFunctionKeywordProp.ts, 5, 19), Decl(declarationEmitFunctionKeywordProp.ts, 7, 17), Decl(declarationEmitFunctionKeywordProp.ts, 8, 17))
34+
>normal : Symbol(baz.normal, Decl(declarationEmitFunctionKeywordProp.ts, 8, 17))
35+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
=== tests/cases/compiler/declarationEmitFunctionKeywordProp.ts ===
2+
function foo() {}
3+
>foo : typeof foo
4+
5+
foo.null = true;
6+
>foo.null = true : true
7+
>foo.null : boolean
8+
>foo : typeof foo
9+
>null : boolean
10+
>true : true
11+
12+
function bar() {}
13+
>bar : typeof bar
14+
15+
bar.async = true;
16+
>bar.async = true : true
17+
>bar.async : boolean
18+
>bar : typeof bar
19+
>async : boolean
20+
>true : true
21+
22+
bar.normal = false;
23+
>bar.normal = false : false
24+
>bar.normal : boolean
25+
>bar : typeof bar
26+
>normal : boolean
27+
>false : false
28+
29+
function baz() {}
30+
>baz : typeof baz
31+
32+
baz.class = true;
33+
>baz.class = true : true
34+
>baz.class : boolean
35+
>baz : typeof baz
36+
>class : boolean
37+
>true : true
38+
39+
baz.normal = false;
40+
>baz.normal = false : false
41+
>baz.normal : boolean
42+
>baz : typeof baz
43+
>normal : boolean
44+
>false : false
45+

tests/baselines/reference/jsDeclarationsClassExtendsVisibility.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,6 @@ declare namespace Foo {
6363
export { Strings };
6464
}
6565
declare namespace Strings {
66-
export const a: string;
67-
export const b: string;
66+
const a: string;
67+
const b: string;
6868
}

tests/baselines/reference/jsDeclarationsClassStatic.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,8 @@ declare namespace Handler {
6363
}
6464
declare function statische(): void;
6565
declare namespace Strings {
66-
export const a: string;
67-
export const b: string;
66+
const a: string;
67+
const b: string;
6868
}
6969
type HandlerOptions = {
7070
/**

tests/baselines/reference/jsDeclarationsEnumTag.js

+9-9
Original file line numberDiff line numberDiff line change
@@ -113,19 +113,19 @@ export function consume(t: Target, s: Second, f: Fs): void;
113113
export function ff(s: string): any;
114114
export type Target = string;
115115
export namespace Target {
116-
export const START: string;
117-
export const MIDDLE: string;
118-
export const END: string;
119-
export const OK_I_GUESS: number;
116+
const START: string;
117+
const MIDDLE: string;
118+
const END: string;
119+
const OK_I_GUESS: number;
120120
}
121121
export type Second = number;
122122
export namespace Second {
123-
export const OK: number;
124-
export const FINE: number;
123+
const OK: number;
124+
const FINE: number;
125125
}
126126
export type Fs = (arg0: number) => number;
127127
export namespace Fs {
128-
export function ADD1(n: any): any;
129-
export function ID(n: any): any;
130-
export function SUB1(n: any): number;
128+
function ADD1(n: any): any;
129+
function ID(n: any): any;
130+
function SUB1(n: any): number;
131131
}

tests/baselines/reference/jsDeclarationsExportAssignmentExpressionPlusSecondary.js

+3-3
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,11 @@ module.exports.Strings = Strings;
3030

3131
//// [index.d.ts]
3232
export namespace Strings {
33-
export const a: string;
34-
export const b: string;
33+
const a: string;
34+
const b: string;
3535
}
3636
export declare const thing: string;
3737
export declare const also: string;
3838
export declare namespace desc {
39-
export const item: string;
39+
const item: string;
4040
}

tests/baselines/reference/jsDeclarationsExportAssignmentWithKeywordName.js

+6-8
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,9 @@ module.exports = {
2020

2121

2222
//// [index.d.ts]
23-
declare const _exports: {
24-
extends: string;
25-
more: {
26-
others: string[];
27-
};
28-
x: number;
29-
};
30-
export = _exports;
23+
export var x: number;
24+
declare const _extends: string;
25+
export declare namespace more {
26+
const others: string[];
27+
}
28+
export { _extends as extends };

tests/baselines/reference/jsDeclarationsExportDefinePropertyEmit.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ Object.defineProperty(module.exports, "j", { value: function j() { } });
114114
export function a(): void;
115115
export function b(): void;
116116
export namespace b {
117-
export const cat: string;
117+
const cat: string;
118118
}
119119
/**
120120
* @param {number} a
@@ -139,7 +139,7 @@ export namespace f {
139139
* @template T
140140
* @param {T} a
141141
*/
142-
export function self<T>(a: T): T;
142+
function self<T>(a: T): T;
143143
}
144144
/**
145145
* @param {{x: string}} a

tests/baselines/reference/jsDeclarationsExportDoubleAssignmentInClosure.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,6 @@ function foo() {
2020
//// [index.d.ts]
2121
declare function _exports(o: any): any;
2222
declare namespace _exports {
23-
export const methods: any;
23+
const methods: any;
2424
}
2525
export = _exports;

tests/baselines/reference/jsDeclarationsExportSubAssignments.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,6 @@ declare namespace Foo {
2929
export { Strings };
3030
}
3131
declare namespace Strings {
32-
export const a: string;
33-
export const b: string;
32+
const a: string;
33+
const b: string;
3434
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
//// [source.js]
2+
function foo() {}
3+
foo.null = true;
4+
5+
function bar() {}
6+
bar.async = true;
7+
bar.normal = false;
8+
9+
function baz() {}
10+
baz.class = true;
11+
baz.normal = false;
12+
13+
//// [source.js]
14+
function foo() { }
15+
foo.null = true;
16+
function bar() { }
17+
bar.async = true;
18+
bar.normal = false;
19+
function baz() { }
20+
baz.class = true;
21+
baz.normal = false;
22+
23+
24+
//// [source.d.ts]
25+
declare function foo(): void;
26+
declare namespace foo {
27+
const _null: boolean;
28+
export { _null as null };
29+
}
30+
declare function bar(): void;
31+
declare namespace bar {
32+
const async: boolean;
33+
const normal: boolean;
34+
}
35+
declare function baz(): void;
36+
declare namespace baz {
37+
const _class: boolean;
38+
export { _class as class };
39+
const normal_1: boolean;
40+
export { normal_1 as normal };
41+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
=== tests/cases/conformance/jsdoc/declarations/source.js ===
2+
function foo() {}
3+
>foo : Symbol(foo, Decl(source.js, 0, 0), Decl(source.js, 0, 17))
4+
5+
foo.null = true;
6+
>foo.null : Symbol(foo.null, Decl(source.js, 0, 17))
7+
>foo : Symbol(foo, Decl(source.js, 0, 0), Decl(source.js, 0, 17))
8+
>null : Symbol(foo.null, Decl(source.js, 0, 17))
9+
10+
function bar() {}
11+
>bar : Symbol(bar, Decl(source.js, 1, 16), Decl(source.js, 3, 17), Decl(source.js, 4, 17))
12+
13+
bar.async = true;
14+
>bar.async : Symbol(bar.async, Decl(source.js, 3, 17))
15+
>bar : Symbol(bar, Decl(source.js, 1, 16), Decl(source.js, 3, 17), Decl(source.js, 4, 17))
16+
>async : Symbol(bar.async, Decl(source.js, 3, 17))
17+
18+
bar.normal = false;
19+
>bar.normal : Symbol(bar.normal, Decl(source.js, 4, 17))
20+
>bar : Symbol(bar, Decl(source.js, 1, 16), Decl(source.js, 3, 17), Decl(source.js, 4, 17))
21+
>normal : Symbol(bar.normal, Decl(source.js, 4, 17))
22+
23+
function baz() {}
24+
>baz : Symbol(baz, Decl(source.js, 5, 19), Decl(source.js, 7, 17), Decl(source.js, 8, 17))
25+
26+
baz.class = true;
27+
>baz.class : Symbol(baz.class, Decl(source.js, 7, 17))
28+
>baz : Symbol(baz, Decl(source.js, 5, 19), Decl(source.js, 7, 17), Decl(source.js, 8, 17))
29+
>class : Symbol(baz.class, Decl(source.js, 7, 17))
30+
31+
baz.normal = false;
32+
>baz.normal : Symbol(baz.normal, Decl(source.js, 8, 17))
33+
>baz : Symbol(baz, Decl(source.js, 5, 19), Decl(source.js, 7, 17), Decl(source.js, 8, 17))
34+
>normal : Symbol(baz.normal, Decl(source.js, 8, 17))
35+

0 commit comments

Comments
 (0)