Friday 1 November 2013

CFML: More on inappropriate use of <cfinclude>

G'day:
I didn't expect to be revisiting this topic - let's face it, it's definitely "slow news day" material - but Ryan Guill, who I chat to on IRC, put me onto this one, and it was intriguing enough to follow-up.

And it's a slow news day.

So previously I wrote this article: "<cfinclude> and JavaScript", which discussed what happens when a non-CFM file gets included.

Disclaimer:

Just in case it's not abundantly apparent from the title of the article or the observations I make as I go: I do not mean this exercise to suggest I recommend the practice detailed below.


Ryan's variation on this is what happens when including a CFC file. Interesting. So I tried that:

<!--- WithComponentTags.cfc--->
<cfcomponent>
    
    <cfscript>
        variables.localToCfc = "true";
        this.publicToCfc = "true";

        public void function f(){

        }
    </cfscript>

</cfcomponent>

<!--- doIncludeOfCfcAsCfc.cfm --->

<cfinclude template="WithComponentTags.cfc">

<cfdump var="#variables#">

So here I have a basic CFC, and simply <cfinclude> it from a CFM file. I kinda half expected this to error with "you're too thick for words, mate". but it "works". Well it compiles and does something:


struct
F
function f
Arguments:none
ReturnType:void
Roles:
Access:public
Output:
DisplayName:
Hint:
Description:
LOCALTOCFCtrue
THIS
struct
PUBLICTOCFCtrue

So basically it just ignores the <cfcomponent> tags and one ends up with the functions/variables created in the variables scope of the calling code. So kinda like importing a UDF library, I guess. I can see how this has a kind of merit.

Next Ryan got me to rename the file with a non-CFC extension: as a .txt file. And I changed the include statement accordingly, and re-ran the code:

Invalid CFML construct found on line 2 at column 1.

ColdFusion was looking at the following text:<
The CFML compiler was processing:

    < marks the beginning of a ColdFusion tag.Did you mean LT or LTE?
The error occurred inC:/Apps/Adobe/ColdFusion/10/cfusion/wwwroot/scribble/shared/git/blogExamples/cfml/cfinclude/WithComponentTags.txt: line 2
1 : <!--- WithComponentTags.txt --->
2 : <cfcomponent>
3 :  
4 :  <cfscript>

And on Railo we get a slightly more elucidating error:

MessageWrong Context, cfcomponent tag must be inside a file with extension cfc
StacktraceThe Error Occurred in
C:\Apps\railo-express-jre-win64\webapps\railo\www.scribble.local\shared\git\blogExamples\cfml\cfinclude\WithComponentTags.txt: line 2 
1: <!--- WithComponentTags.txt --->
2: <cfcomponent>
3: 
4: <cfscript>
called from C:\Apps\railo-express-jre-win64\webapps\railo\www.scribble.local\shared\git\blogExamples\cfml\cfinclude\doIncludeOfCfcAsTxt.cfm: line 3 

So what seems to be happening is that ColdFusion (and Railo behaves this was too), has a "special behaviour" when including a CFC: it explicitly imports it as a UDF lib. But this behaviour is clearly keyed on the file extension, not the code. Because when the file has a .txt extension, the compiler tries to treat it as a .cfm file, and sees the <cfcomponent> tags and borks. It's important to note that the behaviour with a .txt file is the same as if it had a .cfm file: one cannot have <cfcomponent> tags in a .cfm file. So there is definitely a specifically different behaviour for compiling CFC files. But not necessarily CFCs (if you see what I mean: the former is a file-extension consideration, the latter is a source code one).

Anyway... not the most interesting thing to find out, but did kill 28min of my lunchtime.

Now back to my JQuery course @ CodeSchool.com. And a sandwich.

--
Adam