diff --git a/frameworks/projects/XML/src/main/royale/XML.as b/frameworks/projects/XML/src/main/royale/XML.as index b589b7e7b2..b94b87471b 100644 --- a/frameworks/projects/XML/src/main/royale/XML.as +++ b/frameworks/projects/XML/src/main/royale/XML.as @@ -2464,6 +2464,8 @@ package * @param value * @return * + * @royaleignorecoercion XML + * */ public function replace(propertyName:Object, value:*):* { @@ -2502,8 +2504,30 @@ package replaceChildAt(idx, value); return this; //to step 4 above } - //@todo step 5+ above... - return null; + var n:QName = toXMLName(propertyName); //step 5 above + var i:int = -1; // step 6, using -1 instead of undefined + var k:uint = childrenLength() - 1; + var replaceChild:XML = null; + for (;k > -1;k--) { //step 7 + var childK:XML = (_children[k] as XML); + if ( //step 7a + ((n.localName == "*" ) || ((childK.getNodeRef() == ELEMENT) && (childK.localName() == n.localName))) + && ((n.uri == null) || ((childK.getNodeRef() == ELEMENT) && (childK.name().uri == n.uri))) + ){ + if (i != -1) { + deleteChildAt(i); //step 7a.i + xml$_notify("nodeRemoved", this, replaceChild, null); + } + i = k;//step 7a.ii + replaceChild = childK; + } + } + if (i == -1) return this; //step 8, using -1 instead of undefined + _internalSuppressNotify = true; + replaceChildAt(i, value); + _internalSuppressNotify = false; + xml$_notify( "nodeChanged" , this, _children[i], replaceChild); + return this; } /** @@ -2869,6 +2893,7 @@ package childIdx = chldrn[0].childIndex(); len = chldrn.length() -1; + var origFirstChild:XML = null; _internalSuppressNotify = true; for (i= len; i >= 0; i--) { @@ -2883,6 +2908,8 @@ package _internalSuppressNotify = false; xml$_notify("nodeRemoved", this, chldrn[i], null); _internalSuppressNotify = true; + } else { + origFirstChild = chldrn[i]; } } _internalSuppressNotify = false; @@ -2908,7 +2935,11 @@ package } _internalSuppressNotify = false; // legacy behavior is to send first child only, but with post-everything-added "this" - if (len > 0) xml$_notify("nodeAdded", this, firstChild, null); + //if (len > 0) xml$_notify("nodeAdded", this, firstChild, null); + + if (len > 0) { + xml$_notify(origFirstChild ? "nodeChanged" : "nodeAdded", this, firstChild, origFirstChild); + } } return this; diff --git a/frameworks/projects/XML/src/test/royale/flexUnitTests/xml/XMLNotificationTest.as b/frameworks/projects/XML/src/test/royale/flexUnitTests/xml/XMLNotificationTest.as index be1b834151..02b18f6a4e 100644 --- a/frameworks/projects/XML/src/test/royale/flexUnitTests/xml/XMLNotificationTest.as +++ b/frameworks/projects/XML/src/test/royale/flexUnitTests/xml/XMLNotificationTest.as @@ -38,6 +38,7 @@ package flexUnitTests.xml public function setUp():void { settings = XML.settings(); + XML.setSettings(XML.defaultSettings()); } [After] @@ -56,25 +57,79 @@ package flexUnitTests.xml { } + /** + * + * dev use for creating expected tracking sequences ([SWF] output as a reference) + */ + private static function consoleOut(message:String, type:String = 'log', ...args):void + { + args.unshift(message + '\n'); + COMPILE::JS { + args.unshift('[JS]'); + console[type].apply(console, args); + } + COMPILE::SWF{ + import flash.external.ExternalInterface; + + if (ExternalInterface.available) + { + try + { + args.unshift('[SWF]'); + const method:String = 'console.' + type + '.apply'; + ExternalInterface.call(method, null, args); + } catch (e:Error) + { + } + } + } + } + + /** + * + * dev use for creating expected tracking sequences ([SWF] output as a reference) + */ + private function expectify(array:Array, message:String = null):String{ + array = array.slice(); + var l:uint = array.length; + for (var i:uint = 0; i; setNotifier(xml); xml.appendChild(); + var expected:Array = [ - '[ command=nodeAdded, currentTarget=\\n \\n, target=\\n \\n, value=, detail=null, targetType=XML, targetIsCurrent:true, valueType=XML]' + '[ command=nodeAdded, currentTarget=\\n \\n, target=\\n \\n, value=[element: ], detail=null, targetType=XML, targetIsCurrent:true, valueType=XML]' ] + assertTrue(isExpected(expected), 'unexpected XML notifications'); } @@ -146,15 +241,15 @@ package flexUnitTests.xml delete children[0]; var expected:Array = [ - '[ command=nodeRemoved, currentTarget=, target=, value=, detail=null, targetType=XML, targetIsCurrent:true, valueType=XML]' + '[ command=nodeRemoved, currentTarget=, target=, value=[element: ], detail=null, targetType=XML, targetIsCurrent:true, valueType=XML]' ] + assertTrue(isExpected(expected), 'unexpected XML notifications'); } [Test] - [Ignore] //ignored, because not yet working in JS public function testReplaceNode():void { var xml:XML = ; @@ -164,11 +259,28 @@ package flexUnitTests.xml xml.replace('child1',childX); - var expected:Array = [ - '[ command=nodeChanged, currentTarget=\\n \\n \\n, target=\\n \\n \\n, value=, detail=, targetType=XML, targetIsCurrent:true, valueType=XML]' + '[ command=nodeChanged, currentTarget=\\n \\n \\n, target=\\n \\n \\n, value=[element: ], detail=[element: ], targetType=XML, targetIsCurrent:true, valueType=XML]' + ] + + assertTrue(isExpected(expected), 'unexpected XML notifications'); + + + xml = ; + childX = ; + + setNotifier(xml); + + xml.replace('childB',childX); + + expected = [ + '[ command=nodeRemoved, currentTarget=\\n \\n \\n \\n \\n \\n, target=\\n \\n \\n \\n \\n \\n, value=[element: ], detail=null, targetType=XML, targetIsCurrent:true, valueType=XML]', + '[ command=nodeRemoved, currentTarget=\\n \\n \\n \\n \\n, target=\\n \\n \\n \\n \\n, value=[element: ], detail=null, targetType=XML, targetIsCurrent:true, valueType=XML]', + '[ command=nodeChanged, currentTarget=\\n \\n \\n \\n \\n, target=\\n \\n \\n \\n \\n, value=[element: ], detail=[element: ], targetType=XML, targetIsCurrent:true, valueType=XML]' ] + // expectify(tracking, 'testReplaceNode') assertTrue(isExpected(expected), 'unexpected XML notifications'); + } @@ -183,6 +295,7 @@ package flexUnitTests.xml var expected:Array = [ '[ command=namespaceSet, currentTarget=, target=, value=testuri, detail=null, targetType=XML, targetIsCurrent:true, valueType=Namespace]' ] + assertTrue(isExpected(expected), 'unexpected XML notifications'); } @@ -196,9 +309,11 @@ package flexUnitTests.xml xml.@att = "testAtt"; + var expected:Array = [ '[ command=attributeAdded, currentTarget=, target=, value=att, detail=testAtt, targetType=XML, targetIsCurrent:true, valueType=String]' ] + assertTrue(isExpected(expected), 'unexpected XML notifications'); var att:XML = xml.@att[0]; xml = ; @@ -206,15 +321,16 @@ package flexUnitTests.xml xml.appendChild(att); expected = [ - '[ command=textSet, currentTarget=testAtt, target=testAtt, value=testAtt, detail=null, targetType=XML, targetIsCurrent:false, valueType=String]' , - '[ command=nodeAdded, currentTarget=testAtt, target=testAtt, value=testAtt, detail=null, targetType=XML, targetIsCurrent:true, valueType=XML]' + '[ command=textSet, currentTarget=testAtt, target=testAtt, value=testAtt, detail=null, targetType=XML, targetIsCurrent:false, valueType=String]', + '[ command=nodeAdded, currentTarget=testAtt, target=testAtt, value=[text:""], detail=null, targetType=XML, targetIsCurrent:true, valueType=XML]' ] + + assertTrue(isExpected(expected), 'unexpected XML notifications'); //reset the tracking: setNotifier(xml); xml.@something = att; - expected = [ '[ command=attributeAdded, currentTarget=testAtt, target=testAtt, value=something, detail=testAtt, targetType=XML, targetIsCurrent:true, valueType=String]' ] @@ -234,6 +350,7 @@ package flexUnitTests.xml var expected:Array = [ '[ command=attributeRemoved, currentTarget=, target=, value=test, detail=testAtt, targetType=XML, targetIsCurrent:true, valueType=String]' ] + assertTrue(isExpected(expected), 'unexpected XML notifications'); @@ -243,6 +360,7 @@ package flexUnitTests.xml var attributes:XMLList = xml.attributes(); delete attributes[0]; //expect the same (ignore namespace) + assertTrue(isExpected(expected), 'unexpected XML notifications'); } @@ -253,15 +371,13 @@ package flexUnitTests.xml var xml:XML = new XML('') setNotifier(xml); - xml.@test = 'testAtt2'; - var expected:Array = [ '[ command=attributeChanged, currentTarget=, target=, value=test, detail=testAtt, targetType=XML, targetIsCurrent:true, valueType=String]' ] - assertTrue(isExpected(expected), 'unexpected XML notifications'); + assertTrue(isExpected(expected), 'unexpected XML notifications'); } @@ -278,18 +394,84 @@ package flexUnitTests.xml var expected:Array = [ '[ command=nameSet, currentTarget=, target=, value=test, detail=xml, targetType=XML, targetIsCurrent:true, valueType=QName]' ] + assertTrue(isExpected(expected), 'unexpected XML notifications'); setNotifier(xml); xml.setName('test2'); + expected = [ '[ command=nameSet, currentTarget=, target=, value=test2, detail=test, targetType=XML, targetIsCurrent:true, valueType=String]' ] + assertTrue(isExpected(expected), 'unexpected XML notifications'); } + [Test] + public function testSetChildren():void + { + var xml:XML = ; + + setNotifier(xml); + var alternateChildren:XMLList = XMLList(""); + + xml.setChildren(alternateChildren); + + + var expected:Array = [ + '[ command=nodeRemoved, currentTarget=\\n \\n \\n, target=\\n \\n \\n, value=[element: ], detail=null, targetType=XML, targetIsCurrent:true, valueType=XML]', + '[ command=nodeRemoved, currentTarget=\\n \\n, target=\\n \\n, value=[element: ], detail=null, targetType=XML, targetIsCurrent:true, valueType=XML]', + '[ command=nodeChanged, currentTarget=\\n \\n \\n \\n, target=\\n \\n \\n \\n, value=[element: ], detail=[element: ], targetType=XML, targetIsCurrent:true, valueType=XML]' + ] + assertTrue(isExpected(expected), 'unexpected XML notifications'); + + setNotifier(xml); + alternateChildren = new XMLList(); + xml.setChildren(alternateChildren); + + expected = [ + '[ command=nodeRemoved, currentTarget=\\n \\n \\n, target=\\n \\n \\n, value=[element: ], detail=null, targetType=XML, targetIsCurrent:true, valueType=XML]', + '[ command=nodeRemoved, currentTarget=\\n \\n, target=\\n \\n, value=[element: ], detail=null, targetType=XML, targetIsCurrent:true, valueType=XML]' + ] + assertTrue(isExpected(expected), 'unexpected XML notifications'); + xml = ; + setNotifier(xml); + alternateChildren = XMLList(""); + xml.setChildren(alternateChildren); + expected = [ + '[ command=nodeAdded, currentTarget=\\n \\n \\n \\n, target=\\n \\n \\n \\n, value=[element: ], detail=null, targetType=XML, targetIsCurrent:true, valueType=XML]' + ] + assertTrue(isExpected(expected), 'unexpected XML notifications'); + xml = some text; + setNotifier(xml); + alternateChildren = XMLList(""); + xml.setChildren(alternateChildren); + expected = [ + '[ command=nodeChanged, currentTarget=\\n \\n \\n \\n, target=\\n \\n \\n \\n, value=[element: ], detail=[element: some text], targetType=XML, targetIsCurrent:true, valueType=XML]' + ] + assertTrue(isExpected(expected), 'unexpected XML notifications'); + + //check what the children do (if anything) + xml = ; + setNotifier(xml); + alternateChildren = XMLList(""); + xml.setChildren(alternateChildren); + xml.setChildren(alternateChildren); + expected = [ + '[ command=nodeRemoved, currentTarget=\\n \\n \\n, target=\\n \\n \\n, value=[element: ], detail=null, targetType=XML, targetIsCurrent:true, valueType=XML]', + '[ command=nodeRemoved, currentTarget=\\n \\n, target=\\n \\n, value=[element: ], detail=null, targetType=XML, targetIsCurrent:true, valueType=XML]', + '[ command=nodeChanged, currentTarget=\\n \\n \\n \\n, target=\\n \\n \\n \\n, value=[element: ], detail=[element: ], targetType=XML, targetIsCurrent:true, valueType=XML]', + '[ command=nodeRemoved, currentTarget=\\n \\n \\n, target=\\n \\n \\n, value=[element: ], detail=null, targetType=XML, targetIsCurrent:true, valueType=XML]', + '[ command=nodeRemoved, currentTarget=\\n \\n, target=\\n \\n, value=[element: ], detail=null, targetType=XML, targetIsCurrent:true, valueType=XML]', + '[ command=nodeChanged, currentTarget=\\n \\n \\n \\n, target=\\n \\n \\n \\n, value=[element: ], detail=[element: ], targetType=XML, targetIsCurrent:true, valueType=XML]' + ] + + assertTrue(isExpected(expected), 'unexpected XML notifications'); + + + } + - } }