⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 178768 in webkit


Ignore:
Timestamp:
Jan 20, 2015, 4:34:57 PM (12 years ago)
Author:
commit-queue@webkit.org
Message:

Web Inspector: Expanding event objects in console shows undefined for most values, it should have real values
​https://bugs.webkit.org/show_bug.cgi?id=137306

Patch by Joseph Pecoraro <Joseph Pecoraro> on 2015-01-20
Reviewed by Timothy Hatcher.

Source/JavaScriptCore:

Provide another optional parameter to getProperties, to gather a list
of all own and getter properties.

  • inspector/InjectedScript.cpp:

(Inspector::InjectedScript::getProperties):

  • inspector/InjectedScript.h:
  • inspector/InjectedScriptSource.js:
  • inspector/agents/InspectorRuntimeAgent.cpp:

(Inspector::InspectorRuntimeAgent::getProperties):

  • inspector/agents/InspectorRuntimeAgent.h:
  • inspector/protocol/Runtime.json:

Source/WebInspectorUI:

When first expanding an object, show all the object's own properties and any
getter properties that may be on its prototype chain. Now, we only fetch
own properties, for proto properties.

  • UserInterface/Protocol/RemoteObject.js:

(WebInspector.RemoteObject.prototype.getOwnProperties):
(WebInspector.RemoteObject.prototype.getOwnAndGetterProperties):
(WebInspector.RemoteObject.prototype.getAllProperties):
(WebInspector.RemoteObject.prototype.get hasChildren): Deleted.

  • UserInterface/Views/ObjectPropertiesSection.js:

(WebInspector.ObjectPropertiesSection):
(WebInspector.ObjectPropertiesSection.prototype.update):
(WebInspector.ObjectPropertyTreeElement.prototype.onpopulate):

LayoutTests:

  • inspector/model/remote-object-get-properties-expected.txt: Added.
  • inspector/model/remote-object-get-properties.html: Added.
