diff --git a/common/content/base.js b/common/content/base.js index 16c6d227..babd5c8f 100644 --- a/common/content/base.js +++ b/common/content/base.js @@ -29,7 +29,23 @@ function array(obj) { return util.Array(obj); } +function allkeys(obj) { + let ret = {}; + for (; obj; obj = obj.__proto__) { + services.get("debugger").wrapValue(obj).getProperties(ret, {}); + for (let prop in values(ret.value)) + yield prop.name.stringValue; + } +} + function keys(obj) { + if (modules.services) { + let ret = {}; + services.get("debugger").wrapValue(obj).getProperties(ret, {}); + for (let prop in values(ret.value)) + yield prop.name.stringValue; + return; + } if ('__iterator__' in obj) { var iter = obj.__iterator__; yield '__iterator__'; diff --git a/common/content/completion.js b/common/content/completion.js index fff020c0..f80f97d0 100644 --- a/common/content/completion.js +++ b/common/content/completion.js @@ -783,24 +783,18 @@ const Completion = Module("completion", { } this.iter = function iter(obj) { - let iterator = ([k, getKey(obj, k)] for (k in obj)); - try { - // The point of 'for k in obj' is to get keys - // that are accessible via . or [] notation. - // Iterators quite often return values of no - // use whatsoever for this purpose, so, we try - // this rather dirty hack of getting a standard - // object iterator for any object that defines its - // own. - if ("__iterator__" in obj) { - let oldIter = obj.__iterator__; - delete obj.__iterator__; - iterator = Iterator(obj); - obj.__iterator__ = oldIter; + let seen = {}; + let ret = {}; + for (; obj; obj = obj.__proto__) { + services.get("debugger").wrapValue(obj).getProperties(ret, {}); + for (let prop in values(ret.value)) { + let name = '|' + prop.name.stringValue; + if (name in seen) + continue; + seen[name] = 1; + yield [prop.name.stringValue, prop.value.getWrappedValue()] } } - catch (e) {} - return iterator; }; // Search the object for strings starting with @key. @@ -829,6 +823,7 @@ const Completion = Module("completion", { // objects are problematic, to say the least. compl = [v for (v in this.iter(obj)) if (v && (typeof orig == "object" && v[0] in orig || getKey(orig, v[0]) !== undefined))]; + compl = util.Array.uniq(compl, true); } // And if wrappedJSObject happens to be available, diff --git a/common/content/modules.js b/common/content/modules.js index a068214b..d3e661d9 100644 --- a/common/content/modules.js +++ b/common/content/modules.js @@ -61,7 +61,7 @@ window.addEventListener("load", function () { fn(); } catch (e) { - dump("Loading " + (module && module.name) + ": " + e); + dump("Loading " + (module && module.name) + ": " + e + "\n"); if (e.stack) dump(e.stack); } diff --git a/common/content/services.js b/common/content/services.js index 355361ef..8b5a4189 100644 --- a/common/content/services.js +++ b/common/content/services.js @@ -22,6 +22,7 @@ const Services = Module("services", { this.add("cache", "@mozilla.org/network/cache-service;1", Ci.nsICacheService); this.add("console", "@mozilla.org/consoleservice;1", Ci.nsIConsoleService); this.add("liberator:", "@mozilla.org/network/protocol;1?name=liberator"); + this.add("debugger", "@mozilla.org/js/jsd/debugger-service;1", Ci.jsdIDebuggerService); this.add("directory", "@mozilla.org/file/directory_service;1", Ci.nsIProperties); this.add("downloadManager", "@mozilla.org/download-manager;1", Ci.nsIDownloadManager); this.add("environment", "@mozilla.org/process/environment;1", Ci.nsIEnvironment);