Merge inbound to central, a=merge

This commit is contained in:
Wes Kocher 2017-03-31 17:48:18 -07:00
Родитель 4cfcb8865a d205ea3601
Коммит 483fea00ef
64 изменённых файлов: 4346 добавлений и 403 удалений

Просмотреть файл

@ -28,8 +28,8 @@ this.SessionCookies = Object.freeze({
SessionCookiesInternal.update(windows);
},
getHostsForWindow(window, checkPrivacy = false) {
return SessionCookiesInternal.getHostsForWindow(window, checkPrivacy);
getHostsForWindow(window) {
return SessionCookiesInternal.getHostsForWindow(window);
},
restore(cookies) {
@ -58,16 +58,20 @@ var SessionCookiesInternal = {
update(windows) {
this._ensureInitialized();
// Check whether we're allowed to store cookies.
let storeAnyCookies = PrivacyLevel.canSave(false);
let storeSecureCookies = PrivacyLevel.canSave(true);
for (let window of windows) {
let cookies = [];
// Collect all cookies for the current window.
for (let host of this.getHostsForWindow(window, true)) {
for (let cookie of CookieStore.getCookiesForHost(host)) {
// getCookiesForHost() will only return hosts with the right privacy
// rules. Check again here to exclude HTTPS-only cookies if needed.
if (PrivacyLevel.canSave(cookie.secure)) {
cookies.push(cookie);
if (storeAnyCookies) {
// Collect all cookies for the current window.
for (let host of this.getHostsForWindow(window)) {
for (let cookie of CookieStore.getCookiesForHost(host)) {
if (!cookie.secure || storeSecureCookies) {
cookies.push(cookie);
}
}
}
}
@ -87,16 +91,14 @@ var SessionCookiesInternal = {
*
* @param window
* A window state object containing tabs with history entries.
* @param checkPrivacy (bool)
* Whether to check the privacy level for each host.
* @return {set} A set of hosts for a given window state object.
*/
getHostsForWindow(window, checkPrivacy = false) {
getHostsForWindow(window) {
let hosts = new Set();
for (let tab of window.tabs) {
for (let entry of tab.entries) {
this._extractHostsFromEntry(entry, hosts, checkPrivacy);
this._extractHostsFromEntry(entry, hosts);
}
}
@ -171,26 +173,19 @@ var SessionCookiesInternal = {
* the history entry, serialized
* @param hosts
* the set that will be used to store hosts
* @param checkPrivacy
* should we check the privacy level for https
*/
_extractHostsFromEntry(entry, hosts, checkPrivacy) {
_extractHostsFromEntry(entry, hosts) {
try {
// It's alright if this throws for about: URIs.
let {host, scheme} = Utils.makeURI(entry.url);
if (scheme == "file") {
if (/^(file|https?)$/.test(scheme)) {
hosts.add(host);
} else if (/https?/.test(scheme)) {
if (!checkPrivacy || PrivacyLevel.canSave(scheme == "https")) {
hosts.add(host);
}
}
} catch (ex) { }
if (entry.children) {
for (let child of entry.children) {
this._extractHostsFromEntry(child, hosts, checkPrivacy);
this._extractHostsFromEntry(child, hosts);
}
}
},

Просмотреть файл

@ -6,7 +6,7 @@ const PATH = "/browser/browser/components/sessionstore/test/";
* Remove all cookies to start off a clean slate.
*/
add_task(function* test_setup() {
requestLongerTimeout(2);
requestLongerTimeout(3);
Services.cookies.removeAll();
});
@ -79,6 +79,104 @@ add_task(function* test_run() {
});
});
/**
* Test multiple scenarios with different privacy levels.
*/
add_task(function* test_run_privacy_level() {
registerCleanupFunction(() => {
Services.prefs.clearUserPref("browser.sessionstore.privacy_level");
});
// With the default privacy level we collect all cookies.
yield testCookieCollection({
host: "http://example.com",
domain: ".example.com",
cookieHost: ".example.com",
cookieURIs: ["https://example.com/" + PATH, "http://example.com/" + PATH],
noCookieURIs: ["about:robots"]
});
// With the default privacy level we collect all cookies.
yield testCookieCollection({
host: "https://example.com",
domain: ".example.com",
cookieHost: ".example.com",
cookieURIs: ["https://example.com/" + PATH, "http://example.com/" + PATH],
noCookieURIs: ["about:robots"]
});
// With the default privacy level we collect all cookies.
yield testCookieCollection({
isSecure: true,
host: "https://example.com",
domain: ".example.com",
cookieHost: ".example.com",
cookieURIs: ["https://example.com/" + PATH, "http://example.com/" + PATH],
noCookieURIs: ["about:robots"]
});
// Set level=encrypted, don't store any secure cookies.
Services.prefs.setIntPref("browser.sessionstore.privacy_level", 1);
// With level=encrypted, non-secure cookies will be stored.
yield testCookieCollection({
host: "http://example.com",
domain: ".example.com",
cookieHost: ".example.com",
cookieURIs: ["https://example.com/" + PATH, "http://example.com/" + PATH],
noCookieURIs: ["about:robots"]
});
// With level=encrypted, non-secure cookies will be stored,
// even if sent by an HTTPS site.
yield testCookieCollection({
host: "https://example.com",
domain: ".example.com",
cookieHost: ".example.com",
cookieURIs: ["https://example.com/" + PATH, "http://example.com/" + PATH],
noCookieURIs: ["about:robots"]
});
// With level=encrypted, secure cookies will NOT be stored.
yield testCookieCollection({
isSecure: true,
host: "https://example.com",
domain: ".example.com",
cookieHost: ".example.com",
noCookieURIs: ["https://example.com/" + PATH, "http://example.com/" + PATH]
});
// Set level=full, don't store any cookies.
Services.prefs.setIntPref("browser.sessionstore.privacy_level", 2);
// With level=full we must not store any cookies.
yield testCookieCollection({
host: "http://example.com",
domain: ".example.com",
cookieHost: ".example.com",
noCookieURIs: ["https://example.com/" + PATH, "http://example.com/" + PATH]
});
// With level=full we must not store any cookies.
yield testCookieCollection({
host: "https://example.com",
domain: ".example.com",
cookieHost: ".example.com",
noCookieURIs: ["https://example.com/" + PATH, "http://example.com/" + PATH]
});
// With level=full we must not store any cookies.
yield testCookieCollection({
isSecure: true,
host: "https://example.com",
domain: ".example.com",
cookieHost: ".example.com",
noCookieURIs: ["https://example.com/" + PATH, "http://example.com/" + PATH]
});
Services.prefs.clearUserPref("browser.sessionstore.privacy_level");
});
/**
* Generic test function to check sessionstore's cookie collection module with
* different cookie domains given in the Set-Cookie header. See above for some
@ -96,6 +194,10 @@ var testCookieCollection = async function(params) {
urlParams.append("domain", params.domain);
}
if (params.isSecure) {
urlParams.append("secure", "1");
}
// Construct request URI.
let requestUri = `${params.host}${PATH}browser_cookies.sjs?${urlParams}`;

Просмотреть файл

@ -12,10 +12,15 @@ function handleRequest(req, resp) {
let value = params.get("value");
let domain = "";
if (params.has("domain")) {
if (params.has("domain")) {
domain = `; Domain=${params.get("domain")}`;
}
resp.setHeader("Set-Cookie", `foobar=${value}${domain}`);
let secure = "";
if (params.has("secure")) {
secure = "; Secure";
}
resp.setHeader("Set-Cookie", `foobar=${value}${domain}${secure}`);
resp.write("<meta charset=utf-8>hi");
}

Просмотреть файл

@ -9,28 +9,36 @@
<pre id="test">
<script class="testbody" type="text/javascript">
SimpleTest.requestCompleteLog();
SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPrefEnv({
set: [
[ "dom.disable_open_during_load", false ]
]
}).then(function() {
info("after pref");
var sub = encodeURI("data:text/html,<!DOCTYPE html>\n"+
"<html><script>"+
"var context = new AudioContext();"+
"setTimeout(function(){window.close();},1000);\x3C/script></html>");
window.onload = function(){
info("after onload");
var a = window.open(sub);
info("after open: " + a);
a.onbeforeunload = function(){
setTimeout(function(){
try {
info("before sp");
a.context.createScriptProcessor(512, 1, 1);
info("after sp");
} catch(e) {
ok (true,"got exception");
}
setTimeout(function() {
ok (true,"no crash");
info("finish");
ok (true,"no crash");
SimpleTest.finish();
}, 0);
}, 0);

Просмотреть файл

@ -0,0 +1,21 @@
<script id=o_xml type="text/plain"><?xml version="1.0" encoding="UTF-8"?>
<xb></xb>
</script>
<script id=o_xslt type="text/plain"><?xml version="1.0" encoding="UTF-8"?>
<xsl:transform version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="xb[$v1]"></xsl:template>
<xsl:variable name="v1">
<xsl:attribute name="a1" namespace="z">
<xsl:variable name="v2" select="$v2"></xsl:variable>
</xsl:attribute>
</xsl:variable>
</xsl:transform>
</script>
<script>
addEventListener("DOMContentLoaded", function(){
let doc = new DOMParser();
let xsltPrs = new XSLTProcessor();
xsltPrs.importStylesheet(doc.parseFromString(o_xslt.textContent, "text/xml"));
xsltPrs.transformToDocument(doc.parseFromString(o_xml.textContent, "text/xml"));
});
</script>

Просмотреть файл

@ -18,3 +18,4 @@ load 667315.xml
load 1089049.html
load 1205163.xml
load 1243337.xml
load 1338277.html

Просмотреть файл

@ -206,10 +206,12 @@ EvalContextImpl::getVariable(int32_t aNamespace,
return NS_ERROR_INVALID_ARG;
}
bool
EvalContextImpl::isStripSpaceAllowed(const txXPathNode& aNode)
nsresult
EvalContextImpl::isStripSpaceAllowed(const txXPathNode& aNode, bool& aAllowed)
{
return false;
aAllowed = false;
return NS_OK;
}
void*

Просмотреть файл

@ -28,6 +28,7 @@ class txIMatchContext;
class txIEvalContext;
class txNodeSet;
class txXPathNode;
class txXPathTreeWalker;
/**
* A Base Class for all XSL Expressions
@ -394,8 +395,9 @@ public:
* standalone. The NodeTest node() is different to the
* Pattern "node()" (document node isn't matched)
*/
virtual bool matches(const txXPathNode& aNode,
txIMatchContext* aContext) = 0;
virtual nsresult matches(const txXPathNode& aNode,
txIMatchContext* aContext,
bool& aMatched) = 0;
virtual double getDefaultPriority() = 0;
/**
@ -424,7 +426,9 @@ public:
#define TX_DECL_NODE_TEST \
TX_DECL_TOSTRING \
bool matches(const txXPathNode& aNode, txIMatchContext* aContext) override; \
nsresult matches(const txXPathNode& aNode, \
txIMatchContext* aContext, \
bool& aMatched) override; \
double getDefaultPriority() override; \
bool isSensitiveTo(Expr::ContextSensitivity aContext) override;
@ -630,10 +634,30 @@ public:
}
private:
void fromDescendants(const txXPathNode& aNode, txIMatchContext* aCs,
txNodeSet* aNodes);
void fromDescendantsRev(const txXPathNode& aNode, txIMatchContext* aCs,
txNodeSet* aNodes);
/**
* Append the current position of aWalker to aNodes if it matches mNodeTest,
* using aContext as the context for matching.
*/
nsresult appendIfMatching(const txXPathTreeWalker& aWalker,
txIMatchContext* aContext,
txNodeSet* aNodes);
/**
* Append the descendants of the current position of aWalker to aNodes if
* they match mNodeTest, using aContext as the context for matching.
*/
nsresult appendMatchingDescendants(const txXPathTreeWalker& aWalker,
txIMatchContext* aContext,
txNodeSet* aNodes);
/**
* Append the descendants of the current position of aWalker to aNodes in
* reverse order if they match mNodeTest, using aContext as the context for
* matching.
*/
nsresult appendMatchingDescendantsRev(const txXPathTreeWalker& aWalker,
txIMatchContext* aContext,
txNodeSet* aNodes);
nsAutoPtr<txNodeTest> mNodeTest;
LocationStepType mAxisIdentifier;

Просмотреть файл

@ -30,10 +30,11 @@ nsresult txForwardContext::getVariable(int32_t aNamespace, nsIAtom* aLName,
return mInner->getVariable(aNamespace, aLName, aResult);
}
bool txForwardContext::isStripSpaceAllowed(const txXPathNode& aNode)
nsresult
txForwardContext::isStripSpaceAllowed(const txXPathNode& aNode, bool& aAllowed)
{
NS_ASSERTION(mInner, "mInner is null!!!");
return mInner->isStripSpaceAllowed(aNode);
return mInner->isStripSpaceAllowed(aNode, aAllowed);
}
void* txForwardContext::getPrivateContext()

Просмотреть файл

@ -88,7 +88,8 @@ public:
* Is whitespace stripping allowed for the given node?
* See http://www.w3.org/TR/xslt#strip
*/
virtual bool isStripSpaceAllowed(const txXPathNode& aNode) = 0;
virtual nsresult isStripSpaceAllowed(const txXPathNode& aNode,
bool& aAllowed) = 0;
/**
* Returns a pointer to the private context
@ -106,7 +107,7 @@ public:
#define TX_DECL_MATCH_CONTEXT \
nsresult getVariable(int32_t aNamespace, nsIAtom* aLName, \
txAExprResult*& aResult); \
bool isStripSpaceAllowed(const txXPathNode& aNode); \
nsresult isStripSpaceAllowed(const txXPathNode& aNode, bool& aAllowed); \
void* getPrivateContext(); \
txResultRecycler* recycler(); \
void receiveError(const nsAString& aMsg, nsresult aRes)

Просмотреть файл

@ -49,9 +49,8 @@ LocationStep::evaluate(txIEvalContext* aContext, txAExprResult** aResult)
nodes->setReverse();
do {
if (mNodeTest->matches(walker.getCurrentPosition(), aContext)) {
nodes->append(walker.getCurrentPosition());
}
rv = appendIfMatching(walker, aContext, nodes);
NS_ENSURE_SUCCESS(rv, rv);
} while (walker.moveToParent());
break;
@ -63,29 +62,29 @@ LocationStep::evaluate(txIEvalContext* aContext, txAExprResult** aResult)
}
do {
if (mNodeTest->matches(walker.getCurrentPosition(), aContext)) {
nodes->append(walker.getCurrentPosition());
}
rv = appendIfMatching(walker, aContext, nodes);
NS_ENSURE_SUCCESS(rv, rv);
} while (walker.moveToNextAttribute());
break;
}
case DESCENDANT_OR_SELF_AXIS:
{
if (mNodeTest->matches(walker.getCurrentPosition(), aContext)) {
nodes->append(walker.getCurrentPosition());
}
rv = appendIfMatching(walker, aContext, nodes);
NS_ENSURE_SUCCESS(rv, rv);
MOZ_FALLTHROUGH;
}
case DESCENDANT_AXIS:
{
fromDescendants(walker.getCurrentPosition(), aContext, nodes);
rv = appendMatchingDescendants(walker, aContext, nodes);
NS_ENSURE_SUCCESS(rv, rv);
break;
}
case FOLLOWING_AXIS:
{
if (txXPathNodeUtils::isAttribute(walker.getCurrentPosition())) {
walker.moveToParent();
fromDescendants(walker.getCurrentPosition(), aContext, nodes);
rv = appendMatchingDescendants(walker, aContext, nodes);
NS_ENSURE_SUCCESS(rv, rv);
}
bool cont = true;
while (!walker.moveToNextSibling()) {
@ -95,11 +94,11 @@ LocationStep::evaluate(txIEvalContext* aContext, txAExprResult** aResult)
}
}
while (cont) {
if (mNodeTest->matches(walker.getCurrentPosition(), aContext)) {
nodes->append(walker.getCurrentPosition());
}
rv = appendIfMatching(walker, aContext, nodes);
NS_ENSURE_SUCCESS(rv, rv);
fromDescendants(walker.getCurrentPosition(), aContext, nodes);
rv = appendMatchingDescendants(walker, aContext, nodes);
NS_ENSURE_SUCCESS(rv, rv);
while (!walker.moveToNextSibling()) {
if (!walker.moveToParent()) {
@ -113,9 +112,8 @@ LocationStep::evaluate(txIEvalContext* aContext, txAExprResult** aResult)
case FOLLOWING_SIBLING_AXIS:
{
while (walker.moveToNextSibling()) {
if (mNodeTest->matches(walker.getCurrentPosition(), aContext)) {
nodes->append(walker.getCurrentPosition());
}
rv = appendIfMatching(walker, aContext, nodes);
NS_ENSURE_SUCCESS(rv, rv);
}
break;
}
@ -127,9 +125,9 @@ LocationStep::evaluate(txIEvalContext* aContext, txAExprResult** aResult)
break;
case PARENT_AXIS :
{
if (walker.moveToParent() &&
mNodeTest->matches(walker.getCurrentPosition(), aContext)) {
nodes->append(walker.getCurrentPosition());
if (walker.moveToParent()) {
rv = appendIfMatching(walker, aContext, nodes);
NS_ENSURE_SUCCESS(rv, rv);
}
break;
}
@ -145,11 +143,11 @@ LocationStep::evaluate(txIEvalContext* aContext, txAExprResult** aResult)
}
}
while (cont) {
fromDescendantsRev(walker.getCurrentPosition(), aContext, nodes);
rv = appendMatchingDescendantsRev(walker, aContext, nodes);
NS_ENSURE_SUCCESS(rv, rv);
if (mNodeTest->matches(walker.getCurrentPosition(), aContext)) {
nodes->append(walker.getCurrentPosition());
}
rv = appendIfMatching(walker, aContext, nodes);
NS_ENSURE_SUCCESS(rv, rv);
while (!walker.moveToPreviousSibling()) {
if (!walker.moveToParent()) {
@ -165,17 +163,15 @@ LocationStep::evaluate(txIEvalContext* aContext, txAExprResult** aResult)
nodes->setReverse();
while (walker.moveToPreviousSibling()) {
if (mNodeTest->matches(walker.getCurrentPosition(), aContext)) {
nodes->append(walker.getCurrentPosition());
}
rv = appendIfMatching(walker, aContext, nodes);
NS_ENSURE_SUCCESS(rv, rv);
}
break;
}
case SELF_AXIS:
{
if (mNodeTest->matches(walker.getCurrentPosition(), aContext)) {
nodes->append(walker.getCurrentPosition());
}
rv = appendIfMatching(walker, aContext, nodes);
NS_ENSURE_SUCCESS(rv, rv);
break;
}
default: // Children Axis
@ -185,9 +181,8 @@ LocationStep::evaluate(txIEvalContext* aContext, txAExprResult** aResult)
}
do {
if (mNodeTest->matches(walker.getCurrentPosition(), aContext)) {
nodes->append(walker.getCurrentPosition());
}
rv = appendIfMatching(walker, aContext, nodes);
NS_ENSURE_SUCCESS(rv, rv);
} while (walker.moveToNextSibling());
break;
}
@ -206,42 +201,62 @@ LocationStep::evaluate(txIEvalContext* aContext, txAExprResult** aResult)
return NS_OK;
}
void LocationStep::fromDescendants(const txXPathNode& aNode,
txIMatchContext* aCs,
txNodeSet* aNodes)
nsresult
LocationStep::appendIfMatching(const txXPathTreeWalker& aWalker,
txIMatchContext* aContext,
txNodeSet* aNodes)
{
txXPathTreeWalker walker(aNode);
if (!walker.moveToFirstChild()) {
return;
}
bool matched;
const txXPathNode& child = aWalker.getCurrentPosition();
nsresult rv = mNodeTest->matches(child, aContext, matched);
NS_ENSURE_SUCCESS(rv, rv);
do {
const txXPathNode& child = walker.getCurrentPosition();
if (mNodeTest->matches(child, aCs)) {
aNodes->append(child);
}
fromDescendants(child, aCs, aNodes);
} while (walker.moveToNextSibling());
if (matched) {
aNodes->append(child);
}
return NS_OK;
}
void LocationStep::fromDescendantsRev(const txXPathNode& aNode,
txIMatchContext* aCs,
txNodeSet* aNodes)
nsresult
LocationStep::appendMatchingDescendants(const txXPathTreeWalker& aWalker,
txIMatchContext* aContext,
txNodeSet* aNodes)
{
txXPathTreeWalker walker(aNode);
if (!walker.moveToLastChild()) {
return;
txXPathTreeWalker walker(aWalker);
if (!walker.moveToFirstChild()) {
return NS_OK;
}
do {
const txXPathNode& child = walker.getCurrentPosition();
fromDescendantsRev(child, aCs, aNodes);
nsresult rv = appendIfMatching(walker, aContext, aNodes);
NS_ENSURE_SUCCESS(rv, rv);
if (mNodeTest->matches(child, aCs)) {
aNodes->append(child);
}
rv = appendMatchingDescendants(walker, aContext, aNodes);
NS_ENSURE_SUCCESS(rv, rv);
} while (walker.moveToNextSibling());
return NS_OK;
}
nsresult
LocationStep::appendMatchingDescendantsRev(const txXPathTreeWalker& aWalker,
txIMatchContext* aContext,
txNodeSet* aNodes)
{
txXPathTreeWalker walker(aWalker);
if (!walker.moveToLastChild()) {
return NS_OK;
}
do {
nsresult rv = appendMatchingDescendantsRev(walker, aContext, aNodes);
NS_ENSURE_SUCCESS(rv, rv);
rv = appendIfMatching(walker, aContext, aNodes);
NS_ENSURE_SUCCESS(rv, rv);
} while (walker.moveToPreviousSibling());
return NS_OK;
}
Expr::ExprType

Просмотреть файл

@ -23,7 +23,9 @@ txNameTest::txNameTest(nsIAtom* aPrefix, nsIAtom* aLocalName, int32_t aNSID,
"Go fix txNameTest::matches");
}
bool txNameTest::matches(const txXPathNode& aNode, txIMatchContext* aContext)
nsresult
txNameTest::matches(const txXPathNode& aNode, txIMatchContext* aContext,
bool& aMatched)
{
if ((mNodeType == txXPathNodeType::ELEMENT_NODE &&
!txXPathNodeUtils::isElement(aNode)) ||
@ -31,26 +33,34 @@ bool txNameTest::matches(const txXPathNode& aNode, txIMatchContext* aContext)
!txXPathNodeUtils::isAttribute(aNode)) ||
(mNodeType == txXPathNodeType::DOCUMENT_NODE &&
!txXPathNodeUtils::isRoot(aNode))) {
return false;
aMatched = false;
return NS_OK;
}
// Totally wild?
if (mLocalName == nsGkAtoms::_asterisk && !mPrefix)
return true;
if (mLocalName == nsGkAtoms::_asterisk && !mPrefix) {
aMatched = true;
return NS_OK;
}
// Compare namespaces
if (mNamespace != txXPathNodeUtils::getNamespaceID(aNode)
&& !(mNamespace == kNameSpaceID_None &&
txXPathNodeUtils::isHTMLElementInHTMLDocument(aNode))
)
return false;
) {
aMatched = false;
return NS_OK;
}
// Name wild?
if (mLocalName == nsGkAtoms::_asterisk)
return true;
if (mLocalName == nsGkAtoms::_asterisk) {
aMatched = true;
return NS_OK;
}
// Compare local-names
return txXPathNodeUtils::localNameEquals(aNode, mLocalName);
aMatched = txXPathNodeUtils::localNameEquals(aNode, mLocalName);
return NS_OK;
}
/*

Просмотреть файл

@ -29,10 +29,11 @@ nsresult txNodeSetContext::getVariable(int32_t aNamespace, nsIAtom* aLName,
return mInner->getVariable(aNamespace, aLName, aResult);
}
bool txNodeSetContext::isStripSpaceAllowed(const txXPathNode& aNode)
nsresult
txNodeSetContext::isStripSpaceAllowed(const txXPathNode& aNode, bool& aAllowed)
{
NS_ASSERTION(mInner, "mInner is null!!!");
return mInner->isStripSpaceAllowed(aNode);
return mInner->isStripSpaceAllowed(aNode, aAllowed);
}
void* txNodeSetContext::getPrivateContext()

Просмотреть файл

@ -8,32 +8,54 @@
#include "txIXPathContext.h"
#include "txXPathTreeWalker.h"
bool txNodeTypeTest::matches(const txXPathNode& aNode,
txIMatchContext* aContext)
nsresult
txNodeTypeTest::matches(const txXPathNode& aNode, txIMatchContext* aContext,
bool& aMatched)
{
switch (mNodeType) {
case COMMENT_TYPE:
{
return txXPathNodeUtils::isComment(aNode);
aMatched = txXPathNodeUtils::isComment(aNode);
return NS_OK;
}
case TEXT_TYPE:
{
return txXPathNodeUtils::isText(aNode) &&
!aContext->isStripSpaceAllowed(aNode);
aMatched = txXPathNodeUtils::isText(aNode);
if (aMatched) {
bool allowed;
nsresult rv = aContext->isStripSpaceAllowed(aNode, allowed);
NS_ENSURE_SUCCESS(rv, rv);
aMatched = !allowed;
}
return NS_OK;
}
case PI_TYPE:
{
return txXPathNodeUtils::isProcessingInstruction(aNode) &&
(!mNodeName ||
txXPathNodeUtils::localNameEquals(aNode, mNodeName));
aMatched = txXPathNodeUtils::isProcessingInstruction(aNode) &&
(!mNodeName ||
txXPathNodeUtils::localNameEquals(aNode, mNodeName));
return NS_OK;
}
case NODE_TYPE:
{
return !txXPathNodeUtils::isText(aNode) ||
!aContext->isStripSpaceAllowed(aNode);
if (txXPathNodeUtils::isText(aNode)) {
bool allowed;
nsresult rv = aContext->isStripSpaceAllowed(aNode, allowed);
NS_ENSURE_SUCCESS(rv, rv);
aMatched = !allowed;
} else {
aMatched = true;
}
return NS_OK;
}
}
return true;
NS_NOTREACHED("Didn't deal with all values of the NodeType enum!");
aMatched = false;
return NS_OK;
}
txNodeTest::NodeTestType

Просмотреть файл

@ -160,7 +160,9 @@ PathExpr::evalDescendants(Expr* aStep, const txXPathNode& aNode,
resNodes->addAndTransfer(newSet);
bool filterWS = aContext->isStripSpaceAllowed(aNode);
bool filterWS;
rv = aContext->isStripSpaceAllowed(aNode, filterWS);
NS_ENSURE_SUCCESS(rv, rv);
txXPathTreeWalker walker(aNode);
if (!walker.moveToFirstChild()) {

Просмотреть файл

@ -16,20 +16,25 @@ txPredicatedNodeTest::txPredicatedNodeTest(txNodeTest* aNodeTest,
"predicate must not be context-nodeset-sensitive");
}
bool
nsresult
txPredicatedNodeTest::matches(const txXPathNode& aNode,
txIMatchContext* aContext)
txIMatchContext* aContext,
bool& aMatched)
{
if (!mNodeTest->matches(aNode, aContext)) {
return false;
nsresult rv = mNodeTest->matches(aNode, aContext, aMatched);
NS_ENSURE_SUCCESS(rv, rv);
if (!aMatched) {
return NS_OK;
}
txSingleNodeContext context(aNode, aContext);
RefPtr<txAExprResult> res;
nsresult rv = mPredicate->evaluate(&context, getter_AddRefs(res));
NS_ENSURE_SUCCESS(rv, false);
rv = mPredicate->evaluate(&context, getter_AddRefs(res));
NS_ENSURE_SUCCESS(rv, rv);
return res->booleanValue();
aMatched = res->booleanValue();
return NS_OK;
}
double

Просмотреть файл

@ -27,10 +27,11 @@ public:
return mInner->getVariable(aNamespace, aLName, aResult);
}
bool isStripSpaceAllowed(const txXPathNode& aNode) override
nsresult isStripSpaceAllowed(const txXPathNode& aNode,
bool& aAllowed) override
{
NS_ASSERTION(mInner, "mInner is null!!!");
return mInner->isStripSpaceAllowed(aNode);
return mInner->isStripSpaceAllowed(aNode, aAllowed);
}
void* getPrivateContext() override

Просмотреть файл

@ -10,18 +10,22 @@
#include "txExprResult.h"
#include "txSingleNodeContext.h"
bool
txUnionNodeTest::matches(const txXPathNode& aNode,
txIMatchContext* aContext)
nsresult
txUnionNodeTest::matches(const txXPathNode& aNode, txIMatchContext* aContext,
bool& aMatched)
{
uint32_t i, len = mNodeTests.Length();
for (i = 0; i < len; ++i) {
if (mNodeTests[i]->matches(aNode, aContext)) {
return true;
nsresult rv = mNodeTests[i]->matches(aNode, aContext, aMatched);
NS_ENSURE_SUCCESS(rv, rv);
if (aMatched) {
return NS_OK;
}
}
return false;
aMatched = false;
return NS_OK;
}
double

Просмотреть файл

@ -26,7 +26,7 @@ public:
{
MOZ_CRASH("shouldn't depend on this context");
}
bool isStripSpaceAllowed(const txXPathNode& aNode)
nsresult isStripSpaceAllowed(const txXPathNode& aNode, bool& aAllowed)
{
MOZ_CRASH("shouldn't depend on this context");
}

Просмотреть файл

@ -87,10 +87,7 @@ txExecutionState::~txExecutionState()
txStackIterator handlerIter(&mResultHandlerStack);
while (handlerIter.hasNext()) {
txAXMLEventHandler* handler = (txAXMLEventHandler*)handlerIter.next();
if (handler != mObsoleteHandler) {
delete handler;
}
delete (txAXMLEventHandler*)handlerIter.next();
}
txStackIterator paramIter(&mParamStack);
@ -141,8 +138,11 @@ txExecutionState::init(const txXPathNode& aNode,
// might use us.
txStylesheet::ImportFrame* frame = 0;
txExpandedName nullName;
txInstruction* templ = mStylesheet->findTemplate(aNode, nullName,
this, nullptr, &frame);
txInstruction* templ;
rv = mStylesheet->findTemplate(aNode, nullName, this, nullptr, &templ,
&frame);
NS_ENSURE_SUCCESS(rv, rv);
pushTemplateRule(frame, nullName, nullptr);
return runTemplate(templ);
@ -162,17 +162,6 @@ txExecutionState::end(nsresult aResult)
return mOutputHandler->endDocument(aResult);
}
void
txExecutionState::popAndDeleteEvalContext()
{
if (!mEvalContextStack.isEmpty()) {
auto ctx = popEvalContext();
if (ctx != mInitialEvalContext) {
delete ctx;
}
}
}
void
txExecutionState::popAndDeleteEvalContextUntil(txIEvalContext* aContext)
{
@ -306,10 +295,10 @@ txExecutionState::getVariable(int32_t aNamespace, nsIAtom* aLName,
return NS_OK;
}
bool
txExecutionState::isStripSpaceAllowed(const txXPathNode& aNode)
nsresult
txExecutionState::isStripSpaceAllowed(const txXPathNode& aNode, bool& aAllowed)
{
return mStylesheet->isStripSpaceAllowed(aNode, this);
return mStylesheet->isStripSpaceAllowed(aNode, this, aAllowed);
}
void*

Просмотреть файл

@ -95,8 +95,6 @@ public:
nsresult pushEvalContext(txIEvalContext* aContext);
txIEvalContext* popEvalContext();
void popAndDeleteEvalContext();
/**
* Helper that deletes all entries before |aContext| and then
* pops it off the stack. The caller must delete |aContext| if

Просмотреть файл

@ -27,9 +27,11 @@ txApplyDefaultElementTemplate::execute(txExecutionState& aEs)
txExecutionState::TemplateRule* rule = aEs.getCurrentTemplateRule();
txExpandedName mode(rule->mModeNsId, rule->mModeLocalName);
txStylesheet::ImportFrame* frame = 0;
txInstruction* templ =
txInstruction* templ;
nsresult rv =
aEs.mStylesheet->findTemplate(aEs.getEvalContext()->getContextNode(),
mode, &aEs, nullptr, &frame);
mode, &aEs, nullptr, &templ, &frame);
NS_ENSURE_SUCCESS(rv, rv);
aEs.pushTemplateRule(frame, mode, aEs.mTemplateParams);
@ -53,9 +55,11 @@ txApplyImports::execute(txExecutionState& aEs)
txStylesheet::ImportFrame* frame = 0;
txExpandedName mode(rule->mModeNsId, rule->mModeLocalName);
txInstruction* templ =
aEs.mStylesheet->findTemplate(aEs.getEvalContext()->getContextNode(),
mode, &aEs, rule->mFrame, &frame);
txInstruction* templ;
rv = aEs.mStylesheet->findTemplate(aEs.getEvalContext()->getContextNode(),
mode, &aEs, rule->mFrame, &templ,
&frame);
NS_ENSURE_SUCCESS(rv, rv);
aEs.pushTemplateRule(frame, mode, rule->mParams);
@ -76,9 +80,11 @@ nsresult
txApplyTemplates::execute(txExecutionState& aEs)
{
txStylesheet::ImportFrame* frame = 0;
txInstruction* templ =
txInstruction* templ;
nsresult rv =
aEs.mStylesheet->findTemplate(aEs.getEvalContext()->getContextNode(),
mMode, &aEs, nullptr, &frame);
mMode, &aEs, nullptr, &templ, &frame);
NS_ENSURE_SUCCESS(rv, rv);
aEs.pushTemplateRule(frame, mMode, aEs.mTemplateParams);
@ -470,7 +476,7 @@ txLoopNodeSet::execute(txExecutionState& aEs)
txNodeSetContext* context =
static_cast<txNodeSetContext*>(aEs.getEvalContext());
if (!context->hasNext()) {
aEs.popAndDeleteEvalContext();
delete aEs.popEvalContext();
return NS_OK;
}

Просмотреть файл

@ -338,7 +338,11 @@ nsresult txXSLKey::testNode(const txXPathNode& aNode,
nsAutoString val;
uint32_t currKey, numKeys = mKeys.Length();
for (currKey = 0; currKey < numKeys; ++currKey) {
if (mKeys[currKey].matchPattern->matches(aNode, &aEs)) {
bool matched;
nsresult rv = mKeys[currKey].matchPattern->matches(aNode, &aEs, matched);
NS_ENSURE_SUCCESS(rv, rv);
if (matched) {
txSingleNodeContext *evalContext =
new txSingleNodeContext(aNode, &aEs);
NS_ENSURE_TRUE(evalContext, NS_ERROR_OUT_OF_MEMORY);

Просмотреть файл

@ -441,9 +441,11 @@ public:
aResult = nullptr;
return NS_ERROR_INVALID_ARG;
}
bool isStripSpaceAllowed(const txXPathNode& aNode)
nsresult isStripSpaceAllowed(const txXPathNode& aNode, bool& aAllowed)
{
return false;
aAllowed = false;
return NS_OK;
}
void* getPrivateContext()
{

Просмотреть файл

@ -88,17 +88,18 @@ txStylesheet::~txStylesheet()
}
}
txInstruction*
nsresult
txStylesheet::findTemplate(const txXPathNode& aNode,
const txExpandedName& aMode,
txIMatchContext* aContext,
ImportFrame* aImportedBy,
txInstruction** aTemplate,
ImportFrame** aImportFrame)
{
NS_ASSERTION(aImportFrame, "missing ImportFrame pointer");
*aTemplate = nullptr;
*aImportFrame = nullptr;
txInstruction* matchTemplate = nullptr;
ImportFrame* endFrame = nullptr;
txListIterator frameIter(&mImportFrames);
@ -115,7 +116,7 @@ txStylesheet::findTemplate(const txXPathNode& aNode,
#endif
ImportFrame* frame;
while (!matchTemplate &&
while (!*aTemplate &&
(frame = static_cast<ImportFrame*>(frameIter.next())) &&
frame != endFrame) {
@ -126,10 +127,14 @@ txStylesheet::findTemplate(const txXPathNode& aNode,
if (templates) {
// Find template with highest priority
uint32_t i, len = templates->Length();
for (i = 0; i < len && !matchTemplate; ++i) {
for (i = 0; i < len && !*aTemplate; ++i) {
MatchableTemplate& templ = (*templates)[i];
if (templ.mMatch->matches(aNode, aContext)) {
matchTemplate = templ.mFirstInstruction;
bool matched;
nsresult rv = templ.mMatch->matches(aNode, aContext, matched);
NS_ENSURE_SUCCESS(rv, rv);
if (matched) {
*aTemplate = templ.mFirstInstruction;
*aImportFrame = frame;
#if defined(TX_TO_STRING)
match = templ.mMatch;
@ -145,7 +150,7 @@ txStylesheet::findTemplate(const txXPathNode& aNode,
aMode.mLocalName->ToString(mode);
}
txXPathNodeUtils::getNodeName(aNode, nodeName);
if (matchTemplate) {
if (*aTemplate) {
nsAutoString matchAttr;
#ifdef TX_TO_STRING
match->toString(matchAttr);
@ -164,23 +169,23 @@ txStylesheet::findTemplate(const txXPathNode& aNode,
}
}
if (!matchTemplate) {
if (!*aTemplate) {
// Test for these first since a node can be both a text node
// and a root (if it is orphaned)
if (txXPathNodeUtils::isAttribute(aNode) ||
txXPathNodeUtils::isText(aNode)) {
matchTemplate = mCharactersTemplate;
*aTemplate = mCharactersTemplate;
}
else if (txXPathNodeUtils::isElement(aNode) ||
txXPathNodeUtils::isRoot(aNode)) {
matchTemplate = mContainerTemplate;
*aTemplate = mContainerTemplate;
}
else {
matchTemplate = mEmptyTemplate;
*aTemplate = mEmptyTemplate;
}
}
return matchTemplate;
return NS_OK;
}
txDecimalFormat*
@ -219,37 +224,53 @@ txStylesheet::getKeyMap()
return mKeys;
}
bool
txStylesheet::isStripSpaceAllowed(const txXPathNode& aNode, txIMatchContext* aContext)
nsresult
txStylesheet::isStripSpaceAllowed(const txXPathNode& aNode,
txIMatchContext* aContext, bool& aAllowed)
{
int32_t frameCount = mStripSpaceTests.Length();
if (frameCount == 0) {
return false;
aAllowed = false;
return NS_OK;
}
txXPathTreeWalker walker(aNode);
if (txXPathNodeUtils::isText(walker.getCurrentPosition()) &&
(!txXPathNodeUtils::isWhitespace(aNode) || !walker.moveToParent())) {
return false;
aAllowed = false;
return NS_OK;
}
const txXPathNode& node = walker.getCurrentPosition();
if (!txXPathNodeUtils::isElement(node)) {
return false;
aAllowed = false;
return NS_OK;
}
// check Whitespace stipping handling list against given Node
int32_t i;
for (i = 0; i < frameCount; ++i) {
txStripSpaceTest* sst = mStripSpaceTests[i];
if (sst->matches(node, aContext)) {
return sst->stripsSpace() && !XMLUtils::getXMLSpacePreserve(node);
bool matched;
nsresult rv = sst->matches(node, aContext, matched);
NS_ENSURE_SUCCESS(rv, rv);
if (matched) {
aAllowed = sst->stripsSpace() &&
!XMLUtils::getXMLSpacePreserve(node);
return NS_OK;
}
}
return false;
aAllowed = false;
return NS_OK;
}
nsresult

Просмотреть файл

@ -35,19 +35,21 @@ public:
NS_INLINE_DECL_REFCOUNTING(txStylesheet)
txInstruction* findTemplate(const txXPathNode& aNode,
const txExpandedName& aMode,
txIMatchContext* aContext,
ImportFrame* aImportedBy,
ImportFrame** aImportFrame);
nsresult findTemplate(const txXPathNode& aNode,
const txExpandedName& aMode,
txIMatchContext* aContext,
ImportFrame* aImportedBy,
txInstruction** aTemplate,
ImportFrame** aImportFrame);
txDecimalFormat* getDecimalFormat(const txExpandedName& aName);
txInstruction* getAttributeSet(const txExpandedName& aName);
txInstruction* getNamedTemplate(const txExpandedName& aName);
txOutputFormat* getOutputFormat();
GlobalVariable* getGlobalVariable(const txExpandedName& aName);
const txOwningExpandedNameMap<txXSLKey>& getKeyMap();
bool isStripSpaceAllowed(const txXPathNode& aNode,
txIMatchContext* aContext);
nsresult isStripSpaceAllowed(const txXPathNode& aNode,
txIMatchContext* aContext,
bool& aAllowed);
/**
* Called by the stylesheet compiler once all stylesheets has been read.
@ -166,8 +168,10 @@ public:
{
}
bool matches(const txXPathNode& aNode, txIMatchContext* aContext) {
return mNameTest.matches(aNode, aContext);
nsresult matches(const txXPathNode& aNode, txIMatchContext* aContext,
bool& aMatched)
{
return mNameTest.matches(aNode, aContext, aMatched);
}
bool stripsSpace() {

Просмотреть файл

@ -108,13 +108,12 @@ txXSLTNumber::getValueList(Expr* aValueExpr, txPattern* aCountPattern,
// Otherwise use count/from/level
txPattern* countPattern = aCountPattern;
bool ownsCountPattern = false;
nsAutoPtr<txPattern> newCountPattern;
const txXPathNode& currNode = aContext->getContextNode();
// Parse count- and from-attributes
if (!aCountPattern) {
ownsCountPattern = true;
txNodeTest* nodeTest;
uint16_t nodeType = txXPathNodeUtils::getNodeType(currNode);
switch (nodeType) {
@ -160,7 +159,7 @@ txXSLTNumber::getValueList(Expr* aValueExpr, txPattern* aCountPattern,
}
}
MOZ_ASSERT(nodeTest);
countPattern = new txStepPattern(nodeTest, false);
countPattern = newCountPattern = new txStepPattern(nodeTest, false);
}
@ -170,14 +169,28 @@ txXSLTNumber::getValueList(Expr* aValueExpr, txPattern* aCountPattern,
if (aLevel == eLevelSingle) {
txXPathTreeWalker walker(currNode);
do {
if (aFromPattern && !walker.isOnNode(currNode) &&
aFromPattern->matches(walker.getCurrentPosition(), aContext)) {
break;
if (aFromPattern && !walker.isOnNode(currNode)) {
bool matched;
rv = aFromPattern->matches(walker.getCurrentPosition(),
aContext, matched);
NS_ENSURE_SUCCESS(rv, rv);
if (matched) {
break;
}
}
if (countPattern->matches(walker.getCurrentPosition(), aContext)) {
aValues.add(NS_INT32_TO_PTR(getSiblingCount(walker, countPattern,
aContext)));
bool matched;
rv = countPattern->matches(walker.getCurrentPosition(), aContext,
matched);
NS_ENSURE_SUCCESS(rv, rv);
if (matched) {
int32_t count;
rv = getSiblingCount(walker, countPattern, aContext, &count);
NS_ENSURE_SUCCESS(rv, rv);
aValues.add(NS_INT32_TO_PTR(count));
break;
}
@ -189,7 +202,12 @@ txXSLTNumber::getValueList(Expr* aValueExpr, txPattern* aCountPattern,
if (aFromPattern && aValues.getLength()) {
bool hasParent;
while ((hasParent = walker.moveToParent())) {
if (aFromPattern->matches(walker.getCurrentPosition(), aContext)) {
bool matched;
rv = aFromPattern->matches(walker.getCurrentPosition(),
aContext, matched);
NS_ENSURE_SUCCESS(rv, rv);
if (matched) {
break;
}
}
@ -205,16 +223,28 @@ txXSLTNumber::getValueList(Expr* aValueExpr, txPattern* aCountPattern,
txXPathTreeWalker walker(currNode);
bool matchedFrom = false;
do {
if (aFromPattern && !walker.isOnNode(currNode) &&
aFromPattern->matches(walker.getCurrentPosition(), aContext)) {
//... we find one that matches from
matchedFrom = true;
break;
if (aFromPattern && !walker.isOnNode(currNode)) {
rv = aFromPattern->matches(walker.getCurrentPosition(),
aContext, matchedFrom);
NS_ENSURE_SUCCESS(rv, rv);
if (matchedFrom) {
//... we find one that matches from
break;
}
}
if (countPattern->matches(walker.getCurrentPosition(), aContext)) {
aValues.add(NS_INT32_TO_PTR(getSiblingCount(walker, countPattern,
aContext)));
bool matched;
rv = countPattern->matches(walker.getCurrentPosition(), aContext,
matched);
NS_ENSURE_SUCCESS(rv, rv);
if (matched) {
int32_t count;
rv = getSiblingCount(walker, countPattern, aContext, &count);
NS_ENSURE_SUCCESS(rv, rv);
aValues.add(NS_INT32_TO_PTR(count));
}
} while (walker.moveToParent());
@ -232,13 +262,22 @@ txXSLTNumber::getValueList(Expr* aValueExpr, txPattern* aCountPattern,
txXPathTreeWalker walker(currNode);
do {
if (aFromPattern && !walker.isOnNode(currNode) &&
aFromPattern->matches(walker.getCurrentPosition(), aContext)) {
matchedFrom = true;
break;
if (aFromPattern && !walker.isOnNode(currNode)) {
rv = aFromPattern->matches(walker.getCurrentPosition(),
aContext, matchedFrom);
NS_ENSURE_SUCCESS(rv, rv);
if (matchedFrom) {
break;
}
}
if (countPattern->matches(walker.getCurrentPosition(), aContext)) {
bool matched;
rv = countPattern->matches(walker.getCurrentPosition(), aContext,
matched);
NS_ENSURE_SUCCESS(rv, rv);
if (matched) {
++value;
}
@ -256,10 +295,6 @@ txXSLTNumber::getValueList(Expr* aValueExpr, txPattern* aCountPattern,
}
}
if (ownsCountPattern) {
delete countPattern;
}
return NS_OK;
}
@ -388,18 +423,27 @@ txXSLTNumber::getCounters(Expr* aGroupSize, Expr* aGroupSeparator,
return NS_OK;
}
int32_t
nsresult
txXSLTNumber::getSiblingCount(txXPathTreeWalker& aWalker,
txPattern* aCountPattern,
txIMatchContext* aContext)
txIMatchContext* aContext,
int32_t* aCount)
{
int32_t value = 1;
while (aWalker.moveToPreviousSibling()) {
if (aCountPattern->matches(aWalker.getCurrentPosition(), aContext)) {
bool matched;
nsresult rv = aCountPattern->matches(aWalker.getCurrentPosition(),
aContext, matched);
NS_ENSURE_SUCCESS(rv, rv);
if (matched) {
++value;
}
}
return value;
*aCount = value;
return NS_OK;
}
bool

Просмотреть файл

@ -46,9 +46,10 @@ private:
* position.
*
*/
static int32_t getSiblingCount(txXPathTreeWalker& aWalker,
txPattern* aCountPattern,
txIMatchContext* aContext);
static nsresult getSiblingCount(txXPathTreeWalker& aWalker,
txPattern* aCountPattern,
txIMatchContext* aContext,
int32_t* aCount);
static bool getPrevInDocumentOrder(txXPathTreeWalker& aWalker);

Просмотреть файл

@ -32,15 +32,25 @@ double txUnionPattern::getDefaultPriority()
* This should be called on the simple patterns for xsl:template,
* but is fine for xsl:key and xsl:number
*/
bool txUnionPattern::matches(const txXPathNode& aNode, txIMatchContext* aContext)
nsresult
txUnionPattern::matches(const txXPathNode& aNode, txIMatchContext* aContext,
bool& aMatched)
{
uint32_t i, len = mLocPathPatterns.Length();
for (i = 0; i < len; ++i) {
if (mLocPathPatterns[i]->matches(aNode, aContext)) {
return true;
nsresult rv = mLocPathPatterns[i]->matches(aNode, aContext, aMatched);
NS_ENSURE_SUCCESS(rv, rv);
if (aMatched) {
aMatched = true;
return NS_OK;
}
}
return false;
aMatched = false;
return NS_OK;
}
txPattern::Type
@ -103,7 +113,9 @@ nsresult txLocPathPattern::addStep(txPattern* aPattern, bool isChild)
return NS_OK;
}
bool txLocPathPattern::matches(const txXPathNode& aNode, txIMatchContext* aContext)
nsresult
txLocPathPattern::matches(const txXPathNode& aNode, txIMatchContext* aContext,
bool& aMatched)
{
NS_ASSERTION(mSteps.Length() > 1, "Internal error");
@ -121,18 +133,39 @@ bool txLocPathPattern::matches(const txXPathNode& aNode, txIMatchContext* aConte
uint32_t pos = mSteps.Length();
Step* step = &mSteps[--pos];
if (!step->pattern->matches(aNode, aContext))
return false;
nsresult rv = step->pattern->matches(aNode, aContext, aMatched);
NS_ENSURE_SUCCESS(rv, rv);
if (!aMatched) {
return NS_OK;
}
txXPathTreeWalker walker(aNode);
bool hasParent = walker.moveToParent();
while (step->isChild) {
if (!pos)
return true; // all steps matched
if (!pos) {
aMatched = true;
return NS_OK; // all steps matched
}
if (!hasParent) {
// no more ancestors
aMatched = false;
return NS_OK;
}
step = &mSteps[--pos];
if (!hasParent || !step->pattern->matches(walker.getCurrentPosition(), aContext))
return false; // no more ancestors or no match
rv = step->pattern->matches(walker.getCurrentPosition(), aContext,
aMatched);
NS_ENSURE_SUCCESS(rv, rv);
if (!aMatched) {
// no match
return NS_OK;
}
hasParent = walker.moveToParent();
}
@ -142,12 +175,19 @@ bool txLocPathPattern::matches(const txXPathNode& aNode, txIMatchContext* aConte
uint32_t blockPos = pos;
while (pos) {
if (!hasParent)
return false; // There are more steps in the current block
// than ancestors of the tested node
if (!hasParent) {
aMatched = false; // There are more steps in the current block
// than ancestors of the tested node
return NS_OK;
}
step = &mSteps[--pos];
if (!step->pattern->matches(walker.getCurrentPosition(), aContext)) {
bool matched;
rv = step->pattern->matches(walker.getCurrentPosition(), aContext,
matched);
NS_ENSURE_SUCCESS(rv, rv);
if (!matched) {
// Didn't match. We restart at beginning of block using a new
// start node
pos = blockPos;
@ -164,7 +204,9 @@ bool txLocPathPattern::matches(const txXPathNode& aNode, txIMatchContext* aConte
}
}
return true;
aMatched = true;
return NS_OK;
} // txLocPathPattern::matches
double txLocPathPattern::getDefaultPriority()
@ -218,9 +260,13 @@ txLocPathPattern::toString(nsAString& aDest)
* a txPattern matching the document node, or '/'
*/
bool txRootPattern::matches(const txXPathNode& aNode, txIMatchContext* aContext)
nsresult
txRootPattern::matches(const txXPathNode& aNode, txIMatchContext* aContext,
bool& aMatched)
{
return txXPathNodeUtils::isRoot(aNode);
aMatched = txXPathNodeUtils::isRoot(aNode);
return NS_OK;
}
double txRootPattern::getDefaultPriority()
@ -264,10 +310,14 @@ txIdPattern::txIdPattern(const nsSubstring& aString)
}
}
bool txIdPattern::matches(const txXPathNode& aNode, txIMatchContext* aContext)
nsresult
txIdPattern::matches(const txXPathNode& aNode, txIMatchContext* aContext,
bool& aMatched)
{
if (!txXPathNodeUtils::isElement(aNode)) {
return false;
aMatched = false;
return NS_OK;
}
// Get a ID attribute, if there is
@ -275,7 +325,9 @@ bool txIdPattern::matches(const txXPathNode& aNode, txIMatchContext* aContext)
NS_ASSERTION(content, "a Element without nsIContent");
nsIAtom* id = content->GetID();
return id && mIds.IndexOf(id) > -1;
aMatched = id && mIds.IndexOf(id) > -1;
return NS_OK;
}
double txIdPattern::getDefaultPriority()
@ -320,18 +372,22 @@ txIdPattern::toString(nsAString& aDest)
* argument.
*/
bool txKeyPattern::matches(const txXPathNode& aNode, txIMatchContext* aContext)
nsresult
txKeyPattern::matches(const txXPathNode& aNode, txIMatchContext* aContext,
bool& aMatched)
{
txExecutionState* es = (txExecutionState*)aContext->getPrivateContext();
nsAutoPtr<txXPathNode> contextDoc(txXPathNodeUtils::getOwnerDocument(aNode));
NS_ENSURE_TRUE(contextDoc, false);
NS_ENSURE_TRUE(contextDoc, NS_ERROR_FAILURE);
RefPtr<txNodeSet> nodes;
nsresult rv = es->getKeyNodes(mName, *contextDoc, mValue, true,
getter_AddRefs(nodes));
NS_ENSURE_SUCCESS(rv, false);
NS_ENSURE_SUCCESS(rv, rv);
return nodes->contains(aNode);
aMatched = nodes->contains(aNode);
return NS_OK;
}
double txKeyPattern::getDefaultPriority()
@ -373,21 +429,32 @@ txKeyPattern::toString(nsAString& aDest)
* a txPattern to hold the NodeTest and the Predicates of a StepPattern
*/
bool txStepPattern::matches(const txXPathNode& aNode, txIMatchContext* aContext)
nsresult
txStepPattern::matches(const txXPathNode& aNode, txIMatchContext* aContext,
bool& aMatched)
{
NS_ASSERTION(mNodeTest, "Internal error");
if (!mNodeTest->matches(aNode, aContext))
return false;
nsresult rv = mNodeTest->matches(aNode, aContext, aMatched);
NS_ENSURE_SUCCESS(rv, rv);
if (!aMatched) {
return NS_OK;
}
txXPathTreeWalker walker(aNode);
if ((!mIsAttr &&
txXPathNodeUtils::isAttribute(walker.getCurrentPosition())) ||
!walker.moveToParent()) {
return false;
aMatched = false;
return NS_OK;
}
if (isEmpty()) {
return true;
aMatched = true;
return NS_OK;
}
/*
@ -410,13 +477,17 @@ bool txStepPattern::matches(const txXPathNode& aNode, txIMatchContext* aContext)
// Create the context node set for evaluating the predicates
RefPtr<txNodeSet> nodes;
nsresult rv = aContext->recycler()->getNodeSet(getter_AddRefs(nodes));
NS_ENSURE_SUCCESS(rv, false);
rv = aContext->recycler()->getNodeSet(getter_AddRefs(nodes));
NS_ENSURE_SUCCESS(rv, rv);
bool hasNext = mIsAttr ? walker.moveToFirstAttribute() :
walker.moveToFirstChild();
while (hasNext) {
if (mNodeTest->matches(walker.getCurrentPosition(), aContext)) {
bool matched;
rv = mNodeTest->matches(walker.getCurrentPosition(), aContext, matched);
NS_ENSURE_SUCCESS(rv, rv);
if (matched) {
nodes->append(walker.getCurrentPosition());
}
hasNext = mIsAttr ? walker.moveToNextAttribute() :
@ -426,7 +497,7 @@ bool txStepPattern::matches(const txXPathNode& aNode, txIMatchContext* aContext)
Expr* predicate = mPredicates[0];
RefPtr<txNodeSet> newNodes;
rv = aContext->recycler()->getNodeSet(getter_AddRefs(newNodes));
NS_ENSURE_SUCCESS(rv, false);
NS_ENSURE_SUCCESS(rv, rv);
uint32_t i, predLen = mPredicates.Length();
for (i = 1; i < predLen; ++i) {
@ -437,7 +508,7 @@ bool txStepPattern::matches(const txXPathNode& aNode, txIMatchContext* aContext)
predContext.next();
RefPtr<txAExprResult> exprResult;
rv = predicate->evaluate(&predContext, getter_AddRefs(exprResult));
NS_ENSURE_SUCCESS(rv, false);
NS_ENSURE_SUCCESS(rv, rv);
switch(exprResult->getResultType()) {
case txAExprResult::NUMBER:
@ -464,20 +535,25 @@ bool txStepPattern::matches(const txXPathNode& aNode, txIMatchContext* aContext)
nodes->clear();
nodes->append(*newNodes);
if (!contextIsInPredicate) {
return false;
aMatched = false;
return NS_OK;
}
predicate = mPredicates[i];
}
txForwardContext evalContext(aContext, aNode, nodes);
RefPtr<txAExprResult> exprResult;
rv = predicate->evaluate(&evalContext, getter_AddRefs(exprResult));
NS_ENSURE_SUCCESS(rv, false);
NS_ENSURE_SUCCESS(rv, rv);
if (exprResult->getResultType() == txAExprResult::NUMBER)
if (exprResult->getResultType() == txAExprResult::NUMBER) {
// handle default, [position() == numberValue()]
return ((double)evalContext.position() == exprResult->numberValue());
aMatched = ((double)evalContext.position() == exprResult->numberValue());
} else {
aMatched = exprResult->booleanValue();
}
return exprResult->booleanValue();
return NS_OK;
} // matches
double txStepPattern::getDefaultPriority()

Просмотреть файл

@ -26,8 +26,9 @@ public:
/*
* Determines whether this Pattern matches the given node.
*/
virtual bool matches(const txXPathNode& aNode,
txIMatchContext* aContext) = 0;
virtual nsresult matches(const txXPathNode& aNode,
txIMatchContext* aContext,
bool& aMatched) = 0;
/*
* Returns the default priority of this Pattern.
@ -86,7 +87,8 @@ public:
};
#define TX_DECL_PATTERN_BASE \
bool matches(const txXPathNode& aNode, txIMatchContext* aContext) override; \
nsresult matches(const txXPathNode& aNode, txIMatchContext* aContext, \
bool& aMatched) override; \
double getDefaultPriority() override; \
virtual Expr* getSubExprAt(uint32_t aPos) override; \
virtual void setSubExprAt(uint32_t aPos, Expr* aExpr) override; \

Просмотреть файл

@ -10,6 +10,7 @@
#include "nsString.h"
#include "nsStreamUtils.h"
#include "nsTArray.h"
#include "mozilla/CheckedInt.h"
using namespace mozilla;
using namespace mozilla::image;
@ -58,6 +59,11 @@ nsBMPEncoder::InitFromData(const uint8_t* aData,
return NS_ERROR_INVALID_ARG;
}
CheckedInt32 check = CheckedInt32(aWidth) * 4;
if (MOZ_UNLIKELY(!check.isValid())) {
return NS_ERROR_INVALID_ARG;
}
// Stride is the padded width of each row, so it better be longer
if ((aInputFormat == INPUT_FORMAT_RGB &&
aStride < aWidth * 3) ||
@ -86,19 +92,19 @@ nsBMPEncoder::InitFromData(const uint8_t* aData,
// Just a helper method to make it explicit in calculations that we are dealing
// with bytes and not bits
static inline uint32_t
BytesPerPixel(uint32_t aBPP)
static inline uint16_t
BytesPerPixel(uint16_t aBPP)
{
return aBPP / 8;
}
// Calculates the number of padding bytes that are needed per row of image data
static inline uint32_t
PaddingBytes(uint32_t aBPP, uint32_t aWidth)
PaddingBytes(uint16_t aBPP, uint32_t aWidth)
{
uint32_t rowSize = aWidth * BytesPerPixel(aBPP);
uint8_t paddingSize = 0;
if(rowSize % 4) {
if (rowSize % 4) {
paddingSize = (4 - (rowSize % 4));
}
return paddingSize;
@ -125,14 +131,21 @@ nsBMPEncoder::StartImageEncode(uint32_t aWidth,
// parse and check any provided output options
Version version;
uint32_t bpp;
uint16_t bpp;
nsresult rv = ParseOptions(aOutputOptions, version, bpp);
if (NS_FAILED(rv)) {
return rv;
}
MOZ_ASSERT(bpp <= 32);
InitFileHeader(version, bpp, aWidth, aHeight);
InitInfoHeader(version, bpp, aWidth, aHeight);
rv = InitFileHeader(version, bpp, aWidth, aHeight);
if (NS_FAILED(rv)) {
return rv;
}
rv = InitInfoHeader(version, bpp, aWidth, aHeight);
if (NS_FAILED(rv)) {
return rv;
}
mImageBufferSize = mBMPFileHeader.filesize;
mImageBufferStart = static_cast<uint8_t*>(malloc(mImageBufferSize));
@ -187,12 +200,26 @@ nsBMPEncoder::AddImageFrame(const uint8_t* aData,
return NS_ERROR_INVALID_ARG;
}
auto row = MakeUniqueFallible<uint8_t[]>(mBMPInfoHeader.width *
BytesPerPixel(mBMPInfoHeader.bpp));
if (mBMPInfoHeader.width < 0) {
return NS_ERROR_ILLEGAL_VALUE;
}
CheckedUint32 size =
CheckedUint32(mBMPInfoHeader.width) * CheckedUint32(BytesPerPixel(mBMPInfoHeader.bpp));
if (MOZ_UNLIKELY(!size.isValid())) {
return NS_ERROR_FAILURE;
}
auto row = MakeUniqueFallible<uint8_t[]>(size.value());
if (!row) {
return NS_ERROR_OUT_OF_MEMORY;
}
CheckedUint32 check = CheckedUint32(mBMPInfoHeader.height) * aStride;
if (MOZ_UNLIKELY(!check.isValid())) {
return NS_ERROR_FAILURE;
}
// write each row: if we add more input formats, we may want to
// generalize the conversions
if (aInputFormat == INPUT_FORMAT_HOSTARGB) {
@ -256,7 +283,7 @@ nsBMPEncoder::EndImageEncode()
// See InitFromData for a description of the parse options
nsresult
nsBMPEncoder::ParseOptions(const nsAString& aOptions, Version& aVersionOut,
uint32_t& aBppOut)
uint16_t& aBppOut)
{
aVersionOut = VERSION_3;
aBppOut = 24;
@ -424,7 +451,7 @@ nsBMPEncoder::ConvertHostARGBRow(const uint8_t* aSrc,
const UniquePtr<uint8_t[]>& aDest,
uint32_t aPixelWidth)
{
int bytes = BytesPerPixel(mBMPInfoHeader.bpp);
uint16_t bytes = BytesPerPixel(mBMPInfoHeader.bpp);
if (mBMPInfoHeader.bpp == 32) {
for (uint32_t x = 0; x < aPixelWidth; x++) {
@ -473,8 +500,8 @@ nsBMPEncoder::NotifyListener()
}
// Initializes the BMP file header mBMPFileHeader to the passed in values
void
nsBMPEncoder::InitFileHeader(Version aVersion, uint32_t aBPP, uint32_t aWidth,
nsresult
nsBMPEncoder::InitFileHeader(Version aVersion, uint16_t aBPP, uint32_t aWidth,
uint32_t aHeight)
{
memset(&mBMPFileHeader, 0, sizeof(mBMPFileHeader));
@ -491,13 +518,25 @@ nsBMPEncoder::InitFileHeader(Version aVersion, uint32_t aBPP, uint32_t aWidth,
if (aBPP <= 8) {
uint32_t numColors = 1 << aBPP;
mBMPFileHeader.dataoffset += 4 * numColors;
mBMPFileHeader.filesize = mBMPFileHeader.dataoffset + aWidth * aHeight;
CheckedUint32 filesize =
CheckedUint32(mBMPFileHeader.dataoffset) + CheckedUint32(aWidth) * aHeight;
if (MOZ_UNLIKELY(!filesize.isValid())) {
return NS_ERROR_INVALID_ARG;
}
mBMPFileHeader.filesize = filesize.value();
} else {
mBMPFileHeader.filesize = mBMPFileHeader.dataoffset +
(aWidth * BytesPerPixel(aBPP) + PaddingBytes(aBPP, aWidth)) * aHeight;
CheckedUint32 filesize =
CheckedUint32(mBMPFileHeader.dataoffset) +
(CheckedUint32(aWidth) * BytesPerPixel(aBPP) + PaddingBytes(aBPP, aWidth)) * aHeight;
if (MOZ_UNLIKELY(!filesize.isValid())) {
return NS_ERROR_INVALID_ARG;
}
mBMPFileHeader.filesize = filesize.value();
}
mBMPFileHeader.reserved = 0;
return NS_OK;
}
#define ENCODE(pImageBufferCurr, value) \
@ -505,8 +544,8 @@ nsBMPEncoder::InitFileHeader(Version aVersion, uint32_t aBPP, uint32_t aWidth,
*pImageBufferCurr += sizeof value;
// Initializes the bitmap info header mBMPInfoHeader to the passed in values
void
nsBMPEncoder::InitInfoHeader(Version aVersion, uint32_t aBPP, uint32_t aWidth,
nsresult
nsBMPEncoder::InitInfoHeader(Version aVersion, uint16_t aBPP, uint32_t aWidth,
uint32_t aHeight)
{
memset(&mBMPInfoHeader, 0, sizeof(mBMPInfoHeader));
@ -516,18 +555,39 @@ nsBMPEncoder::InitInfoHeader(Version aVersion, uint32_t aBPP, uint32_t aWidth,
MOZ_ASSERT(aVersion == VERSION_5);
mBMPInfoHeader.bihsize = InfoHeaderLength::WIN_V5;
}
mBMPInfoHeader.width = aWidth;
mBMPInfoHeader.height = aHeight;
CheckedInt32 width(aWidth);
CheckedInt32 height(aHeight);
if (MOZ_UNLIKELY(!width.isValid() || !height.isValid())) {
return NS_ERROR_INVALID_ARG;
}
mBMPInfoHeader.width = width.value();
mBMPInfoHeader.height = height.value();
mBMPInfoHeader.planes = 1;
mBMPInfoHeader.bpp = aBPP;
mBMPInfoHeader.compression = 0;
mBMPInfoHeader.colors = 0;
mBMPInfoHeader.important_colors = 0;
CheckedUint32 check = CheckedUint32(aWidth) * BytesPerPixel(aBPP);
if (MOZ_UNLIKELY(!check.isValid())) {
return NS_ERROR_INVALID_ARG;
}
if (aBPP <= 8) {
mBMPInfoHeader.image_size = aWidth * aHeight;
CheckedUint32 imagesize = CheckedUint32(aWidth) * aHeight;
if (MOZ_UNLIKELY(!imagesize.isValid())) {
return NS_ERROR_INVALID_ARG;
}
mBMPInfoHeader.image_size = imagesize.value();
} else {
mBMPInfoHeader.image_size =
(aWidth * BytesPerPixel(aBPP) + PaddingBytes(aBPP, aWidth)) * aHeight;
CheckedUint32 imagesize =
(CheckedUint32(aWidth) * BytesPerPixel(aBPP) + PaddingBytes(aBPP, aWidth)) * CheckedUint32(aHeight);
if (MOZ_UNLIKELY(!imagesize.isValid())) {
return NS_ERROR_INVALID_ARG;
}
mBMPInfoHeader.image_size = imagesize.value();
}
mBMPInfoHeader.xppm = 0;
mBMPInfoHeader.yppm = 0;
@ -554,6 +614,8 @@ nsBMPEncoder::InitInfoHeader(Version aVersion, uint32_t aBPP, uint32_t aWidth,
mBMPInfoHeader.profile_size = 0;
mBMPInfoHeader.reserved = 0;
}
return NS_OK;
}
// Encodes the BMP file header mBMPFileHeader

Просмотреть файл

@ -104,7 +104,7 @@ protected:
// See InitData in the cpp for valid parse options
nsresult ParseOptions(const nsAString& aOptions, Version& aVersionOut,
uint32_t& aBppOut);
uint16_t& aBppOut);
// Obtains data with no alpha in machine-independent byte order
void ConvertHostARGBRow(const uint8_t* aSrc,
const mozilla::UniquePtr<uint8_t[]>& aDest,
@ -113,11 +113,11 @@ protected:
void NotifyListener();
// Initializes the bitmap file header member mBMPFileHeader
void InitFileHeader(Version aVersion, uint32_t aBPP, uint32_t aWidth,
uint32_t aHeight);
nsresult InitFileHeader(Version aVersion, uint16_t aBPP, uint32_t aWidth,
uint32_t aHeight);
// Initializes the bitmap info header member mBMPInfoHeader
void InitInfoHeader(Version aVersion, uint32_t aBPP, uint32_t aWidth,
uint32_t aHeight);
nsresult InitInfoHeader(Version aVersion, uint16_t aBPP, uint32_t aWidth,
uint32_t aHeight);
// Encodes the bitmap file header member mBMPFileHeader
void EncodeFileHeader();

Просмотреть файл

@ -228,10 +228,11 @@ nsICOEncoder::StartImageEncode(uint32_t aWidth,
}
// parse and check any provided output options
uint32_t bpp = 24;
uint16_t bpp = 24;
bool usePNG = true;
nsresult rv = ParseOptions(aOutputOptions, bpp, usePNG);
NS_ENSURE_SUCCESS(rv, rv);
MOZ_ASSERT(bpp <= 32);
mUsePNG = usePNG;
@ -265,7 +266,7 @@ nsICOEncoder::EndImageEncode()
// Parses the encoder options and sets the bits per pixel to use and PNG or BMP
// See InitFromData for a description of the parse options
nsresult
nsICOEncoder::ParseOptions(const nsAString& aOptions, uint32_t& aBppOut,
nsICOEncoder::ParseOptions(const nsAString& aOptions, uint16_t& aBppOut,
bool& aUsePNGOut)
{
// If no parsing options just use the default of 24BPP and PNG yes
@ -469,7 +470,7 @@ nsICOEncoder::InitFileHeader()
// Initializes the icon directory info header mICODirEntry
void
nsICOEncoder::InitInfoHeader(uint32_t aBPP, uint8_t aWidth, uint8_t aHeight)
nsICOEncoder::InitInfoHeader(uint16_t aBPP, uint8_t aWidth, uint8_t aHeight)
{
memset(&mICODirEntry, 0, sizeof(mICODirEntry));
mICODirEntry.mBitCount = aBPP;

Просмотреть файл

@ -50,14 +50,14 @@ public:
protected:
~nsICOEncoder();
nsresult ParseOptions(const nsAString& aOptions, uint32_t& aBppOut,
nsresult ParseOptions(const nsAString& aOptions, uint16_t& aBppOut,
bool& aUsePNGOut);
void NotifyListener();
// Initializes the icon file header mICOFileHeader
void InitFileHeader();
// Initializes the icon directory info header mICODirEntry
void InitInfoHeader(uint32_t aBPP, uint8_t aWidth, uint8_t aHeight);
void InitInfoHeader(uint16_t aBPP, uint8_t aWidth, uint8_t aHeight);
// Encodes the icon file header mICOFileHeader
void EncodeFileHeader();
// Encodes the icon directory info header mICODirEntry

Просмотреть файл

@ -902,6 +902,8 @@ LIRGeneratorARM::visitAsmJSCompareExchangeHeap(MAsmJSCompareExchangeHeap* ins)
MOZ_ASSERT(base->type() == MIRType::Int32);
if (byteSize(ins->access().type()) != 4 && !HasLDSTREXBHD()) {
gen->setPerformsCall();
LAsmJSCompareExchangeCallout* lir =
new(alloc()) LAsmJSCompareExchangeCallout(useFixedAtStart(base, IntArgReg2),
useFixedAtStart(ins->oldValue(), IntArgReg3),
@ -929,6 +931,8 @@ LIRGeneratorARM::visitAsmJSAtomicExchangeHeap(MAsmJSAtomicExchangeHeap* ins)
MOZ_ASSERT(ins->access().offset() == 0);
if (byteSize(ins->access().type()) < 4 && !HasLDSTREXBHD()) {
gen->setPerformsCall();
// Call out on ARMv6.
defineReturn(new(alloc()) LAsmJSAtomicExchangeCallout(useFixedAtStart(ins->base(), IntArgReg2),
useFixedAtStart(ins->value(), IntArgReg3),
@ -953,6 +957,8 @@ LIRGeneratorARM::visitAsmJSAtomicBinopHeap(MAsmJSAtomicBinopHeap* ins)
MOZ_ASSERT(base->type() == MIRType::Int32);
if (byteSize(ins->access().type()) != 4 && !HasLDSTREXBHD()) {
gen->setPerformsCall();
LAsmJSAtomicBinopCallout* lir =
new(alloc()) LAsmJSAtomicBinopCallout(useFixedAtStart(base, IntArgReg2),
useFixedAtStart(ins->value(), IntArgReg3),

Просмотреть файл

@ -238,6 +238,19 @@ AssertedCast(const From aFrom)
return static_cast<To>(aFrom);
}
/**
* Cast a value of integral type |From| to a value of integral type |To|,
* release asserting that the cast will be a safe cast per C++ (that is, that
* |to| is in the range of values permitted for the type |From|).
*/
template<typename To, typename From>
inline To
ReleaseAssertedCast(const From aFrom)
{
MOZ_RELEASE_ASSERT((detail::IsInBounds<From, To>(aFrom)));
return static_cast<To>(aFrom);
}
} // namespace mozilla
#endif /* mozilla_Casting_h */

Просмотреть файл

@ -9,6 +9,7 @@
#include "mozilla/RangedPtr.h"
#include "mozilla/TypeTraits.h"
#include "mozilla/Span.h"
#include <stddef.h>
@ -44,6 +45,19 @@ public:
mEnd(aOther.mEnd)
{}
MOZ_IMPLICIT Range(Span<T> aSpan)
: Range(aSpan.Elements(), aSpan.Length())
{
}
template<typename U,
class = typename EnableIf<IsConvertible<U (*)[], T (*)[]>::value,
int>::Type>
MOZ_IMPLICIT Range(const Span<U>& aSpan)
: Range(aSpan.Elements(), aSpan.Length())
{
}
RangedPtr<T> begin() const { return mStart; }
RangedPtr<T> end() const { return mEnd; }
size_t length() const { return mEnd - mStart; }
@ -51,8 +65,26 @@ public:
T& operator[](size_t aOffset) const { return mStart[aOffset]; }
explicit operator bool() const { return mStart != nullptr; }
operator Span<T>() { return Span<T>(mStart.get(), length()); }
operator Span<const T>() const { return Span<T>(mStart.get(), length()); }
};
template<class T>
Span<T>
MakeSpan(Range<T>& aRange)
{
return aRange;
}
template<class T>
Span<const T>
MakeSpan(const Range<T>& aRange)
{
return aRange;
}
} // namespace mozilla
#endif /* mozilla_Range_h */

1041
mfbt/Span.h Normal file

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -82,6 +82,7 @@ EXPORTS.mozilla = [
'SegmentedVector.h',
'SHA1.h',
'SizePrintfMacros.h',
'Span.h',
'SplayTree.h',
'Sprintf.h',
'StaticAnalysisFunctions.h',

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -0,0 +1,15 @@
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# 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/.
UNIFIED_SOURCES += [
'TestSpan.cpp',
]
#LOCAL_INCLUDES += [
# '../../base',
#]
FINAL_LIBRARY = 'xul-gtest'

Просмотреть файл

@ -4,6 +4,11 @@
# 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/.
if not CONFIG['JS_STANDALONE']:
TEST_DIRS += [
'gtest',
]
CppUnitTests([
'TestArray',
'TestArrayUtils',

Просмотреть файл

@ -55,7 +55,7 @@ public final class EventDispatcher extends JNIObject {
new HashMap<String, List<BundleEventListener>>(DEFAULT_BACKGROUND_EVENTS_COUNT);
private boolean mAttachedToGecko;
private final StateHolder mStateHolder;
private volatile StateHolder mStateHolder;
@ReflectionTarget
@WrapForJNI(calledFrom = "gecko")
@ -71,6 +71,13 @@ public final class EventDispatcher extends JNIObject {
mStateHolder = stateHolder;
}
/* package */ void setStateHolder(final NativeQueue.StateHolder stateHolder) {
mStateHolder = stateHolder;
// Force queue flushing.
final NativeQueue.State state = mStateHolder.getState();
mStateHolder.checkAndSetState(state, state);
}
private boolean isReadyForDispatchingToGecko() {
return mStateHolder.isReady();
}

Просмотреть файл

@ -47,10 +47,10 @@ public class GeckoView extends LayerView
@WrapForJNI INITIAL(0),
@WrapForJNI READY(1);
private int rank;
private int mRank;
private State(int rank) {
this.rank = rank;
mRank = rank;
}
@Override
@ -61,22 +61,17 @@ public class GeckoView extends LayerView
@Override
public boolean isAtLeast(final NativeQueue.State other) {
if (other instanceof State) {
return this.rank >= ((State) other).rank;
return mRank >= ((State) other).mRank;
}
return false;
}
}
private final StateHolder mStateHolder =
private static final StateHolder sDummyStateHolder =
new StateHolder(State.INITIAL, State.READY);
@WrapForJNI(calledFrom = "gecko")
private void setState(final State newState) {
mStateHolder.setState(newState);
}
private final EventDispatcher mEventDispatcher =
new EventDispatcher(mStateHolder);
new EventDispatcher(sDummyStateHolder);
private ChromeDelegate mChromeDelegate;
/* package */ ContentListener mContentListener;
@ -92,6 +87,10 @@ public class GeckoView extends LayerView
@WrapForJNI(dispatchTo = "proxy")
protected static final class Window extends JNIObject {
@WrapForJNI(skip = true)
/* package */ final StateHolder mStateHolder =
new StateHolder(State.INITIAL, State.READY);
@WrapForJNI(skip = true)
/* package */ Window() {}
@ -101,9 +100,18 @@ public class GeckoView extends LayerView
int screenId);
@Override protected native void disposeNative();
native void close();
native void reattach(GeckoView view, Object compositor, EventDispatcher dispatcher);
native void reattach(GeckoView view, Object compositor,
EventDispatcher dispatcher);
native void loadUri(String uri, int flags);
@WrapForJNI(calledFrom = "gecko")
private void setState(final State newState) {
mStateHolder.setState(newState);
}
}
// Object to hold onto our nsWindow connection when GeckoView gets destroyed.
@ -197,9 +205,9 @@ public class GeckoView extends LayerView
}
}
protected Window window;
private boolean stateSaved;
private final Listener listener = new Listener();
protected Window mWindow;
private boolean mStateSaved;
private final Listener mListener = new Listener();
public GeckoView(Context context) {
super(context);
@ -227,7 +235,7 @@ public class GeckoView extends LayerView
GeckoAppShell.setLayerView(this);
initializeView();
listener.registerListeners();
mListener.registerListeners();
mSettings = new GeckoViewSettings(getEventDispatcher());
}
@ -235,8 +243,8 @@ public class GeckoView extends LayerView
@Override
protected Parcelable onSaveInstanceState() {
final Parcelable superState = super.onSaveInstanceState();
stateSaved = true;
return new StateBinder(superState, this.window);
mStateSaved = true;
return new StateBinder(superState, mWindow);
}
@Override
@ -244,9 +252,9 @@ public class GeckoView extends LayerView
final StateBinder stateBinder = (StateBinder) state;
if (stateBinder.window != null) {
this.window = stateBinder.window;
mWindow = stateBinder.window;
}
stateSaved = false;
mStateSaved = false;
if (mOnAttachedToWindowCalled) {
reattachWindow();
@ -263,12 +271,12 @@ public class GeckoView extends LayerView
}
if (GeckoThread.isStateAtLeast(GeckoThread.State.PROFILE_READY)) {
Window.open(window, this, getCompositor(), mEventDispatcher,
Window.open(mWindow, this, getCompositor(), mEventDispatcher,
mChromeUri, mSettings.asBundle(), mScreenId);
} else {
GeckoThread.queueNativeCallUntil(
GeckoThread.State.PROFILE_READY,
Window.class, "open", window,
Window.class, "open", mWindow,
GeckoView.class, this,
Object.class, getCompositor(),
EventDispatcher.class, mEventDispatcher,
@ -279,11 +287,13 @@ public class GeckoView extends LayerView
}
protected void reattachWindow() {
mEventDispatcher.setStateHolder(mWindow.mStateHolder);
if (GeckoThread.isStateAtLeast(GeckoThread.State.PROFILE_READY)) {
window.reattach(this, getCompositor(), mEventDispatcher);
mWindow.reattach(this, getCompositor(), mEventDispatcher);
} else {
GeckoThread.queueNativeCallUntil(GeckoThread.State.PROFILE_READY,
window, "reattach", GeckoView.class, this,
mWindow, "reattach", GeckoView.class, this,
Object.class, getCompositor(), EventDispatcher.class, mEventDispatcher);
}
}
@ -292,9 +302,10 @@ public class GeckoView extends LayerView
public void onAttachedToWindow() {
final DisplayMetrics metrics = getContext().getResources().getDisplayMetrics();
if (window == null) {
if (mWindow == null) {
// Open a new nsWindow if we didn't have one from before.
window = new Window();
mWindow = new Window();
mEventDispatcher.setStateHolder(mWindow.mStateHolder);
openWindow();
} else {
reattachWindow();
@ -310,21 +321,22 @@ public class GeckoView extends LayerView
super.onDetachedFromWindow();
super.destroy();
if (stateSaved) {
if (mStateSaved) {
// If we saved state earlier, we don't want to close the nsWindow.
return;
}
if (GeckoThread.isStateAtLeast(GeckoThread.State.PROFILE_READY)) {
window.close();
window.disposeNative();
mWindow.close();
mWindow.disposeNative();
} else {
GeckoThread.queueNativeCallUntil(GeckoThread.State.PROFILE_READY,
window, "close");
mWindow, "close");
GeckoThread.queueNativeCallUntil(GeckoThread.State.PROFILE_READY,
window, "disposeNative");
mWindow, "disposeNative");
}
mEventDispatcher.setStateHolder(sDummyStateHolder);
mOnAttachedToWindowCalled = false;
}
@ -339,14 +351,14 @@ public class GeckoView extends LayerView
* @param flags The load flags (TODO).
*/
public void loadUri(String uri, int flags) {
if (window == null) {
if (mWindow == null) {
throw new IllegalStateException("Not attached to window");
}
if (GeckoThread.isRunning()) {
window.loadUri(uri, flags);
mWindow.loadUri(uri, flags);
} else {
GeckoThread.queueNativeCall(window, "loadUri", String.class, uri, flags);
GeckoThread.queueNativeCall(mWindow, "loadUri", String.class, uri, flags);
}
}

Просмотреть файл

@ -25,6 +25,7 @@ EXPORTS += [
]
UNIFIED_SOURCES += [
'AppCacheStorage.cpp',
'CacheEntry.cpp',
'CacheFile.cpp',
'CacheFileChunk.cpp',
@ -46,11 +47,6 @@ UNIFIED_SOURCES += [
'OldWrappers.cpp',
]
# AppCacheStorage.cpp cannot be built in unified mode because it uses plarena.h.
SOURCES += [
'AppCacheStorage.cpp',
]
LOCAL_INCLUDES += [
'/netwerk/base',
'/netwerk/cache',

Просмотреть файл

@ -63,9 +63,6 @@ using namespace mozilla::ipc;
namespace mozilla {
namespace net {
extern bool
WillRedirect(nsHttpResponseHead * response);
namespace {
const uint32_t kMaxFileDescriptorsPerMessage = 250;
@ -3179,14 +3176,14 @@ HttpChannelChild::OverrideWithSynthesizedResponse(nsAutoPtr<nsHttpResponseHead>&
// Intercepted responses should already be decoded. If its a redirect,
// however, we want to respect the encoding of the final result instead.
if (!WillRedirect(aResponseHead)) {
if (!nsHttpChannel::WillRedirect(aResponseHead)) {
SetApplyConversion(false);
}
mResponseHead = aResponseHead;
mSynthesizedResponse = true;
if (WillRedirect(mResponseHead)) {
if (nsHttpChannel::WillRedirect(mResponseHead)) {
mShouldInterceptSubsequentRedirect = true;
// Continue with the original cross-process request
nsresult rv = ContinueAsyncOpen();

Просмотреть файл

@ -21,9 +21,6 @@
namespace mozilla {
namespace net {
extern bool
WillRedirect(const nsHttpResponseHead * response);
extern nsresult
DoUpdateExpirationTime(nsHttpChannel* aSelf,
nsICacheEntry* aCacheEntry,
@ -246,7 +243,7 @@ InterceptedChannelChrome::FinishSynthesizedResponse(const nsACString& aFinalURLS
// If the synthesized response is a redirect, then we want to respect
// the encoding of whatever is loaded as a result.
if (WillRedirect(mSynthesizedResponseHead.ref())) {
if (nsHttpChannel::WillRedirect(mSynthesizedResponseHead.ref())) {
nsresult rv = mChannel->SetApplyConversion(mOldApplyConversion);
NS_ENSURE_SUCCESS(rv, rv);
}

Просмотреть файл

@ -49,18 +49,15 @@ EXPORTS.mozilla.net += [
'TimingStruct.h',
]
# ASpdySession.cpp and nsHttpAuthCache cannot be built in unified mode because
# they use plarena.h.
SOURCES += [
'AlternateServices.cpp',
'ASpdySession.cpp',
'nsHttpAuthCache.cpp',
'nsHttpChannelAuthProvider.cpp', # redefines GetAuthType
]
UNIFIED_SOURCES += [
'AltDataOutputStreamChild.cpp',
'AltDataOutputStreamParent.cpp',
'AlternateServices.cpp',
'ASpdySession.cpp',
'CacheControlParser.cpp',
'ConnectionDiagnostics.cpp',
'HSTSPrimerListener.cpp',
@ -78,6 +75,7 @@ UNIFIED_SOURCES += [
'nsCORSListenerProxy.cpp',
'nsHttp.cpp',
'nsHttpActivityDistributor.cpp',
'nsHttpAuthCache.cpp',
'nsHttpAuthManager.cpp',
'nsHttpBasicAuth.cpp',
'nsHttpChannel.cpp',

Просмотреть файл

@ -192,9 +192,9 @@ Hash(const char *buf, nsACString &hash)
// We only treat 3xx responses as redirects if they have a Location header and
// the status code is in a whitelist.
bool
WillRedirect(nsHttpResponseHead * response)
nsHttpChannel::WillRedirect(nsHttpResponseHead * response)
{
return nsHttpChannel::IsRedirectStatus(response->Status()) &&
return IsRedirectStatus(response->Status()) &&
response->HasHeader(nsHttp::Location);
}

Просмотреть файл

@ -138,6 +138,7 @@ public:
Http2PushedStream *pushedStream);
static bool IsRedirectStatus(uint32_t status);
static bool WillRedirect(nsHttpResponseHead * response);
// Methods HttpBaseChannel didn't implement for us or that we override.

Просмотреть файл

@ -8,6 +8,7 @@
#include "HttpLog.h"
#include "mozilla/Sprintf.h"
#include "mozilla/Unused.h"
#include "nsHttp.h"
#include "nsHttpDigestAuth.h"

Просмотреть файл

@ -699,6 +699,10 @@ nsIndexedToHTML::OnIndexAvailable(nsIRequest *aRequest,
// Adjust the length in case unescaping shortened the string.
loc.Truncate(nsUnescapeCount(loc.BeginWriting()));
if (loc.IsEmpty()) {
return NS_ERROR_ILLEGAL_VALUE;
}
if (loc.First() == char16_t('.'))
pushBuffer.AppendLiteral(" class=\"hidden-object\"");

Просмотреть файл

@ -101,6 +101,7 @@
<li><a href="about:license#gears">Google Gears License</a></li>
<li><a href="about:license#gears-istumbler">Google Gears/iStumbler License</a></li>
<li><a href="about:license#vp8">Google VP8 License</a></li>
<li><a href="about:license#gsl">GSL License</a></li>
<li><a href="about:license#gyp">gyp License</a></li>
<li><a href="about:license#halloc">halloc License</a></li>
<li><a href="about:license#harfbuzz">HarfBuzz License</a></li>
@ -3415,6 +3416,38 @@ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
</pre>
<hr>
<h1><a id="gsl"></a>GSL License</h1>
<p>This license applies to <span class="path">mfbt/Span.h</span> and
<span class="path">mfbt/tests/gtest/TestSpan.cpp</span>.</p>
<!-- https://github.com/Microsoft/GSL/blob/3819df6e378ffccf0e29465afe99c3b324c2aa70/LICENSE -->
<pre>
Copyright (c) 2015 Microsoft Corporation. All rights reserved.
This code is licensed under the MIT License (MIT).
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
</pre>
<hr>
<h1><a id="gyp"></a>gyp License</h1>

Просмотреть файл

@ -116,6 +116,13 @@ using google_breakpad::PageAllocator;
using namespace mozilla;
using mozilla::ipc::CrashReporterClient;
// From toolkit/library/rust/shared/lib.rs
extern "C" {
void install_rust_panic_hook();
bool get_rust_panic_reason(char** reason, size_t* length);
}
namespace CrashReporter {
#ifdef XP_WIN32
@ -1131,7 +1138,17 @@ bool MinidumpCallback(
WriteGlobalMemoryStatus(&apiData, &eventFile);
#endif // XP_WIN
if (gMozCrashReason) {
char* rust_panic_reason;
size_t rust_panic_len;
if (get_rust_panic_reason(&rust_panic_reason, &rust_panic_len)) {
// rust_panic_reason is not null-terminated.
WriteLiteral(apiData, "MozCrashReason=");
apiData.WriteBuffer(rust_panic_reason, rust_panic_len);
WriteLiteral(apiData, "\n");
WriteLiteral(eventFile, "MozCrashReason=");
eventFile.WriteBuffer(rust_panic_reason, rust_panic_len);
WriteLiteral(eventFile, "\n");
} else if (gMozCrashReason) {
WriteAnnotation(apiData, "MozCrashReason", gMozCrashReason);
WriteAnnotation(eventFile, "MozCrashReason", gMozCrashReason);
}
@ -1577,6 +1594,8 @@ nsresult SetExceptionHandler(nsIFile* aXREDirectory,
if (gExceptionHandler)
return NS_ERROR_ALREADY_INITIALIZED;
install_rust_panic_hook();
#if !defined(DEBUG) || defined(MOZ_WIDGET_GONK)
// In non-debug builds, enable the crash reporter by default, and allow
// disabling it with the MOZ_CRASHREPORTER_DISABLE environment variable.

Просмотреть файл

@ -0,0 +1,11 @@
function run_test() {
// Try crashing with a Rust panic
do_crash(function() {
Components.classes["@mozilla.org/xpcom/debug;1"].getService(Components.interfaces.nsIDebug2).rustPanic("OH NO");
},
function(mdump, extra) {
do_check_eq(extra.MozCrashReason, "OH NO");
},
// process will exit with a zero exit status
true);
}

Просмотреть файл

@ -7,6 +7,9 @@ support-files =
[test_crash_moz_crash.js]
[test_crash_purevirtual.js]
[test_crash_rust_panic.js]
# Fails on Win64, bug 1302078.
fail-if = os == 'win' && bits == 64
[test_crash_after_js_oom_reported.js]
[test_crash_after_js_oom_recovered.js]
[test_crash_after_js_oom_reported_2.js]

Просмотреть файл

@ -10,3 +10,59 @@ extern crate nsstring;
extern crate rust_url_capi;
#[cfg(feature = "quantum_render")]
extern crate webrender_bindings;
use std::boxed::Box;
use std::ffi::CStr;
use std::os::raw::c_char;
use std::panic;
/// Used to implement `nsIDebug2::RustPanic` for testing purposes.
#[no_mangle]
pub extern "C" fn intentional_panic(message: *const c_char) {
panic!("{}", unsafe { CStr::from_ptr(message) }.to_string_lossy());
}
/// Contains the panic message, if set.
static mut PANIC_REASON: Option<(*const str, usize)> = None;
/// Configure a panic hook to capture panic messages for crash reports.
///
/// We don't store this in `gMozCrashReason` because:
/// a) Rust strings aren't null-terminated, so we'd have to allocate
/// memory to get a null-terminated string
/// b) The panic=abort handler is going to call `abort()` on non-Windows,
/// which is `mozalloc_abort` for us, which will use `MOZ_CRASH` and
/// overwrite `gMozCrashReason` with an unhelpful string.
#[no_mangle]
pub extern "C" fn install_rust_panic_hook() {
panic::set_hook(Box::new(|info| {
// Try to handle &str/String payloads, which should handle 99% of cases.
let payload = info.payload();
// We'll hold a raw *const str here, but it will be OK because
// Rust is going to abort the process before the payload could be
// deallocated.
if let Some(s) = payload.downcast_ref::<&str>() {
unsafe { PANIC_REASON = Some((*s as *const str, s.len())) }
} else if let Some(s) = payload.downcast_ref::<String>() {
unsafe { PANIC_REASON = Some((s.as_str() as *const str, s.len())) }
} else {
// Not the most helpful thing, but seems unlikely to happen
// in practice.
println!("Unhandled panic payload!");
}
}));
}
#[no_mangle]
pub extern "C" fn get_rust_panic_reason(reason: *mut *const c_char, length: *mut usize) -> bool {
unsafe {
match PANIC_REASON {
Some((s, len)) => {
*reason = s as *const c_char;
*length = len;
true
}
None => false,
}
}
}

Просмотреть файл

@ -967,14 +967,6 @@ auto GeckoThread::State::RUNNING() -> State::LocalRef
const char GeckoView::name[] =
"org/mozilla/gecko/GeckoView";
constexpr char GeckoView::SetState_t::name[];
constexpr char GeckoView::SetState_t::signature[];
auto GeckoView::SetState(mozilla::jni::Object::Param a0) const -> void
{
return mozilla::jni::Method<SetState_t>::Call(GeckoView::mCtx, nullptr, a0);
}
const char GeckoView::State::name[] =
"org/mozilla/gecko/GeckoView$State";
@ -1012,6 +1004,14 @@ constexpr char GeckoView::Window::Open_t::signature[];
constexpr char GeckoView::Window::Reattach_t::name[];
constexpr char GeckoView::Window::Reattach_t::signature[];
constexpr char GeckoView::Window::SetState_t::name[];
constexpr char GeckoView::Window::SetState_t::signature[];
auto GeckoView::Window::SetState(mozilla::jni::Object::Param a0) const -> void
{
return mozilla::jni::Method<SetState_t>::Call(Window::mCtx, nullptr, a0);
}
const char PrefsHelper::name[] =
"org/mozilla/gecko/PrefsHelper";

Просмотреть файл

@ -2883,26 +2883,6 @@ public:
class State;
class Window;
struct SetState_t {
typedef GeckoView Owner;
typedef void ReturnType;
typedef void SetterType;
typedef mozilla::jni::Args<
mozilla::jni::Object::Param> Args;
static constexpr char name[] = "setState";
static constexpr char signature[] =
"(Lorg/mozilla/gecko/GeckoView$State;)V";
static const bool isStatic = false;
static const mozilla::jni::ExceptionMode exceptionMode =
mozilla::jni::ExceptionMode::ABORT;
static const mozilla::jni::CallingThread callingThread =
mozilla::jni::CallingThread::GECKO;
static const mozilla::jni::DispatchTarget dispatchTarget =
mozilla::jni::DispatchTarget::CURRENT;
};
auto SetState(mozilla::jni::Object::Param) const -> void;
static const int32_t LOAD_DEFAULT = 0;
static const int32_t LOAD_NEW_TAB = 1;
@ -2910,7 +2890,7 @@ public:
static const int32_t LOAD_SWITCH_TAB = 2;
static const mozilla::jni::CallingThread callingThread =
mozilla::jni::CallingThread::GECKO;
mozilla::jni::CallingThread::ANY;
};
@ -3068,6 +3048,26 @@ public:
mozilla::jni::DispatchTarget::PROXY;
};
struct SetState_t {
typedef Window Owner;
typedef void ReturnType;
typedef void SetterType;
typedef mozilla::jni::Args<
mozilla::jni::Object::Param> Args;
static constexpr char name[] = "setState";
static constexpr char signature[] =
"(Lorg/mozilla/gecko/GeckoView$State;)V";
static const bool isStatic = false;
static const mozilla::jni::ExceptionMode exceptionMode =
mozilla::jni::ExceptionMode::ABORT;
static const mozilla::jni::CallingThread callingThread =
mozilla::jni::CallingThread::GECKO;
static const mozilla::jni::DispatchTarget dispatchTarget =
mozilla::jni::DispatchTarget::CURRENT;
};
auto SetState(mozilla::jni::Object::Param) const -> void;
static const mozilla::jni::CallingThread callingThread =
mozilla::jni::CallingThread::ANY;

Просмотреть файл

@ -242,7 +242,7 @@ class nsWindow::GeckoViewSupport final
, public SupportsWeakPtr<GeckoViewSupport>
{
nsWindow& window;
GeckoView::GlobalRef mView;
GeckoView::Window::GlobalRef mGeckoViewWindow;
public:
typedef GeckoView::Window::Natives<GeckoViewSupport> Base;
@ -265,10 +265,9 @@ public:
}
GeckoViewSupport(nsWindow* aWindow,
const GeckoView::Window::LocalRef& aInstance,
GeckoView::Param aView)
const GeckoView::Window::LocalRef& aInstance)
: window(*aWindow)
, mView(aView)
, mGeckoViewWindow(aInstance)
{
Base::AttachNative(aInstance, static_cast<SupportsWeakPtr*>(this));
}
@ -1252,7 +1251,7 @@ nsWindow::GeckoViewSupport::Open(const jni::Class::LocalRef& aCls,
// Attach a new GeckoView support object to the new window.
window->mGeckoViewSupport = mozilla::MakeUnique<GeckoViewSupport>(
window, GeckoView::Window::LocalRef(aCls.Env(), aWindow), aView);
window, (GeckoView::Window::LocalRef(aCls.Env(), aWindow)));
window->mGeckoViewSupport->mDOMWindow = pdomWindow;
@ -1297,6 +1296,7 @@ nsWindow::GeckoViewSupport::Close()
mDOMWindow->ForceClose();
mDOMWindow = nullptr;
mGeckoViewWindow = nullptr;
}
void
@ -2078,8 +2078,10 @@ nsWindow::GetEventTimeStamp(int64_t aEventTime)
void
nsWindow::GeckoViewSupport::EnableEventDispatcher()
{
MOZ_ASSERT(mView);
mView->SetState(GeckoView::State::READY());
if (!mGeckoViewWindow) {
return;
}
mGeckoViewWindow->SetState(GeckoView::State::READY());
}
void

Просмотреть файл

@ -148,6 +148,16 @@ nsDebugImpl::Abort(const char* aFile, int32_t aLine)
return NS_OK;
}
// From toolkit/library/rust/lib.rs
extern "C" void intentional_panic(const char* message);
NS_IMETHODIMP
nsDebugImpl::RustPanic(const char* aMessage)
{
intentional_panic(aMessage);
return NS_OK;
}
NS_IMETHODIMP
nsDebugImpl::GetIsDebugBuild(bool* aResult)
{

Просмотреть файл

@ -79,4 +79,11 @@ interface nsIDebug2 : nsISupports
*/
void abort(in string aFile,
in long aLine);
/**
* Request the process to trigger a fatal panic!() from Rust code.
*
* @param aMessage the string to pass to panic!().
*/
void rustPanic(in string aMessage);
};

Просмотреть файл

@ -19,6 +19,7 @@
#include "mozilla/Move.h"
#include "mozilla/ReverseIterator.h"
#include "mozilla/TypeTraits.h"
#include "mozilla/Span.h"
#include <string.h>
@ -1116,6 +1117,18 @@ public:
const_reverse_iterator rend() const { return const_reverse_iterator(begin()); }
const_reverse_iterator crend() const { return rend(); }
// Span integration
operator mozilla::Span<elem_type>()
{
return mozilla::Span<elem_type>(Elements(), Length());
}
operator mozilla::Span<const elem_type>() const
{
return mozilla::Span<const elem_type>(Elements(), Length());
}
//
// Search methods
//
@ -1340,6 +1353,16 @@ protected:
return ReplaceElementsAt<Item, ActualAlloc>(
aStart, aCount, aArray.Elements(), aArray.Length());
}
template<class Item, typename ActualAlloc = Alloc>
elem_type* ReplaceElementsAt(index_type aStart,
size_type aCount,
mozilla::Span<const Item> aSpan)
{
return ReplaceElementsAt<Item, ActualAlloc>(
aStart, aCount, aSpan.Elements(), aSpan.Length());
}
public:
template<class Item>
@ -1351,6 +1374,15 @@ public:
return ReplaceElementsAt<Item, FallibleAlloc>(aStart, aCount, aArray);
}
template<class Item>
MOZ_MUST_USE elem_type* ReplaceElementsAt(index_type aStart,
size_type aCount,
mozilla::Span<const Item> aSpan,
const mozilla::fallible_t&)
{
return ReplaceElementsAt<Item, FallibleAlloc>(aStart, aCount, aSpan);
}
// A variation on the ReplaceElementsAt method defined above.
protected:
template<class Item, typename ActualAlloc = Alloc>
@ -1403,6 +1435,15 @@ protected:
return ReplaceElementsAt<Item, ActualAlloc>(
aIndex, 0, aArray.Elements(), aArray.Length());
}
template<class Item, typename ActualAlloc = Alloc>
elem_type* InsertElementsAt(index_type aIndex,
mozilla::Span<const Item> aSpan)
{
return ReplaceElementsAt<Item, ActualAlloc>(
aIndex, 0, aSpan.Elements(), aSpan.Length());
}
public:
template<class Item, class Allocator>
@ -1414,6 +1455,14 @@ public:
return InsertElementsAt<Item, Allocator, FallibleAlloc>(aIndex, aArray);
}
template<class Item>
MOZ_MUST_USE elem_type* InsertElementsAt(index_type aIndex,
mozilla::Span<const Item> aSpan,
const mozilla::fallible_t&)
{
return InsertElementsAt<Item, FallibleAlloc>(aIndex, aSpan);
}
// Insert a new element without copy-constructing. This is useful to avoid
// temporaries.
// @return A pointer to the newly inserted element, or null on OOM.
@ -1548,6 +1597,13 @@ protected:
template<class Item, typename ActualAlloc = Alloc>
elem_type* AppendElements(const Item* aArray, size_type aArrayLen);
template<class Item, typename ActualAlloc = Alloc>
elem_type* AppendElements(mozilla::Span<const Item> aSpan)
{
return AppendElements<Item, FallibleAlloc>(aSpan.Elements(),
aSpan.Length());
}
template<class Item, size_t Length, typename ActualAlloc = Alloc>
elem_type* AppendElements(const mozilla::Array<Item, Length>& aArray)
{
@ -1564,6 +1620,15 @@ public:
return AppendElements<Item, FallibleAlloc>(aArray, aArrayLen);
}
template<class Item>
/* MOZ_MUST_USE */
elem_type* AppendElements(mozilla::Span<const Item> aSpan,
const mozilla::fallible_t&)
{
return AppendElements<Item, FallibleAlloc>(aSpan.Elements(),
aSpan.Length());
}
// A variation on the AppendElements method defined above.
protected:
template<class Item, class Allocator, typename ActualAlloc = Alloc>
@ -2397,6 +2462,25 @@ struct nsTArray_CopyChooser<AutoTArray<E, N>>
typedef nsTArray_CopyWithConstructors<AutoTArray<E, N>> Type;
};
// Span integration
namespace mozilla {
template<class ElementType, class TArrayAlloc>
Span<ElementType>
MakeSpan(nsTArray_Impl<ElementType, TArrayAlloc>& aTArray)
{
return aTArray;
}
template<class ElementType, class TArrayAlloc>
Span<const ElementType>
MakeSpan(const nsTArray_Impl<ElementType, TArrayAlloc>& aTArray)
{
return aTArray;
}
} // namespace mozilla
// Assert that AutoTArray doesn't have any extra padding inside.
//
// It's important that the data stored in this auto array takes up a multiple of

Просмотреть файл

@ -9,6 +9,8 @@
#include "mozilla/IntegerPrintfMacros.h"
#include "mozilla/UniquePtr.h"
#include "mozilla/MemoryReporting.h"
#include "mozilla/IntegerTypeTraits.h"
#include "mozilla/Span.h"
#ifndef MOZILLA_INTERNAL_API
#error "Using XPCOM strings is limited to code linked into libxul."
@ -922,6 +924,68 @@ public:
}
#endif
/**
* Span integration
*/
operator mozilla::Span<char_type>()
{
return mozilla::MakeSpan(BeginWriting(), Length());
}
operator mozilla::Span<const char_type>() const
{
return mozilla::MakeSpan(BeginReading(), Length());
}
void Append(mozilla::Span<const char_type> aSpan)
{
auto len = aSpan.Length();
MOZ_RELEASE_ASSERT(len <= mozilla::MaxValue<size_type>::value);
Append(aSpan.Elements(), len);
}
MOZ_MUST_USE bool Append(mozilla::Span<const char_type> aSpan,
const fallible_t& aFallible)
{
auto len = aSpan.Length();
if (len > mozilla::MaxValue<size_type>::value) {
return false;
}
return Append(aSpan.Elements(), len, aFallible);
}
#if !defined(CharT_is_PRUnichar)
operator mozilla::Span<uint8_t>()
{
return mozilla::MakeSpan(reinterpret_cast<uint8_t*>(BeginWriting()),
Length());
}
operator mozilla::Span<const uint8_t>() const
{
return mozilla::MakeSpan(reinterpret_cast<const uint8_t*>(BeginReading()),
Length());
}
void Append(mozilla::Span<const uint8_t> aSpan)
{
auto len = aSpan.Length();
MOZ_RELEASE_ASSERT(len <= mozilla::MaxValue<size_type>::value);
Append(reinterpret_cast<const char*>(aSpan.Elements()), len);
}
MOZ_MUST_USE bool Append(mozilla::Span<const uint8_t> aSpan,
const fallible_t& aFallible)
{
auto len = aSpan.Length();
if (len > mozilla::MaxValue<size_type>::value) {
return false;
}
return Append(
reinterpret_cast<const char*>(aSpan.Elements()), len, aFallible);
}
#endif
/**
* string data is never null, but can be marked void. if true, the
@ -1272,3 +1336,22 @@ public:
return mArray[index];
}
};
/**
* Span integration
*/
namespace mozilla {
inline Span<CharT>
MakeSpan(nsTSubstring_CharT& aString)
{
return aString;
}
inline Span<const CharT>
MakeSpan(const nsTSubstring_CharT& aString)
{
return aString;
}
} // namespace mozilla