tracker issue : CF-4199892

select a category, or use search below
(searches all categories and all time range)
Title:

[ANeff] Bug for: CF passes date by reference

| View in Tracker

Status/Resolution/Reason: To Track//PRNeedInfo

Reporter/Name(from Bugbase): Aaron Neff / Aaron Neff ()

Created: 10/03/2017

Components: Language, DateTime Functions

Versions: 2016,2018

Failure Type: Incorrectly functioning

Found In Build/Fixed In Build: 2016.0.01.298513 /

Priority/Frequency: Normal / Some users will encounter

Locale/System: / Win All

Vote Count: 1

Issue: CF passes date by reference

Repro:

<cfscript>
  function myFunction(required date myDateTime) {
      ARGUMENTS.myDateTime.setYear(2018);
  }
  myDateTime = createDate(2017,1,1);
  myFunction(myDateTime);
  writeOutput(myDateTime);//returns {ts '2018-01-01 00:00:00'} (bug - year should remain 2017)
</cfscript>

Actual Result: {ts '2018-01-01 00:00:00'}

Expected Result: {ts '2017-01-01 00:00:00'}

Attachments:

Comments:

@Aaron This is an expected behavior as an object as an argument works like a call by reference . For primary data types and string, it works as call by value, just like java.    
Comment by Dattanand M.
29750 | October 01, 2018 05:40:52 AM GMT
Hi Dattanand, Simple values, like date-time objects, must pass by value? Please see: https://helpx.adobe.com/coldfusion/developing-applications/building-blocks-of-coldfusion-applications/writing-and-calling-user-defined-functions/working-with-arguments-and-variables-in-functions.html What am I missing? Thanks!, -Aaron
Comment by Aaron N.
29751 | October 01, 2018 06:52:20 PM GMT
Hello? Date-time objects are simple values. Simple values pass by value. https://helpx.adobe.com/coldfusion/developing-applications/building-blocks-of-coldfusion-applications/writing-and-calling-user-defined-functions/working-with-arguments-and-variables-in-functions.html Why do I even have to explain this? Thanks!, -Aaron
Comment by Aaron N.
29803 | October 18, 2018 06:42:02 AM GMT
Hello Aaron, Yes, there is inconsistency in documentation and the way setter methods are implemented. We want setter methods to work as call by reference only therefore to avoid this inconsistency we will be changing documentation soon. thanks
Comment by Ajay R.
29838 | October 24, 2018 12:07:19 PM GMT
Hi Ajay, The documentation is correct. Date-time is always "simple" / "pass-by-value". Otherwise, confusion/corruption. Please see Actual vs Expected: https://cffiddle.org/app/file?filepath=c7701ad4-90f4-4dc8-9173-dada7aa18d22/ae8930de-3c3c-439c-8c3e-0f9bed34a32b/32c5b3b2-3f92-46d7-9ba7-493f3cf292b6.cfm Thanks!, -Aaron
Comment by Aaron N.
29851 | October 26, 2018 06:17:05 AM GMT
Hello Aron, As I mentioned in last comment that setter methods are implemented to work as "call by reference" and we want setters to work in that way only. Coming to your example :- *Good Case:* myDateTime1 = createDateTime(2017) myDateTime2 = myDateTime1.add("h", 1).setYear(2018)//good When you call add() method first then as it works as "call by value" so add() will return a object with new reference that is not same as "myDateTime1" (lets say new reference is newMyDateTime1. As you are calling setYear() method after add()  so it will change the year of newMyDateTime1 not myDateTime1. *Bug Case:* myDateTime3 = createDateTime(2017) myDateTime4 = myDateTime3.setYear(2018).add("h", 1) When you call setYear() method first it will change year of myDateTime3 (as it is "call by reference"). After setYear you are calling add() that will return newly reference object as it is  "call by reference".   *Final Conclusion* : setter methods are "pass by reference" and we want it to be that way but it does cop up with documented behavior.
Comment by Ajay R.
29854 | October 26, 2018 06:39:20 AM GMT
Hi Ajay, Yup, I realize all that. I'm saying Date-Time should basically be immutable. Otherwise, confusion/corruption. Let's say an array is set earlier in the code: <cfset myArray = ["1/1/2017","2/1/2017"]> ….then, somewhere later in the code (even within another .cfm or .cfc or UDF body), the array is used: <cfscript> for(stringDate in myArray) { writeOutput(stringDate.setYear(2018)) } writeDump(myArray) </cfscript> Then, in future, that 1st line is changed to: `<myArray = [createDateTime(2017,1),createDateTime(2017,2)]>` and then the other code starts breaking. Then, we hear: "my code used to work, why doesn't it work no more??" See? Thanks!, -Aaron
Comment by Aaron N.
29858 | October 26, 2018 09:47:56 PM GMT
https://tracker.adobe.com/#/view/CF-3374275 fix was incorrect wrt the .set_() member functions.
Comment by Aaron N.
29862 | October 27, 2018 02:49:20 AM GMT
.setYear() ignores final keyword ;)
Comment by Aaron N.
29863 | October 27, 2018 03:08:30 AM GMT
Fun will be when a per-app setting is introduced to cause deserializeJSON() to deserialize ISO8601 strings to date-time. Sit back. Grab popcorn.
Comment by Aaron N.
29864 | October 27, 2018 03:11:27 AM GMT
CF auto-casts between java.lang.String or coldfusion.runtime.OleDateTime behind-the-scenes. CF doesn't permit us to *force* a date's underlying data type. Additionally, a UDF datetime argument allows any java.lang.String that can be cast-to-date. Thusly, `foo.setYear(2018)` must always behave the same, regardless if foo is java.lang.String or coldfusion.runtime.OleDateTime. It currently _doesn't_, when using .setYear() etc, and that's the bug.
Comment by Aaron N.
29865 | October 27, 2018 03:21:52 AM GMT
Hi Adobe, I am requesting that more members of the ColdFusion team read my last few comments on this ticket. Usage of DateTime setter methods leads to silent corruption when their input DateTime variable's type changes from String to OleDateTime. THIS MUST NOT HAPPEN! Either: 1) CF must stop auto-casting between java.lang.String and coldfusion.runtime.OleDateTime -or- 2) The DateTime setter methods must be 'pass by value' w.r.t. their input DateTime variable Thanks!, -Aaron
Comment by Aaron N.
31212 | August 26, 2019 06:37:25 AM GMT