Ensure computed property names are always checked (#37307)

This commit is contained in:
Wesley Wigham
2020-03-25 15:16:54 -07:00
committed by GitHub
parent 6c1e8aa0ad
commit 4567fc4f1a
5 changed files with 242 additions and 0 deletions
+9
View File
@@ -22808,6 +22808,15 @@ namespace ts {
let hasComputedStringProperty = false;
let hasComputedNumberProperty = false;
// Spreads may cause an early bail; ensure computed names are always checked (this is cached)
// As otherwise they may not be checked until exports for the type at this position are retrieved,
// which may never occur.
for (const elem of node.properties) {
if (elem.name && isComputedPropertyName(elem.name) && !isWellKnownSymbolSyntactically(elem.name)) {
checkComputedPropertyName(elem.name);
}
}
let offset = 0;
for (let i = 0; i < node.properties.length; i++) {
const memberDecl = node.properties[i];
@@ -0,0 +1,45 @@
//// [tests/cases/compiler/jsFileImportPreservedWhenUsed.ts] ////
//// [dash.d.ts]
type ObjectIterator<TObject, TResult> = (value: TObject[keyof TObject], key: string, collection: TObject) => TResult;
interface LoDashStatic {
mapValues<T extends object, TResult>(obj: T | null | undefined, callback: ObjectIterator<T, TResult>): { [P in keyof T]: TResult };
}
declare const _: LoDashStatic;
export = _;
//// [Consts.ts]
export const INDEX_FIELD = '__INDEX';
//// [index.js]
import * as _ from './dash';
import { INDEX_FIELD } from './Consts';
export class Test {
/**
* @param {object} obj
* @param {object} vm
*/
test(obj, vm) {
let index = 0;
vm.objects = _.mapValues(
obj,
object => ({ ...object, [INDEX_FIELD]: index++ }),
);
}
}
//// [Consts.js]
export const INDEX_FIELD = '__INDEX';
//// [index.js]
import * as _ from './dash';
import { INDEX_FIELD } from './Consts';
export class Test {
/**
* @param {object} obj
* @param {object} vm
*/
test(obj, vm) {
let index = 0;
vm.objects = _.mapValues(obj, object => ({ ...object, [INDEX_FIELD]: index++ }));
}
}
@@ -0,0 +1,82 @@
=== tests/cases/compiler/dash.d.ts ===
type ObjectIterator<TObject, TResult> = (value: TObject[keyof TObject], key: string, collection: TObject) => TResult;
>ObjectIterator : Symbol(ObjectIterator, Decl(dash.d.ts, 0, 0))
>TObject : Symbol(TObject, Decl(dash.d.ts, 0, 20))
>TResult : Symbol(TResult, Decl(dash.d.ts, 0, 28))
>value : Symbol(value, Decl(dash.d.ts, 0, 41))
>TObject : Symbol(TObject, Decl(dash.d.ts, 0, 20))
>TObject : Symbol(TObject, Decl(dash.d.ts, 0, 20))
>key : Symbol(key, Decl(dash.d.ts, 0, 71))
>collection : Symbol(collection, Decl(dash.d.ts, 0, 84))
>TObject : Symbol(TObject, Decl(dash.d.ts, 0, 20))
>TResult : Symbol(TResult, Decl(dash.d.ts, 0, 28))
interface LoDashStatic {
>LoDashStatic : Symbol(LoDashStatic, Decl(dash.d.ts, 0, 117))
mapValues<T extends object, TResult>(obj: T | null | undefined, callback: ObjectIterator<T, TResult>): { [P in keyof T]: TResult };
>mapValues : Symbol(LoDashStatic.mapValues, Decl(dash.d.ts, 2, 24))
>T : Symbol(T, Decl(dash.d.ts, 3, 14))
>TResult : Symbol(TResult, Decl(dash.d.ts, 3, 31))
>obj : Symbol(obj, Decl(dash.d.ts, 3, 41))
>T : Symbol(T, Decl(dash.d.ts, 3, 14))
>callback : Symbol(callback, Decl(dash.d.ts, 3, 67))
>ObjectIterator : Symbol(ObjectIterator, Decl(dash.d.ts, 0, 0))
>T : Symbol(T, Decl(dash.d.ts, 3, 14))
>TResult : Symbol(TResult, Decl(dash.d.ts, 3, 31))
>P : Symbol(P, Decl(dash.d.ts, 3, 110))
>T : Symbol(T, Decl(dash.d.ts, 3, 14))
>TResult : Symbol(TResult, Decl(dash.d.ts, 3, 31))
}
declare const _: LoDashStatic;
>_ : Symbol(_, Decl(dash.d.ts, 5, 13))
>LoDashStatic : Symbol(LoDashStatic, Decl(dash.d.ts, 0, 117))
export = _;
>_ : Symbol(_, Decl(dash.d.ts, 5, 13))
=== tests/cases/compiler/Consts.ts ===
export const INDEX_FIELD = '__INDEX';
>INDEX_FIELD : Symbol(INDEX_FIELD, Decl(Consts.ts, 0, 12))
=== tests/cases/compiler/index.js ===
import * as _ from './dash';
>_ : Symbol(_, Decl(index.js, 0, 6))
import { INDEX_FIELD } from './Consts';
>INDEX_FIELD : Symbol(INDEX_FIELD, Decl(index.js, 1, 8))
export class Test {
>Test : Symbol(Test, Decl(index.js, 1, 39))
/**
* @param {object} obj
* @param {object} vm
*/
test(obj, vm) {
>test : Symbol(Test.test, Decl(index.js, 3, 19))
>obj : Symbol(obj, Decl(index.js, 8, 9))
>vm : Symbol(vm, Decl(index.js, 8, 13))
let index = 0;
>index : Symbol(index, Decl(index.js, 9, 11))
vm.objects = _.mapValues(
>vm : Symbol(vm, Decl(index.js, 8, 13))
>_.mapValues : Symbol(LoDashStatic.mapValues, Decl(dash.d.ts, 2, 24))
>_ : Symbol(_, Decl(index.js, 0, 6))
>mapValues : Symbol(LoDashStatic.mapValues, Decl(dash.d.ts, 2, 24))
obj,
>obj : Symbol(obj, Decl(index.js, 8, 9))
object => ({ ...object, [INDEX_FIELD]: index++ }),
>object : Symbol(object, Decl(index.js, 11, 16))
>object : Symbol(object, Decl(index.js, 11, 16))
>[INDEX_FIELD] : Symbol([INDEX_FIELD], Decl(index.js, 12, 35))
>INDEX_FIELD : Symbol(INDEX_FIELD, Decl(index.js, 1, 8))
>index : Symbol(index, Decl(index.js, 9, 11))
);
}
}
@@ -0,0 +1,75 @@
=== tests/cases/compiler/dash.d.ts ===
type ObjectIterator<TObject, TResult> = (value: TObject[keyof TObject], key: string, collection: TObject) => TResult;
>ObjectIterator : ObjectIterator<TObject, TResult>
>value : TObject[keyof TObject]
>key : string
>collection : TObject
interface LoDashStatic {
mapValues<T extends object, TResult>(obj: T | null | undefined, callback: ObjectIterator<T, TResult>): { [P in keyof T]: TResult };
>mapValues : <T extends object, TResult>(obj: T | null | undefined, callback: ObjectIterator<T, TResult>) => { [P in keyof T]: TResult; }
>obj : T | null | undefined
>null : null
>callback : ObjectIterator<T, TResult>
}
declare const _: LoDashStatic;
>_ : LoDashStatic
export = _;
>_ : LoDashStatic
=== tests/cases/compiler/Consts.ts ===
export const INDEX_FIELD = '__INDEX';
>INDEX_FIELD : "__INDEX"
>'__INDEX' : "__INDEX"
=== tests/cases/compiler/index.js ===
import * as _ from './dash';
>_ : LoDashStatic
import { INDEX_FIELD } from './Consts';
>INDEX_FIELD : "__INDEX"
export class Test {
>Test : Test
/**
* @param {object} obj
* @param {object} vm
*/
test(obj, vm) {
>test : (obj: object, vm: object) => void
>obj : object
>vm : object
let index = 0;
>index : number
>0 : 0
vm.objects = _.mapValues(
>vm.objects = _.mapValues( obj, object => ({ ...object, [INDEX_FIELD]: index++ }), ) : object
>vm.objects : error
>vm : object
>objects : any
>_.mapValues( obj, object => ({ ...object, [INDEX_FIELD]: index++ }), ) : object
>_.mapValues : <T extends object, TResult>(obj: T | null | undefined, callback: (value: T[keyof T], key: string, collection: T) => TResult) => { [P in keyof T]: TResult; }
>_ : LoDashStatic
>mapValues : <T extends object, TResult>(obj: T | null | undefined, callback: (value: T[keyof T], key: string, collection: T) => TResult) => { [P in keyof T]: TResult; }
obj,
>obj : object
object => ({ ...object, [INDEX_FIELD]: index++ }),
>object => ({ ...object, [INDEX_FIELD]: index++ }) : (object: never) => any
>object : never
>({ ...object, [INDEX_FIELD]: index++ }) : error
>{ ...object, [INDEX_FIELD]: index++ } : error
>object : never
>[INDEX_FIELD] : number
>INDEX_FIELD : "__INDEX"
>index++ : number
>index : number
);
}
}
@@ -0,0 +1,31 @@
// @target: esnext
// @allowJs: true
// @strict: true
// @outDir: ./out
// @filename: dash.d.ts
type ObjectIterator<TObject, TResult> = (value: TObject[keyof TObject], key: string, collection: TObject) => TResult;
interface LoDashStatic {
mapValues<T extends object, TResult>(obj: T | null | undefined, callback: ObjectIterator<T, TResult>): { [P in keyof T]: TResult };
}
declare const _: LoDashStatic;
export = _;
// @filename: Consts.ts
export const INDEX_FIELD = '__INDEX';
// @filename: index.js
import * as _ from './dash';
import { INDEX_FIELD } from './Consts';
export class Test {
/**
* @param {object} obj
* @param {object} vm
*/
test(obj, vm) {
let index = 0;
vm.objects = _.mapValues(
obj,
object => ({ ...object, [INDEX_FIELD]: index++ }),
);
}
}