Adam Tuttle

Scope Priority Changes in ColdFusion 9

According to the documentation regarding the order in which unscoped variables are evaluated for ColdFusion 8 vs. the documentation for ColdFusion 9, there have been some not insignificant changes in scope priority. Are these typos in the documentation, or have things really been changed?

The first thing I noticed about these two lists was that version 9 lists one more scope than version 8: Query. It does caveat that by saying that Query is not a true scope, but it's good to know that it is specially checked and where in the priority it falls. (In fact, that's why I was checking this in the first place.)

Let's look at the lists side-by-side for comparison purposes. CF8 is on the left, and CF9 is on the right.

CF8 Scope PriorityCF9 Scope Priority

1) We can see that function local variables -- including the new "local" named scope in CF9 -- get top billing in both CF8 and CF9. No change here.

2-3) It looks as if Arguments and Thread Local (not the named "thread" scope) have been swapped. No big deal here, because you can't define a UDF inside a thread, and although you can run a thread inside a function, when you do the thread has a private namespace and doesn't have access to it's parent's (the function's) arguments scope.

So essentially Arguments and Thread Local variables are equals, being interchanged in the priority list where applicable, and ignored where not applicable; and never the twain shall meet.

4) Query was injected into the list here

5-6) Variables and Thread (the named "thread" scope) have been swapped. This is where there might be a problem!

From here on out, the lists are identical; so we'll ignore the rest and assume they're correct. Of course, this 5/6 swap could have been a human error in transposition, so let's write a test to find out if the documentation is correct or if it needs to be addressed.

Unfortunately, this code sample was lost due to technical difficulties. :(

The first time I ran this test, I got these results:

Inside thread:
local
*thread local has been found - can't be deleted.

Outside thread:
variables
Could not find any more instances.

ref thread externally by thread name: thread

This test confirmed that the thread-local scope is first priority among the 4 being tested (thread-local, thread-named, attributes, variables), as the documentation says it should be. Great! Unfortunately, I can't delete that variable once it's been set (even doing structDelete(local, 'foo') in CF9 didn't work -- the thread local scope is NOT the same as the function local scope!) So to get around this limitation, I comment out my local variable and hard-code in the result where it would fall based on the results of test #1.

With that done, here are the results of re-running the page:

Inside thread:
local
attributes
variables
Could not find any more instances.

Outside thread:
variables
Could not find any more instances.

ref thread externally by thread name: thread

What do these results mean, as far as the exact order that ColdFusion uses for our 4 scopes in question (again: thread-local, thread-named, attributes, variables)? I ran my test on both ColdFusion 8 and 9 and the results were the same.

  1. Function Local (if inside a function) or Thread Local (if inside a thread)
  2. Attributes (if inside a thread)
  3. Variables

Wait, what?!

So thread-named doesn't make the list at all. The documentation says both on the general scope priority page and the thread scopes page (and this is carried over to the CF9 documentation as well) that thread scope should be available to the creating page; but in my testing, it isn't available to the creating page at all (trying to dump #thread# throws an exception) and it is not checked when evaluating unscoped variables. It is shared between running threads, that much is true; but it doesn't seem possible to use thread.someVar to access data that was set inside the thread. That said, you can use [threadName].someVar as I do in my test above, so it's not a total loss. But I'd call it a bug. Would you agree?

In addition, and although documented on the Using Thread Data pages in the CF8 and CF9 documentation, Attributes is not mentioned on the general scope priority documentation (for either version). Attributes is also a scope available in custom tags, but (and I tested this!) it is not checked when evaluating unscoped variables inside a custom tag.

So I think that leaves the final tally for scope priority as such:

  1. Function Local (if inside a function) or Thread Local (if inside a thread)
  2. Attributes (if inside a thread)
  3. Query
  4. Variables
  5. CGI
  6. Cffile (if an applicable CFFile tag was used)
  7. Url
  8. Form
  9. Cookie
  10. Client (if client variables are enabled)

Wow, that turned out to be much deeper of a rabbit hole than I was expecting when I started out. Glad to have it sorted out, though.

7 responses:

Dale Severin

Dale Severin

What happened to the Request, Session, and Application scopes?
Adam Tuttle

Adam Tuttle

Dale, those scopes (and others, like Server) are still there. They have not historically been checked in the event of an unscoped variable reference (and remain that way), so there was no point mentioning them here.
Dale Severin

Dale Severin

I always thought that Request, Session, Application, and Server scopes were checked for unscoped variables. Thanks for the clarification.
Chandan Kumar

Chandan Kumar

Arguments is wrongly placed at 2, thread local is similar to function local and it should take the priority in any unscoped searches. Thread named variables are not searched for unscoped searches, however you can always use it using the thread name as scope.

And thread scope mentioned in the list keeps thread names of all the threads. In example above it will have testThread in it. It does not keep named thread variables with it.

HTH,
Chandan
Adam Tuttle

Adam Tuttle

@Chandan Kumar, thanks for the extra clarification. Indeed, I had removed Arguments from my final list; and it's good to know that the scope named "thread" keeps a list of the thread names that are available; I can see that being handy.

Is the documentation going to be updated accordingly?
Ben Nadel

Ben Nadel

Adam, great article. I was trying to demo some stuff that Elliott Sprehn did in his CFUNITED preso and I realized (after 15 minute) that I couldn't do it because of these differences you have outlined:

http://www.bennadel.com/blog/1994-Overriding-Internal-ColdFusion-Component-Variables-With-Method-Arguments.htm

It looks like it was the ColdFusion 8 documentation that was inaccurate; ColdFusion 9 finally implements the scope precedence that the documentation reflects.

Thanks!
Rob Nikkel

Rob Nikkel

I think the introduction of this new scope (query - variables in query loops) has caused an issue. If you have a query with a column named "application" and loop through it, you will find that your actual application scope gets lost within the request. Yikes! I'm going to submit a ticket with Adobe.

Rob

Your comment:

Leave this field empty: