Railo 4.2 variables scope reference bug?

122 views
Skip to first unread message

Rory

unread,
Jun 2, 2014, 3:55:30 PM6/2/14
to ra...@googlegroups.com
Hello,

I'm wondering if this was an intentional change, I couldn't find anything specific to it. There is a difference between Railo 4.0.4.001 and 4.2.1.000 when dynamically adding functions to a CFC and which scopes that function binds to. 

See a simplified same below where in component1.cfc I instantiate component2, and I define a function on the THIS scope of component2

//component1.cfc
component {

variables.testValue = "Component1";

public function test(){
local.com2 = new component2();
local.com2.override = function(){
writeDump(this); //References the this scope of component1 when it should be component2
writeDump(variables); //References the variables scope of component1 when it should be component2
}
local.com2.override();
}
}

My intention is to be able to spy/inject values into component2 variables scope from component1 dynamically on the fly without having to write a temporary wrapper CFC to extend component 2. This worked as I expected in 4.0.4, but not in 4.2. Attached is the test code for those interested. 

In Railo 4.0.4.001, the output looks like this where I see the values of component 2 when I call the override method:



























In Railo 4.2 however, doing this results showing the values of component 1, so the function is bound to the component in which it is instantiated, not that in which it is called:





inject_test.zip

Rory

unread,
Jun 2, 2014, 4:25:03 PM6/2/14
to ra...@googlegroups.com
Perhaps related to: "super reference invalid when called from within closure" https://issues.jboss.org/browse/RAILO-2902

I am thinking this is the same kind of issue. The variables scope should be referenced from where the function is called/bound, not where it is created, I think.

Michael Offner

unread,
Jun 3, 2014, 2:05:49 AM6/3/14
to ra...@googlegroups.com
Could you raise a ticket in jira for this, we will take a closer look.

Micha
--
Did you find this reply useful? Help the Railo community and add it to the Railo Server wiki at https://github.com/getrailo/railo/wiki
---
You received this message because you are subscribed to the Google Groups "Railo" group.
To view this discussion on the web visit https://groups.google.com/d/msgid/railo/367a6783-c9ba-45b1-9324-8492ff7ecf57%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


--
/micha

Michael Offner CTO Railo Technologies GmbH

Rory

unread,
Jun 3, 2014, 8:41:43 AM6/3/14
to ra...@googlegroups.com

Peter Jackson

unread,
Jun 4, 2014, 10:15:08 AM6/4/14
to ra...@googlegroups.com
I don't want to pollute this topic but I have a similar and more fundamental scope oddity that has just started happening - strangely without any changes to my Java or Railo.  I wonder if it's related?

The shortest test case I have is:

<cfset myQuery = query(lastName:array('Jordan','Bryant'),age:array(42,24))>
<cfset queryAddColumn(myQuery, "firstname")>
<cfloop query="myQuery">
<cfset firstName = "Bob">
<cfoutput>[#firstName#]</cfoutput>
</cfloop>

I have "cascading" set to strict.  After adding a column named "firstname", when I output firstname inside the query loop, it outputs "[][]".  If I remove the queryAddCollumn, it outputs "[Bob][Bob]".

If someone can confirm this is incorrect behaviour, I will raise a ticket.

Peter


Rory

unread,
Jun 4, 2014, 10:18:35 AM6/4/14
to ra...@googlegroups.com
Update: The solution here is to use UDFs to do the mixin. It turns out that on Railo 4.0.4 I was defining a closure that was not properly enclosing the scopes of where it was created, but Railo 4.1+ is working with closures enclosing the scopes properly and this is intended. For the purposes of injecting methods which access the scopes of where they are called from and not where they are created, use a UDF (defined in either a CFC or CFM). 


On Monday, June 2, 2014 3:55:30 PM UTC-4, Rory wrote:

Michael Offner

unread,
Jun 4, 2014, 2:41:10 PM6/4/14
to ra...@googlegroups.com
No this is correct behavior, inside a cfloop-query/cfoutput-query Railo (and acf) first looks into the query that is iterated before it looks into scopes.
Scope cascading setting has no influence on that, but there is a setting in admin to disable this behavior ( look into query when no query name is defined ) on the same page in the admin where you define scope cascading.

Micha

Peter Jackson

unread,
Jun 5, 2014, 4:31:24 AM6/5/14
to ra...@googlegroups.com
Thanks Micha. 

ML

unread,
Jul 21, 2014, 11:41:08 AM7/21/14
to ra...@googlegroups.com
Hi all,

I am still struggling to understand this closure scope and I am wondering if anyone could help enlighten me.   Here's the example I have in mind:

test.cfc
component {

   
public Any function init(){

        instance
.member = [];

       
for( counter in [1,2,3] )

            instance
.member[ counter ] = function() { dump( counter ); }


       
return this;

   
}

   
public any function getMember( idx ){

       
return instance.member[ arguments.idx ];

   
}

}


    obj = new Test();
    firstMember
= obj.getMember( 1 );
    secondMember
= obj.getMember( 2 );
    thirdMember
= obj.getMember( 3 );

    firstMember
();  // return 3
    secondMember
(); // return 3
    thirdMember
();  // return 3

So, in this example, when I called firstMember(), secondMember(), thirdMember(), I was expecting to get 1,2, and 3 respectively.  However, I got 3, 3, 3.  So, does that mean that the value of counter is based on the live value of counter at the time the closure is called, as opposed to the the value of counter at the time the closure is constructed?  If so, how would I be able to keep track of the value of counter at the time the closure is defined when I have an array of similar objects?

Thanks!

Andrew Dixon

unread,
Jul 21, 2014, 2:37:35 PM7/21/14
to ra...@googlegroups.com

Hi,

This presentation from Adam Tuttle is a pretty good explanation for clousure.

http://fusiongrokker.com/p/closures/#/


Kind regards,

Andrew


--
Did you find this reply useful? Help the Railo community and add it to the Railo Server wiki at https://github.com/getrailo/railo/wiki
---
You received this message because you are subscribed to the Google Groups "Railo" group.

Jeroen Knoef

unread,
Jul 22, 2014, 6:12:39 PM7/22/14
to ra...@googlegroups.com
Hi,

The outcome you get is what I'd expect because the same counter variable is present in all 3 closures. To get what you want you'd have to introduce another closure where you can copy the counter value (which is common in JavaScript, I haven't actually tried this in Railo):

public Any function init(){

        instance
.member = [];

        var createMember = function (index) {
            var counter = arguments.index;
            return function () {
                return counter;
            }
        }

        
for( counter in [1,2,3] )


            instance
.member[ counter ] = createMember(counter); }


        
return this;

    
}

Now every member has its own closure with its own copy of the counter.

Op maandag 21 juli 2014 17:41:08 UTC+2 schreef ML:

ML

unread,
Jul 22, 2014, 11:16:04 PM7/22/14
to ra...@googlegroups.com
That makes sense (and it works in Railo btw).  Thanks!
Reply all
Reply to author
Forward
0 new messages