Files
asciidisco.com/build/node_modules/object-get-own-property-descriptor-x/index.js
2023-08-01 13:49:46 +02:00

210 lines
7.3 KiB
JavaScript

/**
* @file Sham for ES6 Object.getOwnPropertyDescriptor
* @version 3.2.0
* @author Xotic750 <Xotic750@gmail.com>
* @copyright Xotic750
* @license {@link <https://opensource.org/licenses/MIT> MIT}
* @module object-get-own-property-descriptor-x
*/
'use strict';
var toObject = require('to-object-x');
var toPropertyKey = require('to-property-key-x');
var isFalsey = require('is-falsey-x');
var attempt = require('attempt-x');
var nativeGOPD = typeof Object.getOwnPropertyDescriptor === 'function' && Object.getOwnPropertyDescriptor;
var getOPDFallback1;
var getOPDFallback2;
// ES5 15.2.3.3
// http://es5.github.com/#x15.2.3.3
var doesGOPDWork = function (object, prop) {
object[toPropertyKey(prop)] = 0;
var testResult = attempt(nativeGOPD, object, prop);
return testResult.threw === false && testResult.value.value === 0;
};
// check whether getOwnPropertyDescriptor works if it's given. Otherwise, shim partially.
var $getOwnPropertyDescriptor;
if (nativeGOPD) {
var doc = typeof document !== 'undefined' && document;
var getOPDWorksOnDom = doc ? doesGOPDWork(doc.createElement('div'), 'sentinel') : true;
if (getOPDWorksOnDom) {
var res = attempt(nativeGOPD, Object('abc'), 1);
var worksWithStr = res.threw === false && res.value && res.value.value === 'b';
if (worksWithStr) {
var getOPDWorksOnObject = doesGOPDWork({}, 'sentinel');
if (getOPDWorksOnObject) {
var worksWithPrim = attempt(nativeGOPD, 42, 'name').threw === false;
var worksWithObjSym = require('has-symbol-support-x') && doesGOPDWork({}, Object(Symbol('')));
// eslint-disable-next-line max-depth
if (worksWithObjSym) {
// eslint-disable-next-line max-depth
if (worksWithPrim) {
$getOwnPropertyDescriptor = nativeGOPD;
} else {
$getOwnPropertyDescriptor = function getOwnPropertyDescriptor(object, property) {
return nativeGOPD(toObject(object), property);
};
}
} else if (worksWithPrim) {
$getOwnPropertyDescriptor = function getOwnPropertyDescriptor(object, property) {
return nativeGOPD(object, toPropertyKey(property));
};
} else {
$getOwnPropertyDescriptor = function getOwnPropertyDescriptor(object, property) {
return nativeGOPD(toObject(object), toPropertyKey(property));
};
}
} else {
getOPDFallback1 = nativeGOPD;
}
} else {
getOPDFallback2 = nativeGOPD;
}
}
}
if (isFalsey($getOwnPropertyDescriptor) || getOPDFallback1 || getOPDFallback2) {
var owns = require('has-own-property-x');
var isPrimitive = require('is-primitive');
var isString = require('is-string');
var isIndex = require('is-index-x');
var propertyIsEnumerable = require('property-is-enumerable-x');
var prototypeOfObject = Object.prototype;
// If JS engine supports accessors creating shortcuts.
var lookupGetter;
var lookupSetter;
var supportsAccessors = owns(prototypeOfObject, '__defineGetter__');
if (supportsAccessors) {
// eslint-disable-next-line no-underscore-dangle
var lg = prototypeOfObject.__lookupGetter__;
// eslint-disable-next-line no-underscore-dangle
var ls = prototypeOfObject.__lookupSetter__;
lookupGetter = function (object, property) {
return lg.call(object, property);
};
lookupSetter = function (object, property) {
return ls.call(object, property);
};
}
$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;
};
}
/**
* This method returns a property descriptor for an own property (that is,
* one directly present on an object and not in the object's prototype chain)
* of a given object.
*
* @param {*} object - The object in which to look for the property.
* @param {*} property - The name of the property whose description is to be retrieved.
* @returns {Object} A property descriptor of the given property if it exists on the object, undefined otherwise.
* @example
* var getOwnPropertyDescriptor = require('object-get-own-property-descriptor-x');
* var obj = { bar: 42 };
* var d = getOwnPropertyDescriptor(o, 'bar');
* // d is {
* // configurable: true,
* // enumerable: true,
* // value: 42,
* // writable: true
* // }
*/
module.exports = $getOwnPropertyDescriptor;