Location:
trunk
Files:
2 added
11 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r178767 r178768  
     12015-01-20  Joseph Pecoraro  <pecoraro@apple.com>
     2
     3        Web Inspector: Expanding event objects in console shows undefined for most values, it should have real values
     4        https://bugs.webkit.org/show_bug.cgi?id=137306
     5
     6        Reviewed by Timothy Hatcher.
     7
     8        * inspector/model/remote-object-get-properties-expected.txt: Added.
     9        * inspector/model/remote-object-get-properties.html: Added.
     10
    1112015-01-20  Joseph Pecoraro  <pecoraro@apple.com>
    212
  • trunk/Source/JavaScriptCore/ChangeLog

    r178767 r178768  
     12015-01-20  Joseph Pecoraro  <pecoraro@apple.com>
     2
     3        Web Inspector: Expanding event objects in console shows undefined for most values, it should have real values
     4        https://bugs.webkit.org/show_bug.cgi?id=137306
     5
     6        Reviewed by Timothy Hatcher.
     7
     8        Provide another optional parameter to getProperties, to gather a list
     9        of all own and getter properties.
     10
     11        * inspector/InjectedScript.cpp:
     12        (Inspector::InjectedScript::getProperties):
     13        * inspector/InjectedScript.h:
     14        * inspector/InjectedScriptSource.js:
     15        * inspector/agents/InspectorRuntimeAgent.cpp:
     16        (Inspector::InspectorRuntimeAgent::getProperties):
     17        * inspector/agents/InspectorRuntimeAgent.h:
     18        * inspector/protocol/Runtime.json:
     19
    1202015-01-20  Joseph Pecoraro  <pecoraro@apple.com>
    221
  • trunk/Source/JavaScriptCore/inspector/InjectedScript.cpp

    r178060 r178768  
    110110}
    111111
    112 void InjectedScript::getProperties(ErrorString& errorString, const String& objectId, bool ownProperties, RefPtr<Array<Inspector::Protocol::Runtime::PropertyDescriptor>>* properties)
     112void InjectedScript::getProperties(ErrorString& errorString, const String& objectId, bool ownProperties, bool ownAndGetterProperties, RefPtr<Array<Inspector::Protocol::Runtime::PropertyDescriptor>>* properties)
    113113{
    114114    Deprecated::ScriptFunctionCall function(injectedScriptObject(), ASCIILiteral("getProperties"), inspectorEnvironment()->functionCallHandler());
    115115    function.appendArgument(objectId);
    116116    function.appendArgument(ownProperties);
     117    function.appendArgument(ownAndGetterProperties);
    117118
    118119    RefPtr<InspectorValue> result;
  • trunk/Source/JavaScriptCore/inspector/InjectedScript.h

    r178060 r178768  
    6060    void evaluateOnCallFrame(ErrorString&, const Deprecated::ScriptValue& callFrames, const String& callFrameId, const String& expression, const String& objectGroup, bool includeCommandLineAPI, bool returnByValue, bool generatePreview, RefPtr<Protocol::Runtime::RemoteObject>* result, Protocol::OptOutput<bool>* wasThrown);
    6161    void getFunctionDetails(ErrorString&, const String& functionId, RefPtr<Protocol::Debugger::FunctionDetails>* result);
    62     void getProperties(ErrorString&, const String& objectId, bool ownProperties, RefPtr<Protocol::Array<Protocol::Runtime::PropertyDescriptor>>* result);
     62    void getProperties(ErrorString&, const String& objectId, bool ownProperties, bool ownAndGetterProperties, RefPtr<Protocol::Array<Protocol::Runtime::PropertyDescriptor>>* result);
    6363    void getInternalProperties(ErrorString&, const String& objectId, RefPtr<Protocol::Array<Protocol::Runtime::InternalPropertyDescriptor>>* result);
    6464
  • trunk/Source/JavaScriptCore/inspector/InjectedScriptSource.js

    r176357 r178768  
    227227    },
    228228
    229     /**
    230      * @param {string} objectId
    231      * @param {boolean} ownProperties
    232      * @return {Array.<RuntimeAgent.PropertyDescriptor>|boolean}
    233      */
    234     getProperties: function(objectId, ownProperties)
     229    getProperties: function(objectId, ownProperties, ownAndGetterProperties)
    235230    {
    236231        var parsedObjectId = this._parseObjectId(objectId);
    … …  
    240235        if (!this._isDefined(object))
    241236            return false;
    242         var descriptors = this._propertyDescriptors(object, ownProperties);
     237
     238        var descriptors = this._propertyDescriptors(object, ownProperties, ownAndGetterProperties);
    243239
    244240        // Go over properties, wrap object values.
    … …  
    256252                descriptor.enumerable = false;
    257253        }
     254
    258255        return descriptors;
    259256    },
    … …  
    329326
    330327    /**
    331      * @param {Object} object
    332      * @param {boolean} ownProperties
    333      * @return {Array.<Object>}
    334      */
    335     _propertyDescriptors: function(object, ownProperties)
    336     {
    337         var descriptors = [];
    338         var nameProcessed = {};
    339         nameProcessed["__proto__"] = null;
    340         for (var o = object; this._isDefined(o); o = o.__proto__) {
    341             var names = Object.getOwnPropertyNames(/** @type {!Object} */ (o));
    342             for (var i = 0; i < names.length; ++i) {
    343                 var name = names[i];
    344                 if (nameProcessed[name])
    345                     continue;
    346 
    347                 try {
    348                     nameProcessed[name] = true;
    349                     var descriptor = Object.getOwnPropertyDescriptor(/** @type {!Object} */ (object), name);
    350                     if (!descriptor) {
    351                         // Not all bindings provide proper descriptors. Fall back to the writable, configurable property.
    352                         try {
    353                             descriptor = { name: name, value: object[name], writable: false, configurable: false, enumerable: false};
    354                             if (o === object)
    355                                 descriptor.isOwn = true;
    356                             descriptors.push(descriptor);
    357                         } catch (e) {
    358                             // Silent catch.
    359                         }
    360                         continue;
    361                     }
    362                     if (descriptor.hasOwnProperty("get") && descriptor.hasOwnProperty("set") && !descriptor.get && !descriptor.set) {
    363                         // Not all bindings provide proper descriptors. Fall back to the writable, configurable property.
    364                         try {
    365                             descriptor = { name: name, value: object[name], writable: false, configurable: false, enumerable: false};
    366                             if (o === object)
    367                                 descriptor.isOwn = true;
    368                             descriptors.push(descriptor);
    369                         } catch (e) {
    370                             // Silent catch.
    371                         }
    372                         continue;
    373                     }
    374                 } catch (e) {
    375                     var descriptor = {};
    376                     descriptor.value = e;
    377                     descriptor.wasThrown = true;
    378                 }
    379 
    380                 descriptor.name = name;
    381                 if (o === object)
    382                     descriptor.isOwn = true;
    383                 descriptors.push(descriptor);
    384             }
    385             if (ownProperties) {
    386                 if (object.__proto__)
    387                     descriptors.push({ name: "__proto__", value: object.__proto__, writable: true, configurable: true, enumerable: false, isOwn: true});
    388                 break;
    389             }
    390         }
    391         return descriptors;
    392     },
    393 
    394     /**
    395328     * @param {string} expression
    396329     * @param {string} objectGroup
    … …  
    688621        this._modules[name] = module;
    689622        return module;
     623    },
     624
     625    _propertyDescriptors: function(object, ownProperties, ownAndGetterProperties)
     626    {
     627        // Modes:
     628        //  - ownProperties - only own properties and __proto__
     629        //  - ownAndGetterProperties - own properties, __proto__, and getters in the prototype chain
     630        //  - neither - get all properties in the prototype chain, exclude __proto__
     631
     632        var descriptors = [];
     633        var nameProcessed = {};
     634        nameProcessed["__proto__"] = null;
     635
     636        function createFakeValueDescriptor(name, descriptor, isOwnProperty)
     637        {
     638            try {
     639                return {name: name, value: object[name], writable: descriptor.writable, configurable: descriptor.configurable, enumerable: descriptor.enumerable};
     640            } catch (e) {
     641                var errorDescriptor = {name: name, value: e, wasThrown: true};
     642                if (isOwnProperty)
     643                    errorDescriptor.isOwn = true;
     644                return errorDescriptor;
     645            }
     646        }
     647
     648        function processDescriptor(descriptor, isOwnProperty)
     649        {
     650            // Own properties only.
     651            if (ownProperties) {
     652                if (isOwnProperty)
     653                    descriptors.push(descriptor);
     654                return;
     655            }
     656
     657            // Own and getter properties.
     658            if (ownAndGetterProperties) {
     659                if (isOwnProperty) {
     660                    // Own property, include the descriptor as is.
     661                    descriptors.push(descriptor);
     662                } else if (descriptor.hasOwnProperty("get") && descriptor.get) {
     663                    // Getter property in the prototype chain. Create a fake value descriptor.
     664                    descriptors.push(createFakeValueDescriptor(descriptor.name, descriptor, isOwnProperty));
     665                } else if (descriptor.possibleNativeBindingGetter) {
     666                    // Possible getter property in the prototype chain.
     667                    descriptors.push(descriptor);
     668                }
     669                return;
     670            }
     671
     672            // All properties.
     673            descriptors.push(descriptor);
     674        }
     675
     676        function processPropertyNames(o, names, isOwnProperty)
     677        {
     678            for (var i = 0; i < names.length; ++i) {
     679                var name = names[i];
     680                if (nameProcessed[name] || name === "__proto__")
     681                    continue;
     682
     683                nameProcessed[name] = true;
     684
     685                var descriptor = Object.getOwnPropertyDescriptor(o, name);
     686                if (!descriptor) {
     687                    // FIXME: Bad descriptor. Can we get here?
     688                    // Fall back to very restrictive settings.
     689                    var fakeDescriptor = createFakeValueDescriptor(name, {writable: false, configurable: false, enumerable: false}, isOwnProperty);
     690                    processDescriptor(fakeDescriptor, isOwnProperty);
     691                    continue;
     692                }
     693
     694                if (descriptor.hasOwnProperty("get") && descriptor.hasOwnProperty("set") && !descriptor.get && !descriptor.set) {
     695                    // FIXME: <https://webkit.org/b/140575> Web Inspector: Native Bindings Descriptors are Incomplete
     696                    // Developers may create such a descriptors, so we should be resilient:
     697                    // var x = {}; Object.defineProperty(x, "p", {get:undefined}); Object.getOwnPropertyDescriptor(x, "p")
     698                    var fakeDescriptor = createFakeValueDescriptor(name, descriptor, isOwnProperty);
     699                    fakeDescriptor.possibleNativeBindingGetter = true; // Native bindings.
     700                    processDescriptor(fakeDescriptor, isOwnProperty);
     701                    continue;
     702                }
     703
     704                descriptor.name = name;
     705                if (isOwnProperty)
     706                    descriptor.isOwn = true;
     707                processDescriptor(descriptor, isOwnProperty);
     708            }
     709        }
     710
     711        // Iterate prototype chain.
     712        for (var o = object; this._isDefined(o); o = o.__proto__) {
     713            var isOwnProperty = o === object;
     714            processPropertyNames(o, Object.getOwnPropertyNames(o), isOwnProperty);
     715            if (ownProperties)
     716                break;
     717        }
     718       
     719        // Include __proto__ at the end.
     720        try {
     721            if (object.__proto__)
     722                descriptors.push({name: "__proto__", value: object.__proto__, writable: true, configurable: true, enumerable: false, isOwn: true});
     723        } catch (e) {}
     724
     725        return descriptors;
    690726    },
    691727
  • trunk/Source/JavaScriptCore/inspector/agents/InspectorRuntimeAgent.cpp

    r178695 r178768  
    164164}
    165165
    166 void InspectorRuntimeAgent::getProperties(ErrorString& errorString, const String& objectId, const bool* const ownProperties, RefPtr<Inspector::Protocol::Array<Inspector::Protocol::Runtime::PropertyDescriptor>>& result, RefPtr<Inspector::Protocol::Array<Inspector::Protocol::Runtime::InternalPropertyDescriptor>>& internalProperties)
     166void InspectorRuntimeAgent::getProperties(ErrorString& errorString, const String& objectId, const bool* const ownProperties, const bool* const ownAndGetterProperties, RefPtr<Inspector::Protocol::Array<Inspector::Protocol::Runtime::PropertyDescriptor>>& result, RefPtr<Inspector::Protocol::Array<Inspector::Protocol::Runtime::InternalPropertyDescriptor>>& internalProperties)
    167167{
    168168    InjectedScript injectedScript = m_injectedScriptManager->injectedScriptForObjectId(objectId);
    … …  
    175175    muteConsole();
    176176
    177     injectedScript.getProperties(errorString, objectId, ownProperties ? *ownProperties : false, &result);
     177    injectedScript.getProperties(errorString, objectId, ownProperties ? *ownProperties : false, ownAndGetterProperties ? *ownAndGetterProperties : false, &result);
    178178    injectedScript.getInternalProperties(errorString, objectId, &internalProperties);
    179179
  • trunk/Source/JavaScriptCore/inspector/agents/InspectorRuntimeAgent.h

    r178060 r178768  
    6666    virtual void callFunctionOn(ErrorString&, const String& objectId, const String& expression, const RefPtr<Inspector::InspectorArray>&& optionalArguments, const bool* doNotPauseOnExceptionsAndMuteConsole, const bool* returnByValue, const bool* generatePreview, RefPtr<Inspector::Protocol::Runtime::RemoteObject>& result, Inspector::Protocol::OptOutput<bool>* wasThrown) override final;
    6767    virtual void releaseObject(ErrorString&, const ErrorString& objectId) override final;
    68     virtual void getProperties(ErrorString&, const String& objectId, const bool* ownProperties, RefPtr<Inspector::Protocol::Array<Inspector::Protocol::Runtime::PropertyDescriptor>>& result, RefPtr<Inspector::Protocol::Array<Inspector::Protocol::Runtime::InternalPropertyDescriptor>>& internalProperties) override final;
     68    virtual void getProperties(ErrorString&, const String& objectId, const bool* ownProperties, const bool* ownAndGetterProperties, RefPtr<Inspector::Protocol::Array<Inspector::Protocol::Runtime::PropertyDescriptor>>& result, RefPtr<Inspector::Protocol::Array<Inspector::Protocol::Runtime::InternalPropertyDescriptor>>& internalProperties) override final;
    6969    virtual void releaseObjectGroup(ErrorString&, const String& objectGroup) override final;
    7070    virtual void run(ErrorString&) override;
  • trunk/Source/JavaScriptCore/inspector/protocol/Runtime.json

    r177008 r178768  
    216216            "parameters": [
    217217                { "name": "objectId", "$ref": "RemoteObjectId", "description": "Identifier of the object to return properties for." },
    218                 { "name": "ownProperties", "optional": true, "type": "boolean", "description": "If true, returns properties belonging only to the element itself, not to its prototype chain." }
     218                { "name": "ownProperties", "optional": true, "type": "boolean", "description": "If true, returns properties belonging only to the object itself, not to its prototype chain." },
     219                { "name": "ownAndGetterProperties", "optional": true, "type": "boolean", "description": "If true, returns properties belonging to the object itself, and getters in its prototype chain." }
    219220            ],
    220221            "returns": [
  • trunk/Source/WebInspectorUI/ChangeLog

    r178767 r178768  
     12015-01-20  Joseph Pecoraro  <pecoraro@apple.com>
     2
     3        Web Inspector: Expanding event objects in console shows undefined for most values, it should have real values
     4        https://bugs.webkit.org/show_bug.cgi?id=137306
     5
     6        Reviewed by Timothy Hatcher.
     7
     8        When first expanding an object, show all the object's own properties and any
     9        getter properties that may be on its prototype chain. Now, we only fetch
     10        own properties, for __proto__ properties.
     11
     12        * UserInterface/Protocol/RemoteObject.js:
     13        (WebInspector.RemoteObject.prototype.getOwnProperties):
     14        (WebInspector.RemoteObject.prototype.getOwnAndGetterProperties):
     15        (WebInspector.RemoteObject.prototype.getAllProperties):
     16        (WebInspector.RemoteObject.prototype.get hasChildren): Deleted.
     17        * UserInterface/Views/ObjectPropertiesSection.js:
     18        (WebInspector.ObjectPropertiesSection):
     19        (WebInspector.ObjectPropertiesSection.prototype.update):
     20        (WebInspector.ObjectPropertyTreeElement.prototype.onpopulate):
     21
    1222015-01-20  Joseph Pecoraro  <pecoraro@apple.com>
    223
  • trunk/Source/WebInspectorUI/UserInterface/Protocol/RemoteObject.js

    r178610 r178768  
    114114    getOwnProperties: function(callback)
    115115    {
    116         this._getProperties(true, callback);
     116        this._getProperties(true, false, callback);
     117    },
     118
     119    getOwnAndGetterProperties: function(callback)
     120    {
     121        this._getProperties(false, true, callback);
    117122    },
    118123
    119124    getAllProperties: function(callback)
    120125    {
    121         this._getProperties(false, callback);
    122     },
    123 
    124     _getProperties: function(ownProperties, callback)
     126        this._getProperties(false, false, callback);
     127    },
     128
     129    _getProperties: function(ownProperties, ownAndGetterProperties, callback)
    125130    {
    126131        if (!this._objectId) {
    … …  
    148153            callback(result);
    149154        }
    150         RuntimeAgent.getProperties(this._objectId, ownProperties, remoteObjectBinder);
     155
     156        // COMPATIBILITY (iOS 8): RuntimeAgent.getProperties did not support ownerAndGetterProperties.
     157        // Here we do our best to reimplement it by getting all properties and reducing them down.
     158        if (ownAndGetterProperties && !RuntimeAgent.getProperties.supports("ownAndGetterProperties")) {
     159            RuntimeAgent.getProperties(this._objectId, function(error, allProperties) {
     160                var ownOrGetterPropertiesList = [];
     161                if (allProperties) {
     162                    for (var property of allProperties) {
     163                        if (property.isOwn || property.get || property.name === "__proto__") {
     164                            // Own property or getter property in prototype chain.
     165                            ownOrGetterPropertiesList.push(property);
     166                        } else if (property.value && property.name !== property.name.toUpperCase()) {
     167                            var type = property.value.type;
     168                            if (type && type !== "function" && property.name !== "constructor") {
     169                                // Possible native binding getter property converted to a value. Also, no CONSTANT name style and not "constructor".
     170                                ownOrGetterPropertiesList.push(property);
     171                            }
     172                        }
     173                    }
     174                }
     175                remoteObjectBinder(error, ownOrGetterPropertiesList);
     176            });
     177            return;
     178        }
     179
     180        RuntimeAgent.getProperties(this._objectId, ownProperties, ownAndGetterProperties, remoteObjectBinder);
    151181    },
    152182
  • trunk/Source/WebInspectorUI/UserInterface/Views/ObjectPropertiesSection.js

    r173432 r178768  
    2424 */
    2525
    26 WebInspector.ObjectPropertiesSection = function(object, title, subtitle, emptyPlaceholder, ignoreHasOwnProperty, extraProperties, treeElementConstructor)
     26WebInspector.ObjectPropertiesSection = function(object, title, subtitle, emptyPlaceholder, getAllProperties, extraProperties, treeElementConstructor)
    2727{
    2828    this.emptyPlaceholder = (emptyPlaceholder || WebInspector.UIString("No Properties"));
    2929    this.object = object;
    30     this.ignoreHasOwnProperty = ignoreHasOwnProperty;
     30    this.getAllProperties = getAllProperties;
    3131    this.extraProperties = extraProperties;
    3232    this.treeElementConstructor = treeElementConstructor || WebInspector.ObjectPropertyTreeElement;
    … …  
    5151            self.updateProperties(properties);
    5252        }
    53         if (this.ignoreHasOwnProperty)
     53        if (this.getAllProperties)
    5454            this.object.getAllProperties(callback);
    5555        else
    56             this.object.getOwnProperties(callback);
     56            this.object.getOwnAndGetterProperties(callback);
    5757    },
    5858
    … …  
    164164            }
    165165        };
    166         this.property.value.getOwnProperties(callback.bind(this));
     166
     167        if (this.property.name === "__proto__")
     168            this.property.value.getOwnProperties(callback.bind(this));
     169        else
     170            this.property.value.getOwnAndGetterProperties(callback.bind(this));
    167171    },
    168172
Note: See TracChangeset for help on using the changeset viewer.