4

I came across an interesting scenario today using StructCopy with the URL scope.

I'm not looking for answers on how to get around it - I know/have used structAppend/duplicate etc

I wanted to copy the URL scope to a new struct so I can process/alter it without effecting the URL scope itself, so I used structCopy( url ). I know that structcopy is a shallow copy of the struct, but as my url scope will only contain url params (as far as I know - is this correct? they are all I am interested in this case anyway) which are string key/values then I figured a shallow copy would be adequate (string being immutable and all).

However, when copying the URL scope, it resulted in strange behaviour - it appears as though structCopy(url) just returns the url scope - not a copy of it, not an error. For example, if I perform the following (assume I have url query params, including one called "rob":

<cfset local.clonedUrl = structCopy( url ) />
<cfdump var="#local.clonedUrl#">
<cfdump var="#url#">
<cfset structDelete( local.clonedUrl, "rob" ) />
<cfdump var="#local.clonedUrl#">
<cfdump var="#url#">

In the above scenario, after the struct delete call, the clonedUrl and URL have both had the entry removed (obviously, performing the above with a normal created Struct rather than URL in the first place behaves correctly)

So, my questions are:

  1. what? I have seen that the URL scope is actually an instance of coldfusions URLScope class, so maybe treated differently for that reason, but returning the same instance from a structCopy call is just mean. At very least if it can't do it I would expect an error, not a result that looks very similar to expected but actually exactly the behaviour I want to avoid. Also noticed that if I pass a component to structCopy it appears to have similar results.

  2. What is the URLScope - does it extend Struct? When I dump the classname I see it is a URLScope, but just dumping the object dumps it like it would a Struct. Anyone got any advice for viewing either the sourcecode for the object or at least an API/Javadocs type spec?

I'm using CF10 (I'm not looking for answers on how to get around it - I know/have used structAppend/duplicate etc)

Peter Boughton
  • 110,170
  • 32
  • 120
  • 176
rhinds
  • 9,976
  • 13
  • 68
  • 111
  • 1
    _"Anyone got any advice for viewing either the sourcecode for the object"_ - CF is proprietary; the source code isn't available. (It was apparently taken in an attack last year, but I've not seen it actually available anywhere.) You can of course view the [Railo source](https://github.com/getrailo/railo/) - you should check there to see if the behaviour is the same? – Peter Boughton Feb 18 '14 at 12:38
  • Thanks, thats a shame about no access to the code - even just some detailed API specs/class heirarchy would be nice. Will have a look at the Railo source now. – rhinds Feb 18 '14 at 13:14
  • There are several places where a ColdFusion structure does not really behave like other structures - ever try overwriting a value in the CGI scope? I would hazard a guess the same behavior would exist for the FORM scope as you are seeing for the URL scope. Whenever I have needed functionality like you describe, I simply use `duplicate()` and be done with it. – Scott Stroz Feb 18 '14 at 13:27
  • 1
    (Edit) *pass a component to structCopy it appears to have similar results* What test are you using? `StructCopy` returns a shallow copy, so simple values should be independent. Though nested (complex) objects should be passed "by reference". As far as the URL scope, I imagine the behavior is by design, as URL is a special system scope. Granted, `structCopy` should provide a better indication of the actual behavior, but given your goal of not affecting the original scope, it sounds like `duplicate` is really the function to use anyway. – Leigh Feb 18 '14 at 14:24
  • *does it extend Struct* No. `URL` inherits from coldfusion.runtime.Scope, rather than coldfusion.runtime.Struct. (Just walk the hierarchy by [grabbing the object's SuperClass](http://www.bpurcell.org/blog/index.cfm?mode=entry&entry=925)) – Leigh Feb 18 '14 at 14:39
  • 1
    Agree, duplicate does the job - But it seems to me like stuctCopy should throw an exception if it isn't going to copy the struct for a special reason (such as it being a system scope) - It seems nasty returning the URL scope back, as for all intents and purposes, that looks like it has worked ok and you have a struct with the same values. – rhinds Feb 18 '14 at 14:44
  • 1
    Being as most other places URL is treated like a struct (writeDump url and it is labelled as a struct, pass URL to a function that requires a Struct type argument and it is accepted), and surely the most common use case for cloning a struct being to make changes without modifying the original - structCopy appearing to work but actually handing back the original seems wrong - and dangerous, as unless it results in immediate & obvious bugs it could sting you pretty nastily – rhinds Feb 18 '14 at 14:46
  • 1
    Yeah, poor design decision not to give some indication, but {shrug} not much you can do about it, other than submitting a bug/enhancement request maybe. As Scott mentioned, it is not the only place in which `Scope` behaves differently than a regular structure. *RE: cloning a struct* Well a "true clone" is a deep copy, which is what `duplicate()` gives you, NOT `stuctCopy`. Personally I rarely use the latter because it is known to create a *shallow* copy, which is rarely what is wanted in situations like this. – Leigh Feb 18 '14 at 15:16
  • Yeah, you are right of course. Will just use duplicate. The only reason I switched to give structCopy a try was to see if it improved performance at all (was doing this a bit) and even though I only needed a shallow copy (all String keys & values so immutable) was interested in whether there were any performance costs with using duplicate vs structCopy in the simple case. meh. – rhinds Feb 18 '14 at 15:32
  • Well given that you are only dealing with strings, which are immutable, I would not expect much difference between the two. Both create a new structure, but not the values. So I am guessing there is no measurable performance difference. Especially as the URL scope is unlikely to contain a huge amount of keys anyway. – Leigh Feb 18 '14 at 16:13

1 Answers1

1

Thanks for the comments folks - the conclusion was don't use StructCopy() with the URL object (and possibly on the Form scope object etc). It's pretty grim, but URL isn't technically a struct, so all bets are off. (I moan some more here)

rhinds
  • 9,976
  • 13
  • 68
  • 111