Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: remy/undefsafe
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 9c7867e6dc75ee8842b4bbfdfeba9e3ccf3bc616
Choose a base ref
...
head repository: remy/undefsafe
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: f272681b3a50e2c4cbb6a8533795e1453382c822
Choose a head ref
  • 6 commits
  • 9 files changed
  • 2 contributors

Commits on Feb 12, 2017

  1. feat: * rule returns all matches (#7)

    BREAKING CHANGE:
    
    Instead of * rule returning the first, it now returns all the matches in a flattened array.
    remy authored Feb 12, 2017
    Copy the full SHA
    2d38e72 View commit details

Commits on Feb 21, 2017

  1. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    9a1631a View commit details
  2. Merge branch 'master' of github.com:remy/undefsafe

    * 'master' of github.com:remy/undefsafe:
      feat: * rule returns all matches (#7)
    remy committed Feb 21, 2017
    Copy the full SHA
    29c8d32 View commit details

Commits on Feb 15, 2018

  1. fix: add .npmignore (#11)

    Remove test/ folder from being published with the npm package
    eugenelim authored and remy committed Feb 15, 2018
    Copy the full SHA
    e4180ba View commit details

Commits on Feb 17, 2020

  1. chore: prettier changes

    remy committed Feb 17, 2020
    Copy the full SHA
    f495954 View commit details
  2. Copy the full SHA
    f272681 View commit details
Showing with 106 additions and 57 deletions.
  1. +2 −0 .npmignore
  2. +1 −1 example.js
  3. +36 −10 lib/undefsafe.js
  4. +4 −0 package.json
  5. +5 −6 test/array.test.js
  6. +11 −0 test/misc.test.js
  7. +5 −5 test/set.test.js
  8. +23 −18 test/star-rule.test.js
  9. +19 −17 test/undefsafe.test.js
2 changes: 2 additions & 0 deletions .npmignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# .npmignore file
test/
2 changes: 1 addition & 1 deletion example.js
Original file line number Diff line number Diff line change
@@ -4,7 +4,7 @@ var object = {
a: {
b: {
c: 1,
d: [1,2,3],
d: [1, 2, 3],
e: 'remy'
}
}
46 changes: 36 additions & 10 deletions lib/undefsafe.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
'use strict';

function undefsafe(obj, path, value) {

function undefsafe(obj, path, value, __res) {
// I'm not super keen on this private function, but it's because
// it'll also be use in the browser and I wont *one* function exposed
function split(path) {
@@ -19,7 +18,8 @@ function undefsafe(obj, path, value) {
c = path.substr(i, 1);
}

if (key) { // the first value could be a string
if (key) {
// the first value could be a string
res.push(key);
}
key = '';
@@ -40,15 +40,23 @@ function undefsafe(obj, path, value) {
return res;
}

// bail if there's nothing
if (obj === undefined || obj === null) {
return undefined;
}

var parts = split(path);
var key = null;
var type = typeof obj;
var root = obj;
var parent = obj;

var star = parts.filter(function (_) { return _ === '*' }).length > 0;
var star =
parts.filter(function(_) {
return _ === '*';
}).length > 0;

// we're dealing with a primative
// we're dealing with a primitive
if (type !== 'object' && type !== 'function') {
return obj;
} else if (path.trim() === '') {
@@ -64,17 +72,35 @@ function undefsafe(obj, path, value) {
if (key === '*') {
// loop through each property
var prop = '';
var res = __res || [];

for (prop in parent) {
var shallowObj = undefsafe(obj[prop], parts.slice(i + 1).join('.'), value);
if (shallowObj) {
if ((value && shallowObj === value) || (!value)) {
return shallowObj;
var shallowObj = undefsafe(
obj[prop],
parts.slice(i + 1).join('.'),
value,
res
);
if (shallowObj && shallowObj !== res) {
if ((value && shallowObj === value) || value === undefined) {
if (value !== undefined) {
return shallowObj;
}

res.push(shallowObj);
}
}
}

if (res.length === 0) {
return undefined;
}

return res;
}

if (Object.getOwnPropertyNames(obj).indexOf(key) == -1) {
return undefined;
key = prop;
}

obj = obj[key];
4 changes: 4 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -11,6 +11,10 @@
"cover": "tap test/*.test.js --cov --coverage-report=lcov",
"semantic-release": "semantic-release pre && npm publish && semantic-release post"
},
"prettier": {
"trailingComma": "none",
"singleQuote": true
},
"repository": {
"type": "git",
"url": "https://github.com/remy/undefsafe.git"
11 changes: 5 additions & 6 deletions test/array.test.js
Original file line number Diff line number Diff line change
@@ -2,23 +2,22 @@
var test = require('tap').test;
var undefsafe = require('../lib/undefsafe');

test('get specific array index', function (t) {
test('get specific array index', function(t) {
var fixture = {
a: [1,2,3,4]
a: [1, 2, 3, 4]
};

var res = undefsafe(fixture, 'a.2');
t.equal(res, 3);
t.end();
});

test('set specific array index', function (t) {
test('set specific array index', function(t) {
var fixture = {
a: [1,2,3,4]
a: [1, 2, 3, 4]
};

undefsafe(fixture, 'a.2', 30);
t.deepEqual(fixture, { a: [1,2,30,4] });
t.deepEqual(fixture, { a: [1, 2, 30, 4] });
t.end();
});

11 changes: 11 additions & 0 deletions test/misc.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
var test = require('tap').test;
var undefsafe = require('../lib/undefsafe');

test('cannot modify prototype chain', function(t) {
const pre = {}.__proto__.toString;
var payload = '__proto__.toString';
undefsafe({ a: 'b' }, payload, 'JHU');
t.notEqual({}.toString, 'JHU');
({}.__proto__.toString = pre); // restore
t.end();
});
10 changes: 5 additions & 5 deletions test/set.test.js
Original file line number Diff line number Diff line change
@@ -2,7 +2,7 @@
var test = require('tap').test;
var undefsafe = require('../lib/undefsafe');

test('setting deep object values', function (t) {
test('setting deep object values', function(t) {
var fixture = {
a: {
b: {
@@ -14,11 +14,11 @@ test('setting deep object values', function (t) {
};

undefsafe(fixture, 'a.b.c.d', 20);
t.equal(fixture.a.b.c.d, 20, 'deep primative changed');
t.equal(fixture.a.b.c.d, 20, 'deep primitive changed');
t.end();
});

test('setting shallow object values', function (t) {
test('setting shallow object values', function(t) {
var fixture = {
a: {
b: {
@@ -34,7 +34,7 @@ test('setting shallow object values', function (t) {
t.end();
});

test('undef value', function (t) {
test('undef value', function(t) {
var fixture = {
a: {
b: {
@@ -50,7 +50,7 @@ test('undef value', function (t) {
t.end();
});

test('missing value', function (t) {
test('missing value', function(t) {
var fixture = {
a: {
b: {
41 changes: 23 additions & 18 deletions test/star-rule.test.js
Original file line number Diff line number Diff line change
@@ -2,49 +2,54 @@
var test = require('tap-only');
var undefsafe = require('../lib/undefsafe');
var fixture = {
"commits": [
commits: [
{
"modified": [
"one",
"two"
]
modified: ['one', 'two']
},
{
"modified": [
"two",
"four"
]
modified: ['two', 'four']
}
]
};

test('get value on first * selector', function (t) {
var res = undefsafe(fixture, 'commits.*.modified.*');
t.equal(res, 'one');
test('2.0.0: match all.*', function(t) {
var res = undefsafe(fixture, '*.*.*.1');
t.deepEqual(res, ['two', 'four']);
t.end();
});

test('2.0.0: match all.*', function(t) {
var res = undefsafe(fixture, 'commits.*.modified.*.b');
t.deepEqual(res, ['one', 'two', 'two', 'four']);
t.end();
});

test('walking multiple routes', function (t) {
test('get value on first * selector', function(t) {
var res = undefsafe(fixture, 'commits.*.modified.0');
t.deepEqual(res, ['one', 'two']);
t.end();
});

test('walking multiple routes', function(t) {
var res = undefsafe(fixture, 'commits.*.modified.*', 'four');
t.equal(res, 'four');
t.end();
});


test('get specific match * selector', function (t) {
test('get specific match * selector', function(t) {
var res = undefsafe(fixture, 'commits.*.modified.*', 'two');
t.equal(res, 'two');
t.end();
});

test('match * selector returns undefined', function (t) {
test('match * selector returns undefined', function(t) {
var res = undefsafe(fixture, 'commits.*.modified.*', 'three');
t.equal(res, undefined);
t.end();
});

test('match * selector works on objects', function (t) {
var res = undefsafe(fixture, '*.*.modified.*');
test('match * selector works on objects', function(t) {
var res = undefsafe(fixture, '*.*.modified.*', 'one');
t.equal(res, 'one');
t.end();
});
36 changes: 19 additions & 17 deletions test/undefsafe.test.js
Original file line number Diff line number Diff line change
@@ -2,13 +2,19 @@
var test = require('tap-only');
var undefsafe = require('../lib/undefsafe');

test('should handle primatives', function (t) {
test('should handle primatives', function(t) {
var r = undefsafe(1, '');
t.equal(r, 1, 'undefsafe is 1: ' + r);
t.end();
});

test('should handle empty objects', function (t) {
test('should handle null', function(t) {
var r = undefsafe(null, 'foo');
t.equal(r, undefined, 'undefsafe works with null');
t.end();
});

test('should handle empty objects', function(t) {
var value = {};
var r;

@@ -24,11 +30,11 @@ test('should handle empty objects', function (t) {
t.end();
});

test('should handle null properties', function (t) {
test('should handle null properties', function(t) {
var value = {
a: {
b: null,
},
b: null
}
};
var r;

@@ -41,7 +47,7 @@ test('should handle null properties', function (t) {
t.end();
});

test('should find properties with periods in them', function (t) {
test('should find properties with periods in them', function(t) {
var value = {
a: { 'one.two': true }
};
@@ -57,10 +63,7 @@ test('should find properties with periods in them', function (t) {
t.equal(r, true, 'weird: ' + r);

value = {
a: { 'one.two.and\three': [
false,
true,
] }
a: { 'one.two.and\three': [false, true] }
};

r = undefsafe(value, `a['one.two.and\three'].1`);
@@ -76,23 +79,22 @@ test('should find properties with periods in them', function (t) {
t.end();
});


test('should find deep object properties', function (t) {
test('should find deep object properties', function(t) {
var value = {
a: {
b: {
c: {
d: 10,
e: {
f: 20,
f: 20
},
g: true,
h: false,
i: undefined,
j: null,
},
},
},
j: null
}
}
}
};
var r;