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

fix(core): module execution with top level await #7672

Merged
merged 19 commits into from
Oct 6, 2020

Conversation

bartlomieju
Copy link
Member

@bartlomieju bartlomieju commented Sep 25, 2020

Fixes #7649

This commit fixes implementation of top level await in "deno_core".

Previously promise returned from module execution was ignored causing to execute
modules out-of-order.

With this commit promise returned from module execution is stored on "JsRuntime"
and event loop is polled until the promise resolves.

@bartlomieju bartlomieju changed the title [WIP] debug TLA in modules fix: top level await in deno_core Oct 4, 2020
@bartlomieju bartlomieju changed the title fix: top level await in deno_core fix(core): module execution with top level await Oct 4, 2020
Copy link
Member

@ry ry left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given that it fixes a bug, I think we should land this - awesome work.

Ok(receiver)
}

pub async fn mod_evaluate(&mut self, id: ModuleId) -> Result<(), AnyError> {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it odd that JsRuntime itself is a future, but it now has a method which also returns a future?

Copy link
Member Author

@bartlomieju bartlomieju Oct 5, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ry there is a precedent with JsRuntime::load_module which we've had for a couple months. I think having load_module and mod_evaluate be async really well represents what's going on in V8.

Copy link
Member

@ry ry Oct 5, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happens if you try to tokio::select! on both the result of mod_evaluate and the JsRuntime itself?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

JsRuntime would be polled twice (because it's polled once in mod_evaluate). I don't like JsRuntime being a future, there's only a single time that you want to run event loop to complication - in main.rs. I would prefer to have explicit JsRuntime::poll_event_loop() instead.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happens if you try to tokio::select! on both the result of mod_evaluate and the JsRuntime itself?

That either isn't or shouldn't be possible.
You need a &mut reference to a Future to poll it, so you can't poll X and a container with X in it at the same time.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually @piscisaureus is right:

  let fut = self.isolate.mod_evaluate(id);
    tokio::select! {
      _ = fut => {
        // 
        Ok(())
      }
      _ = self.isolate => {
        //
        Ok(())
      }
    }
error[E0507]: cannot move out of `self.isolate` which is behind a mutable reference
   --> cli/worker.rs:198:11
    |
198 |       _ = self.isolate => {
    |           ^^^^^^^^^^^^ move occurs because `self.isolate` has type `deno_core::JsRuntime`, which does not implement the `Copy` trait

error[E0505]: cannot move out of `self.isolate` because it is borrowed
   --> cli/worker.rs:198:11
    |
192 |       let fut = self.isolate.mod_evaluate(id);
    |                 ------------ borrow of `self.isolate` occurs here
193 | /     tokio::select! {
194 | |       _ = fut => {
195 | |         //
196 | |         Ok(())
197 | |       }
198 | |       _ = self.isolate => {
    | |           ^^^^^^^^^^^^ move out of `self.isolate` occurs here
...   |
201 | |       }
202 | |     }
    | |_____- borrow later used here

@piscisaureus
Copy link
Member

The strategy seems sound to me.
Also underlines the need for this monster to be refactored...

Copy link
Member

@piscisaureus piscisaureus left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

A skilful hack; also great to accumulate all these tests.

@bartlomieju bartlomieju merged commit c7c7677 into denoland:master Oct 6, 2020
@bartlomieju bartlomieju deleted the debug_tla branch October 6, 2020 08:18
Soremwar pushed a commit to Soremwar/deno that referenced this pull request Oct 6, 2020
This commit fixes implementation of top level await in "deno_core".

Previously promise returned from module execution was ignored causing to execute
modules out-of-order.

With this commit promise returned from module execution is stored on "JsRuntime"
and event loop is polled until the promise resolves.
ry added a commit to ry/deno that referenced this pull request Oct 10, 2020
bartlomieju pushed a commit that referenced this pull request Oct 10, 2020
* Revert "refactor: Worker is not a Future (#7895)"

This reverts commit f4357f0.

* Revert "refactor(core): JsRuntime is not a Future (#7855)"

This reverts commit d8879fe.

* Revert "fix(core): module execution with top level await (#7672)"

This reverts commit c7c7677.
iykekings pushed a commit to iykekings/deno that referenced this pull request Oct 10, 2020
* Revert "refactor: Worker is not a Future (denoland#7895)"

This reverts commit f4357f0.

* Revert "refactor(core): JsRuntime is not a Future (denoland#7855)"

This reverts commit d8879fe.

* Revert "fix(core): module execution with top level await (denoland#7672)"

This reverts commit c7c7677.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Top-level await does not work with dynamic await import()
3 participants