Upgrade to rbx_dom_weak 2.0 (#377)

* Mostly mechanical port bits

* Almost there

* It builds again!

* Turn on all the code again

* Tests compiling but not passing

* Stub work for value resolution

* Implement resolution minus enums and derived properties

* Implement property descriptor resolution

* Update referent snapshots

* Update unions test project

Using a place file instead of a model yields better
error messages in Roblox Studio.

* Add easy shortcut to testing with local rbx-dom

* Update rbx-dom

* Add enum resolution

* Update init.meta.json to use UnresolvedValue

* Expand value resolution support, add test

* Filter SharedString values from web API

* Add 'property' builder method to InstanceSnapshot

* Change InstanceSnapshot/InstanceBuilder boundary

* Fix remove_file crash

* rustfmt

* Update to latest rbx_dom_lua

* Update dependencies, including rbx_dom_weak

* Update to latest rbx-dom

* Update dependencies

* Update rbx-dom, fixing more bugs

* Remove experimental warning on binary place builds

* Remove unused imports
This commit is contained in:
Lucien Greathouse
2021-02-18 20:56:09 -05:00
committed by GitHub
parent b84aab0960
commit 59ef5f05ea
63 changed files with 45602 additions and 21004 deletions

View File

@@ -0,0 +1 @@
require(game.ReplicatedStorage.TestEZ).TestBootstrap:run({game.ReplicatedStorage.RbxDom})

View File

@@ -20,6 +20,9 @@ local function serializeFloat(value)
return value
end
local ALL_AXES = {"X", "Y", "Z"}
local ALL_FACES = {"Right", "Top", "Back", "Left", "Bottom", "Front"}
local encoders
encoders = {
Bool = identity,
@@ -33,12 +36,56 @@ encoders = {
BinaryString = base64.encode,
SharedString = base64.encode,
Axes = function(value)
local output = {}
for _, axis in ipairs(ALL_AXES) do
if value[axis] then
table.insert(output, axis)
end
end
return output
end,
Faces = function(value)
local output = {}
for _, face in ipairs(ALL_FACES) do
if value[face] then
table.insert(output, face)
end
end
return output
end,
Enum = function(value)
if typeof(value) == "number" then
return value
else
return value.Value
end
end,
BrickColor = function(value)
return value.Number
end,
CFrame = function(value)
return {value:GetComponents()}
local x, y, z,
r00, r01, r02,
r10, r11, r12,
r20, r21, r22 = value:GetComponents()
return {
Position = {x, y, z},
Orientation = {
{r00, r10, r20},
{r01, r11, r21},
{r02, r12, r22},
},
}
end,
Color3 = function(value)
return {value.r, value.g, value.b}
@@ -77,15 +124,18 @@ encoders = {
end,
Rect = function(value)
return {
Min = {value.Min.X, value.Min.Y},
Max = {value.Max.X, value.Max.Y},
encoders.Vector2(value.Min),
encoders.Vector2(value.Max),
}
end,
UDim = function(value)
return {value.Scale, value.Offset}
end,
UDim2 = function(value)
return {value.X.Scale, value.X.Offset, value.Y.Scale, value.Y.Offset}
return {
encoders.UDim(value.X),
encoders.UDim(value.Y),
}
end,
Vector2 = function(value)
return {
@@ -121,12 +171,35 @@ encoders = {
end
end,
Ray = function(value)
return {
Origin = encoders.Vector3(value.Origin),
Direction = encoders.Vector3(value.Direction),
}
end,
Ref = function(value)
return nil
end,
Region3int16 = function(value)
return {
encoders.Vector3int16(value.Min),
encoders.Vector3int16(value.Max),
}
end,
Color3uint8 = function(value)
return {
math.round(value.R * 255),
math.round(value.G * 255),
math.round(value.B * 255),
}
end,
}
local decoders = {
local decoders
decoders = {
Bool = identity,
Content = identity,
Enum = identity,
@@ -141,19 +214,63 @@ local decoders = {
BrickColor = BrickColor.new,
CFrame = unpackDecoder(CFrame.new),
Color3 = unpackDecoder(Color3.new),
Color3uint8 = unpackDecoder(Color3.fromRGB),
NumberRange = unpackDecoder(NumberRange.new),
UDim = unpackDecoder(UDim.new),
UDim2 = unpackDecoder(UDim2.new),
Vector2 = unpackDecoder(Vector2.new),
Vector2int16 = unpackDecoder(Vector2int16.new),
Vector3 = unpackDecoder(Vector3.new),
Vector3int16 = unpackDecoder(Vector3int16.new),
UDim2 = function(value)
return UDim2.new(
value[1][1],
value[1][2],
value[2][1],
value[2][2]
)
end,
Axes = function(value)
local axes = {}
for index, axisName in ipairs(value) do
axes[index] = Enum.Axis[axisName]
end
return Axes.new(unpack(axes))
end,
Faces = function(value)
local normalIds = {}
for index, faceName in ipairs(value) do
normalIds[index] = Enum.NormalId[faceName]
end
return Faces.new(unpack(normalIds))
end,
CFrame = function(value)
return CFrame.fromMatrix(
decoders.Vector3(value.Position),
decoders.Vector3(value.Orientation[1]),
decoders.Vector3(value.Orientation[2]),
decoders.Vector3(value.Orientation[3])
)
end,
Rect = function(value)
return Rect.new(value.Min[1], value.Min[2], value.Max[1], value.Max[2])
return Rect.new(
decoders.Vector2(value[1]),
decoders.Vector2(value[2])
)
end,
Ray = function(value)
return Ray.new(
decoders.Vector3(value.Origin),
decoders.Vector3(value.Direction)
)
end,
NumberSequence = function(value)
@@ -200,6 +317,13 @@ local decoders = {
Ref = function()
return nil
end,
Region3int16 = function(value)
return Region3int16.new(
decoders.Vector3int16(value[1]),
decoders.Vector3int16(value[2])
)
end,
}
local EncodedValue = {}
@@ -216,27 +340,16 @@ end
function EncodedValue.encode(rbxValue, propertyType)
assert(propertyType ~= nil, "Property type descriptor is required")
if propertyType.type == "Data" then
local encoder = encoders[propertyType.name]
local encoder = encoders[propertyType]
if encoder == nil then
return false, ("Missing encoder for property type %q"):format(propertyType.name)
end
if encoder ~= nil then
return true, {
Type = propertyType.name,
Value = encoder(rbxValue),
}
end
elseif propertyType.type == "Enum" then
return true, {
Type = "Enum",
Value = rbxValue.Value,
}
if encoder == nil then
return false, ("Missing encoder for property type %q"):format(propertyType)
end
return false, ("Unknown property descriptor type %q"):format(tostring(propertyType.type))
return true, {
Type = propertyType,
Value = encoder(rbxValue),
}
end
return EncodedValue
return EncodedValue

View File

@@ -1,127 +1,63 @@
return function()
local HttpService = game:GetService("HttpService")
local RbxDom = require(script.Parent)
local EncodedValue = require(script.Parent.EncodedValue)
local allValues = require(script.Parent.allValues)
it("should decode Rect values", function()
local input = {
Type = "Rect",
Value = {
Min = {1, 2},
Max = {3, 4},
},
}
local function deepEq(a, b)
if typeof(a) ~= typeof(b) then
return false
end
local output = Rect.new(1, 2, 3, 4)
local ty = typeof(a)
local ok, decoded = EncodedValue.decode(input)
if ty == "table" then
local visited = {}
for key, valueA in pairs(a) do
visited[key] = true
if not deepEq(valueA, b[key]) then
return false
end
end
assert(ok, decoded)
expect(decoded).to.equal(output)
end)
for key, valueB in pairs(b) do
if visited[key] then
continue
end
it("should decode ColorSequence values", function()
local input = {
Type = "ColorSequence",
Value = {
Keypoints = {
{
Time = 0,
Color = { 0.12, 0.34, 0.56 },
},
if not deepEq(valueB, a[key]) then
return false
end
end
{
Time = 1,
Color = { 0.13, 0.33, 0.37 },
},
}
},
}
return true
else
return a == b
end
end
local output = ColorSequence.new({
ColorSequenceKeypoint.new(0, Color3.new(0.12, 0.34, 0.56)),
ColorSequenceKeypoint.new(1, Color3.new(0.13, 0.33, 0.37)),
})
for testName, testEntry in pairs(allValues) do
it("round trip " .. testName, function()
local ok, decoded = EncodedValue.decode(testEntry.value)
assert(ok, decoded)
local ok, decoded = EncodedValue.decode(input)
assert(ok, decoded)
expect(decoded).to.equal(output)
end)
local ok, encoded = EncodedValue.encode(decoded, testEntry.ty)
assert(ok, encoded)
it("should decode NumberSequence values", function()
local input = {
Type = "NumberSequence",
Value = {
Keypoints = {
{
Time = 0,
Value = 0.5,
Envelope = 0,
},
if not deepEq(encoded, testEntry.value) then
local expected = HttpService:JSONEncode(testEntry.value)
local actual = HttpService:JSONEncode(encoded)
{
Time = 1,
Value = 0.5,
Envelope = 0,
},
}
},
}
local message = string.format(
"Round-trip results did not match.\nExpected:\n%s\nActual:\n%s",
expected, actual
)
local output = NumberSequence.new({
NumberSequenceKeypoint.new(0, 0.5, 0),
NumberSequenceKeypoint.new(1, 0.5, 0),
})
local ok, decoded = EncodedValue.decode(input)
assert(ok, decoded)
expect(decoded).to.equal(output)
end)
it("should decode PhysicalProperties values", function()
local input = {
Type = "PhysicalProperties",
Value = {
Density = 0.1,
Friction = 0.2,
Elasticity = 0.3,
FrictionWeight = 0.4,
ElasticityWeight = 0.5,
},
}
local output = PhysicalProperties.new(
0.1,
0.2,
0.3,
0.4,
0.5
)
local ok, decoded = EncodedValue.decode(input)
assert(ok, decoded)
expect(decoded).to.equal(output)
end)
-- This part of rbx_dom_lua needs some work still.
itSKIP("should encode Rect values", function()
local input = Rect.new(10, 20, 30, 40)
local output = {
Type = "Rect",
Value = {
Min = {10, 20},
Max = {30, 40},
},
}
local descriptor = RbxDom.findCanonicalPropertyDescriptor("ImageLabel", "SliceCenter")
local ok, encoded = EncodedValue.encode(input, descriptor)
assert(ok, encoded)
expect(encoded.Type).to.equal(output.Type)
expect(encoded.Value.Min[1]).to.equal(output.Value.Min[1])
expect(encoded.Value.Min[2]).to.equal(output.Value.Min[2])
expect(encoded.Value.Max[1]).to.equal(output.Value.Max[1])
expect(encoded.Value.Max[2]).to.equal(output.Value.Max[2])
end)
end
error(message)
end
end)
end
end

View File

@@ -21,7 +21,7 @@ end
function PropertyDescriptor.fromRaw(data, className, propertyName)
return setmetatable({
scriptability = data.scriptability,
scriptability = data.Scriptability,
className = className,
name = propertyName,
}, PropertyDescriptor)

File diff suppressed because it is too large Load Diff

View File

@@ -1,3 +0,0 @@
return {
classes = require(script.classes)
}

View File

@@ -0,0 +1,338 @@
{
"Color3uint8": {
"value": {
"Type": "Color3uint8",
"Value": [
0,
128,
255
]
},
"ty": "Color3uint8"
},
"Bool": {
"value": {
"Type": "Bool",
"Value": true
},
"ty": "Bool"
},
"BinaryString": {
"value": {
"Type": "BinaryString",
"Value": "SGVsbG8h"
},
"ty": "BinaryString"
},
"BrickColor": {
"value": {
"Type": "BrickColor",
"Value": 1004
},
"ty": "BrickColor"
},
"Vector3": {
"value": {
"Type": "Vector3",
"Value": [
-300.0,
0.0,
1500.0
]
},
"ty": "Vector3"
},
"String": {
"value": {
"Type": "String",
"Value": "Hello, world!"
},
"ty": "String"
},
"NumberRange": {
"value": {
"Type": "NumberRange",
"Value": [
-36.0,
94.0
]
},
"ty": "NumberRange"
},
"Int64": {
"value": {
"Type": "Int64",
"Value": 23491023
},
"ty": "Int64"
},
"Vector3int16": {
"value": {
"Type": "Vector3int16",
"Value": [
60,
37,
-450
]
},
"ty": "Vector3int16"
},
"Float32": {
"value": {
"Type": "Float32",
"Value": 15.0
},
"ty": "Float32"
},
"NumberSequence": {
"value": {
"Type": "NumberSequence",
"Value": {
"Keypoints": [
{
"Time": 0.0,
"Value": 5.0,
"Envelope": 2.0
},
{
"Time": 1.0,
"Value": 22.0,
"Envelope": 0.0
}
]
}
},
"ty": "NumberSequence"
},
"ColorSequence": {
"value": {
"Type": "ColorSequence",
"Value": {
"Keypoints": [
{
"Time": 0.0,
"Color": [
1.0,
1.0,
0.5
]
},
{
"Time": 1.0,
"Color": [
0.0,
0.0,
0.0
]
}
]
}
},
"ty": "ColorSequence"
},
"Ray": {
"value": {
"Type": "Ray",
"Value": {
"Origin": [
1.0,
2.0,
3.0
],
"Direction": [
4.0,
5.0,
6.0
]
}
},
"ty": "Ray"
},
"Int32": {
"value": {
"Type": "Int32",
"Value": 6014
},
"ty": "Int32"
},
"Axes": {
"value": {
"Type": "Axes",
"Value": [
"X",
"Y",
"Z"
]
},
"ty": "Axes"
},
"Enum": {
"value": {
"Type": "Enum",
"Value": 1234
},
"ty": "Enum"
},
"Faces": {
"value": {
"Type": "Faces",
"Value": [
"Right",
"Top",
"Back",
"Left",
"Bottom",
"Front"
]
},
"ty": "Faces"
},
"UDim": {
"value": {
"Type": "UDim",
"Value": [
1.0,
32
]
},
"ty": "UDim"
},
"Vector2": {
"value": {
"Type": "Vector2",
"Value": [
-50.0,
50.0
]
},
"ty": "Vector2"
},
"Color3": {
"value": {
"Type": "Color3",
"Value": [
1.0,
2.0,
3.0
]
},
"ty": "Color3"
},
"Float64": {
"value": {
"Type": "Float64",
"Value": 15123.0
},
"ty": "Float64"
},
"UDim2": {
"value": {
"Type": "UDim2",
"Value": [
[
-1.0,
100
],
[
1.0,
-100
]
]
},
"ty": "UDim2"
},
"Region3int16": {
"value": {
"Type": "Region3int16",
"Value": [
[
-10,
-5,
0
],
[
5,
10,
15
]
]
},
"ty": "Region3int16"
},
"CFrame": {
"value": {
"Type": "CFrame",
"Value": {
"Position": [
1.0,
2.0,
3.0
],
"Orientation": [
[
4.0,
5.0,
6.0
],
[
7.0,
8.0,
9.0
],
[
10.0,
11.0,
12.0
]
]
}
},
"ty": "CFrame"
},
"Content": {
"value": {
"Type": "Content",
"Value": "rbxassetid://12345"
},
"ty": "Content"
},
"PhysicalProperties": {
"value": {
"Type": "PhysicalProperties",
"Value": {
"Density": 0.5,
"Friction": 1.0,
"Elasticity": 0.0,
"FrictionWeight": 50.0,
"ElasticityWeight": 25.0
}
},
"ty": "PhysicalProperties"
},
"Rect": {
"value": {
"Type": "Rect",
"Value": [
[
0.0,
5.0
],
[
10.0,
15.0
]
]
},
"ty": "Rect"
},
"Vector2int16": {
"value": {
"Type": "Vector2int16",
"Value": [
-300,
300
]
},
"ty": "Vector2int16"
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +1,4 @@
local ReflectionDatabase = require(script.ReflectionDatabase)
local database = require(script.database)
local Error = require(script.Error)
local PropertyDescriptor = require(script.PropertyDescriptor)
@@ -6,29 +6,31 @@ local function findCanonicalPropertyDescriptor(className, propertyName)
local currentClassName = className
repeat
local currentClass = ReflectionDatabase.classes[currentClassName]
local currentClass = database.Classes[currentClassName]
if currentClass == nil then
return currentClass
end
local propertyData = currentClass.properties[propertyName]
local propertyData = currentClass.Properties[propertyName]
if propertyData ~= nil then
if propertyData.isCanonical then
local canonicalData = propertyData.Kind.Canonical
if canonicalData ~= nil then
return PropertyDescriptor.fromRaw(propertyData, currentClassName, propertyName)
end
if propertyData.canonicalName ~= nil then
local aliasData = propertyData.Kind.Alias
if aliasData ~= nil then
return PropertyDescriptor.fromRaw(
currentClass.properties[propertyData.canonicalName],
currentClass.properties[aliasData.AliasFor],
currentClassName,
propertyData.canonicalName)
aliasData.AliasFor)
end
return nil
end
currentClassName = currentClass.superclass
currentClassName = currentClass.Superclass
until currentClassName == nil
return nil

4
plugin/rbx_dom_lua/test Normal file
View File

@@ -0,0 +1,4 @@
#!/bin/sh
rojo build test-place.project.json -o TestPlace.rbxlx
run-in-roblox --script run-tests.lua --place TestPlace.rbxlx

View File

@@ -16,7 +16,7 @@
"$className": "ServerScriptService",
"Run Tests": {
"$path": "test.server.lua"
"$path": "run-tests.lua"
}
},
"Players": {

View File

@@ -1,7 +0,0 @@
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local LIB_ROOT = ReplicatedStorage.RbxDom
local TestEZ = require(ReplicatedStorage.TestEZ)
TestEZ.TestBootstrap:run({LIB_ROOT})