Skip to content

Commit 6a6cb09

Browse files
authored
Fix circularity in expando object property assignment (#3699)
1 parent 2f6504c commit 6a6cb09

4 files changed

Lines changed: 93 additions & 6 deletions

File tree

internal/checker/relater.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4583,16 +4583,16 @@ func (r *Relater) typeRelatedToIndexInfo(source *Type, targetInfo *IndexInfo, re
45834583
return TernaryFalse
45844584
}
45854585

4586-
/**
4587-
* Return true if type was inferred from an object literal, written as an object type literal, or is the shape of a module
4588-
* with no call or construct signatures.
4589-
*/
4586+
// Return true if type was inferred from a non-expando object literal, written as an object type literal, or is the shape of a module
4587+
// with no call or construct signatures.
45904588
func (c *Checker) isObjectTypeWithInferableIndex(t *Type) bool {
45914589
if t.flags&TypeFlagsIntersection != 0 {
45924590
return core.Every(t.Types(), c.isObjectTypeWithInferableIndex)
45934591
}
4594-
return t.symbol != nil && t.symbol.Flags&(ast.SymbolFlagsObjectLiteral|ast.SymbolFlagsTypeLiteral|ast.SymbolFlagsEnum|ast.SymbolFlagsValueModule) != 0 &&
4595-
t.symbol.Flags&ast.SymbolFlagsClass == 0 && !c.typeHasCallOrConstructSignatures(t) ||
4592+
return t.symbol != nil &&
4593+
(t.symbol.Flags&(ast.SymbolFlagsObjectLiteral|ast.SymbolFlagsTypeLiteral) != 0 && len(t.symbol.Exports) == 0 ||
4594+
t.symbol.Flags&(ast.SymbolFlagsEnum|ast.SymbolFlagsValueModule) != 0 && t.symbol.Flags&ast.SymbolFlagsClass == 0) &&
4595+
!c.typeHasCallOrConstructSignatures(t) ||
45964596
t.objectFlags&ObjectFlagsObjectRestType != 0 ||
45974597
t.objectFlags&ObjectFlagsReverseMapped != 0 && c.isObjectTypeWithInferableIndex(t.AsReverseMappedType().source)
45984598
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
//// [tests/cases/compiler/expandoNoInferredIndex.ts] ////
2+
3+
=== main.js ===
4+
export class C {
5+
>C : Symbol(C, Decl(main.js, 0, 0))
6+
7+
method() {
8+
>method : Symbol(C.method, Decl(main.js, 0, 16))
9+
10+
const obj = {};
11+
>obj : Symbol(obj, Decl(main.js, 2, 13))
12+
13+
obj.foo = 'foo';
14+
>obj.foo : Symbol(foo, Decl(main.js, 2, 23))
15+
>obj : Symbol(obj, Decl(main.js, 2, 13))
16+
>foo : Symbol(foo, Decl(main.js, 2, 23))
17+
18+
obj.bar = 'bar';
19+
>obj.bar : Symbol(bar, Decl(main.js, 3, 24))
20+
>obj : Symbol(obj, Decl(main.js, 2, 13))
21+
>bar : Symbol(bar, Decl(main.js, 3, 24))
22+
23+
obj.buzz = Object.values(obj);
24+
>obj.buzz : Symbol(buzz, Decl(main.js, 4, 24))
25+
>obj : Symbol(obj, Decl(main.js, 2, 13))
26+
>buzz : Symbol(buzz, Decl(main.js, 4, 24))
27+
>Object.values : Symbol(ObjectConstructor.values, Decl(lib.es2017.object.d.ts, --, --), Decl(lib.es2017.object.d.ts, --, --))
28+
>Object : Symbol(Object, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
29+
>values : Symbol(ObjectConstructor.values, Decl(lib.es2017.object.d.ts, --, --), Decl(lib.es2017.object.d.ts, --, --))
30+
>obj : Symbol(obj, Decl(main.js, 2, 13))
31+
}
32+
}
33+
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
//// [tests/cases/compiler/expandoNoInferredIndex.ts] ////
2+
3+
=== main.js ===
4+
export class C {
5+
>C : C
6+
7+
method() {
8+
>method : () => void
9+
10+
const obj = {};
11+
>obj : { foo: string; bar: string; buzz: any[]; }
12+
>{} : { foo: string; bar: string; buzz: any[]; }
13+
14+
obj.foo = 'foo';
15+
>obj.foo = 'foo' : "foo"
16+
>obj.foo : string
17+
>obj : { foo: string; bar: string; buzz: any[]; }
18+
>foo : string
19+
>'foo' : "foo"
20+
21+
obj.bar = 'bar';
22+
>obj.bar = 'bar' : "bar"
23+
>obj.bar : string
24+
>obj : { foo: string; bar: string; buzz: any[]; }
25+
>bar : string
26+
>'bar' : "bar"
27+
28+
obj.buzz = Object.values(obj);
29+
>obj.buzz = Object.values(obj) : any[]
30+
>obj.buzz : any[]
31+
>obj : { foo: string; bar: string; buzz: any[]; }
32+
>buzz : any[]
33+
>Object.values(obj) : any[]
34+
>Object.values : { <T>(o: { [s: string]: T; } | ArrayLike<T>): T[]; (o: {}): any[]; }
35+
>Object : ObjectConstructor
36+
>values : { <T>(o: { [s: string]: T; } | ArrayLike<T>): T[]; (o: {}): any[]; }
37+
>obj : { foo: string; bar: string; buzz: any[]; }
38+
}
39+
}
40+
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// @checkJs: true
2+
// @noEmit: true
3+
4+
// https://github.com/microsoft/typescript-go/issues/3691
5+
6+
// @filename: main.js
7+
export class C {
8+
method() {
9+
const obj = {};
10+
obj.foo = 'foo';
11+
obj.bar = 'bar';
12+
obj.buzz = Object.values(obj);
13+
}
14+
}

0 commit comments

Comments
 (0)