Use clone_multiple_into_external in Document instance methods (#117)

This commit is contained in:
Kenneth Loeffler 2023-10-04 15:25:26 -04:00 committed by GitHub
parent 74d7f3d66f
commit c43648faec
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 109 additions and 47 deletions

View file

@ -1,4 +1,4 @@
use rbx_dom_weak::{InstanceBuilder as DomInstanceBuilder, WeakDom};
use rbx_dom_weak::{types::Ref as DomRef, InstanceBuilder as DomInstanceBuilder, WeakDom};
use rbx_xml::{
DecodeOptions as XmlDecodeOptions, DecodePropertyBehavior as XmlDecodePropertyBehavior,
EncodeOptions as XmlEncodeOptions, EncodePropertyBehavior as XmlEncodePropertyBehavior,
@ -247,11 +247,13 @@ impl Document {
}
let mut dom = WeakDom::new(DomInstanceBuilder::new("ROOT"));
let children: Vec<DomRef> = i
.get_children()
.iter()
.map(|instance| instance.dom_ref)
.collect();
for data_model_child in i.get_children() {
data_model_child.clone_into_external_dom(&mut dom);
}
Instance::clone_multiple_into_external_dom(&children, &mut dom);
postprocess_dom_for_place(&mut dom);
Ok(Self {
@ -274,11 +276,9 @@ impl Document {
}
let mut dom = WeakDom::new(DomInstanceBuilder::new("ROOT"));
let instances: Vec<DomRef> = v.iter().map(|instance| instance.dom_ref).collect();
for instance in v {
instance.clone_into_external_dom(&mut dom);
}
Instance::clone_multiple_into_external_dom(&instances, &mut dom);
postprocess_dom_for_model(&mut dom);
Ok(Self {

View file

@ -144,6 +144,21 @@ impl Instance {
cloned
}
pub fn clone_multiple_into_external_dom(
referents: &[DomRef],
external_dom: &mut WeakDom,
) -> Vec<DomRef> {
let dom = INTERNAL_DOM.lock().expect("Failed to lock document");
let cloned = dom.clone_multiple_into_external(referents, external_dom);
for referent in cloned.iter() {
external_dom.transfer_within(*referent, external_dom.root_ref());
}
cloned
}
/**
Clones the instance and all of its descendants, and orphans it.

View file

@ -2,6 +2,8 @@ local fs = require("@lune/fs")
local roblox = require("@lune/roblox")
local Instance = roblox.Instance
-- Smoke tests
do
local instances = {
Instance.new("Model"),
Instance.new("Part"),
@ -30,3 +32,23 @@ assert(savedBinary[2].ClassName == "Part")
assert(savedXml[1].ClassName == "Model")
assert(savedXml[2].ClassName == "Part")
end
-- Ensure Ref properties are preserved across descendants of multi-root model siblings
do
local part = Instance.new("Part")
local particleEmitter = Instance.new("ParticleEmitter")
particleEmitter.Parent = part
local folder = Instance.new("Folder")
local objectValue = Instance.new("ObjectValue") :: any
objectValue.Value = particleEmitter
objectValue.Parent = folder
local serialized = roblox.serializeModel({ part, folder })
local deserialized = roblox.deserializeModel(serialized) :: any
assert(deserialized[2].ObjectValue.Value == deserialized[1].ParticleEmitter)
end

View file

@ -2,6 +2,8 @@ local fs = require("@lune/fs")
local roblox = require("@lune/roblox")
local Instance = roblox.Instance
-- Smoke tests
do
local game = Instance.new("DataModel")
local workspace = game:GetService("Workspace")
@ -29,3 +31,26 @@ assert(savedXml.Name ~= "ROOT")
assert(savedBinary.ClassName == "DataModel")
assert(savedXml.ClassName == "DataModel")
end
-- Ensure Ref properties are preserved across services
do
local game = Instance.new("DataModel")
local ReplicatedStorage = Instance.new("ReplicatedStorage")
local Workspace = Instance.new("Workspace")
Workspace.Parent = game
ReplicatedStorage.Parent = game
local part = Instance.new("Part")
part.Parent = ReplicatedStorage
local objectValue = Instance.new("ObjectValue") :: any
objectValue.Value = part
objectValue.Parent = Workspace
local serialized = roblox.serializePlace(game)
local deserialized = roblox.deserializePlace(serialized) :: any
assert(deserialized.Workspace.ObjectValue.Value == deserialized.ReplicatedStorage.Part)
end