Skip to content

Instantly share code, notes, and snippets.

@bennadel
Created August 8, 2019 21:51
Using Function LocalMode Modern To More-Safely Render ColdFusion Templates In Lucee 5.3.2.77
<cfscript>
// Assert the expected values.
// --
// NOTE: Using param in this case as an excuse to declare more variables.
param
name = "categorization"
type = "string"
default = "My Friends" // Will assign this value if not provided.
;
param
name = "friends"
type = "array"
;
// Just creating a mapping as an excuse to declare another variable :D
myFriends = friends.map(
( friend ) => {
return( friend.name );
}
);
</cfscript>
<cfoutput>
<h2>
#encodeForHtml( categorization )#
</h2>
<ul>
<!---
In "classic" ColdFusion mode, the declaration of the iteration item,
"friend", causes "friend" to be stored into the "variables" scope. Depending
on how this template is being used, improper understanding of this behavior
would likely cause a "race-condition" at some point.
--->
<cfloop index="friend" array="#myFriends#">
<li>
#encodeForHtml( friend )#
</li>
</cfloop>
</ul>
</cfoutput>
<cfscript>
/**
* I execute the "template.cfm" ColdFusion template with the given values and return
* the generated output.
*
* NOTE: By using localmode="modern", we are safely capturing any unscoped variable
* assignment in the function's local scope - not the Variables scope.
*/
public string function renderTemplate() localmode = "modern" {
savecontent variable = "local.generatedTemplateOutput" {
// NOTE: The ARGUMENTS scope of this function context will implicitly provide
// passed-in values to the following template evaluation.
include "./template.cfm";
}
return( generatedTemplateOutput );
}
// ------------------------------------------------------------------------------- //
// ------------------------------------------------------------------------------- //
renderedContent = renderTemplate(
friends = [
{ id: 1, name: "Sarah" },
{ id: 2, name: "Jo" },
{ id: 3, name: "Kim" }
]
);
dump( label = "VARIABLES Scope", var = variables );
</cfscript>
<cfscript>
/**
* I execute the "template.cfm" ColdFusion template with the given values and return
* the generated output.
*
* CAUTION: By using localmode="classic" - which is the same as omitting localmode
* altogether - we are allowing unscoped variable assignments to persist to the
* Variables scope.
*/
public string function renderTemplate() localmode = "classic" {
savecontent variable = "local.generatedTemplateOutput" {
// NOTE: The ARGUMENTS scope of this function context will implicitly provide
// passed-in values to the following template evaluation.
include "./template.cfm";
}
return( generatedTemplateOutput );
}
// ------------------------------------------------------------------------------- //
// ------------------------------------------------------------------------------- //
renderedContent = renderTemplate(
friends = [
{ id: 1, name: "Sarah" },
{ id: 2, name: "Jo" },
{ id: 3, name: "Kim" }
]
);
dump( label = "VARIABLES Scope", var = variables );
</cfscript>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment