Skip to content

Commit b2df264

Browse files
author
Chris K
committed
DFL-3441 Prototypes of a __proto__ can't be expanded
1 parent b54faf0 commit b2df264

File tree

4 files changed

+117
-59
lines changed

4 files changed

+117
-59
lines changed

src/client-en.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,7 @@ window.load_screen_timeout = window.setTimeout(function()
220220
<script src="./lib/stylesheetlistprototype.js"/>
221221
<script src="./lib/xmlhttprequestprototype.js"/>
222222
<script src="./lib/storageprototype.js"/>
223+
<script src="./lib/dict.js"/>
223224

224225

225226
<script src="./scripts/Timeouts.js"/>

src/ecma-debugger/objectinspection.6.0/inspectablejsobject.js

Lines changed: 49 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ cls.EcmascriptDebugger["6.0"].InspectableJSObject.prototype = new function()
107107
]
108108
};
109109
this._queried_map = {};
110-
this._expand_tree = {object_id: 0, protos: {}};
110+
this._expand_tree = new Dict({object_id: 0, protos: new Dict()});
111111
this._rt_id = rt_id;
112112
this._obj_id = obj_id;
113113
this._identifier = identifier || '';
@@ -125,26 +125,32 @@ cls.EcmascriptDebugger["6.0"].InspectableJSObject.prototype = new function()
125125

126126
this._get_subtree = function(path)
127127
{
128-
const PATH_KEY = 0, PATH_OBJ_ID = 1, PATH_PROTO_INDEX = 2;
129-
var key = '', obj_id = 0, proto_index = 0, i = 0, tree = this._expand_tree, index = 0;
130-
for ( ; path && path[i]; i++)
128+
var PATH_KEY = 0;
129+
var PATH_OBJ_ID = 1;
130+
var PATH_PROTO_INDEX = 2;
131+
var key = "";
132+
var obj_id = 0;
133+
var proto_index = 0;
134+
var tree = this._expand_tree;
135+
var index = 0;
136+
for (var i = 0 ; path && path[i]; i++)
131137
{
132138
key = path[i][PATH_KEY];
133139
obj_id = path[i][PATH_OBJ_ID];
134140
index = path[i][PATH_PROTO_INDEX];
135-
if (i < (path.length - 1) && !(tree.protos[index] && tree.protos[index][key]))
136-
{
137-
throw 'not valid path in InspectionBaseData._handle_examine_object';
138-
}
139-
if (!tree.protos)
140-
tree.protos = {};
141-
if (!tree.protos[index])
142-
tree.protos[index] = {};
141+
if (i < (path.length - 1) && !(tree.get_chain(["protos", index, key])))
142+
throw "not valid path in InspectableJSObject._get_subtree";
143+
144+
if (!tree.get("protos"))
145+
tree.set("protos", new Dict());
146+
var protos = tree.get("protos");
147+
if (!protos.get(index))
148+
protos.set(index, new Dict());
149+
var proto_index = protos.get(index);
143150
/* the last element of a prototype path has no object id */
144-
if ((!has_own_property.call(tree.protos[index], key) && !isNaN(obj_id)) ||
145-
tree.protos[index][key] === null)
146-
tree.protos[index][key] = {object_id: obj_id, protos: {}};
147-
tree = tree.protos[index][key];
151+
if (!proto_index.get(key) && !isNaN(obj_id))
152+
proto_index.set(key, new Dict({object_id: obj_id, protos: new Dict()}));
153+
tree = proto_index.get(key);
148154
}
149155
return tree;
150156
}
@@ -153,33 +159,33 @@ cls.EcmascriptDebugger["6.0"].InspectableJSObject.prototype = new function()
153159
// returns the removed tree
154160
this._remove_subtree = function(path)
155161
{
156-
const PATH_KEY = 0, PATH_OBJ_ID = 1, PATH_PROTO_INDEX = 2;
157-
var
158-
key = '',
159-
obj_id = 0,
160-
proto_index = 0,
161-
i = 0,
162-
tree = this._expand_tree,
163-
ret = null;
164-
165-
for ( ; path && path[i]; i++)
162+
var PATH_KEY = 0;
163+
var PATH_OBJ_ID = 1;
164+
var PATH_PROTO_INDEX = 2;
165+
var key = "";
166+
var obj_id = 0;
167+
var proto_index = 0;
168+
var tree = this._expand_tree;
169+
var ret = null;
170+
for (var i = 0 ; path && path[i]; i++)
166171
{
167172
key = path[i][PATH_KEY];
168173
obj_id = path[i][PATH_OBJ_ID];
169174
index = path[i][PATH_PROTO_INDEX];
170-
if (!(tree.protos && tree.protos[index] && tree.protos[index][key]))
175+
var sub_tree = tree.get_chain(["protos", index, key]);
176+
if (!sub_tree)
171177
{
172178
// with watches it can happen that we try to collapse
173179
// a path which was never expanded.
174180
return ret;
175181
}
176182
if (i == path.length - 1)
177183
{
178-
ret = tree.protos[index][key];
179-
tree.protos[index][key] = null;
184+
ret = sub_tree;
185+
tree.get_chain(["protos", index]).delete(key);
180186
break;
181187
}
182-
tree = tree.protos[index][key];
188+
tree = sub_tree;
183189
}
184190
return ret;
185191
}
@@ -285,7 +291,7 @@ cls.EcmascriptDebugger["6.0"].InspectableJSObject.prototype = new function()
285291
}
286292

