-
Notifications
You must be signed in to change notification settings - Fork 85
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
Request: IterableNodes for Rc<VirtualNode> somehow #108
Comments
index.html just holds the script tag in the body now. We do a nasty hack in Percy to workaround the lack of an `Rc<VirtualNode>` embedding. See chinedufn/percy#108 We suffer with an O(n^2) virtual node embedding for now. It seems like with the current WASM work, we only spend 0.85ms in our Rust code! We have plenty of time to spare for actual GameBoy logic. Included here is an unused (for now) memory table debug interface that will eventually be hooked into the data and GUI.
Thanks so much for opening this issue! A big goal of the tools in the Percy family is to be useful to people who want to just use one or two tools to go do something else.. so this is such a great issue...! BackgroundOver time we want to make Percy's data structures more and more generic / trait based so that no matter if you're using Instead of just imagining that outright .. we're waiting for real use cases to emerge so that we can design against them.. So thanks for this real use case! Current data structuresSo right now the children are stored as percy/crates/virtual-node/src/lib.rs Line 74 in 792b4e4
Potential SolutionOff the top of my head I can't think of a reason that we couldn't instead have children be stored as Then you'd be able to use anything that can be referenced as a Side thoughtsWe eventually want ConclusionMy thinking here is that we can
percy/crates/virtual-node/src/lib.rs Line 377 in 792b4e4
If you're interested in taking a stab I'd be more than happy to type up some detailed notes for you on how to go about it, as well as answer any questions that you might have. Should you not be interested or not have the time - I'd be more than happy to take a look at this next time I'm diving into that library! Thanks so much for opening this issue! Let me know if you have a different implementation in mind than what I described. Open to other ideas! |
@chinedufn Thanks for the wonderful response! I'm newish to Rust, so I hadn't seen the I can't guarantee I'll have the time, but next week I can attempt to try this late at night after work one day. Would you mind writing up those notes? Is there more I should know besides just swapping in the AsRef and fixing compiler errors until it works? Thanks! |
Yeah it should boil down to just that - but if it doesn't just let me know! And no worries if you don't end up having time - I have this on my radar! Cheers - happy to answer any questions should you end up diving in! |
@chinedufn I started taking a look at this, and I just wanted to make sure I'm on the right track before I spend too much time down the compiler yelling rabbit hole:
See here for some of that work: |
@bkase looks about right. There's a performance "penalty" for the heap allocation - but I can't see this being a material issue in any reasonable situation when working in the DOM (knock on wood). In the future we'll want performance profiling around our virtual-dom ... but for now this looks totally fine! |
Also apologies for the delays in this thread .. I typically try to respond more quickly.. sorry and feel free to keep any questions coming! Looking smooth! |
No worries, thanks for the tips! |
@chinedufn I've run up against some borrow-checker issues: First onepub struct VElement {
/// The HTML tag, such as "div"
pub tag: String,
/// HTML attributes such as id, class, style, etc
pub attrs: HashMap<String, String>,
/// Events that will get added to your real DOM element via `.addEventListener`
pub events: Events,
/// The children of this `VirtualNode`. So a <div> <em></em> </div> structure would
/// have a parent div and one child, em.
pub children: Vec<Box<AsRef<VirtualNode>>>,
}
impl PartialEq for VElement {
fn eq(&self, other: &VElement) -> bool {
self.tag == other.tag
&& self.attrs == other.attrs
&& self.events == other.events
&& self
.children
.into_iter()
.zip(other.children.into_iter())
.all(|(x, y)| x.as_ref().as_ref().eq(y.as_ref().as_ref()))
}
} Apparently I'm moving Second one// needed for trait coherence reasons
struct AsRefVirtualNode(Box<AsRef<VirtualNode>>);
impl fmt::Debug for AsRefVirtualNode {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.0.as_ref().as_ref().fmt(f)
}
}
impl fmt::Debug for VElement {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let xs: Vec<AsRefVirtualNode> = self
.children
.into_iter()
.map(|x| AsRefVirtualNode(x))
.collect();
write!(
f,
"Element(<{}>, attrs: {:?}, children: {:?})",
self.tag, self.attrs, xs
)
}
} I don't really like making that wrapper struct, but I couldn't think of another way to get the Any help would be appreciated, thanks! Here's the branch I'm working on: |
From a quick glance it looks like I would try using Let me know if that helps! As for the wrapper struct - cool for now after things are working / PR'd I'd be happy to take a looksie at things like that and see what we can massage around! Feel free to keep asking questions here! Looking good! |
@chinedufn Thanks for the tip! I was able to finish the virtual-node crate switching to I've made more progress, the wrapper struct has come in handy; it's a nice way to get the PartialEq and Debug instances in other structs (like Patch). I'm at the point where I need to change the Thanks! |
Woohoo! This is awesome and is amazing groundwork for making the virtual dom implementation compatible with any other types (not just the ones we define). Which is groundwork for a future where making a component in XYZ framework would still make it compatible with components made using So, to run the html macro tests
Here's where we insert children: percy/crates/html-macro/src/parser/mod.rs Line 127 in 6462688
So I might try Let me know if that helps! |
Hey there, just wanted to let you know that I've become quite busy with other things and this PR ended up requiring a lot more changes than I was expecting, so I'd like to abandon this task. Please feel free to work off of my branch if it is helpful, and thanks for all your help! |
Awesome - when I get around to solving this problem I'll update this issue - thanks for all of your effort here - cheers!! |
Great project!
Background
I'm attempting to use parts of Percy (namely virtual-dom-rs) in a user interface that is driven using FRP signals (similar, but a bit different from https://cycle.js.org/ ). Using this library and
futures-signals
, I can get something that seems like it could work well.Essentially, I'm modeling components as functions of the form:
Because of the way the FRP signals work, I only get a reference to a
VirtualNode
in certain places and so I need to wrap the result in anRc
.Problem
Here is my issue:
VirtualNode
s own all their descendants and so there's no easy way for me to use theRc<VirtualNode>
as a descendant of some otherVirtualNode
tree.Request
It would be great if
VirtualNode
supported anO(1)
way to embed anRc<VirtualNode>
as a child (aka there's an instanceFrom<Rc<VirtualNode>>
forIterableNodes
).Potential Solution
For example: If the
VirtualNode
enum had a third variant such asIt would be very easy to implement an efficient
From<Rc<VirtualNodes>>
.Conclusion
Please let me know if you need any more information, or if there is some way for me to get an
O(1)
injection with the library as is. I have a workaround that is slow, but will at least unblock my development for now (see below), but not having a cheap way to embedRc<VirtualNode>
s will be a blocker for me soon.Thanks!
===
Hacky Workaround
For anyone who sees this and has my same problem before it's resolved, I've figured out a nasty hack that doesn't require forking Percy, but is
O(n)
per injection (it's basically an implementation of clone for VirtualNode):The text was updated successfully, but these errors were encountered: