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

refactor(core): unwrap sync ops in rust #15449

Merged
merged 31 commits into from
Aug 11, 2022

Conversation

nayeemrmn
Copy link
Collaborator

Helps with #15337.
Supersedes #14811.

I messed up the branch at #15351 and had to open a new PR.

andreubotella and others added 29 commits July 11, 2022 17:52
Pull request denoland#14019 enabled initial support for realms, but it did not
include support for async ops anywhere other than the main realm. The
main issue was that the `js_recv_cb` callback, which resolves promises
corresponding to async ops, was only set for the main realm, so async
ops in other realms would never resolve. Furthermore, promise ID's are
specific to each realm, which meant that async ops from other realms
would result in a wrong promise from the main realm being resolved.

This change creates a `ContextState` struct, similar to
`JsRuntimeState` but stored in a slot of each `v8::Context`, which
contains a `js_recv_cb` callback for each realm. Combined with a new
list of known realms, which stores them as `v8::Weak<v8::Context>`,
and a change in the `#[op]` macro to pass the current context to
`queue_async_op`, this makes it possible to send the results of
promises for different realms to their realm, and prevent the ID's
from getting mixed up.

Additionally, since promise ID's are no longer unique to the isolate,
having a single set of unrefed ops doesn't work. This change therefore
also moves `unrefed_ops` from `JsRuntimeState` to `ContextState`, and
adds the lengths of the unrefed op sets for all known realms to get
the total number of unrefed ops to compare in the event loop.

Towards #13239.

Co-authored-by: Luis Malheiro <[email protected]>
This is so the `ContextState` reference isn't tied to the lifetime of
the isolate.

The `JsRealm::state_from_scope` method used to take a callback and
pass it a `&mut ContextState` because the mutable reference was tied
to the lifetime of a variable internal to the function, but with this
change it isn't anymore. So this method is also updated to return a
`Rc<RefCell<ContextState>>`.
}
return error;
}

function unwrapOpResult(res) {
Copy link

Choose a reason for hiding this comment

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

You should now be able to remove the unwrapOpResult function, yes?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

It's still used for async ops

Copy link

@ghost ghost Aug 11, 2022

Choose a reason for hiding this comment

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

Ah, my bad

Copy link
Member

@littledivy littledivy left a comment

Choose a reason for hiding this comment

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

LGTM!

@aapoalas
Copy link
Collaborator

LGTM

core/01_core.js Outdated Show resolved Hide resolved
Comment on lines +131 to +139
const error = errorMap[className]?.(message);
// Strip buildCustomError() calls from stack trace
if (typeof error == "object") {
ErrorCaptureStackTrace(error, buildCustomError);
if (code) {
error.code = code;
}
}
return error;
Copy link

Choose a reason for hiding this comment

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

Nit: minor, but it can be clearer, (when isn't the result an object?)

Suggested change
const error = errorMap[className]?.(message);
// Strip buildCustomError() calls from stack trace
if (typeof error == "object") {
ErrorCaptureStackTrace(error, buildCustomError);
if (code) {
error.code = code;
}
}
return error;
const errorConstructor = errorMap[className];
if (errorConstructor !== undefined) {
const error = errorConstructor(message);
// Strip buildCustomError() calls from stack trace
ErrorCaptureStackTrace(error, buildCustomError);
if (code) {
error.code = code;
}
return error;
}

Copy link
Collaborator

Choose a reason for hiding this comment

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

Theoretically the error constructor function could return anything, eg. null, I guess.

Copy link
Member

@bartlomieju bartlomieju left a comment

Choose a reason for hiding this comment

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

LGTM

@bartlomieju bartlomieju merged commit 25a1cc1 into denoland:main Aug 11, 2022
bartlomieju pushed a commit to littledivy/deno that referenced this pull request Aug 11, 2022
@nayeemrmn nayeemrmn deleted the op-sync-unwrap-in-rust branch August 11, 2022 13:46
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.

5 participants