From c5a81edfb1515c694ffd1fcc2639c288d5f71695 Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Tue, 3 May 2016 14:51:30 -0700 Subject: [PATCH 1/6] Fix #8423: Remove undefined while getting the type of the first argument of then signature --- src/compiler/checker.ts | 2 +- .../asyncFunctionsAndStrictNullChecks.js | 33 ++++++ .../asyncFunctionsAndStrictNullChecks.symbols | 102 +++++++++++++++++ .../asyncFunctionsAndStrictNullChecks.types | 103 ++++++++++++++++++ .../asyncFunctionsAndStrictNullChecks.ts | 18 +++ 5 files changed, 257 insertions(+), 1 deletion(-) create mode 100644 tests/baselines/reference/asyncFunctionsAndStrictNullChecks.js create mode 100644 tests/baselines/reference/asyncFunctionsAndStrictNullChecks.symbols create mode 100644 tests/baselines/reference/asyncFunctionsAndStrictNullChecks.types create mode 100644 tests/cases/compiler/asyncFunctionsAndStrictNullChecks.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index bf0ba6beb25..68a0c23a301 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -13443,7 +13443,7 @@ namespace ts { } function getTypeOfFirstParameterOfSignature(signature: Signature) { - return getTypeAtPosition(signature, 0); + return getTypeWithFacts(getTypeAtPosition(signature, 0), TypeFacts.NEUndefined); } /** diff --git a/tests/baselines/reference/asyncFunctionsAndStrictNullChecks.js b/tests/baselines/reference/asyncFunctionsAndStrictNullChecks.js new file mode 100644 index 00000000000..32fc769e4f3 --- /dev/null +++ b/tests/baselines/reference/asyncFunctionsAndStrictNullChecks.js @@ -0,0 +1,33 @@ +//// [asyncFunctionsAndStrictNullChecks.ts] + +declare namespace Windows.Foundation { + interface IPromise { + then(success?: (value: TResult) => IPromise, error?: (error: any) => IPromise, progress?: (progress: any) => void): IPromise; + then(success?: (value: TResult) => IPromise, error?: (error: any) => U, progress?: (progress: any) => void): IPromise; + then(success?: (value: TResult) => U, error?: (error: any) => IPromise, progress?: (progress: any) => void): IPromise; + then(success?: (value: TResult) => U, error?: (error: any) => U, progress?: (progress: any) => void): IPromise; + done(success?: (value: TResult) => any, error?: (error: any) => any, progress?: (progress: any) => void): void; + + cancel(): void; + } +} + +async function sample(promise: Windows.Foundation.IPromise) { + var number = await promise; +} + + +//// [asyncFunctionsAndStrictNullChecks.js] +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator.throw(value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments)).next()); + }); +}; +function sample(promise) { + return __awaiter(this, void 0, void 0, function* () { + var number = yield promise; + }); +} diff --git a/tests/baselines/reference/asyncFunctionsAndStrictNullChecks.symbols b/tests/baselines/reference/asyncFunctionsAndStrictNullChecks.symbols new file mode 100644 index 00000000000..593702a35fd --- /dev/null +++ b/tests/baselines/reference/asyncFunctionsAndStrictNullChecks.symbols @@ -0,0 +1,102 @@ +=== tests/cases/compiler/asyncFunctionsAndStrictNullChecks.ts === + +declare namespace Windows.Foundation { +>Windows : Symbol(Windows, Decl(asyncFunctionsAndStrictNullChecks.ts, 0, 0)) +>Foundation : Symbol(Foundation, Decl(asyncFunctionsAndStrictNullChecks.ts, 1, 26)) + + interface IPromise { +>IPromise : Symbol(IPromise, Decl(asyncFunctionsAndStrictNullChecks.ts, 1, 38)) +>TResult : Symbol(TResult, Decl(asyncFunctionsAndStrictNullChecks.ts, 2, 23)) + + then(success?: (value: TResult) => IPromise, error?: (error: any) => IPromise, progress?: (progress: any) => void): IPromise; +>then : Symbol(IPromise.then, Decl(asyncFunctionsAndStrictNullChecks.ts, 2, 33), Decl(asyncFunctionsAndStrictNullChecks.ts, 3, 145), Decl(asyncFunctionsAndStrictNullChecks.ts, 4, 135), Decl(asyncFunctionsAndStrictNullChecks.ts, 5, 135)) +>U : Symbol(U, Decl(asyncFunctionsAndStrictNullChecks.ts, 3, 13)) +>success : Symbol(success, Decl(asyncFunctionsAndStrictNullChecks.ts, 3, 16)) +>value : Symbol(value, Decl(asyncFunctionsAndStrictNullChecks.ts, 3, 27)) +>TResult : Symbol(TResult, Decl(asyncFunctionsAndStrictNullChecks.ts, 2, 23)) +>IPromise : Symbol(IPromise, Decl(asyncFunctionsAndStrictNullChecks.ts, 1, 38)) +>U : Symbol(U, Decl(asyncFunctionsAndStrictNullChecks.ts, 3, 13)) +>error : Symbol(error, Decl(asyncFunctionsAndStrictNullChecks.ts, 3, 58)) +>error : Symbol(error, Decl(asyncFunctionsAndStrictNullChecks.ts, 3, 68)) +>IPromise : Symbol(IPromise, Decl(asyncFunctionsAndStrictNullChecks.ts, 1, 38)) +>U : Symbol(U, Decl(asyncFunctionsAndStrictNullChecks.ts, 3, 13)) +>progress : Symbol(progress, Decl(asyncFunctionsAndStrictNullChecks.ts, 3, 95)) +>progress : Symbol(progress, Decl(asyncFunctionsAndStrictNullChecks.ts, 3, 108)) +>IPromise : Symbol(IPromise, Decl(asyncFunctionsAndStrictNullChecks.ts, 1, 38)) +>U : Symbol(U, Decl(asyncFunctionsAndStrictNullChecks.ts, 3, 13)) + + then(success?: (value: TResult) => IPromise, error?: (error: any) => U, progress?: (progress: any) => void): IPromise; +>then : Symbol(IPromise.then, Decl(asyncFunctionsAndStrictNullChecks.ts, 2, 33), Decl(asyncFunctionsAndStrictNullChecks.ts, 3, 145), Decl(asyncFunctionsAndStrictNullChecks.ts, 4, 135), Decl(asyncFunctionsAndStrictNullChecks.ts, 5, 135)) +>U : Symbol(U, Decl(asyncFunctionsAndStrictNullChecks.ts, 4, 13)) +>success : Symbol(success, Decl(asyncFunctionsAndStrictNullChecks.ts, 4, 16)) +>value : Symbol(value, Decl(asyncFunctionsAndStrictNullChecks.ts, 4, 27)) +>TResult : Symbol(TResult, Decl(asyncFunctionsAndStrictNullChecks.ts, 2, 23)) +>IPromise : Symbol(IPromise, Decl(asyncFunctionsAndStrictNullChecks.ts, 1, 38)) +>U : Symbol(U, Decl(asyncFunctionsAndStrictNullChecks.ts, 4, 13)) +>error : Symbol(error, Decl(asyncFunctionsAndStrictNullChecks.ts, 4, 58)) +>error : Symbol(error, Decl(asyncFunctionsAndStrictNullChecks.ts, 4, 68)) +>U : Symbol(U, Decl(asyncFunctionsAndStrictNullChecks.ts, 4, 13)) +>progress : Symbol(progress, Decl(asyncFunctionsAndStrictNullChecks.ts, 4, 85)) +>progress : Symbol(progress, Decl(asyncFunctionsAndStrictNullChecks.ts, 4, 98)) +>IPromise : Symbol(IPromise, Decl(asyncFunctionsAndStrictNullChecks.ts, 1, 38)) +>U : Symbol(U, Decl(asyncFunctionsAndStrictNullChecks.ts, 4, 13)) + + then(success?: (value: TResult) => U, error?: (error: any) => IPromise, progress?: (progress: any) => void): IPromise; +>then : Symbol(IPromise.then, Decl(asyncFunctionsAndStrictNullChecks.ts, 2, 33), Decl(asyncFunctionsAndStrictNullChecks.ts, 3, 145), Decl(asyncFunctionsAndStrictNullChecks.ts, 4, 135), Decl(asyncFunctionsAndStrictNullChecks.ts, 5, 135)) +>U : Symbol(U, Decl(asyncFunctionsAndStrictNullChecks.ts, 5, 13)) +>success : Symbol(success, Decl(asyncFunctionsAndStrictNullChecks.ts, 5, 16)) +>value : Symbol(value, Decl(asyncFunctionsAndStrictNullChecks.ts, 5, 27)) +>TResult : Symbol(TResult, Decl(asyncFunctionsAndStrictNullChecks.ts, 2, 23)) +>U : Symbol(U, Decl(asyncFunctionsAndStrictNullChecks.ts, 5, 13)) +>error : Symbol(error, Decl(asyncFunctionsAndStrictNullChecks.ts, 5, 48)) +>error : Symbol(error, Decl(asyncFunctionsAndStrictNullChecks.ts, 5, 58)) +>IPromise : Symbol(IPromise, Decl(asyncFunctionsAndStrictNullChecks.ts, 1, 38)) +>U : Symbol(U, Decl(asyncFunctionsAndStrictNullChecks.ts, 5, 13)) +>progress : Symbol(progress, Decl(asyncFunctionsAndStrictNullChecks.ts, 5, 85)) +>progress : Symbol(progress, Decl(asyncFunctionsAndStrictNullChecks.ts, 5, 98)) +>IPromise : Symbol(IPromise, Decl(asyncFunctionsAndStrictNullChecks.ts, 1, 38)) +>U : Symbol(U, Decl(asyncFunctionsAndStrictNullChecks.ts, 5, 13)) + + then(success?: (value: TResult) => U, error?: (error: any) => U, progress?: (progress: any) => void): IPromise; +>then : Symbol(IPromise.then, Decl(asyncFunctionsAndStrictNullChecks.ts, 2, 33), Decl(asyncFunctionsAndStrictNullChecks.ts, 3, 145), Decl(asyncFunctionsAndStrictNullChecks.ts, 4, 135), Decl(asyncFunctionsAndStrictNullChecks.ts, 5, 135)) +>U : Symbol(U, Decl(asyncFunctionsAndStrictNullChecks.ts, 6, 13)) +>success : Symbol(success, Decl(asyncFunctionsAndStrictNullChecks.ts, 6, 16)) +>value : Symbol(value, Decl(asyncFunctionsAndStrictNullChecks.ts, 6, 27)) +>TResult : Symbol(TResult, Decl(asyncFunctionsAndStrictNullChecks.ts, 2, 23)) +>U : Symbol(U, Decl(asyncFunctionsAndStrictNullChecks.ts, 6, 13)) +>error : Symbol(error, Decl(asyncFunctionsAndStrictNullChecks.ts, 6, 48)) +>error : Symbol(error, Decl(asyncFunctionsAndStrictNullChecks.ts, 6, 58)) +>U : Symbol(U, Decl(asyncFunctionsAndStrictNullChecks.ts, 6, 13)) +>progress : Symbol(progress, Decl(asyncFunctionsAndStrictNullChecks.ts, 6, 75)) +>progress : Symbol(progress, Decl(asyncFunctionsAndStrictNullChecks.ts, 6, 88)) +>IPromise : Symbol(IPromise, Decl(asyncFunctionsAndStrictNullChecks.ts, 1, 38)) +>U : Symbol(U, Decl(asyncFunctionsAndStrictNullChecks.ts, 6, 13)) + + done(success?: (value: TResult) => any, error?: (error: any) => any, progress?: (progress: any) => void): void; +>done : Symbol(IPromise.done, Decl(asyncFunctionsAndStrictNullChecks.ts, 6, 125)) +>U : Symbol(U, Decl(asyncFunctionsAndStrictNullChecks.ts, 7, 13)) +>success : Symbol(success, Decl(asyncFunctionsAndStrictNullChecks.ts, 7, 16)) +>value : Symbol(value, Decl(asyncFunctionsAndStrictNullChecks.ts, 7, 27)) +>TResult : Symbol(TResult, Decl(asyncFunctionsAndStrictNullChecks.ts, 2, 23)) +>error : Symbol(error, Decl(asyncFunctionsAndStrictNullChecks.ts, 7, 50)) +>error : Symbol(error, Decl(asyncFunctionsAndStrictNullChecks.ts, 7, 60)) +>progress : Symbol(progress, Decl(asyncFunctionsAndStrictNullChecks.ts, 7, 79)) +>progress : Symbol(progress, Decl(asyncFunctionsAndStrictNullChecks.ts, 7, 92)) + + cancel(): void; +>cancel : Symbol(IPromise.cancel, Decl(asyncFunctionsAndStrictNullChecks.ts, 7, 122)) + } +} + +async function sample(promise: Windows.Foundation.IPromise) { +>sample : Symbol(sample, Decl(asyncFunctionsAndStrictNullChecks.ts, 11, 1)) +>promise : Symbol(promise, Decl(asyncFunctionsAndStrictNullChecks.ts, 13, 22)) +>Windows : Symbol(Windows, Decl(asyncFunctionsAndStrictNullChecks.ts, 0, 0)) +>Foundation : Symbol(Windows.Foundation, Decl(asyncFunctionsAndStrictNullChecks.ts, 1, 26)) +>IPromise : Symbol(Windows.Foundation.IPromise, Decl(asyncFunctionsAndStrictNullChecks.ts, 1, 38)) + + var number = await promise; +>number : Symbol(number, Decl(asyncFunctionsAndStrictNullChecks.ts, 14, 7)) +>promise : Symbol(promise, Decl(asyncFunctionsAndStrictNullChecks.ts, 13, 22)) +} + diff --git a/tests/baselines/reference/asyncFunctionsAndStrictNullChecks.types b/tests/baselines/reference/asyncFunctionsAndStrictNullChecks.types new file mode 100644 index 00000000000..4d3424b730c --- /dev/null +++ b/tests/baselines/reference/asyncFunctionsAndStrictNullChecks.types @@ -0,0 +1,103 @@ +=== tests/cases/compiler/asyncFunctionsAndStrictNullChecks.ts === + +declare namespace Windows.Foundation { +>Windows : any +>Foundation : any + + interface IPromise { +>IPromise : IPromise +>TResult : TResult + + then(success?: (value: TResult) => IPromise, error?: (error: any) => IPromise, progress?: (progress: any) => void): IPromise; +>then : { (success?: ((value: TResult) => IPromise) | undefined, error?: ((error: any) => IPromise) | undefined, progress?: ((progress: any) => void) | undefined): IPromise; (success?: ((value: TResult) => IPromise) | undefined, error?: ((error: any) => U) | undefined, progress?: ((progress: any) => void) | undefined): IPromise; (success?: ((value: TResult) => U) | undefined, error?: ((error: any) => IPromise) | undefined, progress?: ((progress: any) => void) | undefined): IPromise; (success?: ((value: TResult) => U) | undefined, error?: ((error: any) => U) | undefined, progress?: ((progress: any) => void) | undefined): IPromise; } +>U : U +>success : ((value: TResult) => IPromise) | undefined +>value : TResult +>TResult : TResult +>IPromise : IPromise +>U : U +>error : ((error: any) => IPromise) | undefined +>error : any +>IPromise : IPromise +>U : U +>progress : ((progress: any) => void) | undefined +>progress : any +>IPromise : IPromise +>U : U + + then(success?: (value: TResult) => IPromise, error?: (error: any) => U, progress?: (progress: any) => void): IPromise; +>then : { (success?: ((value: TResult) => IPromise) | undefined, error?: ((error: any) => IPromise) | undefined, progress?: ((progress: any) => void) | undefined): IPromise; (success?: ((value: TResult) => IPromise) | undefined, error?: ((error: any) => U) | undefined, progress?: ((progress: any) => void) | undefined): IPromise; (success?: ((value: TResult) => U) | undefined, error?: ((error: any) => IPromise) | undefined, progress?: ((progress: any) => void) | undefined): IPromise; (success?: ((value: TResult) => U) | undefined, error?: ((error: any) => U) | undefined, progress?: ((progress: any) => void) | undefined): IPromise; } +>U : U +>success : ((value: TResult) => IPromise) | undefined +>value : TResult +>TResult : TResult +>IPromise : IPromise +>U : U +>error : ((error: any) => U) | undefined +>error : any +>U : U +>progress : ((progress: any) => void) | undefined +>progress : any +>IPromise : IPromise +>U : U + + then(success?: (value: TResult) => U, error?: (error: any) => IPromise, progress?: (progress: any) => void): IPromise; +>then : { (success?: ((value: TResult) => IPromise) | undefined, error?: ((error: any) => IPromise) | undefined, progress?: ((progress: any) => void) | undefined): IPromise; (success?: ((value: TResult) => IPromise) | undefined, error?: ((error: any) => U) | undefined, progress?: ((progress: any) => void) | undefined): IPromise; (success?: ((value: TResult) => U) | undefined, error?: ((error: any) => IPromise) | undefined, progress?: ((progress: any) => void) | undefined): IPromise; (success?: ((value: TResult) => U) | undefined, error?: ((error: any) => U) | undefined, progress?: ((progress: any) => void) | undefined): IPromise; } +>U : U +>success : ((value: TResult) => U) | undefined +>value : TResult +>TResult : TResult +>U : U +>error : ((error: any) => IPromise) | undefined +>error : any +>IPromise : IPromise +>U : U +>progress : ((progress: any) => void) | undefined +>progress : any +>IPromise : IPromise +>U : U + + then(success?: (value: TResult) => U, error?: (error: any) => U, progress?: (progress: any) => void): IPromise; +>then : { (success?: ((value: TResult) => IPromise) | undefined, error?: ((error: any) => IPromise) | undefined, progress?: ((progress: any) => void) | undefined): IPromise; (success?: ((value: TResult) => IPromise) | undefined, error?: ((error: any) => U) | undefined, progress?: ((progress: any) => void) | undefined): IPromise; (success?: ((value: TResult) => U) | undefined, error?: ((error: any) => IPromise) | undefined, progress?: ((progress: any) => void) | undefined): IPromise; (success?: ((value: TResult) => U) | undefined, error?: ((error: any) => U) | undefined, progress?: ((progress: any) => void) | undefined): IPromise; } +>U : U +>success : ((value: TResult) => U) | undefined +>value : TResult +>TResult : TResult +>U : U +>error : ((error: any) => U) | undefined +>error : any +>U : U +>progress : ((progress: any) => void) | undefined +>progress : any +>IPromise : IPromise +>U : U + + done(success?: (value: TResult) => any, error?: (error: any) => any, progress?: (progress: any) => void): void; +>done : (success?: ((value: TResult) => any) | undefined, error?: ((error: any) => any) | undefined, progress?: ((progress: any) => void) | undefined) => void +>U : U +>success : ((value: TResult) => any) | undefined +>value : TResult +>TResult : TResult +>error : ((error: any) => any) | undefined +>error : any +>progress : ((progress: any) => void) | undefined +>progress : any + + cancel(): void; +>cancel : () => void + } +} + +async function sample(promise: Windows.Foundation.IPromise) { +>sample : (promise: Windows.Foundation.IPromise) => Promise +>promise : Windows.Foundation.IPromise +>Windows : any +>Foundation : any +>IPromise : Windows.Foundation.IPromise + + var number = await promise; +>number : number +>await promise : number +>promise : Windows.Foundation.IPromise +} + diff --git a/tests/cases/compiler/asyncFunctionsAndStrictNullChecks.ts b/tests/cases/compiler/asyncFunctionsAndStrictNullChecks.ts new file mode 100644 index 00000000000..f9a751314e9 --- /dev/null +++ b/tests/cases/compiler/asyncFunctionsAndStrictNullChecks.ts @@ -0,0 +1,18 @@ +// @target: es6 +// @strictNullChecks: true + +declare namespace Windows.Foundation { + interface IPromise { + then(success?: (value: TResult) => IPromise, error?: (error: any) => IPromise, progress?: (progress: any) => void): IPromise; + then(success?: (value: TResult) => IPromise, error?: (error: any) => U, progress?: (progress: any) => void): IPromise; + then(success?: (value: TResult) => U, error?: (error: any) => IPromise, progress?: (progress: any) => void): IPromise; + then(success?: (value: TResult) => U, error?: (error: any) => U, progress?: (progress: any) => void): IPromise; + done(success?: (value: TResult) => any, error?: (error: any) => any, progress?: (progress: any) => void): void; + + cancel(): void; + } +} + +async function sample(promise: Windows.Foundation.IPromise) { + var number = await promise; +} From b4baee492f25d0fed94e60ec6fbde29851991f41 Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Tue, 3 May 2016 14:52:41 -0700 Subject: [PATCH 2/6] Polyfill String.prototyp.fill --- src/compiler/commandLineParser.ts | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts index bd9373e2d3f..c53e2fcc2ec 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -143,7 +143,7 @@ namespace ts { name: "out", type: "string", isFilePath: false, // This is intentionally broken to support compatability with existing tsconfig files - // for correct behaviour, please use outFile + // for correct behaviour, please use outFile paramType: Diagnostics.FILE, }, { @@ -464,7 +464,7 @@ namespace ts { /* @internal */ export function parseCustomTypeOption(opt: CommandLineOptionOfCustomType, value: string, errors: Diagnostic[]) { - const key = (value || "").trim().toLowerCase(); + const key = trimString((value || "")).toLowerCase(); const map = opt.type; if (hasProperty(map, key)) { return map[key]; @@ -476,7 +476,7 @@ namespace ts { /* @internal */ export function parseListTypeOption(opt: CommandLineOptionOfListType, value: string, errors: Diagnostic[]): (string | number)[] { - const values = (value || "").trim().split(","); + const values = trimString((value || "")).split(","); switch (opt.element.type) { case "number": return ts.map(values, parseInt); @@ -601,7 +601,7 @@ namespace ts { * Read tsconfig.json file * @param fileName The path to the config file */ - export function readConfigFile(fileName: string, readFile: (path: string) => string): { config?: any; error?: Diagnostic } { + export function readConfigFile(fileName: string, readFile: (path: string) => string): { config?: any; error?: Diagnostic } { let text = ""; try { text = readFile(fileName); @@ -775,7 +775,7 @@ namespace ts { defaultOptions: CompilerOptions | TypingOptions, diagnosticMessage: DiagnosticMessage, errors: Diagnostic[]) { if (!jsonOptions) { - return ; + return; } const optionNameMap = arrayToMap(optionDeclarations, opt => opt.name); @@ -829,4 +829,8 @@ namespace ts { function convertJsonOptionOfListType(option: CommandLineOptionOfListType, values: any[], basePath: string, errors: Diagnostic[]): any[] { return filter(map(values, v => convertJsonOption(option.element, v, basePath, errors)), v => !!v); } + + function trimString(s: string) { + return typeof s.trim === "function" ? s.trim() : s.replace(/^[\s]+|[\s]+$/g, ""); + } } From 9ad08324d8086ca221479aad25ea41bd33cd64c4 Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Tue, 3 May 2016 15:53:17 -0700 Subject: [PATCH 3/6] Fix #8357: Remove optionality for the definition of `IteratorResult` --- src/lib/es2015.iterable.d.ts | 2 +- .../reference/iteratorsAndStrictNullChecks.js | 22 +++++++++++ .../iteratorsAndStrictNullChecks.symbols | 25 +++++++++++++ .../iteratorsAndStrictNullChecks.types | 37 +++++++++++++++++++ .../compiler/iteratorsAndStrictNullChecks.ts | 12 ++++++ 5 files changed, 97 insertions(+), 1 deletion(-) create mode 100644 tests/baselines/reference/iteratorsAndStrictNullChecks.js create mode 100644 tests/baselines/reference/iteratorsAndStrictNullChecks.symbols create mode 100644 tests/baselines/reference/iteratorsAndStrictNullChecks.types create mode 100644 tests/cases/compiler/iteratorsAndStrictNullChecks.ts diff --git a/src/lib/es2015.iterable.d.ts b/src/lib/es2015.iterable.d.ts index 85c95a73bb0..4a9e321d2f6 100644 --- a/src/lib/es2015.iterable.d.ts +++ b/src/lib/es2015.iterable.d.ts @@ -2,7 +2,7 @@ interface IteratorResult { done: boolean; - value?: T; + value: T; } interface Iterator { diff --git a/tests/baselines/reference/iteratorsAndStrictNullChecks.js b/tests/baselines/reference/iteratorsAndStrictNullChecks.js new file mode 100644 index 00000000000..97007917de5 --- /dev/null +++ b/tests/baselines/reference/iteratorsAndStrictNullChecks.js @@ -0,0 +1,22 @@ +//// [iteratorsAndStrictNullChecks.ts] + +// for..of +for (const x of ["a", "b"]) { + x.substring; +} + +// Spread +const xs = [1, 2, 3]; +const ys = [4, 5]; +xs.push(...ys); + + +//// [iteratorsAndStrictNullChecks.js] +// for..of +for (const x of ["a", "b"]) { + x.substring; +} +// Spread +const xs = [1, 2, 3]; +const ys = [4, 5]; +xs.push(...ys); diff --git a/tests/baselines/reference/iteratorsAndStrictNullChecks.symbols b/tests/baselines/reference/iteratorsAndStrictNullChecks.symbols new file mode 100644 index 00000000000..8201a845a0f --- /dev/null +++ b/tests/baselines/reference/iteratorsAndStrictNullChecks.symbols @@ -0,0 +1,25 @@ +=== tests/cases/compiler/iteratorsAndStrictNullChecks.ts === + +// for..of +for (const x of ["a", "b"]) { +>x : Symbol(x, Decl(iteratorsAndStrictNullChecks.ts, 2, 10)) + + x.substring; +>x.substring : Symbol(String.substring, Decl(lib.es5.d.ts, --, --)) +>x : Symbol(x, Decl(iteratorsAndStrictNullChecks.ts, 2, 10)) +>substring : Symbol(String.substring, Decl(lib.es5.d.ts, --, --)) +} + +// Spread +const xs = [1, 2, 3]; +>xs : Symbol(xs, Decl(iteratorsAndStrictNullChecks.ts, 7, 5)) + +const ys = [4, 5]; +>ys : Symbol(ys, Decl(iteratorsAndStrictNullChecks.ts, 8, 5)) + +xs.push(...ys); +>xs.push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) +>xs : Symbol(xs, Decl(iteratorsAndStrictNullChecks.ts, 7, 5)) +>push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) +>ys : Symbol(ys, Decl(iteratorsAndStrictNullChecks.ts, 8, 5)) + diff --git a/tests/baselines/reference/iteratorsAndStrictNullChecks.types b/tests/baselines/reference/iteratorsAndStrictNullChecks.types new file mode 100644 index 00000000000..ce1d7430f77 --- /dev/null +++ b/tests/baselines/reference/iteratorsAndStrictNullChecks.types @@ -0,0 +1,37 @@ +=== tests/cases/compiler/iteratorsAndStrictNullChecks.ts === + +// for..of +for (const x of ["a", "b"]) { +>x : string +>["a", "b"] : string[] +>"a" : string +>"b" : string + + x.substring; +>x.substring : (start: number, end?: number | undefined) => string +>x : string +>substring : (start: number, end?: number | undefined) => string +} + +// Spread +const xs = [1, 2, 3]; +>xs : number[] +>[1, 2, 3] : number[] +>1 : number +>2 : number +>3 : number + +const ys = [4, 5]; +>ys : number[] +>[4, 5] : number[] +>4 : number +>5 : number + +xs.push(...ys); +>xs.push(...ys) : number +>xs.push : (...items: number[]) => number +>xs : number[] +>push : (...items: number[]) => number +>...ys : number +>ys : number[] + diff --git a/tests/cases/compiler/iteratorsAndStrictNullChecks.ts b/tests/cases/compiler/iteratorsAndStrictNullChecks.ts new file mode 100644 index 00000000000..5bc43343873 --- /dev/null +++ b/tests/cases/compiler/iteratorsAndStrictNullChecks.ts @@ -0,0 +1,12 @@ +// @target : ES6 +// @strictNullChecks: true + +// for..of +for (const x of ["a", "b"]) { + x.substring; +} + +// Spread +const xs = [1, 2, 3]; +const ys = [4, 5]; +xs.push(...ys); From 9ff66fbb5edfaafe7d1877dba68e6f2659b8877a Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Tue, 3 May 2016 16:09:01 -0700 Subject: [PATCH 4/6] Code review comments --- src/compiler/checker.ts | 4 +- .../asyncFunctionsAndStrictNullChecks.js | 15 ++++++++ .../asyncFunctionsAndStrictNullChecks.symbols | 34 +++++++++++++++++ .../asyncFunctionsAndStrictNullChecks.types | 38 +++++++++++++++++++ .../asyncFunctionsAndStrictNullChecks.ts | 9 +++++ 5 files changed, 98 insertions(+), 2 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 68a0c23a301..6d36e86aad0 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -13428,7 +13428,7 @@ namespace ts { return undefined; } - const onfulfilledParameterType = getUnionType(map(thenSignatures, getTypeOfFirstParameterOfSignature)); + const onfulfilledParameterType = getTypeWithFacts(getUnionType(map(thenSignatures, getTypeOfFirstParameterOfSignature)), TypeFacts.NEUndefined); if (onfulfilledParameterType.flags & TypeFlags.Any) { return undefined; } @@ -13443,7 +13443,7 @@ namespace ts { } function getTypeOfFirstParameterOfSignature(signature: Signature) { - return getTypeWithFacts(getTypeAtPosition(signature, 0), TypeFacts.NEUndefined); + return getTypeAtPosition(signature, 0); } /** diff --git a/tests/baselines/reference/asyncFunctionsAndStrictNullChecks.js b/tests/baselines/reference/asyncFunctionsAndStrictNullChecks.js index 32fc769e4f3..3e351c37046 100644 --- a/tests/baselines/reference/asyncFunctionsAndStrictNullChecks.js +++ b/tests/baselines/reference/asyncFunctionsAndStrictNullChecks.js @@ -15,6 +15,15 @@ declare namespace Windows.Foundation { async function sample(promise: Windows.Foundation.IPromise) { var number = await promise; } + + +declare function resolve1(value: T): Promise; +declare function resolve2(value: T): Windows.Foundation.IPromise; + +async function sample2(x?: number) { + let x1 = await resolve1(x); + let x2 = await resolve2(x); +} //// [asyncFunctionsAndStrictNullChecks.js] @@ -31,3 +40,9 @@ function sample(promise) { var number = yield promise; }); } +function sample2(x) { + return __awaiter(this, void 0, void 0, function* () { + let x1 = yield resolve1(x); + let x2 = yield resolve2(x); + }); +} diff --git a/tests/baselines/reference/asyncFunctionsAndStrictNullChecks.symbols b/tests/baselines/reference/asyncFunctionsAndStrictNullChecks.symbols index 593702a35fd..2d10183133d 100644 --- a/tests/baselines/reference/asyncFunctionsAndStrictNullChecks.symbols +++ b/tests/baselines/reference/asyncFunctionsAndStrictNullChecks.symbols @@ -100,3 +100,37 @@ async function sample(promise: Windows.Foundation.IPromise) { >promise : Symbol(promise, Decl(asyncFunctionsAndStrictNullChecks.ts, 13, 22)) } + +declare function resolve1(value: T): Promise; +>resolve1 : Symbol(resolve1, Decl(asyncFunctionsAndStrictNullChecks.ts, 15, 1)) +>T : Symbol(T, Decl(asyncFunctionsAndStrictNullChecks.ts, 18, 26)) +>value : Symbol(value, Decl(asyncFunctionsAndStrictNullChecks.ts, 18, 29)) +>T : Symbol(T, Decl(asyncFunctionsAndStrictNullChecks.ts, 18, 26)) +>Promise : Symbol(Promise, Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --)) +>T : Symbol(T, Decl(asyncFunctionsAndStrictNullChecks.ts, 18, 26)) + +declare function resolve2(value: T): Windows.Foundation.IPromise; +>resolve2 : Symbol(resolve2, Decl(asyncFunctionsAndStrictNullChecks.ts, 18, 51)) +>T : Symbol(T, Decl(asyncFunctionsAndStrictNullChecks.ts, 19, 26)) +>value : Symbol(value, Decl(asyncFunctionsAndStrictNullChecks.ts, 19, 29)) +>T : Symbol(T, Decl(asyncFunctionsAndStrictNullChecks.ts, 19, 26)) +>Windows : Symbol(Windows, Decl(asyncFunctionsAndStrictNullChecks.ts, 0, 0)) +>Foundation : Symbol(Windows.Foundation, Decl(asyncFunctionsAndStrictNullChecks.ts, 1, 26)) +>IPromise : Symbol(Windows.Foundation.IPromise, Decl(asyncFunctionsAndStrictNullChecks.ts, 1, 38)) +>T : Symbol(T, Decl(asyncFunctionsAndStrictNullChecks.ts, 19, 26)) + +async function sample2(x?: number) { +>sample2 : Symbol(sample2, Decl(asyncFunctionsAndStrictNullChecks.ts, 19, 71)) +>x : Symbol(x, Decl(asyncFunctionsAndStrictNullChecks.ts, 21, 23)) + + let x1 = await resolve1(x); +>x1 : Symbol(x1, Decl(asyncFunctionsAndStrictNullChecks.ts, 22, 7)) +>resolve1 : Symbol(resolve1, Decl(asyncFunctionsAndStrictNullChecks.ts, 15, 1)) +>x : Symbol(x, Decl(asyncFunctionsAndStrictNullChecks.ts, 21, 23)) + + let x2 = await resolve2(x); +>x2 : Symbol(x2, Decl(asyncFunctionsAndStrictNullChecks.ts, 23, 7)) +>resolve2 : Symbol(resolve2, Decl(asyncFunctionsAndStrictNullChecks.ts, 18, 51)) +>x : Symbol(x, Decl(asyncFunctionsAndStrictNullChecks.ts, 21, 23)) +} + diff --git a/tests/baselines/reference/asyncFunctionsAndStrictNullChecks.types b/tests/baselines/reference/asyncFunctionsAndStrictNullChecks.types index 4d3424b730c..f4eb4f7fa05 100644 --- a/tests/baselines/reference/asyncFunctionsAndStrictNullChecks.types +++ b/tests/baselines/reference/asyncFunctionsAndStrictNullChecks.types @@ -101,3 +101,41 @@ async function sample(promise: Windows.Foundation.IPromise) { >promise : Windows.Foundation.IPromise } + +declare function resolve1(value: T): Promise; +>resolve1 : (value: T) => Promise +>T : T +>value : T +>T : T +>Promise : Promise +>T : T + +declare function resolve2(value: T): Windows.Foundation.IPromise; +>resolve2 : (value: T) => Windows.Foundation.IPromise +>T : T +>value : T +>T : T +>Windows : any +>Foundation : any +>IPromise : Windows.Foundation.IPromise +>T : T + +async function sample2(x?: number) { +>sample2 : (x?: number | undefined) => Promise +>x : number | undefined + + let x1 = await resolve1(x); +>x1 : number | undefined +>await resolve1(x) : number | undefined +>resolve1(x) : Promise +>resolve1 : (value: T) => Promise +>x : number | undefined + + let x2 = await resolve2(x); +>x2 : number | undefined +>await resolve2(x) : number | undefined +>resolve2(x) : Windows.Foundation.IPromise +>resolve2 : (value: T) => Windows.Foundation.IPromise +>x : number | undefined +} + diff --git a/tests/cases/compiler/asyncFunctionsAndStrictNullChecks.ts b/tests/cases/compiler/asyncFunctionsAndStrictNullChecks.ts index f9a751314e9..9b7185f8853 100644 --- a/tests/cases/compiler/asyncFunctionsAndStrictNullChecks.ts +++ b/tests/cases/compiler/asyncFunctionsAndStrictNullChecks.ts @@ -16,3 +16,12 @@ declare namespace Windows.Foundation { async function sample(promise: Windows.Foundation.IPromise) { var number = await promise; } + + +declare function resolve1(value: T): Promise; +declare function resolve2(value: T): Windows.Foundation.IPromise; + +async function sample2(x?: number) { + let x1 = await resolve1(x); + let x2 = await resolve2(x); +} From ccad31bf24ffce8380ff3c99702206623a7a1907 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Tue, 3 May 2016 17:05:12 -0700 Subject: [PATCH 5/6] Equality comparisons for null/undefined in strict null checking mode --- src/compiler/checker.ts | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index df3528a17ac..27efc2eec5a 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -12053,6 +12053,10 @@ namespace ts { return sourceType; } + function isTypeEqualityComparableTo(source: Type, target: Type) { + return (target.flags & TypeFlags.Nullable) !== 0 || isTypeComparableTo(source, target); + } + function checkBinaryExpression(node: BinaryExpression, contextualMapper?: TypeMapper) { return checkBinaryLikeExpression(node.left, node.operatorToken, node.right, contextualMapper, node); } @@ -12166,15 +12170,17 @@ namespace ts { case SyntaxKind.GreaterThanToken: case SyntaxKind.LessThanEqualsToken: case SyntaxKind.GreaterThanEqualsToken: - if (!checkForDisallowedESSymbolOperand(operator)) { - return booleanType; + if (checkForDisallowedESSymbolOperand(operator)) { + if (!isTypeComparableTo(leftType, rightType) && !isTypeComparableTo(rightType, leftType)) { + reportOperatorError(); + } } - // Fall through + return booleanType; case SyntaxKind.EqualsEqualsToken: case SyntaxKind.ExclamationEqualsToken: case SyntaxKind.EqualsEqualsEqualsToken: case SyntaxKind.ExclamationEqualsEqualsToken: - if (!isTypeComparableTo(leftType, rightType) && !isTypeComparableTo(rightType, leftType)) { + if (!isTypeEqualityComparableTo(leftType, rightType) && !isTypeEqualityComparableTo(rightType, leftType)) { reportOperatorError(); } return booleanType; From e828fce952790c3fdef3dd16c929c2504f5046ae Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Tue, 3 May 2016 17:05:23 -0700 Subject: [PATCH 6/6] Adding tests --- .../reference/equalityStrictNulls.errors.txt | 84 +++++++++++ .../reference/equalityStrictNulls.js | 136 ++++++++++++++++++ .../comparable/equalityStrictNulls.ts | 69 +++++++++ 3 files changed, 289 insertions(+) create mode 100644 tests/baselines/reference/equalityStrictNulls.errors.txt create mode 100644 tests/baselines/reference/equalityStrictNulls.js create mode 100644 tests/cases/conformance/types/typeRelationships/comparable/equalityStrictNulls.ts diff --git a/tests/baselines/reference/equalityStrictNulls.errors.txt b/tests/baselines/reference/equalityStrictNulls.errors.txt new file mode 100644 index 00000000000..54b581c87e6 --- /dev/null +++ b/tests/baselines/reference/equalityStrictNulls.errors.txt @@ -0,0 +1,84 @@ +tests/cases/conformance/types/typeRelationships/comparable/equalityStrictNulls.ts(60,9): error TS2365: Operator '>' cannot be applied to types 'number' and 'undefined'. +tests/cases/conformance/types/typeRelationships/comparable/equalityStrictNulls.ts(62,9): error TS2365: Operator '<' cannot be applied to types 'number' and 'undefined'. +tests/cases/conformance/types/typeRelationships/comparable/equalityStrictNulls.ts(64,9): error TS2365: Operator '>=' cannot be applied to types 'number' and 'undefined'. +tests/cases/conformance/types/typeRelationships/comparable/equalityStrictNulls.ts(66,9): error TS2365: Operator '<=' cannot be applied to types 'number' and 'undefined'. + + +==== tests/cases/conformance/types/typeRelationships/comparable/equalityStrictNulls.ts (4 errors) ==== + + function f1(x: string) { + if (x == undefined) { + } + if (x != undefined) { + } + if (x === undefined) { + } + if (x !== undefined) { + } + if (x == null) { + } + if (x != null) { + } + if (x === null) { + } + if (x !== null) { + } + if (undefined == x) { + } + if (undefined != x) { + } + if (undefined === x) { + } + if (undefined !== x) { + } + if (null == x) { + } + if (null != x) { + } + if (null === x) { + } + if (null !== x) { + } + } + + function f2() { + if (undefined == undefined) { + } + if (undefined == null) { + } + if (null == undefined) { + } + if (null == null) { + } + } + + function f3(a: number, b: boolean, c: { x: number }, d: number | string) { + if (a == null) { + } + if (b == null) { + } + if (c == null) { + } + if (d == null) { + } + } + + function f4(x: number) { + if (x > undefined) { + ~~~~~~~~~~~~~ +!!! error TS2365: Operator '>' cannot be applied to types 'number' and 'undefined'. + } + if (x < undefined) { + ~~~~~~~~~~~~~ +!!! error TS2365: Operator '<' cannot be applied to types 'number' and 'undefined'. + } + if (x >= undefined) { + ~~~~~~~~~~~~~~ +!!! error TS2365: Operator '>=' cannot be applied to types 'number' and 'undefined'. + } + if (x <= undefined) { + ~~~~~~~~~~~~~~ +!!! error TS2365: Operator '<=' cannot be applied to types 'number' and 'undefined'. + } + } + \ No newline at end of file diff --git a/tests/baselines/reference/equalityStrictNulls.js b/tests/baselines/reference/equalityStrictNulls.js new file mode 100644 index 00000000000..99ff801a52c --- /dev/null +++ b/tests/baselines/reference/equalityStrictNulls.js @@ -0,0 +1,136 @@ +//// [equalityStrictNulls.ts] + +function f1(x: string) { + if (x == undefined) { + } + if (x != undefined) { + } + if (x === undefined) { + } + if (x !== undefined) { + } + if (x == null) { + } + if (x != null) { + } + if (x === null) { + } + if (x !== null) { + } + if (undefined == x) { + } + if (undefined != x) { + } + if (undefined === x) { + } + if (undefined !== x) { + } + if (null == x) { + } + if (null != x) { + } + if (null === x) { + } + if (null !== x) { + } +} + +function f2() { + if (undefined == undefined) { + } + if (undefined == null) { + } + if (null == undefined) { + } + if (null == null) { + } +} + +function f3(a: number, b: boolean, c: { x: number }, d: number | string) { + if (a == null) { + } + if (b == null) { + } + if (c == null) { + } + if (d == null) { + } +} + +function f4(x: number) { + if (x > undefined) { + } + if (x < undefined) { + } + if (x >= undefined) { + } + if (x <= undefined) { + } +} + + +//// [equalityStrictNulls.js] +function f1(x) { + if (x == undefined) { + } + if (x != undefined) { + } + if (x === undefined) { + } + if (x !== undefined) { + } + if (x == null) { + } + if (x != null) { + } + if (x === null) { + } + if (x !== null) { + } + if (undefined == x) { + } + if (undefined != x) { + } + if (undefined === x) { + } + if (undefined !== x) { + } + if (null == x) { + } + if (null != x) { + } + if (null === x) { + } + if (null !== x) { + } +} +function f2() { + if (undefined == undefined) { + } + if (undefined == null) { + } + if (null == undefined) { + } + if (null == null) { + } +} +function f3(a, b, c, d) { + if (a == null) { + } + if (b == null) { + } + if (c == null) { + } + if (d == null) { + } +} +function f4(x) { + if (x > undefined) { + } + if (x < undefined) { + } + if (x >= undefined) { + } + if (x <= undefined) { + } +} diff --git a/tests/cases/conformance/types/typeRelationships/comparable/equalityStrictNulls.ts b/tests/cases/conformance/types/typeRelationships/comparable/equalityStrictNulls.ts new file mode 100644 index 00000000000..6b2744e8849 --- /dev/null +++ b/tests/cases/conformance/types/typeRelationships/comparable/equalityStrictNulls.ts @@ -0,0 +1,69 @@ +// @strictNullChecks: true + +function f1(x: string) { + if (x == undefined) { + } + if (x != undefined) { + } + if (x === undefined) { + } + if (x !== undefined) { + } + if (x == null) { + } + if (x != null) { + } + if (x === null) { + } + if (x !== null) { + } + if (undefined == x) { + } + if (undefined != x) { + } + if (undefined === x) { + } + if (undefined !== x) { + } + if (null == x) { + } + if (null != x) { + } + if (null === x) { + } + if (null !== x) { + } +} + +function f2() { + if (undefined == undefined) { + } + if (undefined == null) { + } + if (null == undefined) { + } + if (null == null) { + } +} + +function f3(a: number, b: boolean, c: { x: number }, d: number | string) { + if (a == null) { + } + if (b == null) { + } + if (c == null) { + } + if (d == null) { + } +} + +function f4(x: number) { + if (x > undefined) { + } + if (x < undefined) { + } + if (x >= undefined) { + } + if (x <= undefined) { + } +}