From ad96a52cc6451be4ee3b48078da875a9eb2faa49 Mon Sep 17 00:00:00 2001 From: Jack Works Date: Fri, 16 Oct 2020 02:01:26 +0800 Subject: [PATCH] fix: IOSession access this before calling super (#40645) * fix: IOSession access this before calling super close #40399 This makes the TS server crashes if the build target is ES6 or higher. * fix * revert unrelated changes * revert unrelated changes * revert unrelated changes * better way --- src/tsserver/server.ts | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/src/tsserver/server.ts b/src/tsserver/server.ts index 3f6ba6b2a17..306cbd7bba3 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(); @@ -481,21 +485,12 @@ 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() { - const event: Event | undefined = (body: object, eventName: string) => { - if (this.constructed) { - this.event(body, eventName); - } - else { - // It is unsafe to dereference `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;