I\'m writing a Javascript stacktrace library. The library needs to detect wether a particular object or function was created by the programmer or was there as part of the en
ALMOST SOLVED
Almost managed to get this to work.
The solution falls short in that Host objects are sometimes undistinguishable from Native ones. The code below fails when testing isNative(window.alert)
on Chrome as webkit engine defines an alert
function that (so far) looks identical to a native one.
It uses plain javascript as per ES3 and is based on testing that an object is native (as opposed to Host object). However, as per ES3 definition of Host Objects: 'Any object that is not native is a host object.' this function can be used to detect host objects.
// ISNATIVE OBJECT DETECTION
function isNative(obj) {
switch(typeof obj) {
case 'number': case 'string': case 'boolean':
// Primitive types are not native objects
return false;
}
// Should be an instance of an Object
if (!(obj instanceof Object)) return false;
// Should have a constructor that is an instance of Function
if (typeof obj.constructor === 'undefined') return false;
if (!(obj.constructor instanceof Function)) return false;
return true;
}
// CHECK IF AN OBJECT IS HOST OR NATIVE
if (typeof myObject === 'object' || typeof myObject === 'function')
alert(isNative(myObject) ? 'Native Object' : 'Host Object');
Here is a list of JsFiddle tests that can be used to test this in IE / Firefox / Chrome.
I havent tested Non-browser environments as its a bit more of a hassle but since the code is so basic I dont think it'll have any problems.
// ASSERT HELPER FUNCTION
var n = 0;
function assert(condition, message) {
n++;
if (condition !== true) {
document.write(n + '. FAILS: ' + (message || '(no message)') + '
');
} else {
document.write(n + '. PASS: ' + (message || '(no message)') + '
');
}
}
// USER CREATED OBJECTS
assert(isNative({}), '{} -- Plain object');
assert(isNative(function() {}), 'function() {} -- Plain function');
assert(isNative([]), '[] -- Plain array');
assert(isNative(/regex/), '/regex/ - Native regex');
assert(isNative(new Date()), 'new Date() - Native date object through instantiation');
assert(isNative(new String('string')), 'new String("string") - Native string object through instantiation');
assert(isNative(new Number(1)), 'new Number(1) - Native number object through instantiation');
assert(isNative(new Boolean(true)), 'new Boolean(true) - Native boolean object through instantiation');
assert(isNative(new Array()), 'new Array() - Native array object through instantiation');
assert(isNative(new Object()), '{} -- new Object() - Native object through instantiation');
assert(isNative(new Function('alert(1)')), '{} -- Native function through instantiation');
// USER OBJECT INSTANTIATION AND INHERITANCE
var Animal = function() {};
var animal = new Animal();
var Dog = function() {};
Dog.prototype = animal;
var dog = new Dog();
assert(isNative(Animal), 'Animal -- User defined type');
assert(isNative(animal), 'animal -- Instance of User defined type');
assert(isNative(Dog), 'Dog -- User defined inherited type');
assert(isNative(dog), 'dog -- Instance of User defined inherited type');
// BUILT IN OBJECTS
assert(isNative(Object), 'Object -- Built in');
assert(isNative(Array), 'Array -- Built in');
assert(isNative(Date), 'Date -- Built in');
assert(isNative(Boolean), 'Boolean -- Built in');
assert(isNative(String), 'String -- Built in');
assert(isNative(Function), 'Function -- Built in');
// PRIMITIVE TYPES
assert(!isNative('string'), '"string" - Primitive string');
assert(!isNative(1), '1 - Primitive number');
assert(!isNative(true), 'true - Primitive boolean');
assert(!isNative(null), 'null - Primitive null');
assert(!isNative(NaN), 'NaN - Primitive number NotANumber');
assert(!isNative(Infinity), 'Infinity - Primitive number Infinity');
assert(!isNative(undefined), 'undefined - Primitive value undefined');
// HOST OBJECTS
assert(!isNative(window), 'window -- Host object');
assert(!isNative(alert), 'alert -- Host function'); // fails on chrome
assert(!isNative(document), 'document -- Host object');
assert(!isNative(location), 'location -- Host object');
assert(!isNative(navigator), 'navigator -- Host object');
assert(!isNative(parent), 'parent -- Host object');
assert(!isNative(frames), 'frames -- Host object');