Bug 1370139 - Escape slashes in TreeView paths. r=Honza

This commit is contained in:
Oriol 2017-06-05 20:31:00 -04:00
Родитель 5d8aa01e08
Коммит d4593a2a0d
6 изменённых файлов: 81 добавлений и 78 удалений

Просмотреть файл

@ -8,7 +8,8 @@
define(function (require, exports, module) { define(function (require, exports, module) {
const { DOM: dom, createFactory, createClass, PropTypes } = require("devtools/client/shared/vendor/react"); const { DOM: dom, createFactory, createClass, PropTypes } = require("devtools/client/shared/vendor/react");
const TreeView = createFactory(require("devtools/client/shared/components/tree/tree-view")); const TreeViewClass = require("devtools/client/shared/components/tree/tree-view");
const TreeView = createFactory(TreeViewClass);
const { REPS, MODE } = require("devtools/client/shared/components/reps/reps"); const { REPS, MODE } = require("devtools/client/shared/components/reps/reps");
const { createFactories } = require("devtools/client/shared/react-utils"); const { createFactories } = require("devtools/client/shared/react-utils");
@ -65,28 +66,6 @@ define(function (require, exports, module) {
return json.toLowerCase().indexOf(this.props.searchFilter.toLowerCase()) >= 0; 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 => { renderValue: props => {
let member = props.member; let member = props.member;
@ -112,7 +91,10 @@ define(function (require, exports, module) {
// Expand the document by default if its size isn't bigger than 100KB. // Expand the document by default if its size isn't bigger than 100KB.
let expandedNodes = new Set(); let expandedNodes = new Set();
if (this.props.jsonTextLength <= AUTO_EXPAND_MAX_SIZE) { if (this.props.jsonTextLength <= AUTO_EXPAND_MAX_SIZE) {
expandedNodes = this.getExpandedNodes(this.props.data); expandedNodes = TreeViewClass.getExpandedNodes(
this.props.data,
{maxLevel: AUTO_EXPAND_MAX_LEVEL}
);
} }
// Render tree component. // Render tree component.

Просмотреть файл

@ -35,6 +35,7 @@ skip-if = (os == 'linux' && bits == 32 && debug) # bug 1328915, disable linux32
[browser_jsonview_save_json.js] [browser_jsonview_save_json.js]
support-files = support-files =
!/toolkit/content/tests/browser/common/mockTransfer.js !/toolkit/content/tests/browser/common/mockTransfer.js
[browser_jsonview_slash.js]
[browser_jsonview_utf8.js] [browser_jsonview_utf8.js]
[browser_jsonview_valid_json.js] [browser_jsonview_valid_json.js]
[browser_json_refresh.js] [browser_json_refresh.js]

Просмотреть файл

@ -0,0 +1,16 @@
/* -*- 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");
});

Просмотреть файл

@ -20,7 +20,8 @@ const { FILTER_SEARCH_DELAY } = require("../constants");
// Components // Components
const SearchBox = createFactory(require("devtools/client/shared/components/search-box")); const SearchBox = createFactory(require("devtools/client/shared/components/search-box"));
const TreeView = createFactory(require("devtools/client/shared/components/tree/tree-view")); const TreeViewClass = require("devtools/client/shared/components/tree/tree-view");
const TreeView = createFactory(TreeViewClass);
const TreeRow = createFactory(require("devtools/client/shared/components/tree/tree-row")); const TreeRow = createFactory(require("devtools/client/shared/components/tree/tree-row"));
const SourceEditor = createFactory(require("./source-editor")); const SourceEditor = createFactory(require("./source-editor"));
@ -137,38 +138,6 @@ 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() { render() {
const { const {
decorator, decorator,
@ -205,7 +174,10 @@ const PropertiesView = createClass({
enableInput, enableInput,
expandableStrings, expandableStrings,
useQuotes: false, useQuotes: false,
expandedNodes: this.getExpandedNodes(object), expandedNodes: TreeViewClass.getExpandedNodes(
object,
{maxLevel: AUTO_EXPAND_MAX_LEVEL, maxNodes: AUTO_EXPAND_MAX_NODES}
),
onFilter: (props) => this.onFilter(props, sectionNames), onFilter: (props) => this.onFilter(props, sectionNames),
renderRow: renderRow || this.renderRowWithEditor, renderRow: renderRow || this.renderRowWithEditor,
renderValue: renderValue || this.renderValueWithRep, renderValue: renderValue || this.renderValueWithRep,

Просмотреть файл

@ -13,6 +13,7 @@ const { L10N } = require("../utils/l10n");
const { getUrlHost } = require("../utils/request-utils"); const { getUrlHost } = require("../utils/request-utils");
// Components // Components
const TreeViewClass = require("devtools/client/shared/components/tree/tree-view");
const PropertiesView = createFactory(require("./properties-view")); const PropertiesView = createFactory(require("./properties-view"));
const { div, input, span } = DOM; const { div, input, span } = DOM;
@ -95,7 +96,7 @@ function SecurityPanel({ request }) {
object, object,
renderValue: (props) => renderValue(props, securityInfo.weaknessReasons), renderValue: (props) => renderValue(props, securityInfo.weaknessReasons),
enableFilter: false, enableFilter: false,
expandedNodes: getExpandedNodes(object), expandedNodes: TreeViewClass.getExpandedNodes(object),
}) })
); );
} }
@ -139,22 +140,4 @@ 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; module.exports = SecurityPanel;

Просмотреть файл

@ -277,7 +277,7 @@ define(function (require, exports, module) {
return children.map(child => { return children.map(child => {
let key = provider.getKey(child); let key = provider.getKey(child);
let nodePath = path + "/" + key; let nodePath = TreeView.subPath(path, key);
let type = provider.getType(child); let type = provider.getType(child);
let hasChildren = provider.hasChildren(child); let hasChildren = provider.hasChildren(child);
@ -419,6 +419,55 @@ 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 // Helpers
/** /**