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

feat(core): Add initial support for realms #14019

Merged
merged 14 commits into from
Apr 17, 2022

Conversation

andreubotella
Copy link
Contributor

This handles bindings, extension JS and sync ops. It also adds the JsRealm API that adds methods like JsRuntime's handle_scope, global_object and execute_script specific to the realm.

Towards #13239.


@bartlomieju @AaronO @littledivy PTAL. Does this conflict with some of the remaining work to do for ops?

This handles bindings, extension JS and sync ops. It also adds the
`JsRealm` API that adds methods like `JsRuntime`'s `handle_scope`,
`global_object` and `execute_script` specific to the realm.

Towards denoland#13239.
@andreubotella andreubotella marked this pull request as ready for review March 21, 2022 10:14
@andreubotella andreubotella changed the title [WIP] Add initial support for realms in deno_core Add initial support for realms in deno_core Mar 21, 2022
Copy link
Member

@lucacasonato lucacasonato left a comment

Choose a reason for hiding this comment

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

Looks good to me. Thanks for the work @andreubotella.

I do wonder if JsRealm's lifetime could not be bound to JsRuntime, so it could store a reference to the JsRuntime in the JsRealm struct. That would alleviate the need to pass the runtime to all the methods on the JsRealm.

@bartlomieju
Copy link
Member

Looks good to me. Thanks for the work @andreubotella.

I do wonder if JsRealm's lifetime could not be bound to JsRuntime, so it could store a reference to the JsRuntime in the JsRealm struct. That would alleviate the need to pass the runtime to all the methods on the JsRealm.

I think it might be a bad idea to store a mutable reference to JsRuntime inside the JsRealm, that would effectively limit to a creation of a single realm and wouldn't allow to use JsRuntime anymore?

core/runtime.rs Outdated Show resolved Hide resolved
@bartlomieju bartlomieju changed the title Add initial support for realms in deno_core feat(core): Add initial support for realms Mar 22, 2022
@bartlomieju
Copy link
Member

Yikes, sorry it takes so long @andreubotella, could you rebase the PR?

@andreubotella
Copy link
Contributor Author

Yikes, sorry it takes so long @andreubotella, could you rebase the PR?

Done.

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!

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 19bb82a into denoland:main Apr 17, 2022
@andreubotella andreubotella deleted the initial-realms branch April 17, 2022 15:58
andreubotella added a commit to andreubotella/deno that referenced this pull request May 26, 2022
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 denoland#13239.
andreubotella added a commit to andreubotella/deno that referenced this pull request May 28, 2022
This behavior was introduced in denoland#14019 but wasn't properly tested in
that PR.
bartlomieju pushed a commit that referenced this pull request May 30, 2022
#14750)

This behavior was introduced in #14019 but wasn't properly tested in
that PR.
bartlomieju pushed a commit that referenced this pull request Jun 2, 2022
#14750)

This behavior was introduced in #14019 but wasn't properly tested in
that PR.
andreubotella added a commit to andreubotella/deno that referenced this pull request Jul 10, 2022
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 denoland#13239.

Co-authored-by: Luis Malheiro <[email protected]>
andreubotella added a commit to andreubotella/deno that referenced this pull request Jul 11, 2022
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 denoland#13239.

Co-authored-by: Luis Malheiro <[email protected]>
bartlomieju pushed a commit that referenced this pull request Aug 10, 2022
Pull request #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.

Co-authored-by: Luis Malheiro <[email protected]>
bartlomieju pushed a commit to littledivy/deno that referenced this pull request Aug 11, 2022
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.

Co-authored-by: Luis Malheiro <[email protected]>
dsherret pushed a commit that referenced this pull request Aug 11, 2022
Pull request #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.

Co-authored-by: Luis Malheiro <[email protected]>
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.

None yet

4 participants