Skip to content

Commit

Permalink
fixed process.mixin to properly copy getters/setters
Browse files Browse the repository at this point in the history
  • Loading branch information
rsms authored and ry committed Feb 18, 2010
1 parent bcc032e commit 3bb7ad6
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 21 deletions.
45 changes: 25 additions & 20 deletions src/node.js
Original file line number Diff line number Diff line change
Expand Up @@ -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" ) {
Expand All @@ -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
Expand Down
17 changes: 16 additions & 1 deletion test/mjsunit/test-process-mixin.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,19 @@ var objectWithUndefinedValue = {foo: undefined};
target = {};

process.mixin(target, objectWithUndefinedValue);
assert.ok(target.hasOwnProperty('foo'));
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');

0 comments on commit 3bb7ad6

Please sign in to comment.