[dev-servo] Servo embedding story & killing mozbrowser
We want to be able to embed Servo in applications. We want to build a functional Servo based browser. In Rust, in JavaScript, or any language. The 2 ways to do so today is either to use CEF, a C++ embedding API (with multiple bindings) designed for Webkit/Blink, or use the mozbrowser API which requires the user to use HTML and JavaScript, and which tend to pollute the Servo code base and the web standards. I would like to start a discussion about a possible better embedding story, and also about getting rid of the mozbrowser code. We would like a Servo-specific embedding API, designed in a way that: - it is optimised for Servo (we don't want to be limited by the webkit or gecko legacy) - it is Rust-first. Then bindings for JavaScript and any other popular language - it doesn't bend existing web standards and pollute the code base - it doesn't make assumption about how a web browser (the application) is supposed to be working. A next-gen browser might want to go beyond the regular urlbar+tabstrip design - it delegates as much as possible to the embedder. Separation of concerns: Servo renders web content. The rest is up to the embedder - give deeper access to the engine, especially to the compositor and events management I have outlined a proposal here: https://github.com/paulrouget/servo-embedding-api/ It's a draft. It's high level. It's not valid Rust code.The goal is to outline a future servo_traits API. The README includes some notes about the rational. There are a lot of comments inside the code itself. I have also outlined a possible way of implementing a JS API as a third-party project: https://github.com/paulrouget/servo-embedding-api/blob/master/JS_API.md The major short term changes necessary in Servo I foresee are: - move `fn main()` out of Servo (basically make Servo a library) - support multiple frame tree, support multiple compositors and WR instances - support multiple root frame in the constellation - support creation of a new compositor and a new browser at anytime - change the way web content is clipped (see browserview.rs) - delegate events routing to the embedder (there's probably a lot of things I haven't considered. please comment) The first milestone would be to rebuilt the current Glutin port but with `fn main()` within /ports/, without any reference to glutin within /components/, with multiple window support, and only relying on a servo_traits API. A second milestone would be to build a JavaScript binding, a bit like the Electron webview works, as a third-party project (no impact on the servo code base, only use the servo_traits API), and remove all the mozbrowser code from Servo, while keeping browserhtml functional. ~ Please take a look at https://github.com/paulrouget/servo-embedding-api We would need now: - to agree that we want a servo-specific rust embedding API - to agree on a minimal API that we could start working on, which I hope will be a subset of what I'm describing here: https://github.com/paulrouget/servo-embedding-api Then: - I will describe precisely the next milestones (glutin/miniservo port, then mozbrowser killing plan) - I will file relevant bugs. The same way I did for the initial BrowserHTML developer preview Thanks, -- Paul Rouget ___ dev-servo mailing list dev-servo@lists.mozilla.org https://lists.mozilla.org/listinfo/dev-servo
[dev-servo] CSSOM ownership woes
This is basically the gist of a discussion that I and xidorn were having, pertaining to CSSOM in both Servo and Stylo. We mostly wrapped it up, but there are loose ends and I'm not sure if the choices made are correct. In CSSOM, you basically have a StyleSheetList holding many StyleSheets holding a CSSRuleList holding many CSSRules. You can index/insert/delete on the lists and CSSRule can be manipulated in a bunch of ways. One invariant that's not *exactly* specified by the spec (but is sort of hinted at, and implemented by browsers) is that these lists should yield the same underlying JS object when you access the same conceptual rule/stylesheet in a list (even if the rest of the list was mutated). So the DOM indexing methods cannot just create rule/stylesheet JS objects on the fly, they need to cache them somehow and update them when the list is updated. Servo currently has a style tree (stylesheets->rulelist->rules->other rules and rule lists) in style::Stylesheet[1], and this is shared with the DOM via Arcs. As I understand it, Gecko, on the other hand, just uses the CSSOM DOM tree and has no "style tree" otherwise. Reading rules in Gecko requires traversing through CSSOM objects. This is a straightforward solution to the same-object restriction; if your style tree is made up of these objects in the first place there's nothing to worry about. Servo can't use this solution. Trying to thread style through the DOM will mean merging the style and script crates, and it will be quite complicated to make Servo's style system generic over CSSOM implementations for stylo to work. A possible solution is to have a opaquish DOM backpointer to corresponding rule objects in the style tree and have it call some update function to update the DOM when mutating. This isn't a great solution IMO. The one that we seem to prefer is maintaining the style tree and the CSSOM tree in parallel, with references from the CSSOM tree to the style tree, but not vice versa. Only the DOM mutates the style tree. This could possible be enforced by wrapping all interior mutability in the style tree with a type that requires a zero-sized token to be passed in to the borrow_mut/write method; a token which can't be created normally but can be obtained via a method on dom::Reflectable (within arms reach for most DOM code). Stylo code can FFI call into functions using a similar mechanism. So far this seems good (though very open to other ideas or suggestions for improvement). However, in this model the DOM still needs to hold Arcs to the corresponding style system objects. In some cases, this is straightforward. dom::StyleSheet holds an arc to a style::Stylesheet. dom::CSSRule contains a style::CSSRule (which is a cheaply cloneable enum of Arcs). In the case of CSSRuleList, we have a bit of an issue. There's no corresponding arc'd style:: type for CSSRuleList. There's just `Vec`, which is used in Stylesheet[1], MediaRule[2], and @supports rules (not supported in servo yet). Now, we could just put the Vec in an Arc. I'm not sure if we want to with the extra indirection, but it's a simple solution. An alternative is to recognize that the `Vec` is always going to be stored within larger Arc'd objects, and just use those, by storing an enum RuleListOwner { Sheet(Arc), Media(Arc), // .. } This is great for the Rust code -- easy to abstract over and no extra perf cost. However, this can't be easily passed over to C++ for stylo. There's no way to write a corresponding C++ type that takes up the same space/alignment as a Rust enum. We could hardcode the size and have sizeof assertions in the tests, but that may not solve alignment issues, especially with the unspecified Rust ABI. We could also store an explicit tag/pointer pair which we have unsafe wrappers for on the Rust side. Ick. Personally I think just sticking the vec into an Arc is fine and won't impact us much. But I don't know. Overall, I think we need to map out the ownership graph of CSSOM in both Servo and Stylo before starting work on it. [1]: https://doc.servo.org/style/stylesheets/struct.Stylesheet.html [2]: https://doc.servo.org/style/stylesheets/struct.MediaRule.html Thanks, -Manish Goregaokar ___ dev-servo mailing list dev-servo@lists.mozilla.org https://lists.mozilla.org/listinfo/dev-servo
Re: [dev-servo] CSSOM ownership woes
On Fri, Nov 11, 2016 at 03:22:16AM -0800, Manish Goregaokar wrote: > A possible solution is to have a opaquish DOM backpointer to > corresponding rule objects in the style tree and have it call some > update function to update the DOM when mutating. This isn't a great > solution IMO. Note that this is already what is done for a Node's computed style (and the rest of the style and layout data) in Servo, and it's already causing some problems, like unnecessary extra reflows and overhead to check a node's computed value for a given property using GetComputedStyle. As a side note, given we're thinking in how to structure these crates, it would be nice to find a solution for this too, since the extra reflows aren't cheap, and a layout thread query in general seems a lot of overhead for something that should be really cheap. That's probably a slightly harder problem though, because it involves knowing layout data structures (as in: Servo's layout crate). I've thought about enforcing the first member of the heap-allocated node data to be a ComputedStyle, but I sincerely would prefer to avoid as many transmutes as possible, one of them is too many... > The one that we seem to prefer is maintaining the style tree and the > CSSOM tree in parallel, with references from the CSSOM tree to the > style tree, but not vice versa. Only the DOM mutates the style tree. This seems like the most reasonable approach to me too. Merging style and DOM will not only be probably a blocker for Stylo, but also make the style system much more unsafe (having lots more of JS reflectors in random threads). > This could possible be enforced by wrapping all interior mutability in > the style tree with a type that requires a zero-sized token to be > passed in to the borrow_mut/write method; a token which can't be > created normally but can be obtained via a method on dom::Reflectable > (within arms reach for most DOM code). Stylo code can FFI call into > functions using a similar mechanism. Or probably asserting that we're not in a Servo Layout thread when we `borrow_mut`? Not perfect, but... Also, note that the layout thread right now is the one that constructs and manages the Stylist, and that stylesheet web fonts are processed right now async with script (see the AddStylesheet layout message), and it reads the font face rules, so potentially you want a stronger synchronization there. > Now, we could just put the Vec in an Arc. I'm not sure if we want to > with the extra indirection, but it's a simple solution. An alternative > is to recognize that the `Vec` is always going to be stored > within larger Arc'd objects, and just use those, by storing an > > enum RuleListOwner { > Sheet(Arc), > Media(Arc), > // .. > } > > This is great for the Rust code -- easy to abstract over and no extra perf > cost. Can you move the same CSSRuleList to a different owner? If you can, this wouldn't work, right? > Personally I think just sticking the vec into an Arc is fine and won't > impact us much. But I don't know. Agreed, the extra Arc, over all given where it's used doesn't seem such a show-stopper to me. We have Arc> all over the place, and I don't think this two places are hotter than the ones on top of, let's say, property declaration blocks. I assume this will also need it's own RwLock in order to mutate the list, right? If that's the case, probably something like Arc>, where CSSRuleList(Vec) is probably nicer. -- Emilio signature.asc Description: PGP signature ___ dev-servo mailing list dev-servo@lists.mozilla.org https://lists.mozilla.org/listinfo/dev-servo
[dev-servo] Quantum productivity obstacles
Hi all, As more people get involved in Quantum engineering efforts, tooling and automation deficits have a greater cumulative impact. Engineering Productivity is involved in some Quantum-related work involving the build system and version control/autoland, but there are likely other ways we could help. If there's a productivity obstacle involving any of the domains we work in (build system, version control, Treeherder, sheriffing, continuous integration, perf testing and others), please document that in this shared Google doc so we can prioritize and work towards fixing them. https://docs.google.com/document/d/1N2d0nrpEIPUr002piERNPqmjwpWLN4z5nxDWWCjaZDU/edit?usp=sharing Thanks, Jonathan ___ dev-servo mailing list dev-servo@lists.mozilla.org https://lists.mozilla.org/listinfo/dev-servo
Re: [dev-servo] Servo embedding story & killing mozbrowser
On Friday, November 11, 2016 at 2:05:28 AM UTC-8, Paul Rouget wrote: > We would like a Servo-specific embedding API, designed in a way that: > - it is optimised for Servo (we don't want to be limited by the webkit > or gecko legacy) For Quantum, I've thinking about a new embedding API, and there's a use case for embedding both Quantum and Blink (as well as both Quantum and Servo), so I'd like to harmonize Quantum APIs with Blink (and Servo) equivalents to the extent possible. I'm curious to understand more about the WebKit/Gecko limitations you're trying to avoid. > - it is Rust-first. Then bindings for JavaScript and any other popular > language That makes sense, given that Servo is implemented in Rust. I'm not familiar with the state of Rust to C++ bindings, but presumably that's the easy part of creating a C++ binding that looks like Quantum's or Blink's API. The harder part is harmonizing the API concepts. > - it doesn't bend existing web standards and pollute the code base By this do you mean primarily mozbrowser, or are there other issues with existing embedding APIs that you're looking to avoid? > - it doesn't make assumption about how a web browser (the application) > is supposed to be working. A next-gen browser might want to go beyond > the regular urlbar+tabstrip design > - it delegates as much as possible to the embedder. Separation of > concerns: Servo renders web content. The rest is up to the embedder Right, this makes perfect sense, especially since there are a variety of use cases for embedding a rendering engine, and they aren't all browsers. There may be some complexity to determining which specific parts of the browser belong in the engine versus the embedder, but this is a good guiding principle. It'll also be easier to pull parts into the engine later than to pull them out of it. > - give deeper access to the engine, especially to the compositor and > events management I'm not familiar with the use cases for this, but from the proposal, it sounds like you want to do some interesting experiments on a browser interface. Seems reasonable, although I wonder if there's an abstraction for the common cases of rendering some content in a rectangle. > I have also outlined a possible way of implementing a JS API as a > third-party project: > https://github.com/paulrouget/servo-embedding-api/blob/master/JS_API.md Would you be interested in using SpiderNode as this runtime? We used in Positron to run Electron's Node modules and are now experimenting with using in Firefox to enable WebExtensions to spawn Node child processes. Using it would give you the Node APIs implemented on top of libuv, plus third-party APIs available via NPM. -myk ___ dev-servo mailing list dev-servo@lists.mozilla.org https://lists.mozilla.org/listinfo/dev-servo
Re: [dev-servo] CSSOM ownership woes
> Or probably asserting that we're not in a Servo Layout thread when we > `borrow_mut`? Not perfect, but... Extra runtime check and I'm not fond of this solution in general, since it's runtime. The token thing is a pure compile time option. Making it !Send+!Sync means that it's hard to make it accidentally end up in the layout thread. > Can you move the same CSSRuleList to a different owner? If you can, this > wouldn't work, right? I don't think you can. e this will also need it's own RwLock in order to mutate the > list, right? If that's the case, probably something like > Arc>, where CSSRuleList(Vec) is probably > nicer. Yep. I'm implementing an immutable cssom first, and will revisit the exact positions of the rwlocks later. ___ dev-servo mailing list dev-servo@lists.mozilla.org https://lists.mozilla.org/listinfo/dev-servo