From 8a334ac00d82243b6371db24ee612eef59702e3e Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Mon, 21 Nov 2016 23:13:22 -0800 Subject: [PATCH 1/6] Add special handeling for function and array in Object.freeze --- src/lib/es5.d.ts | 12 ++++++++++++ .../reference/objectFreeze.errors.txt | 15 +++++++++++++++ tests/baselines/reference/objectFreeze.js | 18 ++++++++++++++++++ tests/cases/compiler/objectFreeze.ts | 6 ++++++ 4 files changed, 51 insertions(+) create mode 100644 tests/baselines/reference/objectFreeze.errors.txt create mode 100644 tests/baselines/reference/objectFreeze.js create mode 100644 tests/cases/compiler/objectFreeze.ts diff --git a/src/lib/es5.d.ts b/src/lib/es5.d.ts index 7ee47817802..63b60f534af 100644 --- a/src/lib/es5.d.ts +++ b/src/lib/es5.d.ts @@ -176,6 +176,18 @@ interface ObjectConstructor { */ seal(o: T): T; + /** + * Prevents the modification of existing property attributes and values, and prevents the addition of new properties. + * @param o Object on which to lock the attributes. + */ + freeze(a: T[]): ReadonlyArray; + + /** + * Prevents the modification of existing property attributes and values, and prevents the addition of new properties. + * @param o Object on which to lock the attributes. + */ + freeze(f: (...args: T[]) => U): (...args: T[]) => U; + /** * Prevents the modification of existing property attributes and values, and prevents the addition of new properties. * @param o Object on which to lock the attributes. diff --git a/tests/baselines/reference/objectFreeze.errors.txt b/tests/baselines/reference/objectFreeze.errors.txt new file mode 100644 index 00000000000..e820520ed8a --- /dev/null +++ b/tests/baselines/reference/objectFreeze.errors.txt @@ -0,0 +1,15 @@ +tests/cases/compiler/objectFreeze.ts(5,24): error TS2345: Argument of type '123' is not assignable to parameter of type 'string'. +tests/cases/compiler/objectFreeze.ts(6,2): error TS1128: Declaration or statement expected. + + +==== tests/cases/compiler/objectFreeze.ts (2 errors) ==== + class A { + constructor(public a1: string) { + } + } + function foo(x = new A(123)) { //should error, 123 is not string + ~~~ +!!! error TS2345: Argument of type '123' is not assignable to parameter of type 'string'. + }} + ~ +!!! error TS1128: Declaration or statement expected. \ No newline at end of file diff --git a/tests/baselines/reference/objectFreeze.js b/tests/baselines/reference/objectFreeze.js new file mode 100644 index 00000000000..86c2833dabf --- /dev/null +++ b/tests/baselines/reference/objectFreeze.js @@ -0,0 +1,18 @@ +//// [objectFreeze.ts] +class A { + constructor(public a1: string) { + } +} +function foo(x = new A(123)) { //should error, 123 is not string +}} + +//// [objectFreeze.js] +var A = (function () { + function A(a1) { + this.a1 = a1; + } + return A; +}()); +function foo(x) { + if (x === void 0) { x = new A(123); } +} diff --git a/tests/cases/compiler/objectFreeze.ts b/tests/cases/compiler/objectFreeze.ts new file mode 100644 index 00000000000..e92f9ecd00e --- /dev/null +++ b/tests/cases/compiler/objectFreeze.ts @@ -0,0 +1,6 @@ +class A { + constructor(public a1: string) { + } +} +function foo(x = new A(123)) { //should error, 123 is not string +}} \ No newline at end of file From 72df02cbbd70061574988eef38f9cb775b5bfa61 Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Mon, 21 Nov 2016 23:27:18 -0800 Subject: [PATCH 2/6] Add function --- src/lib/es5.d.ts | 2 +- .../reference/objectFreeze.errors.txt | 27 +++++++++-------- tests/baselines/reference/objectFreeze.js | 30 +++++++++---------- tests/cases/compiler/objectFreeze.ts | 14 +++++---- 4 files changed, 39 insertions(+), 34 deletions(-) diff --git a/src/lib/es5.d.ts b/src/lib/es5.d.ts index 63b60f534af..3ad6046c85e 100644 --- a/src/lib/es5.d.ts +++ b/src/lib/es5.d.ts @@ -186,7 +186,7 @@ interface ObjectConstructor { * Prevents the modification of existing property attributes and values, and prevents the addition of new properties. * @param o Object on which to lock the attributes. */ - freeze(f: (...args: T[]) => U): (...args: T[]) => U; + freeze(f: (...args: any[]) => T): (...args: any[]) => T; /** * Prevents the modification of existing property attributes and values, and prevents the addition of new properties. diff --git a/tests/baselines/reference/objectFreeze.errors.txt b/tests/baselines/reference/objectFreeze.errors.txt index e820520ed8a..0a1a0518829 100644 --- a/tests/baselines/reference/objectFreeze.errors.txt +++ b/tests/baselines/reference/objectFreeze.errors.txt @@ -1,15 +1,18 @@ -tests/cases/compiler/objectFreeze.ts(5,24): error TS2345: Argument of type '123' is not assignable to parameter of type 'string'. -tests/cases/compiler/objectFreeze.ts(6,2): error TS1128: Declaration or statement expected. +tests/cases/compiler/objectFreeze.ts(5,1): error TS2542: Index signature in type 'ReadonlyArray' only permits reading. +tests/cases/compiler/objectFreeze.ts(8,3): error TS2540: Cannot assign to 'b' because it is a constant or a read-only property. ==== tests/cases/compiler/objectFreeze.ts (2 errors) ==== - class A { - constructor(public a1: string) { - } - } - function foo(x = new A(123)) { //should error, 123 is not string - ~~~ -!!! error TS2345: Argument of type '123' is not assignable to parameter of type 'string'. - }} - ~ -!!! error TS1128: Declaration or statement expected. \ No newline at end of file + const f = Object.freeze(function foo(a: number, b: string) { return false; }); + f(1, "") === false; + + const a = Object.freeze([1, 2, 3]); + a[0] = 1; + ~~~~ +!!! error TS2542: Index signature in type 'ReadonlyArray' only permits reading. + + const o = Object.freeze({ a: 1, b: "string" }); + o.b = "another"; + ~ +!!! error TS2540: Cannot assign to 'b' because it is a constant or a read-only property. + \ No newline at end of file diff --git a/tests/baselines/reference/objectFreeze.js b/tests/baselines/reference/objectFreeze.js index 86c2833dabf..51308c8e07c 100644 --- a/tests/baselines/reference/objectFreeze.js +++ b/tests/baselines/reference/objectFreeze.js @@ -1,18 +1,18 @@ //// [objectFreeze.ts] -class A { - constructor(public a1: string) { - } -} -function foo(x = new A(123)) { //should error, 123 is not string -}} +const f = Object.freeze(function foo(a: number, b: string) { return false; }); +f(1, "") === false; + +const a = Object.freeze([1, 2, 3]); +a[0] = 1; + +const o = Object.freeze({ a: 1, b: "string" }); +o.b = "another"; + //// [objectFreeze.js] -var A = (function () { - function A(a1) { - this.a1 = a1; - } - return A; -}()); -function foo(x) { - if (x === void 0) { x = new A(123); } -} +var f = Object.freeze(function foo(a, b) { return false; }); +f(1, "") === false; +var a = Object.freeze([1, 2, 3]); +a[0] = 1; +var o = Object.freeze({ a: 1, b: "string" }); +o.b = "another"; diff --git a/tests/cases/compiler/objectFreeze.ts b/tests/cases/compiler/objectFreeze.ts index e92f9ecd00e..2c93fc8f075 100644 --- a/tests/cases/compiler/objectFreeze.ts +++ b/tests/cases/compiler/objectFreeze.ts @@ -1,6 +1,8 @@ -class A { - constructor(public a1: string) { - } -} -function foo(x = new A(123)) { //should error, 123 is not string -}} \ No newline at end of file +const f = Object.freeze(function foo(a: number, b: string) { return false; }); +f(1, "") === false; + +const a = Object.freeze([1, 2, 3]); +a[0] = 1; + +const o = Object.freeze({ a: 1, b: "string" }); +o.b = "another"; From 60395565e6fb9767aa6a73a0086238793bb7df58 Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Wed, 23 Nov 2016 09:48:25 -0800 Subject: [PATCH 3/6] Handel call and construct signatures --- src/lib/es5.d.ts | 12 ++++++++++++ .../reference/objectFreeze.errors.txt | 12 ++++++++---- tests/baselines/reference/objectFreeze.js | 19 +++++++++++++++---- tests/cases/compiler/objectFreeze.ts | 8 ++++++-- 4 files changed, 41 insertions(+), 10 deletions(-) diff --git a/src/lib/es5.d.ts b/src/lib/es5.d.ts index 3ad6046c85e..097089e371f 100644 --- a/src/lib/es5.d.ts +++ b/src/lib/es5.d.ts @@ -182,6 +182,18 @@ interface ObjectConstructor { */ freeze(a: T[]): ReadonlyArray; + /** + * Prevents the modification of existing property attributes and values, and prevents the addition of new properties. + * @param o Object on which to lock the attributes. + */ + freeze any>(f: T): T; + + /** + * Prevents the modification of existing property attributes and values, and prevents the addition of new properties. + * @param o Object on which to lock the attributes. + */ + freeze any>(c: T): T; + /** * Prevents the modification of existing property attributes and values, and prevents the addition of new properties. * @param o Object on which to lock the attributes. diff --git a/tests/baselines/reference/objectFreeze.errors.txt b/tests/baselines/reference/objectFreeze.errors.txt index 0a1a0518829..9c28c62f534 100644 --- a/tests/baselines/reference/objectFreeze.errors.txt +++ b/tests/baselines/reference/objectFreeze.errors.txt @@ -1,18 +1,22 @@ -tests/cases/compiler/objectFreeze.ts(5,1): error TS2542: Index signature in type 'ReadonlyArray' only permits reading. -tests/cases/compiler/objectFreeze.ts(8,3): error TS2540: Cannot assign to 'b' because it is a constant or a read-only property. +tests/cases/compiler/objectFreeze.ts(9,1): error TS2542: Index signature in type 'ReadonlyArray' only permits reading. +tests/cases/compiler/objectFreeze.ts(12,3): error TS2540: Cannot assign to 'b' because it is a constant or a read-only property. ==== tests/cases/compiler/objectFreeze.ts (2 errors) ==== const f = Object.freeze(function foo(a: number, b: string) { return false; }); f(1, "") === false; + class C { constructor(a: number) { } } + const c = Object.freeze(C); + new c(1); + const a = Object.freeze([1, 2, 3]); - a[0] = 1; + a[0] = a[2].toString(); ~~~~ !!! error TS2542: Index signature in type 'ReadonlyArray' only permits reading. const o = Object.freeze({ a: 1, b: "string" }); - o.b = "another"; + o.b = o.a.toString(); ~ !!! error TS2540: Cannot assign to 'b' because it is a constant or a read-only property. \ No newline at end of file diff --git a/tests/baselines/reference/objectFreeze.js b/tests/baselines/reference/objectFreeze.js index 51308c8e07c..4c37631bb10 100644 --- a/tests/baselines/reference/objectFreeze.js +++ b/tests/baselines/reference/objectFreeze.js @@ -2,17 +2,28 @@ const f = Object.freeze(function foo(a: number, b: string) { return false; }); f(1, "") === false; +class C { constructor(a: number) { } } +const c = Object.freeze(C); +new c(1); + const a = Object.freeze([1, 2, 3]); -a[0] = 1; +a[0] = a[2].toString(); const o = Object.freeze({ a: 1, b: "string" }); -o.b = "another"; +o.b = o.a.toString(); //// [objectFreeze.js] var f = Object.freeze(function foo(a, b) { return false; }); f(1, "") === false; +var C = (function () { + function C(a) { + } + return C; +}()); +var c = Object.freeze(C); +new c(1); var a = Object.freeze([1, 2, 3]); -a[0] = 1; +a[0] = a[2].toString(); var o = Object.freeze({ a: 1, b: "string" }); -o.b = "another"; +o.b = o.a.toString(); diff --git a/tests/cases/compiler/objectFreeze.ts b/tests/cases/compiler/objectFreeze.ts index 2c93fc8f075..5e8539831b1 100644 --- a/tests/cases/compiler/objectFreeze.ts +++ b/tests/cases/compiler/objectFreeze.ts @@ -1,8 +1,12 @@ const f = Object.freeze(function foo(a: number, b: string) { return false; }); f(1, "") === false; +class C { constructor(a: number) { } } +const c = Object.freeze(C); +new c(1); + const a = Object.freeze([1, 2, 3]); -a[0] = 1; +a[0] = a[2].toString(); const o = Object.freeze({ a: 1, b: "string" }); -o.b = "another"; +o.b = o.a.toString(); From 15d870bdcf6875b3d0824e642ce4aa673826dba6 Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Wed, 23 Nov 2016 10:56:42 -0800 Subject: [PATCH 4/6] Use `Function` instead of call and construct signatures --- src/lib/es5.d.ts | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/src/lib/es5.d.ts b/src/lib/es5.d.ts index 097089e371f..1e6b44788b3 100644 --- a/src/lib/es5.d.ts +++ b/src/lib/es5.d.ts @@ -186,19 +186,7 @@ interface ObjectConstructor { * Prevents the modification of existing property attributes and values, and prevents the addition of new properties. * @param o Object on which to lock the attributes. */ - freeze any>(f: T): T; - - /** - * Prevents the modification of existing property attributes and values, and prevents the addition of new properties. - * @param o Object on which to lock the attributes. - */ - freeze any>(c: T): T; - - /** - * Prevents the modification of existing property attributes and values, and prevents the addition of new properties. - * @param o Object on which to lock the attributes. - */ - freeze(f: (...args: any[]) => T): (...args: any[]) => T; + freeze(f: T): T; /** * Prevents the modification of existing property attributes and values, and prevents the addition of new properties. From 20a8a30b76bf9ca95678951f69a1cc8f418bad71 Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Wed, 23 Nov 2016 12:20:55 -0800 Subject: [PATCH 5/6] Instead of creating clone of the jsxFactory's leaf node, create synthesized node Fixes #12467 This avoid setting original node which would be something from isolated parsing and hence not valid when resolving expression --- src/compiler/factory.ts | 14 +++------- .../jsxFactoryQualifiedNameWithEs5.js | 27 +++++++++++++++++++ .../jsxFactoryQualifiedNameWithEs5.symbols | 23 ++++++++++++++++ .../jsxFactoryQualifiedNameWithEs5.types | 27 +++++++++++++++++++ .../jsxFactoryQualifiedNameWithEs5.ts | 17 ++++++++++++ 5 files changed, 98 insertions(+), 10 deletions(-) create mode 100644 tests/baselines/reference/jsxFactoryQualifiedNameWithEs5.js create mode 100644 tests/baselines/reference/jsxFactoryQualifiedNameWithEs5.symbols create mode 100644 tests/baselines/reference/jsxFactoryQualifiedNameWithEs5.types create mode 100644 tests/cases/compiler/jsxFactoryQualifiedNameWithEs5.ts diff --git a/src/compiler/factory.ts b/src/compiler/factory.ts index 63333dbe0b2..ebcea221f9e 100644 --- a/src/compiler/factory.ts +++ b/src/compiler/factory.ts @@ -1677,16 +1677,10 @@ namespace ts { function createJsxFactoryExpressionFromEntityName(jsxFactory: EntityName, parent: JsxOpeningLikeElement): Expression { if (isQualifiedName(jsxFactory)) { - return createPropertyAccess( - createJsxFactoryExpressionFromEntityName( - jsxFactory.left, - parent - ), - setEmitFlags( - getMutableClone(jsxFactory.right), - EmitFlags.NoSourceMap - ) - ); + const left = createJsxFactoryExpressionFromEntityName(jsxFactory.left, parent); + const right = createSynthesizedNode(SyntaxKind.Identifier); + right.text = jsxFactory.right.text; + return createPropertyAccess(left, right); } else { return createReactNamespace(jsxFactory.text, parent); diff --git a/tests/baselines/reference/jsxFactoryQualifiedNameWithEs5.js b/tests/baselines/reference/jsxFactoryQualifiedNameWithEs5.js new file mode 100644 index 00000000000..ecf7d13d89d --- /dev/null +++ b/tests/baselines/reference/jsxFactoryQualifiedNameWithEs5.js @@ -0,0 +1,27 @@ +//// [index.tsx] + +import "./jsx"; + +var skate: any; +const React = { createElement: skate.h }; + +class Component { + renderCallback() { + return
test
; + } +}; + +//// [index.js] +"use strict"; +require("./jsx"); +var skate; +var React = { createElement: skate.h }; +var Component = (function () { + function Component() { + } + Component.prototype.renderCallback = function () { + return skate.h("div", null, "test"); + }; + return Component; +}()); +; diff --git a/tests/baselines/reference/jsxFactoryQualifiedNameWithEs5.symbols b/tests/baselines/reference/jsxFactoryQualifiedNameWithEs5.symbols new file mode 100644 index 00000000000..35879c81ca6 --- /dev/null +++ b/tests/baselines/reference/jsxFactoryQualifiedNameWithEs5.symbols @@ -0,0 +1,23 @@ +=== tests/cases/compiler/index.tsx === + +import "./jsx"; + +var skate: any; +>skate : Symbol(skate, Decl(index.tsx, 3, 3)) + +const React = { createElement: skate.h }; +>React : Symbol(React, Decl(index.tsx, 4, 5)) +>createElement : Symbol(createElement, Decl(index.tsx, 4, 15)) +>skate : Symbol(skate, Decl(index.tsx, 3, 3)) + +class Component { +>Component : Symbol(Component, Decl(index.tsx, 4, 41)) + + renderCallback() { +>renderCallback : Symbol(Component.renderCallback, Decl(index.tsx, 6, 17)) + + return
test
; +>div : Symbol(unknown) +>div : Symbol(unknown) + } +}; diff --git a/tests/baselines/reference/jsxFactoryQualifiedNameWithEs5.types b/tests/baselines/reference/jsxFactoryQualifiedNameWithEs5.types new file mode 100644 index 00000000000..21fd4bae84b --- /dev/null +++ b/tests/baselines/reference/jsxFactoryQualifiedNameWithEs5.types @@ -0,0 +1,27 @@ +=== tests/cases/compiler/index.tsx === + +import "./jsx"; + +var skate: any; +>skate : any + +const React = { createElement: skate.h }; +>React : { createElement: any; } +>{ createElement: skate.h } : { createElement: any; } +>createElement : any +>skate.h : any +>skate : any +>h : any + +class Component { +>Component : Component + + renderCallback() { +>renderCallback : () => any + + return
test
; +>
test
: any +>div : any +>div : any + } +}; diff --git a/tests/cases/compiler/jsxFactoryQualifiedNameWithEs5.ts b/tests/cases/compiler/jsxFactoryQualifiedNameWithEs5.ts new file mode 100644 index 00000000000..86fd9935a1f --- /dev/null +++ b/tests/cases/compiler/jsxFactoryQualifiedNameWithEs5.ts @@ -0,0 +1,17 @@ +//@module: commonjs +//@target: es5 +//@jsx: react +//@jsxFactory: skate.h +//@noEmit: false + +// @filename: index.tsx +import "./jsx"; + +var skate: any; +const React = { createElement: skate.h }; + +class Component { + renderCallback() { + return
test
; + } +}; \ No newline at end of file From c05bf3b0a2ff5c72b37d271dc557391f66d2c79a Mon Sep 17 00:00:00 2001 From: Vladimir Matveev Date: Wed, 23 Nov 2016 12:34:00 -0800 Subject: [PATCH 6/6] respect casing when comparing names of config files (#12474) --- .../unittests/tsserverProjectSystem.ts | 29 +++++++++++++++++++ src/server/editorServices.ts | 10 +++++-- src/server/project.ts | 2 ++ 3 files changed, 39 insertions(+), 2 deletions(-) diff --git a/src/harness/unittests/tsserverProjectSystem.ts b/src/harness/unittests/tsserverProjectSystem.ts index 43f125b0bed..a0a6ac7f01e 100644 --- a/src/harness/unittests/tsserverProjectSystem.ts +++ b/src/harness/unittests/tsserverProjectSystem.ts @@ -578,6 +578,35 @@ namespace ts.projectSystem { checkWatchedDirectories(host, ["/a/b/c", "/a/b", "/a"]); }); + it("can handle tsconfig file name with difference casing", () => { + const f1 = { + path: "/a/b/app.ts", + content: "let x = 1" + }; + const config = { + path: "/a/b/tsconfig.json", + content: JSON.stringify({ + include: [] + }) + }; + + const host = createServerHost([f1, config], { useCaseSensitiveFileNames: false }); + const service = createProjectService(host); + service.openExternalProject({ + projectFileName: "/a/b/project.csproj", + rootFiles: toExternalFiles([f1.path, combinePaths(getDirectoryPath(config.path).toUpperCase(), getBaseFileName(config.path))]), + options: {} + }); + service.checkNumberOfProjects({ configuredProjects: 1 }); + checkProjectActualFiles(service.configuredProjects[0], []); + + service.openClientFile(f1.path); + service.checkNumberOfProjects({ configuredProjects: 1, inferredProjects: 1 }); + + checkProjectActualFiles(service.configuredProjects[0], []); + checkProjectActualFiles(service.inferredProjects[0], [f1.path]); + }) + it("create configured project without file list", () => { const configFile: FileOrFolder = { path: "/a/b/tsconfig.json", diff --git a/src/server/editorServices.ts b/src/server/editorServices.ts index 881d188307d..df46f32672f 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -257,7 +257,7 @@ namespace ts.server { private changedFiles: ScriptInfo[]; - private toCanonicalFileName: (f: string) => string; + readonly toCanonicalFileName: (f: string) => string; public lastDeletedFile: ScriptInfo; @@ -777,7 +777,13 @@ namespace ts.server { } private findConfiguredProjectByProjectName(configFileName: NormalizedPath) { - return findProjectByName(configFileName, this.configuredProjects); + // make sure that casing of config file name is consistent + configFileName = asNormalizedPath(this.toCanonicalFileName(configFileName)); + for (const proj of this.configuredProjects) { + if (proj.canonicalConfigFilePath === configFileName) { + return proj; + } + } } private findExternalProjectByProjectName(projectFileName: string) { diff --git a/src/server/project.ts b/src/server/project.ts index c37dd6e135a..c28b29b944b 100644 --- a/src/server/project.ts +++ b/src/server/project.ts @@ -817,6 +817,7 @@ namespace ts.server { private directoryWatcher: FileWatcher; private directoriesWatchedForWildcards: Map; private typeRootsWatchers: FileWatcher[]; + readonly canonicalConfigFilePath: NormalizedPath; /** Used for configured projects which may have multiple open roots */ openRefCount = 0; @@ -830,6 +831,7 @@ namespace ts.server { languageServiceEnabled: boolean, public compileOnSaveEnabled: boolean) { super(configFileName, ProjectKind.Configured, projectService, documentRegistry, hasExplicitListOfFiles, languageServiceEnabled, compilerOptions, compileOnSaveEnabled); + this.canonicalConfigFilePath = asNormalizedPath(projectService.toCanonicalFileName(configFileName)); } getConfigFilePath() {