Bug 1444119 - Remove XPCOM extensibility of XSLT functions. r=bz.

--HG--
extra : rebase_source : 7ee56e82624d401f62dccd1180ce07b531ae816e
This commit is contained in:
Peter Van der Beken 2018-02-27 19:08:46 +01:00
Родитель 34e1a9308b
Коммит edd705b1ca
20 изменённых файлов: 561 добавлений и 1189 удалений

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

@ -9,9 +9,6 @@ with Files("**"):
XPIDL_SOURCES += [
'txIEXSLTRegExFunctions.idl',
'txIFunctionEvaluationContext.idl',
'txINodeSet.idl',
'txIXPathObject.idl',
]
XPIDL_MODULE = 'content_xslt'

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

@ -17,5 +17,5 @@
[test_bug1135764.html]
support-files = file_bug1135764.xml file_bug1135764.xsl
[test_bug1436040.html]
[test_exslt_regex.html]
[test_exslt.html]
[test_parameter.html]

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

@ -0,0 +1,249 @@
<!DOCTYPE HTML>
<html>
<!--
Test EXSLT extensions
http://www.exslt.org/
-->
<head>
<title>Test for EXSLT extensions</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test">
<script type="application/javascript">
let tests = [
{
descr: "Testing common:node-set",
expr: "common:node-set($tree)",
useCopyOf: true,
expResult: "<abc>def</abc>",
},
{
descr: "Testing common:object-type(string)",
expr: "common:object-type($string)",
expResult: "string",
},
{
descr: "Testing common:object-type(number)",
expr: "common:object-type($number)",
expResult: "number",
},
{
descr: "Testing common:object-type(boolean)",
expr: "common:object-type($boolean)",
expResult: "boolean",
},
{
descr: "Testing common:object-type(node-set)",
expr: "common:object-type($node-set)",
expResult: "node-set",
},
{
descr: "Testing common:object-type(tree)",
expr: "common:object-type($tree)",
expResult: "RTF",
},
{
descr: "Testing math:max",
expr: "math:max(root/numbers/number)",
expResult: "11",
},
{
descr: "Testing math:min",
expr: "math:min(root/numbers/number)",
expResult: "4",
},
{
descr: "Testing math:highest",
expr: "math:highest(root/numbers/number)/@id",
expResult: "eleven",
},
{
descr: "Testing math:lowest",
expr: "math:lowest(root/numbers/number)/@id",
expResult: "four",
},
{
descr: "Testing regexp:test",
expr: "regexp:test('XSLT is great', 'XSLT', '')",
expResult: "true",
},
{
descr: "Testing regexp:match",
expr: "regexp:match('XSLT is great', 'XSL.', '')[1]",
expResult: "XSLT",
},
{
descr: "Testing regexp:replace",
expr: "regexp:replace('Food is great', 'Fo.d', '', 'XSLT')",
expResult: "XSLT is great",
},
{
descr: "Testing sets:difference",
expr: "sets:difference($i, $e)",
useCopyOf: true,
expResult: "<city name=\"Paris\" country=\"France\"></city><city name=\"Madrid\" country=\"Spain\"></city><city name=\"Calais\" country=\"France\"></city>",
},
{
descr: "Testing sets:distinct",
expr: "strings:concat(sets:distinct(//@country))",
expResult: "FranceSpainAustriaGermany",
},
{
descr: "Testing sets:hasSameNode",
expr: "sets:has-same-node($i, $e)",
expResult: "true",
},
{
descr: "Testing sets:hasSameNode",
expr: "sets:has-same-node($i, $o)",
expResult: "false",
},
{
descr: "Testing sets:intersection",
expr: "sets:intersection($i, $e)",
useCopyOf: true,
expResult: "<city name=\"Vienna\" country=\"Austria\"></city><city name=\"Berlin\" country=\"Germany\"></city>",
},
{
descr: "Testing sets:leading",
expr: "sets:leading($i, $e)",
useCopyOf: true,
expResult: "<city name=\"Paris\" country=\"France\"></city><city name=\"Madrid\" country=\"Spain\"></city>",
},
{
descr: "Testing sets:leading",
expr: "sets:leading($i, $o)",
useCopyOf: true,
expResult: "",
},
{
descr: "Testing sets:leading",
expr: "sets:leading($i, $empty)",
useCopyOf: true,
expResult: "<city name=\"Paris\" country=\"France\"></city><city name=\"Madrid\" country=\"Spain\"></city><city name=\"Vienna\" country=\"Austria\"></city><city name=\"Calais\" country=\"France\"></city><city name=\"Berlin\" country=\"Germany\"></city>",
},
{
descr: "Testing sets:trailing",
expr: "sets:trailing($i, $e)",
useCopyOf: true,
expResult: "<city name=\"Calais\" country=\"France\"></city><city name=\"Berlin\" country=\"Germany\"></city>",
},
{
descr: "Testing sets:trailing",
expr: "sets:trailing($i, $o)",
useCopyOf: true,
expResult: "",
},
{
descr: "Testing sets:trailing",
expr: "sets:trailing($i, $empty)",
useCopyOf: true,
expResult: "<city name=\"Paris\" country=\"France\"></city><city name=\"Madrid\" country=\"Spain\"></city><city name=\"Vienna\" country=\"Austria\"></city><city name=\"Calais\" country=\"France\"></city><city name=\"Berlin\" country=\"Germany\"></city>",
},
{
descr: "Testing strings:concat",
expr: "strings:concat(root/numbers/number/@id)",
expResult: "seveneleveneightfour",
},
{
descr: "Testing strings:split",
expr: "strings:split('a, simple, list', ', ')",
useCopyOf: true,
expResult: "<token>a</token><token>simple</token><token>list</token>",
},
{
descr: "Testing strings:split",
expr: "strings:split('date math str')",
useCopyOf: true,
expResult: "<token>date</token><token>math</token><token>str</token>",
},
{
descr: "Testing strings:split",
expr: "strings:split('foo', '')",
useCopyOf: true,
expResult: "<token>f</token><token>o</token><token>o</token>",
},
{
descr: "Testing strings:tokenize",
expr: "strings:tokenize('2001-06-03T11:40:23', '-T:')",
useCopyOf: true,
expResult: "<token>2001</token><token>06</token><token>03</token><token>11</token><token>40</token><token>23</token>",
},
{
descr: "Testing strings:tokenize",
expr: "strings:tokenize('date math str')",
useCopyOf: true,
expResult: "<token>date</token><token>math</token><token>str</token>",
},
{
descr: "Testing strings:tokenize",
expr: "strings:tokenize('foo', '')",
useCopyOf: true,
expResult: "<token>f</token><token>o</token><token>o</token>",
},
];
let style =
`<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
xmlns:common="http://exslt.org/common"
xmlns:math="http://exslt.org/math"
xmlns:regexp="http://exslt.org/regular-expressions"
xmlns:sets="http://exslt.org/sets"
xmlns:strings="http://exslt.org/strings">
<xsl:output method="html"/>
<xsl:variable name="tree"><abc>def</abc></xsl:variable>
<xsl:variable name="string" select="'abc'"/>
<xsl:variable name="number" select="123"/>
<xsl:variable name="boolean" select="true()"/>
<xsl:variable name="node-set" select="//*"/>
<xsl:variable name="i" select="/root/sets/city[contains(@name, 'i')]" />
<xsl:variable name="e" select="/root/sets/city[contains(@name, 'e')]" />
<xsl:variable name="o" select="/root/sets/city[contains(@name, 'o')]" />
<xsl:variable name="empty" select="/root/sets/city[contains(@name, 'x')]" />
<xsl:template match="/">
${tests.map(({expr, useCopyOf}, i) => `<div id="${i}"><xsl:${useCopyOf ? "copy-of" : "value-of"} select="${expr}"/></div>`).join("\n")}
</xsl:template>
</xsl:stylesheet>`;
let styleDoc = new DOMParser().parseFromString(style, "text/xml");
let data = `<root>
<numbers>
<number id="seven">7</number>
<number id="eleven">11</number>
<number id="eight">8</number>
<number id="four">4</number>
</numbers>
<sets>
<city name="Paris" country="France" />
<city name="Madrid" country="Spain" />
<city name="Vienna" country="Austria" />
<city name="Barcelona" country="Spain" />
<city name="Salzburg" country="Austria" />
<city name="Bonn" country="Germany" />
<city name="Lyon" country="France" />
<city name="Hannover" country="Germany" />
<city name="Calais" country="France" />
<city name="Berlin" country="Germany" />
</sets>
</root>`;
let originalDoc = new DOMParser().parseFromString(data, "text/xml");
let processor = new XSLTProcessor();
processor.importStylesheet(styleDoc);
let fragment = processor.transformToFragment(originalDoc, document);
tests.forEach(({descr, expResult}, i) => {
let result = fragment.getElementById(i);
is(result.innerHTML, expResult, descr);
});
</script>
</pre>
</body>
</html>

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

