07.31
In part 1 we set up the Flex SDK and in part 2 we started with the Adobe bug system. Now, since the contributor’s agreement has been approved, it’s time to fix a bug and submit a patch. I’ve figured out a patch for SDK-19385 that I think works well. There was already a patch attempt (SDK-19510) but it was rejected. Fortunately, the reviewers usually explain why they rejected it and may even offer suggestions for a second attempt. I’m working in Eclipse, but any IDE that allows you to debug will make your life easier. So lets get started.
- First make sure you understand the problem. Most bugs are explained in the “Steps to Reproduce” area along with the comments. The test cases we’ll create in the next step will help as well. Don’t feel bad if you look at a bug and feel completely over your head. It’s just means this isn’t the bug for you.
- Set up a test case project. In SDK-19385 there’s already a test case, so we don’t have to rig up our own project. If there’s not a test case, go ahead and upload yours. Even if you can’t come up with a patch, you’ve made it easier for someone else. I added a few more tests to the mxml file to check for the case mentioned in the patch rejection and a case resulting in an infinite recursion loop that the original doesn’t have. Here is my final “test File”:
?Download CompareText.mxml
<?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" creationComplete="testObjectUtilsBug()"> <mx:Script> <![CDATA[ import mx.utils.ObjectUtil; import mx.collections.ArrayCollection; public function testObjectUtilsBug():void { var objA:Object = new Object(); objA['id'] = 'A'; var objB:Object = new Object(); objB['id'] = 'B'; var objC:Object = new Object(); objC['id'] = 'C'; var array1:ArrayCollection =new ArrayCollection([objA,objB,objC ]); var array2:ArrayCollection =new ArrayCollection([objA,objB,objC ]); // these two arrays are identical, so it should pass compare1.text=String(ObjectUtil.compare(array1,array2) == 0); // these two arrays are NOT identical, so it should fail array1 =new ArrayCollection([objA,objB,objC, objC ]); array2 =new ArrayCollection([objA,objB,objC, objA ]); compare2.text=String((ObjectUtil.compare(array1,array2) == 0)); var objA2:Object = new Object(); objA2['id'] = 'A'; // these two arrays are identical (but different objects), so it should pass array1 =new ArrayCollection([objA,objA, objA]); array2 =new ArrayCollection([objA,objA2, objA2]); compare3.text=String((ObjectUtil.compare(array1,array2) == 0)); var objI:Object = new Object(); var objI2:Object = new Object(); objI['i']=objI2; objI2['i']=objI; array1 =new ArrayCollection([objI2]); array2 =new ArrayCollection([objI]); // these two arrays are identical (but infinately loop), so it should pass compare4.text=String((ObjectUtil.compare(array1,array2) == 0)); } ]]> </mx:Script> <mx:Label text="A,B,C == A,B,C (same object)"/><mx:TextInput id="compare1"/> <mx:Label text="A,B,C,C == A,B,C,A (different object, repeat)"/><mx:TextInput id="compare2"/> <mx:Label text="A,A,A == A,A2,A2 (same data, different object)"/><mx:TextInput id="compare3"/> <mx:Label text="I == I2 (infinate)"/><mx:TextInput id="compare4"/> </mx:Application>
- Now that we have our project, compile it with the latest branch and verify it still exists. Bugs are sometimes duplicated and once one is fixed the other is, however there’s nothing to tell anyone to close the second. If the bug isn’t there, go ahead and comment about it being no longer an issue. In this case I ran it against the 3.x branch as Flex 4 is still in it’s volatile stage and isn’t accepting patches.
- I suggest “watching” the bug so it’s on your home JIRA page. It can be horribly irritating if you’ve got a patch but can’t find the bug to apply it to.
- Now that we have a “good” bug, let’s fix it. Rather than recompile the SDK, I’ll work on the SDK class via a monkeypatch. For my bug, I copied the 3.x branch ObjectUtil file to my source code directory under my\utils\ObjectUtil.as and changed CompareTest’s 5th line from
import mx.utils.ObjectUtil;
to
import my.utils.ObjectUtil;
- To have the project compile properly, I also altered the removed the ObjectUtil.as file slightly. I added an “import mx.utils.*” to the import list and removed the line “include “../core/Version.as”;” which simply tracks versions of the SDK. Now I compiled and re-verified the error.
- With the patch, I had a general idea of where to look. Within the ObjectUtil.as code there was a series of lines causing the problem, and I just had to rework some logic to make it happen. Here is the old lines
?Download CompareText.mxml
if (aRef && !bRef) return 1; else if (bRef && !aRef) return -1; else if (bRef && aRef) return 0;
And what I changed them to:
?Download CompareText.mxmlif (bRef && aRef) //if we've seen both a & b already { if (a==b) //The same Object is always equal { return 0; } else { // to avoid an endless loop we'll do a string // comparison of the 2 Object structures. This will // assign generic object numbers and prevent a // recursion loop return stringCompare(toString(a), toString(b)) } }
- So, now that we have a fix, it’s time to move them over to the SDK code. Since I know my changes, I just copy them into the ObjectUtil.as file directly. You may need to adjust your code to follow the Adobe coding conventions and best practices.
- Once we’ve update the source code in the SDK, it’s time to rebuild the SDK and test it out, just like in part 1. If it’s successful, you’re probably home free. It’s just time to make sure your test case builds properly.
- Remove the monkeypatch (I just change my.utils to mx.utils) and rebuild using just the SDK. If the bug is gone, you’re ready to patch!
- Create a patch file. This is a little different for each platform, but for Windows I use TortoiseSVN again.:
- Right click on the branch you fixed (in my case 3.x) and choose SVN Commit
- From the changed files find the files you actual altered. You may see prefs and properties files as well as the unversioned files you built with the SDK.
- Right click on each file and choose “create Patch”
- Save the files where you can remember them
- Back in the bug system, find your issue and open it
- Click “Submit patch” and you’ll be brought to the patch entry screen
- Fill out the form and upload each patch file. Then click “Create”
- Congratulations, you have a new patch! (for me it’s SDK-22491) now you can sit back and wait for it to be accepted
So, where to go for more information? You can try the official forums, the Flexcoders group, or the #flex channel on Freenode. So, other than good karma, what do you get for fixing Flex SDK issues? How about free stuff? For every 3 patches that are accepted you can get an Adobe related book off your Amazon wish list.
Great information. Not sure I’m quite brave enough to send stuff to adobe yet, or to work for free (as the previous guy mentioned), but at least this shows me how to fix an annoying bug in the VScrollbar autorepeat code via this “monkey patch” technique.
Thanks a lot!