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
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 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
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. -
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 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.