287293
}
288-
this._obj_map[this._get_subtree(path).object_id] = proto_chain;
294+
this._obj_map[this._get_subtree(path).get("object_id")] = proto_chain;
289295
if (cb)
290296
cb();
291297
}
@@ -320,22 +326,21 @@ cls.EcmascriptDebugger["6.0"].InspectableJSObject.prototype = new function()
320326
this._get_all_ids = function get_all_ids(tree, ret)
321327
{
322328
ret || (ret = []);
323-
if (tree)
329+
if (tree && tree.get("object_id"))
324330
{
325-
ret.push(tree.object_id);
326-
for (var index in tree.protos)
331+
ret.push(tree.get("object_id"));
332+
var protos = tree.get("protos");
333+
protos.keys().forEach(function(index)
327334
{
328-
for (var key in tree.protos[index])
335+
var proto = protos.get(index);
336+
proto.keys().forEach(function(key)
329337
{
330-
if (tree.protos[index][key])
331-
{
332-
get_all_ids(tree.protos[index][key], ret);
333-
}
334-
}
335-
}
338+
get_all_ids(proto.get(key), ret);
339+
});
340+
});
336341
}
337342
return ret;
338-
}
343+
};
339344

340345
this._get_id = (function()
341346
{
@@ -436,8 +441,8 @@ cls.EcmascriptDebugger["6.0"].InspectableJSObject.prototype = new function()
436441
path = this._norm_path(path).slice(0);
437442
var index = path.pop()[PATH_PROTO_INDEX];
438443
var top = this._get_subtree(path);
439-
var removed = top.protos[index];
440-
top.protos[index] = null;
444+
var removed = top.get(["protos", index]);
445+
top.get("protos").delete(index);
441446
this._cleanup_maps(removed);
442447
};
443448

src/ecma-debugger/objectinspection.6.0/templates.js

Lines changed: 12 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -34,13 +34,10 @@
3434
{
3535
if (!index) // the properties of the object itself
3636
return true;
37-
38-
if (!_has_own_prop.call(tree.protos, index.toString()))
39-
return collapsed_protos[0] == '*'
40-
? false
41-
: (collapsed_protos.indexOf(name) == -1);
42-
43-
return Boolean(tree.protos[index]);
37+
var proto = tree.get_chain(["protos", index]);
38+
if (!proto)
39+
return collapsed_protos[0] == '*' ? false : (collapsed_protos.indexOf(name) == -1);
40+
return true;
4441
}
4542

4643
var _pretty_print_object = function(model,
@@ -86,9 +83,10 @@
8683
var ret = [];
8784
var name = proto[VALUE][CLASS_NAME] || "";
8885
var is_unfolded = _is_unfolded(tree, index, name, collapsed_protos);
86+
var proto_tree = tree.get_chain(["protos", index]) || new Dict();
8987
var expanded_props = is_unfolded &&
9088
_pretty_print_properties(model,
91-
tree.protos && tree.protos[index] || {},
89+
proto_tree,
9290
proto[PROPERTY_LIST] || [],
9391
collapsed_protos,
9492
filter,
@@ -274,9 +272,9 @@
274272
case "object":
275273
{
276274
obj_id = prop[OBJECT_VALUE][OBJECT_ID];
277-
expanded_prop = _has_own_prop.call(tree, prop[NAME]) &&
275+
expanded_prop = tree.get(prop[NAME]) &&
278276
_pretty_print_object(model,
279-
tree[prop[NAME]],
277+
tree.get(prop[NAME]),
280278
obj_id,
281279
collapsed_protos,
282280
filter,
@@ -294,8 +292,7 @@
294292
"handler='examine-object' " +
295293
"class='folder-key" + (has_match ? "" : " no-match") + "' "
296294
);
297-
// 'in' is true for all non enumarables
298-
if (_has_own_prop.call(tree, prop[NAME]) && tree[prop[NAME]])
295+
if (tree.get(prop[NAME]))
299296
ret.push(STYLE_EXPANDED);
300297
ret.push(
301298
"/>" +
@@ -308,7 +305,7 @@
308305
"data-tooltip='" + TOOLTIP_NAME + "' >" + value + "</value>"
309306
);
310307

311-
if (_has_own_prop.call(tree, prop[NAME]))
308+
if (tree.get(prop[NAME]))
312309
ret.extend(expanded_prop);
313310

314311
ret.push("</item>");
@@ -332,7 +329,7 @@
332329
window.inspectionfilters;
333330
var ret = _pretty_print_object(model,
334331
tree,
335-
tree.object_id,
332+
tree.get("object_id"),
336333
collapsed_protos,
337334
filter,
338335
searchterm).join('');
@@ -345,7 +342,7 @@
345342
{
346343
var OBJ_ID = 1;
347344
var tree = model.get_expanded_tree(null, path);
348-
var data = tree && model.get_data(tree.object_id);
345+
var data = tree && model.get_data(tree.get("object_id"));
349346
var setting = window.settings.inspection;
350347
var collapsed_protos = setting.get('collapsed-prototypes');
351348
var filter = !setting.get('show-default-nulls-and-empty-strings') &&

src/lib/dict.js

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
"use strict";
2+
3+
var Dict = function(obj)
4+
{
5+
this._init(obj);
6+
};
7+
8+
Dict.prototype = new function()
9+
{
10+
var PREFIX = "$";
11+
12+
this.get = function(key) { return this._dict[PREFIX + key]; };
13+
14+
this.set = function(key, value) { this._dict[PREFIX + key] = value; };
15+
16+
this.delete = function(key) { delete this._dict[PREFIX + key]; };
17+
18+
this.get_chain = function(prop_list)
19+
{
20+
for (var i = 0, value = this; i < prop_list.length && (value = value.get(prop_list[i])); i++);
21+
return value;
22+
};
23+
24+
this.keys = function()
25+
{
26+
var keys = [];
27+
for (var key in this._dict)
28+
{
29+
keys.push(key.slice(PREFIX.length));
30+
}
31+
return keys;
32+
};
33+
34+
this.toString = function()
35+
{
36+
var rep = [];
37+
for (var key in this._dict)
38+
{
39+
var value = this._dict[key];
40+
value = typeof value == "string" ? "\"" + value + "\"" : String(value);
41+
key = key.slice(PREFIX.length);
42+
rep.push(rep.length ? ", " : "", "\"", key, "\": ", value);
43+
}
44+
return "{" + rep.join("") + "}";
45+
};
46+
47+
this._init = function(obj)
48+
{
49+
this._dict = Object.create ? Object.create(null) : {};
50+
for (var key in obj)
51+
{
52+
this.set(key, obj[key]);
53+
}
54+
};
55+
};

0 commit comments

Comments
 (0)