@ -1,60 +0,0 @@
<!DOCTYPE HTML>
<html>
<!--
Test EXSLT Regular Expression Extension
http://www.exslt.org/regexp/index.html
-->
<head>
<title>Test for EXSLT Regular Expression Extensions</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test">
<script type="application/javascript">
var tests = [
{ descr: "Testing regexp:test",
expr: "regexp:test('XSLT is great', 'XSLT', '')",
expResult: "true" },
{ descr: "Testing regexp:match",
expr: "regexp:match('XSLT is great', 'XSL.', '')[1]",
expResult: "XSLT" },
{ descr: "Testing regexp:replace",
expr: "regexp:replace('Food is great', 'Fo.d', '', 'XSLT')",
expResult: "XSLT is great" }
];
for (test of tests) {
var style =
'<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" ' +
'xmlns:regexp="http://exslt.org/regular-expressions" '+
'version="1.0">' +
'<xsl:output method="html"/>' +
'<xsl:template match="/">' +
'<xsl:value-of select="'+test.expr+'" /> ' +
'</xsl:template>' +
'</xsl:stylesheet>';
var styleDoc = new DOMParser().parseFromString (style, "text/xml");
var data = '<root/>';
var originalDoc = new DOMParser().parseFromString(data, "text/xml");
var processor = new XSLTProcessor();
processor.importStylesheet(styleDoc);
var fragment = processor.transformToFragment(originalDoc, document);
var content = document.getElementById("content");
content.appendChild(fragment);
is(content.innerHTML, test.expResult, test.descr);
content.innerHTML = '';
}
</script>
</pre>
</body>
</html>

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

