Status/Resolution/Reason: Closed/Fixed/
Reporter/Name(from Bugbase): Lewis Stewart / Lewis Stewart (Lewis Stewart)
Created: 06/20/2015
Components: Language
Versions: 10.0
Failure Type: Performance Issue
Found In Build/Fixed In Build: Final /
Priority/Frequency: Major / All users will encounter
Locale/System: English / Linux All
Vote Count: 1
I believe there is a serious bug with the for-in construct when used in a particular fashion. In particular, if the "in" expression is a function call, it appears that the function is invoked multiple times (to be precise, it always appears to be 5 times).
Clearly there are many situations where this could have serious consequences, not least if the function does any serious work or has side effects.
Key points:
Tested on Coldfusion 10 update 16
Using a for-in construct where the "in" expression invokes a function results in that function being invoked multiple times.
It doesn't seem to matter what the function returns (e.g. struct, array, potentially other iterables)
Workaround:
Assign the result of the function call to a local variable outside the for-in construct
Severity:
This a serious issue as,
It is easy to cause using a common idiom
It is completed unexpected
The fact that it is happening is essentially invisible to the developer
The results are potentially very serious
Speculation:
I speculate that the code is pre-processed into a construct that does (in clause).size() (in clause).iterator(), etc
Test Case:
See below for some code which tests this:
component displayname="ForInTest" {
ForInTest function init() {
variables.count = 0;
return this;
}
void function test1() {
variables.count = 0;
for( var item in getArray() ) {
// do something interesting
}
if( variables.count==1 ) {
writeoutput( "getArray() was called once." );
}
else {
writeoutput( "getArray() was called multiple times! (" & variables.count & ")" );
}
}
void function test2() {
variables.count = 0;
var items = getArray();
for( var item in items ) {
// do something interesting
}
if( variables.count==1 ) {
writeoutput( "getArray() was called once." );
}
else {
writeoutput( "getArray() was called multiple times! (" & variables.count & ")" );
}
}
private array function getArray() {
variables.count++;
var data = [1,2,3];
return data;
}
}
var test = new ForInTest();
test.test1();
test.test2();
Output:
getArray() was called multiple times! (5)
getArray() was called once.
----------------------------- Additional Watson Details -----------------------------
Watson Bug ID: 4010308
External Customer Info:
External Company:
External Customer Name: Lewis
External Customer Email:
External Test Config: My Hardware and Environment details:
Attachments:
Comments: