diff --git a/packages/devtools-reps/src/object-inspector/actions.js b/packages/devtools-reps/src/object-inspector/actions.js index d34b2bcb9..f6d02800d 100644 --- a/packages/devtools-reps/src/object-inspector/actions.js +++ b/packages/devtools-reps/src/object-inspector/actions.js @@ -5,6 +5,7 @@ // @flow import type { + GripProperties, LoadedProperties, Node, ObjectClient, @@ -12,6 +13,10 @@ import type { ReduxAction, } from "./types"; +const { + loadItemProperties, +} = require("./utils/load-properties"); + type Dispatch = ReduxAction => void; type ThunkArg = { @@ -19,27 +24,6 @@ type ThunkArg = { dispatch: Dispatch, } -const { - getClosestGripNode, - getValue, -} = require("./utils/node"); - -const { - shouldLoadItemEntries, - shouldLoadItemIndexedProperties, - shouldLoadItemNonIndexedProperties, - shouldLoadItemPrototype, - shouldLoadItemSymbols, -} = require("./utils/load-properties"); - -const { - enumEntries, - enumIndexedProperties, - enumNonIndexedProperties, - getPrototype, - enumSymbols, -} = require("./utils/client"); - /** * This action is responsible for expanding a given node, * which also means that it will call the action responsible to fetch properties. @@ -84,40 +68,10 @@ function nodeLoadProperties( ) { return async ({dispatch} : ThunkArg) => { try { - const gripItem = getClosestGripNode(item); - const value = getValue(gripItem); - - const [start, end] = item.meta - ? [item.meta.startIndex, item.meta.endIndex] - : []; - - let promises = []; - let objectClient; - const getObjectClient = () => objectClient || createObjectClient(value); - - if (shouldLoadItemIndexedProperties(item, loadedProperties)) { - promises.push(enumIndexedProperties(getObjectClient(), start, end)); - } - - if (shouldLoadItemNonIndexedProperties(item, loadedProperties)) { - promises.push(enumNonIndexedProperties(getObjectClient(), start, end)); - } - - if (shouldLoadItemEntries(item, loadedProperties)) { - promises.push(enumEntries(getObjectClient(), start, end)); - } - - if (shouldLoadItemPrototype(item, loadedProperties)) { - promises.push(getPrototype(getObjectClient())); - } - - if (shouldLoadItemSymbols(item, loadedProperties)) { - promises.push(enumSymbols(getObjectClient(), start, end)); - } - - if (promises.length > 0) { - const responses = await Promise.all(promises); - dispatch(nodePropertiesLoaded(item, actor, responses)); + const properties = + await loadItemProperties(item, createObjectClient, loadedProperties); + if (Object.keys(properties).length > 0) { + dispatch(nodePropertiesLoaded(item, actor, properties)); } } catch (e) { console.error(e); @@ -128,11 +82,11 @@ function nodeLoadProperties( function nodePropertiesLoaded( node : Node, actor?: string, - responses : Array + properties: GripProperties ) { return { type: "NODE_PROPERTIES_LOADED", - data: {node, actor, responses} + data: {node, actor, properties} }; } diff --git a/packages/devtools-reps/src/object-inspector/reducer.js b/packages/devtools-reps/src/object-inspector/reducer.js index 4be60c63f..227268749 100644 --- a/packages/devtools-reps/src/object-inspector/reducer.js +++ b/packages/devtools-reps/src/object-inspector/reducer.js @@ -32,13 +32,10 @@ function reducer( } if (type === "NODE_PROPERTIES_LOADED") { - // Let's loop through the responses to build a single object. - const properties = mergeResponses(data.responses); - return cloneState({ actors: data.actor ? (new Set(state.actors || [])).add(data.actor) : state.actors, loadedProperties: (new Map(state.loadedProperties)) - .set(data.node.path, properties), + .set(data.node.path, action.data.properties), }); } @@ -51,24 +48,4 @@ function reducer( return state; } -function mergeResponses(responses: Array) : Object { - const data = {}; - - for (const response of responses) { - if (response.hasOwnProperty("ownProperties")) { - data.ownProperties = {...data.ownProperties, ...response.ownProperties}; - } - - if (response.ownSymbols && response.ownSymbols.length > 0) { - data.ownSymbols = response.ownSymbols; - } - - if (response.prototype) { - data.prototype = response.prototype; - } - } - - return data; -} - module.exports = reducer; diff --git a/packages/devtools-reps/src/object-inspector/utils/load-properties.js b/packages/devtools-reps/src/object-inspector/utils/load-properties.js index c890636e7..f7387b665 100644 --- a/packages/devtools-reps/src/object-inspector/utils/load-properties.js +++ b/packages/devtools-reps/src/object-inspector/utils/load-properties.js @@ -2,6 +2,14 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +const { + enumEntries, + enumIndexedProperties, + enumNonIndexedProperties, + getPrototype, + enumSymbols, +} = require("./client"); + const { getClosestGripNode, getClosestNonBucketNode, @@ -19,10 +27,72 @@ const { } = require("./node"); import type { + GripProperties, LoadedProperties, Node, + ObjectClient, + RdpGrip, } from "../types"; +function loadItemProperties( + item : Node, + createObjectClient : (RdpGrip) => ObjectClient, + loadedProperties : LoadedProperties, +) : Promise { + const gripItem = getClosestGripNode(item); + const value = getValue(gripItem); + + const [start, end] = item.meta + ? [item.meta.startIndex, item.meta.endIndex] + : []; + + let promises = []; + let objectClient; + const getObjectClient = () => objectClient || createObjectClient(value); + + if (shouldLoadItemIndexedProperties(item, loadedProperties)) { + promises.push(enumIndexedProperties(getObjectClient(), start, end)); + } + + if (shouldLoadItemNonIndexedProperties(item, loadedProperties)) { + promises.push(enumNonIndexedProperties(getObjectClient(), start, end)); + } + + if (shouldLoadItemEntries(item, loadedProperties)) { + promises.push(enumEntries(getObjectClient(), start, end)); + } + + if (shouldLoadItemPrototype(item, loadedProperties)) { + promises.push(getPrototype(getObjectClient())); + } + + if (shouldLoadItemSymbols(item, loadedProperties)) { + promises.push(enumSymbols(getObjectClient(), start, end)); + } + + return Promise.all(promises).then(mergeResponses); +} + +function mergeResponses(responses: Array) : Object { + const data = {}; + + for (const response of responses) { + if (response.hasOwnProperty("ownProperties")) { + data.ownProperties = {...data.ownProperties, ...response.ownProperties}; + } + + if (response.ownSymbols && response.ownSymbols.length > 0) { + data.ownSymbols = response.ownSymbols; + } + + if (response.prototype) { + data.prototype = response.prototype; + } + } + + return data; +} + function shouldLoadItemIndexedProperties( item: Node, loadedProperties: LoadedProperties = new Map() @@ -105,6 +175,8 @@ function shouldLoadItemSymbols( } module.exports = { + loadItemProperties, + mergeResponses, shouldLoadItemEntries, shouldLoadItemIndexedProperties, shouldLoadItemNonIndexedProperties,