зеркало из https://github.com/mozilla/gecko-dev.git
merge devtools to m-c
This commit is contained in:
Коммит
f40c4e13ed
|
@ -75,6 +75,7 @@ function AutocompletePopup(aDocument)
|
|||
stringBundle.GetStringFromName("Autocomplete.label"));
|
||||
this._panel.setAttribute("noautofocus", "true");
|
||||
this._panel.setAttribute("ignorekeys", "true");
|
||||
this._panel.setAttribute("level", "top");
|
||||
|
||||
let mainPopupSet = this._document.getElementById("mainPopupSet");
|
||||
if (mainPopupSet) {
|
||||
|
|
|
@ -51,6 +51,7 @@ 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"];
|
||||
|
||||
|
@ -4174,6 +4175,8 @@ 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.
|
||||
|
@ -4212,10 +4215,15 @@ 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 (obj.__lookupGetter__(prop)) {
|
||||
if (isNonNativeGetter(win, obj, prop)) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
obj = obj[prop];
|
||||
}
|
||||
catch (ex) {
|
||||
return null;
|
||||
}
|
||||
obj = obj[prop];
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
@ -4258,10 +4266,16 @@ function isIteratorOrGenerator(aObject)
|
|||
return true;
|
||||
}
|
||||
|
||||
let str = aObject.toString();
|
||||
if (typeof aObject.next == "function" &&
|
||||
str.indexOf("[object Generator") == 0) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4564,8 +4578,7 @@ JSTerm.prototype = {
|
|||
},
|
||||
|
||||
/**
|
||||
* Evaluates a string in the sandbox. The string is currently wrapped by a
|
||||
* with(window) { aString } construct, see bug 574033.
|
||||
* Evaluates a string in the sandbox.
|
||||
*
|
||||
* @param string aString
|
||||
* String to evaluate in the sandbox.
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
/* -*- 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
|
||||
*
|
||||
|
@ -44,7 +45,8 @@ const Cu = Components.utils;
|
|||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
var EXPORTED_SYMBOLS = ["PropertyPanel", "PropertyTreeView", "namesAndValuesOf"];
|
||||
var EXPORTED_SYMBOLS = ["PropertyPanel", "PropertyTreeView",
|
||||
"namesAndValuesOf", "isNonNativeGetter"];
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//// Helper for PropertyTreeView
|
||||
|
@ -112,11 +114,20 @@ function presentableValueFor(aObject)
|
|||
presentable = aObject.toString();
|
||||
let m = /^\[object (\S+)\]/.exec(presentable);
|
||||
|
||||
if (typeof aObject == "object" && typeof aObject.next == "function" &&
|
||||
m && m[1] == "Generator") {
|
||||
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.
|
||||
return {
|
||||
type: TYPE_OTHER,
|
||||
display: m[1]
|
||||
type: TYPE_OBJECT,
|
||||
display: m ? m[1] : "Object"
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -148,6 +159,49 @@ 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.
|
||||
*
|
||||
|
@ -159,7 +213,7 @@ function isNativeFunction(aFunction)
|
|||
function namesAndValuesOf(aObject)
|
||||
{
|
||||
let pairs = [];
|
||||
let value, presentable, getter;
|
||||
let value, presentable;
|
||||
|
||||
let isDOMDocument = aObject instanceof Ci.nsIDOMDocument;
|
||||
|
||||
|
@ -169,11 +223,11 @@ function namesAndValuesOf(aObject)
|
|||
continue;
|
||||
}
|
||||
|
||||
// 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)) {
|
||||
// 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)) {
|
||||
value = ""; // Value is never displayed.
|
||||
presentable = {type: TYPE_OTHER, display: "Getter"};
|
||||
}
|
||||
|
|
|
@ -143,6 +143,7 @@ _BROWSER_TEST_FILES = \
|
|||
browser_webconsole_bug_585991_autocomplete_keys.js \
|
||||
browser_webconsole_bug_663443_panel_title.js \
|
||||
browser_webconsole_bug_660806_history_nav.js \
|
||||
browser_webconsole_bug_651501_document_body_autocomplete.js \
|
||||
head.js \
|
||||
$(NULL)
|
||||
|
||||
|
|
|
@ -0,0 +1,76 @@
|
|||
/* 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);
|
||||
let docProps = 0;
|
||||
for (let prop in content.document) {
|
||||
docProps++;
|
||||
}
|
||||
is (propPanel.treeView.rowCount, docProps, "all document properties shown in propertyPanel");
|
||||
|
||||
let treeRows = propPanel.treeView._rows;
|
||||
is (treeRows[30].display, "body: Object", "found document.body");
|
||||
propPanel.destroy();
|
||||
executeSoon(finishTest);
|
||||
}
|
||||
|
Загрузка…
Ссылка в новой задаче