Skip to content
This repository was archived by the owner on Sep 21, 2021. It is now read-only.

Commit 607db6b

Browse files
committed
More efficient Object Reps construction.
The patch minimize the amount of time we have to build the keys from an object and loop over it.
1 parent afafbf3 commit 607db6b

File tree

1 file changed

+60
-90
lines changed

1 file changed

+60
-90
lines changed

packages/devtools-reps/src/reps/object.js

Lines changed: 60 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -88,100 +88,35 @@ function safePropIterator(props, object, max) {
8888
}
8989

9090
function propIterator(props, object, max) {
91-
let isInterestingProp = (type, value) => {
92-
// Do not pick objects, it could cause recursion.
93-
return (type == "boolean" || type == "number" || (type == "string" && value));
94-
};
95-
9691
// Work around https://bugzilla.mozilla.org/show_bug.cgi?id=945377
9792
if (Object.prototype.toString.call(object) === "[object Generator]") {
9893
object = Object.getPrototypeOf(object);
9994
}
10095

101-
// Object members with non-empty values are preferred since it gives the
102-
// user a better overview of the object.
103-
let interestingObject = getFilteredObject(object, max, isInterestingProp);
104-
105-
if (Object.keys(interestingObject).length < max) {
106-
// There are not enough props yet (or at least, not enough props to
107-
// be able to know whether we should print "more…" or not).
108-
// Let's display also empty members and functions.
109-
interestingObject = Object.assign({}, interestingObject,
110-
getFilteredObject(
111-
object,
112-
max - Object.keys(interestingObject).length,
113-
(type, value) => !isInterestingProp(type, value)
114-
)
115-
);
116-
}
117-
118-
let propsArray = getPropsArray(interestingObject, props);
119-
if (Object.keys(object).length > max) {
120-
propsArray.push(span({
121-
className: "more-ellipsis",
122-
title: "more…"
123-
}, "…"));
124-
}
125-
126-
return unfoldProps(propsArray);
127-
}
128-
129-
function unfoldProps(items) {
130-
return items.reduce((res, item, index) => {
131-
if (Array.isArray(item)) {
132-
res = res.concat(item);
133-
} else {
134-
res.push(item);
135-
}
136-
137-
// Interleave commas between elements
138-
if (index !== items.length - 1) {
139-
res.push(", ");
96+
const elements = [];
97+
const unimportantProperties = [];
98+
let propertiesNumber = 0;
99+
const propertiesNames = Object.keys(object);
100+
101+
const pushPropRep = (name, value) => {
102+
elements.push(PropRep(Object.assign({}, props, {
103+
key: name,
104+
mode: MODE.TINY,
105+
name,
106+
object: value,
107+
equal: ": ",
108+
})));
109+
propertiesNumber++;
110+
111+
if (propertiesNumber < propertiesNames.length) {
112+
elements.push(", ");
140113
}
141-
return res;
142-
}, []);
143-
}
144-
145-
/**
146-
* Get an array of components representing the properties of the object
147-
*
148-
* @param {Object} object
149-
* @param {Object} props
150-
* @return {Array} Array of PropRep.
151-
*/
152-
function getPropsArray(object, props) {
153-
let propsArray = [];
154-
155-
if (!object) {
156-
return propsArray;
157-
}
158-
159-
// Hardcode tiny mode to avoid recursive handling.
160-
let mode = MODE.TINY;
161-
const objectKeys = Object.keys(object);
162-
return objectKeys.map((name, i) => PropRep(Object.assign({}, props, {
163-
mode,
164-
name,
165-
object: object[name],
166-
equal: ": ",
167-
})));
168-
}
169-
170-
/**
171-
* Get a copy of the object filtered by a given predicate.
172-
*
173-
* @param {Object} object.
174-
* @param {Number} max The maximum length of keys array.
175-
* @param {Function} filter Filter the props you want.
176-
* @return {Object} the filtered object.
177-
*/
178-
function getFilteredObject(object, max, filter) {
179-
let filteredObject = {};
114+
};
180115

181116
try {
182-
for (let name in object) {
183-
if (Object.keys(filteredObject).length >= max) {
184-
return filteredObject;
117+
for (let name of propertiesNames) {
118+
if (propertiesNumber >= max) {
119+
break;
185120
}
186121

187122
let value;
@@ -191,15 +126,50 @@ function getFilteredObject(object, max, filter) {
191126
continue;
192127
}
193128

194-
let t = typeof value;
195-
if (filter(t, value)) {
196-
filteredObject[name] = value;
129+
// Object members with non-empty values are preferred since it gives the
130+
// user a better overview of the object.
131+
if (isInterestingProp(value)) {
132+
pushPropRep(name, value);
133+
} else {
134+
// If the property is not important, put its name on an array for later use.
135+
unimportantProperties.push(name);
197136
}
198137
}
199138
} catch (err) {
200139
console.error(err);
201140
}
202-
return filteredObject;
141+
142+
if (propertiesNumber < max) {
143+
for (let name of unimportantProperties) {
144+
if (propertiesNumber >= max) {
145+
break;
146+
}
147+
148+
let value;
149+
try {
150+
value = object[name];
151+
} catch (exc) {
152+
continue;
153+
}
154+
155+
pushPropRep(name, value);
156+
}
157+
}
158+
159+
if (propertiesNumber < propertiesNames.length) {
160+
elements.push(span({
161+
key: "more",
162+
className: "more-ellipsis",
163+
title: ", more…"
164+
}, "…"));
165+
}
166+
167+
return elements;
168+
}
169+
170+
function isInterestingProp(value) {
171+
const type = typeof value;
172+
return (type == "boolean" || type == "number" || (type == "string" && value));
203173
}
204174

205175
function supportsObject(object) {

0 commit comments

Comments
 (0)