From a7a64abcf5483a6eaa49a8330d3bbde9bb1b707c Mon Sep 17 00:00:00 2001 From: Catrope Date: Wed, 10 Oct 2012 17:13:01 -0700 Subject: [PATCH] Add ve.getProp() Change-Id: Iad9f53ae252acbeb2842645e6e66c0dfc7618f9f --- modules/ve/test/ve.test.js | 57 ++++++++++++++++++++++++++++++++++++++ modules/ve/ve.js | 24 ++++++++++++++++ 2 files changed, 81 insertions(+) diff --git a/modules/ve/test/ve.test.js b/modules/ve/test/ve.test.js index db81a0f9ef..77fc3493e0 100644 --- a/modules/ve/test/ve.test.js +++ b/modules/ve/test/ve.test.js @@ -314,3 +314,60 @@ QUnit.test( 'getOpeningHtmlTag', 5, function ( assert ) { 'escaping of attribute values' ); } ); + +QUnit.test( 'getProp', 9, function ( assert ) { + var obj = { + 'foo': 3, + 'bar': { + 'baz': null, + 'quux': { + 'whee': 'yay' + } + } + }; + assert.deepEqual( + ve.getProp( obj, 'foo' ), + 3, + 'single key' + ); + assert.deepEqual( + ve.getProp( obj, 'bar' ), + { 'baz': null, 'quux': { 'whee': 'yay' } }, + 'singe key, returns object' + ); + assert.deepEqual( + ve.getProp( obj, 'bar', 'baz' ), + null, + 'two keys, returns null' + ); + assert.deepEqual( + ve.getProp( obj, 'bar', 'quux', 'whee' ), + 'yay', + 'three keys' + ); + assert.deepEqual( + ve.getProp( obj, 'x' ), + undefined, + 'missing property returns undefined' + ); + assert.deepEqual( + ve.getProp( obj, 'foo', 'bar' ), + undefined, + 'missing 2nd-level property returns undefined' + ); + assert.deepEqual( + ve.getProp( obj, 'foo', 'bar', 'baz', 'quux', 'whee' ), + undefined, + 'multiple missing properties don\'t cause an error' + ); + assert.deepEqual( + ve.getProp( obj, 'bar', 'baz', 'quux' ), + undefined, + 'accessing property of null returns undefined, doesn\'t cause an error' + ); + assert.deepEqual( + ve.getProp( obj, 'bar', 'baz', 'quux', 'whee', 'yay' ), + undefined, + 'accessing multiple properties of null' + ); +} ); diff --git a/modules/ve/ve.js b/modules/ve/ve.js index 5b0a489e83..1ff0914bab 100644 --- a/modules/ve/ve.js +++ b/modules/ve/ve.js @@ -527,6 +527,30 @@ ve.batchSplice( dst, offset, 0, src ); }; + /** + * Get a deeply nested property of an object using variadic arguments, protecting against + * undefined property errors. + * + * quux = getProp( obj, 'foo', 'bar', 'baz' ); is equivalent to quux = obj.foo.bar.baz; + * except that the former protects against JS errors if one of the intermediate properties + * is undefined. Instead of throwing an error, this function will return undefined in + * that case. + * + * @param {Object} obj + * @returns obj[arguments[1]][arguments[2]].... or undefined + */ + ve.getProp = function ( obj /*, keys ... */ ) { + var retval = obj; + for ( i = 1; i < arguments.length; i++ ) { + if ( retval === undefined || retval === null ) { + // Trying to access a property of undefined or null causes an error + return undefined; + } + retval = retval[arguments[i]]; + } + return retval; + }; + /** * Logs data to the console. *