From 5af2c47b13015a71139e040ca55646a8ee7e6d25 Mon Sep 17 00:00:00 2001 From: Ryan Cavanaugh Date: Wed, 10 Feb 2016 10:41:52 -0800 Subject: [PATCH 1/4] Add undefined checks for malformed type tags Fixes #7002 --- src/compiler/checker.ts | 4 ++-- src/harness/harness.ts | 3 +++ tests/baselines/reference/malformedTags.js | 17 +++++++++++++++++ tests/baselines/reference/malformedTags.symbols | 13 +++++++++++++ tests/baselines/reference/malformedTags.types | 13 +++++++++++++ tests/cases/conformance/salsa/malformedTags.ts | 10 ++++++++++ 6 files changed, 58 insertions(+), 2 deletions(-) create mode 100644 tests/baselines/reference/malformedTags.js create mode 100644 tests/baselines/reference/malformedTags.symbols create mode 100644 tests/baselines/reference/malformedTags.types create mode 100644 tests/cases/conformance/salsa/malformedTags.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 3965665ba19..0b428d143a2 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -2621,7 +2621,7 @@ namespace ts { function getJSDocTypeForVariableLikeDeclarationFromJSDocComment(declaration: VariableLikeDeclaration): JSDocType { // First, see if this node has an @type annotation on it directly. const typeTag = getJSDocTypeTag(declaration); - if (typeTag) { + if (typeTag && typeTag.typeExpression) { return typeTag.typeExpression.type; } @@ -2631,7 +2631,7 @@ namespace ts { // @type annotation might have been on the variable statement, try that instead. const annotation = getJSDocTypeTag(declaration.parent.parent); - if (annotation) { + if (annotation && annotation.typeExpression) { return annotation.typeExpression.type; } } diff --git a/src/harness/harness.ts b/src/harness/harness.ts index 7fd81973172..25dfbfaa2c2 100644 --- a/src/harness/harness.ts +++ b/src/harness/harness.ts @@ -947,6 +947,9 @@ namespace Harness { } } } + else if (name === 'suppressOutputPathCheck') { + options.suppressOutputPathCheck = true; + } else { throw new Error(`Unknown compiler option '${name}'.`); } diff --git a/tests/baselines/reference/malformedTags.js b/tests/baselines/reference/malformedTags.js new file mode 100644 index 00000000000..33b2c1e6f41 --- /dev/null +++ b/tests/baselines/reference/malformedTags.js @@ -0,0 +1,17 @@ +//// [myFile02.js] + +/** + * Checks if `value` is classified as an `Array` object. + * + * @type Function + */ +var isArray = Array.isArray; + + +//// [myFile02.js] +/** + * Checks if `value` is classified as an `Array` object. + * + * @type Function + */ +var isArray = Array.isArray; diff --git a/tests/baselines/reference/malformedTags.symbols b/tests/baselines/reference/malformedTags.symbols new file mode 100644 index 00000000000..df953a82497 --- /dev/null +++ b/tests/baselines/reference/malformedTags.symbols @@ -0,0 +1,13 @@ +=== tests/cases/conformance/salsa/myFile02.js === + +/** + * Checks if `value` is classified as an `Array` object. + * + * @type Function + */ +var isArray = Array.isArray; +>isArray : Symbol(isArray, Decl(myFile02.js, 6, 3)) +>Array.isArray : Symbol(ArrayConstructor.isArray, Decl(lib.d.ts, --, --)) +>Array : Symbol(Array, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>isArray : Symbol(ArrayConstructor.isArray, Decl(lib.d.ts, --, --)) + diff --git a/tests/baselines/reference/malformedTags.types b/tests/baselines/reference/malformedTags.types new file mode 100644 index 00000000000..acf442f7cba --- /dev/null +++ b/tests/baselines/reference/malformedTags.types @@ -0,0 +1,13 @@ +=== tests/cases/conformance/salsa/myFile02.js === + +/** + * Checks if `value` is classified as an `Array` object. + * + * @type Function + */ +var isArray = Array.isArray; +>isArray : (arg: any) => arg is any[] +>Array.isArray : (arg: any) => arg is any[] +>Array : ArrayConstructor +>isArray : (arg: any) => arg is any[] + diff --git a/tests/cases/conformance/salsa/malformedTags.ts b/tests/cases/conformance/salsa/malformedTags.ts new file mode 100644 index 00000000000..1128ce73f15 --- /dev/null +++ b/tests/cases/conformance/salsa/malformedTags.ts @@ -0,0 +1,10 @@ +// @allowJS: true +// @suppressOutputPathCheck: true + +// @filename: myFile02.js +/** + * Checks if `value` is classified as an `Array` object. + * + * @type Function + */ +var isArray = Array.isArray; From 03d23823266d0a73faae3787f8262c4911138870 Mon Sep 17 00:00:00 2001 From: Ryan Cavanaugh Date: Wed, 10 Feb 2016 11:18:02 -0800 Subject: [PATCH 2/4] :heart: linter --- src/harness/harness.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/harness/harness.ts b/src/harness/harness.ts index 25dfbfaa2c2..44ca9fc6b3e 100644 --- a/src/harness/harness.ts +++ b/src/harness/harness.ts @@ -947,7 +947,7 @@ namespace Harness { } } } - else if (name === 'suppressOutputPathCheck') { + else if (name === "suppressOutputPathCheck") { options.suppressOutputPathCheck = true; } else { From a99b5cb132be491cf56d1f6aca7a0b78bf3723be Mon Sep 17 00:00:00 2001 From: Ryan Cavanaugh Date: Wed, 10 Feb 2016 11:30:21 -0800 Subject: [PATCH 3/4] Check in other places too --- src/compiler/checker.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 0b428d143a2..193ebe0f72c 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -7392,7 +7392,7 @@ namespace ts { function getTypeForThisExpressionFromJSDoc(node: Node) { const typeTag = getJSDocTypeTag(node); - if (typeTag && typeTag.typeExpression.type.kind === SyntaxKind.JSDocFunctionType) { + if (typeTag && typeTag.typeExpression && typeTag.typeExpression.type && typeTag.typeExpression.type.kind === SyntaxKind.JSDocFunctionType) { const jsDocFunctionType = typeTag.typeExpression.type; if (jsDocFunctionType.parameters.length > 0 && jsDocFunctionType.parameters[0].type.kind === SyntaxKind.JSDocThisType) { return getTypeFromTypeNode(jsDocFunctionType.parameters[0].type); From 6658e2149c32e526f14f7c502d29a48f25f0af49 Mon Sep 17 00:00:00 2001 From: Ryan Cavanaugh Date: Wed, 10 Feb 2016 12:51:21 -0800 Subject: [PATCH 4/4] Move suppress option to appropriate place --- src/harness/harness.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/harness/harness.ts b/src/harness/harness.ts index 44ca9fc6b3e..57643e548f9 100644 --- a/src/harness/harness.ts +++ b/src/harness/harness.ts @@ -904,7 +904,8 @@ namespace Harness { { name: "includeBuiltFile", type: "string" }, { name: "fileName", type: "string" }, { name: "libFiles", type: "string" }, - { name: "noErrorTruncation", type: "boolean" } + { name: "noErrorTruncation", type: "boolean" }, + { name: "suppressOutputPathCheck", type: "boolean" } ]; let optionsIndex: ts.Map; @@ -947,9 +948,6 @@ namespace Harness { } } } - else if (name === "suppressOutputPathCheck") { - options.suppressOutputPathCheck = true; - } else { throw new Error(`Unknown compiler option '${name}'.`); }