From 48abcd84c536e5ce7778308cef2de78cae8c9f24 Mon Sep 17 00:00:00 2001 From: Kit Goncharov Date: Sun, 20 Mar 2011 10:08:32 -0600 Subject: [PATCH] Issue #149: `_.keys` should throw a `TypeError` for non-objects. --- test/objects.js | 25 +++++++++++++++++++++++++ underscore.js | 1 + 2 files changed, 26 insertions(+) diff --git a/test/objects.js b/test/objects.js index d4bfac645..5fa9168ab 100644 --- a/test/objects.js +++ b/test/objects.js @@ -2,8 +2,33 @@ $(document).ready(function() { module("Object functions (values, extend, isEqual, and so on...)"); + function raises(block, expected, message) { + var pass = typeof block == 'function', + isRegExp = expected && Object.prototype.toString.call(expected) == '[object RegExp]', + isFunction = !isRegExp && typeof expected == 'function'; + if (!isFunction && !isRegExp && message == null) { + message = expected; + expected = null; + } + if (pass) { + try { + block(); + pass = false; + } catch (error) { + pass = expected == null || (isRegExp && expected.test(error)) || (isFunction && expected.call(null, error)); + } + } + ok(pass, typeof message == 'string' && message || 'error'); + } + test("objects: keys", function() { + var exception = /TypeError/; equals(_.keys({one : 1, two : 2}).join(', '), 'one, two', 'can extract the keys from an object'); + raises(function() { _.keys(null); }, exception, 'throws an error for `null` values'); + raises(function() { _.keys(void 0); }, exception, 'throws an error for `undefined` values'); + raises(function() { _.keys(1); }, exception, 'throws an error for number primitives'); + raises(function() { _.keys('a'); }, exception, 'throws an error for string primitives'); + raises(function() { _.keys(true); }, exception, 'throws an error for boolean primitives'); }); test("objects: values", function() { diff --git a/underscore.js b/underscore.js index 2b7968ddf..1c83d0987 100644 --- a/underscore.js +++ b/underscore.js @@ -504,6 +504,7 @@ // Retrieve the names of an object's properties. // Delegates to **ECMAScript 5**'s native `Object.keys` _.keys = nativeKeys || function(obj) { + if (obj !== Object(obj)) throw new TypeError('Invalid object'); var keys = []; for (var key in obj) if (hasOwnProperty.call(obj, key)) keys[keys.length] = key; return keys;