From cfffc235595dfdfb49d696724fe0685b95883b80 Mon Sep 17 00:00:00 2001 From: Kanchalai Tanglertsampan Date: Wed, 29 Jun 2016 10:56:57 -0700 Subject: [PATCH 1/2] Error when undefined or null is pass in as argument for destructuring parameter --- src/compiler/checker.ts | 15 +++++++++++++++ src/compiler/diagnosticMessages.json | 4 ++++ 2 files changed, 19 insertions(+) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 06591a7ab3d44..b771d53f7d390 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -10817,6 +10817,15 @@ namespace ts { argType = arg.kind === SyntaxKind.StringLiteral && !reportErrors ? getStringLiteralTypeForText((arg).text) : checkExpressionWithContextualType(arg, paramType, excludeArgument && excludeArgument[i] ? identityMapper : undefined); + + } + + // If the parameter is a destructuring without initializer and argType is undefined, we should give an error + if (argType.flags & (TypeFlags.Undefined | TypeFlags.Null)) { + const parameterDeclaration = getParameterAtPosition(signature, i); + if (parameterDeclaration && !parameterDeclaration.initializer && isBindingPattern(parameterDeclaration.name)) { + error(arg, Diagnostics.Undefined_or_null_is_not_assignable_to_a_destructuring_parameter); + } } // Use argument expression as error location when reporting errors @@ -11761,6 +11770,12 @@ namespace ts { return type; } + function getParameterAtPosition(signature: Signature, pos: number): ParameterDeclaration { + return signature.hasRestParameter ? + pos < signature.parameters.length - 1 ? signature.parameters[pos].valueDeclaration as ParameterDeclaration : undefined : + pos < signature.parameters.length ? signature.parameters[pos].valueDeclaration as ParameterDeclaration : undefined; + } + function getTypeAtPosition(signature: Signature, pos: number): Type { return signature.hasRestParameter ? pos < signature.parameters.length - 1 ? getTypeOfParameter(signature.parameters[pos]) : getRestTypeOfSignature(signature) : diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 0ee1818ee5743..c4b8ab3170a58 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -1943,6 +1943,10 @@ "category": "Error", "code": 2689 }, + "'Undefined or 'null' is not assignable to a destructuring parameter.": { + "category": "Error", + "code": 2690 + }, "Import declaration '{0}' is using private name '{1}'.": { "category": "Error", "code": 4000 From 5cf7cf29807eb4a3ffacc423e8adab35240a76cd Mon Sep 17 00:00:00 2001 From: Kanchalai Tanglertsampan Date: Wed, 29 Jun 2016 11:31:27 -0700 Subject: [PATCH 2/2] Add tests and baselines --- ...cturingParameterDeclaration8ES5.errors.txt | 52 +++++++++++++++++++ .../destructuringParameterDeclaration8ES5.js | 36 +++++++++++++ .../destructuringParameterDeclaration9ES5.js | 28 ++++++++++ ...tructuringParameterDeclaration9ES5.symbols | 24 +++++++++ ...estructuringParameterDeclaration9ES5.types | 32 ++++++++++++ .../destructuringParameterDeclaration8ES5.ts | 20 +++++++ .../destructuringParameterDeclaration9ES5.ts | 15 ++++++ 7 files changed, 207 insertions(+) create mode 100644 tests/baselines/reference/destructuringParameterDeclaration8ES5.errors.txt create mode 100644 tests/baselines/reference/destructuringParameterDeclaration8ES5.js create mode 100644 tests/baselines/reference/destructuringParameterDeclaration9ES5.js create mode 100644 tests/baselines/reference/destructuringParameterDeclaration9ES5.symbols create mode 100644 tests/baselines/reference/destructuringParameterDeclaration9ES5.types create mode 100644 tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration8ES5.ts create mode 100644 tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration9ES5.ts diff --git a/tests/baselines/reference/destructuringParameterDeclaration8ES5.errors.txt b/tests/baselines/reference/destructuringParameterDeclaration8ES5.errors.txt new file mode 100644 index 0000000000000..25fc60e2b9455 --- /dev/null +++ b/tests/baselines/reference/destructuringParameterDeclaration8ES5.errors.txt @@ -0,0 +1,52 @@ +tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration8ES5.ts(9,5): error TS2690: 'Undefined or 'null' is not assignable to a destructuring parameter. +tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration8ES5.ts(11,5): error TS2690: 'Undefined or 'null' is not assignable to a destructuring parameter. +tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration8ES5.ts(11,16): error TS2690: 'Undefined or 'null' is not assignable to a destructuring parameter. +tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration8ES5.ts(13,5): error TS2690: 'Undefined or 'null' is not assignable to a destructuring parameter. +tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration8ES5.ts(15,5): error TS2690: 'Undefined or 'null' is not assignable to a destructuring parameter. +tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration8ES5.ts(15,11): error TS2690: 'Undefined or 'null' is not assignable to a destructuring parameter. +tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration8ES5.ts(17,5): error TS2690: 'Undefined or 'null' is not assignable to a destructuring parameter. +tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration8ES5.ts(17,16): error TS2690: 'Undefined or 'null' is not assignable to a destructuring parameter. +tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration8ES5.ts(19,5): error TS2690: 'Undefined or 'null' is not assignable to a destructuring parameter. +tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration8ES5.ts(19,11): error TS2690: 'Undefined or 'null' is not assignable to a destructuring parameter. + + +==== tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration8ES5.ts (10 errors) ==== + + function one({}, {foo, bar}) { + // ... + } + + function two([], [a,b]) {} + + // should be an error + one(undefined, { foo: 'foo', bar: 'bar' }); + ~~~~~~~~~ +!!! error TS2690: 'Undefined or 'null' is not assignable to a destructuring parameter. + + one(undefined, undefined); + ~~~~~~~~~ +!!! error TS2690: 'Undefined or 'null' is not assignable to a destructuring parameter. + ~~~~~~~~~ +!!! error TS2690: 'Undefined or 'null' is not assignable to a destructuring parameter. + + one(null, { foo: 'foo', bar: 'bar' }); + ~~~~ +!!! error TS2690: 'Undefined or 'null' is not assignable to a destructuring parameter. + + one(null, null); + ~~~~ +!!! error TS2690: 'Undefined or 'null' is not assignable to a destructuring parameter. + ~~~~ +!!! error TS2690: 'Undefined or 'null' is not assignable to a destructuring parameter. + + two(undefined, undefined); + ~~~~~~~~~ +!!! error TS2690: 'Undefined or 'null' is not assignable to a destructuring parameter. + ~~~~~~~~~ +!!! error TS2690: 'Undefined or 'null' is not assignable to a destructuring parameter. + + two(null, null); + ~~~~ +!!! error TS2690: 'Undefined or 'null' is not assignable to a destructuring parameter. + ~~~~ +!!! error TS2690: 'Undefined or 'null' is not assignable to a destructuring parameter. \ No newline at end of file diff --git a/tests/baselines/reference/destructuringParameterDeclaration8ES5.js b/tests/baselines/reference/destructuringParameterDeclaration8ES5.js new file mode 100644 index 0000000000000..b5eca12017471 --- /dev/null +++ b/tests/baselines/reference/destructuringParameterDeclaration8ES5.js @@ -0,0 +1,36 @@ +//// [destructuringParameterDeclaration8ES5.ts] + +function one({}, {foo, bar}) { + // ... +} + +function two([], [a,b]) {} + +// should be an error +one(undefined, { foo: 'foo', bar: 'bar' }); + +one(undefined, undefined); + +one(null, { foo: 'foo', bar: 'bar' }); + +one(null, null); + +two(undefined, undefined); + +two(null, null); + +//// [destructuringParameterDeclaration8ES5.js] +function one(_a, _b) { + var foo = _b.foo, bar = _b.bar; + // ... +} +function two(_a, _b) { + var a = _b[0], b = _b[1]; +} +// should be an error +one(undefined, { foo: 'foo', bar: 'bar' }); +one(undefined, undefined); +one(null, { foo: 'foo', bar: 'bar' }); +one(null, null); +two(undefined, undefined); +two(null, null); diff --git a/tests/baselines/reference/destructuringParameterDeclaration9ES5.js b/tests/baselines/reference/destructuringParameterDeclaration9ES5.js new file mode 100644 index 0000000000000..73fad4482a7c5 --- /dev/null +++ b/tests/baselines/reference/destructuringParameterDeclaration9ES5.js @@ -0,0 +1,28 @@ +//// [destructuringParameterDeclaration9ES5.ts] + +function three({} = {}) {} + +function four([] = []) {} + +// should not be an error + +three(undefined); + +three(null); + +four(undefined); + +four(null) + +//// [destructuringParameterDeclaration9ES5.js] +function three(_a) { + var _a = {}; +} +function four(_a) { + var _a = []; +} +// should not be an error +three(undefined); +three(null); +four(undefined); +four(null); diff --git a/tests/baselines/reference/destructuringParameterDeclaration9ES5.symbols b/tests/baselines/reference/destructuringParameterDeclaration9ES5.symbols new file mode 100644 index 0000000000000..3447c878e6b1a --- /dev/null +++ b/tests/baselines/reference/destructuringParameterDeclaration9ES5.symbols @@ -0,0 +1,24 @@ +=== tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration9ES5.ts === + +function three({} = {}) {} +>three : Symbol(three, Decl(destructuringParameterDeclaration9ES5.ts, 0, 0)) + +function four([] = []) {} +>four : Symbol(four, Decl(destructuringParameterDeclaration9ES5.ts, 1, 26)) + +// should not be an error + +three(undefined); +>three : Symbol(three, Decl(destructuringParameterDeclaration9ES5.ts, 0, 0)) +>undefined : Symbol(undefined) + +three(null); +>three : Symbol(three, Decl(destructuringParameterDeclaration9ES5.ts, 0, 0)) + +four(undefined); +>four : Symbol(four, Decl(destructuringParameterDeclaration9ES5.ts, 1, 26)) +>undefined : Symbol(undefined) + +four(null) +>four : Symbol(four, Decl(destructuringParameterDeclaration9ES5.ts, 1, 26)) + diff --git a/tests/baselines/reference/destructuringParameterDeclaration9ES5.types b/tests/baselines/reference/destructuringParameterDeclaration9ES5.types new file mode 100644 index 0000000000000..aba50cc297b79 --- /dev/null +++ b/tests/baselines/reference/destructuringParameterDeclaration9ES5.types @@ -0,0 +1,32 @@ +=== tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration9ES5.ts === + +function three({} = {}) {} +>three : ({}?: {}) => void +>{} : {} + +function four([] = []) {} +>four : ([]?: any[]) => void +>[] : undefined[] + +// should not be an error + +three(undefined); +>three(undefined) : void +>three : ({}?: {}) => void +>undefined : undefined + +three(null); +>three(null) : void +>three : ({}?: {}) => void +>null : null + +four(undefined); +>four(undefined) : void +>four : ([]?: any[]) => void +>undefined : undefined + +four(null) +>four(null) : void +>four : ([]?: any[]) => void +>null : null + diff --git a/tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration8ES5.ts b/tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration8ES5.ts new file mode 100644 index 0000000000000..e6cbfb8b8d2fa --- /dev/null +++ b/tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration8ES5.ts @@ -0,0 +1,20 @@ +// @target: es5 + +function one({}, {foo, bar}) { + // ... +} + +function two([], [a,b]) {} + +// should be an error +one(undefined, { foo: 'foo', bar: 'bar' }); + +one(undefined, undefined); + +one(null, { foo: 'foo', bar: 'bar' }); + +one(null, null); + +two(undefined, undefined); + +two(null, null); \ No newline at end of file diff --git a/tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration9ES5.ts b/tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration9ES5.ts new file mode 100644 index 0000000000000..ff67fefde50e0 --- /dev/null +++ b/tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration9ES5.ts @@ -0,0 +1,15 @@ +// @target: es5 + +function three({} = {}) {} + +function four([] = []) {} + +// should not be an error + +three(undefined); + +three(null); + +four(undefined); + +four(null) \ No newline at end of file