@ -5,15 +5,17 @@
#include "nsISupports.idl"
interface txIFunctionEvaluationContext;
interface txINodeSet;
interface nsIDOMDocument;
interface nsIDOMDocumentFragment;
[scriptable, uuid(c180e993-aced-4839-95a0-ecd5ff138be9)]
interface txIEXSLTRegExFunctions : nsISupports
{
txINodeSet match(in txIFunctionEvaluationContext aContext,
in DOMString aString, in DOMString aRegEx,
in DOMString aFlags);
// Make this take Document and return DocumentFragment once https://bugzil.la/1444991
// is fixed.
nsIDOMDocumentFragment match(in DOMString aString, in DOMString aRegEx,
in DOMString aFlags,
in nsIDOMDocument aResultDocument);
DOMString replace(in DOMString aString, in DOMString aRegEx,
in DOMString aFlags, in DOMString aReplace);
boolean test(in DOMString aString, in DOMString aRegEx,

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

@ -1,18 +0,0 @@
/* -*- Mode: IDL; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* 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 "nsISupports.idl"
interface nsIDOMNode;
interface txINodeSet;
[scriptable, uuid(0ecbb00c-6a78-11d9-9791-000a95dc234c)]
interface txIFunctionEvaluationContext : nsISupports
{
readonly attribute uint32_t position;
readonly attribute uint32_t size;
readonly attribute nsIDOMNode contextNode;
readonly attribute nsISupports state;
};

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

@ -1,16 +0,0 @@
/* -*- Mode: IDL; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* 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 "domstubs.idl"
[scriptable, uuid(15d424c0-6b47-11d9-9791-000a95dc234c)]
interface txINodeSet : nsISupports
{
nsIDOMNode item(in unsigned long index);
double itemAsNumber(in unsigned long index);
DOMString itemAsString(in unsigned long index);
readonly attribute unsigned long length;
void add(in nsIDOMNode node);
};

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

@ -1,18 +0,0 @@
/* -*- Mode: IDL; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* 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 "nsISupports.idl"
%{ C++
class txAExprResult;
%}
[ptr] native txAExprResultPtr(txAExprResult);
[scriptable, uuid(67706346-dece-4c9b-9fc2-57cf19071014)]
interface txIXPathObject : nsISupports
{
[noscript, notxpcom] txAExprResultPtr getResult();
};

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

@ -27,7 +27,6 @@ UNIFIED_SOURCES += [
'txNamedAttributeStep.cpp',
'txNameTest.cpp',
'txNodeSet.cpp',
'txNodeSetAdaptor.cpp',
'txNodeSetContext.cpp',
'txNodeTypeTest.cpp',
'txNumberExpr.cpp',
@ -44,7 +43,6 @@ UNIFIED_SOURCES += [
'txUnionNodeTest.cpp',
'txVariableRefExpr.cpp',
'txXPathOptimizer.cpp',
'txXPCOMExtensionFunction.cpp',
'XPathEvaluator.cpp',
'XPathExpression.cpp',
'XPathResult.cpp',

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

@ -1,88 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* 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 "txNodeSetAdaptor.h"
#include "txXPathTreeWalker.h"
txNodeSetAdaptor::txNodeSetAdaptor()
: txXPathObjectAdaptor(),
mWritable(true)
{
}
txNodeSetAdaptor::txNodeSetAdaptor(txNodeSet *aNodeSet)
: txXPathObjectAdaptor(aNodeSet),
mWritable(false)
{
}
NS_IMPL_ISUPPORTS_INHERITED(txNodeSetAdaptor, txXPathObjectAdaptor, txINodeSet)
nsresult
txNodeSetAdaptor::Init()
{
if (!mValue) {
mValue = new txNodeSet(nullptr);
}
return NS_OK;
}
NS_IMETHODIMP
txNodeSetAdaptor::Item(uint32_t aIndex, nsIDOMNode **aResult)
{
*aResult = nullptr;
if (aIndex > (uint32_t)NodeSet()->size()) {
return NS_ERROR_ILLEGAL_VALUE;
}
return txXPathNativeNode::getNode(NodeSet()->get(aIndex), aResult);
}
NS_IMETHODIMP
txNodeSetAdaptor::ItemAsNumber(uint32_t aIndex, double *aResult)
{
if (aIndex > (uint32_t)NodeSet()->size()) {
return NS_ERROR_ILLEGAL_VALUE;
}
nsAutoString result;
txXPathNodeUtils::appendNodeValue(NodeSet()->get(aIndex), result);
*aResult = txDouble::toDouble(result);
return NS_OK;
}
NS_IMETHODIMP
txNodeSetAdaptor::ItemAsString(uint32_t aIndex, nsAString &aResult)
{
if (aIndex > (uint32_t)NodeSet()->size()) {
return NS_ERROR_ILLEGAL_VALUE;
}
txXPathNodeUtils::appendNodeValue(NodeSet()->get(aIndex), aResult);
return NS_OK;
}
NS_IMETHODIMP
txNodeSetAdaptor::GetLength(uint32_t *aLength)
{
*aLength = (uint32_t)NodeSet()->size();
return NS_OK;
}
NS_IMETHODIMP
txNodeSetAdaptor::Add(nsIDOMNode *aNode)
{
NS_ENSURE_TRUE(mWritable, NS_ERROR_FAILURE);
nsAutoPtr<txXPathNode> node(txXPathNativeNode::createXPathNode(aNode,
true));
return node ? NodeSet()->add(*node) : NS_ERROR_OUT_OF_MEMORY;
}

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

@ -1,41 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* 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 txNodeSetAdaptor_h__
#define txNodeSetAdaptor_h__
#include "txINodeSet.h"
#include "txNodeSet.h"
#include "txXPathObjectAdaptor.h"
/**
* Implements an XPCOM wrapper around an XPath NodeSet.
*/
class txNodeSetAdaptor : public txXPathObjectAdaptor,
public txINodeSet
{
public:
txNodeSetAdaptor();
explicit txNodeSetAdaptor(txNodeSet* aNodeSet);
nsresult Init();
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_TXINODESET
protected:
~txNodeSetAdaptor() {}
private:
txNodeSet* NodeSet()
{
return static_cast<txNodeSet*>(mValue.get());
}
bool mWritable;
};
#endif // txNodeSetAdaptor_h__

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

@ -1,618 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* 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 "nsAutoPtr.h"
#include "nsComponentManagerUtils.h"
#include "nsDependentString.h"
#include "nsAtom.h"
#include "nsIInterfaceInfoManager.h"
#include "nsMemory.h"
#include "nsServiceManagerUtils.h"
#include "txExpr.h"
#include "txIFunctionEvaluationContext.h"
#include "txIXPathContext.h"
#include "txNodeSetAdaptor.h"
#include "txXPathTreeWalker.h"
#include "xptcall.h"
#include "txXPathObjectAdaptor.h"
#include "mozilla/Attributes.h"
#include "mozilla/UniquePtr.h"
#include "mozilla/dom/ScriptSettings.h"
#include "nsIClassInfo.h"
#include "nsIInterfaceInfo.h"
#include "js/RootingAPI.h"
NS_IMPL_ISUPPORTS(txXPathObjectAdaptor, txIXPathObject)
class txFunctionEvaluationContext final : public txIFunctionEvaluationContext
{
public:
txFunctionEvaluationContext(txIEvalContext *aContext, nsISupports *aState);
NS_DECL_ISUPPORTS
NS_DECL_TXIFUNCTIONEVALUATIONCONTEXT
void ClearContext()
{
mContext = nullptr;
}
private:
~txFunctionEvaluationContext() {}
txIEvalContext *mContext;
nsCOMPtr<nsISupports> mState;
};
txFunctionEvaluationContext::txFunctionEvaluationContext(txIEvalContext *aContext,
nsISupports *aState)
: mContext(aContext),
mState(aState)
{
}
NS_IMPL_ISUPPORTS(txFunctionEvaluationContext, txIFunctionEvaluationContext)
NS_IMETHODIMP
txFunctionEvaluationContext::GetPosition(uint32_t *aPosition)
{
NS_ENSURE_TRUE(mContext, NS_ERROR_FAILURE);
*aPosition = mContext->position();
return NS_OK;
}
NS_IMETHODIMP
txFunctionEvaluationContext::GetSize(uint32_t *aSize)
{
NS_ENSURE_TRUE(mContext, NS_ERROR_FAILURE);
*aSize = mContext->size();
return NS_OK;
}
NS_IMETHODIMP
txFunctionEvaluationContext::GetContextNode(nsIDOMNode **aNode)
{
NS_ENSURE_TRUE(mContext, NS_ERROR_FAILURE);
return txXPathNativeNode::getNode(mContext->getContextNode(), aNode);
}
NS_IMETHODIMP
txFunctionEvaluationContext::GetState(nsISupports **aState)
{
NS_IF_ADDREF(*aState = mState);
return NS_OK;
}
enum txArgumentType {
eBOOLEAN = nsXPTType::T_BOOL,
eNUMBER = nsXPTType::T_DOUBLE,
eSTRING = nsXPTType::T_DOMSTRING,
eNODESET,
eCONTEXT,
eOBJECT,
eUNKNOWN
};
class txXPCOMExtensionFunctionCall : public FunctionCall
{
public:
txXPCOMExtensionFunctionCall(nsISupports *aHelper, const nsIID &aIID,
uint16_t aMethodIndex,
#ifdef TX_TO_STRING
nsAtom *aName,
#endif
nsISupports *aState);
TX_DECL_FUNCTION
private:
txArgumentType GetParamType(const nsXPTParamInfo &aParam,
nsIInterfaceInfo *aInfo);
nsCOMPtr<nsISupports> mHelper;
nsIID mIID;
uint16_t mMethodIndex;
#ifdef TX_TO_STRING
RefPtr<nsAtom> mName;
#endif
nsCOMPtr<nsISupports> mState;
};
txXPCOMExtensionFunctionCall::txXPCOMExtensionFunctionCall(nsISupports *aHelper,
const nsIID &aIID,
uint16_t aMethodIndex,
#ifdef TX_TO_STRING
nsAtom *aName,
#endif
nsISupports *aState)
: mHelper(aHelper),
mIID(aIID),
mMethodIndex(aMethodIndex),
#ifdef TX_TO_STRING
mName(aName),
#endif
mState(aState)
{
}
class txInterfacesArrayHolder
{
public:
txInterfacesArrayHolder(nsIID **aArray, uint32_t aCount) : mArray(aArray),
mCount(aCount)
{
}
~txInterfacesArrayHolder()
{
NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(mCount, mArray);
}
private:
nsIID **mArray;
uint32_t mCount;
};
static nsresult
LookupFunction(const char *aContractID, nsAtom* aName, nsIID &aIID,
uint16_t &aMethodIndex, nsISupports **aHelper)
{
nsresult rv;
nsCOMPtr<nsISupports> helper = do_GetService(aContractID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIClassInfo> classInfo = do_QueryInterface(helper, &rv);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIInterfaceInfoManager> iim =
do_GetService(NS_INTERFACEINFOMANAGER_SERVICE_CONTRACTID);
NS_ENSURE_TRUE(iim, NS_ERROR_FAILURE);
nsIID** iidArray = nullptr;
uint32_t iidCount = 0;
rv = classInfo->GetInterfaces(&iidCount, &iidArray);
NS_ENSURE_SUCCESS(rv, rv);
txInterfacesArrayHolder holder(iidArray, iidCount);
// Remove any minus signs and uppercase the following letter (so
// foo-bar becomes fooBar). Note that if there are any names that already
// have uppercase letters they might cause false matches (both fooBar and
// foo-bar matching fooBar).
const char16_t *name = aName->GetUTF16String();
nsAutoCString methodName;
char16_t letter;
bool upperNext = false;
while ((letter = *name)) {
if (letter == '-') {
upperNext = true;
}
else {
MOZ_ASSERT(nsCRT::IsAscii(letter),
"invalid static_cast coming up");
methodName.Append(upperNext ?
nsCRT::ToUpper(static_cast<char>(letter)) :
letter);
upperNext = false;
}
++name;
}
uint32_t i;
for (i = 0; i < iidCount; ++i) {
nsIID *iid = iidArray[i];
nsCOMPtr<nsIInterfaceInfo> info;
rv = iim->GetInfoForIID(iid, getter_AddRefs(info));
NS_ENSURE_SUCCESS(rv, rv);
uint16_t methodIndex;
const nsXPTMethodInfo *methodInfo;
rv = info->GetMethodInfoForName(methodName.get(), &methodIndex,
&methodInfo);
if (NS_SUCCEEDED(rv)) {
// Exclude notxpcom and hidden. Also check that we have at least a
// return value (the xpidl compiler ensures that that return value
// is the last argument).
uint8_t paramCount = methodInfo->GetParamCount();
if (methodInfo->IsNotXPCOM() || methodInfo->IsHidden() ||
paramCount == 0 ||
!methodInfo->GetParam(paramCount - 1).IsRetval()) {
return NS_ERROR_FAILURE;
}
aIID = *iid;
aMethodIndex = methodIndex;
return helper->QueryInterface(aIID, (void**)aHelper);
}
}
return NS_ERROR_XPATH_UNKNOWN_FUNCTION;
}
/* static */
nsresult
TX_ResolveFunctionCallXPCOM(const nsCString &aContractID, int32_t aNamespaceID,
nsAtom* aName, nsISupports *aState,
FunctionCall **aFunction)
{
nsIID iid;
uint16_t methodIndex = 0;
nsCOMPtr<nsISupports> helper;
nsresult rv = LookupFunction(aContractID.get(), aName, iid, methodIndex,
getter_AddRefs(helper));
NS_ENSURE_SUCCESS(rv, rv);
if (!aFunction) {
return NS_OK;
}
*aFunction = new txXPCOMExtensionFunctionCall(helper, iid, methodIndex,
#ifdef TX_TO_STRING
aName,
#endif
aState);
return NS_OK;
}
txArgumentType
txXPCOMExtensionFunctionCall::GetParamType(const nsXPTParamInfo &aParam,
nsIInterfaceInfo *aInfo)
{
uint8_t tag = aParam.GetType().TagPart();
switch (tag) {
case nsXPTType::T_BOOL:
case nsXPTType::T_DOUBLE:
case nsXPTType::T_DOMSTRING:
{
return txArgumentType(tag);
}
case nsXPTType::T_INTERFACE:
case nsXPTType::T_INTERFACE_IS:
{
nsIID iid;
aInfo->GetIIDForParamNoAlloc(mMethodIndex, &aParam, &iid);
if (iid.Equals(NS_GET_IID(txINodeSet))) {
return eNODESET;
}
if (iid.Equals(NS_GET_IID(txIFunctionEvaluationContext))) {
return eCONTEXT;
}
if (iid.Equals(NS_GET_IID(txIXPathObject))) {
return eOBJECT;
}
return eUNKNOWN;
}
default:
{
// XXX Error!
return eUNKNOWN;
}
}
}
class txParamArrayHolder
{
public:
txParamArrayHolder()
: mCount(0)
{
}
txParamArrayHolder(txParamArrayHolder&& rhs)
: mArray(mozilla::Move(rhs.mArray))
, mCount(rhs.mCount)
{
rhs.mCount = 0;
}
~txParamArrayHolder();
bool Init(uint8_t aCount);
operator nsXPTCVariant*() const
{
return mArray.get();
}
void trace(JSTracer* trc) {
for (uint8_t i = 0; i < mCount; ++i) {
if (mArray[i].type == nsXPTType::T_JSVAL) {
JS::UnsafeTraceRoot(trc, &mArray[i].val.j.asValueRef(), "txParam value");
}
}
}
private:
mozilla::UniquePtr<nsXPTCVariant[]> mArray;
uint8_t mCount;
};
txParamArrayHolder::~txParamArrayHolder()
{
uint8_t i;
for (i = 0; i < mCount; ++i) {
nsXPTCVariant &variant = mArray[i];
if (variant.DoesValNeedCleanup()) {
if (variant.type.TagPart() == nsXPTType::T_DOMSTRING)
delete (nsAString*)variant.val.p;
else {
MOZ_ASSERT(variant.type.TagPart() == nsXPTType::T_INTERFACE ||
variant.type.TagPart() == nsXPTType::T_INTERFACE_IS,
"We only support cleanup of strings and interfaces "
"here, and this looks like neither!");
if (variant.val.p != nullptr) {
static_cast<nsISupports*>(variant.val.p)->Release();
}
}
}
}
}
bool
txParamArrayHolder::Init(uint8_t aCount)
{
mCount = aCount;
mArray = mozilla::MakeUnique<nsXPTCVariant[]>(mCount);
if (!mArray) {
return false;
}
memset(mArray.get(), 0, mCount * sizeof(nsXPTCVariant));
return true;
}
nsresult
txXPCOMExtensionFunctionCall::evaluate(txIEvalContext* aContext,
txAExprResult** aResult)
{
nsCOMPtr<nsIInterfaceInfoManager> iim =
do_GetService(NS_INTERFACEINFOMANAGER_SERVICE_CONTRACTID);
NS_ENSURE_TRUE(iim, NS_ERROR_FAILURE);
nsCOMPtr<nsIInterfaceInfo> info;
nsresult rv = iim->GetInfoForIID(&mIID, getter_AddRefs(info));
NS_ENSURE_SUCCESS(rv, rv);
const nsXPTMethodInfo *methodInfo;
rv = info->GetMethodInfo(mMethodIndex, &methodInfo);
NS_ENSURE_SUCCESS(rv, rv);
uint8_t paramCount = methodInfo->GetParamCount();
uint8_t inArgs = paramCount - 1;
JS::Rooted<txParamArrayHolder> invokeParams(mozilla::dom::RootingCx());
if (!invokeParams.get().Init(paramCount)) {
return NS_ERROR_OUT_OF_MEMORY;
}
const nsXPTParamInfo &paramInfo = methodInfo->GetParam(0);
txArgumentType type = GetParamType(paramInfo, info);
if (type == eUNKNOWN) {
return NS_ERROR_FAILURE;
}
txFunctionEvaluationContext *context;
uint32_t paramStart = 0;
if (type == eCONTEXT) {
if (paramInfo.IsOut()) {
// We don't support out values.
return NS_ERROR_FAILURE;
}
// Create context wrapper.
context = new txFunctionEvaluationContext(aContext, mState);
nsXPTCVariant &invokeParam = invokeParams.get()[0];
invokeParam.type = paramInfo.GetType();
invokeParam.SetValNeedsCleanup();
NS_ADDREF((txIFunctionEvaluationContext*&)invokeParam.val.p = context);
// Skip first argument, since it's the context.
paramStart = 1;
}
else {
context = nullptr;
}
// XXX varargs
if (!requireParams(inArgs - paramStart, inArgs - paramStart, aContext)) {
return NS_ERROR_FAILURE;
}
uint32_t i;
for (i = paramStart; i < inArgs; ++i) {
Expr* expr = mParams[i - paramStart];
const nsXPTParamInfo &paramInfo = methodInfo->GetParam(i);
txArgumentType type = GetParamType(paramInfo, info);
if (type == eUNKNOWN) {
return NS_ERROR_FAILURE;
}
nsXPTCVariant &invokeParam = invokeParams.get()[i];
if (paramInfo.IsOut()) {
// We don't support out values.
return NS_ERROR_FAILURE;
}
invokeParam.type = paramInfo.GetType();
switch (type) {
case eNODESET:
{
RefPtr<txNodeSet> nodes;
rv = evaluateToNodeSet(expr, aContext, getter_AddRefs(nodes));
NS_ENSURE_SUCCESS(rv, rv);
txNodeSetAdaptor *adaptor = new txNodeSetAdaptor(nodes);
if (!adaptor) {
return NS_ERROR_OUT_OF_MEMORY;
}
nsCOMPtr<txINodeSet> nodeSet = adaptor;
rv = adaptor->Init();
NS_ENSURE_SUCCESS(rv, rv);
invokeParam.SetValNeedsCleanup();
nodeSet.swap((txINodeSet*&)invokeParam.val.p);
break;
}
case eBOOLEAN:
{
rv = expr->evaluateToBool(aContext, invokeParam.val.b);
NS_ENSURE_SUCCESS(rv, rv);
break;
}
case eNUMBER:
{
double dbl;
rv = evaluateToNumber(mParams[0], aContext, &dbl);
NS_ENSURE_SUCCESS(rv, rv);
invokeParam.val.d = dbl;
break;
}
case eSTRING:
{
nsString *value = new nsString();
if (!value) {
return NS_ERROR_OUT_OF_MEMORY;
}
rv = expr->evaluateToString(aContext, *value);
NS_ENSURE_SUCCESS(rv, rv);
invokeParam.SetValNeedsCleanup();
invokeParam.val.p = value;
break;
}
case eOBJECT:
{
RefPtr<txAExprResult> exprRes;
rv = expr->evaluate(aContext, getter_AddRefs(exprRes));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<txIXPathObject> adaptor =
new txXPathObjectAdaptor(exprRes);
if (!adaptor) {
return NS_ERROR_OUT_OF_MEMORY;
}
invokeParam.SetValNeedsCleanup();
adaptor.swap((txIXPathObject*&)invokeParam.val.p);
break;
}
case eCONTEXT:
case eUNKNOWN:
{
// We only support passing the context as the *first* argument.
return NS_ERROR_FAILURE;
}
}
}
const nsXPTParamInfo &returnInfo = methodInfo->GetParam(inArgs);
txArgumentType returnType = GetParamType(returnInfo, info);
if (returnType == eUNKNOWN) {
return NS_ERROR_FAILURE;
}
nsXPTCVariant &returnParam = invokeParams.get()[inArgs];
returnParam.type = returnInfo.GetType();
if (returnType == eSTRING) {
nsString *value = new nsString();
returnParam.SetValNeedsCleanup();
returnParam.val.p = value;
}
else {
returnParam.SetIndirect();
if (returnType == eNODESET || returnType == eOBJECT) {
returnParam.SetValNeedsCleanup();
}
}
rv = NS_InvokeByIndex(mHelper, mMethodIndex, paramCount, invokeParams.get());
// In case someone is holding on to the txFunctionEvaluationContext which
// could thus stay alive longer than this function.
if (context) {
context->ClearContext();
}
NS_ENSURE_SUCCESS(rv, rv);
switch (returnType) {
case eNODESET:
{
txINodeSet* nodeSet = static_cast<txINodeSet*>(returnParam.val.p);
nsCOMPtr<txIXPathObject> object = do_QueryInterface(nodeSet, &rv);
NS_ENSURE_SUCCESS(rv, rv);
NS_ADDREF(*aResult = object->GetResult());
return NS_OK;
}
case eBOOLEAN:
{
aContext->recycler()->getBoolResult(returnParam.val.b, aResult);
return NS_OK;
}
case eNUMBER:
{
return aContext->recycler()->getNumberResult(returnParam.val.d,
aResult);
}
case eSTRING:
{
nsString *returned = static_cast<nsString*>
(returnParam.val.p);
return aContext->recycler()->getStringResult(*returned, aResult);
}
case eOBJECT:
{
txIXPathObject *object =
static_cast<txIXPathObject*>(returnParam.val.p);
NS_ADDREF(*aResult = object->GetResult());
return NS_OK;
}
default:
{
// Huh?
return NS_ERROR_FAILURE;
}
}
}
Expr::ResultType
txXPCOMExtensionFunctionCall::getReturnType()
{
// It doesn't really matter what we return here, but it might
// be a good idea to try to keep this as unoptimizable as possible
return ANY_RESULT;
}
bool
txXPCOMExtensionFunctionCall::isSensitiveTo(ContextSensitivity aContext)
{
// It doesn't really matter what we return here, but it might
// be a good idea to try to keep this as unoptimizable as possible
return true;
}
#ifdef TX_TO_STRING
void
txXPCOMExtensionFunctionCall::appendName(nsAString& aDest)
{
aDest.Append(mName->GetUTF16String());
}
#endif

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

@ -1,45 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* 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 txXPathObjectAdaptor_h__
#define txXPathObjectAdaptor_h__
#include "txExprResult.h"
#include "txINodeSet.h"
#include "txIXPathObject.h"
/**
* Implements an XPCOM wrapper around XPath data types boolean, number, string,
* or nodeset.
*/
class txXPathObjectAdaptor : public txIXPathObject
{
public:
explicit txXPathObjectAdaptor(txAExprResult* aValue) : mValue(aValue)
{
NS_ASSERTION(aValue,
"Don't create a txXPathObjectAdaptor if you don't have a "
"txAExprResult");
}
NS_DECL_ISUPPORTS
NS_IMETHOD_(txAExprResult*) GetResult() override
{
return mValue;
}
protected:
txXPathObjectAdaptor() : mValue(nullptr)
{
}
virtual ~txXPathObjectAdaptor() {}
RefPtr<txAExprResult> mValue;
};
#endif // txXPathObjectAdaptor_h__

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

@ -4,7 +4,11 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/ArrayUtils.h"
#include "mozilla/EnumeratedArray.h"
#include "mozilla/EnumeratedRange.h"
#include "mozilla/FloatingPoint.h"
#include "mozilla/MacroArgs.h"
#include "mozilla/MacroForEach.h"
#include "nsAtom.h"
#include "nsGkAtoms.h"
@ -25,6 +29,7 @@
#include "nsTextNode.h"
#include "mozilla/dom/DocumentFragment.h"
#include "prtime.h"
#include "txIEXSLTRegExFunctions.h"
using namespace mozilla;
using namespace mozilla::dom;
@ -35,20 +40,29 @@ class txStylesheetCompilerState;
// Utility functions
// ------------------------------------------------------------------
static nsresult
convertRtfToNode(txIEvalContext *aContext, txResultTreeFragment *aRtf)
static nsIDocument*
getSourceDocument(txIEvalContext *aContext)
{
txExecutionState* es =
static_cast<txExecutionState*>(aContext->getPrivateContext());
if (!es) {
NS_ERROR("Need txExecutionState!");
return NS_ERROR_UNEXPECTED;
return nullptr;
}
const txXPathNode& document = es->getSourceDocument();
return txXPathNativeNode::getDocument(document);
}
static nsresult
convertRtfToNode(txIEvalContext *aContext, txResultTreeFragment *aRtf)
{
nsIDocument *doc = getSourceDocument(aContext);
if (!doc) {
return NS_ERROR_UNEXPECTED;
}
nsIDocument *doc = txXPathNativeNode::getDocument(document);
nsCOMPtr<nsIDOMDocumentFragment> domFragment =
new DocumentFragment(doc->NodeInfoManager());
@ -75,17 +89,11 @@ static nsresult
createTextNode(txIEvalContext *aContext, nsString& aValue,
txXPathNode* *aResult)
{
txExecutionState* es =
static_cast<txExecutionState*>(aContext->getPrivateContext());
if (!es) {
NS_ERROR("Need txExecutionState!");
nsIDocument *doc = getSourceDocument(aContext);
if (!doc) {
return NS_ERROR_UNEXPECTED;
}
const txXPathNode& document = es->getSourceDocument();
nsIDocument *doc = txXPathNativeNode::getDocument(document);
RefPtr<nsTextNode> text = new nsTextNode(doc->NodeInfoManager());
nsresult rv = text->SetText(aValue, false);
@ -99,25 +107,6 @@ createTextNode(txIEvalContext *aContext, nsString& aValue,
return NS_OK;
}
static already_AddRefed<DocumentFragment>
createDocFragment(txIEvalContext *aContext)
{
txExecutionState* es =
static_cast<txExecutionState*>(aContext->getPrivateContext());
if (!es) {
NS_ERROR("Need txExecutionState!");
return nullptr;
}
const txXPathNode& document = es->getSourceDocument();
nsIDocument *doc = txXPathNativeNode::getDocument(document);
RefPtr<DocumentFragment> fragment =
new DocumentFragment(doc->NodeInfoManager());
return fragment.forget();
}
static nsresult
createAndAddToResult(nsAtom* aName, const nsAString& aValue,
txNodeSet* aResultSet, nsIContent* aResultHolder)
@ -165,79 +154,97 @@ static const char * const sTypes[] = {
// Function implementations
// ------------------------------------------------------------------
enum class txEXSLTType {
// http://exslt.org/common
NODE_SET,
OBJECT_TYPE,
// http://exslt.org/dates-and-times
DATE_TIME,
// http://exslt.org/math
MAX,
MIN,
HIGHEST,
LOWEST,
// http://exslt.org/regular-expressions
MATCH,
REPLACE,
TEST,
// http://exslt.org/sets
DIFFERENCE,
DISTINCT,
HAS_SAME_NODE,
INTERSECTION,
LEADING,
TRAILING,
// http://exslt.org/strings
CONCAT,
SPLIT,
TOKENIZE,
_LIMIT,
};
struct txEXSLTFunctionDescriptor
{
int8_t mMinParams;
int8_t mMaxParams;
Expr::ResultType mReturnType;
nsStaticAtom* mName;
bool (*mCreator)(txEXSLTType, FunctionCall**);
int32_t mNamespaceID;
nsStaticAtom** mName;
const char* mNamespaceURI;
};
static const char kEXSLTCommonNS[] = "http://exslt.org/common";
static const char kEXSLTSetsNS[] = "http://exslt.org/sets";
static const char kEXSLTStringsNS[] = "http://exslt.org/strings";
static const char kEXSLTMathNS[] = "http://exslt.org/math";
static const char kEXSLTDatesAndTimesNS[] = "http://exslt.org/dates-and-times";
// The order of this table must be the same as the
// txEXSLTFunctionCall::eType enum
static txEXSLTFunctionDescriptor descriptTable[] =
{
{ 1, 1, Expr::NODESET_RESULT, 0, &nsGkAtoms::nodeSet, kEXSLTCommonNS }, // NODE_SET
{ 1, 1, Expr::STRING_RESULT, 0, &nsGkAtoms::objectType, kEXSLTCommonNS }, // OBJECT_TYPE
{ 2, 2, Expr::NODESET_RESULT, 0, &nsGkAtoms::difference, kEXSLTSetsNS }, // DIFFERENCE
{ 1, 1, Expr::NODESET_RESULT, 0, &nsGkAtoms::distinct, kEXSLTSetsNS }, // DISTINCT
{ 2, 2, Expr::BOOLEAN_RESULT, 0, &nsGkAtoms::hasSameNode, kEXSLTSetsNS }, // HAS_SAME_NODE
{ 2, 2, Expr::NODESET_RESULT, 0, &nsGkAtoms::intersection, kEXSLTSetsNS }, // INTERSECTION
{ 2, 2, Expr::NODESET_RESULT, 0, &nsGkAtoms::leading, kEXSLTSetsNS }, // LEADING
{ 2, 2, Expr::NODESET_RESULT, 0, &nsGkAtoms::trailing, kEXSLTSetsNS }, // TRAILING
{ 1, 1, Expr::STRING_RESULT, 0, &nsGkAtoms::concat, kEXSLTStringsNS }, // CONCAT
{ 1, 2, Expr::STRING_RESULT, 0, &nsGkAtoms::split, kEXSLTStringsNS }, // SPLIT
{ 1, 2, Expr::STRING_RESULT, 0, &nsGkAtoms::tokenize, kEXSLTStringsNS }, // TOKENIZE
{ 1, 1, Expr::NUMBER_RESULT, 0, &nsGkAtoms::max, kEXSLTMathNS }, // MAX
{ 1, 1, Expr::NUMBER_RESULT, 0, &nsGkAtoms::min, kEXSLTMathNS }, // MIN
{ 1, 1, Expr::NODESET_RESULT, 0, &nsGkAtoms::highest, kEXSLTMathNS }, // HIGHEST
{ 1, 1, Expr::NODESET_RESULT, 0, &nsGkAtoms::lowest, kEXSLTMathNS }, // LOWEST
{ 0, 0, Expr::STRING_RESULT, 0, &nsGkAtoms::dateTime, kEXSLTDatesAndTimesNS }, // DATE_TIME
};
static EnumeratedArray<txEXSLTType, txEXSLTType::_LIMIT, txEXSLTFunctionDescriptor>
descriptTable;
class txEXSLTFunctionCall : public FunctionCall
{
public:
// The order of this enum must be the same as the descriptTable
// table above
enum eType {
// Set functions
NODE_SET,
OBJECT_TYPE,
DIFFERENCE,
DISTINCT,
HAS_SAME_NODE,
INTERSECTION,
LEADING,
TRAILING,
CONCAT,
SPLIT,
TOKENIZE,
MAX,
MIN,
HIGHEST,
LOWEST,
DATE_TIME
};
explicit txEXSLTFunctionCall(eType aType)
explicit txEXSLTFunctionCall(txEXSLTType aType)
: mType(aType)
{}
static bool Create(txEXSLTType aType, FunctionCall** aFunction)
{
*aFunction = new txEXSLTFunctionCall(aType);
return true;
}
TX_DECL_FUNCTION
private:
eType mType;
txEXSLTType mType;
};
class txEXSLTRegExFunctionCall : public FunctionCall
{
public:
txEXSLTRegExFunctionCall(txEXSLTType aType, txIEXSLTRegExFunctions* aRegExService)
: mType(aType)
, mRegExService(aRegExService)
{}
static bool Create(txEXSLTType aType, FunctionCall** aFunction)
{
nsCOMPtr<txIEXSLTRegExFunctions> regExService =
do_GetService("@mozilla.org/exslt/regexp;1");
if (!regExService) {
return false;
}
*aFunction = new txEXSLTRegExFunctionCall(aType, regExService);
return true;
}
TX_DECL_FUNCTION
private:
txEXSLTType mType;
nsCOMPtr<txIEXSLTRegExFunctions> mRegExService;
};
nsresult
@ -253,7 +260,7 @@ txEXSLTFunctionCall::evaluate(txIEvalContext *aContext,
nsresult rv = NS_OK;
switch (mType) {
case NODE_SET:
case txEXSLTType::NODE_SET:
{
RefPtr<txAExprResult> exprResult;
rv = mParams[0]->evaluate(aContext, getter_AddRefs(exprResult));
@ -301,7 +308,7 @@ txEXSLTFunctionCall::evaluate(txIEvalContext *aContext,
return NS_OK;
}
case OBJECT_TYPE:
case txEXSLTType::OBJECT_TYPE:
{
RefPtr<txAExprResult> exprResult;
nsresult rv = mParams[0]->evaluate(aContext,
@ -319,8 +326,8 @@ txEXSLTFunctionCall::evaluate(txIEvalContext *aContext,
return NS_OK;
}
case DIFFERENCE:
case INTERSECTION:
case txEXSLTType::DIFFERENCE:
case txEXSLTType::INTERSECTION:
{
RefPtr<txNodeSet> nodes1;
rv = evaluateToNodeSet(mParams[0], aContext,
@ -336,7 +343,7 @@ txEXSLTFunctionCall::evaluate(txIEvalContext *aContext,
rv = aContext->recycler()->getNodeSet(getter_AddRefs(resultSet));
NS_ENSURE_SUCCESS(rv, rv);
bool insertOnFound = mType == INTERSECTION;
bool insertOnFound = mType == txEXSLTType::INTERSECTION;
int32_t searchPos = 0;
int32_t i, len = nodes1->size();
@ -357,7 +364,7 @@ txEXSLTFunctionCall::evaluate(txIEvalContext *aContext,
return NS_OK;
}
case DISTINCT:
case txEXSLTType::DISTINCT:
{
RefPtr<txNodeSet> nodes;
rv = evaluateToNodeSet(mParams[0], aContext,
@ -386,7 +393,7 @@ txEXSLTFunctionCall::evaluate(txIEvalContext *aContext,
return NS_OK;
}
case HAS_SAME_NODE:
case txEXSLTType::HAS_SAME_NODE:
{
RefPtr<txNodeSet> nodes1;
rv = evaluateToNodeSet(mParams[0], aContext,
@ -411,8 +418,8 @@ txEXSLTFunctionCall::evaluate(txIEvalContext *aContext,
return NS_OK;
}
case LEADING:
case TRAILING:
case txEXSLTType::LEADING:
case txEXSLTType::TRAILING:
{
RefPtr<txNodeSet> nodes1;
rv = evaluateToNodeSet(mParams[0], aContext,
@ -438,7 +445,7 @@ txEXSLTFunctionCall::evaluate(txIEvalContext *aContext,
int32_t end = nodes1->indexOf(nodes2->get(0));
if (end >= 0) {
int32_t i = 0;
if (mType == TRAILING) {
if (mType == txEXSLTType::TRAILING) {
i = end + 1;
end = nodes1->size();
}
@ -452,7 +459,7 @@ txEXSLTFunctionCall::evaluate(txIEvalContext *aContext,
return NS_OK;
}
case CONCAT:
case txEXSLTType::CONCAT:
{
RefPtr<txNodeSet> nodes;
rv = evaluateToNodeSet(mParams[0], aContext,
@ -467,8 +474,8 @@ txEXSLTFunctionCall::evaluate(txIEvalContext *aContext,
return aContext->recycler()->getStringResult(str, aResult);
}
case SPLIT:
case TOKENIZE:
case txEXSLTType::SPLIT:
case txEXSLTType::TOKENIZE:
{
// Evaluate parameters
nsAutoString string;
@ -480,7 +487,7 @@ txEXSLTFunctionCall::evaluate(txIEvalContext *aContext,
rv = mParams[1]->evaluateToString(aContext, pattern);
NS_ENSURE_SUCCESS(rv, rv);
}
else if (mType == SPLIT) {
else if (mType == txEXSLTType::SPLIT) {
pattern.Assign(' ');
}
else {
@ -488,8 +495,11 @@ txEXSLTFunctionCall::evaluate(txIEvalContext *aContext,
}
// Set up holders for the result
RefPtr<DocumentFragment> docFrag = createDocFragment(aContext);
NS_ENSURE_STATE(docFrag);
nsIDocument* sourceDoc = getSourceDocument(aContext);
NS_ENSURE_STATE(sourceDoc);
RefPtr<DocumentFragment> docFrag =
new DocumentFragment(sourceDoc->NodeInfoManager());
RefPtr<txNodeSet> resultSet;
rv = aContext->recycler()->getNodeSet(getter_AddRefs(resultSet));
@ -510,7 +520,7 @@ txEXSLTFunctionCall::evaluate(txIEvalContext *aContext,
tailIndex = string.Length();
}
else if (mType == SPLIT) {
else if (mType == txEXSLTType::SPLIT) {
nsAString::const_iterator strStart, strEnd;
string.BeginReading(strStart);
string.EndReading(strEnd);
@ -558,8 +568,8 @@ txEXSLTFunctionCall::evaluate(txIEvalContext *aContext,
return NS_OK;
}
case MAX:
case MIN:
case txEXSLTType::MAX:
case txEXSLTType::MIN:
{
RefPtr<txNodeSet> nodes;
rv = evaluateToNodeSet(mParams[0], aContext,
@ -571,7 +581,7 @@ txEXSLTFunctionCall::evaluate(txIEvalContext *aContext,
getNumberResult(UnspecifiedNaN<double>(), aResult);
}
bool findMax = mType == MAX;
bool findMax = mType == txEXSLTType::MAX;
double res = findMax ? mozilla::NegativeInfinity<double>() :
mozilla::PositiveInfinity<double>();
@ -592,8 +602,8 @@ txEXSLTFunctionCall::evaluate(txIEvalContext *aContext,
return aContext->recycler()->getNumberResult(res, aResult);
}
case HIGHEST:
case LOWEST:
case txEXSLTType::HIGHEST:
case txEXSLTType::LOWEST:
{
RefPtr<txNodeSet> nodes;
rv = evaluateToNodeSet(mParams[0], aContext,
@ -610,7 +620,7 @@ txEXSLTFunctionCall::evaluate(txIEvalContext *aContext,
rv = aContext->recycler()->getNodeSet(getter_AddRefs(resultSet));
NS_ENSURE_SUCCESS(rv, rv);
bool findMax = mType == HIGHEST;
bool findMax = mType == txEXSLTType::HIGHEST;
double res = findMax ? mozilla::NegativeInfinity<double>() :
mozilla::PositiveInfinity<double>();
int32_t i, len = nodes->size();
@ -638,7 +648,7 @@ txEXSLTFunctionCall::evaluate(txIEvalContext *aContext,
return NS_OK;
}
case DATE_TIME:
case txEXSLTType::DATE_TIME:
{
// http://exslt.org/date/functions/date-time/
@ -668,10 +678,15 @@ txEXSLTFunctionCall::evaluate(txIEvalContext *aContext,
return NS_OK;
}
default:
{
aContext->receiveError(NS_LITERAL_STRING("Internal error"),
NS_ERROR_UNEXPECTED);
return NS_ERROR_UNEXPECTED;
}
}
aContext->receiveError(NS_LITERAL_STRING("Internal error"),
NS_ERROR_UNEXPECTED);
NS_NOTREACHED("Missing return?");
return NS_ERROR_UNEXPECTED;
}
@ -684,7 +699,8 @@ txEXSLTFunctionCall::getReturnType()
bool
txEXSLTFunctionCall::isSensitiveTo(ContextSensitivity aContext)
{
if (mType == NODE_SET || mType == SPLIT || mType == TOKENIZE) {
if (mType == txEXSLTType::NODE_SET || mType == txEXSLTType::SPLIT ||
mType == txEXSLTType::TOKENIZE) {
return (aContext & PRIVATE_CONTEXT) || argsSensitiveTo(aContext);
}
return argsSensitiveTo(aContext);
@ -694,7 +710,124 @@ txEXSLTFunctionCall::isSensitiveTo(ContextSensitivity aContext)
void
txEXSLTFunctionCall::appendName(nsAString& aDest)
{
aDest.Append((*descriptTable[mType].mName)->GetUTF16String());
aDest.Append(descriptTable[mType].mName->GetUTF16String());
}
#endif
nsresult
txEXSLTRegExFunctionCall::evaluate(txIEvalContext* aContext,
txAExprResult** aResult)
{
*aResult = nullptr;
if (!requireParams(descriptTable[mType].mMinParams,
descriptTable[mType].mMaxParams,
aContext)) {
return NS_ERROR_XPATH_BAD_ARGUMENT_COUNT;
}
nsAutoString string;
nsresult rv = mParams[0]->evaluateToString(aContext, string);
NS_ENSURE_SUCCESS(rv, rv);
nsAutoString regex;
rv = mParams[1]->evaluateToString(aContext, regex);
NS_ENSURE_SUCCESS(rv, rv);
nsAutoString flags;
if (mParams.Length() >= 3) {
rv = mParams[2]->evaluateToString(aContext, flags);
NS_ENSURE_SUCCESS(rv, rv);
}
switch (mType) {
case txEXSLTType::MATCH:
{
nsCOMPtr<nsIDOMDocument> sourceDoc =
do_QueryInterface(getSourceDocument(aContext));
NS_ENSURE_STATE(sourceDoc);
nsCOMPtr<nsIDOMDocumentFragment> domDocFrag;
rv = mRegExService->Match(string, regex, flags, sourceDoc,
getter_AddRefs(domDocFrag));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIContent> docFrag = do_QueryInterface(domDocFrag, &rv);
NS_ENSURE_SUCCESS(rv, rv);
RefPtr<txNodeSet> resultSet;
rv = aContext->recycler()->getNodeSet(getter_AddRefs(resultSet));
NS_ENSURE_SUCCESS(rv, rv);
nsAutoPtr<txXPathNode> node;
for (nsIContent* result = docFrag->GetFirstChild(); result;
result = result->GetNextSibling()) {
node = txXPathNativeNode::createXPathNode(result, true);
rv = resultSet->add(*node);
NS_ENSURE_SUCCESS(rv, rv);
}
resultSet.forget(aResult);
return NS_OK;
}
case txEXSLTType::REPLACE:
{
nsAutoString replace;
rv = mParams[3]->evaluateToString(aContext, replace);
NS_ENSURE_SUCCESS(rv, rv);
nsString result;
rv = mRegExService->Replace(string, regex, flags, replace, result);
NS_ENSURE_SUCCESS(rv, rv);
rv = aContext->recycler()->getStringResult(result, aResult);
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
}
case txEXSLTType::TEST:
{
bool result;
rv = mRegExService->Test(string, regex, flags, &result);
NS_ENSURE_SUCCESS(rv, rv);
aContext->recycler()->getBoolResult(result, aResult);
return NS_OK;
}
default:
{
aContext->receiveError(NS_LITERAL_STRING("Internal error"),
NS_ERROR_UNEXPECTED);
return NS_ERROR_UNEXPECTED;
}
}
NS_NOTREACHED("Missing return?");
return NS_ERROR_UNEXPECTED;
}
Expr::ResultType
txEXSLTRegExFunctionCall::getReturnType()
{
return descriptTable[mType].mReturnType;
}
bool
txEXSLTRegExFunctionCall::isSensitiveTo(ContextSensitivity aContext)
{
if (mType == txEXSLTType::MATCH) {
return (aContext & PRIVATE_CONTEXT) || argsSensitiveTo(aContext);
}
return argsSensitiveTo(aContext);
}
#ifdef TX_TO_STRING
void
txEXSLTRegExFunctionCall::appendName(nsAString& aDest)
{
aDest.Append(descriptTable[mType].mName->GetUTF16String());
}
#endif
@ -704,13 +837,10 @@ TX_ConstructEXSLTFunction(nsAtom *aName,
txStylesheetCompilerState* aState,
FunctionCall **aResult)
{
uint32_t i;
for (i = 0; i < ArrayLength(descriptTable); ++i) {
txEXSLTFunctionDescriptor& desc = descriptTable[i];
if (aName == *desc.mName && aNamespaceID == desc.mNamespaceID) {
*aResult = new txEXSLTFunctionCall(
static_cast<txEXSLTFunctionCall::eType>(i));
return NS_OK;
for (auto i : MakeEnumeratedRange(txEXSLTType::_LIMIT)) {
const txEXSLTFunctionDescriptor& desc = descriptTable[i];
if (aName == desc.mName && aNamespaceID == desc.mNamespaceID) {
return desc.mCreator(i, aResult) ? NS_OK : NS_ERROR_FAILURE;
}
}
@ -720,17 +850,53 @@ TX_ConstructEXSLTFunction(nsAtom *aName,
extern bool
TX_InitEXSLTFunction()
{
uint32_t i;
for (i = 0; i < ArrayLength(descriptTable); ++i) {
txEXSLTFunctionDescriptor& desc = descriptTable[i];
NS_ConvertASCIItoUTF16 namespaceURI(desc.mNamespaceURI);
desc.mNamespaceID =
txNamespaceManager::getNamespaceID(namespaceURI);
if (desc.mNamespaceID == kNameSpaceID_Unknown) {
return false;
}
#define EXSLT_FUNCS(NS, CLASS, ...) \
{ \
int32_t nsid = txNamespaceManager::getNamespaceID(NS_LITERAL_STRING(NS)); \
if (nsid == kNameSpaceID_Unknown) { \
return false; \
} \
MOZ_FOR_EACH(EXSLT_FUNC, (nsid, CLASS,), (__VA_ARGS__)) \
}
#define EXSLT_FUNC(NS, CLASS, ...) \
descriptTable[txEXSLTType::MOZ_ARG_1 __VA_ARGS__] = { MOZ_ARGS_AFTER_1 __VA_ARGS__, CLASS::Create, NS };
EXSLT_FUNCS("http://exslt.org/common", txEXSLTFunctionCall,
(NODE_SET, 1, 1, Expr::NODESET_RESULT, nsGkAtoms::nodeSet),
(OBJECT_TYPE, 1, 1, Expr::STRING_RESULT, nsGkAtoms::objectType))
EXSLT_FUNCS("http://exslt.org/dates-and-times", txEXSLTFunctionCall,
(DATE_TIME, 0, 0, Expr::STRING_RESULT, nsGkAtoms::dateTime))
EXSLT_FUNCS("http://exslt.org/math", txEXSLTFunctionCall,
(MAX, 1, 1, Expr::NUMBER_RESULT, nsGkAtoms::max),
(MIN, 1, 1, Expr::NUMBER_RESULT, nsGkAtoms::min),
(HIGHEST, 1, 1, Expr::NODESET_RESULT, nsGkAtoms::highest),
(LOWEST, 1, 1, Expr::NODESET_RESULT, nsGkAtoms::lowest))
EXSLT_FUNCS("http://exslt.org/regular-expressions", txEXSLTRegExFunctionCall,
(MATCH, 2, 3, Expr::NODESET_RESULT, nsGkAtoms::match),
(REPLACE, 4, 4, Expr::STRING_RESULT, nsGkAtoms::replace),
(TEST, 2, 3, Expr::BOOLEAN_RESULT, nsGkAtoms::test))
EXSLT_FUNCS("http://exslt.org/sets", txEXSLTFunctionCall,
(DIFFERENCE, 2, 2, Expr::NODESET_RESULT, nsGkAtoms::difference),
(DISTINCT, 1, 1, Expr::NODESET_RESULT, nsGkAtoms::distinct),
(HAS_SAME_NODE, 2, 2, Expr::BOOLEAN_RESULT, nsGkAtoms::hasSameNode),
(INTERSECTION, 2, 2, Expr::NODESET_RESULT, nsGkAtoms::intersection),
(LEADING, 2, 2, Expr::NODESET_RESULT, nsGkAtoms::leading),
(TRAILING, 2, 2, Expr::NODESET_RESULT, nsGkAtoms::trailing))
EXSLT_FUNCS("http://exslt.org/strings", txEXSLTFunctionCall,
(CONCAT, 1, 1, Expr::STRING_RESULT, nsGkAtoms::concat),
(SPLIT, 1, 2, Expr::STRING_RESULT, nsGkAtoms::split),
(TOKENIZE, 1, 2, Expr::STRING_RESULT, nsGkAtoms::tokenize))
#undef EXSLT_FUNCS
#undef EXSLT_FUNC
#undef EXSLT_FUNC_HELPER
#undef EXSLT_FUNC_HELPER2
return true;
}

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

@ -6,9 +6,6 @@
ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
const EXSLT_REGEXP_CID = Components.ID("{18a03189-067b-4978-b4f1-bafe35292ed6}");
const EXSLT_REGEXP_CONTRACTID = "@mozilla.org/exslt/regexp;1";
const NODESET_CONTRACTID = "@mozilla.org/transformiix-nodeset;1";
function txEXSLTRegExFunctions()
{
@ -21,34 +18,21 @@ txEXSLTRegExFunctions.prototype = {
QueryInterface: XPCOMUtils.generateQI([Ci.txIEXSLTRegExFunctions]),
classInfo: XPCOMUtils.generateCI({classID: EXSLT_REGEXP_CID,
contractID: EXSLT_REGEXP_CONTRACTID,
interfaces: [Ci.txIEXSLTRegExFunctions]}),
// txIEXSLTRegExFunctions
match: function(context, str, regex, flags) {
var nodeset = Cc[NODESET_CONTRACTID]
.createInstance(Ci.txINodeSet);
match: function(str, regex, flags, doc) {
var docFrag = doc.createDocumentFragment();
var re = new RegExp(regex, flags);
var matches = str.match(re);
if (matches != null && matches.length > 0) {
var contextNode = context.contextNode;
var doc = contextNode.nodeType == Ci.nsIDOMNode.DOCUMENT_NODE ?
contextNode : contextNode.ownerDocument;
var docFrag = doc.createDocumentFragment();
if (matches != null) {
for (var i = 0; i < matches.length; ++i) {
var match = matches[i];
var elem = doc.createElementNS(null, "match");
var text = doc.createTextNode(match ? match : '');
elem.appendChild(text);
docFrag.appendChild(elem);
nodeset.add(elem);
}
}
return nodeset;
return docFrag;
},
replace: function(str, regex, flags, replace) {

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

@ -1,3 +1,2 @@
component {18a03189-067b-4978-b4f1-bafe35292ed6} txEXSLTRegExFunctions.js
contract @mozilla.org/exslt/regexp;1 {18a03189-067b-4978-b4f1-bafe35292ed6}
category XSLT-extension-functions http://exslt.org/regular-expressions @mozilla.org/exslt/regexp;1

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

@ -899,8 +899,7 @@ txErrorFunctionCall::appendName(nsAString& aDest)
#endif
static nsresult
TX_ConstructXSLTFunction(nsAtom* aName, int32_t aNamespaceID,
txStylesheetCompilerState* aState,
TX_ConstructXSLTFunction(nsAtom* aName, txStylesheetCompilerState* aState,
FunctionCall** aFunction)
{
if (aName == nsGkAtoms::document) {
@ -951,115 +950,21 @@ TX_ConstructXSLTFunction(nsAtom* aName, int32_t aNamespaceID,
return NS_OK;
}
typedef nsresult (*txFunctionFactory)(nsAtom* aName,
int32_t aNamespaceID,
txStylesheetCompilerState* aState,
FunctionCall** aResult);
struct txFunctionFactoryMapping
{
const char* const mNamespaceURI;
int32_t mNamespaceID;
txFunctionFactory mFactory;
};
extern nsresult
TX_ConstructEXSLTFunction(nsAtom *aName,
int32_t aNamespaceID,
txStylesheetCompilerState* aState,
FunctionCall **aResult);
static txFunctionFactoryMapping kExtensionFunctions[] = {
{ "", kNameSpaceID_Unknown, TX_ConstructXSLTFunction },
{ "http://exslt.org/common", kNameSpaceID_Unknown,
TX_ConstructEXSLTFunction },
{ "http://exslt.org/sets", kNameSpaceID_Unknown,
TX_ConstructEXSLTFunction },
{ "http://exslt.org/strings", kNameSpaceID_Unknown,
TX_ConstructEXSLTFunction },
{ "http://exslt.org/math", kNameSpaceID_Unknown,
TX_ConstructEXSLTFunction },
{ "http://exslt.org/dates-and-times", kNameSpaceID_Unknown,
TX_ConstructEXSLTFunction }
};
extern nsresult
TX_ResolveFunctionCallXPCOM(const nsCString &aContractID, int32_t aNamespaceID,
nsAtom *aName, nsISupports *aState,
FunctionCall **aFunction);
struct txXPCOMFunctionMapping
{
int32_t mNamespaceID;
nsCString mContractID;
};
static nsTArray<txXPCOMFunctionMapping> *sXPCOMFunctionMappings = nullptr;
static nsresult
findFunction(nsAtom* aName, int32_t aNamespaceID,
txStylesheetCompilerState* aState, FunctionCall** aResult)
{
if (kExtensionFunctions[0].mNamespaceID == kNameSpaceID_Unknown) {
uint32_t i;
for (i = 0; i < ArrayLength(kExtensionFunctions); ++i) {
txFunctionFactoryMapping& mapping = kExtensionFunctions[i];
NS_ConvertASCIItoUTF16 namespaceURI(mapping.mNamespaceURI);
mapping.mNamespaceID =
txNamespaceManager::getNamespaceID(namespaceURI);
}
if (aNamespaceID == kNameSpaceID_None) {
return TX_ConstructXSLTFunction(aName, aState, aResult);
}
uint32_t i;
for (i = 0; i < ArrayLength(kExtensionFunctions); ++i) {
const txFunctionFactoryMapping& mapping = kExtensionFunctions[i];
if (mapping.mNamespaceID == aNamespaceID) {
return mapping.mFactory(aName, aNamespaceID, aState, aResult);
}
}
if (!sXPCOMFunctionMappings) {
sXPCOMFunctionMappings = new nsTArray<txXPCOMFunctionMapping>;
}
txXPCOMFunctionMapping *map = nullptr;
uint32_t count = sXPCOMFunctionMappings->Length();
for (i = 0; i < count; ++i) {
map = &sXPCOMFunctionMappings->ElementAt(i);
if (map->mNamespaceID == aNamespaceID) {
break;
}
}
if (i == count) {
nsresult rv;
nsCOMPtr<nsICategoryManager> catman =
do_GetService(NS_CATEGORYMANAGER_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
nsAutoString namespaceURI;
rv = txNamespaceManager::getNamespaceURI(aNamespaceID, namespaceURI);
NS_ENSURE_SUCCESS(rv, rv);
nsCString contractID;
rv = catman->GetCategoryEntry("XSLT-extension-functions",
NS_ConvertUTF16toUTF8(namespaceURI).get(),
getter_Copies(contractID));
if (rv == NS_ERROR_NOT_AVAILABLE) {
return NS_ERROR_XPATH_UNKNOWN_FUNCTION;
}
NS_ENSURE_SUCCESS(rv, rv);
map = sXPCOMFunctionMappings->AppendElement();
if (!map) {
return NS_ERROR_OUT_OF_MEMORY;
}
map->mNamespaceID = aNamespaceID;
map->mContractID = contractID;
}
return TX_ResolveFunctionCallXPCOM(map->mContractID, aNamespaceID, aName,
nullptr, aResult);
return TX_ConstructEXSLTFunction(aName, aNamespaceID, aState, aResult);
}
extern bool
@ -1104,14 +1009,6 @@ txStylesheetCompilerState::SetErrorOffset(uint32_t aOffset)
// XXX implement me
}
/* static */
void
txStylesheetCompilerState::shutdown()
{
delete sXPCOMFunctionMappings;
sXPCOMFunctionMappings = nullptr;
}
txElementContext::txElementContext(const nsAString& aBaseURI)
: mPreserveWhitespace(false),
mForwardsCompatibleParsing(true),

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

@ -152,8 +152,6 @@ public:
fcp();
}
static void shutdown();
RefPtr<txStylesheet> mStylesheet;
txHandlerTable* mHandlerTable;

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

@ -34,7 +34,6 @@ txXSLTProcessor::init()
void
txXSLTProcessor::shutdown()
{
txStylesheetCompilerState::shutdown();
txHandlerTable::shutdown();
}

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

@ -54,7 +54,6 @@
// Transformiix stuff
#include "mozilla/dom/XPathEvaluator.h"
#include "txNodeSetAdaptor.h"
#include "mozilla/dom/DOMParser.h"
#include "nsDOMSerializer.h"
@ -193,14 +192,6 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(nsParserUtils)
NS_GENERIC_FACTORY_CONSTRUCTOR(HTMLEditor)
// Transformiix
/* 5d5d92cd-6bf8-11d9-bf4a-000a95dc234c */
#define TRANSFORMIIX_NODESET_CID \
{ 0x5d5d92cd, 0x6bf8, 0x11d9, { 0xbf, 0x4a, 0x0, 0x0a, 0x95, 0xdc, 0x23, 0x4c } }
#define TRANSFORMIIX_NODESET_CONTRACTID \
"@mozilla.org/transformiix-nodeset;1"
// PresentationDeviceManager
/* e1e79dec-4085-4994-ac5b-744b016697e6 */
#define PRESENTATION_DEVICE_MANAGER_CID \
@ -212,7 +203,6 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(HTMLEditor)
already_AddRefed<nsIPresentationService> NS_CreatePresentationService();
// Factory Constructor
NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(txNodeSetAdaptor, Init)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsDOMSerializer)
typedef nsHostObjectURI::Mutator nsHostObjectURIMutator;
NS_GENERIC_FACTORY_CONSTRUCTOR(nsHostObjectURIMutator)
@ -573,7 +563,6 @@ NS_DEFINE_NAMED_CID(NS_PLUGINDOCLOADERFACTORY_CID);
NS_DEFINE_NAMED_CID(NS_PLUGINDOCUMENT_CID);
NS_DEFINE_NAMED_CID(NS_VIDEODOCUMENT_CID);
NS_DEFINE_NAMED_CID(NS_STYLESHEETSERVICE_CID);
NS_DEFINE_NAMED_CID(TRANSFORMIIX_NODESET_CID);
NS_DEFINE_NAMED_CID(NS_XMLSERIALIZER_CID);
NS_DEFINE_NAMED_CID(NS_HOSTOBJECTURI_CID);
NS_DEFINE_NAMED_CID(NS_HOSTOBJECTURIMUTATOR_CID);
@ -821,7 +810,6 @@ static const mozilla::Module::CIDEntry kLayoutCIDs[] = {
{ &kNS_PLUGINDOCUMENT_CID, false, nullptr, CreatePluginDocument },
{ &kNS_VIDEODOCUMENT_CID, false, nullptr, CreateVideoDocument },
{ &kNS_STYLESHEETSERVICE_CID, false, nullptr, nsStyleSheetServiceConstructor },
{ &kTRANSFORMIIX_NODESET_CID, false, nullptr, txNodeSetAdaptorConstructor },
{ &kNS_XMLSERIALIZER_CID, false, nullptr, nsDOMSerializerConstructor },
{ &kNS_HOSTOBJECTURI_CID, false, nullptr, nsHostObjectURIMutatorConstructor }, // do_CreateInstance returns mutator
{ &kNS_HOSTOBJECTURIMUTATOR_CID, false, nullptr, nsHostObjectURIMutatorConstructor },
@ -934,7 +922,6 @@ static const mozilla::Module::ContractIDEntry kLayoutContracts[] = {
{ NS_WINDOWCONTROLLER_CONTRACTID, &kNS_WINDOWCONTROLLER_CID },
{ PLUGIN_DLF_CONTRACTID, &kNS_PLUGINDOCLOADERFACTORY_CID },
{ NS_STYLESHEETSERVICE_CONTRACTID, &kNS_STYLESHEETSERVICE_CID },
{ TRANSFORMIIX_NODESET_CONTRACTID, &kTRANSFORMIIX_NODESET_CID },
{ NS_XMLSERIALIZER_CONTRACTID, &kNS_XMLSERIALIZER_CID },
{ NS_DOMPARSER_CONTRACTID, &kNS_DOMPARSER_CID },
{ "@mozilla.org/dom/localStorage-manager;1", &kNS_DOMLOCALSTORAGEMANAGER_CID },