Skip to content

Commit

Permalink
Merge pull request #17 from jonschlinkert/key-properties
Browse files Browse the repository at this point in the history
Property keys
  • Loading branch information
doowb committed Jan 11, 2021
2 parents 12cbc0b + 393e2cb commit e370968
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 1 deletion.
1 change: 1 addition & 0 deletions .travis.yml
Expand Up @@ -17,4 +17,5 @@ node_js:
matrix:
fast_finish: true
allow_failures:
- node_js: 'node'
- node_js: '0.8'
6 changes: 5 additions & 1 deletion index.js
Expand Up @@ -32,7 +32,7 @@ module.exports = function mergeDeep(orig, objects) {

function merge(target, obj) {
for (var key in obj) {
if (key === '__proto__' || !hasOwn(obj, key)) {
if (!isValidKey(key) || !hasOwn(obj, key)) {
continue;
}

Expand All @@ -57,3 +57,7 @@ function hasOwn(obj, key) {
function isObject(val) {
return typeOf(val) === 'object' || typeOf(val) === 'function';
}

function isValidKey(key) {
return key !== '__proto__' && key !== 'constructor' && key !== 'prototype';
}
64 changes: 64 additions & 0 deletions test.js
Expand Up @@ -134,4 +134,68 @@ describe('mergeDeep', function() {
var actual = merge(fixture);
assert.deepEqual(actual, fixture);
});

it('should not clone invalid keys', function() {
var obj1 = { a: { b: 1 } };
var obj2 = JSON.parse('{ "a": { "c": 2 }, "constructor": { "keys": 42 } }');

var actual = merge({}, obj1, obj2);
assert.deepEqual(actual, { a: { b: 1, c: 2 } });
assert.notDeepEqual(actual.a, obj1.a);
assert.notDeepEqual(actual.a, obj2.a);
assert.notEqual(actual.keys, 42);
assert.notEqual(actual.constructor.keys, 42);
});

it('should allow being used for custom constructors', function() {
// The following setup code is a simple way to demonstrate multiple inheritance by merging the prototype of one class onto another
function Shape() {
this.type = '';
}

function Position(x, y) {
this.x = x || 0;
this.y = y || 0;
}

Position.prototype.stringify = function() {
return '(' + this.x + ', ' + this.y + ')';
};

function Moveable(x, y) {
Position.call(this, x, y);
}

// By making Moveable inherit from Position, allows us to test what happens when `constructor` is passed to `isValidKey`.
Moveable.prototype = Object.create(Position.prototype);
Moveable.prototype.constructor = Moveable;
Moveable.prototype = merge(Moveable.prototype, Position.prototype);

Moveable.prototype.move = function(x, y) {
this.x += x;
this.y += y;
};

Moveable.prototype.position = function() {
return this.stringify();
};

function Rectangle() {
Shape.call(this);
Moveable.call(this);
this.type = 'rectangle';
}

// Single inheritance using Object.create
Rectangle.prototype = Object.create(Shape.prototype);
Rectangle.prototype.constructor = Rectangle;

// This is the test to ensure that `merge-deep` can be used with prototypal inheritance
Rectangle.prototype = merge(Rectangle.prototype, Moveable.prototype);

var rectangle = new Rectangle();
assert.equal(rectangle.position(), '(0, 0)');
rectangle.move(10, 20);
assert.equal(rectangle.position(), '(10, 20)');
});
});

0 comments on commit e370968

Please sign in to comment.