Hi Garry,
I'm porting the B4X B4XSerializator (binary serializer used by jRDC2) to Objo and ran into three runtime behaviours that look like bugs. The first one is the serious one.
Environment: Objo Studio 26.2.93, MACOS 27.0, desktop application project.
1) A Dictionary does not keep class instances alive
If a class instance is stored as a Dictionary value and the last variable referencing it goes out of scope, reading it back returns a default-constructed instance (constructor not run, all properties Nothing). Arrays do not have this problem.
Minimal repro:
Public Class Box
Public Property Items As Array(Of Object)
Public Constructor(source As Array(Of Object))
Self.Items = source
End Constructor
End Class
Function MakeDict() As Dictionary(Of Object, Object)
Var b As New Box(["x"])
Var d As New Dictionary(Of Object, Object)
d.Value("b") = b
Return d
End Function
Function MakeArr() As Array(Of Object)
Var b As New Box(["x"])
Var a() As Object
a.Append(b)
Return a
End Function
# caller
Var d As Dictionary(Of Object, Object) = MakeDict()
Var o As Object = d.Value("b")
Var b1 As Box = Box(o)
Print(b1.Items = Nothing) # prints True - expected False
Var a As Array(Of Object) = MakeArr()
Var o2 As Object = a[0]
Var b2 As Box = Box(o2)
Print(b2.Items = Nothing) # prints False - correct
The same thing happens without a function boundary when the result of a call is assigned straight into a dictionary value, e.g.
d.Value("b") = SomeFunctionReturningBox()
whereas assigning through a local first (Var tmp As Box = SomeFunctionReturningBox() / d.Value("b") = tmp) works as long as tmp stays in scope. It looks as if the dictionary holds a weak reference or a copy that is re-instantiated rather than the object itself.
2) A parameter with the same name as a property silently shadows it
Public Class Wrapper
Public Property Value As Integer
Public Constructor(value As Integer)
Self.Value = value # property is never set; Value stays Nothing/0
End Constructor
End Class
Because identifiers are case-insensitive, value and Value are the same name and Self.Value = value appears to assign the parameter to itself. Renaming the parameter (e.g. v) fixes it. I'd expect either Self.X to always resolve to the member, or a compile-time error/warning about the shadowing. As it is, it fails silently.
3) Reading a non-Public property from another class returns Nothing instead of failing to compile
Public Class Holder
Property Data As String # no access modifier
Public Constructor()
Self.Data = "hello"
End Constructor
End Class
# in another class:
Var h As New Holder
Print(h.Data = Nothing) # prints True; compiles without error
If a property without a modifier is meant to be private, an external read should be a compile error rather than silently yielding Nothing.
Happy to provide the full project or run any additional tests if that helps. The serializer is otherwise working well with array-backed containers as a workaround.
Thanks for Objo 🙂
Best regards,
Guido