From 1cf58c3994321e2c5f2aafbf73bc89c18eb8c3cf Mon Sep 17 00:00:00 2001 From: Jack Works Date: Sat, 19 Sep 2020 17:02:46 +0800 Subject: [PATCH 1/6] fix: IOSession access this before calling super close #40399 This makes the TS server crashes if the build target is ES6 or higher. --- src/tsserver/server.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/tsserver/server.ts b/src/tsserver/server.ts index 3f6ba6b2a1769..0c3efa03f00a3 100644 --- a/src/tsserver/server.ts +++ b/src/tsserver/server.ts @@ -484,8 +484,9 @@ namespace ts.server { private constructed: boolean | undefined; constructor() { + let isConstructed = false; const event: Event | undefined = (body: object, eventName: string) => { - if (this.constructed) { + if (isConstructed) { this.event(body, eventName); } else { @@ -539,6 +540,7 @@ namespace ts.server { } this.constructed = true; + isConstructed = true; } event(body: T, eventName: string): void { From 25ebc12cb3d2ad8dd6b32c6ca70701260588a2d8 Mon Sep 17 00:00:00 2001 From: Jack Works Date: Thu, 15 Oct 2020 13:29:54 +0800 Subject: [PATCH 2/6] fix --- .vscode/tasks.json | 9 +++++++++ src/tsconfig-base.json | 2 +- src/tsserver/server.ts | 14 ++++++-------- 3 files changed, 16 insertions(+), 9 deletions(-) diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 807da9ce56e69..a023aca90f931 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -39,7 +39,16 @@ "label": "gulp: services", "problemMatcher": [ "$tsc" + ] + }, + { + "type": "gulp", + "task": "watch-tsserver", + "problemMatcher": [ + "$gulp-tsc" ], + "group": "build", + "label": "gulp: watch-tsserver" } ] } \ No newline at end of file diff --git a/src/tsconfig-base.json b/src/tsconfig-base.json index b0515e0a023d6..bbf41460cd3d5 100644 --- a/src/tsconfig-base.json +++ b/src/tsconfig-base.json @@ -2,7 +2,7 @@ "compilerOptions": { "pretty": true, "lib": ["es2015.iterable", "es2015.generator", "es5"], - "target": "es5", + "target": "es2018", "moduleResolution": "classic", "rootDir": ".", diff --git a/src/tsserver/server.ts b/src/tsserver/server.ts index 0c3efa03f00a3..094ad7a0dfac2 100644 --- a/src/tsserver/server.ts +++ b/src/tsserver/server.ts @@ -481,18 +481,17 @@ namespace ts.server { private eventPort: number | undefined; private eventSocket: NodeSocket | undefined; private socketEventQueue: { body: any, eventName: string }[] | undefined; + /** No longer needed if syntax target is es6 or above. Any access to "this" before initialized will be a runtime error. */ private constructed: boolean | undefined; constructor() { - let isConstructed = false; const event: Event | undefined = (body: object, eventName: string) => { - if (isConstructed) { + try { this.event(body, eventName); - } - else { - // It is unsafe to dereference `this` before initialization completes, - // so we defer until the next tick. - // + } catch(e) { + // ReferenceError: Must call super constructor in derived class before accessing 'this' or returning from derived constructor in ES6 or above + if (!(e instanceof ReferenceError)) throw e; + // It is unsafe to reference `this` before initialization completes, so we defer until the next tick. // Construction should finish before the next tick fires, so we do not need to do this recursively. // eslint-disable-next-line no-restricted-globals setImmediate(() => this.event(body, eventName)); @@ -540,7 +539,6 @@ namespace ts.server { } this.constructed = true; - isConstructed = true; } event(body: T, eventName: string): void { From 1351267167756dad4b212e48a09651fbb24cb191 Mon Sep 17 00:00:00 2001 From: Jack Works Date: Thu, 15 Oct 2020 13:31:03 +0800 Subject: [PATCH 3/6] revert unrelated changes --- .vscode/tasks.json | 9 --------- src/tsconfig-base.json | 2 +- 2 files changed, 1 insertion(+), 10 deletions(-) diff --git a/.vscode/tasks.json b/.vscode/tasks.json index a023aca90f931..c0aa8a34e0317 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -40,15 +40,6 @@ "problemMatcher": [ "$tsc" ] - }, - { - "type": "gulp", - "task": "watch-tsserver", - "problemMatcher": [ - "$gulp-tsc" - ], - "group": "build", - "label": "gulp: watch-tsserver" } ] } \ No newline at end of file diff --git a/src/tsconfig-base.json b/src/tsconfig-base.json index bbf41460cd3d5..b0515e0a023d6 100644 --- a/src/tsconfig-base.json +++ b/src/tsconfig-base.json @@ -2,7 +2,7 @@ "compilerOptions": { "pretty": true, "lib": ["es2015.iterable", "es2015.generator", "es5"], - "target": "es2018", + "target": "es5", "moduleResolution": "classic", "rootDir": ".", From fef1ad94474a720860b00d504605737c43a02132 Mon Sep 17 00:00:00 2001 From: Jack Works Date: Thu, 15 Oct 2020 13:31:47 +0800 Subject: [PATCH 4/6] revert unrelated changes --- .vscode/tasks.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.vscode/tasks.json b/.vscode/tasks.json index c0aa8a34e0317..4cf8e0ba106af 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -41,5 +41,5 @@ "$tsc" ] } - ] + ], } \ No newline at end of file From 61ea8fbd20343091d93f10ad36004386b8fc2856 Mon Sep 17 00:00:00 2001 From: Jack Works Date: Thu, 15 Oct 2020 13:32:18 +0800 Subject: [PATCH 5/6] revert unrelated changes --- .vscode/tasks.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 4cf8e0ba106af..807da9ce56e69 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -39,7 +39,7 @@ "label": "gulp: services", "problemMatcher": [ "$tsc" - ] + ], } - ], + ] } \ No newline at end of file From 53f1fbe6492be2be24f1a4b479129bca53718067 Mon Sep 17 00:00:00 2001 From: Jack Works Date: Thu, 15 Oct 2020 13:43:47 +0800 Subject: [PATCH 6/6] better way --- src/tsserver/server.ts | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/src/tsserver/server.ts b/src/tsserver/server.ts index 094ad7a0dfac2..306cbd7bba393 100644 --- a/src/tsserver/server.ts +++ b/src/tsserver/server.ts @@ -323,7 +323,11 @@ namespace ts.server { this.installer = childProcess.fork(combinePaths(__dirname, "typingsInstaller.js"), args, { execArgv }); this.installer.on("message", m => this.handleMessage(m)); - this.event({ pid: this.installer.pid }, "typingsInstallerPid"); + // We have to schedule this event to the next tick + // cause this fn will be called during + // new IOSession => super(which is Session) => new ProjectService => NodeTypingsInstaller.attach + // and if "event" is referencing "this" before super class is initialized, it will be a ReferenceError in ES6 class. + this.host.setImmediate(() => this.event({ pid: this.installer.pid }, "typingsInstallerPid")); process.on("exit", () => { this.installer.kill(); @@ -485,17 +489,8 @@ namespace ts.server { private constructed: boolean | undefined; constructor() { - const event: Event | undefined = (body: object, eventName: string) => { - try { - this.event(body, eventName); - } catch(e) { - // ReferenceError: Must call super constructor in derived class before accessing 'this' or returning from derived constructor in ES6 or above - if (!(e instanceof ReferenceError)) throw e; - // It is unsafe to reference `this` before initialization completes, so we defer until the next tick. - // Construction should finish before the next tick fires, so we do not need to do this recursively. - // eslint-disable-next-line no-restricted-globals - setImmediate(() => this.event(body, eventName)); - } + const event = (body: object, eventName: string) => { + this.event(body, eventName); }; const host = sys;