Bug 651501 - document.body fails to autocomplete in Web Console; backout; a=developers

This commit is contained in:
Rob Campbell 2011-06-24 18:01:32 -03:00
parent 64a4c20982
commit 53a9430a7b
4 changed files with 19 additions and 159 deletions

View File

@ -51,7 +51,6 @@ const CONSOLEAPI_CLASS_ID = "{b49c18f8-3379-4fc0-8c90-d7772c1a9ff3}";
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource:///modules/NetworkHelper.jsm");
Cu.import("resource:///modules/PropertyPanel.jsm");
var EXPORTED_SYMBOLS = ["HUDService", "ConsoleUtils"];
@ -4175,8 +4174,6 @@ function findCompletionBeginning(aStr)
function JSPropertyProvider(aScope, aInputValue)
{
let obj = unwrap(aScope);
// Store the scope object, since obj will be modified later on.
let win = obj;
// Analyse the aInputValue and find the beginning of the last part that
// should be completed.
@ -4215,15 +4212,10 @@ function JSPropertyProvider(aScope, aInputValue)
// Check if prop is a getter function on obj. Functions can change other
// stuff so we can't execute them to get the next object. Stop here.
if (isNonNativeGetter(win, obj, prop)) {
return null;
}
try {
obj = obj[prop];
}
catch (ex) {
if (obj.__lookupGetter__(prop)) {
return null;
}
obj = obj[prop];
}
}
else {
@ -4266,16 +4258,10 @@ function isIteratorOrGenerator(aObject)
return true;
}
try {
let str = aObject.toString();
if (typeof aObject.next == "function" &&
str.indexOf("[object Generator") == 0) {
return true;
}
}
catch (ex) {
// window.history.next throws in the typeof check above.
return false;
let str = aObject.toString();
if (typeof aObject.next == "function" &&
str.indexOf("[object Generator") == 0) {
return true;
}
}
@ -4578,7 +4564,8 @@ JSTerm.prototype = {
},
/**
* Evaluates a string in the sandbox.
* Evaluates a string in the sandbox. The string is currently wrapped by a
* with(window) { aString } construct, see bug 574033.
*
* @param string aString
* String to evaluate in the sandbox.

View File

@ -1,5 +1,4 @@
/* -*- Mode: js2; js2-basic-offset: 2; indent-tabs-mode: nil; -*- */
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
@ -45,8 +44,7 @@ const Cu = Components.utils;
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/Services.jsm");
var EXPORTED_SYMBOLS = ["PropertyPanel", "PropertyTreeView",
"namesAndValuesOf", "isNonNativeGetter"];
var EXPORTED_SYMBOLS = ["PropertyPanel", "PropertyTreeView", "namesAndValuesOf"];
///////////////////////////////////////////////////////////////////////////
//// Helper for PropertyTreeView
@ -114,20 +112,11 @@ function presentableValueFor(aObject)
presentable = aObject.toString();
let m = /^\[object (\S+)\]/.exec(presentable);
try {
if (typeof aObject == "object" && typeof aObject.next == "function" &&
m && m[1] == "Generator") {
return {
type: TYPE_OTHER,
display: m[1]
};
}
}
catch (ex) {
// window.history.next throws in the typeof check above.
if (typeof aObject == "object" && typeof aObject.next == "function" &&
m && m[1] == "Generator") {
return {
type: TYPE_OBJECT,
display: m ? m[1] : "Object"
type: TYPE_OTHER,
display: m[1]
};
}
@ -159,49 +148,6 @@ function isNativeFunction(aFunction)
return typeof aFunction == "function" && !("prototype" in aFunction);
}
/**
* Tells if the given property of the provided object is a non-native getter or
* not.
*
* @param object aScope
* Scope to use for the check.
*
* @param object aObject
* The object that contains the property.
*
* @param string aProp
* The property you want to check if it is a getter or not.
*
* @return boolean
* True if the given property is a getter, false otherwise.
*/
function isNonNativeGetter(aScope, aObject, aProp) {
if (typeof aObject != "object") {
return false;
}
let desc;
while (aObject) {
try {
if (desc = aScope.Object.getOwnPropertyDescriptor(aObject, aProp)) {
break;
}
}
catch (ex) {
// Native getters throw here. See bug 520882.
if (ex.name == "NS_ERROR_XPC_BAD_CONVERT_JS" ||
ex.name == "NS_ERROR_XPC_BAD_OP_ON_WN_PROTO") {
return false;
}
throw ex;
}
aObject = Object.getPrototypeOf(aObject);
}
if (desc && desc.get && !isNativeFunction(desc.get)) {
return true;
}
return false;
}
/**
* Get an array of property name value pairs for the tree.
*
@ -213,7 +159,7 @@ function isNonNativeGetter(aScope, aObject, aProp) {
function namesAndValuesOf(aObject)
{
let pairs = [];
let value, presentable;
let value, presentable, getter;
let isDOMDocument = aObject instanceof Ci.nsIDOMDocument;
@ -223,11 +169,11 @@ function namesAndValuesOf(aObject)
continue;
}
// Also skip non-native getters. Pass the content window so that
// getOwnPropertyDescriptor can work later on.
let chromeWindow = Services.wm.getMostRecentWindow("navigator:browser");
let contentWindow = chromeWindow.gBrowser.selectedBrowser.contentWindow;
if (isNonNativeGetter(contentWindow.wrappedJSObject, aObject, propName)) {
// Also skip non-native getters.
// TODO: implement a safer way to skip non-native getters. See bug 647235.
getter = aObject.__lookupGetter__ ?
aObject.__lookupGetter__(propName) : null;
if (getter && !isNativeFunction(getter)) {
value = ""; // Value is never displayed.
presentable = {type: TYPE_OTHER, display: "Getter"};
}

View File

@ -141,7 +141,6 @@ _BROWSER_TEST_FILES = \
browser_webconsole_bug_642615_autocomplete.js \
browser_webconsole_bug_585991_autocomplete_popup.js \
browser_webconsole_bug_585991_autocomplete_keys.js \
browser_webconsole_bug_651501_document_body_autocomplete.js \
browser_webconsole_bug_663443_panel_title.js \
browser_webconsole_bug_660806_history_nav.js \
head.js \

View File

@ -1,72 +0,0 @@
/* vim:set ts=2 sw=2 sts=2 et: */
/*
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
// Tests that document.body autocompletes in the web console.
Cu.import("resource://gre/modules/PropertyPanel.jsm");
function test() {
addTab("data:text/html,Web Console autocompletion bug in document.body");
browser.addEventListener("load", onLoad, true);
}
var gHUD;
function onLoad(aEvent) {
browser.removeEventListener(aEvent.type, arguments.callee, true);
openConsole();
let hudId = HUDService.getHudIdByWindow(content);
gHUD = HUDService.hudReferences[hudId];
let jsterm = gHUD.jsterm;
let popup = jsterm.autocompletePopup;
let completeNode = jsterm.completeNode;
ok(!popup.isOpen, "popup is not open");
popup._panel.addEventListener("popupshown", function() {
popup._panel.removeEventListener("popupshown", arguments.callee, false);
ok(popup.isOpen, "popup is open");
let props = namesAndValuesOf(content.wrappedJSObject.document.body).length;
is(popup.itemCount, props, "popup.itemCount is correct");
popup._panel.addEventListener("popuphidden", autocompletePopupHidden, false);
EventUtils.synthesizeKey("VK_ESCAPE", {});
}, false);
jsterm.setInputValue("document.body");
EventUtils.synthesizeKey(".", {});
}
function autocompletePopupHidden()
{
let jsterm = gHUD.jsterm;
let popup = jsterm.autocompletePopup;
let completeNode = jsterm.completeNode;
let inputNode = jsterm.inputNode;
popup._panel.removeEventListener("popuphidden", arguments.callee, false);
ok(!popup.isOpen, "popup is not open");
let inputStr = "document.b";
jsterm.setInputValue(inputStr);
EventUtils.synthesizeKey("o", {});
let testStr = inputStr.replace(/./g, " ") + " ";
is(completeNode.value, testStr + "dy", "completeNode is empty");
jsterm.setInputValue("");
// Check the property panel as well.
let propPanel = jsterm.openPropertyPanel("Test", content.document);
is (propPanel.treeView.rowCount, 153, "153 elements shown in propertyPanel");
let treeRows = propPanel.treeView._rows;
is (treeRows[30].display, "body: Object", "found document.body");
propPanel.destroy();
executeSoon(finishTest);
}