Bug 1013814 - add inIDOMUtils.getRelativeRuleLine; r=heycam,pbrosset

This commit is contained in:
Tom Tromey 2015-08-17 15:19:21 -07:00
parent a3ee1eaac2
commit a609b68474
9 changed files with 127 additions and 52 deletions

View File

@ -13,8 +13,8 @@ class nsICSSLoaderObserver;
class nsIURI;
#define NS_ISTYLESHEETLINKINGELEMENT_IID \
{ 0xe5855604, 0x8a9a, 0x4181, \
{ 0xbe, 0x41, 0xdd, 0xf7, 0x08, 0x70, 0x3f, 0xbe } }
{ 0xa8b79f3b, 0x9d18, 0x4f9c, \
{ 0xb1, 0xaa, 0x8c, 0x9b, 0x1b, 0xaa, 0xac, 0xad } }
namespace mozilla {
class CSSStyleSheet;
@ -97,6 +97,14 @@ public:
// some types of linking elements, but it's a better place than
// anywhere else.
virtual void SetLineNumber(uint32_t aLineNumber) = 0;
/**
* Get the line number, as previously set by SetLineNumber.
*
* @return the line number of this element; or 1 if no line number
* was set
*/
virtual uint32_t GetLineNumber() = 0;
};
NS_DEFINE_STATIC_IID_ACCESSOR(nsIStyleSheetLinkingElement,

View File

@ -119,6 +119,12 @@ nsStyleLinkElement::SetLineNumber(uint32_t aLineNumber)
mLineNumber = aLineNumber;
}
/* virtual */ uint32_t
nsStyleLinkElement::GetLineNumber()
{
return mLineNumber;
}
/* static */ bool
nsStyleLinkElement::IsImportEnabled()
{

View File

@ -52,6 +52,7 @@ public:
virtual void OverrideBaseURI(nsIURI* aNewBaseURI) override;
virtual void SetLineNumber(uint32_t aLineNumber) override;
virtual uint32_t GetLineNumber() override;
enum RelValue {
ePREFETCH = 0x00000001,

View File

@ -12,6 +12,7 @@
#include "nsIServiceManager.h"
#include "nsISupportsArray.h"
#include "nsString.h"
#include "nsIStyleSheetLinkingElement.h"
#include "nsIDOMElement.h"
#include "nsIDocument.h"
#include "nsIPresShell.h"
@ -290,6 +291,33 @@ inDOMUtils::GetRuleColumn(nsIDOMCSSRule* aRule, uint32_t* _retval)
return NS_OK;
}
NS_IMETHODIMP
inDOMUtils::GetRelativeRuleLine(nsIDOMCSSRule* aRule, uint32_t* _retval)
{
NS_ENSURE_ARG_POINTER(aRule);
Rule* rule = aRule->GetCSSRule();
if (!rule) {
return NS_ERROR_FAILURE;
}
uint32_t lineNumber = rule->GetLineNumber();
CSSStyleSheet* sheet = rule->GetStyleSheet();
if (sheet) {
nsINode* owningNode = sheet->GetOwnerNode();
if (owningNode) {
nsCOMPtr<nsIStyleSheetLinkingElement> link =
do_QueryInterface(owningNode);
if (link) {
lineNumber -= link->GetLineNumber() - 1;
}
}
}
*_retval = lineNumber;
return NS_OK;
}
NS_IMETHODIMP
inDOMUtils::GetCSSLexer(const nsAString& aText, JSContext* aCx,
JS::MutableHandleValue aResult)

View File

@ -17,7 +17,7 @@ interface nsIDOMFontFaceList;
interface nsIDOMRange;
interface nsIDOMCSSStyleSheet;
[scriptable, uuid(60b4cbf7-2a08-4419-8937-6ef495417824)]
[scriptable, uuid(d67c0463-592e-4d7c-b67e-923ee3f6c643)]
interface inIDOMUtils : nsISupports
{
// CSS utilities
@ -28,6 +28,16 @@ interface inIDOMUtils : nsISupports
unsigned long getRuleLine(in nsIDOMCSSRule aRule);
unsigned long getRuleColumn(in nsIDOMCSSRule aRule);
/**
* Like getRuleLine, but if the rule is in a <style> element,
* returns a line number relative to the start of the element.
*
* @param nsIDOMCSSRule aRule the rule to examine
* @return the line number of the rule, possibly relative to the
* <style> element
*/
unsigned long getRelativeRuleLine(in nsIDOMCSSRule aRule);
[implicit_jscontext]
jsval getCSSLexer(in DOMString aText);

View File

@ -16,6 +16,7 @@ support-files =
[test_bug1006595.html]
[test_color_to_rgba.html]
[test_css_property_is_valid.html]
[test_getRelativeRuleLine.html]
[test_get_all_style_sheets.html]
[test_is_valid_css_color.html]
[test_isinheritableproperty.html]

View File

@ -0,0 +1,67 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>Test inDOMUtils::getRelativeRuleLine</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<style>
@supports (not (whatever: 72 zq)) {
#test {
background-color: #f0c;
}
}
#test {
color: #f0c;
}
</style>
<style>#test { color: red; }</style>
<style>
@invalidatkeyword {
}
#test {
color: blue;
}
</style>
<script type="application/javascript;version=1.8">
let utils = SpecialPowers.Cc["@mozilla.org/inspector/dom-utils;1"]
.getService(SpecialPowers.Ci.inIDOMUtils);
let tests = [
{ sheetNo: 0, ruleNo: 0, lineNo: 1, columnNo: 1 },
{ sheetNo: 1, ruleNo: 0, lineNo: 2, columnNo: 15 },
{ sheetNo: 1, ruleNo: 1, lineNo: 8, columnNo: 5 },
{ sheetNo: 2, ruleNo: 0, lineNo: 1, columnNo: 1 },
{ sheetNo: 3, ruleNo: 0, lineNo: 5, columnNo: 6 },
];
function doTest() {
for (let test of tests) {
let sheet = document.styleSheets[test.sheetNo];
let rule = sheet.cssRules[test.ruleNo];
let line = utils.getRelativeRuleLine(rule);
let column = utils.getRuleColumn(rule);
info("testing sheet " + test.sheetNo + ", rule " + test.ruleNo);
is(line, test.lineNo, "line number is correct");
is(column, test.columnNo, "column number is correct");
}
SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
addLoadEvent(doTest);
</script>
</head>
<body>
<h1>Test inDOMUtils::getRelativeRuleLine</h1>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
</pre>
</body>
</html>

View File

@ -564,8 +564,9 @@ function getImportedSheets(stylesheet) {
* @see deconstructRuleId(ruleId)
*/
function ruleToId(rule) {
let loc = stylesheets.getRuleLocation(rule);
return sheetToUrl(rule.parentStyleSheet) + "|" + loc.line + "|" + loc.column;
let line = DOMUtils.getRelativeRuleLine(rule);
let column = DOMUtils.getRuleColumn(rule);
return sheetToUrl(rule.parentStyleSheet) + "|" + line + "|" + column;
}
/**

View File

@ -932,53 +932,6 @@ let StyleSheetActor = protocol.ActorClass({
}
})
/**
* Find the line/column for a rule.
* This is like DOMUtils.getRule[Line|Column] except for inline <style> sheets,
* the line number returned here is relative to the <style> tag rather than the
* containing HTML document (which is what DOMUtils does).
* This is hacky, but we don't know of a better implementation right now.
*/
const getRuleLocation = exports.getRuleLocation = function(rule) {
let reply = {
line: DOMUtils.getRuleLine(rule),
column: DOMUtils.getRuleColumn(rule)
};
let sheet = rule.parentStyleSheet;
if (sheet.ownerNode && sheet.ownerNode.localName === "style") {
// For inline sheets, the line is relative to HTML not the stylesheet, so
// Get the location of the first { to know the line num of the first rule,
// relative to this sheet, to get the offset
let text = sheet.ownerNode.textContent;
// Hacky for now, because this will fail if { appears in a comment before
// but better than nothing, and faster than parsing the whole text
let start = text.substring(0, text.indexOf("{"));
let relativeStartLine = start.split("\n").length;
let absoluteStartLine;
let i = 0;
while (absoluteStartLine == null) {
let irule = sheet.cssRules[i];
if (irule instanceof Ci.nsIDOMCSSStyleRule) {
absoluteStartLine = DOMUtils.getRuleLine(irule);
}
else if (irule == null) {
break;
}
i++;
}
if (absoluteStartLine != null) {
let offset = absoluteStartLine - relativeStartLine;
reply.line -= offset;
}
}
return reply;
};
/**
* StyleSheetFront is the client-side counterpart to a StyleSheetActor.
*/