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
This commit is contained in:
Jack Works 2020-10-16 02:01:26 +08:00 committed by GitHub
parent 9e5a77937a
commit ad96a52cc6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -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;