Skip to content

Commit 87036fe

Browse files
committed
Merge pull request #6058 from Microsoft/delayAccessorBodyCheck
Defer checks of accessor bodies in object literals
2 parents 9d1cc31 + 18e23a1 commit 87036fe

File tree

5 files changed

+143
-7
lines changed

5 files changed

+143
-7
lines changed

src/compiler/checker.ts

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11255,7 +11255,7 @@ namespace ts {
1125511255
checkGrammarMethod(node) || checkGrammarComputedPropertyName(node.name);
1125611256

1125711257
// Grammar checking for modifiers is done inside the function checkGrammarFunctionLikeDeclaration
11258-
checkFunctionLikeDeclaration(node);
11258+
checkFunctionOrMethodDeclaration(node);
1125911259

1126011260
// Abstract methods cannot have an implementation.
1126111261
// Extra checks are to avoid reporting multiple errors relating to the "abstractness" of the node.
@@ -11382,6 +11382,8 @@ namespace ts {
1138211382
// Grammar checking accessors
1138311383
checkGrammarFunctionLikeDeclaration(node) || checkGrammarAccessor(node) || checkGrammarComputedPropertyName(node.name);
1138411384

11385+
checkDecorators(node);
11386+
checkSignatureDeclaration(node);
1138511387
if (node.kind === SyntaxKind.GetAccessor) {
1138611388
if (!isInAmbientContext(node) && nodeIsPresent(node.body) && (node.flags & NodeFlags.HasImplicitReturn)) {
1138711389
if (node.flags & NodeFlags.HasExplicitReturn) {
@@ -11394,7 +11396,12 @@ namespace ts {
1139411396
}
1139511397
}
1139611398
}
11397-
11399+
// Do not use hasDynamicName here, because that returns false for well known symbols.
11400+
// We want to perform checkComputedPropertyName for all computed properties, including
11401+
// well known symbols.
11402+
if (node.name.kind === SyntaxKind.ComputedPropertyName) {
11403+
checkComputedPropertyName(<ComputedPropertyName>node.name);
11404+
}
1139811405
if (!hasDynamicName(node)) {
1139911406
// TypeScript 1.0 spec (April 2014): 8.4.3
1140011407
// Accessors for the same member name must specify the same accessibility.
@@ -11418,8 +11425,16 @@ namespace ts {
1141811425
}
1141911426
getTypeOfAccessors(getSymbolOfNode(node));
1142011427
}
11428+
if (node.parent.kind !== SyntaxKind.ObjectLiteralExpression) {
11429+
checkSourceElement(node.body);
11430+
}
11431+
}
1142111432

11422-
checkFunctionLikeDeclaration(node);
11433+
function checkObjectLiteralAccessorBody(node: AccessorDeclaration) {
11434+
if (node.body) {
11435+
checkSourceElement(node.body);
11436+
checkFunctionAndClassExpressionBodies(node.body);
11437+
}
1142311438
}
1142411439

1142511440
function checkMissingDeclaration(node: Node) {
@@ -12277,15 +12292,15 @@ namespace ts {
1227712292

1227812293
function checkFunctionDeclaration(node: FunctionDeclaration): void {
1227912294
if (produceDiagnostics) {
12280-
checkFunctionLikeDeclaration(node) || checkGrammarForGenerator(node);
12295+
checkFunctionOrMethodDeclaration(node) || checkGrammarForGenerator(node);
1228112296

1228212297
checkCollisionWithCapturedSuperVariable(node, node.name);
1228312298
checkCollisionWithCapturedThisVariable(node, node.name);
1228412299
checkCollisionWithRequireExportsInGeneratedCode(node, node.name);
1228512300
}
1228612301
}
1228712302

12288-
function checkFunctionLikeDeclaration(node: FunctionLikeDeclaration): void {
12303+
function checkFunctionOrMethodDeclaration(node: FunctionDeclaration | MethodDeclaration): void {
1228912304
checkDecorators(node);
1229012305
checkSignatureDeclaration(node);
1229112306
const isAsync = isAsyncFunctionLike(node);
@@ -12332,7 +12347,7 @@ namespace ts {
1233212347
}
1233312348

1233412349
checkSourceElement(node.body);
12335-
if (!isAccessor(node.kind) && !node.asteriskToken) {
12350+
if (!node.asteriskToken) {
1233612351
const returnOrPromisedType = node.type && (isAsync ? checkAsyncFunctionReturnType(node) : getTypeFromTypeNode(node.type));
1233712352
checkAllCodePathsInNonVoidFunctionReturnOrThrow(node, returnOrPromisedType);
1233812353
}
@@ -14483,10 +14498,15 @@ namespace ts {
1448314498
}
1448414499
break;
1448514500
case SyntaxKind.Constructor:
14501+
case SyntaxKind.FunctionDeclaration:
14502+
forEach((<FunctionLikeDeclaration>node).parameters, checkFunctionAndClassExpressionBodies);
14503+
break;
1448614504
case SyntaxKind.GetAccessor:
1448714505
case SyntaxKind.SetAccessor:
14488-
case SyntaxKind.FunctionDeclaration:
1448914506
forEach((<FunctionLikeDeclaration>node).parameters, checkFunctionAndClassExpressionBodies);
14507+
if (node.parent.kind === SyntaxKind.ObjectLiteralExpression) {
14508+
checkObjectLiteralAccessorBody(<AccessorDeclaration>node);
14509+
}
1449014510
break;
1449114511
case SyntaxKind.WithStatement:
1449214512
checkFunctionAndClassExpressionBodies((<WithStatement>node).expression);
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
//// [circularObjectLiteralAccessors.ts]
2+
3+
// Repro from #6000
4+
5+
const a = {
6+
b: {
7+
get foo(): string {
8+
return a.foo;
9+
},
10+
set foo(value: string) {
11+
a.foo = value;
12+
}
13+
},
14+
foo: ''
15+
};
16+
17+
//// [circularObjectLiteralAccessors.js]
18+
// Repro from #6000
19+
var a = {
20+
b: {
21+
get foo() {
22+
return a.foo;
23+
},
24+
set foo(value) {
25+
a.foo = value;
26+
}
27+
},
28+
foo: ''
29+
};
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
=== tests/cases/compiler/circularObjectLiteralAccessors.ts ===
2+
3+
// Repro from #6000
4+
5+
const a = {
6+
>a : Symbol(a, Decl(circularObjectLiteralAccessors.ts, 3, 5))
7+
8+
b: {
9+
>b : Symbol(b, Decl(circularObjectLiteralAccessors.ts, 3, 11))
10+
11+
get foo(): string {
12+
>foo : Symbol(foo, Decl(circularObjectLiteralAccessors.ts, 4, 8), Decl(circularObjectLiteralAccessors.ts, 7, 10))
13+
14+
return a.foo;
15+
>a.foo : Symbol(foo, Decl(circularObjectLiteralAccessors.ts, 11, 6))
16+
>a : Symbol(a, Decl(circularObjectLiteralAccessors.ts, 3, 5))
17+
>foo : Symbol(foo, Decl(circularObjectLiteralAccessors.ts, 11, 6))
18+
19+
},
20+
set foo(value: string) {
21+
>foo : Symbol(foo, Decl(circularObjectLiteralAccessors.ts, 4, 8), Decl(circularObjectLiteralAccessors.ts, 7, 10))
22+
>value : Symbol(value, Decl(circularObjectLiteralAccessors.ts, 8, 16))
23+
24+
a.foo = value;
25+
>a.foo : Symbol(foo, Decl(circularObjectLiteralAccessors.ts, 11, 6))
26+
>a : Symbol(a, Decl(circularObjectLiteralAccessors.ts, 3, 5))
27+
>foo : Symbol(foo, Decl(circularObjectLiteralAccessors.ts, 11, 6))
28+
>value : Symbol(value, Decl(circularObjectLiteralAccessors.ts, 8, 16))
29+
}
30+
},
31+
foo: ''
32+
>foo : Symbol(foo, Decl(circularObjectLiteralAccessors.ts, 11, 6))
33+
34+
};
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
=== tests/cases/compiler/circularObjectLiteralAccessors.ts ===
2+
3+
// Repro from #6000
4+
5+
const a = {
6+
>a : { b: { foo: string; }; foo: string; }
7+
>{ b: { get foo(): string { return a.foo; }, set foo(value: string) { a.foo = value; } }, foo: ''} : { b: { foo: string; }; foo: string; }
8+
9+
b: {
10+
>b : { foo: string; }
11+
>{ get foo(): string { return a.foo; }, set foo(value: string) { a.foo = value; } } : { foo: string; }
12+
13+
get foo(): string {
14+
>foo : string
15+
16+
return a.foo;
17+
>a.foo : string
18+
>a : { b: { foo: string; }; foo: string; }
19+
>foo : string
20+
21+
},
22+
set foo(value: string) {
23+
>foo : string
24+
>value : string
25+
26+
a.foo = value;
27+
>a.foo = value : string
28+
>a.foo : string
29+
>a : { b: { foo: string; }; foo: string; }
30+
>foo : string
31+
>value : string
32+
}
33+
},
34+
foo: ''
35+
>foo : string
36+
>'' : string
37+
38+
};
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// @target: es5
2+
3+
// Repro from #6000
4+
5+
const a = {
6+
b: {
7+
get foo(): string {
8+
return a.foo;
9+
},
10+
set foo(value: string) {
11+
a.foo = value;
12+
}
13+
},
14+
foo: ''
15+
};

0 commit comments

Comments
 (0)