Dec 31, 2009

Is this an issue with the local scope in ColdFusion 9?

Consider the following:

Demo1:
Run it.


Demo2:
Run it.


With ColdFusion 9 local is supposed to be private to the method. In Demo 2 the code behaves as expected but in Demo 1 the local in the variables scope is over written.

I consider this a bug with the local scope but I'd like some feed back.

BTW how did I find this? A friend on mine had code similar to the example and was wondering why local went blank half way through a page. I tracked it back to a UDF that had:

cfset local = {}

OK so calling a variable in a .cfm local not all the common but it could ( and did ) happen.

Thoughts?

27 comments:

  1. Ignore the < br />'s the syntax highligter adds them and I havn't got around to fixing it yet.

    ReplyDelete
  2. Paul, this is not a bug. However it is pretty silly code if you are setting the local scope to a struct.

    ReplyDelete
  3. Nice find.. Also, to add another angle to this issue. If you do this:



    in the function it blanks the struct entirely.

    ReplyDelete
  4. @Dave

    Sorry Blogger strips out the tags.

    I assume you did:

    cfset local = ""

    ReplyDelete
  5. Dang it.. code wiped.. should have been:

    <cfset local = '' />

    ReplyDelete
  6. Paul, I think your problem is that in example one, you are not actually altering the local scope, but a variable called local. If you look at Ben Forta's blog entry from back in June http://forta.com/blog/index.cfm/2009/6/21/The-New-ColdFusion-LOCAL-Scope, if you define a variable called var local, you are actually creating a variable Local.local. Since you did not var the local variable name, you are creating the local variable in the variable scope variable.local, which would overwrite your original value.

    Dean

    ReplyDelete
  7. @Dean

    That's not correct

    < cfset var local /> within a method in ColdFusion 9 is ignored. It dosn't create local.local

    ReplyDelete
  8. @Paul,

    I misspoke, apparently this changes since the release. However on those same lines, if you name a variable called local without the var keyword (which apparently is ignored anyway), it places it into the variable scope.








    Either way, it's odd behavior.

    ReplyDelete
  9. Interesting... I just tried setting one of the other scopes to an empty structure and it treated it the exact same way.

    URL = {}

    When I dumped the variable scope it was located there. I don't know if this is something new to CF9 or if it has always treated direct setting of protected structure (without key names) in this manner.

    ReplyDelete
  10. Both demos worked as expected on my machine.

    ReplyDelete
  11. Its not a bug because you need to understand what you are doing.

    This may change with the release of updater 1, but here is what you are doing. In the CFM page you are defining a local scope to a struct. ColdFusion has in its wisdom made a decision that it will convert this to a variable, and place it into the variables scope.

    In you function because the scope doesn't exist, you are referencing the variable as variables.local.name without the variables scope.

    Does that make more sense!

    Sorry I went Annonymous before, because it refused to save my comment, by throwing an error.

    ReplyDelete
  12. But in my function which is CF9 local always exists? Its a scope so it has to exist?

    ReplyDelete
  13. Paul,

    If you set local to a struct you are defining it back to the variables scope. That is by design.

    ReplyDelete
  14. Consider this:

    < cfset request = {} /> or < cfset session = {} />

    It's ignored as thats nto that way to clear a scope.

    Why if local is a scope withing a method is

    < cfset local = {} /> behaving different to the way all scopes are treated?

    ReplyDelete
  15. Because Adobe wanted to be backward compatible on this, and chose to try to be smart about it. Unfortunetly they got it wrong.

    This is also tied to the local bug described on a few blogs a few months ago.

    I would say it is related, but the local scope is different to other scopes. Due to trying to be backward compatable.

    If you ran this over a line debugger, you would see the problem that Adobe tried to address here.

    ReplyDelete
  16. OK I see so it's intended then by Adobe for compatibility its just mighty confusing :)

    I think I'm going to stick with leaving :

    < cfset var local = {} />

    At the top on my methods just incase ( also so it will work on other engines ).

    ReplyDelete
  17. Or just dont reset the local scope to a struct, there is no need to do that in a function with the local scope.

    Why you even tried is beyond me.

    But as I said you may find it fixed, in CF 9 updater 1, because of the local bug blogged a few months ago.

    But like I stated,

    set local = {} says I am setting the variable local into the variables scope.

    Where var local = {} says you are then creating a local.local variable instead.

    And yes it is confusing if you don't understand what is happening.

    ReplyDelete
  18. @Glen I didn't try LOL I was working with someone who said "Why did local just become empty half way down the page?" I tracked it down to this. By var scoping local = {} in the UDF or simply removing the line local = {} its worked fine.

    Also < cfset var local = {} /> In a method will not create local.local its simply ignored by the engine.

    ReplyDelete
  19. Explain ignored Paul!!

    ReplyDelete
  20. Sure:

    < cfscript>

    tester();

    void function tester() {
    var local = {};
    local.name = "Paul";
    writeDump(local);
    }



    There is no local.local created see: http://cf9.kukiel.net/demos/local/demo3.cfm for the output.

    ReplyDelete
  21. Paul,

    If this is ignored, then why can I do this?

    var local = {firstName='Glen', lastName='dunlop');

    How is it being ignored then, the engine is basically taking the line and converting it to a private scope for the function. This is not what I would call being ignored.

    ReplyDelete
  22. Your correct seems it's not ignored.

    But var local = {} doesn't create local.local but that's a different story. I think I'm happy with the original issue not being a bug but an intended outcome. Regardless it was an interesting journey to back track the original issue to this and goes to show why scoping is important.

    ReplyDelete
  23. Actually it does.

    Lets take this example inside a function for a minute.

    local.test = {firstName='Glen', lastName='dunlop');
    writeDump(local);

    This will dump the local scope out.

    Now lets take these lines
    var local = {firstName='Glen', lastName='dunlop');
    writeDump(local);

    It too will dump the local scope out.

    So what is hapenning here is that, its easy to assume and I had to double check this myself. But in a sense you are typing local.name, and you are referencing it from the local scope. However you can't dump local.local, because the engine is smart enough to know what you are asking from it.

    But it boils down to that this is not a bug, and it is working as expected.

    ReplyDelete
  24. Interesting. I guess what we think and what is really happening behind the scene can be 2 different things. Thanks for taking the time.

    ReplyDelete
  25. Here is a follow up:

    http://blog.kukiel.net/2009/12/coldfusion-9-and-local-scope-continued.html

    ReplyDelete
  26. to add another angle to this issue. If you do this: in the function it blanks the struct entirely.

    if you are looking for a cheap vps that is reliable and the uptime is 99.9%

    ReplyDelete