From 3c7873bd3f7b823db07f08e55fdeac5e4fbde3e9 Mon Sep 17 00:00:00 2001 From: isaacs Date: Sun, 9 May 2010 16:35:15 -0700 Subject: [PATCH] Use duck-typing as well as instanceof in sys.inspect This makes it so that inspecting objects from other contexts works as expected. --- lib/sys.js | 37 ++++++++++++++++++++++++++++++------- 1 file changed, 30 insertions(+), 7 deletions(-) diff --git a/lib/sys.js b/lib/sys.js index 28ec6ff740..3dfcdee77a 100644 --- a/lib/sys.js +++ b/lib/sys.js @@ -65,7 +65,7 @@ exports.inspect = function (obj, showHidden, depth) { // Functions without properties can be shortcutted. if (typeof value === 'function' && keys.length === 0) { - if (value instanceof RegExp) { + if (isRegExp(value)) { return '' + value; } else { return '[Function]'; @@ -73,13 +73,13 @@ exports.inspect = function (obj, showHidden, depth) { } // Dates without properties can be shortcutted - if (value instanceof Date && keys.length === 0) { + if (isDate(value) && keys.length === 0) { return value.toUTCString(); } var base, type, braces; // Determine the object type - if (value instanceof Array) { + if (isArray(value)) { type = 'Array'; braces = ["[", "]"]; } else { @@ -89,13 +89,13 @@ exports.inspect = function (obj, showHidden, depth) { // Make functions say that they are functions if (typeof value === 'function') { - base = (value instanceof RegExp) ? ' ' + value : ' [Function]'; + base = (isRegExp(value)) ? ' ' + value : ' [Function]'; } else { base = ""; } // Make dates with properties first say the date - if (value instanceof Date) { + if (isDate(value)) { base = ' ' + value.toUTCString(); } @@ -106,7 +106,7 @@ exports.inspect = function (obj, showHidden, depth) { } if (recurseTimes < 0) { - if (value instanceof RegExp) { + if (isRegExp(value)) { return '' + value; } else { return "[Object]"; @@ -140,7 +140,7 @@ exports.inspect = function (obj, showHidden, depth) { str = format(value[key], recurseTimes - 1); } if (str.indexOf('\n') > -1) { - if (value instanceof Array) { + if (isArray(value)) { str = str.split('\n').map(function(line) { return ' ' + line; }).join('\n').substr(2); @@ -191,6 +191,29 @@ exports.inspect = function (obj, showHidden, depth) { } return format(obj, (typeof depth === 'undefined' ? 2 : depth)); }; +function isArray (ar) { + return ar instanceof Array + || Array.isArray(ar) + || (ar && ar !== Object.prototype && isArray(ar.__proto__)); +} +function isRegExp (re) { + var s = ""+re; + return re instanceof RegExp // easy case + || typeof(re) === "function" // duck-type for context-switching evalcx case + && re.constructor.name === "RegExp" + && re.compile + && re.test + && re.exec + && s.charAt(0) === "/" + && s.substr(-1) === "/"; +} +function isDate (d) { + if (d instanceof Date) return true; + if (typeof d !== "object") return false; + var properties = Date.prototype && Object.getOwnPropertyNames(Date.prototype); + var proto = d.__proto__ && Object.getOwnPropertyNames(d.__proto__); + return JSON.stringify(proto) === JSON.stringify(properties); +} var pWarning;