From 11c07a321734bb5862d13c79ca02c06978dc4a9d Mon Sep 17 00:00:00 2001 From: Asger F Date: Mon, 29 Apr 2019 12:39:07 +0100 Subject: [PATCH 1/4] TS: Update to TypeScript 3.4.5 --- javascript/extractor/lib/typescript/package.json | 2 +- javascript/extractor/lib/typescript/yarn.lock | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/javascript/extractor/lib/typescript/package.json b/javascript/extractor/lib/typescript/package.json index 4039aaf072d8..e652fec3e167 100644 --- a/javascript/extractor/lib/typescript/package.json +++ b/javascript/extractor/lib/typescript/package.json @@ -2,7 +2,7 @@ "name": "typescript-parser-wrapper", "private": true, "dependencies": { - "typescript": "3.4" + "typescript": "3.4.5" }, "scripts": { "build": "tsc --project tsconfig.json && rollup -c", diff --git a/javascript/extractor/lib/typescript/yarn.lock b/javascript/extractor/lib/typescript/yarn.lock index 48b3484b60fe..0c618e9bbcf8 100644 --- a/javascript/extractor/lib/typescript/yarn.lock +++ b/javascript/extractor/lib/typescript/yarn.lock @@ -509,9 +509,9 @@ tsutils@^2.12.1: dependencies: tslib "^1.8.1" -typescript@3.4: - version "3.4.3" - resolved "typescript-3.4.3.tgz#0eb320e4ace9b10eadf5bc6103286b0f8b7c224f" +typescript@3.4.5: + version "3.4.5" + resolved "typescript-3.4.5.tgz#2d2618d10bb566572b8d7aad5180d84257d70a99" wrappy@1: version "1.0.2" From 686d72c356dd342246e593ee5db7cb1a6d07074a Mon Sep 17 00:00:00 2001 From: Asger F Date: Tue, 30 Apr 2019 10:27:40 +0100 Subject: [PATCH 2/4] TS: Fix handling of 'export =' --- javascript/extractor/lib/typescript/src/main.ts | 4 +++- .../RegressionTests/ExportEqualsExpr/extern.d.ts | 14 ++++++++++++++ .../RegressionTests/ExportEqualsExpr/test.expected | 7 +++++++ .../RegressionTests/ExportEqualsExpr/test.ql | 4 ++++ .../RegressionTests/ExportEqualsExpr/tsconfig.json | 6 ++++++ .../RegressionTests/ExportEqualsExpr/tst.ts | 5 +++++ 6 files changed, 39 insertions(+), 1 deletion(-) create mode 100644 javascript/ql/test/library-tests/TypeScript/RegressionTests/ExportEqualsExpr/extern.d.ts create mode 100644 javascript/ql/test/library-tests/TypeScript/RegressionTests/ExportEqualsExpr/test.expected create mode 100644 javascript/ql/test/library-tests/TypeScript/RegressionTests/ExportEqualsExpr/test.ql create mode 100644 javascript/ql/test/library-tests/TypeScript/RegressionTests/ExportEqualsExpr/tsconfig.json create mode 100644 javascript/ql/test/library-tests/TypeScript/RegressionTests/ExportEqualsExpr/tst.ts diff --git a/javascript/extractor/lib/typescript/src/main.ts b/javascript/extractor/lib/typescript/src/main.ts index 1bb9ab8badc0..39cd5e9a3049 100644 --- a/javascript/extractor/lib/typescript/src/main.ts +++ b/javascript/extractor/lib/typescript/src/main.ts @@ -372,7 +372,9 @@ function handleOpenProjectCommand(command: OpenProjectCommand) { function getEffectiveExportTarget(symbol: ts.Symbol) { if (symbol.exports != null && symbol.exports.has(ts.InternalSymbolName.ExportEquals)) { let exportAlias = symbol.exports.get(ts.InternalSymbolName.ExportEquals); - return typeChecker.getAliasedSymbol(exportAlias); + if (exportAlias.flags & ts.SymbolFlags.Alias) { + return typeChecker.getAliasedSymbol(exportAlias); + } } return symbol; } diff --git a/javascript/ql/test/library-tests/TypeScript/RegressionTests/ExportEqualsExpr/extern.d.ts b/javascript/ql/test/library-tests/TypeScript/RegressionTests/ExportEqualsExpr/extern.d.ts new file mode 100644 index 000000000000..907b6452b9a3 --- /dev/null +++ b/javascript/ql/test/library-tests/TypeScript/RegressionTests/ExportEqualsExpr/extern.d.ts @@ -0,0 +1,14 @@ +class Foo {} + +declare module 'foo' { + export = new Foo(); +} + +declare module 'bar' { + import * as baz from "baz"; + export = baz; +} + +declare module 'baz' { + export class C {} +} diff --git a/javascript/ql/test/library-tests/TypeScript/RegressionTests/ExportEqualsExpr/test.expected b/javascript/ql/test/library-tests/TypeScript/RegressionTests/ExportEqualsExpr/test.expected new file mode 100644 index 000000000000..24fc12058753 --- /dev/null +++ b/javascript/ql/test/library-tests/TypeScript/RegressionTests/ExportEqualsExpr/test.expected @@ -0,0 +1,7 @@ +| "bar" in global scope | +| C in module 'bar' | +| Foo in global scope | +| Foo in tst.ts | +| module 'bar' | +| module 'foo' | +| tst.ts | diff --git a/javascript/ql/test/library-tests/TypeScript/RegressionTests/ExportEqualsExpr/test.ql b/javascript/ql/test/library-tests/TypeScript/RegressionTests/ExportEqualsExpr/test.ql new file mode 100644 index 000000000000..3212e219ccd1 --- /dev/null +++ b/javascript/ql/test/library-tests/TypeScript/RegressionTests/ExportEqualsExpr/test.ql @@ -0,0 +1,4 @@ +import javascript + +from CanonicalName name +select name diff --git a/javascript/ql/test/library-tests/TypeScript/RegressionTests/ExportEqualsExpr/tsconfig.json b/javascript/ql/test/library-tests/TypeScript/RegressionTests/ExportEqualsExpr/tsconfig.json new file mode 100644 index 000000000000..4c06d765a041 --- /dev/null +++ b/javascript/ql/test/library-tests/TypeScript/RegressionTests/ExportEqualsExpr/tsconfig.json @@ -0,0 +1,6 @@ +{ + "include": ["."], + "compilerOptions": { + "esModuleInterop": true + } +} diff --git a/javascript/ql/test/library-tests/TypeScript/RegressionTests/ExportEqualsExpr/tst.ts b/javascript/ql/test/library-tests/TypeScript/RegressionTests/ExportEqualsExpr/tst.ts new file mode 100644 index 000000000000..f86f06fea875 --- /dev/null +++ b/javascript/ql/test/library-tests/TypeScript/RegressionTests/ExportEqualsExpr/tst.ts @@ -0,0 +1,5 @@ +import self from "./tst"; + +class Foo {} + +export = new Foo(); From 5c8dd7eeddfd58ca373f491138fb722ee413a3a8 Mon Sep 17 00:00:00 2001 From: Asger F Date: Tue, 30 Apr 2019 10:56:02 +0100 Subject: [PATCH 3/4] TS: Add workaround for 'globalThis' getProperties() crash --- .../extractor/lib/typescript/src/type_table.ts | 18 +++++++++++++++++- .../RegressionTests/GlobalThis/test.expected | 1 + .../RegressionTests/GlobalThis/test.ql | 3 +++ .../RegressionTests/GlobalThis/tsconfig.json | 3 +++ .../RegressionTests/GlobalThis/tst.ts | 13 +++++++++++++ 5 files changed, 37 insertions(+), 1 deletion(-) create mode 100644 javascript/ql/test/library-tests/TypeScript/RegressionTests/GlobalThis/test.expected create mode 100644 javascript/ql/test/library-tests/TypeScript/RegressionTests/GlobalThis/test.ql create mode 100644 javascript/ql/test/library-tests/TypeScript/RegressionTests/GlobalThis/tsconfig.json create mode 100644 javascript/ql/test/library-tests/TypeScript/RegressionTests/GlobalThis/tst.ts diff --git a/javascript/extractor/lib/typescript/src/type_table.ts b/javascript/extractor/lib/typescript/src/type_table.ts index 9843e2f39882..2e08926489f4 100644 --- a/javascript/extractor/lib/typescript/src/type_table.ts +++ b/javascript/extractor/lib/typescript/src/type_table.ts @@ -819,8 +819,24 @@ export class TypeTable { this.isInShallowTypeContext = false; } + /** + * Returns the properties of the given type, or `null` if the properties of this + * type could not be computed. + */ + private tryGetProperties(type: ts.Type) { + // Workaround for https://github.com/Microsoft/TypeScript/issues/30845 + // Should be safe to remove once that has been fixed. + try { + return type.getProperties(); + } catch (e) { + return null; + } + } + private extractProperties(type: ts.Type, id: number) { - for (let symbol of type.getProperties()) { + let props = this.tryGetProperties(type); + if (props == null) return; + for (let symbol of props) { let propertyType = this.typeChecker.getTypeOfSymbolAtLocation(symbol, this.arbitraryAstNode); if (propertyType == null) continue; let propertyTypeId = this.getId(propertyType); diff --git a/javascript/ql/test/library-tests/TypeScript/RegressionTests/GlobalThis/test.expected b/javascript/ql/test/library-tests/TypeScript/RegressionTests/GlobalThis/test.expected new file mode 100644 index 000000000000..59f6fd6e79b5 --- /dev/null +++ b/javascript/ql/test/library-tests/TypeScript/RegressionTests/GlobalThis/test.expected @@ -0,0 +1 @@ +| Success | diff --git a/javascript/ql/test/library-tests/TypeScript/RegressionTests/GlobalThis/test.ql b/javascript/ql/test/library-tests/TypeScript/RegressionTests/GlobalThis/test.ql new file mode 100644 index 000000000000..26d294c7bce0 --- /dev/null +++ b/javascript/ql/test/library-tests/TypeScript/RegressionTests/GlobalThis/test.ql @@ -0,0 +1,3 @@ +import javascript + +select "Success" diff --git a/javascript/ql/test/library-tests/TypeScript/RegressionTests/GlobalThis/tsconfig.json b/javascript/ql/test/library-tests/TypeScript/RegressionTests/GlobalThis/tsconfig.json new file mode 100644 index 000000000000..d144c8ddb02c --- /dev/null +++ b/javascript/ql/test/library-tests/TypeScript/RegressionTests/GlobalThis/tsconfig.json @@ -0,0 +1,3 @@ +{ + "include": ["."] +} diff --git a/javascript/ql/test/library-tests/TypeScript/RegressionTests/GlobalThis/tst.ts b/javascript/ql/test/library-tests/TypeScript/RegressionTests/GlobalThis/tst.ts new file mode 100644 index 000000000000..1298a73e6dd2 --- /dev/null +++ b/javascript/ql/test/library-tests/TypeScript/RegressionTests/GlobalThis/tst.ts @@ -0,0 +1,13 @@ +'use strict'; + +var _myGlobal = this; + +module Test { + var global = _myGlobal || {}; + + export class C {} + + export function f(x: C) { + global.field = x || {}; + } +} From 15299aba7d9632c2c799ccad81792f357cd99b5e Mon Sep 17 00:00:00 2001 From: Asger F Date: Tue, 30 Apr 2019 16:07:45 +0100 Subject: [PATCH 4/4] TS: Workaround issue with `infer` types --- .../lib/typescript/src/ast_extractor.ts | 20 ++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/javascript/extractor/lib/typescript/src/ast_extractor.ts b/javascript/extractor/lib/typescript/src/ast_extractor.ts index a8325d8537ab..182d8c98a501 100644 --- a/javascript/extractor/lib/typescript/src/ast_extractor.ts +++ b/javascript/extractor/lib/typescript/src/ast_extractor.ts @@ -156,7 +156,21 @@ export function augmentAst(ast: AugmentedSourceFile, code: string, project: Proj } } - forEachNode(ast, (node: AugmentedNode) => { + // Number of conditional type expressions the visitor is currently inside. + // We disable type extraction inside such type expressions, to avoid complications + // with `infer` types. + let insideConditionalTypes = 0; + + visitAstNode(ast); + function visitAstNode(node: AugmentedNode) { + if (node.kind === ts.SyntaxKind.ConditionalType) { + ++insideConditionalTypes; + } + ts.forEachChild(node, visitAstNode); + if (node.kind === ts.SyntaxKind.ConditionalType) { + --insideConditionalTypes; + } + // fill in line/column info if ("pos" in node) { node.$pos = augmentPos(node.pos, true); @@ -176,7 +190,7 @@ export function augmentAst(ast: AugmentedSourceFile, code: string, project: Proj } } - if (typeChecker != null) { + if (typeChecker != null && insideConditionalTypes === 0) { if (isTypedNode(node)) { let contextualType = isContextuallyTypedNode(node) ? typeChecker.getContextualType(node) @@ -250,7 +264,7 @@ export function augmentAst(ast: AugmentedSourceFile, code: string, project: Proj } } } - }); + } } type NamedNodeWithSymbol = AugmentedNode & (ts.ClassDeclaration | ts.InterfaceDeclaration