$getOwnPropertyDescriptor = function getOwnPropertyDescriptor(object, property) { var obj = toObject(object); var propKey = toPropertyKey(property); var result; // make a valiant attempt to use the real getOwnPropertyDescriptor for I8's DOM elements. if (getOPDFallback1) { result = attempt.call(Object, getOPDFallback1, obj, propKey); if (result.threw === false) { return result.value; } // try the shim if the real one doesn't work } var isStringIndex = isString(obj) && isIndex(propKey, obj.length); if (getOPDFallback2 && isStringIndex === false) { result = attempt.call(Object, getOPDFallback2, obj, propKey); if (result.threw === false) { return result.value; } // try the shim if the real one doesn't work } var descriptor; // If object does not owns property return undefined immediately. if (isStringIndex === false && owns(obj, propKey) === false) { return descriptor; } // If object has a property then it's for sure `configurable`, and // probably `enumerable`. Detect enumerability though. descriptor = { configurable: isPrimitive(object) === false && isStringIndex === false, enumerable: propertyIsEnumerable(obj, propKey) }; // If JS engine supports accessor properties then property may be a // getter or setter. if (supportsAccessors) { // Unfortunately `__lookupGetter__` will return a getter even // if object has own non getter property along with a same named // inherited getter. To avoid misbehavior we temporary remove // `__proto__` so that `__lookupGetter__` will return getter only // if it's owned by an object. // eslint-disable-next-line no-proto var prototype = obj.__proto__; var notPrototypeOfObject = obj !== prototypeOfObject; // avoid recursion problem, breaking in Opera Mini when // Object.getOwnPropertyDescriptor(Object.prototype, 'toString') // or any other Object.prototype accessor if (notPrototypeOfObject) { // eslint-disable-next-line no-proto obj.__proto__ = prototypeOfObject; } var getter = lookupGetter(obj, propKey); var setter = lookupSetter(obj, propKey); if (notPrototypeOfObject) { // Once we have getter and setter we can put values back. // eslint-disable-next-line no-proto obj.__proto__ = prototype; } if (getter || setter) { if (getter) { descriptor.get = getter; } if (setter) { descriptor.set = setter; } // If it was accessor property we're done and return here // in order to avoid adding `value` to the descriptor. return descriptor; } } // If we got this far we know that object has an own property that is // not an accessor so we set it as a value and return descriptor. if (isStringIndex) { descriptor.value = obj.charAt(propKey); descriptor.writable = false; } else { descriptor.value = obj[propKey]; descriptor.writable = true; } return descriptor; };
$getOwnPropertyDescriptor = function getOwnPropertyDescriptor(object, property) { return nativeGOPD(toObject(object), toPropertyKey(property)); };