+ _propertyDescriptors: function(object, ownProperties, ownAndGetterProperties)
+ {
+ // Modes:
+ // - ownProperties - only own properties and __proto__
+ // - ownAndGetterProperties - own properties, __proto__, and getters in the prototype chain
+ // - neither - get all properties in the prototype chain, exclude __proto__
+
+ var descriptors = [];
+ var nameProcessed = {};
+ nameProcessed["__proto__"] = null;
+
+ function createFakeValueDescriptor(name, descriptor, isOwnProperty)
+ {
+ try {
+ return {name: name, value: object[name], writable: descriptor.writable || false, configurable: descriptor.configurable || false, enumerable: descriptor.enumerable || false};
+ } catch (e) {
+ var errorDescriptor = {name: name, value: e, wasThrown: true};
+ if (isOwnProperty)
+ errorDescriptor.isOwn = true;
+ return errorDescriptor;
+ }
+ }
+
+ function processDescriptor(descriptor, isOwnProperty, possibleNativeBindingGetter)
+ {
+ // Own properties only.
+ if (ownProperties) {
+ if (isOwnProperty)
+ descriptors.push(descriptor);
+ return;
+ }
+
+ // Own and getter properties.
+ if (ownAndGetterProperties) {
+ if (isOwnProperty) {
+ // Own property, include the descriptor as is.
+ descriptors.push(descriptor);
+ } else if (descriptor.hasOwnProperty("get") && descriptor.get) {
+ // Getter property in the prototype chain. Create a fake value descriptor.
+ descriptors.push(createFakeValueDescriptor(descriptor.name, descriptor, isOwnProperty));
+ } else if (possibleNativeBindingGetter) {
+ // Possible getter property in the prototype chain.
+ descriptors.push(descriptor);
+ }
+ return;
+ }
+
+ // All properties.
+ descriptors.push(descriptor);
+ }
+
+ function processPropertyNames(o, names, isOwnProperty)
+ {
+ for (var i = 0; i < names.length; ++i) {
+ var name = names[i];
+ if (nameProcessed[name] || name === "__proto__")
+ continue;
+
+ nameProcessed[name] = true;
+
+ var descriptor = Object.getOwnPropertyDescriptor(o, name);
+ if (!descriptor) {
+ // FIXME: Bad descriptor. Can we get here?
+ // Fall back to very restrictive settings.
+ var fakeDescriptor = createFakeValueDescriptor(name, {writable: false, configurable: false, enumerable: false}, isOwnProperty);
+ processDescriptor(fakeDescriptor, isOwnProperty);
+ continue;
+ }
+
+ if (descriptor.hasOwnProperty("get") && descriptor.hasOwnProperty("set") && !descriptor.get && !descriptor.set) {
+ // FIXME: <https://webkit.org/b/140575> Web Inspector: Native Bindings Descriptors are Incomplete
+ // Developers may create such a descriptors, so we should be resilient:
+ // var x = {}; Object.defineProperty(x, "p", {get:undefined}); Object.getOwnPropertyDescriptor(x, "p")
+ var fakeDescriptor = createFakeValueDescriptor(name, descriptor, isOwnProperty);
+ processDescriptor(fakeDescriptor, isOwnProperty, true);
+ continue;
+ }
+
+ descriptor.name = name;
+ if (isOwnProperty)
+ descriptor.isOwn = true;
+ processDescriptor(descriptor, isOwnProperty);
+ }
+ }
+
+ // Iterate prototype chain.
+ for (var o = object; this._isDefined(o); o = o.__proto__) {
+ var isOwnProperty = o === object;
+ processPropertyNames(o, Object.getOwnPropertyNames(o), isOwnProperty);
+ if (ownProperties)
+ break;
+ }
+
+ // Include __proto__ at the end.
+ try {
+ if (object.__proto__)
+ descriptors.push({name: "__proto__", value: object.__proto__, writable: true, configurable: true, enumerable: false, isOwn: true});
+ } catch (e) {}
+
+ return descriptors;
+ },
+