Commit 3fe4629b 3fe4629b6bb3e0b7c6aff29f7e7580d067048fe2 by Nicolas Perriault

Merge pull request #659 from mduvall/convert-reference-checking

Change mergeObject to have option to keep references
2 parents c25c439a 258d66d0
...@@ -216,10 +216,12 @@ Checks if passed argument is an instance of native PhantomJS' ``WebPage`` object ...@@ -216,10 +216,12 @@ Checks if passed argument is an instance of native PhantomJS' ``WebPage`` object
216 ``mergeObjects()`` 216 ``mergeObjects()``
217 ------------------------------------------------------------------------------- 217 -------------------------------------------------------------------------------
218 218
219 **Signature:** ``mergeObjects(origin, add)`` 219 **Signature:** ``mergeObjects(origin, add[, Object opts])``
220 220
221 Merges two objects recursively. 221 Merges two objects recursively.
222 222
223 Add ``opts.keepReferences`` if cloning of internal objects is not needed.
224
223 .. index:: DOM 225 .. index:: DOM
224 226
225 ``node()`` 227 ``node()``
......
...@@ -622,14 +622,26 @@ function isPlainObject(obj) { ...@@ -622,14 +622,26 @@ function isPlainObject(obj) {
622 return (type === 'object'); 622 return (type === 'object');
623 } 623 }
624 624
625 function mergeObjectsInSlimerjs(origin, add) { 625 /**
626 * Object recursive merging utility for use in the SlimerJS environment
627 *
628 * @param Object origin the origin object
629 * @param Object add the object to merge data into origin
630 * @param Object opts optional options to be passed in
631 * @return Object
632 */
633 function mergeObjectsInSlimerjs(origin, add, opts) {
626 "use strict"; 634 "use strict";
635
636 var options = opts || {},
637 keepReferences = options.keepReferences;
638
627 for (var p in add) { 639 for (var p in add) {
628 if (isPlainObject(add[p])) { 640 if (isPlainObject(add[p])) {
629 if (isPlainObject(origin[p])) { 641 if (isPlainObject(origin[p])) {
630 origin[p] = mergeObjects(origin[p], add[p]); 642 origin[p] = mergeObjects(origin[p], add[p]);
631 } else { 643 } else {
632 origin[p] = clone(add[p]); 644 origin[p] = keepReferences ? add[p] : clone(add[p]);
633 } 645 }
634 } else { 646 } else {
635 origin[p] = add[p]; 647 origin[p] = add[p];
...@@ -643,23 +655,28 @@ function mergeObjectsInSlimerjs(origin, add) { ...@@ -643,23 +655,28 @@ function mergeObjectsInSlimerjs(origin, add) {
643 * 655 *
644 * @param Object origin the origin object 656 * @param Object origin the origin object
645 * @param Object add the object to merge data into origin 657 * @param Object add the object to merge data into origin
658 * @param Object opts optional options to be passed in
646 * @return Object 659 * @return Object
647 */ 660 */
648 function mergeObjects(origin, add) { 661 function mergeObjects(origin, add, opts) {
649 "use strict"; 662 "use strict";
650 663
664 var options = opts || {},
665 keepReferences = options.keepReferences;
666
651 if (phantom.casperEngine === 'slimerjs') { 667 if (phantom.casperEngine === 'slimerjs') {
652 // Because of an issue in the module system of slimerjs (security membranes?) 668 // Because of an issue in the module system of slimerjs (security membranes?)
653 // constructor is undefined. 669 // constructor is undefined.
654 // let's use an other algorithm 670 // let's use an other algorithm
655 return mergeObjectsInSlimerjs(origin, add); 671 return mergeObjectsInSlimerjs(origin, add);
656 } 672 }
673
657 for (var p in add) { 674 for (var p in add) {
658 if (add[p] && add[p].constructor === Object) { 675 if (add[p] && add[p].constructor === Object) {
659 if (origin[p] && origin[p].constructor === Object) { 676 if (origin[p] && origin[p].constructor === Object) {
660 origin[p] = mergeObjects(origin[p], add[p]); 677 origin[p] = mergeObjects(origin[p], add[p]);
661 } else { 678 } else {
662 origin[p] = clone(add[p]); 679 origin[p] = keepReferences ? add[p] : clone(add[p]);
663 } 680 }
664 } else { 681 } else {
665 origin[p] = add[p]; 682 origin[p] = add[p];
......
...@@ -326,7 +326,8 @@ casper.test.begin('isJsFile() tests', 5, function(test) { ...@@ -326,7 +326,8 @@ casper.test.begin('isJsFile() tests', 5, function(test) {
326 }); 326 });
327 327
328 328
329 casper.test.begin('mergeObjects() tests', 8, function(test) { 329 casper.test.begin('mergeObjects() tests', 10, function(test) {
330 /* jshint eqeqeq:false */
330 var testCases = [ 331 var testCases = [
331 { 332 {
332 obj1: {a: 1}, obj2: {b: 2}, merged: {a: 1, b: 2} 333 obj1: {a: 1}, obj2: {b: 2}, merged: {a: 1, b: 2}
...@@ -360,13 +361,24 @@ casper.test.begin('mergeObjects() tests', 8, function(test) { ...@@ -360,13 +361,24 @@ casper.test.begin('mergeObjects() tests', 8, function(test) {
360 'mergeObjects() can merge objects' 361 'mergeObjects() can merge objects'
361 ); 362 );
362 }); 363 });
363 var obj = {x: 1}; 364 var obj = {x: 1},
365 qtruntimeobject = {foo: 'baz'};
366
364 var merged1 = utils.mergeObjects({}, {a: obj}); 367 var merged1 = utils.mergeObjects({}, {a: obj});
365 var merged2 = utils.mergeObjects({a: {}}, {a: obj});
366 merged1.a.x = 2; 368 merged1.a.x = 2;
367 test.assertEquals(obj.x, 1, 'mergeObjects() creates deep clones #1'); 369 test.assertEquals(obj.x, 1, 'mergeObjects() creates deep clones #1');
370
371 var merged2 = utils.mergeObjects({a: {}}, {a: obj});
368 merged2.a.x = 2; 372 merged2.a.x = 2;
369 test.assertEquals(obj.x, 1, 'mergeObjects() creates deep clones #2'); 373 test.assertEquals(obj.x, 1, 'mergeObjects() creates deep clones #2');
374
375 var refObj = {a: qtruntimeobject};
376 var merged3 = utils.mergeObjects({}, refObj, {keepReferences: false});
377 test.assertFalsy(merged3.a == refObj.a, 'disabling references should not point to same object');
378
379 var merged4 = utils.mergeObjects({}, refObj, {keepReferences: true});
380 test.assert(merged4.a == refObj.a, 'enabling references should point to same object');
381
370 test.done(); 382 test.done();
371 }); 383 });
372 384
......