Yesterday, I posted an Adobe ColdFusion compatible version of my DSL for HTML emails. In that post, I listed
getBaseTagData() as one of the compatibility issues between Lucee CFML and Adobe ColdFusion. It's actually a nuanced issue with several different stumbling blocks; one of which is a strange variable-name error that only gets thrown in Adobe ColdFusion. I figured I'd document that separate in case anyone ever ran into it.
A big part of my DSL (Domain Specific Language) for HTML emails is the communication between parent tags and child tags (which implement and inline cascading styles). As part of that communication, I store data into a shared memory space (shared with the developer). And so, as to reduce the likelihood of variable collisions, I use variable names that are very unlikely to be used by the developer.
For example, I might have a dynamically-generated variable name like:
In Lucee CFML, this variable name - when quoted - is totally fine. However, when I try to save this variable name into the parent tag in Adobe ColdFusion 2018:
<cfscript> parentTag = getBaseTagData( "cf_parent" ); variableName = "$$entity:h1:small-title"; parentTag[ variableName ] = true; writeDump( parentTag ); </cfscript>
... I get the following ColdFusion error:
$$entity:h1:small-titleis not a valid ColdFusion variable name.
Valid variable names must start with a letter and can only contain letter, numbers, and underscores.
I assume this has to do with the fact that ColdFusion custom tags are a little bit magical in terms of how they relate to the "calling context". As such, I suspect that - at least in Adobe ColdFusion - the struct returned from
getBaseTagData() isn't really just a struct, it's a "tunnel" into the context of the parent tag.
We've already covered a divergent behavior in
caller scope assignment between Lucee CFML and Adobe ColdFusion. So, I assume this is a related issue.
To fix this call, we have to explicitly assign the value to the
<cfscript> parentTag = getBaseTagData( "cf_parent" ); variableName = "$$entity:h1:small-title"; // NOTE: This time, I am explicitly referencing the VARIABLES scope in the parent // tag. I'm not relying on Adobe's magical handling of the parent tag context. parentTag.variables[ variableName ] = true; writeDump( parentTag ); </cfscript>
This time, by using
parentTag.variables as my target, the code runs perfectly well in Adobe ColdFusion 2018.
Now, to be clear, this approach breaks Lucee CFML! If we were to run the same code in Lucee CFML, it would store the value into
variables.variables, which is definitely not what we want.
ColdFusion custom tags aren't a hugely popular feature. Before writing my ColdFusion custom tag DSL for HTML emails, I probably hadn't touched them in a couple of years. So, it's not surprising that there are a number of compatibility issues between the two runtimes. It's just something to be aware of when you are coding.
I wonder if this in another place where (the seldom used, at least I rarely use it), setVariable() might solve the issue. There seem to be a lot of weird differences in how ACF/Lucee handle scope assignment and setVariable() seems to behave consistently (at least in my findings) between the two.
Does this work across both?
setVariable('parentTag.' & variableName, true);
It's a good though. I did play around a bit with
setVariable(), but the problem I think is that I can't
use bracket-notation in the variable value. And, I can't use
dot-notation since I have a key that has non-valid variable
characters. So, I could probably get something working if I
made the key a little more "variable friendly". Then, I
setVariable() might work.