diff --git a/package.json b/package.json index 9791e85..424d4cd 100644 --- a/package.json +++ b/package.json @@ -63,5 +63,5 @@ "test:watch": "eslint --fix && jest --watchAll" }, "types": "dist/index.d.ts", - "version": "1.0.2" + "version": "1.1.0" } diff --git a/src/index.js b/src/index.js index a314e32..9946331 100644 --- a/src/index.js +++ b/src/index.js @@ -2,6 +2,8 @@ const DEFAULT_VAL = {}; const RE_DELIMITER = /[\[\]|\.]+/g; +const RE_BEG_BRACKET_LAST_CHAR = /^\[/; + const RE_END_BRACKET_LAST_CHAR = /\]$/; const RE_TYPE = /.*\s(\w+)\]$/; @@ -21,13 +23,23 @@ const toString = Object.prototype.toString; * @see lodash.get documentation */ function getProperty( source, path, defaultValue = DEFAULT_VAL ) { - switch( toString.call( path ).replace( RE_TYPE, '$1' ) ) { - case 'String': path = path.replace( RE_END_BRACKET_LAST_CHAR, '' ).split( RE_DELIMITER ); break; + switch( getTypeName( path ) ) { + case 'String': { + path = path + .replace( RE_BEG_BRACKET_LAST_CHAR, '' ) + .replace( RE_END_BRACKET_LAST_CHAR, '' ) + .split( RE_DELIMITER ); + break; + } case 'Array': break; case 'Undefined': path = []; break; default: path = [ path ]; } - let _value = source; + let _value; + { + const t = getTypeName( source ); + _value = t === 'Object' || t === 'Array' ? source : {}; + } let exists = true; let index = NaN; const trail = []; @@ -66,6 +78,8 @@ function getProperty( source, path, defaultValue = DEFAULT_VAL ) { }; } +function getTypeName( value ) { return toString.call( value ).replace( RE_TYPE, '$1' ) } + function hasEntry( key, object ) { try { return key in object diff --git a/src/index.test.js b/src/index.test.js index 8489110..d745966 100644 --- a/src/index.test.js +++ b/src/index.test.js @@ -280,7 +280,7 @@ describe( 'getProperty(...)', () => { } ); } ); test( 'does not reverse-access indexed objects', () => { - expect( getProperty({ 0: 'one', 1: 'two', 2: 'three' }, -1 ).value ).toBeUndefined(); + expect( getProperty( { 0: 'one', 1: 'two', 2: 'three' }, -1 ).value ).toBeUndefined(); } ); test( 'returns undefined immediately on reverse access error', () => { expect( getProperty( { 0: { name: 'one' } }, '[-1].name' ).value ).toBeUndefined(); @@ -299,4 +299,41 @@ describe( 'getProperty(...)', () => { data.uuyuw[ '654' ][ 1 ].history.places[ 0 ].year ); } ); + describe( 'non object source parameter', () => { + let scalarProperty; + beforeAll(() => { + scalarProperty = { + _value: undefined, + exists: false, + index: NaN, + isSelf: false, + key: 'b', + source: undefined, + trail: [], + value: undefined + }; + }); + test( 'resolves array value', () => { + expect( getProperty( [ 22, 44, 333, { b: 90 }], '[-1].b' ) ).toStrictEqual({ + _value: 90, + exists: true, + index: NaN, + isSelf: false, + key: 'b', + source: { b: 90 }, + trail: [ 3, 'b' ], + value: 90 + }); + } ); + + test( 'ignores attempts to search atomic values', () => { + expect( getProperty( 44, '[-1].b' ) ).toStrictEqual( scalarProperty ); + } ); + test( 'ignores attempts to search null values', () => { + expect( getProperty( null, '[-1].b' ) ).toStrictEqual( scalarProperty ); + } ); + test( 'ignores attempts to search undefined values', () => { + expect( getProperty( undefined, '[-1].b' ) ).toStrictEqual( scalarProperty ); + } ); + } ); } );