Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Strange behaviour of coldfusion arguments surviving outside function?

Tags:

I have programmed ColdFusion for over 15 years, but never came across this. Here's a code to replicate the behaviour:

<cfset _run()>
<cffunction name="_run">
  <cfset variables.dataArray=ArrayNew(1)>
  <cfset local.data={
    area="profile"
  }>
  <cfset _append(data=local.data,field="name")>
  <cfset _append(data=local.data,field="phone")>
  <cfdump var="#variables.dataArray#" label="dataArray">
</cffunction>
<cffunction name="_append">
  <cfargument name="data" type="struct" required="yes">
  <cfargument name="field" type="string" required="yes">
  <cfdump var="#arguments#" label="arguments">
  <cfset arguments.data.field=arguments.field>
  <cfset ArrayAppend(variables.dataArray,arguments.data)>
</cffunction>

As you can see this is what I do:

  1. Initing an array in the variables scope to make it globally accessable
  2. Initing a struct (local.data) in the local scope
  3. Appending first field item (name) by invoking the data to the _append function
  4. Appending second field item (phone) in the same manner

This code will result in the following output:

Dump of output

As you can see, the code results in an array with duplicate entries, when you might expected that the first index should have field="name". As you also can see, the value of data that is invoked to _append the second time, contains the property "field" with the value "name". It seems to linger in the arguments scope from the first time we called the function? How is this possible. I thought the arguments scope was isolated to inside the cffunction tag?

But if I replace the _append function with this:

<cffunction name="_append">
  <cfargument name="data" type="struct" required="yes">
  <cfargument name="field" type="string" required="yes">
  <cfdump var="#arguments#" label="arguments">
  <cfset local.data=Duplicate(arguments.data)>
  <cfset local.data.field=arguments.field>
  <cfset ArrayAppend(variables.dataArray,local.data)>
</cffunction>

it will give the following output:

Dump of output 2

As you can see, making a duplicate of the arguments.data before appending "field" to it, solves the problem. Note that just doing:

<cfset local.data=arguments.data>

was not enough.

Can someone explain this behaviour of the arguments scope?

like image 344
Jörgen Lundgren Avatar asked Dec 15 '17 11:12

Jörgen Lundgren


1 Answers

So after some research, I found this on Adobe Coldfusion Documentation Page (Bolding of text done by me):

About the Arguments scope

All function arguments exist in their own scope, the Arguments scope. The Arguments scope exists for the life of a function call. When the function returns, the scope and its variables are destroyed. However, destroying the Argument scope does not destroy variables, such as structures or query objects, that ColdFusion passes to the function by reference. The variables on the calling page that you use as function arguments continue to exist; if the function changes the argument value, the variable in the calling page reflects the changed value.

This was an eye opener for me, and it will keep me out of trouble in the future :)

like image 161
Jörgen Lundgren Avatar answered Sep 23 '22 13:09

Jörgen Lundgren