Start using new rbx_dom_weak instance cloning methods (#62)

This commit is contained in:
Kenneth Loeffler 2023-07-08 02:14:04 -07:00 committed by GitHub
parent 9adf296539
commit 33be2ed716
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 21 additions and 97 deletions

12
Cargo.lock generated
View file

@ -1535,7 +1535,7 @@ dependencies = [
[[package]] [[package]]
name = "rbx_binary" name = "rbx_binary"
version = "0.7.0" version = "0.7.0"
source = "git+https://github.com/rojo-rbx/rbx-dom?rev=b6d255e0b5d96155f694ca224676b251059cf2de#b6d255e0b5d96155f694ca224676b251059cf2de" source = "git+https://github.com/rojo-rbx/rbx-dom?rev=e7a813d569c3f8a54be8a8873c33f8976c37b8b1#e7a813d569c3f8a54be8a8873c33f8976c37b8b1"
dependencies = [ dependencies = [
"log", "log",
"lz4", "lz4",
@ -1566,7 +1566,7 @@ dependencies = [
[[package]] [[package]]
name = "rbx_dom_weak" name = "rbx_dom_weak"
version = "2.4.0" version = "2.4.0"
source = "git+https://github.com/rojo-rbx/rbx-dom?rev=b6d255e0b5d96155f694ca224676b251059cf2de#b6d255e0b5d96155f694ca224676b251059cf2de" source = "git+https://github.com/rojo-rbx/rbx-dom?rev=e7a813d569c3f8a54be8a8873c33f8976c37b8b1#e7a813d569c3f8a54be8a8873c33f8976c37b8b1"
dependencies = [ dependencies = [
"rbx_types", "rbx_types",
"serde", "serde",
@ -1575,7 +1575,7 @@ dependencies = [
[[package]] [[package]]
name = "rbx_reflection" name = "rbx_reflection"
version = "4.2.0" version = "4.2.0"
source = "git+https://github.com/rojo-rbx/rbx-dom?rev=b6d255e0b5d96155f694ca224676b251059cf2de#b6d255e0b5d96155f694ca224676b251059cf2de" source = "git+https://github.com/rojo-rbx/rbx-dom?rev=e7a813d569c3f8a54be8a8873c33f8976c37b8b1#e7a813d569c3f8a54be8a8873c33f8976c37b8b1"
dependencies = [ dependencies = [
"rbx_types", "rbx_types",
"serde", "serde",
@ -1585,7 +1585,7 @@ dependencies = [
[[package]] [[package]]
name = "rbx_reflection_database" name = "rbx_reflection_database"
version = "0.2.6+roblox-572" version = "0.2.6+roblox-572"
source = "git+https://github.com/rojo-rbx/rbx-dom?rev=b6d255e0b5d96155f694ca224676b251059cf2de#b6d255e0b5d96155f694ca224676b251059cf2de" source = "git+https://github.com/rojo-rbx/rbx-dom?rev=e7a813d569c3f8a54be8a8873c33f8976c37b8b1#e7a813d569c3f8a54be8a8873c33f8976c37b8b1"
dependencies = [ dependencies = [
"lazy_static", "lazy_static",
"rbx_reflection", "rbx_reflection",
@ -1596,7 +1596,7 @@ dependencies = [
[[package]] [[package]]
name = "rbx_types" name = "rbx_types"
version = "1.5.0" version = "1.5.0"
source = "git+https://github.com/rojo-rbx/rbx-dom?rev=b6d255e0b5d96155f694ca224676b251059cf2de#b6d255e0b5d96155f694ca224676b251059cf2de" source = "git+https://github.com/rojo-rbx/rbx-dom?rev=e7a813d569c3f8a54be8a8873c33f8976c37b8b1#e7a813d569c3f8a54be8a8873c33f8976c37b8b1"
dependencies = [ dependencies = [
"base64 0.13.1", "base64 0.13.1",
"bitflags 1.3.2", "bitflags 1.3.2",
@ -1610,7 +1610,7 @@ dependencies = [
[[package]] [[package]]
name = "rbx_xml" name = "rbx_xml"
version = "0.13.0" version = "0.13.0"
source = "git+https://github.com/rojo-rbx/rbx-dom?rev=b6d255e0b5d96155f694ca224676b251059cf2de#b6d255e0b5d96155f694ca224676b251059cf2de" source = "git+https://github.com/rojo-rbx/rbx-dom?rev=e7a813d569c3f8a54be8a8873c33f8976c37b8b1#e7a813d569c3f8a54be8a8873c33f8976c37b8b1"
dependencies = [ dependencies = [
"base64 0.13.1", "base64 0.13.1",
"log", "log",

View file

@ -22,11 +22,11 @@ thiserror.workspace = true
glam = "0.24" glam = "0.24"
rand = "0.8" rand = "0.8"
rbx_binary = { git = "https://github.com/rojo-rbx/rbx-dom", rev = "b6d255e0b5d96155f694ca224676b251059cf2de" } rbx_binary = { git = "https://github.com/rojo-rbx/rbx-dom", rev = "e7a813d569c3f8a54be8a8873c33f8976c37b8b1" }
rbx_dom_weak = { git = "https://github.com/rojo-rbx/rbx-dom", rev = "b6d255e0b5d96155f694ca224676b251059cf2de" } rbx_dom_weak = { git = "https://github.com/rojo-rbx/rbx-dom", rev = "e7a813d569c3f8a54be8a8873c33f8976c37b8b1" }
rbx_reflection = { git = "https://github.com/rojo-rbx/rbx-dom", rev = "b6d255e0b5d96155f694ca224676b251059cf2de" } rbx_reflection = { git = "https://github.com/rojo-rbx/rbx-dom", rev = "e7a813d569c3f8a54be8a8873c33f8976c37b8b1" }
rbx_reflection_database = { git = "https://github.com/rojo-rbx/rbx-dom", rev = "b6d255e0b5d96155f694ca224676b251059cf2de" } rbx_reflection_database = { git = "https://github.com/rojo-rbx/rbx-dom", rev = "e7a813d569c3f8a54be8a8873c33f8976c37b8b1" }
rbx_xml = { git = "https://github.com/rojo-rbx/rbx-dom", rev = "b6d255e0b5d96155f694ca224676b251059cf2de" } rbx_xml = { git = "https://github.com/rojo-rbx/rbx-dom", rev = "e7a813d569c3f8a54be8a8873c33f8976c37b8b1" }
[dev-dependencies] [dev-dependencies]
anyhow = "1.0" anyhow = "1.0"

View file

@ -1,5 +1,5 @@
use std::{ use std::{
collections::{BTreeMap, HashMap, VecDeque}, collections::{BTreeMap, VecDeque},
fmt, fmt,
hash::{Hash, Hasher}, hash::{Hash, Hasher},
sync::RwLock, sync::RwLock,
@ -140,18 +140,14 @@ impl Instance {
root of the weak dom, and return its referent. root of the weak dom, and return its referent.
*/ */
pub fn clone_into_external_dom(self, external_dom: &mut WeakDom) -> DomRef { pub fn clone_into_external_dom(self, external_dom: &mut WeakDom) -> DomRef {
let cloned = self.clone_instance(); let dom = INTERNAL_DOM
let mut dom = INTERNAL_DOM
.try_write() .try_write()
.expect("Failed to get write access to document"); .expect("Failed to get write access to document");
let internal_dom_ref = cloned.dom_ref; let cloned = dom.clone_into_external(self.dom_ref, external_dom);
let external_root_ref = external_dom.root_ref(); external_dom.transfer_within(cloned, external_dom.root_ref());
dom.transfer(internal_dom_ref, external_dom, external_root_ref); cloned
internal_dom_ref
} }
/** /**
@ -167,91 +163,19 @@ impl Instance {
pub fn clone_instance(&self) -> Instance { pub fn clone_instance(&self) -> Instance {
// NOTE: We create a new scope here to avoid deadlocking since // NOTE: We create a new scope here to avoid deadlocking since
// our clone implementation must have exclusive write access // our clone implementation must have exclusive write access
let parent_ref = { let new_ref = {
INTERNAL_DOM
.try_read()
.expect("Failed to get read access to document")
.get_by_ref(self.dom_ref)
.expect("Failed to find instance in document")
.parent()
};
// Keep track of a map from old ref -> new ref for each
// instance so that we can then transform properties that
// are instance refs into ones pointing at the new instances
let mut reference_map = HashMap::new();
let new_ref = Self::clone_inner(self.dom_ref, parent_ref, &mut reference_map);
let new_inst = Self::new(new_ref);
{
let mut dom = INTERNAL_DOM let mut dom = INTERNAL_DOM
.try_write() .try_write()
.expect("Failed to get write access to document"); .expect("Failed to get write access to document");
let new_refs = reference_map.values().clone().collect::<Vec<_>>();
for new_ref in new_refs {
let new_inst = dom
.get_by_ref_mut(*new_ref)
.expect("Failed to find cloned instance in document");
for prop_value in new_inst.properties.values_mut() {
if let DomValue::Ref(prop_ref) = prop_value {
// NOTE: It is possible to get None here if the ref points to
// something outside of the newly cloned instance hierarchy
if let Some(new) = reference_map.get(prop_ref) {
*prop_value = DomValue::Ref(*new);
}
}
}
}
}
dom.clone_within(self.dom_ref)
};
let new_inst = Self::new(new_ref);
new_inst.set_parent(None); new_inst.set_parent(None);
new_inst new_inst
} }
pub fn clone_inner(
dom_ref: DomRef,
parent_ref: DomRef,
reference_map: &mut HashMap<DomRef, DomRef>,
) -> DomRef {
// NOTE: We create a new scope here to avoid deadlocking since
// our clone implementation must have exclusive write access
let (new_ref, child_refs) = {
let mut dom = INTERNAL_DOM
.try_write()
.expect("Failed to get write access to document");
let (new_class, new_name, new_props, child_refs) = {
let instance = dom
.get_by_ref(dom_ref)
.expect("Failed to find instance in document");
(
instance.class.to_string(),
instance.name.to_string(),
instance.properties.clone(),
instance.children().to_vec(),
)
};
let new_ref = dom.insert(
parent_ref,
DomInstanceBuilder::new(new_class)
.with_name(new_name)
.with_properties(new_props),
);
reference_map.insert(dom_ref, new_ref);
(new_ref, child_refs)
};
for child_ref in child_refs {
Self::clone_inner(child_ref, new_ref, reference_map);
}
new_ref
}
/** /**
Destroys the instance, removing it completely Destroys the instance, removing it completely
from the weak dom with no way of recovering it. from the weak dom with no way of recovering it.