diff options
Diffstat (limited to 'layout/inspector')
-rw-r--r-- | layout/inspector/InspectorCSSParser.cpp | 70 | ||||
-rw-r--r-- | layout/inspector/InspectorCSSParser.h | 47 | ||||
-rw-r--r-- | layout/inspector/moz.build | 2 | ||||
-rw-r--r-- | layout/inspector/tests/chrome/chrome.toml | 2 | ||||
-rw-r--r-- | layout/inspector/tests/chrome/test_CSSStyleRule_querySelectorAll.html | 121 |
5 files changed, 242 insertions, 0 deletions
diff --git a/layout/inspector/InspectorCSSParser.cpp b/layout/inspector/InspectorCSSParser.cpp new file mode 100644 index 0000000000..bc9cbf1487 --- /dev/null +++ b/layout/inspector/InspectorCSSParser.cpp @@ -0,0 +1,70 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "mozilla/dom/InspectorCSSParser.h" + +#include "mozilla/ServoBindings.h" +#include "mozilla/ServoStyleConsts.h" +#include "mozilla/UniquePtr.h" + +namespace mozilla::dom { + +InspectorCSSParser::InspectorCSSParser(const nsACString& aText) + : mInput(aText) { + mParserState = Servo_CSSParser_create(&mInput); +} + +UniquePtr<InspectorCSSParser> InspectorCSSParser::Constructor( + const GlobalObject& aGlobal, const nsACString& aText) { + return MakeUnique<InspectorCSSParser>(aText); +} + +InspectorCSSParser::~InspectorCSSParser() { + Servo_CSSParser_destroy(mParserState); + mParserState = nullptr; +} + +uint32_t InspectorCSSParser::LineNumber() const { return mLineNumber; } + +uint32_t InspectorCSSParser::ColumnNumber() const { + // mColumnNumber is 1-based, but consumers expect 0-based. + return mColumnNumber - 1; +} + +void InspectorCSSParser::NextToken(Nullable<InspectorCSSToken>& aResult) { + StyleCSSToken cssToken; + if (!Servo_CSSParser_NextToken(&mInput, mParserState, &cssToken)) { + aResult.SetNull(); + + mLineNumber = Servo_CSSParser_GetCurrentLine(mParserState); + mColumnNumber = Servo_CSSParser_GetCurrentColumn(mParserState); + + return; + } + + InspectorCSSToken& inspectorCssToken = aResult.SetValue(); + inspectorCssToken.mText.Append(cssToken.text); + inspectorCssToken.mTokenType.Append(cssToken.token_type); + if (cssToken.has_value) { + inspectorCssToken.mValue.Append(cssToken.value); + } else { + inspectorCssToken.mValue.SetIsVoid(true); + } + if (cssToken.has_unit) { + inspectorCssToken.mUnit.Append(cssToken.unit); + } else { + inspectorCssToken.mUnit.SetIsVoid(true); + } + if (cssToken.has_number) { + // Reduce precision to avoid floating point inprecision + inspectorCssToken.mNumber = round(cssToken.number * 100) / 100.0; + } + + mLineNumber = cssToken.line; + mColumnNumber = cssToken.column; +} + +} // namespace mozilla::dom diff --git a/layout/inspector/InspectorCSSParser.h b/layout/inspector/InspectorCSSParser.h new file mode 100644 index 0000000000..e11bc9a898 --- /dev/null +++ b/layout/inspector/InspectorCSSParser.h @@ -0,0 +1,47 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef InspectorCSSParser_h___ +#define InspectorCSSParser_h___ + +#include "mozilla/dom/InspectorUtilsBinding.h" +#include "mozilla/dom/NonRefcountedDOMObject.h" + +namespace mozilla { + +class StyleParserState; + +namespace dom { + +class InspectorCSSParser final : public NonRefcountedDOMObject { + public: + explicit InspectorCSSParser(const nsACString&); + // The WebIDL constructor. + static UniquePtr<InspectorCSSParser> Constructor(const GlobalObject& aGlobal, + const nsACString& aText); + + ~InspectorCSSParser(); + + bool WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto, + JS::MutableHandle<JSObject*> aReflector) { + return InspectorCSSParser_Binding::Wrap(aCx, this, aGivenProto, aReflector); + } + + uint32_t LineNumber() const; + uint32_t ColumnNumber() const; + void NextToken(Nullable<InspectorCSSToken>& aResult); + + private: + const nsCString mInput; + StyleParserState* mParserState; + uint32_t mLineNumber = 0; + uint32_t mColumnNumber = 0; +}; + +} // namespace dom +} // namespace mozilla + +#endif /* InspectorCSSParser_h___ */ diff --git a/layout/inspector/moz.build b/layout/inspector/moz.build index 45d31eb090..9a6634204c 100644 --- a/layout/inspector/moz.build +++ b/layout/inspector/moz.build @@ -19,6 +19,7 @@ EXPORTS.mozilla += [ ] EXPORTS.mozilla.dom += [ + "InspectorCSSParser.h", "InspectorFontFace.h", "InspectorUtils.h", ] @@ -26,6 +27,7 @@ EXPORTS.mozilla.dom += [ UNIFIED_SOURCES += [ "inDeepTreeWalker.cpp", "inLayoutUtils.cpp", + "InspectorCSSParser.cpp", "InspectorFontFace.cpp", "InspectorUtils.cpp", "ServoStyleRuleMap.cpp", diff --git a/layout/inspector/tests/chrome/chrome.toml b/layout/inspector/tests/chrome/chrome.toml index 193be351cb..4326401918 100644 --- a/layout/inspector/tests/chrome/chrome.toml +++ b/layout/inspector/tests/chrome/chrome.toml @@ -14,6 +14,8 @@ support-files = ["test_bug708874.css"] ["test_bug727834.xhtml"] support-files = ["test_bug727834.css"] +["test_CSSStyleRule_querySelectorAll.html"] + ["test_fontFaceGeneric.xhtml"] ["test_fontFaceRanges.xhtml"] diff --git a/layout/inspector/tests/chrome/test_CSSStyleRule_querySelectorAll.html b/layout/inspector/tests/chrome/test_CSSStyleRule_querySelectorAll.html new file mode 100644 index 0000000000..dcddc5744b --- /dev/null +++ b/layout/inspector/tests/chrome/test_CSSStyleRule_querySelectorAll.html @@ -0,0 +1,121 @@ +<!DOCTYPE html> +<html> + <head> + <meta charset="utf-8" /> + <title>Test CSSStyleRule::QuerySelectorAll</title> + <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/> + <style> + .test-simple { + } + .test-nested-parent { + .test-nested-child { + .test-nested-and-non-nested { + } + } + } + .test-nested-and-non-nested { + } + .test-no-match { + } + </style> + <script> + SimpleTest.waitForExplicitFinish(); + addLoadEvent(doTest); + + function doTest() { + let { cssRules } = document.styleSheets[1]; + + info("Testing simple case"); + let rule = cssRules[0]; + let result = rule.querySelectorAll(document); + is(result.length, 2, `2 elements are matching "${rule.selectorText}"`); + is( + result[0].id, + "a", + `Got expected id for first element matching "${rule.selectorText}"` + ); + is( + result[1].id, + "b", + `Got expected id for second element matching "${rule.selectorText}"` + ); + + info("Testing nested rule"); + rule = cssRules[1].cssRules[0]; + result = rule.querySelectorAll(document); + is(result.length, 1, `1 element is matching "${rule.selectorText}"`); + is( + result[0].id, + "d", + `Got expected id for element matching "${rule.selectorText}"` + ); + + info("Testing multi-level deep nested rule"); + rule = cssRules[1].cssRules[0].cssRules[0]; + result = rule.querySelectorAll(document); + // Check that we're not retrieving `f`, as the rule selectorText is `.test-nested-and-non-nested`, + // but it is nested inside `.test-nested-child`. + is(result.length, 1, `1 element is matching "${rule.selectorText}"`); + is( + result[0].id, + "e", + `Got expected id for element matching "${rule.selectorText}"` + ); + + info( + "Testing rule matching multiple elements with the same class, some nested, some not" + ); + rule = cssRules[2]; + result = rule.querySelectorAll(document); + is(result.length, 2, `2 elements are matching "${rule.selectorText}"`); + is( + result[0].id, + "e", + `Got expected id for first element matching "${rule.selectorText}"` + ); + is( + result[1].id, + "f", + `Got expected id for second element matching "${rule.selectorText}"` + ); + + info("Testing that search results are limited by the passed root node"); + rule = cssRules[2]; + result = rule.querySelectorAll(document.querySelector("#c")); + is( + result.length, + 1, + `An element is matching "${rule.selectorText}" in #c` + ); + is( + result[0].id, + "e", + `Got expected id for element matching "${rule.selectorText}"` + ); + + info("Testing rule with no matching elements"); + rule = cssRules[3]; + result = rule.querySelectorAll(document); + is(result.length, 0, `No elements matching "${rule.selectorText}"`); + + SimpleTest.finish(); + } + </script> + </head> + <body> + <h1>Test CSSStyleRule::QuerySelectorAll</h1> + <p id="display"></p> + <div id="content" style="display: none"> + <div id="a" class="test-simple"></div> + <div id="b" class="test-simple"></div> + <div id="c" class="test-nested-parent"> + <span id="d" class="test-nested-child"> + <b id="e" class="test-nested-and-non-nested"></b> + </span> + </div> + <b id="f" class="test-nested-and-non-nested"></b> + </div> + <pre id="test"></pre> + </body> +</html> |