Odd CFLoop Condition Runtime Compilation Bug

Posted December 11, 2009 at 4:12 PM by Ben Nadel

Tags: ColdFusion

Yesterday (or was it the day before), Mark Mandel brought up a very odd CFLoop / Condition runtime compilation error on Twitter. It involved evaluating explicit True / False data types in order to prepare the Condition attribute of the CFLoop tag. To demonstrate this, take a look at the following code snippets and their associated output:

  • <!--- Store true in a variable. --->
  • <cfset isTrue = true />
  • <!--- Demonstrate that TRUE can be used in hashes and parens. --->
  • Is True: #(true)# | #true#<br />

Is True: true | true

  • <!--- Loop while true. --->
  • <cfloop condition="isTrue">
  • Loop True (delayed variable evaluation).<br />
  • <cfbreak />
  • </cfloop>

Loop True (delayed variable evaluation).

  • <!--- Loop while true (with hash). --->
  • <cfloop condition="#isTrue#">
  • Loop True (immediate variable evaluation).<br />
  • <cfbreak />
  • </cfloop>

Loop True (immediate variable evaluation).

  • <!--- Loop while true (without variable). --->
  • <cfloop condition="#true#">
  • Loop true (immediate evaluation).<br />
  • <cfbreak />
  • </cfloop>

Invalid CFML construct found on line 1 at column 2. ColdFusion was looking at the following text: true The CFML compiler was processing: An expression beginning with #.

  • <!--- Loop while true as string. --->
  • <cfloop condition="#toString( true )#">
  • Loop true (immediate evaluation as string).<br />
  • <cfbreak />
  • </cfloop>

Loop true (immediate evaluation as string).

  • <!--- Loop while true as string (delayed evaluation). --->
  • <cfloop condition="toString( true )">
  • Loop true (delayed evaluation as string).<br />
  • <cfbreak />
  • </cfloop>

Loop true (delayed evaluation as string).

This is too odd. It's like the immediate evaluation of the data type True (False is the same) simply doesn't translate into a string value that can be used in the delayed-evaluation of the Condition attribute. However, you'll notice that if we run the True data type through the ToString() method first, even with immediate evaluation, it works fine. This has got to be a bug?? Can anyone offer any insight that I'm not thinking about?




Reader Comments

Dec 12, 2009 at 3:49 AM // reply »
7 Comments

does look like a bug...
especially considering delayed evaluation works fine
<cfloop condition="true">


Dec 12, 2009 at 7:31 AM // reply »
12 Comments

This reminds me of a problem I encountered yesterday (and solved with your help). If you create an xml with cfxml, you cant create a cffile on MX7 (CF9 can), except you parse it toString. I know, not really the same, but this may be a bug that some variables are not parsed automatically.

Did you do this on CF9?


Dec 14, 2009 at 8:24 AM // reply »
11,243 Comments

@Roman,

I actually ran this on CF8. I still do most of my R&D on CF8 since we have no CF9 production box yet.


Dec 14, 2009 at 8:37 AM // reply »
12 Comments

Okay, if I find some time this evening, I'll run this script on CF9.. just in case. And to satisfy my curiosity ;-)


Dec 14, 2009 at 8:39 AM // reply »
11,243 Comments

@Roman,

Awesome - sounds like a plan.


Dec 14, 2009 at 3:56 PM // reply »
12 Comments

Ah okay, I tried some things out and I got the same result on CF9. So it doesn't have anything with my problem I had.

After experimenting some time I can't add anything to your discovered problem. This is strange and could be called a bug. I tried about 10 ways to set true as a variable (like <cfset true = 1 /> and so on (yea I know, I'm crazy and it is senseless to try this... but I wanted to :-P)) but this is impossible. So, yea, why doesn't Coldfusion automatically parse the 'true' string?


Dec 14, 2009 at 10:29 PM // reply »
44 Comments

This reminds me of a problem I ran into in CF8 where I used the Java method indexOf() to do array searching in CFML.

arr.indexOf("findMe")

Passing in simple values as seen above would work fine, but when I passed in a field from a query variable, it would always fail.

arr.indexOf(qry.col1) - always returns -1

I had to escape anything within parenthesis using toString() like you did here.

arry.indexOf( toString(qry.col1) )

I think deep down it has something to do with typing. Just when you thought toString() was useless, huh?


Dec 15, 2009 at 6:35 PM // reply »
11,243 Comments

@Roman,

Yeah, the fact that this works:

<cfset x = true />
<cfloop condition="#x#">

... and this fails:

<cfloop condition="#true#">

... seems funky, right? It's just a simple substitution. Unless, the CFSet is actually not copying the actual data type "true", but is, instead converting it to a string value?? Perhaps I'll try CFDumping out the underlying class to see what's going on.

@Jose,

Talking between ColdFusion and Java can definitely hiccup when it comes to data types. I think technically, the query.col reference actually returns the underlying Java record set column object... I know that query[ "col" ] returns an object that can take array functions:

http://www.bennadel.com/blog/167-Calling-Array-Functions-on-ColdFusion-Query-Columns.htm


Dec 18, 2009 at 1:28 PM // reply »
2 Comments

@Ben,

Hi Ben,

First thanks for all your posts. They bring light and clarity to a lot of CF topics.

About this issue, I don't think it's a bug. CF is funky that way. It's just a matter of type and evaluation order which in CF is translated to how we use '', ## or both.
In this case the condition accepts a string or an expression and that's why these will work:

