Join GitHub today
GitHub is home to over 50 million developers working together to host and review code, manage projects, and build software together.
Sign upImplemented paint worklets invoking worklet scripts. #17239
Conversation
highfive
commented
Jun 8, 2017
|
Heads up! This PR modifies the following files:
|
highfive
commented
Jun 8, 2017
| debug!("Got {:?}.", alpha); | ||
|
|
||
| // Step 14 | ||
| if unsafe { !IsConstructor(paint_obj.get()) } { |
This comment has been minimized.
This comment has been minimized.
cbrewster
Jun 9, 2017
•
Member
Is paint_ctor allowed to be an arrow function? If not, you may need to unwrap paint_obj first before using IsConstructor.
This comment has been minimized.
This comment has been minimized.
asajeffrey
Jun 9, 2017
Author
Member
Step 14 of https://drafts.css-houdini.org/css-paint-api/#dom-paintworkletglobalscope-registerpaint implies no, since IsConstructor of an arrow function is false?
This comment has been minimized.
This comment has been minimized.
cbrewster
Jun 9, 2017
Member
@asajeffrey IsConstructor returns true for any wrapper that is callable which includes wrapped arrow functions. If you use UnwrapObject and then use IsConstructor, it will return false for the arrow function.
This comment has been minimized.
This comment has been minimized.
asajeffrey
Jun 12, 2017
Author
Member
I tried it, and ran:
registerPaint("foo", (x => "arrow fn"));and got:
$ ./mach run -d ~/tmp/test.html
ERROR:script::dom::bindings::error: Error at :5:1 Not a constructor.
ERROR:script::dom::bindings::error: Error at :5:1 Not a constructor.
ERROR:script::dom::bindings::error: Error at :5:1 Not a constructor.
...
So it looks like it's doing the right thing? (Which reminds me, this needs some test cases...)
This comment has been minimized.
This comment has been minimized.
cbrewster
Jun 12, 2017
Member
Looks like the right thing, quite odd since IsConstructor always returned true for an arrow fn unless I unwrapped it. Maybe it has to do with Function vs VoidFunction
This comment has been minimized.
This comment has been minimized.
|
r? @jdm |
|
Generally straightforward implementation of the spec. Unfortunately our unsafe SpiderMonkey bindings keep getting in the way. |
| /// https://drafts.css-houdini.org/css-paint-api/#paint-definitions | ||
| paint_definitions: DOMRefCell<HashMap<Atom, PaintDefinition>>, | ||
| /// https://drafts.css-houdini.org/css-paint-api/#paint-class-instances | ||
| paint_class_instances: DOMRefCell<HashMap<Atom, Heap<JSVal>>>, |
This comment has been minimized.
This comment has been minimized.
| /// A paint definition | ||
| /// https://drafts.css-houdini.org/css-paint-api/#paint-definition | ||
| #[derive(Clone, JSTraceable, HeapSizeOf)] | ||
| struct PaintDefinition { |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
| class_constructor: Heap<JSVal>, | ||
| paint_function: Heap<JSVal>, | ||
| #[ignore_heap_size_of = "Rc"] | ||
| constructor_valid_flag: Rc<Cell<bool>>, |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
asajeffrey
Jun 16, 2017
Author
Member
It was because I was cloning the definition. I'm not now, so the Rc is gone.
| debug!("Getting alpha."); | ||
| let alpha: bool = | ||
| unsafe { get_property(cx, paint_obj.handle(), "alpha", ()) }? | ||
| .unwrap_or_default(); |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
| // Step 19. | ||
| let definition = PaintDefinition { | ||
| class_constructor: Heap::new(ObjectValue(paint_obj.get())), | ||
| paint_function: Heap::new(paint_function), |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
| // TODO: Steps 1-2.1. | ||
| // Step 3. | ||
| let definition = match self.paint_definitions.borrow().get(&name) { | ||
| Some(defn) => defn.clone(), |
This comment has been minimized.
This comment has been minimized.
jdm
Jun 16, 2017
Member
This is scary when a PaintDefinition contains Heap values. We need to find something else to do here.
This comment has been minimized.
This comment has been minimized.
asajeffrey
Jun 16, 2017
Author
Member
OK, I rewrote this to copy out the values needed (into rooted locations) rather than clone the paint definition.
| return; | ||
| } | ||
| // Step 5.4 | ||
| entry.insert(Heap::new(paint_instance.get())); |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
| // TODO: Step 10 | ||
| // Steps 11-12 | ||
| debug!("Invoking paint function {}.", name); | ||
| let args = unsafe { HandleValueArray::from_rooted_slice(&[ |
This comment has been minimized.
This comment has been minimized.
jdm
Jun 16, 2017
Member
Unfortunately from_rooted_slice is easy to misuse. Please create a RootedVec (rooted_vec!) containing these values and pass its slice as the argument here.
This comment has been minimized.
This comment has been minimized.
asajeffrey
Jun 16, 2017
Author
Member
Well I tried, but I hit:
--> /home/ajeffrey/github/asajeffrey/servo/components/script/dom/macros.rs:549:25
|
549 | let mut $name = $crate::dom::bindings::trace::RootedVec::new(&mut root);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `dom::bindings::trace::JSTraceable` is not implemented for `js::jsapi::Value`
|
::: /home/ajeffrey/github/asajeffrey/servo/components/script/dom/paintworkletglobalscope.rs
|
171 | rooted_vec!(let mut args);
| -------------------------- in this macro invocation
|
= note: required by `<dom::bindings::trace::RootedVec<'a, T>>::new`
The problem being that I need to construct a RootedVec<JSVal>.
There's a similar type error with rooted!(in(cx) let args = ....):
error[E0277]: the trait bound `js::jsapi::HandleValueArray: js::rust::RootKind` is not satisfied
--> /home/ajeffrey/github/asajeffrey/servo/components/script/dom/paintworkletglobalscope.rs:171:9
|
171 | / rooted!(in(cx) let args = unsafe { HandleValueArray::from_rooted_slice(&[
172 | | ObjectValue(rendering_context.reflector().get_jsobject().get()),
173 | | ObjectValue(paint_size.reflector().get_jsobject().get()),
174 | | ]) });
| |______________^ the trait `js::rust::RootKind` is not implemented for `js::jsapi::HandleValueArray`
|
= note: required by `<js::rust::RootedGuard<'a, T>>::new`
= note: this error originates in a macro outside of the current crate
I'm not sure this is needed anyway, all the objects in the array are already rooted, the only thing is the array itself, but I believe Call manages the lifetime of the arguments object?
This comment has been minimized.
This comment has been minimized.
jdm
Jun 20, 2017
Member
HandleValueArray is a type meaning "this is a pointer to an array of values that are rooted." This is literally storing a pointer to an array that goes out of scope immediately after returning.
This comment has been minimized.
This comment has been minimized.
jdm
Jun 29, 2017
Member
I am ok with the current code as long as we store the slice in a binding that outlives the call to from_rooted_slice, otherwise we are storing a pointer to a temporary stack value that could be overwritten before we actually reach Call.
This comment has been minimized.
This comment has been minimized.
|
OK, I fought the JS bindings, and I think it's in better shape now! |
| /// https://drafts.css-houdini.org/css-paint-api/#paint-definitions | ||
| paint_definitions: DOMRefCell<HashMap<Atom, PaintDefinition>>, | ||
| /// https://drafts.css-houdini.org/css-paint-api/#paint-class-instances | ||
| paint_class_instances: DOMRefCell<HashMap<Atom, Heap<JSVal>>>, |
This comment has been minimized.
This comment has been minimized.
| // TODO: Steps 1-2.1. | ||
| // Step 3. | ||
| let definition = match self.paint_definitions.borrow().get(&name) { | ||
| Some(defn) => defn.clone(), |
This comment has been minimized.
This comment has been minimized.
asajeffrey
Jun 16, 2017
Author
Member
OK, I rewrote this to copy out the values needed (into rooted locations) rather than clone the paint definition.
| return; | ||
| } | ||
| // Step 5.4 | ||
| entry.insert(Heap::new(paint_instance.get())); |
This comment has been minimized.
This comment has been minimized.
| // TODO: Step 10 | ||
| // Steps 11-12 | ||
| debug!("Invoking paint function {}.", name); | ||
| let args = unsafe { HandleValueArray::from_rooted_slice(&[ |
This comment has been minimized.
This comment has been minimized.
asajeffrey
Jun 16, 2017
Author
Member
Well I tried, but I hit:
--> /home/ajeffrey/github/asajeffrey/servo/components/script/dom/macros.rs:549:25
|
549 | let mut $name = $crate::dom::bindings::trace::RootedVec::new(&mut root);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `dom::bindings::trace::JSTraceable` is not implemented for `js::jsapi::Value`
|
::: /home/ajeffrey/github/asajeffrey/servo/components/script/dom/paintworkletglobalscope.rs
|
171 | rooted_vec!(let mut args);
| -------------------------- in this macro invocation
|
= note: required by `<dom::bindings::trace::RootedVec<'a, T>>::new`
The problem being that I need to construct a RootedVec<JSVal>.
There's a similar type error with rooted!(in(cx) let args = ....):
error[E0277]: the trait bound `js::jsapi::HandleValueArray: js::rust::RootKind` is not satisfied
--> /home/ajeffrey/github/asajeffrey/servo/components/script/dom/paintworkletglobalscope.rs:171:9
|
171 | / rooted!(in(cx) let args = unsafe { HandleValueArray::from_rooted_slice(&[
172 | | ObjectValue(rendering_context.reflector().get_jsobject().get()),
173 | | ObjectValue(paint_size.reflector().get_jsobject().get()),
174 | | ]) });
| |______________^ the trait `js::rust::RootKind` is not implemented for `js::jsapi::HandleValueArray`
|
= note: required by `<js::rust::RootedGuard<'a, T>>::new`
= note: this error originates in a macro outside of the current crate
I'm not sure this is needed anyway, all the objects in the array are already rooted, the only thing is the array itself, but I believe Call manages the lifetime of the arguments object?
| debug!("Getting alpha."); | ||
| let alpha: bool = | ||
| unsafe { get_property(cx, paint_obj.handle(), "alpha", ()) }? | ||
| .unwrap_or_default(); |
This comment has been minimized.
This comment has been minimized.
| // Step 19. | ||
| let definition = PaintDefinition { | ||
| class_constructor: Heap::new(ObjectValue(paint_obj.get())), | ||
| paint_function: Heap::new(paint_function), |
This comment has been minimized.
This comment has been minimized.
| /// A paint definition | ||
| /// https://drafts.css-houdini.org/css-paint-api/#paint-definition | ||
| #[derive(Clone, JSTraceable, HeapSizeOf)] | ||
| struct PaintDefinition { |
This comment has been minimized.
This comment has been minimized.
| class_constructor: Heap<JSVal>, | ||
| paint_function: Heap<JSVal>, | ||
| #[ignore_heap_size_of = "Rc"] | ||
| constructor_valid_flag: Rc<Cell<bool>>, |
This comment has been minimized.
This comment has been minimized.
asajeffrey
Jun 16, 2017
Author
Member
It was because I was cloning the definition. I'm not now, so the Rc is gone.
| Entry::Vacant(entry) => { | ||
| Some(definition) => { | ||
| class_constructor.set(definition.class_constructor.get()); | ||
| paint_function.set(definition.paint_function.get()); |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
| @@ -208,6 +215,7 @@ impl PaintWorkletGlobalScopeMethods for PaintWorkletGlobalScope { | |||
| let name = Atom::from(name); | |||
| let cx = self.worklet_global.get_cx(); | |||
| rooted!(in(cx) let paint_obj = paint_ctor.callback_holder().get()); | |||
| let paint_val = ObjectValue(paint_obj.get()); | |||
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
asajeffrey
Jun 21, 2017
Author
Member
OK, I rooted it, somewhat unnecessarily because the line above roots it too, but better safe than sorry.
|
|
||
| impl PaintDefinition { | ||
| fn new(class_constructor: JSVal, | ||
| paint_function: JSVal, |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
| paint_function: JSVal, | ||
| input_properties: Vec<DOMString>, | ||
| alpha: bool) | ||
| -> Box<PaintDefinition> |
This comment has been minimized.
This comment has been minimized.
jdm
Jun 20, 2017
Member
I am actually quite unnerved that this does not trigger our must_root compiler check :(
This comment has been minimized.
This comment has been minimized.
| registerPaint("propertiesThrows", class { | ||
| static get inputProperties() { throw new TypeError(); } | ||
| paint(ctx, size) { } | ||
| }); |
This comment has been minimized.
This comment has been minimized.
| // TODO: Step 10 | ||
| // Steps 11-12 | ||
| debug!("Invoking paint function {}.", name); | ||
| let args = unsafe { HandleValueArray::from_rooted_slice(&[ |
This comment has been minimized.
This comment has been minimized.
jdm
Jun 20, 2017
Member
HandleValueArray is a type meaning "this is a pointer to an array of values that are rooted." This is literally storing a pointer to an array that goes out of scope immediately after returning.
|
Some more fighting with GC rooting. |
| Entry::Vacant(entry) => { | ||
| Some(definition) => { | ||
| class_constructor.set(definition.class_constructor.get()); | ||
| paint_function.set(definition.paint_function.get()); |
This comment has been minimized.
This comment has been minimized.
| @@ -208,6 +215,7 @@ impl PaintWorkletGlobalScopeMethods for PaintWorkletGlobalScope { | |||
| let name = Atom::from(name); | |||
| let cx = self.worklet_global.get_cx(); | |||
| rooted!(in(cx) let paint_obj = paint_ctor.callback_holder().get()); | |||
| let paint_val = ObjectValue(paint_obj.get()); | |||
This comment has been minimized.
This comment has been minimized.
asajeffrey
Jun 21, 2017
Author
Member
OK, I rooted it, somewhat unnecessarily because the line above roots it too, but better safe than sorry.
|
|
||
| impl PaintDefinition { | ||
| fn new(class_constructor: JSVal, | ||
| paint_function: JSVal, |
This comment has been minimized.
This comment has been minimized.
| paint_function: JSVal, | ||
| input_properties: Vec<DOMString>, | ||
| alpha: bool) | ||
| -> Box<PaintDefinition> |
This comment has been minimized.
This comment has been minimized.
|
|
db5165a
to
d89851c
|
Can I r=you? |
| // TODO: Step 10 | ||
| // Steps 11-12 | ||
| debug!("Invoking paint function {}.", name); | ||
| let args = unsafe { HandleValueArray::from_rooted_slice(&[ |
This comment has been minimized.
This comment has been minimized.
9c9fb82
to
3db4761
|
Squashed. @bors-servo r=jdm IRL. |
|
|
|
|
|
@bors-servo: treeclosed- |
…t-scripts, r=jdm Implemented paint worklets invoking worklet scripts. <!-- Please describe your changes on the following line: --> Implemented the "invoke a paint callback" functionality of paint worklets (https://drafts.css-houdini.org/css-paint-api/#invoke-a-paint-callback). This PR does not implement the 2D rendering context, and just generates a placeholder image. --- <!-- 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 do not require tests because we can't write reftests until we have 2D rendering contexts implemented. <!-- 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/17239) <!-- Reviewable:end -->
|
|
…=jdm Implement paint worklet properties <!-- Please describe your changes on the following line: --> This is the final PR to get basic paint worklet support. It adds support for paint worklet properties (https://drafts.css-houdini.org/css-paint-api/#paint-definition-input-properties). When a paint worklet is registered, it specifies a list of CSS properties, and is provided with their computed values when it is invoked. This is a dependent PR: * "Implemented paint worklets invoking worklet scripts" is #17239. * "Implemented paint worklets rendering contexts" is #17326. There should be tests added for this, hopefully the existing wpt houdini tests. --- <!-- 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 #16839 - [x] There are tests for these changes <!-- 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/17364) <!-- Reviewable:end -->
…=jdm Implement paint worklet properties <!-- Please describe your changes on the following line: --> This is the final PR to get basic paint worklet support. It adds support for paint worklet properties (https://drafts.css-houdini.org/css-paint-api/#paint-definition-input-properties). When a paint worklet is registered, it specifies a list of CSS properties, and is provided with their computed values when it is invoked. This is a dependent PR: * "Implemented paint worklets invoking worklet scripts" is #17239. * "Implemented paint worklets rendering contexts" is #17326. There should be tests added for this, hopefully the existing wpt houdini tests. --- <!-- 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 #16839 - [x] There are tests for these changes <!-- 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/17364) <!-- Reviewable:end -->
Fixed scaling artefacts in paint worklets caused by zoom and hidpi <!-- Please describe your changes on the following line: --> This PR renders paint worklet canvases at the device pixel resolution, rather than the CSS pixel resolution. It's a dependent PR, building on #17239, #17326 and #17364. --- <!-- 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 #17454 - [X] These changes do not require tests because we don't run reftests with zoom enabled <!-- 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/17499) <!-- Reviewable:end -->
Fixed scaling artefacts in paint worklets caused by zoom and hidpi <!-- Please describe your changes on the following line: --> This PR renders paint worklet canvases at the device pixel resolution, rather than the CSS pixel resolution. It's a dependent PR, building on #17239, #17326 and #17364. --- <!-- 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 #17454 - [X] These changes do not require tests because we don't run reftests with zoom enabled <!-- 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/17499) <!-- Reviewable:end -->
asajeffrey commentedJun 8, 2017
•
edited by larsbergstrom
Implemented the "invoke a paint callback" functionality of paint worklets (https://drafts.css-houdini.org/css-paint-api/#invoke-a-paint-callback).
This PR does not implement the 2D rendering context, and just generates a placeholder image.
./mach build -ddoes not report any errors./mach test-tidydoes not report any errorsThis change is