Andy Jarrett // Code. Develop. Create.

Understanding Variable Scoping Differences Between Lucee 5 and Lucee 6

Computer with code
Photo by Brina Blum on Unsplash

From a conversation on the Working Code Podcast Discord channel I came across a change between Lucee 5 to Lucee 6, and how variables are scoped and handled, specifically when/if using var in a .cfm template. This post is just the sample code I used to do some digging on how the scoping differences between the two versions using a simple test cases to show the different outcomes

Test Scenario

Here are my test files, var.cfm and varinclude.cfm.

var.cfm (main template):

<cfscript>
  var a = "a";
  b = "b";
  local.c = "c";

  dump(a); // Output: "a"
  dump(b); // Output: "b"
  dump(c); // Output: "c"
  dump(local.c); // Output: "c"

  cfinclude(template="varinclude.cfm");
</cfscript>

varinclude.cfm (included template):

<cfscript>
  dump(a); // Output: "a"
  dump(b); // Output: "b"
  dump(c); // Output: "c"
  dump(local.c); // Output: "c"
</cfscript>

This setup works well on Lucee 5, where:

  • The var keyword is used to declare variables with function-local scope, even outside functions.
  • The variable b is implicitly scoped to the current page.
  • The local scope is explicitly used for c.

Results on Lucee 5

On Lucee 5, the following outputs occur:

  • dump(a); outputs "a".
  • dump(b); outputs "b".
  • dump(c); outputs "c".
  • dump(local.c); outputs "c".
Output results

The included template (varinclude.cfm) inherits these variables, and everything behaves as expected. This is because, in Lucee 5, var declarations work even outside of functions.

Behaviour in Lucee 6

When upgrading to Lucee 6, however, some changes in scoping rules cause issues:

  1. Using var outside a function:

    <cfscript>
      var a = "a"; // This line fails with "Can't invoke key A, Local Scope can only be invoked inside a Function"
    </cfscript>
    

    In Lucee 6, the var keyword is now restricted to function scopes, and attempting to use it outside a function will result in an error. This is a notable shift from Lucee 5.

    Output results

  2. Accessing c without scoping:

    <cfscript>
      dump(c); // This line fails with "variable [C] doesn't exist"
    </cfscript>
    

    Lucee 6 enforces stricter scoping rules. Without explicitly declaring c in a shared scope (such as local.c), it's no longer accessible in the same way as in Lucee 5.

    Output results

TL;DR

When migrating from Lucee 5 to Lucee 6, developers need to be aware of the stricter scoping rules. var is now restricted to function scope in Lucee 6. Attempting to use it outside of a function will result in an error.

I’m here, learning and working away. If you liked this content and want to keep me going, consider buying me a coffee. Your support keeps this site running and the coffee brewing! ☕️