Compare commits

..

11 Commits

Author SHA1 Message Date
Micah
41994ec82e Release v7.4.0-rc3 (#811) 2023-10-25 17:01:06 -07:00
Micah
cd14ea7c62 Remove unnecessary borrows (#810) 2023-10-25 17:59:02 -05:00
Kenneth Loeffler
9f13bca6b8 rbx_dom_lua rojo-rbx/rbx-dom@440f3723 (attribute validation) (#809)
Brings over some changes to rbx_dom_lua to validate attribute names
before calling `Instance:SetAttribute`. This should prevent Rojo from
falling over when it attempts to sync an attribute with an invalid name.
2023-10-25 14:21:58 -07:00
Kenneth Loeffler
f4252c3e97 Update changelog in preparation for 7.4.0-rc3 (#808)
Summarizes recent changes since 7.4.0-rc2 in the changelog
2023-10-23 22:54:48 +00:00
Kenneth Loeffler
6598867d3d Bump rbx_binary to 0.7.3 (#807)
Bumps rbx_binary's version to 0.7.3 to bring in the missing
`SecurityCapabilities` serialization fallback default
2023-10-23 22:43:00 +00:00
dependabot[bot]
f39e040a0d Bump rustix from 0.38.15 to 0.38.20 (#806) 2023-10-23 22:38:28 +00:00
Kenneth Loeffler
a3d140269b Demote unapplied patch warnings to debug logs (#805)
These warnings always appear for properties like `Capabilities`,
`SourceAssetId`, etc. and tend to scare users who are syncing models.
This information is now surfaced in the patch visualizer, so I think
these warnings can be demoted to debug logs.
2023-10-23 11:47:50 -07:00
Kenneth Loeffler
feac29ea40 Fix PatchTree incorrect changeList entries on decode failure (#804) 2023-10-22 16:58:12 -07:00
Kenneth Loeffler
834c8cdbca rbx_dom_lua rojo-rbx/rbx-dom@0e10232b (SecurityCapabilities) (#803)
Closes #802.
2023-10-22 16:57:59 -07:00
Kenneth Loeffler
d441fbdf91 Bump rbx_dom_lua rojo-rbx/rbx-dom@e7a5b91c (ScriptEditorService) (#801) 2023-10-17 14:15:47 -07:00
Filip Tibell
e897f524dc Skip sourcemap generation when unaffected by changes in watch mode (#800) 2023-10-13 08:38:21 -07:00
13 changed files with 177 additions and 81 deletions

View File

@@ -2,6 +2,21 @@
## Unreleased Changes
## [7.4.0-rc3] - October 25, 2023
* Changed `sourcemap --watch` to only generate the sourcemap when it's necessary ([#800])
* Switched script source property getter and setter to `ScriptEditorService` methods ([#801])
This ensures that the script editor reflects any changes Rojo makes to a script while it is open in the script editor.
* Fixed issues when handling `SecurityCapabilities` values ([#803], [#807])
* Fixed Rojo plugin erroring out when attempting to sync attributes with invalid names ([#809])
[#800]: https://github.com/rojo-rbx/rojo/pull/800
[#801]: https://github.com/rojo-rbx/rojo/pull/801
[#803]: https://github.com/rojo-rbx/rojo/pull/803
[#807]: https://github.com/rojo-rbx/rojo/pull/807
[#809]: https://github.com/rojo-rbx/rojo/pull/809
## [7.4.0-rc2] - October 3, 2023
* Fixed bug with parsing version for plugin validation ([#797])

10
Cargo.lock generated
View File

@@ -1586,9 +1586,9 @@ dependencies = [
[[package]]
name = "rbx_binary"
version = "0.7.2"
version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "10942950a57c939e540a2f977ba55e9140007d7e96c532d455502c290fdf710d"
checksum = "ad50c13afe91296dad6508ea7e29f4b665fa56cb664ad01eaf8fdbd3da69d5e1"
dependencies = [
"log",
"lz4",
@@ -1831,7 +1831,7 @@ dependencies = [
[[package]]
name = "rojo"
version = "7.4.0-rc2"
version = "7.4.0-rc3"
dependencies = [
"anyhow",
"backtrace",
@@ -1908,9 +1908,9 @@ dependencies = [
[[package]]
name = "rustix"
version = "0.38.15"
version = "0.38.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d2f9da0cbd88f9f09e7814e388301c8414c51c62aa6ce1e4b5c551d49d96e531"
checksum = "67ce50cb2e16c2903e30d1cbccfd8387a74b9d4c938b6a4c5ec6cc7556f7a8a0"
dependencies = [
"bitflags 2.4.0",
"errno",

View File

@@ -1,6 +1,6 @@
[package]
name = "rojo"
version = "7.4.0-rc2"
version = "7.4.0-rc3"
rust-version = "1.70.0"
authors = ["Lucien Greathouse <me@lpghatguy.com>"]
description = "Enables professional-grade development tools for Roblox developers"
@@ -49,7 +49,7 @@ memofs = { version = "0.2.0", path = "crates/memofs" }
# rbx_reflection_database = { path = "../rbx-dom/rbx_reflection_database" }
# rbx_xml = { path = "../rbx-dom/rbx_xml" }
rbx_binary = "0.7.2"
rbx_binary = "0.7.3"
rbx_dom_weak = "2.6.0"
rbx_reflection = "4.4.0"
rbx_reflection_database = "0.2.8"

View File

@@ -46,7 +46,7 @@ fn main() -> Result<(), anyhow::Error> {
let our_version = Version::parse(env::var_os("CARGO_PKG_VERSION").unwrap().to_str().unwrap())?;
let plugin_version =
Version::parse(fs::read_to_string(&plugin_root.join("Version.txt"))?.trim())?;
Version::parse(fs::read_to_string(plugin_root.join("Version.txt"))?.trim())?;
assert!(
our_version.major == plugin_version.major,

View File

@@ -1 +1 @@
7.4.0-rc2
7.4.0-rc3

View File

@@ -412,15 +412,6 @@ types = {
end,
},
SecurityCapabilities = {
fromPod = function(_pod)
error("SecurityCapabilities is not implemented")
end,
toPod = function(_roblox)
error("SecurityCapabilities is not implemented")
end,
},
SharedString = {
fromPod = function(_pod)
error("SharedString is not supported")

View File

@@ -1,4 +1,5 @@
local CollectionService = game:GetService("CollectionService")
local ScriptEditorService = game:GetService("ScriptEditorService")
--- A list of `Enum.Material` values that are used for Terrain.MaterialColors
local TERRAIN_MATERIAL_COLORS = {
@@ -36,9 +37,24 @@ return {
end,
write = function(instance, _, value)
local existing = instance:GetAttributes()
local didAllWritesSucceed = true
for key, attr in pairs(value) do
instance:SetAttribute(key, attr)
for attributeName, attributeValue in pairs(value) do
local isNameValid =
-- For our SetAttribute to succeed, the attribute name must be
-- less than or equal to 100 characters...
#attributeName <= 100
-- ...must only contain alphanumeric characters, periods, hyphens,
-- underscores, or forward slashes...
and attributeName:match("[^%w%.%-_/]") == nil
-- ... and must not use the RBX prefix, which is reserved by Roblox.
and attributeName:sub(1, 3) ~= "RBX"
if isNameValid then
instance:SetAttribute(attributeName, attributeValue)
else
didAllWritesSucceed = false
end
end
for key in pairs(existing) do
@@ -47,7 +63,7 @@ return {
end
end
return true
return didAllWritesSucceed
end,
},
Tags = {
@@ -116,4 +132,34 @@ return {
end,
},
},
Script = {
Source = {
read = function(instance: Script)
return true, ScriptEditorService:GetEditorSource(instance)
end,
write = function(instance: Script, _, value: string)
task.spawn(function()
ScriptEditorService:UpdateSourceAsync(instance, function()
return value
end)
end)
return true
end,
},
},
ModuleScript = {
Source = {
read = function(instance: ModuleScript)
return true, ScriptEditorService:GetEditorSource(instance)
end,
write = function(instance: ModuleScript, _, value: string)
task.spawn(function()
ScriptEditorService:UpdateSourceAsync(instance, function()
return value
end)
end)
return true
end,
},
},
}

View File

@@ -1,9 +1,9 @@
{
"Version": [
0,
596,
597,
1,
5960685
5970668
],
"Classes": {
"Accessory": {
@@ -4504,6 +4504,17 @@
},
"DefaultProperties": {}
},
"AvatarCreationService": {
"Name": "AvatarCreationService",
"Tags": [
"NotCreatable",
"NotReplicated",
"Service"
],
"Superclass": "Instance",
"Properties": {},
"DefaultProperties": {}
},
"AvatarEditorService": {
"Name": "AvatarEditorService",
"Tags": [
@@ -15560,9 +15571,7 @@
},
"DragDetector": {
"Name": "DragDetector",
"Tags": [
"NotBrowsable"
],
"Tags": [],
"Superclass": "ClickDetector",
"Properties": {
"ActivatedCursorIcon": {
@@ -28121,6 +28130,17 @@
}
}
},
"LogReporterService": {
"Name": "LogReporterService",
"Tags": [
"NotCreatable",
"NotReplicated",
"Service"
],
"Superclass": "Instance",
"Properties": {},
"DefaultProperties": {}
},
"LogService": {
"Name": "LogService",
"Tags": [
@@ -31192,7 +31212,7 @@
},
"Source": {
"Name": "Source",
"Scriptability": "ReadWrite",
"Scriptability": "Custom",
"DataType": {
"Value": "String"
},
@@ -41454,7 +41474,7 @@
"Properties": {
"Source": {
"Name": "Source",
"Scriptability": "ReadWrite",
"Scriptability": "Custom",
"DataType": {
"Value": "String"
},
@@ -47977,6 +47997,19 @@
}
}
},
"Camera Speed Adjust Binding": {
"Name": "Camera Speed Adjust Binding",
"Scriptability": "ReadWrite",
"DataType": {
"Enum": "CameraSpeedAdjustBinding"
},
"Tags": [],
"Kind": {
"Canonical": {
"Serialization": "Serializes"
}
}
},
"Camera Zoom to Mouse Position": {
"Name": "Camera Zoom to Mouse Position",
"Scriptability": "ReadWrite",
@@ -49545,7 +49578,9 @@
},
"StudioAttachment": {
"Name": "StudioAttachment",
"Tags": [],
"Tags": [
"NotReplicated"
],
"Superclass": "Instance",
"Properties": {
"AutoHideParent": {
@@ -49614,52 +49649,11 @@
}
}
},
"DefaultProperties": {
"Attributes": {
"Attributes": {}
},
"AutoHideParent": {
"Bool": false
},
"Capabilities": {
"SecurityCapabilities": 0
},
"DefinesCapabilities": {
"Bool": false
},
"IsArrowVisible": {
"Bool": false
},
"Offset": {
"Vector2": [
0.0,
0.0
]
},
"SourceAnchorPoint": {
"Vector2": [
0.0,
0.0
]
},
"SourceAssetId": {
"Int64": -1
},
"Tags": {
"Tags": []
},
"TargetAnchorPoint": {
"Vector2": [
0.0,
0.0
]
}
}
"DefaultProperties": {}
},
"StudioCallout": {
"Name": "StudioCallout",
"Tags": [
"NotCreatable",
"NotReplicated"
],
"Superclass": "Instance",
@@ -64701,6 +64695,14 @@
"EdgeBump": 1
}
},
"CameraSpeedAdjustBinding": {
"name": "CameraSpeedAdjustBinding",
"items": {
"AltScroll": 2,
"None": 0,
"RmbScroll": 1
}
},
"CameraType": {
"name": "CameraType",
"items": {
@@ -67514,6 +67516,9 @@
"Mid": 36,
"Midlight": 98,
"Notification": 4,
"OnboardingCover": 132,
"OnboardingHighlight": 133,
"OnboardingShadow": 134,
"RibbonButton": 19,
"RibbonTab": 15,
"RibbonTabTopBar": 16,

View File

@@ -233,7 +233,7 @@ function PatchTree.build(patch, instanceMap, changeListHeaders)
addProp(
prop,
if currentSuccess then currentValue else "[Error]",
if incomingSuccess then incomingValue else next(incoming)
if incomingSuccess then incomingValue else select(2, next(incoming))
)
end
@@ -359,7 +359,7 @@ function PatchTree.build(patch, instanceMap, changeListHeaders)
if success then
table.insert(changeList, { prop, "N/A", incomingValue })
else
table.insert(changeList, { prop, "N/A", next(incoming) })
table.insert(changeList, { prop, "N/A", select(2, next(incoming)) })
end
end

View File

@@ -282,7 +282,7 @@ function ServeSession:__initialSync(serverInfo)
local unappliedPatch = self.__reconciler:applyPatch(catchUpPatch)
if not PatchSet.isEmpty(unappliedPatch) then
Log.warn(
Log.debug(
"Could not apply all changes requested by the Rojo server:\n{}",
PatchSet.humanSummary(self.__instanceMap, unappliedPatch)
)
@@ -309,7 +309,7 @@ function ServeSession:__mainSyncLoop()
local unappliedPatch = self.__reconciler:applyPatch(message)
if not PatchSet.isEmpty(unappliedPatch) then
Log.warn(
Log.debug(
"Could not apply all changes requested by the Rojo server:\n{}",
PatchSet.humanSummary(self.__instanceMap, unappliedPatch)
)

View File

@@ -14,7 +14,7 @@ use tokio::runtime::Runtime;
use crate::{
serve_session::ServeSession,
snapshot::{InstanceWithMeta, RojoTree},
snapshot::{AppliedPatchSet, InstanceWithMeta, RojoTree},
};
use super::resolve_path;
@@ -90,10 +90,12 @@ impl SourcemapCommand {
loop {
let receiver = session.message_queue().subscribe(cursor);
let (new_cursor, _patch_set) = rt.block_on(receiver).unwrap();
let (new_cursor, patch_set) = rt.block_on(receiver).unwrap();
cursor = new_cursor;
write_sourcemap(&session, self.output.as_deref(), filter)?;
if patch_set_affects_sourcemap(&session, &patch_set, filter) {
write_sourcemap(&session, self.output.as_deref(), filter)?;
}
}
}
@@ -116,6 +118,43 @@ fn filter_non_scripts(instance: &InstanceWithMeta) -> bool {
)
}
fn patch_set_affects_sourcemap(
session: &ServeSession,
patch_set: &[AppliedPatchSet],
filter: fn(&InstanceWithMeta) -> bool,
) -> bool {
let tree = session.tree();
// A sourcemap has probably changed when:
patch_set.par_iter().any(|set| {
// 1. An instance was removed, in which case it will no
// longer exist in the tree and we cant check the filter
!set.removed.is_empty()
// 2. A newly added instance passes the filter
|| set.added.iter().any(|referent| {
let instance = tree
.get_instance(*referent)
.expect("instance did not exist when updating sourcemap");
filter(&instance)
})
// 3. An existing instance has its class name, name,
// or file paths changed, and passes the filter
|| set.updated.iter().any(|updated| {
let changed = updated.changed_class_name.is_some()
|| updated.changed_name.is_some()
|| updated.changed_metadata.is_some();
if changed {
let instance = tree
.get_instance(updated.id)
.expect("instance did not exist when updating sourcemap");
filter(&instance)
} else {
false
}
})
})
}
fn recurse_create_node<'a>(
tree: &'a RojoTree,
referent: Ref,

View File

@@ -24,7 +24,7 @@ impl<K: Hash + Eq, V: Eq> MultiMap<K, V> {
K: Borrow<Q>,
Q: Hash + Eq,
{
self.inner.get(k.borrow()).map(Vec::as_slice).unwrap_or(&[])
self.inner.get(k).map(Vec::as_slice).unwrap_or(&[])
}
pub fn insert(&mut self, k: K, v: V) {

View File

@@ -159,7 +159,7 @@ impl ApiService {
})
.unwrap();
json_ok(&WriteResponse { session_id })
json_ok(WriteResponse { session_id })
}
async fn handle_api_read(&self, request: Request<Body>) -> Response<Body> {
@@ -271,7 +271,7 @@ impl ApiService {
},
};
json_ok(&OpenResponse {
json_ok(OpenResponse {
session_id: self.serve_session.session_id(),
})
}