Divergent CALLER Scope Assignment Behavior In Adobe ColdFusion And Lucee CFML 5.3.7.48
In my recent foray into ColdFusion custom tags, I've stumbled upon a divergent behavior between Adobe ColdFusion and Lucee CFML in terms of CALLER scope assignment within a custom tag. Dating all the way back to 2008, I've demonstrated that the CALLER scope is somewhat magical in how it treats variables references; which, allows for a simpler mental model. It seems, however, that in Lucee CFML some of that magical behavior is, well, not as magical.
What I'm referring to is the CALLER scope's ability to be treated more like a "tunnel" into the calling context as opposed to simple "scope". In Adobe ColdFusion, this "tunnel" treats "keys" almost like a deferred value that is evaluated in the calling context. For example, imagine that we have a ColdFusion custom tag that attempts to set a value into the URL scope via the CALLER scope:
<cfset caller[ "url.setViaCaller" ] = "Test 1,2,3" />
<cfexit method="exitTag" />
With a "traditional struct", attempting to use the key, url.setViaCaller, would simply treat the string as an opaque token and assign the key, url.setViaCaller, into whatever the parent struct is. With the CALLER scope, however, keys get a special treatment: instead of being treated as an opaque token, the key url.setViaCaller is evaluated in the calling context.
As such, if we run the following ColdFusion code in Adobe ColdFusion 2018:
<cf_caller_test />
<!--- Output the platform runtime. --->
<cfif server.keyExists( "lucee" )>
<cfdump var="LUCEE: #server.lucee.version#" />
<cfelse>
<cfdump var="ACF: #server.coldfusion.productVersion#" />
</cfif>
<!--- See which scope received the CALLER assignment. --->
<cfdump var="#url#" label="URL" />
<cfdump var="#variables#" label="VARIABLES" />
... we get the following output:
As you can see, assigning url.setViaCaller into the CALLER scope evaluates the string in the calling context. As such, it ends up assigning the key setViaCaller into the URL scope.
Now, if we run this same code in Lucee CFML 5.3.7.48, we get a different output:
As you can see, assigning url.setViaCaller into the CALLER scope treats the string as an opaque token and ends up assigning the key into the VARIABLES scope, not the URL scope.
ASIDE: The
CALLERscope can still act as a "tunnel", it just needs to be more explicit. For example, assigning a value tocaller.url.setViaCaller- using dots-notation only - works the same in Adobe ColdFusion and Lucee CFML.
ColdFusion custom tags don't get used all that often; so, there's a good chance no one else has run into this issue before (Google certainly didn't turn up any matching hits). That said, just something to be aware of as a difference between the two CFML engines.
Want to use code from this post? Check out the license.
Reader Comments
@All,
I filed an incompatibility ticket with Lucee: https://luceeserver.atlassian.net/browse/LDEV-3309
@All,
Small update - possible work-around for consistency. If you use the
<cfparam>tag to assign values into thecallerscope, it works consistently across ACF and Lucee. Meaning, if you have this in a ColdFusion custom tag:... this does not work the same in ACF and Lucee. But, if you have this:
... where you use the
<cfparam>in lieu of direct assignment, this does work consistently in both ACF and Lucee. So, a possible work-around if you need to get something to function properly.Over on Twitter, Dan G. Switzer, II mentioned that this would be a good use-case for the
setVariable()function in ColdFusion. As in:I haven't tested this, but it sounds right.
@All,
This morning, I already made use of the
caller.#key#concept in a code kata in which I create acf_specifyColdFusion custom tag that wraps the nativecfparamtag and exposes more error information:www.bennadel.com/blog/3996-custom-cfparam-tag-that-exposes-error-information-in-lucee-cfml-5-3-7-48.htm
@All,
I ran into this again - if you have a variable "key" that contains invalid variable-name characters, Adobe ColdFusion will throw an error unless you explicitly reference the
variablesscope:www.bennadel.com/blog/4065-strange-variable-name-error-when-writing-to-base-tag-in-adobe-coldfusion-2018.htm
I assume this is a related issue and relates specifically to the fact that the
callerscope is "magical" in Adobe ColdFusion but "just a struct" in Lucee CFML.