<cfset x = true />

<cfloop condition="x">
<cfloop condition="#x#">
<cfloop condition="'#x#'">

or

<cfloop condition="true">
<cfloop condition="'#true#'">

The fact that <cfloop condition="#true#"> this doesn't work means that we are dobleevaluating the expression and it also means what you said that CF will accept the result of #x# as a string.

This is much like the Evaluate() function. If you run these scenarios with the Evaluate() function it kind of starts to make sense.

The whole topic of the evaluation order and the use of "" and ## is probably the most confusing in CF. There is no clear cut when where and how you use or combine them. Many times the whole process is a black box.
For example since we are talking about cfloop:

<cfset x = StructNew()>

This will work:

<cfloop collection="#x#" item="item">

</cfloop>

and this will not:

<cfloop collection="x" item="item">

</cfloop>

however this will work in a condition loop:

<cfloop condition="x"> (x being an expression/variable that evaluates to true or false or a number or a 'true' 'false' string)

I guess that's the price we have to pay for CF being typeless.


Dec 18, 2009 at 4:17 PM // reply »
11,243 Comments

@Geno,

If you run this code:

<cfset t = true />
<cfdump var="#getMetaData( true ).getName()#" />
<cfdump var="#getMetaData( t ).getName()#" />

... you get the following output:

java.lang.String
java.lang.String

As you can see, both the data type, "true", and the copy of, "true" - t - are being stored as a string value. They are the same data type. As such, I don't think it should follow that:

<cfloop condition="#t#">

... works and:

<cfloop condition="#true#">

... does not.

Maybe there is just something I am not wrapping my head around properly.


Dec 18, 2009 at 4:58 PM // reply »
2 Comments

@Ben,

Good test but the getMetaData( t ).getName() can't be trusted.

If you ran this code:

<cfset t = 1 />
<cfparam name="x" type="boolean" default="true">

<cfdump var="#getMetaData( t ).getName()#" />
<cfdump var="#getMetaData( x ).getName()#" />

You get:

java.lang.String
java.lang.String

Even if you substitute t for 1 as in:

<cfdump var="#getMetaData( 1 ).getName()#" />

You still get:

java.lang.String

However, and this makes this whole thing more interesting, when you ran this:

<cfdump var="#getMetaData( IsBoolean(x) ).getName()#" />

You get:

java.lang.Boolean

If you output the value of the function as:
<cfoutput>#IsBoolean(x)#</cfoutput>

CF returns 'YES'.

Anyway I hope this will be helpful in some way.


Dec 18, 2009 at 5:00 PM // reply »
11,243 Comments

@Geno,

Hmmm. I'm not sure what to even make out of this :) It's like ColdFusion keeps trying to convert all simple data values to String when possible.

I have no answers at this point :)


Post A Comment

Comment Etiquette: Please do not post spam. Please keep the comments on-topic. Please do not post unrelated questions or large chunks of code. And, above all, please be nice to each other - we're trying to have a good conversation here.

Please review the following issues:

Author Name:


Author Email:

Author Website:

Comment:

Supported HTML tags for formatting: <strong>bold</strong>   <em>italic</em>   <code>code</code>







  • Help Wanted - Find Your Next ColdFusion Job
Ben Nadel's Company - Epicenter Consulting Recent Blog Comments
May 23, 2013 at 11:06 AM
Strange Interaction Between DeserializeJson(), ArrayContains(), And Database Values In ColdFusion
@Ben, Are you talking about As Number: YES As String: YES As Java: YES? If so, that's with 3 different ways of referencing the constant 1, not users.id[1]. Query object references(*) are what seem ... read »
May 23, 2013 at 9:55 AM
Strange Interaction Between DeserializeJson(), ArrayContains(), And Database Values In ColdFusion
@Dan, According to the CF Admin, I'm running Java "1.6.0_45". As far as the DB column, in the database it's an INT. I'll see if I can dig into what CF sees it as. @WebManWalking, But h ... read »
May 23, 2013 at 9:49 AM
Strange Interaction Between DeserializeJson(), ArrayContains(), And Database Values In ColdFusion
@Ben, I think the problem is that we're used to loose typing in ColdFusion, like JavaScript. If a value is a number but it's needed in an expression to be a string, noooo problem. I've encountered ... read »
May 23, 2013 at 9:47 AM
ColdFusion QueryAppend( qOne, qTwo )
You rock! Thank you, thank you, thank you!!! ... read »
May 23, 2013 at 5:19 AM
Ask Ben: Print Part Of A Web Page With jQuery
How to print also the background color of table cells and table lines ... read »
May 23, 2013 at 3:55 AM
Javascript Array Methods: Unshift(), Shift(), Push(), And Pop()
very interesting and helpful too. ... read »
May 22, 2013 at 5:35 PM
Script Tags, jQuery, And Html(), Text() And Contents()
This is still an issue 2 years later. jQuery is supposed to remediate these cross browser issues, no? I have been unable to find any statement from the jQuery team calling this behavior "by de ... read »
May 22, 2013 at 12:44 PM
Ask Ben: Query Loop Inside CFScript Tags
In cf10, if you call a function that has: local.result = {}; local.result.msg = ""; local.svc = new query(); local.svc.setSQL("SELECT * FROM..."); local.obj = local.svc.exe ... read »
InVision App - Prototyping Made Beautiful With Prototyping Tools