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
Using OnceCell<T> from Mitochondria #18059
Conversation
|
components/script/dom/bindings/js.rs
Outdated
/// on `JS<T>`. | ||
#[must_root] | ||
pub struct OnceCellJS<T: DomObject> { | ||
ptr: OnceCell<Option<JS<T>>>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There should be no Option<T>
here.
components/script/dom/bindings/js.rs
Outdated
|
||
/// Retrieve a copy of the current inner value. If it is `None`, it is | ||
/// initialized with the result of `cb` first. | ||
pub fn or_init<F>(&self, cb: F) -> Root<T> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should call OnceCell::init_once
.
components/script/dom/bindings/js.rs
Outdated
debug_assert!(thread_state::get().is_layout()); | ||
match self.ptr.as_ref() { | ||
Some(ptr_ref) => { | ||
ptr::read(ptr_ref).map(|js| js.to_layout()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why ptr::read
?
components/script/dom/bindings/js.rs
Outdated
unsafe { | ||
match self.ptr.as_ref() { | ||
Some(ptr_ref) => { | ||
ptr::read(ptr_ref).map(|o| Root::from_ref(&*o)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why ptr::read
?
components/script/dom/bindings/js.rs
Outdated
pub fn get(&self) -> Option<Root<T>> { | ||
debug_assert!(thread_state::get().is_script()); | ||
unsafe { | ||
match self.ptr.as_ref() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use Option::map
instead of a match
expression.
components/script/dom/bindings/js.rs
Outdated
} | ||
|
||
/// Set this `OnceCellJS` to the given value. If it is not already set | ||
pub fn set(&self, val: Option<&T>) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This method shouldn't exist at all.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
using init_once straight away in or_init
method causes the following error
expected type `core::option::Option<T>`
found type `core::option::Option<&dom::bindings::js::JS<T>>`
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
and if I pass it to this method it kinda works.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This method shouldn't exist anyway.
components/script/dom/bindings/js.rs
Outdated
} | ||
|
||
/// Gets the current value out of this object and sets it to `None`. | ||
pub fn take(&self) -> Option<Root<T>> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This method shouldn't exist at all.
components/script/dom/bindings/js.rs
Outdated
} | ||
} | ||
|
||
impl<T: DomObject> PartialEq for OnceCellJS<T> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be derived.
components/script/dom/bindings/js.rs
Outdated
#[cfg(not(debug_assertions))] | ||
let trace_info = "for DOM object on heap"; | ||
|
||
match self.ptr.as_ref().clone() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just call trace on the result of self.ptr.as_ref()
.
components/script/dom/bindings/js.rs
Outdated
@@ -603,4 +756,4 @@ unsafe impl<T: DomObject> JSTraceable for Root<T> { | |||
unsafe fn trace(&self, _: *mut JSTracer) { | |||
// Already traced. | |||
} | |||
} | |||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: missing new line.
components/script/dom/bindings/js.rs
Outdated
|
||
/// Get a rooted value out of this object | ||
#[allow(unrooted_must_root)] | ||
pub fn get(&self) -> Option<Root<T>> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this is the right return type. The whole idea behind the issue is that whenever I call the get
method, I shouldn't need to worry about whether the cell is empty or not, and that it will always get the appropriate value for me.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That makes sense. Since MutNullableJS and MutJS returns Root<T>
, I decided to return something similar. Rather here I will return Option<JS<T>>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, Option<JS<T>>
shouldn't be returned, but Option<&T>
.
components/script/dom/bindings/js.rs
Outdated
/// Retrieve a copy of the current inner value. If it is `None`, it is | ||
/// initialized with the result of `cb` first. | ||
#[allow(unrooted_must_root)] | ||
pub unsafe fn or_init<F>(&self, cb: F) -> &JS<T> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm still not convinced this is an improvement over MutNullableJS<T>
. In fact as it stands currently, it is an exact copy of it. Let me reiterate the goals of the issue:
Consider the Elements method in HTMLFormElement. It tries to see if the elements
field is a Some
; if so, it would return that inner value, and if not, it does a whole chunk of initialization for it, and finally setting that inner value into Some
.
What I personally would like to see is to have that method body be reduced into simply self.elements.get()
, and perhaps in the new
method of the OnceCellJS that houses the list of elements, accept a closure/function that gets called whenever the get
method encounters a None
for its inner value.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should return &T
. get
should either not exist or return Option<&T>
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My comments should be addressed, and then the commits should be squashed together. Also, we can't land this as long as you don't also migrate at least one |
components/script/dom/bindings/js.rs
Outdated
#[allow(unrooted_must_root)] | ||
unsafe impl<T: DomObject> JSTraceable for OnceCellJS<T> { | ||
unsafe fn trace(&self, trc: *mut JSTracer) { | ||
match self.ptr.as_ref() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if let Some(ptr) = self.ptr.as_ref() {
ptr.trace(trc);
}
components/script/dom/bindings/js.rs
Outdated
/// Retrieve a copy of the current inner value. If it is `None`, it is | ||
/// initialized with the result of `cb` first. | ||
#[allow(unrooted_must_root)] | ||
pub unsafe fn or_init<F>(&self, cb: F) -> &T |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is still uncorrect.
- It should not be
unsafe
. F
should beFnOnce() -> Root<T>
.- The method should only call
init_once
with a wrapper ofcb
converting theRoot<T>
toJS<T>
and dereferencing the returnedJS<T>
to&T
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm still confused as to why this function exists. How is this any different than MutNullableJS?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You cannot retrieve a &T
from a MutNullableJS<T>
. IMO the method should be named init_once
just like in Mitochondria.
components/script/dom/bindings/js.rs
Outdated
|
||
impl<T: DomObject> OnceCellJS<T> { | ||
/// Create a new `OnceCellJS` with value | ||
pub fn new(initial: Option<&T>) -> OnceCellJS<T> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm pretty sure there is no need for an initial value at all here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
which makes this function similar to Default::default()
Instead, we can change the signature to new_with_value
similar to mitochondria
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't really seem to see that use case at all... Why would you need to provide an initial value when the purpose is to either get it from the OnceCell
or run a closure to produce a value?
components/script/dom/bindings/js.rs
Outdated
|
||
impl<T: DomObject> OnceCellJS<T> { | ||
/// Create a new `OnceCellJS` with value | ||
pub fn new() -> OnceCellJS<T> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Make that the impl of Default
for OnceCellJS<T>
and this is good to go!
Thanks for keeping up with my comments!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You mean change this method into default
or implement default
separately.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Implement the Default
trait on OnceCellJS
, and move the method body below to be inside of fn default
.
Am stupid, the PR should be rebased to land. >< |
🔒 Merge conflict |
let filter = box ElementsFilter { form: Root::from_ref(self) }; | ||
let window = window_from_node(self); | ||
let elements = HTMLFormControlsCollection::new(&window, self.upcast(), filter); | ||
elements |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can the elements
variable be removed here?
adding oncecell for JS references removing option<JS<T>> to <JS<T>> changing return types removing get method and refactoring the function changing getElements method lint fixes moving to default simplifying return ordering Removing elements linting
@nox is it pending for any other thing? |
@bors-servo r=nox |
📌 Commit 8b33e0f has been approved by |
🌲 The tree is currently closed for pull requests below priority 9000, this pull request will be tested once the tree is reopened |
⌛ Testing commit 8b33e0f with merge b42a2b2918e79820c4b228bfa88cd8cf37eedfe4... |
💔 Test failed - linux-rel-wpt |
Using OnceCell<T> from Mitochondria <!-- Please describe your changes on the following line: --> --- <!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `__` with appropriate data: --> - [x] `./mach build -d` does not report any errors - [x] `./mach test-tidy` does not report any errors - [x] These changes fix #13402 (github issue number if applicable). <!-- Also, please make sure that "Allow edits from maintainers" checkbox is checked, so that we can help you if you get stuck somewhere along the way.--> <!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. --> <!-- Reviewable:start --> --- This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/18059) <!-- Reviewable:end -->
☀️ Test successful - android, arm32, arm64, linux-dev, linux-rel-css, linux-rel-wpt, mac-dev-unit, mac-rel-css1, mac-rel-css2, mac-rel-wpt1, mac-rel-wpt2, mac-rel-wpt3, mac-rel-wpt4, windows-msvc-dev |
./mach build -d
does not report any errors./mach test-tidy
does not report any errorsThis change is