Understanding Variable Scoping Differences Between Lucee 5 and Lucee 6
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
varkeyword is used to declare variables with function-local scope, even outside functions. - The variable
bis implicitly scoped to the current page. - The
localscope is explicitly used forc.
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".
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:
-
Using
varoutside 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
varkeyword 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.
-
Accessing
cwithout scoping:<cfscript> dump(c); // This line fails with "variable [C] doesn't exist" </cfscript>Lucee 6 enforces stricter scoping rules. Without explicitly declaring
cin a shared scope (such aslocal.c), it's no longer accessible in the same way as in Lucee 5.
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.