From 3bb7ad6fea42545e9d84ba5cbef8b48e470790fc Mon Sep 17 00:00:00 2001 From: Rasmus Andersson Date: Thu, 18 Feb 2010 17:50:48 +0100 Subject: [PATCH] fixed process.mixin to properly copy getters/setters --- src/node.js | 45 +++++++++++++++++------------- test/mjsunit/test-process-mixin.js | 17 ++++++++++- 2 files changed, 41 insertions(+), 21 deletions(-) diff --git a/src/node.js b/src/node.js index 4506bd8eaa..0d3da4c8e0 100644 --- a/src/node.js +++ b/src/node.js @@ -105,9 +105,10 @@ process.assert = function (x, msg) { // Copyright (c) 2009 John Resig // Dual licensed under the MIT and GPL licenses. // http://docs.jquery.com/License +// Modified for node.js (formely for copying properties correctly) process.mixin = function() { // copy reference to target object - var target = arguments[0] || {}, i = 1, length = arguments.length, deep = false, options; + var target = arguments[0] || {}, i = 1, length = arguments.length, deep = false, source; // Handle a deep copy situation if ( typeof target === "boolean" ) { @@ -129,27 +130,31 @@ process.mixin = function() { for ( ; i < length; i++ ) { // Only deal with non-null/undefined values - if ( (options = arguments[ i ]) != null ) { + if ( (source = arguments[i]) != null ) { // Extend the base object - for ( var name in options ) { - var src = target[ name ], copy = options[ name ]; - - // Prevent never-ending loop - if ( target === copy ) - continue; - - // Recurse if we're merging object values - if ( deep && copy && typeof copy === "object" ) { - target[ name ] = process.mixin( deep, - // Never move original objects, clone them - src || ( copy.length != null ? [ ] : { } ) - , copy ); - - // Don't bring in undefined values - } else { - target[ name ] = copy; + Object.getOwnPropertyNames(source).forEach(function(k){ + var d = Object.getOwnPropertyDescriptor(source, k); + if (d.get) { + target.__defineGetter__(k, d.get); + if (d.set) + target.__defineSetter__(k, d.set); } - } + else { + // Prevent never-ending loop + if (target === d.value) + continue; + + if (deep && d.value && typeof d.value === "object") { + target[k] = process.mixin(deep, + // Never move original objects, clone them + source || (d.value.length != null ? [] : {}) + , d.value); + } + else { + target[k] = d.value; + } + } + }); } } // Return the modified object diff --git a/test/mjsunit/test-process-mixin.js b/test/mjsunit/test-process-mixin.js index f3578251a2..502c229b35 100644 --- a/test/mjsunit/test-process-mixin.js +++ b/test/mjsunit/test-process-mixin.js @@ -19,4 +19,19 @@ var objectWithUndefinedValue = {foo: undefined}; target = {}; process.mixin(target, objectWithUndefinedValue); -assert.ok(target.hasOwnProperty('foo')); \ No newline at end of file +assert.ok(target.hasOwnProperty('foo')); + +// This test verifies getters and setters being copied correctly + +var source = { + _foo:'a', + get foo(){ return this._foo; }, + set foo(value){ this._foo = "did set to "+value; } +}; +var target = {}; +process.mixin(target, source); +target._foo = 'b'; +assert.equal(source.foo, 'a'); +assert.equal('b', target.foo, 'target.foo != "b" -- value/result was copied instead of getter function'); +source.foo = 'c'; +assert.equal('did set to c', source.foo, 'source.foo != "c" -- value was set instead of calling setter function');