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

selectors::Element without borrowed types #22972

Closed
RazrFalcon opened this issue Mar 5, 2019 · 20 comments
Closed

selectors::Element without borrowed types #22972

RazrFalcon opened this issue Mar 5, 2019 · 20 comments

Comments

@RazrFalcon
Copy link
Contributor

Currently, selectors::Element defines two methods that require borrowed data: local_name and namespace.

The problem is that a usual rc-tree unable to produce a reference that will live long enough. The kuchiki crate uses the NodeDataRef hack that involves unsafe, which is unacceptable in my case.

Can those methods be replaced with something like has_local_name and has_namespace?

@SimonSapin

@SimonSapin
Copy link
Member

I think NodeDataRef uses the same technique as https://crates.io/crates/owning_ref. Would that be more acceptable?

@emilio, any thoughts on this? I think originally we had accessors rather than boolean testing in order to support hash maps indexed by local named, ID, class, etc. But those have since moved out of the selectors crate to Servo’s and Firefox style crate.

@RazrFalcon
Copy link
Contributor Author

RazrFalcon commented Mar 5, 2019

Should I use owning_ref for Node itself or for BorrowedLocalName? Because it doesn't work in both cases (kinda).

error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
   --> src/parser/css2.rs:131:1
    |
131 | impl selectors::Element for OwningRef<Node, NodeData> {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
    |
    = note: the impl does not reference only types defined in this crate
    = note: define and implement a trait or new type instead

@SimonSapin
Copy link
Member

Oh sorry I misremembered. Element::local_name returns &Something (because of lack of generic associated types), so OwningRef likely won’t help there.

Is the problem that you have entire nodes inside a bug RefCell, which needs to stay borrowed while the local name is accessed? In that case what Kuchiki does different that’s relevant is not NodeDataRef, but rather having some components of nodes in their individual smaller Cell or RefCell. This does not include the element’s name, with the trade-off that the only way to change an element’s name is to create a new one and move the other data and child nodes.

@RazrFalcon
Copy link
Contributor Author

Yes, the usual Rc<RefCell<T>> mantra based on rctree. So for my use case has_* methods are preferred.

And since there are no other CSS parsers, I have to find at least some solution. So any suggestions are welcome.

@emilio
Copy link
Member

emilio commented Mar 5, 2019

has_local_name seems fine, but you need something else to deal with nth-of-type (has_same_local_name_as?). It seems a bit unfortunate though.

@SimonSapin
Copy link
Member

As far as I can tell the only three possible resolutions here are:

  • Replace local_name with has_local_name and same_local_name_as. I agree feels awkward, but it might the only way that doesn’t involve distruptive changes to other code or unknown time delays.

  • Restructure rctree to remove the One Big RefCell. Instead, make it more like Kuchiki and have each link to other nodes in individual Cells (which does support !Copy types since 1.17, but some extension traits make that easier to use). Then, the user of rctree can choose to have only parts of their payload (the T in Node<T>) be in smaller Cells or RefCells. In particular, if the local name is not in a cell, the implementation of selectors::Element::local_name can safely return a &LocalName reference.

  • Wait until Generic Associated Types are stable in the language, and have Element::local_name(&'a self) return Self::LocalName<'a> instead of &'a Self::LocalName. That way, your associated type can be for example a std::cell::Ref value obtained with Ref::map, or an owned values that was cloned out of the node. I think this is the “best” solution, but unfortunately GATs likely won’t be ready for months or more.

@RazrFalcon
Copy link
Contributor Author

RazrFalcon commented Apr 9, 2019

Hi. I've tried the second method and it made API a bit nicer, since I don't need Ref and RefMut this way, but in the end I have to wrap all my data in RefCells, which is horrible and no go for me. Am I missing something?

Here is the struct that I put in the rctree. And all fields must be mutable, so I have to wrap all of them in RefCell.

@SimonSapin
Copy link
Member

I don’t think you’re missing anything. This particular case just hadn’t come up before, element name and namespace are immutable in the (web’s) DOM.

This leave GATs, which will likely take longer than when I assume you would like to use selectors in your project, or has_local_name/same_local_name_as. @emilio How would you feel about migrating Stylo to that API?

@RazrFalcon
Copy link
Contributor Author

element name and namespace are immutable in the (web’s) DOM.

Oh, I see.

Yes, I want to use cssparser/selectors in svgdom->resvg.

@emilio
Copy link
Member

emilio commented Apr 10, 2019

Do you really need a mutable tag / namespace?

I'm ok changing the style system to such an API, though I find it still slightly unfortunate :)

@RazrFalcon
Copy link
Contributor Author

The problem is that I'm using rctree, which doesn't support this at all. So I have to rewrite rctree and svgdom completely to be able to support this.

@RazrFalcon
Copy link
Contributor Author

Any updates?

@emilio
Copy link
Member

emilio commented May 25, 2019

Patches welcome I guess? I'm happy to review such a change.

@RazrFalcon
Copy link
Contributor Author

I hope that I will be able at least build servo from sources...

@RazrFalcon
Copy link
Contributor Author

RazrFalcon commented May 26, 2019

As expected:

error: failed to run custom build command for `gstreamer-webrtc-sys v0.7.0`
process didn't exit successfully: `/media/data/servo/target/debug/build/gstreamer-webrtc-sys-0ea001806f557833/build-script-build` (exit code: 1)
--- stderr
`"pkg-config" "--libs" "--cflags" "gstreamer-webrtc-1.0 >= 1.14"` did not exit successfully: exit code: 1
--- stderr
Package gstreamer-webrtc-1.0 was not found in the pkg-config search path.
Perhaps you should add the directory containing `gstreamer-webrtc-1.0.pc'
to the PKG_CONFIG_PATH environment variable
No package 'gstreamer-webrtc-1.0' found

Looks like gstreamer-webrtc isn't available on gentoo at all.

#23050

UPD: it was my mistake. I was able to build it on gentoo just fine.

@jdm
Copy link
Member

jdm commented May 26, 2019

You can probably use ./mach build -p style to work around the gstreamer build issue for the time being.

@RazrFalcon
Copy link
Contributor Author

@jdm Thanks! I was able to build it now.

@RazrFalcon
Copy link
Contributor Author

RazrFalcon commented May 26, 2019

Here is my attempt: #23463

Mostly failed...

@SimonSapin
Copy link
Member

@RazrFalcon Does this new API work for your use case? https://doc.servo.org/selectors/trait.Element.html#tymethod.has_local_name

I can publish to crates.io. Is there anything else to tweak before that?

@RazrFalcon
Copy link
Contributor Author

Yep, I've already tested it and it works perfectly. Thanks.

netbsd-srcmastr pushed a commit to NetBSD/pkgsrc that referenced this issue Mar 10, 2020
Version 2.48.0

- The following is a summary of changes between 2.46.x and 2.48.0.
  For full details, please see the 2.47.x release notes below.

- This release requires at least Rust 1.39.

- #379 - New API, rsvg_handle_set_stylesheet(), to set a CSS
  stylesheet independent of the SVG document.

- #510 - support opacity in patterns.

- Librsvg's XML parser now supports namespaces (xmlns), and is
  stricter than before about it.  Files may fail to parse if there are
  attributes or elements with namespace prefixes (e.g. foo:bar instead
  of plain bar), but without a corresponding namespace declaration
  (e.g. xmlns:foo="http://example.com/foo").

  This may happen especially with incorrectly-written SVGs that use
  xlink:href or xi:include attributes without the corresponding
  namespace declarations.  If you run into this, just add the
  following to your toplevel SVG element:

      <svg xmlns="http://www.w3.org/2000/svg"
           xmlns:xlink="http://www.w3.org/1999/xlink"
	   xmlns:xi="http://www.w3.org/2001/XInclude">
           ^^^^^^^^^ these ones

- Librsvg no longer depends on libcroco, and now does all CSS
  processing using Rust crates from Mozilla Servo.  As a result,
  librsvg can now handle much more complex CSS selectors than before.

- Link-time optimization (LTO) is disabled by default on release
  builds, as this increased build time too much.  Downstream
  distributors may want to turn it back on in the toplevel Cargo.toml.

- #515 (CVE-2019-20446) - Librsvg now has limits on the number of
  loaded XML elements, and the number of referenced elements within an
  SVG document.  This is to mitigate malicious SVGs which try to
  consume all memory, and those which try to consume an exponential
  amount of CPU time.

- Many bugfixes; please see the 2.47.x release notes below.

Version 2.47.4

- (#240) - Fix rsvg-convert's multipage PDF output when the zoom
  option is used (Sven Neumann).

- (#547) - Do not stop rendering if an <image> element references a
  nonexistent file.  This fixes a number of Open Clipart cases.

- (#558) - Compute the font-size cascade correctly when there are "em"
   #and "ex" units involved.

- Updated the man page for rsvg-convert (Sven Neumann).

Version 2.47.3

- #379 - New API, rsvg_handle_set_stylesheet(), to set a CSS
  stylesheet independent of the SVG document.

- #510 - support opacity in patterns (Sven Neumann).

- Move away from the Cairo transform type to our own (Paolo Borelli).

- Update the gtk-rs version.

Version 2.47.2

- Handling of the "result", "in", "in2" attributes in filter
  primitives is slightly stricter now, and spec compliant.  Their
  arguments must be of type CSS custom-ident, so "default", "inherit",
  "initial", and "unset" are disallowed.  Most SVGs should still work
  fine.

- #542 - Fix infinite loop when processing CSS sibling combinators.

- #408 - feImage filters no longer clip their output to integer
  coordinates.

- #504 - Documentation for the Rust crate (available at
  https://gnome.pages.gitlab.gnome.org/librsvg/doc/librsvg/) now has
  API usage examples.

- Debug logs from RSVG_LOG=1 should now be more legible and contain
  better information on invalid CSS.

- Remove link-time workarounds for Rust pre-1.35 (Kleis Auke Wolthuizen).

- Unify internal error types to share the CSS code with gnome-shell.

- Made handling of XML namespaces more spec-compliant.

- Lots of refactoring to start moving away from Cairo internals
  (Paolo Borelli).

Version 2.47.1

- Librsvg no longer depends on libcroco!  It now does all CSS
  processing using Rust crates from Mozilla Servo; these are also the
  crates that are in use in recent versions of Firefox.  As a result,
  librsvg can now handle much more complex CSS selectors than before.
  Fixes #79, #167, #237, #283, #336, #428, #441, #466, #525, #525
  (Paolo Borelli, Federico Mena).  Thanks to Evgeniy Reizner
  for fixing servo/servo#22972, which made
  it possible to use Servo's selectors crate.

- #524 - Panic when reading an invalid stylesheet URL in an XML
  processing instruction (Paolo Borelli)

- Lots of little improvements to the documentation.

- Link-time optimization (LTO) is disabled by default on release
  builds, as this increased build time too much.  Downstream
  distributors may want to turn it back on in the toplevel Cargo.toml.

- We now have the start of documentation on the library's internals at
  https://gnome.pages.gitlab.gnome.org/librsvg/doc/rsvg_internals/index.html
  This should be interest of newcomers to librsvg's source code.

Version 2.47.0

- Librsvg's XML parser now supports namespaces (xmlns), and is
  stricter than before about it.  Files may fail to parse if there are
  attributes or elements with namespace prefixes (e.g. foo:bar instead
  of plain bar), but without a corresponding namespace declaration
  (e.g. xmlns:foo="http://example.com/foo").

  This may happen especially with incorrectly-written SVGs that use
  xlink:href or xi:include attributes without the corresponding
  namespace declarations.  If you run into this, just add the
  following to your toplevel SVG element:

      <svg xmlns="http://www.w3.org/2000/svg"
           xmlns:xlink="http://www.w3.org/1999/xlink"
	   xmlns:xi="http://www.w3.org/2001/XInclude">
           ^^^^^^^^^ these ones

- Patterns and gradients reused across more than one element will only
  get resolved once now; this should make things marginally faster for
  patterns or gradients with fallbacks.

- #515 (CVE-2019-20446) - Librsvg now has limits on the number of
  loaded XML elements, and the number of referenced elements within an
  SVG document.  This is to mitigate malicious SVGs which try to
  consume all memory, and those which try to consume an exponential
  amount of CPU time.

- #521 - Compute geometries correctly if there is a viewBox attribute.

- #308 - Fix stack exhaustion with circular references in <use> elements.

- Consistently use the LGPL 2.1 wherever it is mentioned.

- Patterns and gradients reused across more than one element will only
  get resolved once now; this should make things marginally faster for
  patterns or gradients with fallbacks.

- #506 - Fix empty patterns which reference a fallback pattern with
  children.
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 a pull request may close this issue.

4 participants