Ok, snap quiz time, given the following code, and that url.name exists, will the UDF run?
function getfoo() {
writeoutput("do you see me?");
return "foo";
}
u2 = encodeForHTML(url.name) ?: getfoo();
Ok, time's up. If you said it wouldn't run, because, of course, it doesn't need to, then you would be wrong. Even when url.name exists, getfoo() is executed. Now, in some ways, this is consistent with cfparam's behavior. But to me, that always made sense. When I see this: <cfparam name="url.name" default="#getfoo()#">
- I always figured the compiler had to run getfoo to get the value to cfparam so cfparam could then work. Maybe you don't agree - and that's cool - but it makes sense to me.
In the case of the Elvis operator though it does not make sense. As an FYI, both Railo and Groovy ignore the right hand side when they don't need it.
Bug: 3818770
Archived Comments
The thing with CFPARAM does make sense after a fashion, but it still catches people out.
I do think when the CFML is being compiled it should be compiled down in such a way that the default attribute value is *not* executed unless it's needed, but I see how they've taken a generic approach to processing tags, which does mean all values need to be resolved before they're passed into the tag's actual code. Tag attributes are basically function arguments.
However there's no way that that quirk of how *tags* need to work should filter down into the ?: implementation. That's just wrong.
Cheers for raising the bug, Ray.
--
Adam
As per Twitter... Matt Busche noticed that you've got yer () misplaced in that sample. This:
u2 = encodeForHTML(url.name) ?: getfoo();
Should be this:
u2 = encodeForHTML(url.name ?: getfoo());
But your point still stands.That's just a typo.
--
Adam
Why though? I'm using encodeForHTML because I don't trust url.name. I trust the result of getfoo to be safe for already.
(to be safe to display I mean)
Yeah, but this will fail if url.name doesn't exist:
encodeForHTML(url.name)
And... it does fail. I'm not just making this up.
--
Adam
Weird - I didn't see that. Testing again.
No, I don't get an error. Just to be precise, here is a gist of what I'm running.
https://gist.github.com/cfj...
i test with and without name being defined in the QS and I never get a runtime error. (I do get the bug with RHS of course.)
Yeah, as per IRC discussion... you done found ANOTHER bug with ?: on CF (I was testing on Railo, which works properly). For the sake of others reading along, THIS should error:
encodeForHTML(url.name)
when url.name doesn't exist. So it doesn't matter that the next part of the expression has a ?:, because the code should already have errored out.
--
Adam
Adam, I thought you said it was a bug with encodeForHTML?
Run the following code... pretty sad!
Not only does it run the second one first.
<cfscript>
function a(){
writeDump('a');
return 'a';
}
function b(){
writeDump('b');
return 'b';
}
test = a() ?: b();
</cfscript>
@Timothy: I'm confused - isn't this just what the blog said? Are you trying to show something different?
My point was that it not only always runs both sides, but that it runs the right hand side before the left hand side.
Perhaps this is what you were showing in your blog post, but I missed that. With the above code, I get 'b a' as output. I would have expected at least 'a b' to come back.
The bug is now fixed.