Twitter: raymondcamden


Address: Lafayette, LA, USA

Bug with ColdFusion 11's Elvis Operator

09-04-2014 2,212 views ColdFusion 14 Comments

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

14 Comments

These comments will soon be imported into Disqus. To add a comment, use Disqus above.
  • Commented on 09-05-2014 at 3:07 AM
    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
  • Commented on 09-05-2014 at 8:09 AM
    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
  • Commented on 09-05-2014 at 8:10 AM
    Why though? I'm using encodeForHTML because I don't trust url.name. I trust the result of getfoo to be safe for already.
  • Commented on 09-05-2014 at 8:11 AM
    (to be safe to display I mean)
  • Commented on 09-05-2014 at 8:13 AM
    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
  • Commented on 09-05-2014 at 8:13 AM
    Weird - I didn't see that. Testing again.
  • Commented on 09-05-2014 at 8:15 AM
    No, I don't get an error. Just to be precise, here is a gist of what I'm running.

    https://gist.github.com/cfjedimaster/cfb2202b9ed80...

    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.)
  • Commented on 09-05-2014 at 8:51 AM
    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
  • Commented on 09-05-2014 at 8:59 AM
    Adam, I thought you said it was a bug with encodeForHTML?
  • Timothy Farrar #
    Commented on 09-05-2014 at 1:13 PM
    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>
  • Commented on 09-05-2014 at 1:15 PM
    @Timothy: I'm confused - isn't this just what the blog said? Are you trying to show something different?
  • Timothy Farrar #
    Commented on 09-05-2014 at 1:20 PM
    My point was that it not only always runs both sides, but that it runs the right hand side before the left hand side.
  • Timothy Farrar #
    Commented on 09-05-2014 at 1:22 PM
    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.
  • Commented on 09-12-2014 at 10:04 AM
    The bug is now fixed.