Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Invalid code generation for top-level await with newline (expression duplicated) #39186

Closed
evanw opened this issue Jun 22, 2020 · 5 comments · Fixed by #39216
Closed

Invalid code generation for top-level await with newline (expression duplicated) #39186

evanw opened this issue Jun 22, 2020 · 5 comments · Fixed by #39216
Assignees
Labels
Bug A bug in TypeScript High Priority

Comments

@evanw
Copy link
Contributor

evanw commented Jun 22, 2020

TypeScript Version: Nightly

Search Terms: top-level await newline duplicate duplicated

Code

export let foo = () => {
  console.log('called')
  return Promise.resolve(123)
}
export let bar = await
  foo()

Expected behavior:

The generated code should only call foo() once.

Actual behavior:

The generated code calls foo() twice:

export let foo = () => {
    console.log('called');
    return Promise.resolve(123);
};
export let bar = await foo();
foo();

This may lead to subtle correctness bugs. This only happens when there's a newline between the await keyword and the awaited expression. This also only happens for top-level await. Enclosing the await in an async function makes the bug disappear.

Playground Link: link

Related Issues:

@RyanCavanaugh RyanCavanaugh added the Bug A bug in TypeScript label Jun 22, 2020
@RyanCavanaugh RyanCavanaugh added this to the TypeScript 4.0 milestone Jun 22, 2020
@RyanCavanaugh
Copy link
Member

@rbuckton big emit bug here

@rbuckton
Copy link
Member

Hmm. Not an emit bug, but a bug in the reparse for top-level await due to newline handling probably. I'll investigate.

@rbuckton
Copy link
Member

@RyanCavanaugh:

There's a "quick solution" and a "good solution":

  • quick solution: Limit the reparse to the extent of the original expression. This will prevent duplication but would result in an expression expected error following the await. This is undesirable, but is also no worse than the behavior in 3.9.
  • good solution: When reparsing, if the extent of the new expression is larger than the original expression, we must also reparse the statement that follows starting at the end position of the new expression. This may take some additional time to implement.

I'm investigating the "good solution" currently, and if it looks like it will take more than the rest of the day to implement I would advise we implement the "quick solution" for the 4.0 beta.

@RyanCavanaugh
Copy link
Member

If we already shipped this in 3.9 then I'm OK waiting for the "good solution"

@rbuckton
Copy link
Member

This wasn't in 3.9, its is a bug in the change in 4.0 to reparse await in the top-level of a module.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug A bug in TypeScript High Priority
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants