diff --git a/devtools/client/jsonview/components/json-panel.js b/devtools/client/jsonview/components/json-panel.js index 096d15484bb6..bf992566a8a6 100644 --- a/devtools/client/jsonview/components/json-panel.js +++ b/devtools/client/jsonview/components/json-panel.js @@ -8,8 +8,7 @@ define(function (require, exports, module) { const { DOM: dom, createFactory, createClass, PropTypes } = require("devtools/client/shared/vendor/react"); - const TreeViewClass = require("devtools/client/shared/components/tree/tree-view"); - const TreeView = createFactory(TreeViewClass); + const TreeView = createFactory(require("devtools/client/shared/components/tree/tree-view")); const { REPS, MODE } = require("devtools/client/shared/components/reps/reps"); const { createFactories } = require("devtools/client/shared/react-utils"); @@ -66,6 +65,28 @@ define(function (require, exports, module) { return json.toLowerCase().indexOf(this.props.searchFilter.toLowerCase()) >= 0; }, + getExpandedNodes: function (object, path = "", level = 0) { + if (typeof object != "object") { + return null; + } + + if (level > AUTO_EXPAND_MAX_LEVEL) { + return null; + } + + let expandedNodes = new Set(); + for (let prop in object) { + let nodePath = path + "/" + prop; + expandedNodes.add(nodePath); + + let nodes = this.getExpandedNodes(object[prop], nodePath, level + 1); + if (nodes) { + expandedNodes = new Set([...expandedNodes, ...nodes]); + } + } + return expandedNodes; + }, + renderValue: props => { let member = props.member; @@ -91,10 +112,7 @@ define(function (require, exports, module) { // Expand the document by default if its size isn't bigger than 100KB. let expandedNodes = new Set(); if (this.props.jsonTextLength <= AUTO_EXPAND_MAX_SIZE) { - expandedNodes = TreeViewClass.getExpandedNodes( - this.props.data, - {maxLevel: AUTO_EXPAND_MAX_LEVEL} - ); + expandedNodes = this.getExpandedNodes(this.props.data); } // Render tree component. diff --git a/devtools/client/jsonview/test/browser.ini b/devtools/client/jsonview/test/browser.ini index 852f280bc7db..a7f4c6c8c51a 100644 --- a/devtools/client/jsonview/test/browser.ini +++ b/devtools/client/jsonview/test/browser.ini @@ -35,7 +35,6 @@ skip-if = (os == 'linux' && bits == 32 && debug) # bug 1328915, disable linux32 [browser_jsonview_save_json.js] support-files = !/toolkit/content/tests/browser/common/mockTransfer.js -[browser_jsonview_slash.js] [browser_jsonview_utf8.js] [browser_jsonview_valid_json.js] [browser_json_refresh.js] diff --git a/devtools/client/jsonview/test/browser_jsonview_slash.js b/devtools/client/jsonview/test/browser_jsonview_slash.js deleted file mode 100644 index 9a242b824ee5..000000000000 --- a/devtools/client/jsonview/test/browser_jsonview_slash.js +++ /dev/null @@ -1,16 +0,0 @@ -/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ -/* vim: set ts=2 et sw=2 tw=80: */ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -add_task(function* () { - info("Test JSON with NUL started."); - - const TEST_JSON_URL = "data:application/json,{\"a/b\":[1,2],\"a\":{\"b\":[3,4]}}"; - yield addJsonViewTab(TEST_JSON_URL); - - let countBefore = yield getElementCount(".jsonPanelBox .treeTable .treeRow"); - ok(countBefore == 7, "There must be seven rows"); -}); diff --git a/devtools/client/netmonitor/src/components/properties-view.js b/devtools/client/netmonitor/src/components/properties-view.js index 1d52ae8b3a21..04b6aee2d400 100644 --- a/devtools/client/netmonitor/src/components/properties-view.js +++ b/devtools/client/netmonitor/src/components/properties-view.js @@ -20,8 +20,7 @@ const { FILTER_SEARCH_DELAY } = require("../constants"); // Components const SearchBox = createFactory(require("devtools/client/shared/components/search-box")); -const TreeViewClass = require("devtools/client/shared/components/tree/tree-view"); -const TreeView = createFactory(TreeViewClass); +const TreeView = createFactory(require("devtools/client/shared/components/tree/tree-view")); const TreeRow = createFactory(require("devtools/client/shared/components/tree/tree-row")); const SourceEditor = createFactory(require("./source-editor")); @@ -138,6 +137,38 @@ const PropertiesView = createClass({ }); }, + getExpandedNodes: function (object, path = "", level = 0) { + if (typeof object != "object") { + return null; + } + + if (level > AUTO_EXPAND_MAX_LEVEL) { + return null; + } + + let expandedNodes = new Set(); + for (let prop in object) { + if (expandedNodes.size > AUTO_EXPAND_MAX_NODES) { + // If we reached the limit of expandable nodes, bail out to avoid performance + // issues. + break; + } + + let nodePath = path + "/" + prop; + expandedNodes.add(nodePath); + + let nodes = this.getExpandedNodes(object[prop], nodePath, level + 1); + if (nodes) { + let newSize = expandedNodes.size + nodes.size; + if (newSize < AUTO_EXPAND_MAX_NODES) { + // Avoid having a subtree half expanded. + expandedNodes = new Set([...expandedNodes, ...nodes]); + } + } + } + return expandedNodes; + }, + render() { const { decorator, @@ -174,10 +205,7 @@ const PropertiesView = createClass({ enableInput, expandableStrings, useQuotes: false, - expandedNodes: TreeViewClass.getExpandedNodes( - object, - {maxLevel: AUTO_EXPAND_MAX_LEVEL, maxNodes: AUTO_EXPAND_MAX_NODES} - ), + expandedNodes: this.getExpandedNodes(object), onFilter: (props) => this.onFilter(props, sectionNames), renderRow: renderRow || this.renderRowWithEditor, renderValue: renderValue || this.renderValueWithRep, diff --git a/devtools/client/netmonitor/src/components/security-panel.js b/devtools/client/netmonitor/src/components/security-panel.js index faceb47996eb..7606448ceae2 100644 --- a/devtools/client/netmonitor/src/components/security-panel.js +++ b/devtools/client/netmonitor/src/components/security-panel.js @@ -13,7 +13,6 @@ const { L10N } = require("../utils/l10n"); const { getUrlHost } = require("../utils/request-utils"); // Components -const TreeViewClass = require("devtools/client/shared/components/tree/tree-view"); const PropertiesView = createFactory(require("./properties-view")); const { div, input, span } = DOM; @@ -96,7 +95,7 @@ function SecurityPanel({ request }) { object, renderValue: (props) => renderValue(props, securityInfo.weaknessReasons), enableFilter: false, - expandedNodes: TreeViewClass.getExpandedNodes(object), + expandedNodes: getExpandedNodes(object), }) ); } @@ -140,4 +139,22 @@ function renderValue(props, weaknessReasons = []) { ); } +function getExpandedNodes(object, path = "", level = 0) { + if (typeof object !== "object") { + return null; + } + + let expandedNodes = new Set(); + for (let prop in object) { + let nodePath = path + "/" + prop; + expandedNodes.add(nodePath); + + let nodes = getExpandedNodes(object[prop], nodePath, level + 1); + if (nodes) { + expandedNodes = new Set([...expandedNodes, ...nodes]); + } + } + return expandedNodes; +} + module.exports = SecurityPanel; diff --git a/devtools/client/shared/components/tree/tree-view.js b/devtools/client/shared/components/tree/tree-view.js index 9d30f92ef8b0..d23c9c7c0755 100644 --- a/devtools/client/shared/components/tree/tree-view.js +++ b/devtools/client/shared/components/tree/tree-view.js @@ -277,7 +277,7 @@ define(function (require, exports, module) { return children.map(child => { let key = provider.getKey(child); - let nodePath = TreeView.subPath(path, key); + let nodePath = path + "/" + key; let type = provider.getType(child); let hasChildren = provider.hasChildren(child); @@ -419,55 +419,6 @@ define(function (require, exports, module) { } }); - TreeView.subPath = function (path, subKey) { - return path + "/" + subKey.replace(/[\\/]/g, "\\$&"); - }; - - /** - * Creates a set with the paths of the nodes that should be expanded by default - * according to the passed options. - * @param {Object} The root node of the tree. - * @param {Object} [optional] An object with the following optional parameters: - * - maxLevel: nodes nested deeper than this level won't be expanded. - * - maxNodes: maximum number of nodes that can be expanded. The traversal is - breadth-first, so expanding nodes nearer to the root will be preferred. - Sibling nodes will either be all expanded or none expanded. - * } - */ - TreeView.getExpandedNodes = function (rootObj, - { maxLevel = Infinity, maxNodes = Infinity } = {} - ) { - let expandedNodes = new Set(); - let queue = [{ - object: rootObj, - level: 1, - path: "" - }]; - while (queue.length) { - let {object, level, path} = queue.shift(); - if (Object(object) !== object) { - continue; - } - let keys = Object.keys(object); - if (expandedNodes.size + keys.length > maxNodes) { - // Avoid having children half expanded. - break; - } - for (let key of keys) { - let nodePath = TreeView.subPath(path, key); - expandedNodes.add(nodePath); - if (level < maxLevel) { - queue.push({ - object: object[key], - level: level + 1, - path: nodePath - }); - } - } - } - return expandedNodes; - }; - // Helpers /**