codemodsquad / asyncify

Don't keep your promises 😉
MIT License
13 stars 6 forks source link

fix: avoid creating invalid syntax async get method #40

Closed yonran closed 3 years ago

yonran commented 3 years ago

Previously, asyncify would convert a getter/setter into an invalid async getter/setter.

Input:

class A {
  method() {return p.then(x => f(x))}
  get prop() {return p.then(x => f(x))}
  set prop(val) {return p.then(x => f(x))}
  get longchain() {return p.then(x => f(x)).then(y => g(y)).then(z => h(z))}
}
const obj = {
  method() {return p.then(x => f(x))},
  get prop() {return p.then(x => f(x))},
  set prop(val) {return p.then(x => f(x))}
};

Output before this PR. Note that get prop() is converted to async get prop(), which is invalid ECMAScript and invalid TypeScript:

class A {
  async method() {
    const x = await p;
    return f(x);
  }
  async get prop() {
    const x = await p;
    return f(x);
  }
  async set prop(val) {
    const x = await p;
    return f(x);
  }
  async get longchain() {
    const x = await p;
    const y = await f(x);
    const z = await g(y);
    return h(z);
  }
}
const obj = {
  async method() {
    const x = await p;
    return f(x);
  },
  async get prop() {
    const x = await p;
    return f(x);
  },
  async set prop(val) {
    const x = await p;
    return f(x);
  }
};

Output after this PR: get and set methods are not converted to async, and instead an immediately invoked function expression (IIFE) is created, or the promise chain is ignored, depending on the length of the chain.

class A {
  async method() {
    const x = await p;
    return f(x);
  }
  get prop() {return p.then(x => f(x))}
  set prop(val) {return p.then(x => f(x))}
  get longchain() {return (async () => {
    const x = await p;
    const y = await f(x);
    const z = await g(y);
    return await h(z);
  })();}
}
const obj = {
  async method() {
    const x = await p;
    return f(x);
  },
  get prop() {return p.then(x => f(x))},
  set prop(val) {return p.then(x => f(x))}
};

I made a similar PR here https://github.com/sgilroy/async-await-codemod/pull/21 but then I found this repo where all the action seems to be

Note: the precommit hook failed in tsc --noEmit on files that I did not modify (with errors like Type 'NodePath<Node>' is not assignable to type 'T extends Program ? null : NodePath<Node>'), so I had to git commit --no-verify. Probably I npm installed a different version of TypeScript than you use. Please advise on how to continue.

jedwards1211 commented 3 years ago

Looks good, thanks for the great work!

Yup this project uses yarn 1 instead of npm. Be on the lookout for yarn.lock in other repos, I wish npm would warn when it sees it.

jedwards1211 commented 3 years ago

:tada: This PR is included in version 2.2.2 :tada:

The release is available on:

Your semantic-release bot :package::rocket: