It’s been a looooong time since I’ve really used CFML, so I may be missing something fundamental that has changed
Summary:
Initial values set into the variables scope on a persistent CFC appear to be shared across all instances. In other words:
// Thing.cfc
component persistent='true' {
variables.someStruct = { foo: 'bar'}
}
var thing1 = new Thing()
var thing2 = new Thing()
// This updates thing 1 and thing 2!!
thing2.getSomeStruct().foo = 'thing 2 value'
Reproducible case showing inconsistency with non-persistent CFC behavior
Clone and run (docker): GitHub - joeRinehart/lucee-variables-bug: Demo of bug in legacy app server
More formally
When I:
- Make a CFC persistent
- Have a complex value (struct, array, or component reference) declared within its variables scope
- Do not have a init() method in the component that re-sets the value
- Create two instances of the CFC
- Mutate the complex value in one instance
I’d expect:
- The complex value to only be changed in that instance
Instead:
- It appears to be changed in all instances!
This does not:
- Impact CFCs where the “persistent” attribute is NOT in place
In code, here’s an example of a failing feature in a spec:
it("Struct values should not be shared across instances", function() {
var circle1 = entityNew( 'PersistentCircle' );
var circle2 = entityNew( 'PersistentCircle' );
// expect
expect( structCount(circle1.getStructProp()) ).toBe(0);
expect( structCount(circle2.getStructProp()) ).toBe(0);
// when
var structProp = circle2.getStructProp();
structProp.value = 'Struct prop in circle 2!';
// then
expect( structCount(circle2.getStructProp()) ).toBe(1);
// THIS FAILS!
expect( structCount(circle1.getStructProp()) ).toBe(0, "Circle one's struct was changed!");
});
Don’t forget to tell us about your stack!
OS: Docker/Latest (5.3.10.120)
Java Version: Docker/Latest (5.3.10.120)
Tomcat Version: Docker/Latest (5.3.10.120)
Lucee Version: Docker/Latest (5.3.10.120)