mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Merge last PGO-green changeset of mozilla-inbound to mozilla-central
This commit is contained in:
commit
7b8f9d67b3
@ -80,6 +80,7 @@ endif
|
||||
|
||||
ifdef MOZ_MEMORY
|
||||
tier_base_dirs += memory/jemalloc
|
||||
tier_base_dirs += memory/build
|
||||
endif
|
||||
tier_base_dirs += \
|
||||
mozglue \
|
||||
|
@ -88,6 +88,7 @@ if [ ! "$LIBXUL_SDK" ]; then
|
||||
if [ "$MOZ_MEMORY" ]; then
|
||||
add_makefiles "
|
||||
memory/jemalloc/Makefile
|
||||
memory/build/Makefile
|
||||
"
|
||||
fi
|
||||
if [ "$MOZ_WIDGET_TOOLKIT" = "android" ]; then
|
||||
|
@ -1,2 +1,3 @@
|
||||
README.txt
|
||||
@DLL_PREFIX@mozutils@DLL_SUFFIX@
|
||||
jssubloader/
|
||||
|
@ -24,7 +24,7 @@ CPPSRCS = nsModule.cpp \
|
||||
$(NULL)
|
||||
|
||||
ifeq ($(OS_ARCH),WINNT)
|
||||
OS_LIBS += $(call EXPAND_LIBNAME,ole32 shell32)
|
||||
OS_LIBS += $(call EXPAND_LIBNAME,ole32 shell32 shlwapi)
|
||||
endif
|
||||
|
||||
LOCAL_INCLUDES = \
|
||||
|
@ -77,8 +77,6 @@
|
||||
#define INITGUID
|
||||
#include <shlobj.h>
|
||||
|
||||
#pragma comment(lib, "shlwapi.lib") // for SHDeleteKeyW
|
||||
|
||||
#include <mbstring.h>
|
||||
#include <shlwapi.h>
|
||||
|
||||
|
@ -1475,3 +1475,4 @@ components/nsPlacesDBFlush.js
|
||||
maintenanceservice.exe
|
||||
maintenanceservice_installer.exe
|
||||
#endif
|
||||
jssubloader/
|
||||
|
@ -94,8 +94,10 @@
|
||||
#include "nsIContentSecurityPolicy.h"
|
||||
#include "nsIAsyncVerifyRedirectCallback.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/dom/bindings/Utils.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
|
||||
static NS_DEFINE_CID(kZipReaderCID, NS_ZIPREADER_CID);
|
||||
|
||||
@ -2445,9 +2447,17 @@ nsScriptSecurityManager::doGetObjectPrincipal(JSObject *aObj
|
||||
if (result) {
|
||||
break;
|
||||
}
|
||||
} else if (!(~jsClass->flags & (JSCLASS_HAS_PRIVATE |
|
||||
JSCLASS_PRIVATE_IS_NSISUPPORTS))) {
|
||||
nsISupports *priv = (nsISupports *) js::GetObjectPrivate(aObj);
|
||||
} else {
|
||||
nsISupports *priv;
|
||||
if (!(~jsClass->flags & (JSCLASS_HAS_PRIVATE |
|
||||
JSCLASS_PRIVATE_IS_NSISUPPORTS))) {
|
||||
priv = (nsISupports *) js::GetObjectPrivate(aObj);
|
||||
} else if ((jsClass->flags & JSCLASS_IS_DOMJSCLASS) &&
|
||||
bindings::DOMJSClass::FromJSClass(jsClass)->mDOMObjectIsISupports) {
|
||||
priv = bindings::UnwrapDOMObject<nsISupports>(aObj, jsClass);
|
||||
} else {
|
||||
priv = nsnull;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
if (aAllowShortCircuit) {
|
||||
|
@ -1642,7 +1642,10 @@ public:
|
||||
{
|
||||
return sThreadJSContextStack;
|
||||
}
|
||||
|
||||
|
||||
// Trace the safe JS context of the ThreadJSContextStack.
|
||||
static void TraceSafeJSContext(JSTracer* aTrc);
|
||||
|
||||
|
||||
/**
|
||||
* Get the Origin of the passed in nsIPrincipal or nsIURI. If the passed in
|
||||
|
@ -183,9 +183,10 @@ public:
|
||||
|
||||
/**
|
||||
* Let the document know that we're starting to load data into it.
|
||||
* @param aCommand The parser command
|
||||
* @param aCommand The parser command. Must not be null.
|
||||
* XXXbz It's odd to have that here.
|
||||
* @param aChannel The channel the data will come from
|
||||
* @param aChannel The channel the data will come from. The channel must be
|
||||
* able to report its Content-Type.
|
||||
* @param aLoadGroup The loadgroup this document should use from now on.
|
||||
* Note that the document might not be the only thing using
|
||||
* this loadgroup.
|
||||
@ -204,6 +205,9 @@ public:
|
||||
* @param aSink The content sink to use for the data. If this is null and
|
||||
* the document needs a content sink, it will create one based
|
||||
* on whatever it knows about the data it's going to load.
|
||||
* This MUST be null if the underlying document is an HTML
|
||||
* document. Even in the XML case, please don't add new calls
|
||||
* with non-null sink.
|
||||
*
|
||||
* Once this has been called, the document will return false for
|
||||
* MayStartLayout() until SetMayStartLayout(true) is called on it. Making
|
||||
|
@ -237,6 +237,12 @@ interface nsIDocumentEncoder : nsISupports
|
||||
*/
|
||||
const unsigned long OutputFormatDelSp = (1 << 20);
|
||||
|
||||
/**
|
||||
* Drop <br> elements considered "invisible" by the editor. OutputPreformatted
|
||||
* implies this flag.
|
||||
*/
|
||||
const unsigned long OutputDropInvisibleBreak = (1 << 21);
|
||||
|
||||
/**
|
||||
* Initialize with a pointer to the document and the mime type.
|
||||
* @param aDocument Document to encode.
|
||||
|
@ -403,4 +403,7 @@ mozilla::dom::TraceBlackJS(JSTracer* aTrc)
|
||||
if (windowsById) {
|
||||
windowsById->Enumerate(TraceActiveWindowGlobal, aTrc);
|
||||
}
|
||||
|
||||
// Mark the safe context black
|
||||
nsContentUtils::TraceSafeJSContext(aTrc);
|
||||
}
|
||||
|
@ -1665,6 +1665,23 @@ nsContentUtils::GetContextAndScope(nsIDocument *aOldDocument,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//static
|
||||
void
|
||||
nsContentUtils::TraceSafeJSContext(JSTracer* aTrc)
|
||||
{
|
||||
if (!sThreadJSContextStack) {
|
||||
return;
|
||||
}
|
||||
JSContext* cx = nsnull;
|
||||
sThreadJSContextStack->GetSafeJSContext(&cx);
|
||||
if (!cx) {
|
||||
return;
|
||||
}
|
||||
if (JSObject* global = JS_GetGlobalObject(cx)) {
|
||||
JS_CALL_OBJECT_TRACER(aTrc, global, "safe context");
|
||||
}
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsContentUtils::ReparentContentWrappersInScope(JSContext *cx,
|
||||
nsIScriptGlobalObject *aOldScope,
|
||||
@ -6578,16 +6595,17 @@ nsContentUtils::ReleaseWrapper(nsISupports* aScriptObjectHolder,
|
||||
nsWrapperCache* aCache)
|
||||
{
|
||||
if (aCache->PreservingWrapper()) {
|
||||
// PreserveWrapper puts new DOM bindings in the JS holders hash, but they
|
||||
// can also be in the DOM expando hash, so we need to try to remove them
|
||||
// from both here.
|
||||
JSObject* obj = aCache->GetWrapperPreserveColor();
|
||||
if (aCache->IsDOMBinding()) {
|
||||
if (aCache->IsDOMBinding() && obj) {
|
||||
JSCompartment *compartment = js::GetObjectCompartment(obj);
|
||||
xpc::CompartmentPrivate *priv =
|
||||
static_cast<xpc::CompartmentPrivate *>(JS_GetCompartmentPrivate(compartment));
|
||||
priv->RemoveDOMExpandoObject(obj);
|
||||
}
|
||||
else {
|
||||
DropJSObjects(aScriptObjectHolder);
|
||||
}
|
||||
DropJSObjects(aScriptObjectHolder);
|
||||
|
||||
aCache->SetPreservingWrapper(false);
|
||||
}
|
||||
|
@ -160,25 +160,39 @@ SelectionCopyHelper(nsISelection *aSel, nsIDocument *aDoc,
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
nsCOMPtr<nsIFormatConverter> htmlConverter;
|
||||
|
||||
// sometimes we also need the HTML version
|
||||
// If the selection was in a text input, in textarea or in pre, the encoder
|
||||
// already produced plain text. Otherwise,the encoder produced HTML. In that
|
||||
// case, we need to create an additional plain text serialization and an
|
||||
// addition HTML serialization that encodes context.
|
||||
if (bIsHTMLCopy) {
|
||||
|
||||
// this string may still contain HTML formatting, so we need to remove that too.
|
||||
htmlConverter = do_CreateInstance(kHTMLConverterCID);
|
||||
NS_ENSURE_TRUE(htmlConverter, NS_ERROR_FAILURE);
|
||||
// First, create the plain text serialization
|
||||
mimeType.AssignLiteral("text/plain");
|
||||
|
||||
nsCOMPtr<nsISupportsString> plainHTML = do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID);
|
||||
NS_ENSURE_TRUE(plainHTML, NS_ERROR_FAILURE);
|
||||
plainHTML->SetData(textBuffer);
|
||||
flags =
|
||||
nsIDocumentEncoder::OutputSelectionOnly |
|
||||
nsIDocumentEncoder::OutputAbsoluteLinks |
|
||||
nsIDocumentEncoder::SkipInvisibleContent |
|
||||
nsIDocumentEncoder::OutputDropInvisibleBreak |
|
||||
(aFlags & nsIDocumentEncoder::OutputNoScriptContent);
|
||||
|
||||
nsCOMPtr<nsISupportsString> ConvertedData;
|
||||
PRUint32 ConvertedLen;
|
||||
rv = htmlConverter->Convert(kHTMLMime, plainHTML, textBuffer.Length() * 2, kUnicodeMime, getter_AddRefs(ConvertedData), &ConvertedLen);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = docEncoder->Init(domDoc, mimeType, flags);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
ConvertedData->GetData(plaintextBuffer);
|
||||
rv = docEncoder->SetSelection(aSel);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
rv = docEncoder->EncodeToString(plaintextBuffer);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
// Emulate the collateral damage from bug 564737. Remove the following
|
||||
// line to fix bug 739537.
|
||||
plaintextBuffer.Trim(" ", true, false);
|
||||
|
||||
// Now create the version that shows HTML context
|
||||
|
||||
mimeType.AssignLiteral(kHTMLMime);
|
||||
|
||||
@ -208,7 +222,10 @@ SelectionCopyHelper(nsISelection *aSel, nsIDocument *aDoc,
|
||||
nsCOMPtr<nsITransferable> trans = do_CreateInstance(kCTransferableCID);
|
||||
if (trans) {
|
||||
if (bIsHTMLCopy) {
|
||||
// set up the data converter
|
||||
// Set up a format converter so that clipboard flavor queries work.
|
||||
// This converter isn't really used for conversions.
|
||||
nsCOMPtr<nsIFormatConverter> htmlConverter =
|
||||
do_CreateInstance(kHTMLConverterCID);
|
||||
trans->SetConverter(htmlConverter);
|
||||
|
||||
if (!buffer.IsEmpty()) {
|
||||
|
@ -83,6 +83,10 @@
|
||||
#include "nsIFrame.h"
|
||||
#include "nsStringBuffer.h"
|
||||
#include "mozilla/dom/Element.h"
|
||||
#include "nsIEditorDocShell.h"
|
||||
#include "nsIEditor.h"
|
||||
#include "nsIHTMLEditor.h"
|
||||
#include "nsIDocShell.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
@ -349,6 +353,42 @@ nsDocumentEncoder::IncludeInContext(nsINode *aNode)
|
||||
return false;
|
||||
}
|
||||
|
||||
static
|
||||
bool
|
||||
IsInvisibleBreak(nsINode *aNode) {
|
||||
// xxxehsan: we should probably figure out a way to determine
|
||||
// if a BR node is visible without using the editor.
|
||||
Element* elt = aNode->AsElement();
|
||||
if (!elt->IsHTML(nsGkAtoms::br) ||
|
||||
!aNode->IsEditable()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Grab the editor associated with the document
|
||||
nsIDocument *doc = aNode->GetCurrentDoc();
|
||||
if (doc) {
|
||||
nsPIDOMWindow *window = doc->GetWindow();
|
||||
if (window) {
|
||||
nsIDocShell *docShell = window->GetDocShell();
|
||||
if (docShell) {
|
||||
nsCOMPtr<nsIEditorDocShell> editorDocShell = do_QueryInterface(docShell);
|
||||
if (editorDocShell) {
|
||||
nsCOMPtr<nsIEditor> editor;
|
||||
editorDocShell->GetEditor(getter_AddRefs(editor));
|
||||
nsCOMPtr<nsIHTMLEditor> htmlEditor = do_QueryInterface(editor);
|
||||
if (htmlEditor) {
|
||||
bool isVisible = false;
|
||||
nsCOMPtr<nsIDOMNode> domNode = do_QueryInterface(aNode);
|
||||
htmlEditor->BreakIsVisible(domNode, &isVisible);
|
||||
return !isVisible;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDocumentEncoder::SerializeNodeStart(nsINode* aNode,
|
||||
PRInt32 aStartOffset,
|
||||
@ -381,6 +421,11 @@ nsDocumentEncoder::SerializeNodeStart(nsINode* aNode,
|
||||
node = aNode;
|
||||
|
||||
if (node->IsElement()) {
|
||||
if ((mFlags & (nsIDocumentEncoder::OutputPreformatted |
|
||||
nsIDocumentEncoder::OutputDropInvisibleBreak)) &&
|
||||
IsInvisibleBreak(node)) {
|
||||
return NS_OK;
|
||||
}
|
||||
Element* originalElement =
|
||||
aOriginalNode && aOriginalNode->IsElement() ?
|
||||
aOriginalNode->AsElement() : nsnull;
|
||||
@ -1245,7 +1290,15 @@ nsHTMLCopyEncoder::Init(nsIDOMDocument* aDocument,
|
||||
mDocument = do_QueryInterface(aDocument);
|
||||
NS_ENSURE_TRUE(mDocument, NS_ERROR_FAILURE);
|
||||
|
||||
mMimeType.AssignLiteral("text/html");
|
||||
// Hack, hack! Traditionally, the caller passes text/unicode, which is
|
||||
// treated as "guess text/html or text/plain" in this context. (It has a
|
||||
// different meaning in other contexts. Sigh.) From now on, "text/plain"
|
||||
// means forcing text/plain instead of guessing.
|
||||
if (aMimeType.EqualsLiteral("text/plain")) {
|
||||
mMimeType.AssignLiteral("text/plain");
|
||||
} else {
|
||||
mMimeType.AssignLiteral("text/html");
|
||||
}
|
||||
|
||||
// Make all links absolute when copying
|
||||
// (see related bugs #57296, #41924, #58646, #32768)
|
||||
|
@ -1902,10 +1902,11 @@ GK_ATOM(x_symbol, "x-symbol")
|
||||
// referenced in all.js
|
||||
GK_ATOM(x_user_def, "x-user-def")
|
||||
|
||||
// additional languages that use Turkish-style case transformation
|
||||
// additional languages that have special case transformations
|
||||
GK_ATOM(az, "az")
|
||||
GK_ATOM(ba, "ba")
|
||||
GK_ATOM(crh, "crh")
|
||||
GK_ATOM(nl, "nl")
|
||||
|
||||
// Names for editor transactions
|
||||
GK_ATOM(TypingTxnName, "Typing")
|
||||
|
@ -88,41 +88,6 @@ nsresult NS_NewHTMLContentSerializer(nsIContentSerializer** aSerializer)
|
||||
return CallQueryInterface(it, aSerializer);
|
||||
}
|
||||
|
||||
static
|
||||
bool
|
||||
IsInvisibleBreak(nsIContent *aNode, nsIAtom *aTag, PRInt32 aNamespace) {
|
||||
// xxxehsan: we should probably figure out a way to determine
|
||||
// if a BR node is visible without using the editor.
|
||||
if (!(aTag == nsGkAtoms::br && aNamespace == kNameSpaceID_XHTML) ||
|
||||
!aNode->IsEditable()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Grab the editor associated with the document
|
||||
nsIDocument *doc = aNode->GetCurrentDoc();
|
||||
if (doc) {
|
||||
nsPIDOMWindow *window = doc->GetWindow();
|
||||
if (window) {
|
||||
nsIDocShell *docShell = window->GetDocShell();
|
||||
if (docShell) {
|
||||
nsCOMPtr<nsIEditorDocShell> editorDocShell = do_QueryInterface(docShell);
|
||||
if (editorDocShell) {
|
||||
nsCOMPtr<nsIEditor> editor;
|
||||
editorDocShell->GetEditor(getter_AddRefs(editor));
|
||||
nsCOMPtr<nsIHTMLEditor> htmlEditor = do_QueryInterface(editor);
|
||||
if (htmlEditor) {
|
||||
bool isVisible = false;
|
||||
nsCOMPtr<nsIDOMNode> domNode = do_QueryInterface(aNode);
|
||||
htmlEditor->BreakIsVisible(domNode, &isVisible);
|
||||
return !isVisible;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
nsHTMLContentSerializer::nsHTMLContentSerializer()
|
||||
{
|
||||
mIsHTMLSerializer = true;
|
||||
@ -263,11 +228,6 @@ nsHTMLContentSerializer::AppendElementStart(Element* aElement,
|
||||
nsIAtom *name = content->Tag();
|
||||
PRInt32 ns = content->GetNameSpaceID();
|
||||
|
||||
if ((mFlags & nsIDocumentEncoder::OutputPreformatted) &&
|
||||
IsInvisibleBreak(content, name, ns)) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
bool lineBreakBeforeOpen = LineBreakBeforeOpen(ns, name);
|
||||
|
||||
if ((mDoFormat || forceFormat) && !mPreLevel && !mDoRaw) {
|
||||
|
@ -105,6 +105,7 @@
|
||||
#include "nsIFileChannel.h"
|
||||
#include "mozilla/Telemetry.h"
|
||||
#include "sampler.h"
|
||||
#include "mozilla/dom/bindings/XMLHttpRequestBinding.h"
|
||||
#include "nsIDOMFormData.h"
|
||||
|
||||
#include "nsWrapperCacheInlines.h"
|
||||
@ -483,6 +484,8 @@ nsXMLHttpRequest::nsXMLHttpRequest()
|
||||
mResultArrayBuffer(nsnull)
|
||||
{
|
||||
nsLayoutStatics::AddRef();
|
||||
|
||||
SetIsDOMBinding();
|
||||
#ifdef DEBUG
|
||||
StaticAssertions();
|
||||
#endif
|
||||
@ -540,15 +543,17 @@ nsXMLHttpRequest::Init()
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
NS_ENSURE_STATE(subjectPrincipal);
|
||||
mPrincipal = subjectPrincipal;
|
||||
|
||||
nsIScriptContext* context = GetScriptContextFromJSContext(cx);
|
||||
nsCOMPtr<nsPIDOMWindow> window;
|
||||
if (context) {
|
||||
nsCOMPtr<nsPIDOMWindow> window =
|
||||
do_QueryInterface(context->GetGlobalObject());
|
||||
BindToOwner(window ? window->GetCurrentInnerWindow() : nsnull);
|
||||
window = do_QueryInterface(context->GetGlobalObject());
|
||||
if (window) {
|
||||
window = window->GetCurrentInnerWindow();
|
||||
}
|
||||
}
|
||||
|
||||
Construct(subjectPrincipal, window);
|
||||
return NS_OK;
|
||||
}
|
||||
/**
|
||||
@ -561,11 +566,9 @@ nsXMLHttpRequest::Init(nsIPrincipal* aPrincipal,
|
||||
nsIURI* aBaseURI)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aPrincipal);
|
||||
|
||||
mPrincipal = aPrincipal;
|
||||
BindToOwner(aOwnerWindow ? aOwnerWindow->GetCurrentInnerWindow() : nsnull);
|
||||
mBaseURI = aBaseURI;
|
||||
|
||||
Construct(aPrincipal,
|
||||
aOwnerWindow ? aOwnerWindow->GetCurrentInnerWindow() : nsnull,
|
||||
aBaseURI);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -586,9 +589,9 @@ nsXMLHttpRequest::Initialize(nsISupports* aOwner, JSContext* cx, JSObject* obj,
|
||||
// so re-set principal and script context.
|
||||
nsCOMPtr<nsIScriptObjectPrincipal> scriptPrincipal = do_QueryInterface(aOwner);
|
||||
NS_ENSURE_STATE(scriptPrincipal);
|
||||
mPrincipal = scriptPrincipal->GetPrincipal();
|
||||
BindToOwner(owner);
|
||||
return NS_OK;
|
||||
|
||||
Construct(scriptPrincipal->GetPrincipal(), owner);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
@ -1087,6 +1090,15 @@ nsXMLHttpRequest::StaticAssertions()
|
||||
== bindings::prototypes::XMLHttpRequestResponseType::value(XML_HTTP_RESPONSE_TYPE_ ## _uc), \
|
||||
#_uc " should match")
|
||||
|
||||
ASSERT_ENUM_EQUAL(_empty, DEFAULT);
|
||||
ASSERT_ENUM_EQUAL(arraybuffer, ARRAYBUFFER);
|
||||
ASSERT_ENUM_EQUAL(blob, BLOB);
|
||||
ASSERT_ENUM_EQUAL(document, DOCUMENT);
|
||||
ASSERT_ENUM_EQUAL(json, JSON);
|
||||
ASSERT_ENUM_EQUAL(text, TEXT);
|
||||
ASSERT_ENUM_EQUAL(moz_chunked_text, CHUNKED_TEXT);
|
||||
ASSERT_ENUM_EQUAL(moz_chunked_arraybuffer, CHUNKED_ARRAYBUFFER);
|
||||
ASSERT_ENUM_EQUAL(moz_blob, MOZ_BLOB);
|
||||
#undef ASSERT_ENUM_EQUAL
|
||||
}
|
||||
#endif
|
||||
@ -1122,6 +1134,13 @@ NS_IMETHODIMP nsXMLHttpRequest::SetResponseType(const nsAString& aResponseType)
|
||||
return rv;
|
||||
}
|
||||
|
||||
void
|
||||
nsXMLHttpRequest::SetResponseType(XMLHttpRequestResponseType aType,
|
||||
nsresult& aRv)
|
||||
{
|
||||
SetResponseType(ResponseType(aType), aRv);
|
||||
}
|
||||
|
||||
void
|
||||
nsXMLHttpRequest::SetResponseType(nsXMLHttpRequest::ResponseType aResponseType,
|
||||
nsresult& aRv)
|
||||
@ -2706,7 +2725,7 @@ GetRequestBody(nsIVariant* aBody, nsIInputStream** aResult,
|
||||
/* static */
|
||||
nsresult
|
||||
nsXMLHttpRequest::GetRequestBody(nsIVariant* aVariant,
|
||||
const RequestBody* aBody,
|
||||
const Nullable<RequestBody>& aBody,
|
||||
nsIInputStream** aResult,
|
||||
nsACString& aContentType, nsACString& aCharset)
|
||||
{
|
||||
@ -2714,7 +2733,7 @@ nsXMLHttpRequest::GetRequestBody(nsIVariant* aVariant,
|
||||
return ::GetRequestBody(aVariant, aResult, aContentType, aCharset);
|
||||
}
|
||||
|
||||
const RequestBody& body = *aBody;
|
||||
const RequestBody& body = aBody.Value();
|
||||
RequestBody::Value value = body.GetValue();
|
||||
switch (body.GetType()) {
|
||||
case nsXMLHttpRequest::RequestBody::ArrayBuffer:
|
||||
@ -2764,11 +2783,11 @@ nsXMLHttpRequest::GetRequestBody(nsIVariant* aVariant,
|
||||
NS_IMETHODIMP
|
||||
nsXMLHttpRequest::Send(nsIVariant *aBody)
|
||||
{
|
||||
return Send(aBody, nsnull);
|
||||
return Send(aBody, Nullable<RequestBody>());
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsXMLHttpRequest::Send(nsIVariant* aVariant, const RequestBody* aBody)
|
||||
nsXMLHttpRequest::Send(nsIVariant* aVariant, const Nullable<RequestBody>& aBody)
|
||||
{
|
||||
NS_ENSURE_TRUE(mPrincipal, NS_ERROR_NOT_INITIALIZED);
|
||||
|
||||
@ -2885,7 +2904,7 @@ nsXMLHttpRequest::Send(nsIVariant* aVariant, const RequestBody* aBody)
|
||||
mLoadTotal = 0;
|
||||
mUploadProgress = 0;
|
||||
mUploadProgressMax = 0;
|
||||
if ((aVariant || aBody) && httpChannel &&
|
||||
if ((aVariant || !aBody.IsNull()) && httpChannel &&
|
||||
!method.EqualsLiteral("GET")) {
|
||||
|
||||
nsCAutoString charset;
|
||||
@ -3845,6 +3864,20 @@ nsXMLHttpRequest::GetInterface(const nsIID & aIID, void **aResult)
|
||||
return QueryInterface(aIID, aResult);
|
||||
}
|
||||
|
||||
JS::Value
|
||||
nsXMLHttpRequest::GetInterface(JSContext* aCx, nsIJSIID* aIID, nsresult& aRv)
|
||||
{
|
||||
const nsID* iid = aIID->GetID();
|
||||
nsCOMPtr<nsISupports> result;
|
||||
JS::Value v = JSVAL_NULL;
|
||||
aRv = GetInterface(*iid, getter_AddRefs(result));
|
||||
NS_ENSURE_SUCCESS(aRv, JSVAL_NULL);
|
||||
|
||||
JSObject* global = JS_GetGlobalForObject(aCx, GetWrapper());
|
||||
aRv = nsContentUtils::WrapNative(aCx, global, result, iid, &v);
|
||||
return NS_SUCCEEDED(aRv) ? v : JSVAL_NULL;
|
||||
}
|
||||
|
||||
nsXMLHttpRequestUpload*
|
||||
nsXMLHttpRequest::GetUpload()
|
||||
{
|
||||
|
@ -67,16 +67,37 @@
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsDOMFile.h"
|
||||
#include "nsDOMBlobBuilder.h"
|
||||
#include "nsIPrincipal.h"
|
||||
#include "nsIScriptObjectPrincipal.h"
|
||||
#include "mozilla/dom/bindings/XMLHttpRequestBinding.h"
|
||||
#include "mozilla/dom/bindings/XMLHttpRequestUploadBinding.h"
|
||||
|
||||
#include "mozilla/Assertions.h"
|
||||
|
||||
class nsILoadGroup;
|
||||
class AsyncVerifyRedirectCallbackForwarder;
|
||||
class nsIUnicodeDecoder;
|
||||
class nsIDOMFormData;
|
||||
|
||||
#define IMPL_EVENT_HANDLER(_lowercase, _capitalized) \
|
||||
JSObject* GetOn##_lowercase() \
|
||||
{ \
|
||||
return GetListenerAsJSObject(mOn##_capitalized##Listener); \
|
||||
} \
|
||||
void SetOn##_lowercase(JSContext* aCx, JSObject* aCallback, nsresult& aRv) \
|
||||
{ \
|
||||
aRv = SetJSObjectListener(aCx, NS_LITERAL_STRING(#_lowercase), \
|
||||
mOn##_capitalized##Listener, \
|
||||
aCallback); \
|
||||
}
|
||||
|
||||
class nsXHREventTarget : public nsDOMEventTargetHelper,
|
||||
public nsIXMLHttpRequestEventTarget
|
||||
{
|
||||
public:
|
||||
typedef mozilla::dom::bindings::prototypes::XMLHttpRequestResponseType::value
|
||||
XMLHttpRequestResponseType;
|
||||
|
||||
virtual ~nsXHREventTarget() {}
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsXHREventTarget,
|
||||
@ -84,74 +105,14 @@ public:
|
||||
NS_DECL_NSIXMLHTTPREQUESTEVENTTARGET
|
||||
NS_FORWARD_NSIDOMEVENTTARGET(nsDOMEventTargetHelper::)
|
||||
|
||||
JSObject* GetOnloadstart()
|
||||
{
|
||||
return GetListenerAsJSObject(mOnLoadStartListener);
|
||||
}
|
||||
JSObject* GetOnprogress()
|
||||
{
|
||||
return GetListenerAsJSObject(mOnProgressListener);
|
||||
}
|
||||
JSObject* GetOnabort()
|
||||
{
|
||||
return GetListenerAsJSObject(mOnAbortListener);
|
||||
}
|
||||
JSObject* GetOnerror()
|
||||
{
|
||||
return GetListenerAsJSObject(mOnErrorListener);
|
||||
}
|
||||
JSObject* GetOnload()
|
||||
{
|
||||
return GetListenerAsJSObject(mOnLoadListener);
|
||||
}
|
||||
JSObject* GetOntimeout()
|
||||
{
|
||||
return GetListenerAsJSObject(mOnTimeoutListener);
|
||||
}
|
||||
JSObject* GetOnloadend()
|
||||
{
|
||||
return GetListenerAsJSObject(mOnLoadendListener);
|
||||
}
|
||||
void SetOnloadstart(JSObject* aCallback, nsresult& aRv)
|
||||
{
|
||||
aRv = SetJSObjectListener(NS_LITERAL_STRING("loadstart"),
|
||||
mOnLoadStartListener,
|
||||
aCallback);
|
||||
}
|
||||
void SetOnprogress(JSObject* aCallback, nsresult& aRv)
|
||||
{
|
||||
aRv = SetJSObjectListener(NS_LITERAL_STRING("progress"),
|
||||
mOnProgressListener,
|
||||
aCallback);
|
||||
}
|
||||
void SetOnabort(JSObject* aCallback, nsresult& aRv)
|
||||
{
|
||||
aRv = SetJSObjectListener(NS_LITERAL_STRING("abort"), mOnAbortListener,
|
||||
aCallback);
|
||||
}
|
||||
void SetOnerror(JSObject* aCallback, nsresult& aRv)
|
||||
{
|
||||
aRv = SetJSObjectListener(NS_LITERAL_STRING("error"), mOnErrorListener,
|
||||
aCallback);
|
||||
}
|
||||
void SetOnload(JSObject* aCallback, nsresult& aRv)
|
||||
{
|
||||
aRv = SetJSObjectListener(NS_LITERAL_STRING("load"), mOnLoadListener,
|
||||
aCallback);
|
||||
}
|
||||
void SetOntimeout(JSObject* aCallback, nsresult& aRv)
|
||||
{
|
||||
aRv = SetJSObjectListener(NS_LITERAL_STRING("timeout"),
|
||||
mOnTimeoutListener,
|
||||
aCallback);
|
||||
}
|
||||
void SetOnloadend(JSObject* aCallback, nsresult& aRv)
|
||||
{
|
||||
aRv = SetJSObjectListener(NS_LITERAL_STRING("loadend"),
|
||||
mOnLoadendListener,
|
||||
aCallback);
|
||||
}
|
||||
|
||||
IMPL_EVENT_HANDLER(loadstart, LoadStart)
|
||||
IMPL_EVENT_HANDLER(progress, Progress)
|
||||
IMPL_EVENT_HANDLER(abort, Abort)
|
||||
IMPL_EVENT_HANDLER(error, Error)
|
||||
IMPL_EVENT_HANDLER(load, Load)
|
||||
IMPL_EVENT_HANDLER(timeout, Timeout)
|
||||
IMPL_EVENT_HANDLER(loadend, Loadend)
|
||||
|
||||
virtual void DisconnectFromOwner();
|
||||
protected:
|
||||
static inline JSObject* GetListenerAsJSObject(nsDOMEventListenerWrapper* aWrapper)
|
||||
@ -161,20 +122,18 @@ protected:
|
||||
JSObject* obj;
|
||||
return holder && NS_SUCCEEDED(holder->GetJSObject(&obj)) ? obj : nsnull;
|
||||
}
|
||||
inline nsresult SetJSObjectListener(const nsAString& aType,
|
||||
inline nsresult SetJSObjectListener(JSContext* aCx,
|
||||
const nsAString& aType,
|
||||
nsRefPtr<nsDOMEventListenerWrapper>& aWrapper,
|
||||
JSObject* aCallback)
|
||||
{
|
||||
nsresult rv;
|
||||
nsIScriptContext* context = GetContextForEventHandlers(&rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIDOMEventListener> listener;
|
||||
if (aCallback) {
|
||||
rv = nsContentUtils::XPConnect()->WrapJS(context->GetNativeContext(),
|
||||
aCallback,
|
||||
NS_GET_IID(nsIDOMEventListener),
|
||||
getter_AddRefs(listener));
|
||||
nsresult rv =
|
||||
nsContentUtils::XPConnect()->WrapJS(aCx,
|
||||
aCallback,
|
||||
NS_GET_IID(nsIDOMEventListener),
|
||||
getter_AddRefs(listener));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
@ -197,12 +156,23 @@ public:
|
||||
nsXMLHttpRequestUpload(nsDOMEventTargetHelper* aOwner)
|
||||
{
|
||||
BindToOwner(aOwner);
|
||||
SetIsDOMBinding();
|
||||
}
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_FORWARD_NSIXMLHTTPREQUESTEVENTTARGET(nsXHREventTarget::)
|
||||
NS_FORWARD_NSIDOMEVENTTARGET(nsXHREventTarget::)
|
||||
NS_DECL_NSIXMLHTTPREQUESTUPLOAD
|
||||
|
||||
virtual JSObject* WrapObject(JSContext *cx, JSObject *scope,
|
||||
bool *triedToWrap)
|
||||
{
|
||||
return mozilla::dom::bindings::prototypes::XMLHttpRequestUpload::Wrap(cx, scope, this, triedToWrap);
|
||||
}
|
||||
nsISupports* GetParentObject()
|
||||
{
|
||||
return GetOwner();
|
||||
}
|
||||
|
||||
bool HasListeners()
|
||||
{
|
||||
return mListenerManager && mListenerManager->HasListeners();
|
||||
@ -225,6 +195,43 @@ public:
|
||||
nsXMLHttpRequest();
|
||||
virtual ~nsXMLHttpRequest();
|
||||
|
||||
virtual JSObject* WrapObject(JSContext *cx, JSObject *scope,
|
||||
bool *triedToWrap)
|
||||
{
|
||||
return mozilla::dom::bindings::prototypes::XMLHttpRequest::Wrap(cx, scope, this, triedToWrap);
|
||||
}
|
||||
nsISupports* GetParentObject()
|
||||
{
|
||||
return GetOwner();
|
||||
}
|
||||
|
||||
// The WebIDL parser converts constructors into methods called _Constructor.
|
||||
static already_AddRefed<nsXMLHttpRequest>
|
||||
_Constructor(nsISupports* aGlobal, nsresult& aRv)
|
||||
{
|
||||
nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(aGlobal);
|
||||
nsCOMPtr<nsIScriptObjectPrincipal> principal = do_QueryInterface(aGlobal);
|
||||
if (!window || ! principal) {
|
||||
aRv = NS_ERROR_FAILURE;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
nsRefPtr<nsXMLHttpRequest> req = new nsXMLHttpRequest();
|
||||
req->Construct(principal->GetPrincipal(), window);
|
||||
return req.forget();
|
||||
}
|
||||
|
||||
void Construct(nsIPrincipal* aPrincipal,
|
||||
nsPIDOMWindow* aOwnerWindow,
|
||||
nsIURI* aBaseURI = NULL)
|
||||
{
|
||||
MOZ_ASSERT(aPrincipal);
|
||||
MOZ_ASSERT_IF(aOwnerWindow, aOwnerWindow->IsInnerWindow());
|
||||
mPrincipal = aPrincipal;
|
||||
BindToOwner(aOwnerWindow);
|
||||
mBaseURI = aBaseURI;
|
||||
}
|
||||
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
||||
// nsIXMLHttpRequest
|
||||
@ -265,16 +272,7 @@ public:
|
||||
#endif
|
||||
|
||||
// event handler
|
||||
JSObject* GetOnreadystatechange()
|
||||
{
|
||||
return GetListenerAsJSObject(mOnReadystatechangeListener);
|
||||
}
|
||||
void SetOnreadystatechange(JSObject* aCallback, nsresult& aRv)
|
||||
{
|
||||
aRv = SetJSObjectListener(NS_LITERAL_STRING("readystatechange"),
|
||||
mOnReadystatechangeListener,
|
||||
aCallback);
|
||||
}
|
||||
IMPL_EVENT_HANDLER(readystatechange, Readystatechange)
|
||||
|
||||
// states
|
||||
uint16_t GetReadyState();
|
||||
@ -368,21 +366,25 @@ private:
|
||||
};
|
||||
|
||||
static nsresult GetRequestBody(nsIVariant* aVariant,
|
||||
const RequestBody* aBody,
|
||||
const Nullable<RequestBody>& aBody,
|
||||
nsIInputStream** aResult,
|
||||
nsACString& aContentType,
|
||||
nsACString& aCharset);
|
||||
|
||||
nsresult Send(nsIVariant* aVariant, const RequestBody* aBody);
|
||||
nsresult Send(nsIVariant* aVariant, const Nullable<RequestBody>& aBody);
|
||||
nsresult Send(const Nullable<RequestBody>& aBody)
|
||||
{
|
||||
return Send(nsnull, aBody);
|
||||
}
|
||||
nsresult Send(const RequestBody& aBody)
|
||||
{
|
||||
return Send(nsnull, &aBody);
|
||||
return Send(Nullable<RequestBody>(aBody));
|
||||
}
|
||||
|
||||
public:
|
||||
void Send(nsresult& aRv)
|
||||
{
|
||||
aRv = Send(nsnull, nsnull);
|
||||
aRv = Send(Nullable<RequestBody>());
|
||||
}
|
||||
void Send(JSObject* aArrayBuffer, nsresult& aRv)
|
||||
{
|
||||
@ -449,6 +451,11 @@ public:
|
||||
// XXX Should we do some validation here?
|
||||
mOverrideMimeType = aMimeType;
|
||||
}
|
||||
XMLHttpRequestResponseType GetResponseType()
|
||||
{
|
||||
return XMLHttpRequestResponseType(mResponseType);
|
||||
}
|
||||
void SetResponseType(XMLHttpRequestResponseType aType, nsresult& aRv);
|
||||
JS::Value GetResponse(JSContext* aCx, nsresult& aRv);
|
||||
void GetResponseText(nsString& aResponseText, nsresult& aRv);
|
||||
nsIDocument* GetResponseXML(nsresult& aRv);
|
||||
@ -463,6 +470,9 @@ public:
|
||||
return mChannel;
|
||||
}
|
||||
|
||||
// We need a GetInterface callable from JS for chrome JS
|
||||
JS::Value GetInterface(JSContext*aCx, nsIJSIID* aIID, nsresult& aRv);
|
||||
|
||||
// This creates a trusted readystatechange event, which is not cancelable and
|
||||
// doesn't bubble.
|
||||
static nsresult CreateReadystatechangeEvent(nsIDOMEvent** aDOMEvent);
|
||||
@ -712,6 +722,8 @@ protected:
|
||||
nsTArray<RequestHeader> mModifiedRequestHeaders;
|
||||
};
|
||||
|
||||
#undef IMPL_EVENT_HANDLER
|
||||
|
||||
// helper class to expose a progress DOM Event
|
||||
|
||||
class nsXMLHttpProgressEvent : public nsIDOMProgressEvent,
|
||||
|
@ -25,7 +25,7 @@ req.mozBackgroundRequest = true;
|
||||
req.open("GET", window.location.href);
|
||||
req.send(null);
|
||||
|
||||
ok(req.channel.loadGroup == null, "loadGroup is null");
|
||||
ok(SpecialPowers.wrap(req).channel.loadGroup == null, "loadGroup is null");
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
|
@ -23,8 +23,7 @@ req.open("POST", window.location.href);
|
||||
req.setRequestHeader("Content-Type", "text/plain; charset=us-ascii; boundary=01234567890");
|
||||
req.send("Some text");
|
||||
|
||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||
is(req.channel
|
||||
is(SpecialPowers.wrap(req).channel
|
||||
.QueryInterface(Components.interfaces.nsIHttpChannel)
|
||||
.getRequestHeader("Content-Type"),
|
||||
"text/plain; charset=UTF-8; boundary=01234567890",
|
||||
|
@ -24,8 +24,7 @@ req.open("POST", window.location.href);
|
||||
req.setRequestHeader("Content-Type", "text/plain; charset='uTf-8'");
|
||||
req.send("Some text");
|
||||
|
||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||
is(req.channel
|
||||
is(SpecialPowers.wrap(req).channel
|
||||
.QueryInterface(Components.interfaces.nsIHttpChannel)
|
||||
.getRequestHeader("Content-Type"),
|
||||
"text/plain; charset='uTf-8'",
|
||||
|
@ -23,8 +23,7 @@ req.open("POST", window.location.href);
|
||||
req.setRequestHeader("Content-Type", "text/plain; boundary=01234567890");
|
||||
req.send("Some text");
|
||||
|
||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||
is(req.channel
|
||||
is(SpecialPowers.wrap(req).channel
|
||||
.QueryInterface(Components.interfaces.nsIHttpChannel)
|
||||
.getRequestHeader("Content-Type"),
|
||||
"text/plain; charset=UTF-8; boundary=01234567890",
|
||||
|
@ -36,7 +36,7 @@ for each (var i in body) {
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open("POST", url, true);
|
||||
xhr.send(i);
|
||||
var chan = xhr.channel;
|
||||
var chan = SpecialPowers.unwrap(SpecialPowers.wrap(xhr).channel);
|
||||
if (!(chan instanceof Components.interfaces.nsIUploadChannel))
|
||||
throw "Must be an upload channel";
|
||||
var stream = chan.uploadStream;
|
||||
|
@ -98,8 +98,7 @@ addLoadEvent(function() {
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open("POST", document.location.href);
|
||||
xhr.send(createDoc());
|
||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||
is(xhr.channel.QueryInterface(Components.interfaces.nsIHttpChannel)
|
||||
is(SpecialPowers.wrap(xhr).channel.QueryInterface(Components.interfaces.nsIHttpChannel)
|
||||
.getRequestHeader("Content-Type"),
|
||||
"application/xml; charset=UTF-8", "Testing correct type on the wire");
|
||||
xhr.abort();
|
||||
|
@ -17,8 +17,7 @@ var path = "http://mochi.test:8888/tests/content/base/test/";
|
||||
|
||||
function fromCache(xhr)
|
||||
{
|
||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||
var ch = xhr.channel.QueryInterface(Components.interfaces.nsICachingChannel);
|
||||
var ch = SpecialPowers.wrap(xhr).channel.QueryInterface(Components.interfaces.nsICachingChannel);
|
||||
return ch.isFromCache();
|
||||
}
|
||||
|
||||
|
@ -231,6 +231,11 @@ if (false) {
|
||||
testClipboardValue("text/html", "<div id=\"div13\">__</div>");
|
||||
testPasteText("__");
|
||||
|
||||
// ============ converting cell boundaries to tabs in tables
|
||||
|
||||
copyToClipboard($("tr1"));
|
||||
testClipboardValue("text/unicode", "foo\tbar");
|
||||
|
||||
// ============ manipulating Selection in oncopy
|
||||
|
||||
copyRangeToClipboard($("div11").childNodes[0],0, $("div11").childNodes[1],2);
|
||||
@ -320,6 +325,8 @@ x.appendChild(document.createTextNode('10'))
|
||||
|
||||
<div id="div13">_<noscript>FAIL</noscript>_</div>
|
||||
|
||||
<table><tr id=tr1><td>foo</td><td>bar</td></tr></table>
|
||||
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -55,8 +55,7 @@ for (i = 0; i < headers.length; i++)
|
||||
request.setRequestHeader(headers[i], "test" + i);
|
||||
|
||||
// Read out headers
|
||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||
var channel = request.channel.QueryInterface(Components.interfaces.nsIHttpChannel);
|
||||
var channel = SpecialPowers.wrap(request).channel.QueryInterface(Components.interfaces.nsIHttpChannel);
|
||||
for (i = 0; i < headers.length; i++) {
|
||||
// Retrieving Content-Length will throw an exception
|
||||
var value = null;
|
||||
@ -69,13 +68,14 @@ for (i = 0; i < headers.length; i++) {
|
||||
}
|
||||
|
||||
// Try setting headers in privileged context
|
||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||
request = new XMLHttpRequest();
|
||||
request.open("GET", window.location.href);
|
||||
for (i = 0; i < headers.length; i++)
|
||||
request.setRequestHeader(headers[i], "test" + i);
|
||||
|
||||
// Read out headers
|
||||
var channel = request.channel.QueryInterface(Components.interfaces.nsIHttpChannel);
|
||||
var channel = SpecialPowers.wrap(request).channel.QueryInterface(Components.interfaces.nsIHttpChannel);
|
||||
for (i = 0; i < headers.length; i++) {
|
||||
var value = channel.getRequestHeader(headers[i]);
|
||||
is(value, "test" + i, "Setting " + headers[i] + " header in privileged context");
|
||||
|
@ -579,14 +579,6 @@ WebGLContext::InitAndValidateGL()
|
||||
gl->fGetIntegerv(LOCAL_GL_MAX_TEXTURE_IMAGE_UNITS, &mGLMaxTextureImageUnits);
|
||||
gl->fGetIntegerv(LOCAL_GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &mGLMaxVertexTextureImageUnits);
|
||||
}
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
if (gl->Vendor() == gl::GLContext::VendorIntel) {
|
||||
// bug 684882, corruption in large cube maps on Intel Mac driver.
|
||||
// Is reported to only affect Mac OS < 10.7.2 but don't want to rely on that yet.
|
||||
mGLMaxCubeMapTextureSize = NS_MIN(mGLMaxCubeMapTextureSize, 512);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (MinCapabilityMode()) {
|
||||
mGLMaxFragmentUniformVectors = MINVALUE_GL_MAX_FRAGMENT_UNIFORM_VECTORS;
|
||||
|
@ -77,6 +77,27 @@ public:
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(nsDOMEventTargetHelper)
|
||||
|
||||
NS_DECL_NSIDOMEVENTTARGET
|
||||
void AddEventListener(const nsAString& aType,
|
||||
nsIDOMEventListener* aCallback, // XXX nullable
|
||||
bool aCapture, Nullable<bool>& aWantsUntrusted,
|
||||
nsresult& aRv)
|
||||
{
|
||||
aRv = AddEventListener(aType, aCallback, aCapture,
|
||||
!aWantsUntrusted.IsNull() && aWantsUntrusted.Value(),
|
||||
aWantsUntrusted.IsNull() ? 1 : 2);
|
||||
}
|
||||
void RemoveEventListener(const nsAString& aType,
|
||||
nsIDOMEventListener* aCallback,
|
||||
bool aCapture, nsresult& aRv)
|
||||
{
|
||||
aRv = RemoveEventListener(aType, aCallback, aCapture);
|
||||
}
|
||||
bool DispatchEvent(nsIDOMEvent* aEvent, nsresult& aRv)
|
||||
{
|
||||
bool result = false;
|
||||
aRv = DispatchEvent(aEvent, &result);
|
||||
return result;
|
||||
}
|
||||
|
||||
void GetParentObject(nsIScriptGlobalObject **aParentObject)
|
||||
{
|
||||
|
@ -277,6 +277,10 @@ public:
|
||||
// false here even if CanHandleMediaType would return true.
|
||||
static bool ShouldHandleMediaType(const char* aMIMEType);
|
||||
|
||||
#ifdef MOZ_RAW
|
||||
static bool IsRawEnabled();
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_OGG
|
||||
static bool IsOggEnabled();
|
||||
static bool IsOggType(const nsACString& aType);
|
||||
|
@ -1712,14 +1712,15 @@ static const char* gRawCodecs[] = {
|
||||
nsnull
|
||||
};
|
||||
|
||||
static bool IsRawEnabled()
|
||||
bool
|
||||
nsHTMLMediaElement::IsRawEnabled()
|
||||
{
|
||||
return Preferences::GetBool("media.raw.enabled");
|
||||
}
|
||||
|
||||
static bool IsRawType(const nsACString& aType)
|
||||
{
|
||||
if (!IsRawEnabled()) {
|
||||
if (!nsHTMLMediaElement::IsRawEnabled()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -150,8 +150,6 @@ const PRInt32 kBackward = 1;
|
||||
|
||||
//#define DEBUG_charset
|
||||
|
||||
#define NS_USE_NEW_PLAIN_TEXT 1
|
||||
|
||||
static NS_DEFINE_CID(kCParserCID, NS_PARSER_CID);
|
||||
|
||||
PRUint32 nsHTMLDocument::gWyciwygSessionCnt = 0;
|
||||
@ -560,51 +558,56 @@ nsHTMLDocument::StartDocumentLoad(const char* aCommand,
|
||||
bool aReset,
|
||||
nsIContentSink* aSink)
|
||||
{
|
||||
if (!aCommand) {
|
||||
MOZ_NOT_REACHED("Command is mandatory");
|
||||
return NS_ERROR_INVALID_POINTER;
|
||||
}
|
||||
if (aSink) {
|
||||
MOZ_NOT_REACHED("Got a sink override. Should not happen for HTML doc.");
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
if (!mIsRegularHTML) {
|
||||
MOZ_NOT_REACHED("Must not set HTML doc to XHTML mode before load start.");
|
||||
return NS_ERROR_DOM_INVALID_STATE_ERR;
|
||||
}
|
||||
|
||||
nsCAutoString contentType;
|
||||
aChannel->GetContentType(contentType);
|
||||
|
||||
bool viewSource = aCommand && !nsCRT::strcmp(aCommand, "view-source");
|
||||
bool plainText = (contentType.EqualsLiteral(TEXT_PLAIN) ||
|
||||
bool view = !strcmp(aCommand, "view") ||
|
||||
!strcmp(aCommand, "external-resource");
|
||||
bool viewSource = !strcmp(aCommand, "view-source");
|
||||
bool asData = !strcmp(aCommand, kLoadAsData);
|
||||
if(!(view || viewSource || asData)) {
|
||||
MOZ_NOT_REACHED("Bad parser command");
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
bool html = contentType.EqualsLiteral(TEXT_HTML);
|
||||
bool xhtml = !html && contentType.Equals("application/xhtml+xml");
|
||||
bool plainText = !html && !xhtml && (contentType.EqualsLiteral(TEXT_PLAIN) ||
|
||||
contentType.EqualsLiteral(TEXT_CSS) ||
|
||||
contentType.EqualsLiteral(APPLICATION_JAVASCRIPT) ||
|
||||
contentType.EqualsLiteral(APPLICATION_XJAVASCRIPT) ||
|
||||
contentType.EqualsLiteral(TEXT_ECMASCRIPT) ||
|
||||
contentType.EqualsLiteral(APPLICATION_ECMASCRIPT) ||
|
||||
contentType.EqualsLiteral(TEXT_JAVASCRIPT));
|
||||
bool loadAsHtml5 = nsHtml5Module::sEnabled || viewSource || plainText;
|
||||
if (!NS_USE_NEW_PLAIN_TEXT && !viewSource) {
|
||||
plainText = false;
|
||||
if (!(html || xhtml || plainText || viewSource)) {
|
||||
MOZ_NOT_REACHED("Channel with bad content type.");
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
NS_ASSERTION(!(plainText && aSink),
|
||||
"Someone tries to load plain text into a custom sink.");
|
||||
bool loadAsHtml5 = true;
|
||||
|
||||
if (aSink) {
|
||||
loadAsHtml5 = false;
|
||||
}
|
||||
|
||||
if (contentType.Equals("application/xhtml+xml") && !viewSource) {
|
||||
// We're parsing XHTML as XML, remember that.
|
||||
|
||||
mIsRegularHTML = false;
|
||||
mCompatMode = eCompatibility_FullStandards;
|
||||
loadAsHtml5 = false;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
else {
|
||||
NS_ASSERTION(mIsRegularHTML,
|
||||
"Hey, someone forgot to reset mIsRegularHTML!!!");
|
||||
}
|
||||
#endif
|
||||
|
||||
if (loadAsHtml5 && !viewSource &&
|
||||
(!(contentType.EqualsLiteral("text/html") || plainText) &&
|
||||
aCommand && !nsCRT::strcmp(aCommand, "view"))) {
|
||||
loadAsHtml5 = false;
|
||||
if (!viewSource && xhtml) {
|
||||
// We're parsing XHTML as XML, remember that.
|
||||
mIsRegularHTML = false;
|
||||
mCompatMode = eCompatibility_FullStandards;
|
||||
loadAsHtml5 = false;
|
||||
}
|
||||
|
||||
// TODO: Proper about:blank treatment is bug 543435
|
||||
if (loadAsHtml5 && aCommand && !nsCRT::strcmp(aCommand, "view")) {
|
||||
if (loadAsHtml5 && view) {
|
||||
// mDocumentURI hasn't been set, yet, so get the URI from the channel
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
aChannel->GetOriginalURI(getter_AddRefs(uri));
|
||||
@ -622,14 +625,6 @@ nsHTMLDocument::StartDocumentLoad(const char* aCommand,
|
||||
|
||||
CSSLoader()->SetCompatibilityMode(mCompatMode);
|
||||
|
||||
bool needsParser = true;
|
||||
if (aCommand)
|
||||
{
|
||||
if (!nsCRT::strcmp(aCommand, "view delayedContentLoad")) {
|
||||
needsParser = false;
|
||||
}
|
||||
}
|
||||
|
||||
nsresult rv = nsDocument::StartDocumentLoad(aCommand,
|
||||
aChannel, aLoadGroup,
|
||||
aContainer,
|
||||
@ -649,24 +644,22 @@ nsHTMLDocument::StartDocumentLoad(const char* aCommand,
|
||||
|
||||
nsCOMPtr<nsICachingChannel> cachingChan = do_QueryInterface(aChannel);
|
||||
|
||||
if (needsParser) {
|
||||
if (loadAsHtml5) {
|
||||
mParser = nsHtml5Module::NewHtml5Parser();
|
||||
if (plainText) {
|
||||
if (viewSource) {
|
||||
mParser->MarkAsNotScriptCreated("view-source-plain");
|
||||
} else {
|
||||
mParser->MarkAsNotScriptCreated("plain-text");
|
||||
}
|
||||
} else if (viewSource && !contentType.EqualsLiteral("text/html")) {
|
||||
mParser->MarkAsNotScriptCreated("view-source-xml");
|
||||
if (loadAsHtml5) {
|
||||
mParser = nsHtml5Module::NewHtml5Parser();
|
||||
if (plainText) {
|
||||
if (viewSource) {
|
||||
mParser->MarkAsNotScriptCreated("view-source-plain");
|
||||
} else {
|
||||
mParser->MarkAsNotScriptCreated(aCommand);
|
||||
mParser->MarkAsNotScriptCreated("plain-text");
|
||||
}
|
||||
} else if (viewSource && !html) {
|
||||
mParser->MarkAsNotScriptCreated("view-source-xml");
|
||||
} else {
|
||||
mParser = do_CreateInstance(kCParserCID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
mParser->MarkAsNotScriptCreated(aCommand);
|
||||
}
|
||||
} else {
|
||||
mParser = do_CreateInstance(kCParserCID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
PRInt32 textType = GET_BIDI_OPTION_TEXTTYPE(GetBidiOptions());
|
||||
@ -852,55 +845,38 @@ nsHTMLDocument::StartDocumentLoad(const char* aCommand,
|
||||
}
|
||||
|
||||
// Set the parser as the stream listener for the document loader...
|
||||
if (mParser) {
|
||||
rv = NS_OK;
|
||||
nsCOMPtr<nsIStreamListener> listener = mParser->GetStreamListener();
|
||||
listener.forget(aDocListener);
|
||||
rv = NS_OK;
|
||||
nsCOMPtr<nsIStreamListener> listener = mParser->GetStreamListener();
|
||||
listener.forget(aDocListener);
|
||||
|
||||
#ifdef DEBUG_charset
|
||||
printf(" charset = %s source %d\n",
|
||||
charset.get(), charsetSource);
|
||||
printf(" charset = %s source %d\n",
|
||||
charset.get(), charsetSource);
|
||||
#endif
|
||||
mParser->SetDocumentCharset(parserCharset, parserCharsetSource);
|
||||
mParser->SetCommand(aCommand);
|
||||
mParser->SetDocumentCharset(parserCharset, parserCharsetSource);
|
||||
mParser->SetCommand(aCommand);
|
||||
|
||||
// create the content sink
|
||||
nsCOMPtr<nsIContentSink> sink;
|
||||
|
||||
if (aSink) {
|
||||
NS_ASSERTION(!loadAsHtml5, "Panic: We are loading as HTML5 and someone tries to set an external sink!");
|
||||
sink = aSink;
|
||||
if (!IsHTML()) {
|
||||
MOZ_ASSERT(!loadAsHtml5);
|
||||
nsCOMPtr<nsIXMLContentSink> xmlsink;
|
||||
NS_NewXMLContentSink(getter_AddRefs(xmlsink), this, uri,
|
||||
docShell, aChannel);
|
||||
mParser->SetContentSink(xmlsink);
|
||||
} else {
|
||||
if (loadAsHtml5) {
|
||||
nsHtml5Module::Initialize(mParser, this, uri, docShell, aChannel);
|
||||
} else {
|
||||
if (!IsHTML()) {
|
||||
nsCOMPtr<nsIXMLContentSink> xmlsink;
|
||||
rv = NS_NewXMLContentSink(getter_AddRefs(xmlsink), this, uri,
|
||||
docShell, aChannel);
|
||||
|
||||
sink = xmlsink;
|
||||
} else {
|
||||
if (loadAsHtml5) {
|
||||
nsHtml5Module::Initialize(mParser, this, uri, docShell, aChannel);
|
||||
sink = mParser->GetContentSink();
|
||||
} else {
|
||||
nsCOMPtr<nsIHTMLContentSink> htmlsink;
|
||||
|
||||
rv = NS_NewHTMLContentSink(getter_AddRefs(htmlsink), this, uri,
|
||||
docShell, aChannel);
|
||||
|
||||
sink = htmlsink;
|
||||
}
|
||||
}
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
NS_ASSERTION(sink,
|
||||
"null sink with successful result from factory method");
|
||||
// about:blank *only*
|
||||
nsCOMPtr<nsIHTMLContentSink> htmlsink;
|
||||
NS_NewHTMLContentSink(getter_AddRefs(htmlsink), this, uri,
|
||||
docShell, aChannel);
|
||||
mParser->SetContentSink(htmlsink);
|
||||
}
|
||||
|
||||
mParser->SetContentSink(sink);
|
||||
// parser the content of the URI
|
||||
mParser->Parse(uri, nsnull, (void *)this);
|
||||
}
|
||||
|
||||
// parser the content of the URI
|
||||
mParser->Parse(uri, nsnull, (void *)this);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
@ -1560,35 +1536,13 @@ nsHTMLDocument::Open(const nsAString& aContentTypeOrUrl,
|
||||
mSecurityInfo = securityInfo;
|
||||
|
||||
mParserAborted = false;
|
||||
bool loadAsHtml5 = nsHtml5Module::sEnabled;
|
||||
if (loadAsHtml5) {
|
||||
mParser = nsHtml5Module::NewHtml5Parser();
|
||||
rv = NS_OK;
|
||||
} else {
|
||||
mParser = do_CreateInstance(kCParserCID, &rv);
|
||||
}
|
||||
mParser = nsHtml5Module::NewHtml5Parser();
|
||||
nsHtml5Module::Initialize(mParser, this, uri, shell, channel);
|
||||
rv = NS_OK;
|
||||
|
||||
// This will be propagated to the parser when someone actually calls write()
|
||||
SetContentTypeInternal(contentType);
|
||||
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
if (loadAsHtml5) {
|
||||
nsHtml5Module::Initialize(mParser, this, uri, shell, channel);
|
||||
} else {
|
||||
nsCOMPtr<nsIHTMLContentSink> sink;
|
||||
|
||||
rv = NS_NewHTMLContentSink(getter_AddRefs(sink), this, uri, shell,
|
||||
channel);
|
||||
if (NS_FAILED(rv)) {
|
||||
// Don't use a parser without a content sink.
|
||||
mParser = nsnull;
|
||||
return rv;
|
||||
}
|
||||
|
||||
mParser->SetContentSink(sink);
|
||||
}
|
||||
}
|
||||
|
||||
// Prepare the docshell and the document viewer for the impending
|
||||
// out of band document.write()
|
||||
shell->PrepareForNewContentModel();
|
||||
@ -2271,21 +2225,17 @@ nsHTMLDocument::GenerateParserKey(void)
|
||||
|
||||
// The script loader provides us with the currently executing script element,
|
||||
// which is guaranteed to be unique per script.
|
||||
if (nsHtml5Module::sEnabled) {
|
||||
nsIScriptElement* script = mScriptLoader->GetCurrentParserInsertedScript();
|
||||
if (script && mParser && mParser->IsScriptCreated()) {
|
||||
nsCOMPtr<nsIParser> creatorParser = script->GetCreatorParser();
|
||||
if (creatorParser != mParser) {
|
||||
// Make scripts that aren't inserted by the active parser of this document
|
||||
// participate in the context of the script that document.open()ed
|
||||
// this document.
|
||||
return nsnull;
|
||||
}
|
||||
nsIScriptElement* script = mScriptLoader->GetCurrentParserInsertedScript();
|
||||
if (script && mParser && mParser->IsScriptCreated()) {
|
||||
nsCOMPtr<nsIParser> creatorParser = script->GetCreatorParser();
|
||||
if (creatorParser != mParser) {
|
||||
// Make scripts that aren't inserted by the active parser of this document
|
||||
// participate in the context of the script that document.open()ed
|
||||
// this document.
|
||||
return nsnull;
|
||||
}
|
||||
return script;
|
||||
} else {
|
||||
return mScriptLoader->GetCurrentScript();
|
||||
}
|
||||
return script;
|
||||
}
|
||||
|
||||
/* attribute DOMString designMode; */
|
||||
|
@ -44,7 +44,12 @@
|
||||
class nsOggDecoder : public nsBuiltinDecoder
|
||||
{
|
||||
public:
|
||||
virtual nsMediaDecoder* Clone() { return new nsOggDecoder(); }
|
||||
virtual nsMediaDecoder* Clone() {
|
||||
if (!nsHTMLMediaElement::IsOggEnabled()) {
|
||||
return nsnull;
|
||||
}
|
||||
return new nsOggDecoder();
|
||||
}
|
||||
virtual nsDecoderStateMachine* CreateStateMachine();
|
||||
};
|
||||
|
||||
|
@ -42,7 +42,12 @@
|
||||
class nsRawDecoder : public nsBuiltinDecoder
|
||||
{
|
||||
public:
|
||||
virtual nsMediaDecoder* Clone() { return new nsRawDecoder(); }
|
||||
virtual nsMediaDecoder* Clone() {
|
||||
if (!nsHTMLMediaElement::IsRawEnabled()) {
|
||||
return nsnull;
|
||||
}
|
||||
return new nsRawDecoder();
|
||||
}
|
||||
virtual nsDecoderStateMachine* CreateStateMachine();
|
||||
};
|
||||
|
||||
|
@ -55,8 +55,13 @@
|
||||
class nsWaveDecoder : public nsBuiltinDecoder
|
||||
{
|
||||
public:
|
||||
virtual nsMediaDecoder* Clone() { return new nsWaveDecoder(); }
|
||||
virtual nsDecoderStateMachine* CreateStateMachine();
|
||||
virtual nsMediaDecoder* Clone() {
|
||||
if (!nsHTMLMediaElement::IsWaveEnabled()) {
|
||||
return nsnull;
|
||||
}
|
||||
return new nsWaveDecoder();
|
||||
}
|
||||
virtual nsDecoderStateMachine* CreateStateMachine();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -44,7 +44,12 @@
|
||||
class nsWebMDecoder : public nsBuiltinDecoder
|
||||
{
|
||||
public:
|
||||
virtual nsMediaDecoder* Clone() { return new nsWebMDecoder(); }
|
||||
virtual nsMediaDecoder* Clone() {
|
||||
if (!nsHTMLMediaElement::IsWebMEnabled()) {
|
||||
return nsnull;
|
||||
}
|
||||
return new nsWebMDecoder();
|
||||
}
|
||||
virtual nsDecoderStateMachine* CreateStateMachine();
|
||||
};
|
||||
|
||||
|
@ -90,6 +90,7 @@ LOCAL_INCLUDES = \
|
||||
-I$(srcdir)/../../../layout/style \
|
||||
-I$(srcdir)/../../../dom/base \
|
||||
-I$(topsrcdir)/xpcom/ds \
|
||||
-I$(topsrcdir)/js/xpconnect/src \
|
||||
$(NULL)
|
||||
|
||||
DEFINES += -D_IMPL_NS_LAYOUT
|
||||
|
@ -59,10 +59,13 @@
|
||||
#include "mozilla/scache/StartupCache.h"
|
||||
#include "mozilla/scache/StartupCacheUtils.h"
|
||||
#include "nsCCUncollectableMarker.h"
|
||||
#include "mozilla/dom/bindings/Utils.h"
|
||||
|
||||
using namespace mozilla::scache;
|
||||
using namespace mozilla;
|
||||
|
||||
using mozilla::dom::bindings::DestroyProtoOrIfaceCache;
|
||||
|
||||
static const char kXBLCachePrefix[] = "xblcache";
|
||||
|
||||
static NS_DEFINE_CID(kDOMScriptObjectFactoryCID, NS_DOM_SCRIPT_OBJECT_FACTORY_CID);
|
||||
@ -180,6 +183,8 @@ nsXBLDocGlobalObject_finalize(JSContext *cx, JSObject *obj)
|
||||
|
||||
// The addref was part of JSObject construction
|
||||
NS_RELEASE(nativeThis);
|
||||
|
||||
DestroyProtoOrIfaceCache(obj);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
|
@ -76,6 +76,8 @@ LOCAL_INCLUDES = -I$(srcdir)/../../../base/src \
|
||||
-I$(srcdir)/../../../xbl/src \
|
||||
-I$(srcdir)/../../../events/src \
|
||||
-I$(topsrcdir)/xpcom/ds \
|
||||
-I$(topsrcdir)/js/xpconnect/src \
|
||||
-I$(topsrcdir)/dom/base \
|
||||
$(NULL)
|
||||
|
||||
DEFINES += -D_IMPL_NS_LAYOUT
|
||||
|
@ -66,6 +66,9 @@
|
||||
#include "nsCCUncollectableMarker.h"
|
||||
#include "nsDOMJSUtils.h" // for GetScriptContextFromJSContext
|
||||
#include "xpcpublic.h"
|
||||
#include "mozilla/dom/bindings/Utils.h"
|
||||
|
||||
using mozilla::dom::bindings::DestroyProtoOrIfaceCache;
|
||||
|
||||
static NS_DEFINE_CID(kDOMScriptObjectFactoryCID,
|
||||
NS_DOM_SCRIPT_OBJECT_FACTORY_CID);
|
||||
@ -129,6 +132,8 @@ nsXULPDGlobalObject_finalize(JSContext *cx, JSObject *obj)
|
||||
|
||||
// The addref was part of JSObject construction
|
||||
NS_RELEASE(nativeThis);
|
||||
|
||||
DestroyProtoOrIfaceCache(obj);
|
||||
}
|
||||
|
||||
|
||||
|
@ -76,6 +76,7 @@ DIRS += \
|
||||
|
||||
DIRS += \
|
||||
base \
|
||||
bindings \
|
||||
battery \
|
||||
contacts \
|
||||
power \
|
||||
|
@ -948,7 +948,7 @@ Navigator::GetMozBattery(nsIDOMMozBatteryManager** aBattery)
|
||||
*aBattery = nsnull;
|
||||
|
||||
nsCOMPtr<nsPIDOMWindow> win(do_QueryReferent(mWindow));
|
||||
NS_ENSURE_TRUE(win->GetDocShell(), NS_OK);
|
||||
NS_ENSURE_TRUE(win && win->GetDocShell(), NS_OK);
|
||||
|
||||
mBatteryManager = new battery::BatteryManager();
|
||||
mBatteryManager->Init(win);
|
||||
|
@ -57,6 +57,8 @@
|
||||
#include "xpcprivate.h"
|
||||
#include "XPCWrapper.h"
|
||||
|
||||
#include "mozilla/dom/bindings/Common.h"
|
||||
|
||||
#include "nscore.h"
|
||||
#include "nsDOMClassInfo.h"
|
||||
#include "nsCRT.h"
|
||||
@ -640,7 +642,6 @@ DOMCI_DATA(DOMConstructor, void)
|
||||
0, \
|
||||
false, \
|
||||
false, \
|
||||
NULL, \
|
||||
NS_DEFINE_CLASSINFO_DATA_DEBUG(_class) \
|
||||
},
|
||||
|
||||
@ -657,7 +658,6 @@ DOMCI_DATA(DOMConstructor, void)
|
||||
0, \
|
||||
true, \
|
||||
false, \
|
||||
NULL, \
|
||||
NS_DEFINE_CLASSINFO_DATA_DEBUG(_class) \
|
||||
},
|
||||
|
||||
@ -4484,7 +4484,11 @@ nsDOMClassInfo::Init()
|
||||
sDisableGlobalScopePollutionSupport =
|
||||
Preferences::GetBool("browser.dom.global_scope_pollution.disabled");
|
||||
|
||||
mozilla::dom::binding::Register(sClassInfoData);
|
||||
// Proxy bindings
|
||||
mozilla::dom::binding::Register(nameSpaceManager);
|
||||
|
||||
// Non-proxy bindings
|
||||
mozilla::dom::bindings::Register(nameSpaceManager);
|
||||
|
||||
sIsInitialized = true;
|
||||
|
||||
@ -6590,6 +6594,15 @@ nsWindowSH::GlobalResolve(nsGlobalWindow *aWin, JSContext *cx,
|
||||
// We're resolving a name of a DOM interface for which there is no
|
||||
// direct DOM class, create a constructor object...
|
||||
|
||||
// Lookup new DOM bindings.
|
||||
mozilla::dom::binding::DefineInterface define =
|
||||
name_struct->mDefineDOMInterface;
|
||||
if (define && mozilla::dom::binding::DefineConstructor(cx, obj, define, &rv)) {
|
||||
*did_resolve = NS_SUCCEEDED(rv);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsRefPtr<nsDOMConstructor> constructor;
|
||||
rv = nsDOMConstructor::Create(class_name,
|
||||
nsnull,
|
||||
@ -6647,7 +6660,7 @@ nsWindowSH::GlobalResolve(nsGlobalWindow *aWin, JSContext *cx,
|
||||
// Lookup new DOM bindings.
|
||||
if (name_struct->mType == nsGlobalNameStruct::eTypeClassConstructor) {
|
||||
mozilla::dom::binding::DefineInterface define =
|
||||
sClassInfoData[name_struct->mDOMClassInfoID].mDefineDOMInterface;
|
||||
name_struct->mDefineDOMInterface;
|
||||
if (define && mozilla::dom::binding::DefineConstructor(cx, obj, define, &rv)) {
|
||||
*did_resolve = NS_SUCCEEDED(rv);
|
||||
|
||||
@ -6686,6 +6699,16 @@ nsWindowSH::GlobalResolve(nsGlobalWindow *aWin, JSContext *cx,
|
||||
if (name_struct->mType == nsGlobalNameStruct::eTypeClassProto) {
|
||||
// We don't have a XPConnect prototype object, let ResolvePrototype create
|
||||
// one.
|
||||
|
||||
// Lookup new DOM bindings.
|
||||
mozilla::dom::binding::DefineInterface define =
|
||||
name_struct->mDefineDOMInterface;
|
||||
if (define && mozilla::dom::binding::DefineConstructor(cx, obj, define, &rv)) {
|
||||
*did_resolve = NS_SUCCEEDED(rv);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
return ResolvePrototype(sXPConnect, aWin, cx, obj, class_name, nsnull,
|
||||
name_struct, nameSpaceManager, nsnull, true,
|
||||
did_resolve);
|
||||
@ -7856,10 +7879,6 @@ NS_IMETHODIMP
|
||||
nsEventTargetSH::AddProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
|
||||
JSObject *obj, jsid id, jsval *vp, bool *_retval)
|
||||
{
|
||||
if (id == sAddEventListener_id) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsEventTargetSH::PreserveWrapper(GetNative(wrapper, obj));
|
||||
|
||||
return NS_OK;
|
||||
|
@ -103,8 +103,6 @@ struct nsDOMClassInfoData
|
||||
PRUint32 mInterfacesBitmap;
|
||||
bool mChromeOnly;
|
||||
bool mDisabled;
|
||||
// For new style DOM bindings.
|
||||
mozilla::dom::binding::DefineInterface mDefineDOMInterface;
|
||||
#ifdef NS_DEBUG
|
||||
PRUint32 mDebugID;
|
||||
#endif
|
||||
|
@ -108,6 +108,7 @@
|
||||
#include "mozilla/FunctionTimer.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/Telemetry.h"
|
||||
#include "mozilla/dom/bindings/Utils.h"
|
||||
|
||||
#include "sampler.h"
|
||||
|
||||
@ -2013,12 +2014,16 @@ nsJSContext::GetGlobalObject()
|
||||
|
||||
JSClass *c = JS_GetClass(global);
|
||||
|
||||
if (!c || ((~c->flags) & (JSCLASS_HAS_PRIVATE |
|
||||
JSCLASS_PRIVATE_IS_NSISUPPORTS))) {
|
||||
// Whenever we end up with globals that are JSCLASS_IS_DOMJSCLASS
|
||||
// and have an nsISupports DOM object, we will need to modify this
|
||||
// check here.
|
||||
MOZ_ASSERT(!(c->flags & JSCLASS_IS_DOMJSCLASS));
|
||||
if ((~c->flags) & (JSCLASS_HAS_PRIVATE |
|
||||
JSCLASS_PRIVATE_IS_NSISUPPORTS)) {
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
nsISupports *priv = (nsISupports *)js::GetObjectPrivate(global);
|
||||
|
||||
nsISupports *priv = static_cast<nsISupports*>(js::GetObjectPrivate(global));
|
||||
|
||||
nsCOMPtr<nsIXPConnectWrappedNative> wrapped_native =
|
||||
do_QueryInterface(priv);
|
||||
|
@ -61,6 +61,8 @@
|
||||
|
||||
#include "nsDOMJSUtils.h" // for GetScriptContextFromJSContext
|
||||
|
||||
#include "mozilla/dom/bindings/Utils.h"
|
||||
|
||||
JSBool
|
||||
nsJSUtils::GetCallingLocation(JSContext* aContext, const char* *aFilename,
|
||||
PRUint32* aLineno)
|
||||
@ -99,7 +101,6 @@ nsJSUtils::GetCallingLocation(JSContext* aContext, const char* *aFilename,
|
||||
nsIScriptGlobalObject *
|
||||
nsJSUtils::GetStaticScriptGlobal(JSContext* aContext, JSObject* aObj)
|
||||
{
|
||||
nsISupports* supports;
|
||||
JSClass* clazz;
|
||||
JSObject* glob = aObj; // starting point for search
|
||||
|
||||
@ -111,8 +112,12 @@ nsJSUtils::GetStaticScriptGlobal(JSContext* aContext, JSObject* aObj)
|
||||
|
||||
clazz = JS_GetClass(glob);
|
||||
|
||||
if (!clazz ||
|
||||
!(clazz->flags & JSCLASS_HAS_PRIVATE) ||
|
||||
// Whenever we end up with globals that are JSCLASS_IS_DOMJSCLASS
|
||||
// and have an nsISupports DOM object, we will need to modify this
|
||||
// check here.
|
||||
MOZ_ASSERT(!(clazz->flags & JSCLASS_IS_DOMJSCLASS));
|
||||
nsISupports* supports;
|
||||
if (!(clazz->flags & JSCLASS_HAS_PRIVATE) ||
|
||||
!(clazz->flags & JSCLASS_PRIVATE_IS_NSISUPPORTS) ||
|
||||
!(supports = (nsISupports*)::JS_GetPrivate(glob))) {
|
||||
return nsnull;
|
||||
|
@ -803,3 +803,12 @@ nsScriptNameSpaceManager::Observe(nsISupports* aSubject, const char* aTopic,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsScriptNameSpaceManager::RegisterDefineDOMInterface(const nsAString& aName,
|
||||
mozilla::dom::binding::DefineInterface aDefineDOMInterface)
|
||||
{
|
||||
nsGlobalNameStruct* s = LookupNameInternal(aName);
|
||||
if (s) {
|
||||
s->mDefineDOMInterface = aDefineDOMInterface;
|
||||
}
|
||||
}
|
||||
|
@ -97,6 +97,9 @@ struct nsGlobalNameStruct
|
||||
nsCID mCID; // All other types...
|
||||
};
|
||||
|
||||
// For new style DOM bindings.
|
||||
mozilla::dom::binding::DefineInterface mDefineDOMInterface;
|
||||
|
||||
private:
|
||||
|
||||
// copy constructor
|
||||
@ -166,7 +169,10 @@ public:
|
||||
|
||||
nsGlobalNameStruct* GetConstructorProto(const nsGlobalNameStruct* aStruct);
|
||||
|
||||
protected:
|
||||
void RegisterDefineDOMInterface(const nsAString& aName,
|
||||
mozilla::dom::binding::DefineInterface aDefineDOMInterface);
|
||||
|
||||
private:
|
||||
// Adds a new entry to the hash and returns the nsGlobalNameStruct
|
||||
// that aKey will be mapped to. If mType in the returned
|
||||
// nsGlobalNameStruct is != eTypeNotInitialized, an entry for aKey
|
||||
|
@ -47,6 +47,16 @@ class XPCWrappedNativeScope;
|
||||
|
||||
typedef PRUptrdiff PtrBits;
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
namespace workers {
|
||||
|
||||
class DOMBindingBase;
|
||||
|
||||
} // namespace workers
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#define NS_WRAPPERCACHE_IID \
|
||||
{ 0x6f3179a1, 0x36f7, 0x4a5c, \
|
||||
{ 0x8c, 0xf1, 0xad, 0xc8, 0x7c, 0xde, 0x3e, 0x87 } }
|
||||
@ -72,7 +82,7 @@ typedef PRUptrdiff PtrBits;
|
||||
* - a slim wrapper or the JSObject of an XPCWrappedNative wrapper
|
||||
*
|
||||
* If WRAPPER_IS_DOM_BINDING is set (IsDOMBinding() returns true):
|
||||
* - a DOM binding object (proxy)
|
||||
* - a DOM binding object (regular JS object or proxy)
|
||||
*
|
||||
* The finalizer for the wrapper clears the cache.
|
||||
*
|
||||
@ -82,6 +92,8 @@ typedef PRUptrdiff PtrBits;
|
||||
*/
|
||||
class nsWrapperCache
|
||||
{
|
||||
friend class mozilla::dom::workers::DOMBindingBase;
|
||||
|
||||
public:
|
||||
NS_DECLARE_STATIC_IID_ACCESSOR(NS_WRAPPERCACHE_IID)
|
||||
|
||||
@ -217,7 +229,7 @@ private:
|
||||
|
||||
/**
|
||||
* If this bit is set then the wrapper for the native object is a DOM binding
|
||||
* (proxy).
|
||||
* (regular JS object or proxy).
|
||||
*/
|
||||
enum { WRAPPER_IS_DOM_BINDING = 1 << 1 };
|
||||
|
||||
|
73
dom/bindings/BindingGen.py
Normal file
73
dom/bindings/BindingGen.py
Normal file
@ -0,0 +1,73 @@
|
||||
# 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/.
|
||||
|
||||
import os
|
||||
import cPickle
|
||||
import WebIDL
|
||||
from Configuration import *
|
||||
from Codegen import CGBindingRoot, replaceFileIfChanged
|
||||
# import Codegen in general, so we can set a variable on it
|
||||
import Codegen
|
||||
|
||||
def generate_binding_header(config, outputprefix, webidlfile):
|
||||
"""
|
||||
|config| Is the configuration object.
|
||||
|outputprefix| is a prefix to use for the header guards and filename.
|
||||
"""
|
||||
|
||||
filename = outputprefix + ".h"
|
||||
root = CGBindingRoot(config, outputprefix, webidlfile)
|
||||
if replaceFileIfChanged(filename, root.declare()):
|
||||
print "Generating binding header: %s" % (filename)
|
||||
|
||||
def generate_binding_cpp(config, outputprefix, webidlfile):
|
||||
"""
|
||||
|config| Is the configuration object.
|
||||
|outputprefix| is a prefix to use for the header guards and filename.
|
||||
"""
|
||||
|
||||
filename = outputprefix + ".cpp"
|
||||
root = CGBindingRoot(config, outputprefix, webidlfile)
|
||||
if replaceFileIfChanged(filename, root.define()):
|
||||
print "Generating binding implementation: %s" % (filename)
|
||||
|
||||
def main():
|
||||
|
||||
# Parse arguments.
|
||||
from optparse import OptionParser
|
||||
usagestring = "usage: %prog [header|cpp] configFile outputPrefix webIDLFile"
|
||||
o = OptionParser(usage=usagestring)
|
||||
o.add_option("--verbose-errors", action='store_true', default=False,
|
||||
help="When an error happens, display the Python traceback.")
|
||||
o.add_option("--use-jsop-accessors", action='store_true', default=False,
|
||||
dest='useJSOPAccessors',
|
||||
help="Use JSPropertyOps instead of JSNatives for getters and setters")
|
||||
(options, args) = o.parse_args()
|
||||
Codegen.generateNativeAccessors = not options.useJSOPAccessors
|
||||
|
||||
if len(args) != 4 or (args[0] != "header" and args[0] != "cpp"):
|
||||
o.error(usagestring)
|
||||
buildTarget = args[0]
|
||||
configFile = os.path.normpath(args[1])
|
||||
outputPrefix = args[2]
|
||||
webIDLFile = os.path.normpath(args[3])
|
||||
|
||||
# Load the parsing results
|
||||
f = open('ParserResults.pkl', 'rb')
|
||||
parserData = cPickle.load(f)
|
||||
f.close()
|
||||
|
||||
# Create the configuration data.
|
||||
config = Configuration(configFile, parserData)
|
||||
|
||||
# Generate the prototype classes.
|
||||
if buildTarget == "header":
|
||||
generate_binding_header(config, outputPrefix, webIDLFile);
|
||||
elif buildTarget == "cpp":
|
||||
generate_binding_cpp(config, outputPrefix, webIDLFile);
|
||||
else:
|
||||
assert False # not reached
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
233
dom/bindings/Bindings.conf
Normal file
233
dom/bindings/Bindings.conf
Normal file
@ -0,0 +1,233 @@
|
||||
# DOM Bindings Configuration.
|
||||
#
|
||||
# The WebIDL interfaces are defined in dom/webidl. For each such interface, there
|
||||
# is a corresponding entry in the configuration table below. The configuration
|
||||
# table maps each interface name to a |descriptor| or list of |descriptor|s.
|
||||
#
|
||||
# Valid fields for all descriptors:
|
||||
# * nativeType - The native type (concrete class or XPCOM interface) that
|
||||
# instances of this interface will unwrap to (required).
|
||||
# * headerFile - The file in which the nativeType is declared (defaults
|
||||
# to an educated guess).
|
||||
# * castable - Indicates whether the value in the wrapper can be cast to
|
||||
# nativeType, or whether it needs to be QI-ed (defaults to True
|
||||
# for everything but callback interfaces).
|
||||
# * concrete - Indicates whether there exist objects with this interface as
|
||||
# their primary interface (defaults to True).
|
||||
# * prefable - Indicates whether this binding is subject to the about:config
|
||||
# pref, or whether it's always enabled (defaults to False).
|
||||
# * workers - Indicates whether the descriptor is intended to be used for
|
||||
# worker threads (defaults to false).
|
||||
# * customTrace - The native class will use a custom trace hook (defaults to
|
||||
# true for workers, false otherwise).
|
||||
# * customFinalize - The native class will use a custom finalize hook
|
||||
# (defaults to true for workers, false otherwise).
|
||||
# * notflattened - The native type does not have nsIClassInfo, so when
|
||||
# wrapping it the right IID needs to be passed in.
|
||||
#
|
||||
# The following fields are either a string, an array (defaults to an empty
|
||||
# array) or a dictionary with three possible keys (all, getterOnly and
|
||||
# setterOnly) each having such an array as the value
|
||||
#
|
||||
# * infallible - attributes and methods specified in the .webidl file that
|
||||
# cannot fail and therefore do not require the final nsresult&
|
||||
# argument
|
||||
# * implicitJSContext - attributes and methods specified in the .webidl file
|
||||
# that require a JSContext as the first argument
|
||||
# * resultNotAddRefed - attributes and methods specified in the .webidl file
|
||||
# that do not AddRef the return value
|
||||
|
||||
DOMInterfaces = {
|
||||
|
||||
'XMLHttpRequest': [
|
||||
{
|
||||
'nativeType': 'nsXMLHttpRequest',
|
||||
'prefable': True,
|
||||
'infallible': {
|
||||
'all': [
|
||||
'readyState', 'withCredentials', 'abort', 'statusText',
|
||||
'getAllResponseHeaders', 'overrideMimeType', 'mozBackgroundRequest',
|
||||
'multipart', 'channel', 'upload', 'status'
|
||||
],
|
||||
'getterOnly': [
|
||||
'responseType', 'timeout', 'onreadystatechange'
|
||||
]
|
||||
},
|
||||
'implicitJSContext': {
|
||||
'all': [
|
||||
'response', 'getInterface'
|
||||
],
|
||||
'setterOnly': [
|
||||
'onreadystatechange'
|
||||
]
|
||||
},
|
||||
'resultNotAddRefed': [ 'upload', 'responseXML' ]
|
||||
},
|
||||
{
|
||||
'workers': True,
|
||||
'nativeType': 'mozilla::dom::workers::XMLHttpRequest',
|
||||
'headerFile': 'mozilla/dom/workers/bindings/XMLHttpRequest.h',
|
||||
'infallible': [
|
||||
'readyState', 'statusText'
|
||||
]
|
||||
}],
|
||||
|
||||
'XMLHttpRequestUpload': [
|
||||
{
|
||||
'nativeType': 'nsXMLHttpRequestUpload',
|
||||
'headerFile': 'nsXMLHttpRequest.h',
|
||||
'prefable': True
|
||||
},
|
||||
{
|
||||
'workers': True,
|
||||
'nativeType': 'mozilla::dom::workers::XMLHttpRequestUpload',
|
||||
'headerFile': 'mozilla/dom/workers/bindings/XMLHttpRequestUpload.h'
|
||||
}],
|
||||
|
||||
'MozChannel': [
|
||||
{
|
||||
'nativeType': 'nsIChannel',
|
||||
'prefable': True,
|
||||
'castable': False,
|
||||
'notflattened': True
|
||||
},
|
||||
{
|
||||
'workers': True,
|
||||
'nativeType': 'JSObject',
|
||||
'headerFile': 'jsapi.h',
|
||||
'castable': False
|
||||
}],
|
||||
|
||||
'InputStream': [
|
||||
{
|
||||
'nativeType': 'nsIInputStream',
|
||||
'prefable': True,
|
||||
'castable': False,
|
||||
'notflattened': True
|
||||
},
|
||||
{
|
||||
'workers': True,
|
||||
'nativeType': 'JSObject',
|
||||
'headerFile': 'jsapi.h',
|
||||
'castable': False
|
||||
}],
|
||||
|
||||
'Document': [
|
||||
{
|
||||
'nativeType': 'nsIDocument',
|
||||
'prefable': True,
|
||||
'castable': False
|
||||
},
|
||||
{
|
||||
'workers': True,
|
||||
'nativeType': 'JSObject',
|
||||
'headerFile': 'jsapi.h',
|
||||
'castable': False
|
||||
}],
|
||||
|
||||
'Blob': [
|
||||
{
|
||||
'nativeType': 'nsIDOMBlob',
|
||||
'headerFile': 'nsIDOMFile.h',
|
||||
'prefable': True,
|
||||
'castable': False
|
||||
},
|
||||
{
|
||||
'workers': True,
|
||||
'nativeType': 'JSObject',
|
||||
'headerFile': 'jsapi.h',
|
||||
'castable': False
|
||||
}],
|
||||
|
||||
'FormData': [
|
||||
{
|
||||
'nativeType': 'nsIDOMFormData',
|
||||
'prefable': True,
|
||||
'castable': False
|
||||
},
|
||||
{
|
||||
'workers': True,
|
||||
'nativeType': 'JSObject',
|
||||
'headerFile': 'jsapi.h',
|
||||
'castable': False
|
||||
}],
|
||||
|
||||
'EventTarget': [
|
||||
{
|
||||
'nativeType': 'nsDOMEventTargetHelper',
|
||||
'hasInstanceInterface': 'nsIDOMEventTarget',
|
||||
'concrete': False,
|
||||
'prefable': True,
|
||||
},
|
||||
{
|
||||
'workers': True,
|
||||
'nativeType': 'mozilla::dom::workers::EventTarget',
|
||||
'headerFile': 'mozilla/dom/workers/bindings/EventTarget.h',
|
||||
'concrete': False
|
||||
}],
|
||||
|
||||
'Event': [
|
||||
{
|
||||
'nativeType': 'nsIDOMEvent',
|
||||
'prefable': True,
|
||||
'castable': False
|
||||
},
|
||||
{
|
||||
'workers': True,
|
||||
'nativeType': 'JSObject',
|
||||
'headerFile': 'jsapi.h',
|
||||
'castable': False
|
||||
}],
|
||||
|
||||
'EventListener': [
|
||||
{
|
||||
'nativeType': 'nsIDOMEventListener',
|
||||
'prefable': True
|
||||
},
|
||||
{
|
||||
'workers': True,
|
||||
'nativeType': 'JSObject',
|
||||
'headerFile': 'jsapi.h'
|
||||
}],
|
||||
|
||||
'XMLHttpRequestEventTarget': [
|
||||
{
|
||||
'nativeType': 'nsXHREventTarget',
|
||||
'headerFile': 'nsXMLHttpRequest.h',
|
||||
'concrete': False,
|
||||
'prefable': True,
|
||||
'infallible': {
|
||||
'getterOnly': [
|
||||
'onabort', 'onerror', 'onload', 'onloadstart', 'onprogress',
|
||||
'ontimeout', 'onloadend'
|
||||
]
|
||||
},
|
||||
'implicitJSContext': {
|
||||
'setterOnly': [
|
||||
'onabort', 'onerror', 'onload', 'onloadstart', 'onprogress',
|
||||
'ontimeout', 'onloadend'
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
'workers': True,
|
||||
'concrete': False,
|
||||
'nativeType': 'mozilla::dom::workers::XMLHttpRequestEventTarget',
|
||||
'headerFile': 'mozilla/dom/workers/bindings/XMLHttpRequestEventTarget.h'
|
||||
}],
|
||||
|
||||
'IID': [
|
||||
{
|
||||
'nativeType': 'nsIJSIID',
|
||||
'headerFile': 'xpcjsid.h',
|
||||
'prefable': True,
|
||||
'castable': False
|
||||
},
|
||||
{
|
||||
'workers': True,
|
||||
'nativeType': 'JSObject',
|
||||
'headerFile': 'jsapi.h',
|
||||
'castable': False
|
||||
}],
|
||||
|
||||
}
|
2982
dom/bindings/Codegen.py
Normal file
2982
dom/bindings/Codegen.py
Normal file
File diff suppressed because it is too large
Load Diff
186
dom/bindings/Configuration.py
Normal file
186
dom/bindings/Configuration.py
Normal file
@ -0,0 +1,186 @@
|
||||
# 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/.
|
||||
|
||||
autogenerated_comment = "/* THIS FILE IS AUTOGENERATED - DO NOT EDIT */\n"
|
||||
|
||||
class Configuration:
|
||||
"""
|
||||
Represents global configuration state based on IDL parse data and
|
||||
the configuration file.
|
||||
"""
|
||||
def __init__(self, filename, parseData):
|
||||
|
||||
# Read the configuration file.
|
||||
glbl = {}
|
||||
execfile(filename, glbl)
|
||||
config = glbl['DOMInterfaces']
|
||||
|
||||
# Build descriptors for all the interfaces we have in the parse data.
|
||||
# This allows callers to specify a subset of interfaces by filtering
|
||||
# |parseData|.
|
||||
self.descriptors = []
|
||||
self.interfaces = {}
|
||||
self.maxProtoChainLength = 0;
|
||||
for thing in parseData:
|
||||
if not thing.isInterface(): continue
|
||||
iface = thing
|
||||
if iface.identifier.name not in config: continue
|
||||
self.interfaces[iface.identifier.name] = iface
|
||||
entry = config[iface.identifier.name]
|
||||
if not isinstance(entry, list):
|
||||
assert isinstance(entry, dict)
|
||||
entry = [entry]
|
||||
self.descriptors.extend([Descriptor(self, iface, x) for x in entry])
|
||||
|
||||
# Mark the descriptors for which only a single nativeType implements
|
||||
# an interface.
|
||||
for descriptor in self.descriptors:
|
||||
intefaceName = descriptor.interface.identifier.name
|
||||
otherDescriptors = [d for d in self.descriptors
|
||||
if d.interface.identifier.name == intefaceName]
|
||||
descriptor.uniqueImplementation = len(otherDescriptors) == 1
|
||||
|
||||
self.enums = [e for e in parseData if e.isEnum()]
|
||||
|
||||
# Keep the descriptor list sorted for determinism.
|
||||
self.descriptors.sort(lambda x,y: cmp(x.name, y.name))
|
||||
|
||||
def getInterface(self, ifname):
|
||||
return self.interfaces[ifname]
|
||||
def getDescriptors(self, **filters):
|
||||
"""Gets the descriptors that match the given filters."""
|
||||
curr = self.descriptors
|
||||
for key, val in filters.iteritems():
|
||||
if key == 'webIDLFile':
|
||||
getter = lambda x: x.interface.filename()
|
||||
elif key == 'hasInterfaceObject':
|
||||
getter = lambda x: (not x.interface.isExternal() and
|
||||
x.interface.hasInterfaceObject())
|
||||
elif key == 'hasInterfacePrototypeObject':
|
||||
getter = lambda x: (not x.interface.isExternal() and
|
||||
x.interface.hasInterfacePrototypeObject())
|
||||
elif key == 'hasInterfaceOrInterfacePrototypeObject':
|
||||
getter = lambda x: x.hasInterfaceOrInterfacePrototypeObject()
|
||||
elif key == 'isCallback':
|
||||
getter = lambda x: x.interface.isCallback()
|
||||
elif key == 'isExternal':
|
||||
getter = lambda x: x.interface.isExternal()
|
||||
else:
|
||||
getter = lambda x: getattr(x, key)
|
||||
curr = filter(lambda x: getter(x) == val, curr)
|
||||
return curr
|
||||
def getEnums(self, webIDLFile):
|
||||
return filter(lambda e: e.filename() == webIDLFile, self.enums)
|
||||
|
||||
class Descriptor:
|
||||
"""
|
||||
Represents a single descriptor for an interface. See Bindings.conf.
|
||||
"""
|
||||
def __init__(self, config, interface, desc):
|
||||
self.config = config
|
||||
self.interface = interface
|
||||
|
||||
# Read the desc, and fill in the relevant defaults.
|
||||
self.nativeType = desc['nativeType']
|
||||
self.hasInstanceInterface = desc.get('hasInstanceInterface', None)
|
||||
|
||||
headerDefault = self.nativeType
|
||||
headerDefault = headerDefault.split("::")[-1] + ".h"
|
||||
self.headerFile = desc.get('headerFile', headerDefault)
|
||||
|
||||
castableDefault = not self.interface.isCallback()
|
||||
self.castable = desc.get('castable', castableDefault)
|
||||
|
||||
self.notflattened = desc.get('notflattened', False)
|
||||
|
||||
# If we're concrete, we need to crawl our ancestor interfaces and mark
|
||||
# them as having a concrete descendant.
|
||||
self.concrete = desc.get('concrete', True)
|
||||
if self.concrete:
|
||||
iface = self.interface
|
||||
while iface:
|
||||
iface.setUserData('hasConcreteDescendant', True)
|
||||
iface = iface.parent
|
||||
|
||||
self.prefable = desc.get('prefable', False)
|
||||
|
||||
self.workers = desc.get('workers', False)
|
||||
self.nativeIsISupports = not self.workers
|
||||
self.customTrace = desc.get('customTrace', self.workers)
|
||||
self.customFinalize = desc.get('customFinalize', self.workers)
|
||||
|
||||
def make_name(name):
|
||||
return name + "_workers" if self.workers else name
|
||||
self.name = make_name(interface.identifier.name)
|
||||
|
||||
# self.extendedAttributes is a dict of dicts, keyed on
|
||||
# all/getterOnly/setterOnly and then on member name. Values are an
|
||||
# array of extended attributes.
|
||||
self.extendedAttributes = { 'all': {}, 'getterOnly': {}, 'setterOnly': {} }
|
||||
|
||||
def addExtendedAttribute(attribute, config):
|
||||
def add(key, members, attribute):
|
||||
for member in members:
|
||||
self.extendedAttributes[key].setdefault(member, []).append(attribute)
|
||||
|
||||
if isinstance(config, dict):
|
||||
for key in ['all', 'getterOnly', 'setterOnly']:
|
||||
add(key, config.get(key, []), attribute)
|
||||
elif isinstance(config, list):
|
||||
add('all', config, attribute)
|
||||
else:
|
||||
assert isinstance(config, string)
|
||||
add('all', [config], attribute)
|
||||
|
||||
for attribute in ['infallible', 'implicitJSContext', 'resultNotAddRefed']:
|
||||
addExtendedAttribute(attribute, desc.get(attribute, {}))
|
||||
|
||||
self.binaryNames = desc.get('binaryNames', {})
|
||||
|
||||
# Build the prototype chain.
|
||||
self.prototypeChain = []
|
||||
parent = interface
|
||||
while parent:
|
||||
self.prototypeChain.insert(0, make_name(parent.identifier.name))
|
||||
parent = parent.parent
|
||||
config.maxProtoChainLength = max(config.maxProtoChainLength,
|
||||
len(self.prototypeChain))
|
||||
|
||||
def hasInterfaceOrInterfacePrototypeObject(self):
|
||||
|
||||
# Forward-declared interfaces don't need either interface object or
|
||||
# interface prototype object as they're going to use QI (on main thread)
|
||||
# or be passed as a JSObject (on worker threads).
|
||||
if self.interface.isExternal():
|
||||
return False
|
||||
|
||||
return self.interface.hasInterfaceObject() or self.interface.hasInterfacePrototypeObject()
|
||||
|
||||
def getDescriptor(self, interfaceName):
|
||||
"""
|
||||
Gets the appropriate descriptor for the given interface name given the
|
||||
context of the current descriptor. This selects the appropriate
|
||||
implementation for cases like workers.
|
||||
"""
|
||||
iface = self.config.getInterface(interfaceName)
|
||||
descriptors = self.config.getDescriptors(interface=iface)
|
||||
|
||||
# The only filter we currently have is workers vs non-workers.
|
||||
matches = filter(lambda x: x.workers is self.workers, descriptors)
|
||||
|
||||
# After filtering, we should have exactly one result.
|
||||
if len(matches) is not 1:
|
||||
raise TypeError("For " + interfaceName + " found " +
|
||||
str(len(matches)) + " matches");
|
||||
return matches[0]
|
||||
|
||||
def getExtendedAttributes(self, member, getter=False, setter=False):
|
||||
name = member.identifier.name
|
||||
if member.isMethod():
|
||||
return self.extendedAttributes['all'].get(name, [])
|
||||
|
||||
assert member.isAttr()
|
||||
assert bool(getter) != bool(setter)
|
||||
key = 'getterOnly' if getter else 'setterOnly'
|
||||
return self.extendedAttributes['all'].get(name, []) + self.extendedAttributes[key].get(name, [])
|
104
dom/bindings/DOMJSClass.h
Normal file
104
dom/bindings/DOMJSClass.h
Normal file
@ -0,0 +1,104 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-*/
|
||||
/* 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 mozilla_dom_bindings_DOMJSClass_h
|
||||
#define mozilla_dom_bindings_DOMJSClass_h
|
||||
|
||||
#include "jsapi.h"
|
||||
#include "jsfriendapi.h"
|
||||
|
||||
#include "mozilla/dom/bindings/PrototypeList.h" // auto-generated
|
||||
|
||||
// For non-global objects we use slot 0 for holding the raw object.
|
||||
#define DOM_OBJECT_SLOT 0
|
||||
|
||||
// All DOM globals must have two slots at DOM_GLOBAL_OBJECT_SLOT and
|
||||
// DOM_PROTOTYPE_SLOT. We have to start at 1 past JSCLASS_GLOBAL_SLOT_COUNT
|
||||
// because XPConnect uses that one.
|
||||
#define DOM_GLOBAL_OBJECT_SLOT (JSCLASS_GLOBAL_SLOT_COUNT + 1)
|
||||
#define DOM_PROTOTYPE_SLOT (JSCLASS_GLOBAL_SLOT_COUNT + 2)
|
||||
|
||||
// We use these flag bits for the new bindings.
|
||||
#define JSCLASS_IS_DOMJSCLASS JSCLASS_USERBIT1
|
||||
#define JSCLASS_DOM_GLOBAL JSCLASS_USERBIT2
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
namespace bindings {
|
||||
|
||||
typedef bool
|
||||
(* ResolveProperty)(JSContext* cx, JSObject* wrapper, jsid id, bool set,
|
||||
JSPropertyDescriptor* desc);
|
||||
typedef bool
|
||||
(* EnumerateProperties)(JS::AutoIdVector& props);
|
||||
|
||||
struct NativePropertyHooks
|
||||
{
|
||||
ResolveProperty mResolveProperty;
|
||||
EnumerateProperties mEnumerateProperties;
|
||||
|
||||
const NativePropertyHooks *mProtoHooks;
|
||||
};
|
||||
|
||||
// Special JSClass for reflected DOM objects.
|
||||
struct DOMJSClass
|
||||
{
|
||||
// It would be nice to just inherit from JSClass, but that precludes pure
|
||||
// compile-time initialization of the form |DOMJSClass = {...};|, since C++
|
||||
// only allows brace initialization for aggregate/POD types.
|
||||
JSClass mBase;
|
||||
|
||||
// A list of interfaces that this object implements, in order of decreasing
|
||||
// derivedness.
|
||||
const prototypes::ID mInterfaceChain[prototypes::id::_ID_Count];
|
||||
|
||||
// We cache the VTable index of GetWrapperCache for objects that support it.
|
||||
//
|
||||
// -1 indicates that GetWrapperCache is not implemented on the underlying object.
|
||||
// XXXkhuey this is unused and needs to die.
|
||||
const int16_t mGetWrapperCacheVTableOffset;
|
||||
|
||||
// We store the DOM object in a reserved slot whose index is mNativeSlot.
|
||||
// Sometimes it's an nsISupports and sometimes it's not; this class tells
|
||||
// us which it is.
|
||||
const bool mDOMObjectIsISupports;
|
||||
|
||||
// The slot to use to get the object reference from the object
|
||||
const size_t mNativeSlot;
|
||||
|
||||
const NativePropertyHooks* mNativeHooks;
|
||||
|
||||
static DOMJSClass* FromJSClass(JSClass* base) {
|
||||
MOZ_ASSERT(base->flags & JSCLASS_IS_DOMJSCLASS);
|
||||
return reinterpret_cast<DOMJSClass*>(base);
|
||||
}
|
||||
static const DOMJSClass* FromJSClass(const JSClass* base) {
|
||||
MOZ_ASSERT(base->flags & JSCLASS_IS_DOMJSCLASS);
|
||||
return reinterpret_cast<const DOMJSClass*>(base);
|
||||
}
|
||||
|
||||
static DOMJSClass* FromJSClass(js::Class* base) {
|
||||
return FromJSClass(Jsvalify(base));
|
||||
}
|
||||
static const DOMJSClass* FromJSClass(const js::Class* base) {
|
||||
return FromJSClass(Jsvalify(base));
|
||||
}
|
||||
|
||||
JSClass* ToJSClass() { return &mBase; }
|
||||
};
|
||||
|
||||
inline JSObject**
|
||||
GetProtoOrIfaceArray(JSObject* global)
|
||||
{
|
||||
MOZ_ASSERT(js::GetObjectClass(global)->flags & JSCLASS_DOM_GLOBAL);
|
||||
return static_cast<JSObject**>(
|
||||
js::GetReservedSlot(global, DOM_PROTOTYPE_SLOT).toPrivate());
|
||||
}
|
||||
|
||||
} // namespace bindings
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif /* mozilla_dom_bindings_DOMJSClass_h */
|
81
dom/bindings/GlobalGen.py
Normal file
81
dom/bindings/GlobalGen.py
Normal file
@ -0,0 +1,81 @@
|
||||
# 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/.
|
||||
|
||||
# We do one global pass over all the WebIDL to generate our prototype enum
|
||||
# and generate information for subsequent phases.
|
||||
|
||||
import os
|
||||
import cStringIO
|
||||
import WebIDL
|
||||
import cPickle
|
||||
from Configuration import *
|
||||
from Codegen import GlobalGenRoots, replaceFileIfChanged
|
||||
# import Codegen in general, so we can set a variable on it
|
||||
import Codegen
|
||||
|
||||
def generate_file(config, name, action):
|
||||
|
||||
root = getattr(GlobalGenRoots, name)(config)
|
||||
if action is 'declare':
|
||||
filename = name + '.h'
|
||||
code = root.declare()
|
||||
else:
|
||||
assert action is 'define'
|
||||
filename = name + '.cpp'
|
||||
code = root.define()
|
||||
|
||||
if replaceFileIfChanged(filename, code):
|
||||
print "Generating %s" % (filename)
|
||||
else:
|
||||
print "%s hasn't changed - not touching it" % (filename)
|
||||
|
||||
def main():
|
||||
# Parse arguments.
|
||||
from optparse import OptionParser
|
||||
usageString = "usage: %prog [options] webidldir [files]"
|
||||
o = OptionParser(usage=usageString)
|
||||
o.add_option("--cachedir", dest='cachedir', default=None,
|
||||
help="Directory in which to cache lex/parse tables.")
|
||||
o.add_option("--verbose-errors", action='store_true', default=False,
|
||||
help="When an error happens, display the Python traceback.")
|
||||
o.add_option("--use-jsop-accessors", action='store_true', default=False,
|
||||
dest='useJSOPAccessors',
|
||||
help="Use JSPropertyOps instead of JSNatives for getters and setters")
|
||||
(options, args) = o.parse_args()
|
||||
Codegen.generateNativeAccessors = not options.useJSOPAccessors
|
||||
|
||||
if len(args) < 2:
|
||||
o.error(usageString)
|
||||
|
||||
configFile = args[0]
|
||||
baseDir = args[1]
|
||||
fileList = args[2:]
|
||||
|
||||
# Parse the WebIDL.
|
||||
parser = WebIDL.Parser(options.cachedir)
|
||||
for filename in fileList:
|
||||
fullPath = os.path.normpath(os.path.join(baseDir, filename))
|
||||
f = open(fullPath, 'rb')
|
||||
lines = f.readlines()
|
||||
f.close()
|
||||
parser.parse(''.join(lines), fullPath)
|
||||
parserResults = parser.finish()
|
||||
|
||||
# Write the parser results out to a pickle.
|
||||
resultsFile = open('ParserResults.pkl', 'wb')
|
||||
cPickle.dump(parserResults, resultsFile, -1)
|
||||
resultsFile.close()
|
||||
|
||||
# Load the configuration.
|
||||
config = Configuration(configFile, parserResults)
|
||||
|
||||
# Generate the prototype list.
|
||||
generate_file(config, 'PrototypeList', 'declare')
|
||||
|
||||
# Generate the common code.
|
||||
generate_file(config, 'Common', 'declare')
|
||||
generate_file(config, 'Common', 'define')
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
122
dom/bindings/Makefile.in
Normal file
122
dom/bindings/Makefile.in
Normal file
@ -0,0 +1,122 @@
|
||||
# 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/.
|
||||
|
||||
DEPTH = ../..
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
MODULE = dom
|
||||
LIBRARY_NAME = dombindings_s
|
||||
LIBXUL_LIBRARY = 1
|
||||
FORCE_STATIC_LIB = 1
|
||||
EXPORT_LIBRARY = 1
|
||||
|
||||
include $(topsrcdir)/config/config.mk
|
||||
|
||||
# Define USE_JSOP_ACCESSORS to a nonempty string like "yes" to use them
|
||||
USE_JSOP_ACCESSORS =
|
||||
ifdef USE_JSOP_ACCESSORS
|
||||
DEFINES += -DUSE_JSOP_ACCESSORS
|
||||
ACCESSOR_OPT = --use-jsop-accessors
|
||||
else
|
||||
ACCESSOR_OPT =
|
||||
endif
|
||||
|
||||
# Need this to find all our DOM source files.
|
||||
include $(topsrcdir)/dom/dom-config.mk
|
||||
|
||||
include $(topsrcdir)/dom/webidl/WebIDL.mk
|
||||
|
||||
binding_include_path := mozilla/dom/bindings
|
||||
binding_header_files := $(subst .webidl,Binding.h,$(webidl_files))
|
||||
binding_cpp_files := $(subst .webidl,Binding.cpp,$(webidl_files))
|
||||
|
||||
globalgen_targets := \
|
||||
PrototypeList.h \
|
||||
Common.h \
|
||||
Common.cpp \
|
||||
$(NULL)
|
||||
|
||||
CPPSRCS = \
|
||||
$(binding_cpp_files) \
|
||||
$(filter %.cpp, $(globalgen_targets)) \
|
||||
Utils.cpp \
|
||||
$(NULL)
|
||||
|
||||
EXPORTS_NAMESPACES = $(binding_include_path)
|
||||
|
||||
EXPORTS_$(binding_include_path) = \
|
||||
DOMJSClass.h \
|
||||
PrototypeList.h \
|
||||
Common.h \
|
||||
Nullable.h \
|
||||
Utils.h \
|
||||
$(binding_header_files) \
|
||||
$(NULL)
|
||||
|
||||
LOCAL_INCLUDES += -I$(topsrcdir)/js/xpconnect/src \
|
||||
-I$(topsrcdir)/js/xpconnect/wrappers
|
||||
|
||||
TEST_DIRS += test
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
bindinggen_dependencies := \
|
||||
BindingGen.py \
|
||||
Bindings.conf \
|
||||
Configuration.py \
|
||||
Codegen.py \
|
||||
ParserResults.pkl \
|
||||
$(GLOBAL_DEPS) \
|
||||
$(NULL)
|
||||
|
||||
$(binding_header_files): %Binding.h: $(bindinggen_dependencies) \
|
||||
$(webidl_base)/%.webidl \
|
||||
$(NULL)
|
||||
$(PYTHON) $(topsrcdir)/config/pythonpath.py \
|
||||
-I$(topsrcdir)/other-licenses/ply -I$(srcdir)/parser \
|
||||
$(srcdir)/BindingGen.py $(ACCESSOR_OPT) header $(srcdir)/Bindings.conf $*Binding \
|
||||
$(webidl_base)/$*.webidl
|
||||
|
||||
$(binding_cpp_files): %Binding.cpp: $(bindinggen_dependencies) \
|
||||
$(webidl_base)/%.webidl \
|
||||
$(NULL)
|
||||
$(PYTHON) $(topsrcdir)/config/pythonpath.py \
|
||||
-I$(topsrcdir)/other-licenses/ply -I$(srcdir)/parser \
|
||||
$(srcdir)/BindingGen.py $(ACCESSOR_OPT) cpp $(srcdir)/Bindings.conf $*Binding \
|
||||
$(webidl_base)/$*.webidl
|
||||
|
||||
$(globalgen_targets): ParserResults.pkl
|
||||
|
||||
CACHE_DIR = _cache
|
||||
|
||||
globalgen_dependencies := \
|
||||
GlobalGen.py \
|
||||
Bindings.conf \
|
||||
Configuration.py \
|
||||
Codegen.py \
|
||||
$(CACHE_DIR)/.done \
|
||||
$(GLOBAL_DEPS) \
|
||||
$(NULL)
|
||||
|
||||
$(CACHE_DIR)/.done:
|
||||
$(MKDIR) -p $(CACHE_DIR)
|
||||
@$(TOUCH) $@
|
||||
|
||||
ParserResults.pkl: $(globalgen_dependencies) \
|
||||
$(addprefix $(webidl_base)/, $(webidl_files))
|
||||
$(PYTHON_PATH) -I$(topsrcdir)/other-licenses/ply -I$(srcdir)/parser \
|
||||
$(srcdir)/GlobalGen.py $(ACCESSOR_OPT) $(srcdir)/Bindings.conf $(webidl_base) \
|
||||
--cachedir=$(CACHE_DIR) \
|
||||
$(webidl_files)
|
||||
|
||||
GARBAGE += \
|
||||
$(binding_header_files) \
|
||||
$(binding_cpp_files) \
|
||||
$(globalgen_targets) \
|
||||
ParserResults.pkl \
|
||||
webidlyacc.py \
|
||||
parser.out \
|
||||
$(NULL)
|
57
dom/bindings/Nullable.h
Normal file
57
dom/bindings/Nullable.h
Normal file
@ -0,0 +1,57 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-*/
|
||||
/* vim: set ts=2 sw=2 et tw=79: */
|
||||
/* 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 mozilla_dom_bindings_Nullable_h
|
||||
#define mozilla_dom_bindings_Nullable_h
|
||||
|
||||
#include "mozilla/Assertions.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
namespace bindings {
|
||||
|
||||
// Support for nullable types
|
||||
template <typename T>
|
||||
struct Nullable
|
||||
{
|
||||
private:
|
||||
T mValue;
|
||||
bool mIsNull;
|
||||
|
||||
public:
|
||||
Nullable()
|
||||
: mIsNull(true)
|
||||
{}
|
||||
|
||||
Nullable(T aValue)
|
||||
: mValue(aValue)
|
||||
, mIsNull(false)
|
||||
{}
|
||||
|
||||
void SetValue(T aValue) {
|
||||
mValue = aValue;
|
||||
mIsNull = false;
|
||||
}
|
||||
|
||||
void SetNull() {
|
||||
mIsNull = true;
|
||||
}
|
||||
|
||||
T Value() const {
|
||||
MOZ_ASSERT(!mIsNull);
|
||||
return mValue;
|
||||
}
|
||||
|
||||
bool IsNull() const {
|
||||
return mIsNull;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace bindings
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif /* mozilla_dom_bindings_Nullable_h */
|
244
dom/bindings/Utils.cpp
Normal file
244
dom/bindings/Utils.cpp
Normal file
@ -0,0 +1,244 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-*/
|
||||
/* vim: set ts=2 sw=2 et tw=79: */
|
||||
/* 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 "Utils.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
namespace bindings {
|
||||
|
||||
static bool
|
||||
DefineConstants(JSContext* cx, JSObject* obj, ConstantSpec* cs)
|
||||
{
|
||||
for (; cs->name; ++cs) {
|
||||
JSBool ok =
|
||||
JS_DefineProperty(cx, obj, cs->name, cs->value, NULL, NULL,
|
||||
JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT);
|
||||
if (!ok) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static JSObject*
|
||||
CreateInterfaceObject(JSContext* cx, JSObject* global,
|
||||
JSClass* constructorClass, JSObject* proto,
|
||||
JSFunctionSpec* staticMethods, ConstantSpec* constants,
|
||||
const char* name)
|
||||
{
|
||||
JSObject* functionProto = JS_GetFunctionPrototype(cx, global);
|
||||
if (!functionProto) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
JSObject* constructor =
|
||||
JS_NewObject(cx, constructorClass, functionProto, global);
|
||||
if (!constructor) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (staticMethods && !JS_DefineFunctions(cx, constructor, staticMethods)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (constants && !DefineConstants(cx, constructor, constants)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (proto && !JS_LinkConstructorAndPrototype(cx, constructor, proto)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// This is Enumerable: False per spec.
|
||||
if (!JS_DefineProperty(cx, global, name, OBJECT_TO_JSVAL(constructor), NULL,
|
||||
NULL, 0)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return constructor;
|
||||
}
|
||||
|
||||
static JSObject*
|
||||
CreateInterfacePrototypeObject(JSContext* cx, JSObject* global,
|
||||
JSObject* parentProto, JSClass* protoClass,
|
||||
JSFunctionSpec* methods,
|
||||
JSPropertySpec* properties,
|
||||
ConstantSpec* constants)
|
||||
{
|
||||
JSObject* ourProto = JS_NewObject(cx, protoClass, parentProto, global);
|
||||
if (!ourProto) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (methods && !JS_DefineFunctions(cx, ourProto, methods)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (properties && !JS_DefineProperties(cx, ourProto, properties)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (constants && !DefineConstants(cx, ourProto, constants)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ourProto;
|
||||
}
|
||||
|
||||
JSObject*
|
||||
CreateInterfaceObjects(JSContext *cx, JSObject *global, JSObject *parentProto,
|
||||
JSClass *protoClass, JSClass *constructorClass,
|
||||
JSFunctionSpec *methods, JSPropertySpec *properties,
|
||||
ConstantSpec *constants, JSFunctionSpec *staticMethods,
|
||||
const char* name)
|
||||
{
|
||||
MOZ_ASSERT(protoClass || constructorClass, "Need at least one class!");
|
||||
MOZ_ASSERT(!(methods || properties) || protoClass,
|
||||
"Methods or properties but no protoClass!");
|
||||
MOZ_ASSERT(!staticMethods || constructorClass,
|
||||
"Static methods but no constructorClass!");
|
||||
MOZ_ASSERT(bool(name) == bool(constructorClass),
|
||||
"Must have name precisely when we have an interface object");
|
||||
|
||||
JSObject* proto;
|
||||
if (protoClass) {
|
||||
proto = CreateInterfacePrototypeObject(cx, global, parentProto, protoClass,
|
||||
methods, properties, constants);
|
||||
if (!proto) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else {
|
||||
proto = NULL;
|
||||
}
|
||||
|
||||
JSObject* interface;
|
||||
if (constructorClass) {
|
||||
interface = CreateInterfaceObject(cx, global, constructorClass, proto,
|
||||
staticMethods, constants, name);
|
||||
if (!interface) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return protoClass ? proto : interface;
|
||||
}
|
||||
|
||||
static bool
|
||||
NativeInterface2JSObjectAndThrowIfFailed(XPCLazyCallContext& aLccx,
|
||||
JSContext* aCx,
|
||||
JS::Value* aRetval,
|
||||
xpcObjectHelper& aHelper,
|
||||
const nsIID* aIID,
|
||||
bool aAllowNativeWrapper)
|
||||
{
|
||||
nsresult rv;
|
||||
if (!XPCConvert::NativeInterface2JSObject(aLccx, aRetval, NULL, aHelper, aIID,
|
||||
NULL, aAllowNativeWrapper, &rv)) {
|
||||
// I can't tell if NativeInterface2JSObject throws JS exceptions
|
||||
// or not. This is a sloppy stab at the right semantics; the
|
||||
// method really ought to be fixed to behave consistently.
|
||||
if (!JS_IsExceptionPending(aCx)) {
|
||||
Throw<true>(aCx, NS_FAILED(rv) ? rv : NS_ERROR_UNEXPECTED);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
DoHandleNewBindingWrappingFailure(JSContext* cx, JSObject* scope,
|
||||
nsISupports* value, JS::Value* vp)
|
||||
{
|
||||
if (JS_IsExceptionPending(cx)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
XPCLazyCallContext lccx(JS_CALLER, cx, scope);
|
||||
|
||||
if (value) {
|
||||
xpcObjectHelper helper(value);
|
||||
return NativeInterface2JSObjectAndThrowIfFailed(lccx, cx, vp, helper, NULL,
|
||||
true);
|
||||
}
|
||||
|
||||
return Throw<true>(cx, NS_ERROR_XPC_BAD_CONVERT_JS);
|
||||
}
|
||||
|
||||
// Only set allowNativeWrapper to false if you really know you need it, if in
|
||||
// doubt use true. Setting it to false disables security wrappers.
|
||||
bool
|
||||
XPCOMObjectToJsval(JSContext* cx, JSObject* scope, xpcObjectHelper &helper,
|
||||
const nsIID* iid, bool allowNativeWrapper, JS::Value* rval)
|
||||
{
|
||||
XPCLazyCallContext lccx(JS_CALLER, cx, scope);
|
||||
|
||||
if (!NativeInterface2JSObjectAndThrowIfFailed(lccx, cx, rval, helper, iid,
|
||||
allowNativeWrapper)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
JSObject* jsobj = JSVAL_TO_OBJECT(*rval);
|
||||
if (jsobj && !js::GetObjectParent(jsobj))
|
||||
NS_ASSERTION(js::GetObjectClass(jsobj)->flags & JSCLASS_IS_GLOBAL,
|
||||
"Why did we recreate this wrapper?");
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
JSBool
|
||||
QueryInterface(JSContext* cx, unsigned argc, JS::Value* vp)
|
||||
{
|
||||
JS::Value thisv = JS_THIS(cx, vp);
|
||||
if (thisv == JSVAL_NULL)
|
||||
return false;
|
||||
|
||||
JSObject* obj = JSVAL_TO_OBJECT(thisv);
|
||||
JSClass* clasp = js::GetObjectJSClass(obj);
|
||||
if (!IsDOMClass(clasp)) {
|
||||
return Throw<true>(cx, NS_ERROR_FAILURE);
|
||||
}
|
||||
|
||||
nsISupports* native = UnwrapDOMObject<nsISupports>(obj, clasp);
|
||||
|
||||
if (argc < 1) {
|
||||
return Throw<true>(cx, NS_ERROR_XPC_NOT_ENOUGH_ARGS);
|
||||
}
|
||||
|
||||
JS::Value* argv = JS_ARGV(cx, vp);
|
||||
if (!argv[0].isObject()) {
|
||||
return Throw<true>(cx, NS_ERROR_XPC_BAD_CONVERT_JS);
|
||||
}
|
||||
|
||||
nsIJSIID* iid;
|
||||
xpc_qsSelfRef iidRef;
|
||||
if (NS_FAILED(xpc_qsUnwrapArg<nsIJSIID>(cx, argv[0], &iid, &iidRef.ptr,
|
||||
&argv[0]))) {
|
||||
return Throw<true>(cx, NS_ERROR_XPC_BAD_CONVERT_JS);
|
||||
}
|
||||
MOZ_ASSERT(iid);
|
||||
|
||||
if (iid->GetID()->Equals(NS_GET_IID(nsIClassInfo))) {
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIClassInfo> ci = do_QueryInterface(native, &rv);
|
||||
if (NS_FAILED(rv)) {
|
||||
return Throw<true>(cx, rv);
|
||||
}
|
||||
|
||||
return WrapObject(cx, obj, ci, &NS_GET_IID(nsIClassInfo), vp);
|
||||
}
|
||||
|
||||
// Lie, otherwise we need to check classinfo or QI
|
||||
*vp = thisv;
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace bindings
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
508
dom/bindings/Utils.h
Normal file
508
dom/bindings/Utils.h
Normal file
@ -0,0 +1,508 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-*/
|
||||
/* vim: set ts=2 sw=2 et tw=79: */
|
||||
/* 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 mozilla_dom_bindings_Utils_h__
|
||||
#define mozilla_dom_bindings_Utils_h__
|
||||
|
||||
#include "mozilla/dom/bindings/DOMJSClass.h"
|
||||
|
||||
#include "jsapi.h"
|
||||
#include "jstypedarray.h"
|
||||
|
||||
#include "XPCQuickStubs.h"
|
||||
#include "XPCWrapper.h"
|
||||
#include "nsTraceRefcnt.h"
|
||||
#include "nsWrapperCacheInlines.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
namespace bindings {
|
||||
|
||||
template<bool mainThread>
|
||||
inline bool
|
||||
Throw(JSContext* cx, nsresult rv)
|
||||
{
|
||||
// XXX Introduce exception machinery.
|
||||
if (mainThread) {
|
||||
XPCThrower::Throw(rv, cx);
|
||||
} else {
|
||||
if (!JS_IsExceptionPending(cx)) {
|
||||
JS_ReportError(cx, "Exception thrown (nsresult = %x).", rv);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template<bool mainThread>
|
||||
inline bool
|
||||
ThrowMethodFailedWithDetails(JSContext* cx, nsresult rv,
|
||||
const char* /* ifaceName */,
|
||||
const char* /* memberName */)
|
||||
{
|
||||
return Throw<mainThread>(cx, rv);
|
||||
}
|
||||
|
||||
inline bool
|
||||
IsDOMClass(const JSClass* clasp)
|
||||
{
|
||||
return clasp->flags & JSCLASS_IS_DOMJSCLASS;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T*
|
||||
UnwrapDOMObject(JSObject* obj, const JSClass* clasp)
|
||||
{
|
||||
MOZ_ASSERT(IsDOMClass(clasp));
|
||||
MOZ_ASSERT(JS_GetClass(obj) == clasp);
|
||||
|
||||
size_t slot = DOMJSClass::FromJSClass(clasp)->mNativeSlot;
|
||||
MOZ_ASSERT((slot == DOM_OBJECT_SLOT &&
|
||||
!(clasp->flags & JSCLASS_DOM_GLOBAL)) ||
|
||||
(slot == DOM_GLOBAL_OBJECT_SLOT &&
|
||||
(clasp->flags & JSCLASS_DOM_GLOBAL)));
|
||||
|
||||
JS::Value val = js::GetReservedSlot(obj, slot);
|
||||
// XXXbz/khuey worker code tries to unwrap interface objects (which have
|
||||
// nothing here). That needs to stop.
|
||||
// XXX We don't null-check UnwrapObject's result; aren't we going to crash
|
||||
// anyway?
|
||||
if (val.isUndefined()) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return static_cast<T*>(val.toPrivate());
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T*
|
||||
UnwrapDOMObject(JSObject* obj, const js::Class* clasp)
|
||||
{
|
||||
return UnwrapDOMObject<T>(obj, Jsvalify(clasp));
|
||||
}
|
||||
|
||||
// Some callers don't want to set an exception when unwrappin fails
|
||||
// (for example, overload resolution uses unwrapping to tell what sort
|
||||
// of thing it's looking at).
|
||||
template <prototypes::ID PrototypeID, class T>
|
||||
inline nsresult
|
||||
UnwrapObject(JSContext* cx, JSObject* obj, T** value)
|
||||
{
|
||||
/* First check to see whether we have a DOM object */
|
||||
JSClass* clasp = js::GetObjectJSClass(obj);
|
||||
if (!IsDOMClass(clasp)) {
|
||||
/* Maybe we have a security wrapper or outer window? */
|
||||
if (!js::IsWrapper(obj)) {
|
||||
/* Not a DOM object, not a wrapper, just bail */
|
||||
return NS_ERROR_XPC_BAD_CONVERT_JS;
|
||||
}
|
||||
|
||||
obj = XPCWrapper::Unwrap(cx, obj, false);
|
||||
if (!obj) {
|
||||
return NS_ERROR_XPC_SECURITY_MANAGER_VETO;
|
||||
}
|
||||
MOZ_ASSERT(!js::IsWrapper(obj));
|
||||
clasp = js::GetObjectJSClass(obj);
|
||||
if (!IsDOMClass(clasp)) {
|
||||
/* We don't have a DOM object */
|
||||
return NS_ERROR_XPC_BAD_CONVERT_JS;
|
||||
}
|
||||
}
|
||||
|
||||
MOZ_ASSERT(IsDOMClass(clasp));
|
||||
|
||||
/* This object is a DOM object. Double-check that it is safely
|
||||
castable to T by checking whether it claims to inherit from the
|
||||
class identified by protoID. */
|
||||
DOMJSClass* domClass = DOMJSClass::FromJSClass(clasp);
|
||||
if (domClass->mInterfaceChain[PrototypeTraits<PrototypeID>::Depth] ==
|
||||
PrototypeID) {
|
||||
*value = UnwrapDOMObject<T>(obj, clasp);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* It's the wrong sort of DOM object */
|
||||
return NS_ERROR_XPC_BAD_CONVERT_JS;
|
||||
}
|
||||
|
||||
inline bool
|
||||
IsArrayLike(JSContext* cx, JSObject* obj)
|
||||
{
|
||||
MOZ_ASSERT(obj);
|
||||
// For simplicity, check for security wrappers up front
|
||||
if (js::IsWrapper(obj)) {
|
||||
obj = XPCWrapper::Unwrap(cx, obj, false);
|
||||
if (!obj) {
|
||||
// Let's say it's not
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// XXXbz need to detect platform objects (including listbinding
|
||||
// ones) with indexGetters here!
|
||||
return JS_IsArrayObject(cx, obj);
|
||||
}
|
||||
|
||||
inline bool
|
||||
IsPlatformObject(JSContext* cx, JSObject* obj)
|
||||
{
|
||||
// XXXbz Should be treating list-binding objects as platform objects
|
||||
// too? The one consumer so far wants non-array-like platform
|
||||
// objects, so listbindings that have an indexGetter should test
|
||||
// false from here. Maybe this function should have a different
|
||||
// name?
|
||||
MOZ_ASSERT(obj);
|
||||
// Fast-path the common case
|
||||
JSClass* clasp = js::GetObjectJSClass(obj);
|
||||
if (IsDOMClass(clasp)) {
|
||||
return true;
|
||||
}
|
||||
// Now for simplicity check for security wrappers before anything else
|
||||
if (js::IsWrapper(obj)) {
|
||||
obj = XPCWrapper::Unwrap(cx, obj, false);
|
||||
if (!obj) {
|
||||
// Let's say it's not
|
||||
return false;
|
||||
}
|
||||
clasp = js::GetObjectJSClass(obj);
|
||||
}
|
||||
return IS_WRAPPER_CLASS(js::Valueify(clasp)) || IsDOMClass(clasp) ||
|
||||
JS_IsArrayBufferObject(obj);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline nsresult
|
||||
UnwrapObject(JSContext* cx, JSObject* obj, T* *value)
|
||||
{
|
||||
return UnwrapObject<static_cast<prototypes::ID>(
|
||||
PrototypeIDMap<T>::PrototypeID)>(cx, obj, value);
|
||||
}
|
||||
|
||||
const size_t kProtoOrIfaceCacheCount =
|
||||
prototypes::id::_ID_Count + constructors::id::_ID_Count;
|
||||
|
||||
inline void
|
||||
AllocateProtoOrIfaceCache(JSObject* obj)
|
||||
{
|
||||
MOZ_ASSERT(js::GetObjectClass(obj)->flags & JSCLASS_DOM_GLOBAL);
|
||||
MOZ_ASSERT(js::GetReservedSlot(obj, DOM_PROTOTYPE_SLOT).isUndefined());
|
||||
|
||||
// Important: The () at the end ensure zero-initialization
|
||||
JSObject** protoOrIfaceArray = new JSObject*[kProtoOrIfaceCacheCount]();
|
||||
|
||||
js::SetReservedSlot(obj, DOM_PROTOTYPE_SLOT,
|
||||
JS::PrivateValue(protoOrIfaceArray));
|
||||
}
|
||||
|
||||
inline void
|
||||
DestroyProtoOrIfaceCache(JSObject* obj)
|
||||
{
|
||||
MOZ_ASSERT(js::GetObjectClass(obj)->flags & JSCLASS_DOM_GLOBAL);
|
||||
|
||||
JSObject** protoOrIfaceArray = GetProtoOrIfaceArray(obj);
|
||||
|
||||
delete [] protoOrIfaceArray;
|
||||
}
|
||||
|
||||
struct ConstantSpec
|
||||
{
|
||||
const char* name;
|
||||
JS::Value value;
|
||||
};
|
||||
|
||||
/*
|
||||
* Create a DOM interface object (if constructorClass is non-null) and/or a
|
||||
* DOM interface prototype object (if protoClass is non-null).
|
||||
*
|
||||
* parentProto is the prototype to use for the interface prototype object.
|
||||
* protoClass is the JSClass to use for the interface prototype object.
|
||||
* This is null if we should not create an interface prototype
|
||||
* object.
|
||||
* constructorClass is the JSClass to use for the interface object.
|
||||
* This is null if we should not create an interface object.
|
||||
* methods and properties are to be defined on the interface prototype object;
|
||||
* these arguments are allowed to be null if there are no
|
||||
* methods or properties respectively.
|
||||
* constants are to be defined on the interface object and on the interface
|
||||
* prototype object; allowed to be null if there are no constants.
|
||||
* staticMethods are to be defined on the interface object; allowed to be null
|
||||
* if there are no static methods.
|
||||
*
|
||||
* At least one of protoClass and constructorClass should be non-null.
|
||||
* If constructorClass is non-null, the resulting interface object will be
|
||||
* defined on the given global with property name |name|, which must also be
|
||||
* non-null.
|
||||
*
|
||||
* returns the interface prototype object if protoClass is non-null, else it
|
||||
* returns the interface object.
|
||||
*/
|
||||
JSObject*
|
||||
CreateInterfaceObjects(JSContext* cx, JSObject* global, JSObject* parentProto,
|
||||
JSClass* protoClass, JSClass* constructorClass,
|
||||
JSFunctionSpec* methods, JSPropertySpec* properties,
|
||||
ConstantSpec* constants, JSFunctionSpec* staticMethods,
|
||||
const char* name);
|
||||
|
||||
template <class T>
|
||||
inline bool
|
||||
WrapNewBindingObject(JSContext* cx, JSObject* scope, T* value, JS::Value* vp)
|
||||
{
|
||||
JSObject* obj = value->GetWrapper();
|
||||
if (obj && js::GetObjectCompartment(obj) == js::GetObjectCompartment(scope)) {
|
||||
*vp = JS::ObjectValue(*obj);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!obj) {
|
||||
bool triedToWrap;
|
||||
obj = value->WrapObject(cx, scope, &triedToWrap);
|
||||
if (!obj) {
|
||||
// At this point, obj is null, so just return false. We could
|
||||
// try to communicate triedToWrap to the caller, but in practice
|
||||
// callers seem to be testing JS_IsExceptionPending(cx) to
|
||||
// figure out whether WrapObject() threw instead.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Now make sure that |obj| is wrapped for the compartment of |scope|
|
||||
// correctly. That means entering the compartment of |scope|.
|
||||
JSAutoEnterCompartment ac;
|
||||
if (!ac.enter(cx, scope)) {
|
||||
return false;
|
||||
}
|
||||
*vp = JS::ObjectValue(*obj);
|
||||
return JS_WrapValue(cx, vp);
|
||||
}
|
||||
|
||||
// Helper for smart pointers (nsAutoPtr/nsRefPtr/nsCOMPtr).
|
||||
template <template <class> class SmartPtr, class T>
|
||||
inline bool
|
||||
WrapNewBindingObject(JSContext* cx, JSObject* scope, const SmartPtr<T>& value,
|
||||
JS::Value* vp)
|
||||
{
|
||||
return WrapNewBindingObject(cx, scope, value.get(), vp);
|
||||
}
|
||||
|
||||
/**
|
||||
* A method to handle new-binding wrap failure, by possibly falling back to
|
||||
* wrapping as a non-new-binding object.
|
||||
*/
|
||||
bool
|
||||
DoHandleNewBindingWrappingFailure(JSContext* cx, JSObject* scope,
|
||||
nsISupports* value, JS::Value* vp);
|
||||
|
||||
/**
|
||||
* An easy way to call the above when you have a value which
|
||||
* multiply-inherits from nsISupports.
|
||||
*/
|
||||
template <class T>
|
||||
bool
|
||||
HandleNewBindingWrappingFailure(JSContext* cx, JSObject* scope, T* value,
|
||||
JS::Value* vp)
|
||||
{
|
||||
nsCOMPtr<nsISupports> val;
|
||||
CallQueryInterface(value, getter_AddRefs(val));
|
||||
return DoHandleNewBindingWrappingFailure(cx, scope, val, vp);
|
||||
}
|
||||
|
||||
// Helper for smart pointers (nsAutoPtr/nsRefPtr/nsCOMPtr).
|
||||
template <template <class> class SmartPtr, class T>
|
||||
MOZ_ALWAYS_INLINE bool
|
||||
HandleNewBindingWrappingFailure(JSContext* cx, JSObject* scope,
|
||||
const SmartPtr<T>& value, JS::Value* vp)
|
||||
{
|
||||
return HandleNewBindingWrappingFailure(cx, scope, value.get(), vp);
|
||||
}
|
||||
|
||||
struct EnumEntry {
|
||||
const char* value;
|
||||
size_t length;
|
||||
};
|
||||
|
||||
inline int
|
||||
FindEnumStringIndex(JSContext* cx, JS::Value v, const EnumEntry* values, bool* ok)
|
||||
{
|
||||
// JS_StringEqualsAscii is slow as molasses, so don't use it here.
|
||||
JSString* str = JS_ValueToString(cx, v);
|
||||
if (!str) {
|
||||
*ok = false;
|
||||
return 0;
|
||||
}
|
||||
JS::Anchor<JSString*> anchor(str);
|
||||
size_t length;
|
||||
const jschar* chars = JS_GetStringCharsAndLength(cx, str, &length);
|
||||
if (!chars) {
|
||||
*ok = false;
|
||||
return 0;
|
||||
}
|
||||
int i = 0;
|
||||
for (const EnumEntry* value = values; value->value; ++value, ++i) {
|
||||
if (length != value->length) {
|
||||
continue;
|
||||
}
|
||||
|
||||
bool equal = true;
|
||||
const char* val = value->value;
|
||||
for (size_t j = 0; j != length; ++j) {
|
||||
if (unsigned(val[j]) != unsigned(chars[j])) {
|
||||
equal = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (equal) {
|
||||
*ok = true;
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
// XXX we don't know whether we're on the main thread, so play it safe
|
||||
*ok = Throw<false>(cx, NS_ERROR_XPC_BAD_CONVERT_JS);
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline nsWrapperCache*
|
||||
GetWrapperCache(nsWrapperCache* cache)
|
||||
{
|
||||
return cache;
|
||||
}
|
||||
|
||||
// nsGlobalWindow implements nsWrapperCache, but doesn't always use it. Don't
|
||||
// try to use it without fixing that first.
|
||||
class nsGlobalWindow;
|
||||
inline nsWrapperCache*
|
||||
GetWrapperCache(nsGlobalWindow* not_allowed);
|
||||
|
||||
inline nsWrapperCache*
|
||||
GetWrapperCache(void* p)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Only set allowNativeWrapper to false if you really know you need it, if in
|
||||
// doubt use true. Setting it to false disables security wrappers.
|
||||
bool
|
||||
XPCOMObjectToJsval(JSContext* cx, JSObject* scope, xpcObjectHelper &helper,
|
||||
const nsIID* iid, bool allowNativeWrapper, JS::Value* rval);
|
||||
|
||||
template<class T>
|
||||
inline bool
|
||||
WrapObject(JSContext* cx, JSObject* scope, T* p, nsWrapperCache* cache,
|
||||
const nsIID* iid, JS::Value* vp)
|
||||
{
|
||||
if (xpc_FastGetCachedWrapper(cache, scope, vp))
|
||||
return true;
|
||||
qsObjectHelper helper(p, cache);
|
||||
return XPCOMObjectToJsval(cx, scope, helper, iid, true, vp);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline bool
|
||||
WrapObject(JSContext* cx, JSObject* scope, T* p, const nsIID* iid,
|
||||
JS::Value* vp)
|
||||
{
|
||||
return WrapObject(cx, scope, p, GetWrapperCache(p), iid, vp);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline bool
|
||||
WrapObject(JSContext* cx, JSObject* scope, T* p, JS::Value* vp)
|
||||
{
|
||||
return WrapObject(cx, scope, p, NULL, vp);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline bool
|
||||
WrapObject(JSContext* cx, JSObject* scope, nsCOMPtr<T> &p, const nsIID* iid,
|
||||
JS::Value* vp)
|
||||
{
|
||||
return WrapObject(cx, scope, p.get(), iid, vp);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline bool
|
||||
WrapObject(JSContext* cx, JSObject* scope, nsCOMPtr<T> &p, JS::Value* vp)
|
||||
{
|
||||
return WrapObject(cx, scope, p, NULL, vp);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline bool
|
||||
WrapObject(JSContext* cx, JSObject* scope, nsRefPtr<T> &p, const nsIID* iid,
|
||||
JS::Value* vp)
|
||||
{
|
||||
return WrapObject(cx, scope, p.get(), iid, vp);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline bool
|
||||
WrapObject(JSContext* cx, JSObject* scope, nsRefPtr<T> &p, JS::Value* vp)
|
||||
{
|
||||
return WrapObject(cx, scope, p, NULL, vp);
|
||||
}
|
||||
|
||||
template<>
|
||||
inline bool
|
||||
WrapObject<JSObject>(JSContext* cx, JSObject* scope, JSObject* p, JS::Value* vp)
|
||||
{
|
||||
vp->setObjectOrNull(p);
|
||||
return true;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
static inline JSObject*
|
||||
WrapNativeParent(JSContext* cx, JSObject* scope, T* p)
|
||||
{
|
||||
if (!p)
|
||||
return scope;
|
||||
|
||||
nsWrapperCache* cache = GetWrapperCache(p);
|
||||
JSObject* obj;
|
||||
if (cache && (obj = cache->GetWrapper())) {
|
||||
#ifdef DEBUG
|
||||
qsObjectHelper helper(p, cache);
|
||||
JS::Value debugVal;
|
||||
|
||||
bool ok = XPCOMObjectToJsval(cx, scope, helper, NULL, false, &debugVal);
|
||||
NS_ASSERTION(ok && JSVAL_TO_OBJECT(debugVal) == obj,
|
||||
"Unexpected object in nsWrapperCache");
|
||||
#endif
|
||||
return obj;
|
||||
}
|
||||
|
||||
qsObjectHelper helper(p, cache);
|
||||
JS::Value v;
|
||||
return XPCOMObjectToJsval(cx, scope, helper, NULL, false, &v) ?
|
||||
JSVAL_TO_OBJECT(v) :
|
||||
NULL;
|
||||
}
|
||||
|
||||
// Spec needs a name property
|
||||
template <typename Spec>
|
||||
static bool
|
||||
InitIds(JSContext* cx, Spec* specs, jsid* ids)
|
||||
{
|
||||
Spec* spec = specs;
|
||||
do {
|
||||
JSString *str = ::JS_InternString(cx, spec->name);
|
||||
if (!str) {
|
||||
return false;
|
||||
}
|
||||
|
||||
*ids = INTERNED_STRING_TO_JSID(cx, str);
|
||||
} while (++ids, (++spec)->name);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
JSBool
|
||||
QueryInterface(JSContext* cx, unsigned argc, JS::Value* vp);
|
||||
|
||||
} // namespace bindings
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif /* mozilla_dom_bindings_Utils_h__ */
|
1
dom/bindings/parser/README
Normal file
1
dom/bindings/parser/README
Normal file
@ -0,0 +1 @@
|
||||
A WebIDL parser written in Python to be used in Mozilla.
|
1
dom/bindings/parser/UPSTREAM
Normal file
1
dom/bindings/parser/UPSTREAM
Normal file
@ -0,0 +1 @@
|
||||
http://dev.w3.org/cvsweb/~checkout~/2006/webapi/WebIDL/Overview.html?rev=1.409;content-type=text%2Fhtml%3b+charset=utf-8
|
2872
dom/bindings/parser/WebIDL.py
Normal file
2872
dom/bindings/parser/WebIDL.py
Normal file
File diff suppressed because it is too large
Load Diff
1
dom/bindings/parser/__init__.py
Normal file
1
dom/bindings/parser/__init__.py
Normal file
@ -0,0 +1 @@
|
||||
__all__ = ['WebIDL']
|
72
dom/bindings/parser/runtests.py
Normal file
72
dom/bindings/parser/runtests.py
Normal file
@ -0,0 +1,72 @@
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is WebIDL Parser.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# the Mozilla Foundation.
|
||||
# Portions created by the Initial Developer are Copyright (C) 2011
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
# Kyle Huey <me@kylehuey.com>
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
import os, sys
|
||||
import glob
|
||||
import WebIDL
|
||||
|
||||
class TestHarness(object):
|
||||
def ok(self, condition, msg):
|
||||
if condition:
|
||||
print "TEST-PASS | %s" % msg
|
||||
else:
|
||||
print "TEST-UNEXPECTED-FAIL | %s" % msg
|
||||
|
||||
def check(self, a, b, msg):
|
||||
if a == b:
|
||||
print "TEST-PASS | %s" % msg
|
||||
else:
|
||||
print "TEST-UNEXPECTED-FAIL | %s" % msg
|
||||
print "\tGot %s expected %s" % (a, b)
|
||||
|
||||
def run_tests():
|
||||
harness = TestHarness()
|
||||
|
||||
tests = glob.iglob("tests/*.py")
|
||||
sys.path.append("./tests")
|
||||
for test in tests:
|
||||
(testpath, ext) = os.path.splitext(os.path.basename(test))
|
||||
_test = __import__(testpath, globals(), locals(), ['WebIDLTest'])
|
||||
#try:
|
||||
_test.WebIDLTest.__call__(WebIDL.Parser(), harness)
|
||||
#except:
|
||||
# print "TEST-UNEXPECTED-FAIL | Unhandled exception in Test %s" % testpath
|
||||
# print sys.exc_info()[0]
|
||||
print "Test %s Complete\n" % testpath
|
||||
|
||||
if __name__ == '__main__':
|
||||
run_tests()
|
14
dom/bindings/parser/tests/test_any_null.py
Normal file
14
dom/bindings/parser/tests/test_any_null.py
Normal file
@ -0,0 +1,14 @@
|
||||
def WebIDLTest(parser, harness):
|
||||
threw = False
|
||||
try:
|
||||
parser.parse("""
|
||||
interface DoubleNull {
|
||||
attribute any? foo;
|
||||
};
|
||||
""")
|
||||
|
||||
results = parser.finish()
|
||||
except:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should have thrown.")
|
@ -0,0 +1,14 @@
|
||||
def WebIDLTest(parser, harness):
|
||||
threw = False
|
||||
try:
|
||||
parser.parse("""
|
||||
interface ArgumentIdentifierConflict {
|
||||
void foo(boolean arg1, boolean arg1);
|
||||
};
|
||||
""")
|
||||
|
||||
results = parser.finish()
|
||||
except:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should have thrown.")
|
14
dom/bindings/parser/tests/test_argument_novoid.py
Normal file
14
dom/bindings/parser/tests/test_argument_novoid.py
Normal file
@ -0,0 +1,14 @@
|
||||
def WebIDLTest(parser, harness):
|
||||
threw = False
|
||||
try:
|
||||
parser.parse("""
|
||||
interface VoidArgument1 {
|
||||
void foo(void arg2);
|
||||
};
|
||||
""")
|
||||
|
||||
results = parser.finish()
|
||||
except:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should have thrown.")
|
25
dom/bindings/parser/tests/test_arraybuffer.py
Normal file
25
dom/bindings/parser/tests/test_arraybuffer.py
Normal file
@ -0,0 +1,25 @@
|
||||
import WebIDL
|
||||
|
||||
def WebIDLTest(parser, harness):
|
||||
parser.parse("""
|
||||
interface TestArrayBuffer {
|
||||
attribute ArrayBuffer attr;
|
||||
void method(ArrayBuffer arg1, ArrayBuffer? arg2, ArrayBuffer[] arg3, sequence<ArrayBuffer> arg4);
|
||||
};
|
||||
""")
|
||||
|
||||
results = parser.finish()
|
||||
|
||||
iface = results[0]
|
||||
|
||||
harness.ok(True, "TestArrayBuffer interface parsed without error")
|
||||
harness.check(len(iface.members), 2, "Interface should have two members")
|
||||
|
||||
attr = iface.members[0]
|
||||
method = iface.members[1]
|
||||
|
||||
harness.ok(isinstance(attr, WebIDL.IDLAttribute), "Expect an IDLAttribute")
|
||||
harness.ok(isinstance(method, WebIDL.IDLMethod), "Expect an IDLMethod")
|
||||
|
||||
harness.check(str(attr.type), "ArrayBuffer", "Expect an ArrayBuffer type")
|
||||
harness.ok(attr.type.isArrayBuffer(), "Expect an ArrayBuffer type")
|
275
dom/bindings/parser/tests/test_attr.py
Normal file
275
dom/bindings/parser/tests/test_attr.py
Normal file
@ -0,0 +1,275 @@
|
||||
import WebIDL
|
||||
|
||||
def WebIDLTest(parser, harness):
|
||||
testData = [("::TestAttr%s::b", "b", "Byte%s", False),
|
||||
("::TestAttr%s::rb", "rb", "Byte%s", True),
|
||||
("::TestAttr%s::o", "o", "Octet%s", False),
|
||||
("::TestAttr%s::ro", "ro", "Octet%s", True),
|
||||
("::TestAttr%s::s", "s", "Short%s", False),
|
||||
("::TestAttr%s::rs", "rs", "Short%s", True),
|
||||
("::TestAttr%s::us", "us", "UnsignedShort%s", False),
|
||||
("::TestAttr%s::rus", "rus", "UnsignedShort%s", True),
|
||||
("::TestAttr%s::l", "l", "Long%s", False),
|
||||
("::TestAttr%s::rl", "rl", "Long%s", True),
|
||||
("::TestAttr%s::ul", "ul", "UnsignedLong%s", False),
|
||||
("::TestAttr%s::rul", "rul", "UnsignedLong%s", True),
|
||||
("::TestAttr%s::ll", "ll", "LongLong%s", False),
|
||||
("::TestAttr%s::rll", "rll", "LongLong%s", True),
|
||||
("::TestAttr%s::ull", "ull", "UnsignedLongLong%s", False),
|
||||
("::TestAttr%s::rull", "rull", "UnsignedLongLong%s", True),
|
||||
("::TestAttr%s::str", "str", "String%s", False),
|
||||
("::TestAttr%s::rstr", "rstr", "String%s", True),
|
||||
("::TestAttr%s::obj", "obj", "Object%s", False),
|
||||
("::TestAttr%s::robj", "robj", "Object%s", True),
|
||||
("::TestAttr%s::object", "object", "Object%s", False)]
|
||||
|
||||
parser.parse("""
|
||||
interface TestAttr {
|
||||
attribute byte b;
|
||||
readonly attribute byte rb;
|
||||
attribute octet o;
|
||||
readonly attribute octet ro;
|
||||
attribute short s;
|
||||
readonly attribute short rs;
|
||||
attribute unsigned short us;
|
||||
readonly attribute unsigned short rus;
|
||||
attribute long l;
|
||||
readonly attribute long rl;
|
||||
attribute unsigned long ul;
|
||||
readonly attribute unsigned long rul;
|
||||
attribute long long ll;
|
||||
readonly attribute long long rll;
|
||||
attribute unsigned long long ull;
|
||||
readonly attribute unsigned long long rull;
|
||||
attribute DOMString str;
|
||||
readonly attribute DOMString rstr;
|
||||
attribute object obj;
|
||||
readonly attribute object robj;
|
||||
attribute object _object;
|
||||
};
|
||||
|
||||
interface TestAttrNullable {
|
||||
attribute byte? b;
|
||||
readonly attribute byte? rb;
|
||||
attribute octet? o;
|
||||
readonly attribute octet? ro;
|
||||
attribute short? s;
|
||||
readonly attribute short? rs;
|
||||
attribute unsigned short? us;
|
||||
readonly attribute unsigned short? rus;
|
||||
attribute long? l;
|
||||
readonly attribute long? rl;
|
||||
attribute unsigned long? ul;
|
||||
readonly attribute unsigned long? rul;
|
||||
attribute long long? ll;
|
||||
readonly attribute long long? rll;
|
||||
attribute unsigned long long? ull;
|
||||
readonly attribute unsigned long long? rull;
|
||||
attribute DOMString? str;
|
||||
readonly attribute DOMString? rstr;
|
||||
attribute object? obj;
|
||||
readonly attribute object? robj;
|
||||
attribute object? _object;
|
||||
};
|
||||
|
||||
interface TestAttrArray {
|
||||
attribute byte[] b;
|
||||
readonly attribute byte[] rb;
|
||||
attribute octet[] o;
|
||||
readonly attribute octet[] ro;
|
||||
attribute short[] s;
|
||||
readonly attribute short[] rs;
|
||||
attribute unsigned short[] us;
|
||||
readonly attribute unsigned short[] rus;
|
||||
attribute long[] l;
|
||||
readonly attribute long[] rl;
|
||||
attribute unsigned long[] ul;
|
||||
readonly attribute unsigned long[] rul;
|
||||
attribute long long[] ll;
|
||||
readonly attribute long long[] rll;
|
||||
attribute unsigned long long[] ull;
|
||||
readonly attribute unsigned long long[] rull;
|
||||
attribute DOMString[] str;
|
||||
readonly attribute DOMString[] rstr;
|
||||
attribute object[] obj;
|
||||
readonly attribute object[] robj;
|
||||
attribute object[] _object;
|
||||
};
|
||||
|
||||
interface TestAttrNullableArray {
|
||||
attribute byte[]? b;
|
||||
readonly attribute byte[]? rb;
|
||||
attribute octet[]? o;
|
||||
readonly attribute octet[]? ro;
|
||||
attribute short[]? s;
|
||||
readonly attribute short[]? rs;
|
||||
attribute unsigned short[]? us;
|
||||
readonly attribute unsigned short[]? rus;
|
||||
attribute long[]? l;
|
||||
readonly attribute long[]? rl;
|
||||
attribute unsigned long[]? ul;
|
||||
readonly attribute unsigned long[]? rul;
|
||||
attribute long long[]? ll;
|
||||
readonly attribute long long[]? rll;
|
||||
attribute unsigned long long[]? ull;
|
||||
readonly attribute unsigned long long[]? rull;
|
||||
attribute DOMString[]? str;
|
||||
readonly attribute DOMString[]? rstr;
|
||||
attribute object[]? obj;
|
||||
readonly attribute object[]? robj;
|
||||
attribute object[]? _object;
|
||||
};
|
||||
|
||||
interface TestAttrArrayOfNullableTypes {
|
||||
attribute byte?[] b;
|
||||
readonly attribute byte?[] rb;
|
||||
attribute octet?[] o;
|
||||
readonly attribute octet?[] ro;
|
||||
attribute short?[] s;
|
||||
readonly attribute short?[] rs;
|
||||
attribute unsigned short?[] us;
|
||||
readonly attribute unsigned short?[] rus;
|
||||
attribute long?[] l;
|
||||
readonly attribute long?[] rl;
|
||||
attribute unsigned long?[] ul;
|
||||
readonly attribute unsigned long?[] rul;
|
||||
attribute long long?[] ll;
|
||||
readonly attribute long long?[] rll;
|
||||
attribute unsigned long long?[] ull;
|
||||
readonly attribute unsigned long long?[] rull;
|
||||
attribute DOMString?[] str;
|
||||
readonly attribute DOMString?[] rstr;
|
||||
attribute object?[] obj;
|
||||
readonly attribute object?[] robj;
|
||||
attribute object?[] _object;
|
||||
};
|
||||
|
||||
interface TestAttrNullableArrayOfNullableTypes {
|
||||
attribute byte?[]? b;
|
||||
readonly attribute byte?[]? rb;
|
||||
attribute octet?[]? o;
|
||||
readonly attribute octet?[]? ro;
|
||||
attribute short?[]? s;
|
||||
readonly attribute short?[]? rs;
|
||||
attribute unsigned short?[]? us;
|
||||
readonly attribute unsigned short?[]? rus;
|
||||
attribute long?[]? l;
|
||||
readonly attribute long?[]? rl;
|
||||
attribute unsigned long?[]? ul;
|
||||
readonly attribute unsigned long?[]? rul;
|
||||
attribute long long?[]? ll;
|
||||
readonly attribute long long?[]? rll;
|
||||
attribute unsigned long long?[]? ull;
|
||||
readonly attribute unsigned long long?[]? rull;
|
||||
attribute DOMString?[]? str;
|
||||
readonly attribute DOMString?[]? rstr;
|
||||
attribute object?[]? obj;
|
||||
readonly attribute object?[]? robj;
|
||||
attribute object?[]? _object;
|
||||
};
|
||||
""")
|
||||
|
||||
results = parser.finish()
|
||||
|
||||
def checkAttr(attr, QName, name, type, readonly):
|
||||
harness.ok(isinstance(attr, WebIDL.IDLAttribute),
|
||||
"Should be an IDLAttribute")
|
||||
harness.ok(attr.isAttr(), "Attr is an Attr")
|
||||
harness.ok(not attr.isMethod(), "Attr is not an method")
|
||||
harness.ok(not attr.isConst(), "Attr is not a const")
|
||||
harness.check(attr.identifier.QName(), QName, "Attr has the right QName")
|
||||
harness.check(attr.identifier.name, name, "Attr has the right name")
|
||||
harness.check(str(attr.type), type, "Attr has the right type")
|
||||
harness.check(attr.readonly, readonly, "Attr's readonly state is correct")
|
||||
|
||||
harness.ok(True, "TestAttr interface parsed without error.")
|
||||
harness.check(len(results), 6, "Should be six productions.")
|
||||
iface = results[0]
|
||||
harness.ok(isinstance(iface, WebIDL.IDLInterface),
|
||||
"Should be an IDLInterface")
|
||||
harness.check(iface.identifier.QName(), "::TestAttr", "Interface has the right QName")
|
||||
harness.check(iface.identifier.name, "TestAttr", "Interface has the right name")
|
||||
harness.check(len(iface.members), len(testData), "Expect %s members" % len(testData))
|
||||
|
||||
attrs = iface.members
|
||||
|
||||
for i in range(len(attrs)):
|
||||
data = testData[i]
|
||||
attr = attrs[i]
|
||||
(QName, name, type, readonly) = data
|
||||
checkAttr(attr, QName % "", name, type % "", readonly)
|
||||
|
||||
iface = results[1]
|
||||
harness.ok(isinstance(iface, WebIDL.IDLInterface),
|
||||
"Should be an IDLInterface")
|
||||
harness.check(iface.identifier.QName(), "::TestAttrNullable", "Interface has the right QName")
|
||||
harness.check(iface.identifier.name, "TestAttrNullable", "Interface has the right name")
|
||||
harness.check(len(iface.members), len(testData), "Expect %s members" % len(testData))
|
||||
|
||||
attrs = iface.members
|
||||
|
||||
for i in range(len(attrs)):
|
||||
data = testData[i]
|
||||
attr = attrs[i]
|
||||
(QName, name, type, readonly) = data
|
||||
checkAttr(attr, QName % "Nullable", name, type % "OrNull", readonly)
|
||||
|
||||
iface = results[2]
|
||||
harness.ok(isinstance(iface, WebIDL.IDLInterface),
|
||||
"Should be an IDLInterface")
|
||||
harness.check(iface.identifier.QName(), "::TestAttrArray", "Interface has the right QName")
|
||||
harness.check(iface.identifier.name, "TestAttrArray", "Interface has the right name")
|
||||
harness.check(len(iface.members), len(testData), "Expect %s members" % len(testData))
|
||||
|
||||
attrs = iface.members
|
||||
|
||||
for i in range(len(attrs)):
|
||||
data = testData[i]
|
||||
attr = attrs[i]
|
||||
(QName, name, type, readonly) = data
|
||||
checkAttr(attr, QName % "Array", name, type % "Array", readonly)
|
||||
|
||||
iface = results[3]
|
||||
harness.ok(isinstance(iface, WebIDL.IDLInterface),
|
||||
"Should be an IDLInterface")
|
||||
harness.check(iface.identifier.QName(), "::TestAttrNullableArray", "Interface has the right QName")
|
||||
harness.check(iface.identifier.name, "TestAttrNullableArray", "Interface has the right name")
|
||||
harness.check(len(iface.members), len(testData), "Expect %s members" % len(testData))
|
||||
|
||||
attrs = iface.members
|
||||
|
||||
for i in range(len(attrs)):
|
||||
data = testData[i]
|
||||
attr = attrs[i]
|
||||
(QName, name, type, readonly) = data
|
||||
checkAttr(attr, QName % "NullableArray", name, type % "ArrayOrNull", readonly)
|
||||
|
||||
iface = results[4]
|
||||
harness.ok(isinstance(iface, WebIDL.IDLInterface),
|
||||
"Should be an IDLInterface")
|
||||
harness.check(iface.identifier.QName(), "::TestAttrArrayOfNullableTypes", "Interface has the right QName")
|
||||
harness.check(iface.identifier.name, "TestAttrArrayOfNullableTypes", "Interface has the right name")
|
||||
harness.check(len(iface.members), len(testData), "Expect %s members" % len(testData))
|
||||
|
||||
attrs = iface.members
|
||||
|
||||
for i in range(len(attrs)):
|
||||
data = testData[i]
|
||||
attr = attrs[i]
|
||||
(QName, name, type, readonly) = data
|
||||
checkAttr(attr, QName % "ArrayOfNullableTypes", name, type % "OrNullArray", readonly)
|
||||
|
||||
iface = results[5]
|
||||
harness.ok(isinstance(iface, WebIDL.IDLInterface),
|
||||
"Should be an IDLInterface")
|
||||
harness.check(iface.identifier.QName(), "::TestAttrNullableArrayOfNullableTypes", "Interface has the right QName")
|
||||
harness.check(iface.identifier.name, "TestAttrNullableArrayOfNullableTypes", "Interface has the right name")
|
||||
harness.check(len(iface.members), len(testData), "Expect %s members" % len(testData))
|
||||
|
||||
attrs = iface.members
|
||||
|
||||
for i in range(len(attrs)):
|
||||
data = testData[i]
|
||||
attr = attrs[i]
|
||||
(QName, name, type, readonly) = data
|
||||
checkAttr(attr, QName % "NullableArrayOfNullableTypes", name, type % "OrNullArrayOrNull", readonly)
|
14
dom/bindings/parser/tests/test_attr_sequence_type.py
Normal file
14
dom/bindings/parser/tests/test_attr_sequence_type.py
Normal file
@ -0,0 +1,14 @@
|
||||
def WebIDLTest(parser, harness):
|
||||
threw = False
|
||||
try:
|
||||
parser.parse("""
|
||||
interface AttrSquenceType {
|
||||
attribute sequence<bool> foo;
|
||||
};
|
||||
""")
|
||||
|
||||
results = parser.finish()
|
||||
except:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should have thrown.")
|
41
dom/bindings/parser/tests/test_builtins.py
Normal file
41
dom/bindings/parser/tests/test_builtins.py
Normal file
@ -0,0 +1,41 @@
|
||||
import WebIDL
|
||||
|
||||
def WebIDLTest(parser, harness):
|
||||
parser.parse("""
|
||||
interface TestBuiltins {
|
||||
attribute boolean b;
|
||||
attribute byte s8;
|
||||
attribute octet u8;
|
||||
attribute short s16;
|
||||
attribute unsigned short u16;
|
||||
attribute long s32;
|
||||
attribute unsigned long u32;
|
||||
attribute long long s64;
|
||||
attribute unsigned long long u64;
|
||||
attribute DOMTimeStamp ts;
|
||||
};
|
||||
""")
|
||||
|
||||
results = parser.finish()
|
||||
|
||||
harness.ok(True, "TestBuiltins interface parsed without error.")
|
||||
harness.check(len(results), 1, "Should be one production")
|
||||
harness.ok(isinstance(results[0], WebIDL.IDLInterface),
|
||||
"Should be an IDLInterface")
|
||||
iface = results[0]
|
||||
harness.check(iface.identifier.QName(), "::TestBuiltins", "Interface has the right QName")
|
||||
harness.check(iface.identifier.name, "TestBuiltins", "Interface has the right name")
|
||||
harness.check(iface.parent, None, "Interface has no parent")
|
||||
|
||||
members = iface.members
|
||||
harness.check(len(members), 10, "Should be one production")
|
||||
|
||||
names = ["b", "s8", "u8", "s16", "u16", "s32", "u32", "s64", "u64", "ts"]
|
||||
types = ["Boolean", "Byte", "Octet", "Short", "UnsignedShort", "Long", "UnsignedLong", "LongLong", "UnsignedLongLong", "DOMTimeStamp"]
|
||||
for i in range(10):
|
||||
attr = members[i]
|
||||
harness.ok(isinstance(attr, WebIDL.IDLAttribute), "Should be an IDLAttribute")
|
||||
harness.check(attr.identifier.QName(), "::TestBuiltins::" + names[i], "Attr has correct QName")
|
||||
harness.check(attr.identifier.name, names[i], "Attr has correct name")
|
||||
harness.check(str(attr.type), types[i], "Attr type is the correct name")
|
||||
harness.ok(attr.type.isPrimitive(), "Should be a primitive type")
|
34
dom/bindings/parser/tests/test_callback.py
Normal file
34
dom/bindings/parser/tests/test_callback.py
Normal file
@ -0,0 +1,34 @@
|
||||
import WebIDL
|
||||
|
||||
def WebIDLTest(parser, harness):
|
||||
parser.parse("""
|
||||
interface TestCallback {
|
||||
attribute CallbackType? listener;
|
||||
};
|
||||
|
||||
callback CallbackType = boolean (unsigned long arg);
|
||||
""")
|
||||
|
||||
results = parser.finish()
|
||||
|
||||
harness.ok(True, "TestCallback interface parsed without error.")
|
||||
harness.check(len(results), 2, "Should be one production.")
|
||||
iface = results[0]
|
||||
harness.ok(isinstance(iface, WebIDL.IDLInterface),
|
||||
"Should be an IDLInterface")
|
||||
harness.check(iface.identifier.QName(), "::TestCallback", "Interface has the right QName")
|
||||
harness.check(iface.identifier.name, "TestCallback", "Interface has the right name")
|
||||
harness.check(len(iface.members), 1, "Expect %s members" % 1)
|
||||
|
||||
attr = iface.members[0]
|
||||
harness.ok(isinstance(attr, WebIDL.IDLAttribute),
|
||||
"Should be an IDLAttribute")
|
||||
harness.ok(attr.isAttr(), "Should be an attribute")
|
||||
harness.ok(not attr.isMethod(), "Attr is not an method")
|
||||
harness.ok(not attr.isConst(), "Attr is not a const")
|
||||
harness.check(attr.identifier.QName(), "::TestCallback::listener", "Attr has the right QName")
|
||||
harness.check(attr.identifier.name, "listener", "Attr has the right name")
|
||||
t = attr.type
|
||||
harness.ok(not isinstance(t, WebIDL.IDLWrapperType), "Attr has the right type")
|
||||
harness.ok(isinstance(t, WebIDL.IDLNullableType), "Attr has the right type")
|
||||
harness.ok(t.isCallback(), "Attr has the right type")
|
14
dom/bindings/parser/tests/test_callback_interface.py
Normal file
14
dom/bindings/parser/tests/test_callback_interface.py
Normal file
@ -0,0 +1,14 @@
|
||||
import WebIDL
|
||||
|
||||
def WebIDLTest(parser, harness):
|
||||
parser.parse("""
|
||||
callback interface TestCallbackInterface {
|
||||
attribute boolean bool;
|
||||
};
|
||||
""")
|
||||
|
||||
results = parser.finish()
|
||||
|
||||
iface = results[0]
|
||||
|
||||
harness.ok(iface.isCallback(), "Interface should be a callback")
|
64
dom/bindings/parser/tests/test_const.py
Normal file
64
dom/bindings/parser/tests/test_const.py
Normal file
@ -0,0 +1,64 @@
|
||||
import WebIDL
|
||||
|
||||
def WebIDLTest(parser, harness):
|
||||
parser.parse("""
|
||||
interface TestConsts {
|
||||
const byte zero = 0;
|
||||
const byte b = -1;
|
||||
const octet o = 2;
|
||||
const short s = -3;
|
||||
const unsigned short us = 0x4;
|
||||
const long l = -0X5;
|
||||
const unsigned long ul = 6;
|
||||
const unsigned long long ull = 7;
|
||||
const long long ll = -010;
|
||||
const boolean t = true;
|
||||
const boolean f = false;
|
||||
const boolean? n = null;
|
||||
const boolean? nt = true;
|
||||
const boolean? nf = false;
|
||||
};
|
||||
""")
|
||||
|
||||
results = parser.finish()
|
||||
|
||||
harness.ok(True, "TestConsts interface parsed without error.")
|
||||
harness.check(len(results), 1, "Should be one production.")
|
||||
iface = results[0]
|
||||
harness.ok(isinstance(iface, WebIDL.IDLInterface),
|
||||
"Should be an IDLInterface")
|
||||
harness.check(iface.identifier.QName(), "::TestConsts", "Interface has the right QName")
|
||||
harness.check(iface.identifier.name, "TestConsts", "Interface has the right name")
|
||||
harness.check(len(iface.members), 14, "Expect 14 members")
|
||||
|
||||
consts = iface.members
|
||||
|
||||
def checkConst(const, QName, name, type, value):
|
||||
harness.ok(isinstance(const, WebIDL.IDLConst),
|
||||
"Should be an IDLConst")
|
||||
harness.ok(const.isConst(), "Const is a const")
|
||||
harness.ok(not const.isAttr(), "Const is not an attr")
|
||||
harness.ok(not const.isMethod(), "Const is not a method")
|
||||
harness.check(const.identifier.QName(), QName, "Const has the right QName")
|
||||
harness.check(const.identifier.name, name, "Const has the right name")
|
||||
harness.check(str(const.type), type, "Const has the right type")
|
||||
harness.ok(const.type.isPrimitive(), "All consts should be primitive")
|
||||
harness.check(str(const.value.type), str(const.type),
|
||||
"Const's value has the same type as the type")
|
||||
harness.check(const.value.value, value, "Const value has the right value.")
|
||||
|
||||
checkConst(consts[0], "::TestConsts::zero", "zero", "Byte", 0)
|
||||
checkConst(consts[1], "::TestConsts::b", "b", "Byte", -1)
|
||||
checkConst(consts[2], "::TestConsts::o", "o", "Octet", 2)
|
||||
checkConst(consts[3], "::TestConsts::s", "s", "Short", -3)
|
||||
checkConst(consts[4], "::TestConsts::us", "us", "UnsignedShort", 4)
|
||||
checkConst(consts[5], "::TestConsts::l", "l", "Long", -5)
|
||||
checkConst(consts[6], "::TestConsts::ul", "ul", "UnsignedLong", 6)
|
||||
checkConst(consts[7], "::TestConsts::ull", "ull", "UnsignedLongLong", 7)
|
||||
checkConst(consts[8], "::TestConsts::ll", "ll", "LongLong", -8)
|
||||
checkConst(consts[9], "::TestConsts::t", "t", "Boolean", True)
|
||||
checkConst(consts[10], "::TestConsts::f", "f", "Boolean", False)
|
||||
checkConst(consts[11], "::TestConsts::n", "n", "BooleanOrNull", None)
|
||||
checkConst(consts[12], "::TestConsts::nt", "nt", "BooleanOrNull", True)
|
||||
checkConst(consts[13], "::TestConsts::nf", "nf", "BooleanOrNull", False)
|
||||
|
75
dom/bindings/parser/tests/test_constructor.py
Normal file
75
dom/bindings/parser/tests/test_constructor.py
Normal file
@ -0,0 +1,75 @@
|
||||
import WebIDL
|
||||
|
||||
def WebIDLTest(parser, harness):
|
||||
def checkArgument(argument, QName, name, type, optional, variadic):
|
||||
harness.ok(isinstance(argument, WebIDL.IDLArgument),
|
||||
"Should be an IDLArgument")
|
||||
harness.check(argument.identifier.QName(), QName, "Argument has the right QName")
|
||||
harness.check(argument.identifier.name, name, "Argument has the right name")
|
||||
harness.check(str(argument.type), type, "Argument has the right return type")
|
||||
harness.check(argument.optional, optional, "Argument has the right optional value")
|
||||
harness.check(argument.variadic, variadic, "Argument has the right variadic value")
|
||||
|
||||
def checkMethod(method, QName, name, signatures,
|
||||
static=False, getter=False, setter=False, creator=False,
|
||||
deleter=False, legacycaller=False, stringifier=False):
|
||||
harness.ok(isinstance(method, WebIDL.IDLMethod),
|
||||
"Should be an IDLMethod")
|
||||
harness.ok(method.isMethod(), "Method is a method")
|
||||
harness.ok(not method.isAttr(), "Method is not an attr")
|
||||
harness.ok(not method.isConst(), "Method is not a const")
|
||||
harness.check(method.identifier.QName(), QName, "Method has the right QName")
|
||||
harness.check(method.identifier.name, name, "Method has the right name")
|
||||
harness.check(method.isStatic(), static, "Method has the correct static value")
|
||||
harness.check(method.isGetter(), getter, "Method has the correct getter value")
|
||||
harness.check(method.isSetter(), setter, "Method has the correct setter value")
|
||||
harness.check(method.isCreator(), creator, "Method has the correct creator value")
|
||||
harness.check(method.isDeleter(), deleter, "Method has the correct deleter value")
|
||||
harness.check(method.isLegacycaller(), legacycaller, "Method has the correct legacycaller value")
|
||||
harness.check(method.isStringifier(), stringifier, "Method has the correct stringifier value")
|
||||
harness.check(len(method.signatures()), len(signatures), "Method has the correct number of signatures")
|
||||
|
||||
sigpairs = zip(method.signatures(), signatures)
|
||||
for (gotSignature, expectedSignature) in sigpairs:
|
||||
(gotRetType, gotArgs) = gotSignature
|
||||
(expectedRetType, expectedArgs) = expectedSignature
|
||||
|
||||
harness.check(str(gotRetType), expectedRetType,
|
||||
"Method has the expected return type.")
|
||||
|
||||
for i in range(0, len(gotArgs)):
|
||||
(QName, name, type, optional, variadic) = expectedArgs[i]
|
||||
checkArgument(gotArgs[i], QName, name, type, optional, variadic)
|
||||
|
||||
parser.parse("""
|
||||
[Constructor]
|
||||
interface TestConstructorNoArgs {
|
||||
};
|
||||
|
||||
[Constructor(DOMString name)]
|
||||
interface TestConstructorWithArgs {
|
||||
};
|
||||
|
||||
[Constructor(object foo), Constructor(boolean bar)]
|
||||
interface TestConstructorOverloads {
|
||||
};
|
||||
""")
|
||||
results = parser.finish()
|
||||
harness.check(len(results), 3, "Should be two productions")
|
||||
harness.ok(isinstance(results[0], WebIDL.IDLInterface),
|
||||
"Should be an IDLInterface")
|
||||
harness.ok(isinstance(results[1], WebIDL.IDLInterface),
|
||||
"Should be an IDLInterface")
|
||||
|
||||
checkMethod(results[0].ctor(), "::TestConstructorNoArgs::constructor",
|
||||
"constructor", [("TestConstructorNoArgs", [])])
|
||||
checkMethod(results[1].ctor(), "::TestConstructorWithArgs::constructor",
|
||||
"constructor",
|
||||
[("TestConstructorWithArgs",
|
||||
[("::TestConstructorWithArgs::constructor::name", "name", "String", False, False)])])
|
||||
checkMethod(results[2].ctor(), "::TestConstructorOverloads::constructor",
|
||||
"constructor",
|
||||
[("TestConstructorOverloads",
|
||||
[("::TestConstructorOverloads::constructor::foo", "foo", "Object", False, False)]),
|
||||
("TestConstructorOverloads",
|
||||
[("::TestConstructorOverloads::constructor::bar", "bar", "Boolean", False, False)])])
|
@ -0,0 +1,28 @@
|
||||
def WebIDLTest(parser, harness):
|
||||
threw = False
|
||||
try:
|
||||
parser.parse("""
|
||||
[Constructor, NoInterfaceObject]
|
||||
interface TestConstructorNoInterfaceObject {
|
||||
};
|
||||
""")
|
||||
|
||||
results = parser.finish()
|
||||
except:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should have thrown.")
|
||||
|
||||
threw = False
|
||||
try:
|
||||
parser.parse("""
|
||||
[NoInterfaceObject, Constructor]
|
||||
interface TestConstructorNoInterfaceObject {
|
||||
};
|
||||
""")
|
||||
|
||||
results = parser.finish()
|
||||
except:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should have thrown.")
|
14
dom/bindings/parser/tests/test_double_null.py
Normal file
14
dom/bindings/parser/tests/test_double_null.py
Normal file
@ -0,0 +1,14 @@
|
||||
def WebIDLTest(parser, harness):
|
||||
threw = False
|
||||
try:
|
||||
parser.parse("""
|
||||
interface DoubleNull {
|
||||
attribute byte?? foo;
|
||||
};
|
||||
""")
|
||||
|
||||
results = parser.finish()
|
||||
except:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should have thrown.")
|
84
dom/bindings/parser/tests/test_duplicate_qualifiers.py
Normal file
84
dom/bindings/parser/tests/test_duplicate_qualifiers.py
Normal file
@ -0,0 +1,84 @@
|
||||
def WebIDLTest(parser, harness):
|
||||
threw = False
|
||||
try:
|
||||
parser.parse("""
|
||||
interface DuplicateQualifiers1 {
|
||||
getter getter byte foo(unsigned long index);
|
||||
};
|
||||
""")
|
||||
|
||||
results = parser.finish()
|
||||
except:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should have thrown.")
|
||||
|
||||
threw = False
|
||||
try:
|
||||
parser.parse("""
|
||||
interface DuplicateQualifiers2 {
|
||||
setter setter byte foo(unsigned long index, byte value);
|
||||
};
|
||||
""")
|
||||
|
||||
results = parser.finish()
|
||||
except:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should have thrown.")
|
||||
|
||||
threw = False
|
||||
try:
|
||||
parser.parse("""
|
||||
interface DuplicateQualifiers3 {
|
||||
creator creator byte foo(unsigned long index, byte value);
|
||||
};
|
||||
""")
|
||||
|
||||
results = parser.finish()
|
||||
except:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should have thrown.")
|
||||
|
||||
threw = False
|
||||
try:
|
||||
parser.parse("""
|
||||
interface DuplicateQualifiers4 {
|
||||
deleter deleter byte foo(unsigned long index);
|
||||
};
|
||||
""")
|
||||
|
||||
results = parser.finish()
|
||||
except:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should have thrown.")
|
||||
|
||||
threw = False
|
||||
try:
|
||||
parser.parse("""
|
||||
interface DuplicateQualifiers5 {
|
||||
getter deleter getter byte foo(unsigned long index);
|
||||
};
|
||||
""")
|
||||
|
||||
results = parser.finish()
|
||||
except:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should have thrown.")
|
||||
|
||||
threw = False
|
||||
try:
|
||||
results = parser.parse("""
|
||||
interface DuplicateQualifiers6 {
|
||||
creator setter creator byte foo(unsigned long index, byte value);
|
||||
};
|
||||
""")
|
||||
|
||||
results = parser.finish()
|
||||
except:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should have thrown.")
|
14
dom/bindings/parser/tests/test_empty_enum.py
Normal file
14
dom/bindings/parser/tests/test_empty_enum.py
Normal file
@ -0,0 +1,14 @@
|
||||
import WebIDL
|
||||
|
||||
def WebIDLTest(parser, harness):
|
||||
try:
|
||||
parser.parse("""
|
||||
enum TestEmptyEnum {
|
||||
};
|
||||
""")
|
||||
|
||||
harness.ok(False, "Should have thrown!")
|
||||
except:
|
||||
harness.ok(True, "Parsing TestEmptyEnum enum should fail")
|
||||
|
||||
results = parser.finish()
|
61
dom/bindings/parser/tests/test_enum.py
Normal file
61
dom/bindings/parser/tests/test_enum.py
Normal file
@ -0,0 +1,61 @@
|
||||
import WebIDL
|
||||
|
||||
def WebIDLTest(parser, harness):
|
||||
parser.parse("""
|
||||
enum TestEnum {
|
||||
"",
|
||||
"foo",
|
||||
"bar"
|
||||
};
|
||||
|
||||
interface TestEnumInterface {
|
||||
TestEnum doFoo(boolean arg);
|
||||
readonly attribute TestEnum foo;
|
||||
};
|
||||
""")
|
||||
|
||||
results = parser.finish()
|
||||
|
||||
harness.ok(True, "TestEnumInterfaces interface parsed without error.")
|
||||
harness.check(len(results), 2, "Should be one production")
|
||||
harness.ok(isinstance(results[0], WebIDL.IDLEnum),
|
||||
"Should be an IDLEnum")
|
||||
harness.ok(isinstance(results[1], WebIDL.IDLInterface),
|
||||
"Should be an IDLInterface")
|
||||
|
||||
enum = results[0]
|
||||
harness.check(enum.identifier.QName(), "::TestEnum", "Enum has the right QName")
|
||||
harness.check(enum.identifier.name, "TestEnum", "Enum has the right name")
|
||||
harness.check(enum.values(), ["", "foo", "bar"], "Enum has the right values")
|
||||
|
||||
iface = results[1]
|
||||
|
||||
harness.check(iface.identifier.QName(), "::TestEnumInterface", "Interface has the right QName")
|
||||
harness.check(iface.identifier.name, "TestEnumInterface", "Interface has the right name")
|
||||
harness.check(iface.parent, None, "Interface has no parent")
|
||||
|
||||
members = iface.members
|
||||
harness.check(len(members), 2, "Should be one production")
|
||||
harness.ok(isinstance(members[0], WebIDL.IDLMethod),
|
||||
"Should be an IDLMethod")
|
||||
method = members[0]
|
||||
harness.check(method.identifier.QName(), "::TestEnumInterface::doFoo",
|
||||
"Method has correct QName")
|
||||
harness.check(method.identifier.name, "doFoo", "Method has correct name")
|
||||
|
||||
signatures = method.signatures()
|
||||
harness.check(len(signatures), 1, "Expect one signature")
|
||||
|
||||
(returnType, arguments) = signatures[0]
|
||||
harness.check(str(returnType), "TestEnum", "Method type is the correct name")
|
||||
harness.check(len(arguments), 1, "Method has the right number of arguments")
|
||||
arg = arguments[0]
|
||||
harness.ok(isinstance(arg, WebIDL.IDLArgument), "Should be an IDLArgument")
|
||||
harness.check(str(arg.type), "Boolean", "Argument has the right type")
|
||||
|
||||
attr = members[1]
|
||||
harness.check(attr.identifier.QName(), "::TestEnumInterface::foo",
|
||||
"Attr has correct QName")
|
||||
harness.check(attr.identifier.name, "foo", "Attr has correct name")
|
||||
|
||||
harness.check(str(attr.type), "TestEnum", "Attr type is the correct name")
|
13
dom/bindings/parser/tests/test_enum_duplicate_values.py
Normal file
13
dom/bindings/parser/tests/test_enum_duplicate_values.py
Normal file
@ -0,0 +1,13 @@
|
||||
import WebIDL
|
||||
|
||||
def WebIDLTest(parser, harness):
|
||||
try:
|
||||
parser.parse("""
|
||||
enum TestEnumDuplicateValue {
|
||||
"",
|
||||
""
|
||||
};
|
||||
""")
|
||||
harness.ok(False, "Should have thrown!")
|
||||
except:
|
||||
harness.ok(True, "Enum TestEnumDuplicateValue should throw")
|
11
dom/bindings/parser/tests/test_extended_attributes.py
Normal file
11
dom/bindings/parser/tests/test_extended_attributes.py
Normal file
@ -0,0 +1,11 @@
|
||||
import WebIDL
|
||||
|
||||
def WebIDLTest(parser, harness):
|
||||
parser.parse("""
|
||||
[Flippety]
|
||||
interface TestExtendedAttr {
|
||||
[Foopy] attribute byte b;
|
||||
};
|
||||
""")
|
||||
|
||||
results = parser.finish()
|
15
dom/bindings/parser/tests/test_forward_decl.py
Normal file
15
dom/bindings/parser/tests/test_forward_decl.py
Normal file
@ -0,0 +1,15 @@
|
||||
import WebIDL
|
||||
|
||||
def WebIDLTest(parser, harness):
|
||||
parser.parse("""
|
||||
interface ForwardDeclared;
|
||||
interface ForwardDeclared;
|
||||
|
||||
interface TestForwardDecl {
|
||||
attribute ForwardDeclared foo;
|
||||
};
|
||||
""")
|
||||
|
||||
results = parser.finish()
|
||||
|
||||
harness.ok(True, "TestForwardDeclared interface parsed without error.")
|
18
dom/bindings/parser/tests/test_incomplete_parent.py
Normal file
18
dom/bindings/parser/tests/test_incomplete_parent.py
Normal file
@ -0,0 +1,18 @@
|
||||
import WebIDL
|
||||
|
||||
def WebIDLTest(parser, harness):
|
||||
parser.parse("""
|
||||
interface TestIncompleteParent : NotYetDefined {
|
||||
void foo();
|
||||
};
|
||||
|
||||
interface NotYetDefined : EvenHigherOnTheChain {
|
||||
};
|
||||
|
||||
interface EvenHigherOnTheChain {
|
||||
};
|
||||
""")
|
||||
|
||||
parser.finish()
|
||||
|
||||
harness.ok(True, "TestIncompleteParent interface parsed without error.")
|
44
dom/bindings/parser/tests/test_incomplete_types.py
Normal file
44
dom/bindings/parser/tests/test_incomplete_types.py
Normal file
@ -0,0 +1,44 @@
|
||||
import WebIDL
|
||||
|
||||
def WebIDLTest(parser, harness):
|
||||
parser.parse("""
|
||||
interface TestIncompleteTypes {
|
||||
attribute FooInterface attr1;
|
||||
|
||||
FooInterface method1(FooInterface arg);
|
||||
};
|
||||
|
||||
interface FooInterface {
|
||||
};
|
||||
""")
|
||||
|
||||
results = parser.finish()
|
||||
|
||||
harness.ok(True, "TestIncompleteTypes interface parsed without error.")
|
||||
harness.check(len(results), 2, "Should be two productions.")
|
||||
iface = results[0]
|
||||
harness.ok(isinstance(iface, WebIDL.IDLInterface),
|
||||
"Should be an IDLInterface")
|
||||
harness.check(iface.identifier.QName(), "::TestIncompleteTypes", "Interface has the right QName")
|
||||
harness.check(iface.identifier.name, "TestIncompleteTypes", "Interface has the right name")
|
||||
harness.check(len(iface.members), 2, "Expect 2 members")
|
||||
|
||||
attr = iface.members[0]
|
||||
harness.ok(isinstance(attr, WebIDL.IDLAttribute),
|
||||
"Should be an IDLAttribute")
|
||||
method = iface.members[1]
|
||||
harness.ok(isinstance(method, WebIDL.IDLMethod),
|
||||
"Should be an IDLMethod")
|
||||
|
||||
harness.check(attr.identifier.QName(), "::TestIncompleteTypes::attr1",
|
||||
"Attribute has the right QName")
|
||||
harness.check(attr.type.name.QName(), "::FooInterface",
|
||||
"Previously unresolved type has the right name")
|
||||
|
||||
harness.check(method.identifier.QName(), "::TestIncompleteTypes::method1",
|
||||
"Attribute has the right QName")
|
||||
(returnType, args) = method.signatures()[0]
|
||||
harness.check(returnType.name.QName(), "::FooInterface",
|
||||
"Previously unresolved type has the right name")
|
||||
harness.check(args[0].type.name.QName(), "::FooInterface",
|
||||
"Previously unresolved type has the right name")
|
54
dom/bindings/parser/tests/test_interface.py
Normal file
54
dom/bindings/parser/tests/test_interface.py
Normal file
@ -0,0 +1,54 @@
|
||||
import WebIDL
|
||||
|
||||
def WebIDLTest(parser, harness):
|
||||
parser.parse("interface Foo { };")
|
||||
results = parser.finish()
|
||||
harness.ok(True, "Empty interface parsed without error.")
|
||||
harness.check(len(results), 1, "Should be one production")
|
||||
harness.ok(isinstance(results[0], WebIDL.IDLInterface),
|
||||
"Should be an IDLInterface")
|
||||
iface = results[0]
|
||||
harness.check(iface.identifier.QName(), "::Foo", "Interface has the right QName")
|
||||
harness.check(iface.identifier.name, "Foo", "Interface has the right name")
|
||||
harness.check(iface.parent, None, "Interface has no parent")
|
||||
|
||||
parser.parse("interface Bar : Foo { };")
|
||||
results = parser.finish()
|
||||
harness.ok(True, "Empty interface parsed without error.")
|
||||
harness.check(len(results), 2, "Should be two productions")
|
||||
harness.ok(isinstance(results[1], WebIDL.IDLInterface),
|
||||
"Should be an IDLInterface")
|
||||
iface = results[1]
|
||||
harness.check(iface.identifier.QName(), "::Bar", "Interface has the right QName")
|
||||
harness.check(iface.identifier.name, "Bar", "Interface has the right name")
|
||||
harness.ok(isinstance(iface.parent, WebIDL.IDLInterface),
|
||||
"Interface has a parent")
|
||||
|
||||
parser = parser.reset()
|
||||
parser.parse("""
|
||||
interface QNameBase {
|
||||
attribute long foo;
|
||||
};
|
||||
|
||||
interface QNameDerived : QNameBase {
|
||||
attribute long long foo;
|
||||
attribute byte bar;
|
||||
};
|
||||
""")
|
||||
results = parser.finish()
|
||||
harness.check(len(results), 2, "Should be two productions")
|
||||
harness.ok(isinstance(results[0], WebIDL.IDLInterface),
|
||||
"Should be an IDLInterface")
|
||||
harness.ok(isinstance(results[1], WebIDL.IDLInterface),
|
||||
"Should be an IDLInterface")
|
||||
harness.check(results[1].parent, results[0], "Inheritance chain is right")
|
||||
harness.check(len(results[0].members), 1, "Expect 1 productions")
|
||||
harness.check(len(results[1].members), 2, "Expect 2 productions")
|
||||
base = results[0]
|
||||
derived = results[1]
|
||||
harness.check(base.members[0].identifier.QName(), "::QNameBase::foo",
|
||||
"Member has the right QName")
|
||||
harness.check(derived.members[0].identifier.QName(), "::QNameDerived::foo",
|
||||
"Member has the right QName")
|
||||
harness.check(derived.members[1].identifier.QName(), "::QNameDerived::bar",
|
||||
"Member has the right QName")
|
@ -0,0 +1,15 @@
|
||||
def WebIDLTest(parser, harness):
|
||||
threw = False
|
||||
try:
|
||||
parser.parse("""
|
||||
interface IdentifierConflict {
|
||||
const byte thing1 = 1;
|
||||
const unsigned long thing1 = 1;
|
||||
};
|
||||
""")
|
||||
|
||||
results = parser.finish()
|
||||
except:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should have thrown.")
|
@ -0,0 +1,60 @@
|
||||
def WebIDLTest(parser, harness):
|
||||
threw = False
|
||||
try:
|
||||
parser.parse("""
|
||||
interface IdentifierConflictAcrossMembers1 {
|
||||
const byte thing1 = 1;
|
||||
readonly attribute long thing1;
|
||||
};
|
||||
""")
|
||||
|
||||
results = parser.finish()
|
||||
except:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should have thrown.")
|
||||
|
||||
threw = False
|
||||
try:
|
||||
parser.parse("""
|
||||
interface IdentifierConflictAcrossMembers2 {
|
||||
readonly attribute long thing1;
|
||||
const byte thing1 = 1;
|
||||
};
|
||||
""")
|
||||
|
||||
results = parser.finish()
|
||||
except:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should have thrown.")
|
||||
|
||||
threw = False
|
||||
try:
|
||||
parser.parse("""
|
||||
interface IdentifierConflictAcrossMembers3 {
|
||||
getter boolean thing1(DOMString name);
|
||||
readonly attribute long thing1;
|
||||
};
|
||||
""")
|
||||
|
||||
results = parser.finish()
|
||||
except:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should have thrown.")
|
||||
|
||||
threw = False
|
||||
try:
|
||||
parser.parse("""
|
||||
interface IdentifierConflictAcrossMembers1 {
|
||||
const byte thing1 = 1;
|
||||
long thing1();
|
||||
};
|
||||
""")
|
||||
|
||||
results = parser.finish()
|
||||
except:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should have thrown.")
|
114
dom/bindings/parser/tests/test_method.py
Normal file
114
dom/bindings/parser/tests/test_method.py
Normal file
@ -0,0 +1,114 @@
|
||||
import WebIDL
|
||||
|
||||
def WebIDLTest(parser, harness):
|
||||
parser.parse("""
|
||||
interface TestMethods {
|
||||
void basic();
|
||||
static void basicStatic();
|
||||
void basicWithSimpleArgs(boolean arg1, byte arg2, unsigned long arg3);
|
||||
boolean basicBoolean();
|
||||
static boolean basicStaticBoolean();
|
||||
boolean basicBooleanWithSimpleArgs(boolean arg1, byte arg2, unsigned long arg3);
|
||||
void optionalArg(optional byte? arg1, optional sequence<byte> arg2);
|
||||
void variadicArg(byte?... arg1);
|
||||
void crazyTypes(sequence<long?[]>? arg1, boolean?[][]? arg2);
|
||||
object getObject();
|
||||
void setObject(object arg1);
|
||||
void setAny(any arg1);
|
||||
};
|
||||
""")
|
||||
|
||||
results = parser.finish()
|
||||
|
||||
harness.ok(True, "TestMethods interface parsed without error.")
|
||||
harness.check(len(results), 1, "Should be one production.")
|
||||
iface = results[0]
|
||||
harness.ok(isinstance(iface, WebIDL.IDLInterface),
|
||||
"Should be an IDLInterface")
|
||||
harness.check(iface.identifier.QName(), "::TestMethods", "Interface has the right QName")
|
||||
harness.check(iface.identifier.name, "TestMethods", "Interface has the right name")
|
||||
harness.check(len(iface.members), 12, "Expect 12 members")
|
||||
|
||||
methods = iface.members
|
||||
|
||||
def checkArgument(argument, QName, name, type, optional, variadic):
|
||||
harness.ok(isinstance(argument, WebIDL.IDLArgument),
|
||||
"Should be an IDLArgument")
|
||||
harness.check(argument.identifier.QName(), QName, "Argument has the right QName")
|
||||
harness.check(argument.identifier.name, name, "Argument has the right name")
|
||||
harness.check(str(argument.type), type, "Argument has the right return type")
|
||||
harness.check(argument.optional, optional, "Argument has the right optional value")
|
||||
harness.check(argument.variadic, variadic, "Argument has the right variadic value")
|
||||
|
||||
def checkMethod(method, QName, name, signatures,
|
||||
static=False, getter=False, setter=False, creator=False,
|
||||
deleter=False, legacycaller=False, stringifier=False):
|
||||
harness.ok(isinstance(method, WebIDL.IDLMethod),
|
||||
"Should be an IDLMethod")
|
||||
harness.ok(method.isMethod(), "Method is a method")
|
||||
harness.ok(not method.isAttr(), "Method is not an attr")
|
||||
harness.ok(not method.isConst(), "Method is not a const")
|
||||
harness.check(method.identifier.QName(), QName, "Method has the right QName")
|
||||
harness.check(method.identifier.name, name, "Method has the right name")
|
||||
harness.check(method.isStatic(), static, "Method has the correct static value")
|
||||
harness.check(method.isGetter(), getter, "Method has the correct getter value")
|
||||
harness.check(method.isSetter(), setter, "Method has the correct setter value")
|
||||
harness.check(method.isCreator(), creator, "Method has the correct creator value")
|
||||
harness.check(method.isDeleter(), deleter, "Method has the correct deleter value")
|
||||
harness.check(method.isLegacycaller(), legacycaller, "Method has the correct legacycaller value")
|
||||
harness.check(method.isStringifier(), stringifier, "Method has the correct stringifier value")
|
||||
harness.check(len(method.signatures()), len(signatures), "Method has the correct number of signatures")
|
||||
|
||||
sigpairs = zip(method.signatures(), signatures)
|
||||
for (gotSignature, expectedSignature) in sigpairs:
|
||||
(gotRetType, gotArgs) = gotSignature
|
||||
(expectedRetType, expectedArgs) = expectedSignature
|
||||
|
||||
harness.check(str(gotRetType), expectedRetType,
|
||||
"Method has the expected return type.")
|
||||
|
||||
for i in range(0, len(gotArgs)):
|
||||
(QName, name, type, optional, variadic) = expectedArgs[i]
|
||||
checkArgument(gotArgs[i], QName, name, type, optional, variadic)
|
||||
|
||||
checkMethod(methods[0], "::TestMethods::basic", "basic", [("Void", [])])
|
||||
checkMethod(methods[1], "::TestMethods::basicStatic", "basicStatic",
|
||||
[("Void", [])], static=True)
|
||||
checkMethod(methods[2], "::TestMethods::basicWithSimpleArgs",
|
||||
"basicWithSimpleArgs",
|
||||
[("Void",
|
||||
[("::TestMethods::basicWithSimpleArgs::arg1", "arg1", "Boolean", False, False),
|
||||
("::TestMethods::basicWithSimpleArgs::arg2", "arg2", "Byte", False, False),
|
||||
("::TestMethods::basicWithSimpleArgs::arg3", "arg3", "UnsignedLong", False, False)])])
|
||||
checkMethod(methods[3], "::TestMethods::basicBoolean", "basicBoolean", [("Boolean", [])])
|
||||
checkMethod(methods[4], "::TestMethods::basicStaticBoolean", "basicStaticBoolean", [("Boolean", [])], static=True)
|
||||
checkMethod(methods[5], "::TestMethods::basicBooleanWithSimpleArgs",
|
||||
"basicBooleanWithSimpleArgs",
|
||||
[("Boolean",
|
||||
[("::TestMethods::basicBooleanWithSimpleArgs::arg1", "arg1", "Boolean", False, False),
|
||||
("::TestMethods::basicBooleanWithSimpleArgs::arg2", "arg2", "Byte", False, False),
|
||||
("::TestMethods::basicBooleanWithSimpleArgs::arg3", "arg3", "UnsignedLong", False, False)])])
|
||||
checkMethod(methods[6], "::TestMethods::optionalArg",
|
||||
"optionalArg",
|
||||
[("Void",
|
||||
[("::TestMethods::optionalArg::arg1", "arg1", "ByteOrNull", True, False),
|
||||
("::TestMethods::optionalArg::arg2", "arg2", "ByteSequence", True, False)])])
|
||||
checkMethod(methods[7], "::TestMethods::variadicArg",
|
||||
"variadicArg",
|
||||
[("Void",
|
||||
[("::TestMethods::variadicArg::arg1", "arg1", "ByteOrNull", True, True)])])
|
||||
checkMethod(methods[8], "::TestMethods::crazyTypes",
|
||||
"crazyTypes",
|
||||
[("Void",
|
||||
[("::TestMethods::crazyTypes::arg1", "arg1", "LongOrNullArraySequenceOrNull", False, False),
|
||||
("::TestMethods::crazyTypes::arg2", "arg2", "BooleanOrNullArrayArrayOrNull", False, False)])])
|
||||
checkMethod(methods[9], "::TestMethods::getObject",
|
||||
"getObject", [("Object", [])])
|
||||
checkMethod(methods[10], "::TestMethods::setObject",
|
||||
"setObject",
|
||||
[("Void",
|
||||
[("::TestMethods::setObject::arg1", "arg1", "Object", False, False)])])
|
||||
checkMethod(methods[11], "::TestMethods::setAny",
|
||||
"setAny",
|
||||
[("Void",
|
||||
[("::TestMethods::setAny::arg1", "arg1", "Any", False, False)])])
|
14
dom/bindings/parser/tests/test_nullable_void.py
Normal file
14
dom/bindings/parser/tests/test_nullable_void.py
Normal file
@ -0,0 +1,14 @@
|
||||
def WebIDLTest(parser, harness):
|
||||
threw = False
|
||||
try:
|
||||
parser.parse("""
|
||||
interface NullableVoid {
|
||||
void? foo();
|
||||
};
|
||||
""")
|
||||
|
||||
results = parser.finish()
|
||||
except:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should have thrown.")
|
14
dom/bindings/parser/tests/test_optional_constraints.py
Normal file
14
dom/bindings/parser/tests/test_optional_constraints.py
Normal file
@ -0,0 +1,14 @@
|
||||
def WebIDLTest(parser, harness):
|
||||
threw = False
|
||||
try:
|
||||
parser.parse("""
|
||||
interface OptionalConstraints1 {
|
||||
void foo(optional byte arg1, byte arg2);
|
||||
};
|
||||
""")
|
||||
|
||||
results = parser.finish()
|
||||
except:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should have thrown.")
|
47
dom/bindings/parser/tests/test_overload.py
Normal file
47
dom/bindings/parser/tests/test_overload.py
Normal file
@ -0,0 +1,47 @@
|
||||
import WebIDL
|
||||
|
||||
def WebIDLTest(parser, harness):
|
||||
parser.parse("""
|
||||
interface TestOverloads {
|
||||
void basic();
|
||||
void basic(long arg1);
|
||||
boolean abitharder(unsigned long foo);
|
||||
boolean abitharder(boolean foo);
|
||||
void abitharder(long? foo);
|
||||
};
|
||||
""")
|
||||
|
||||
results = parser.finish()
|
||||
|
||||
harness.ok(True, "TestOverloads interface parsed without error.")
|
||||
harness.check(len(results), 1, "Should be one production.")
|
||||
iface = results[0]
|
||||
harness.ok(isinstance(iface, WebIDL.IDLInterface),
|
||||
"Should be an IDLInterface")
|
||||
harness.check(iface.identifier.QName(), "::TestOverloads", "Interface has the right QName")
|
||||
harness.check(iface.identifier.name, "TestOverloads", "Interface has the right name")
|
||||
harness.check(len(iface.members), 2, "Expect %s members" % 2)
|
||||
|
||||
member = iface.members[0]
|
||||
harness.check(member.identifier.QName(), "::TestOverloads::basic", "Method has the right QName")
|
||||
harness.check(member.identifier.name, "basic", "Method has the right name")
|
||||
harness.check(member.hasOverloads(), True, "Method has overloads")
|
||||
|
||||
signatures = member.signatures()
|
||||
harness.check(len(signatures), 2, "Method should have 2 signatures")
|
||||
|
||||
(retval, argumentSet) = signatures[0]
|
||||
|
||||
harness.check(str(retval), "Void", "Expect a void retval")
|
||||
harness.check(len(argumentSet), 0, "Expect an empty argument set")
|
||||
|
||||
(retval, argumentSet) = signatures[1]
|
||||
harness.check(str(retval), "Void", "Expect a void retval")
|
||||
harness.check(len(argumentSet), 1, "Expect an argument set with one argument")
|
||||
|
||||
argument = argumentSet[0]
|
||||
harness.ok(isinstance(argument, WebIDL.IDLArgument),
|
||||
"Should be an IDLArgument")
|
||||
harness.check(argument.identifier.QName(), "::TestOverloads::basic::arg1", "Argument has the right QName")
|
||||
harness.check(argument.identifier.name, "arg1", "Argument has the right name")
|
||||
harness.check(str(argument.type), "Long", "Argument has the right type")
|
7
dom/bindings/parser/tests/test_sanity.py
Normal file
7
dom/bindings/parser/tests/test_sanity.py
Normal file
@ -0,0 +1,7 @@
|
||||
def WebIDLTest(parser, harness):
|
||||
parser.parse("")
|
||||
parser.finish()
|
||||
harness.ok(True, "Parsing nothing doesn't throw.")
|
||||
parser.parse("interface Foo {};")
|
||||
parser.finish()
|
||||
harness.ok(True, "Parsing a silly interface doesn't throw.")
|
@ -0,0 +1,364 @@
|
||||
def WebIDLTest(parser, harness):
|
||||
threw = False
|
||||
try:
|
||||
parser.parse("""
|
||||
interface SpecialMethodSignatureMismatch1 {
|
||||
getter long long foo(long index);
|
||||
};
|
||||
""")
|
||||
|
||||
results = parser.finish()
|
||||
except:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should have thrown.")
|
||||
|
||||
threw = False
|
||||
try:
|
||||
parser.parse("""
|
||||
interface SpecialMethodSignatureMismatch2 {
|
||||
getter void foo(unsigned long index);
|
||||
};
|
||||
""")
|
||||
|
||||
results = parser.finish()
|
||||
except:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should have thrown.")
|
||||
|
||||
threw = False
|
||||
try:
|
||||
parser.parse("""
|
||||
interface SpecialMethodSignatureMismatch3 {
|
||||
getter boolean foo(unsigned long index, boolean extraArg);
|
||||
};
|
||||
""")
|
||||
|
||||
results = parser.finish()
|
||||
except:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should have thrown.")
|
||||
|
||||
threw = False
|
||||
try:
|
||||
parser.parse("""
|
||||
interface SpecialMethodSignatureMismatch4 {
|
||||
getter boolean foo(unsigned long... index);
|
||||
};
|
||||
""")
|
||||
|
||||
results = parser.finish()
|
||||
except:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should have thrown.")
|
||||
|
||||
threw = False
|
||||
try:
|
||||
parser.parse("""
|
||||
interface SpecialMethodSignatureMismatch5 {
|
||||
getter boolean foo(optional unsigned long index);
|
||||
};
|
||||
""")
|
||||
|
||||
results = parser.finish()
|
||||
except:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should have thrown.")
|
||||
|
||||
threw = False
|
||||
try:
|
||||
parser.parse("""
|
||||
interface SpecialMethodSignatureMismatch6 {
|
||||
getter boolean foo();
|
||||
};
|
||||
""")
|
||||
|
||||
results = parser.finish()
|
||||
except:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should have thrown.")
|
||||
|
||||
threw = False
|
||||
try:
|
||||
parser.parse("""
|
||||
interface SpecialMethodSignatureMismatch7 {
|
||||
deleter long long foo(long index);
|
||||
};
|
||||
""")
|
||||
|
||||
results = parser.finish()
|
||||
except:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should have thrown.")
|
||||
|
||||
threw = False
|
||||
try:
|
||||
parser.parse("""
|
||||
interface SpecialMethodSignatureMismatch8 {
|
||||
deleter void foo(unsigned long index);
|
||||
};
|
||||
""")
|
||||
|
||||
results = parser.finish()
|
||||
except:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should have thrown.")
|
||||
|
||||
threw = False
|
||||
try:
|
||||
parser.parse("""
|
||||
interface SpecialMethodSignatureMismatch9 {
|
||||
deleter boolean foo(unsigned long index, boolean extraArg);
|
||||
};
|
||||
""")
|
||||
|
||||
results = parser.finish()
|
||||
except:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should have thrown.")
|
||||
|
||||
threw = False
|
||||
try:
|
||||
parser.parse("""
|
||||
interface SpecialMethodSignatureMismatch10 {
|
||||
deleter boolean foo(unsigned long... index);
|
||||
};
|
||||
""")
|
||||
|
||||
results = parser.finish()
|
||||
except:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should have thrown.")
|
||||
|
||||
threw = False
|
||||
try:
|
||||
parser.parse("""
|
||||
interface SpecialMethodSignatureMismatch11 {
|
||||
deleter boolean foo(optional unsigned long index);
|
||||
};
|
||||
""")
|
||||
|
||||
results = parser.finish()
|
||||
except:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should have thrown.")
|
||||
|
||||
threw = False
|
||||
try:
|
||||
parser.parse("""
|
||||
interface SpecialMethodSignatureMismatch12 {
|
||||
deleter boolean foo();
|
||||
};
|
||||
""")
|
||||
|
||||
results = parser.finish()
|
||||
except:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should have thrown.")
|
||||
|
||||
threw = False
|
||||
try:
|
||||
parser.parse("""
|
||||
interface SpecialMethodSignatureMismatch13 {
|
||||
setter long long foo(long index, long long value);
|
||||
};
|
||||
""")
|
||||
|
||||
results = parser.finish()
|
||||
except:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should have thrown.")
|
||||
|
||||
threw = False
|
||||
try:
|
||||
parser.parse("""
|
||||
interface SpecialMethodSignatureMismatch14 {
|
||||
setter void foo(unsigned long index, long long value);
|
||||
};
|
||||
""")
|
||||
|
||||
results = parser.finish()
|
||||
except:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should have thrown.")
|
||||
|
||||
threw = False
|
||||
try:
|
||||
parser.parse("""
|
||||
interface SpecialMethodSignatureMismatch15 {
|
||||
setter boolean foo(unsigned long index, boolean value, long long extraArg);
|
||||
};
|
||||
""")
|
||||
|
||||
results = parser.finish()
|
||||
except:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should have thrown.")
|
||||
|
||||
threw = False
|
||||
try:
|
||||
parser.parse("""
|
||||
interface SpecialMethodSignatureMismatch16 {
|
||||
setter boolean foo(unsigned long index, boolean... value);
|
||||
};
|
||||
""")
|
||||
|
||||
results = parser.finish()
|
||||
except:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should have thrown.")
|
||||
|
||||
threw = False
|
||||
try:
|
||||
parser.parse("""
|
||||
interface SpecialMethodSignatureMismatch17 {
|
||||
setter boolean foo(unsigned long index, optional boolean value);
|
||||
};
|
||||
""")
|
||||
|
||||
results = parser.finish()
|
||||
except:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should have thrown.")
|
||||
|
||||
threw = False
|
||||
try:
|
||||
parser.parse("""
|
||||
interface SpecialMethodSignatureMismatch18 {
|
||||
setter boolean foo();
|
||||
};
|
||||
""")
|
||||
|
||||
results = parser.finish()
|
||||
except:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should have thrown.")
|
||||
|
||||
threw = False
|
||||
try:
|
||||
parser.parse("""
|
||||
interface SpecialMethodSignatureMismatch19 {
|
||||
setter boolean foo(unsigned long index, long long value);
|
||||
};
|
||||
""")
|
||||
|
||||
results = parser.finish()
|
||||
except:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should have thrown.")
|
||||
|
||||
threw = False
|
||||
try:
|
||||
parser.parse("""
|
||||
interface SpecialMethodSignatureMismatch20 {
|
||||
creator long long foo(long index, long long value);
|
||||
};
|
||||
""")
|
||||
|
||||
results = parser.finish()
|
||||
except:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should have thrown.")
|
||||
|
||||
threw = False
|
||||
try:
|
||||
parser.parse("""
|
||||
interface SpecialMethodSignatureMismatch21 {
|
||||
creator void foo(unsigned long index, long long value);
|
||||
};
|
||||
""")
|
||||
|
||||
results = parser.finish()
|
||||
except:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should have thrown.")
|
||||
|
||||
threw = False
|
||||
try:
|
||||
parser.parse("""
|
||||
interface SpecialMethodSignatureMismatch22 {
|
||||
creator boolean foo(unsigned long index, boolean value, long long extraArg);
|
||||
};
|
||||
""")
|
||||
|
||||
results = parser.finish()
|
||||
except:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should have thrown.")
|
||||
|
||||
threw = False
|
||||
try:
|
||||
parser.parse("""
|
||||
interface SpecialMethodSignatureMismatch23 {
|
||||
creator boolean foo(unsigned long index, boolean... value);
|
||||
};
|
||||
""")
|
||||
|
||||
results = parser.finish()
|
||||
except:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should have thrown.")
|
||||
|
||||
threw = False
|
||||
try:
|
||||
parser.parse("""
|
||||
interface SpecialMethodSignatureMismatch24 {
|
||||
creator boolean foo(unsigned long index, optional boolean value);
|
||||
};
|
||||
""")
|
||||
|
||||
results = parser.finish()
|
||||
except:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should have thrown.")
|
||||
|
||||
threw = False
|
||||
try:
|
||||
parser.parse("""
|
||||
interface SpecialMethodSignatureMismatch25 {
|
||||
creator boolean foo();
|
||||
};
|
||||
""")
|
||||
|
||||
results = parser.finish()
|
||||
except:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should have thrown.")
|
||||
|
||||
threw = False
|
||||
try:
|
||||
parser.parse("""
|
||||
interface SpecialMethodSignatureMismatch26 {
|
||||
creator boolean foo(unsigned long index, long long value);
|
||||
};
|
||||
""")
|
||||
|
||||
results = parser.finish()
|
||||
except:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should have thrown.")
|
73
dom/bindings/parser/tests/test_special_methods.py
Normal file
73
dom/bindings/parser/tests/test_special_methods.py
Normal file
@ -0,0 +1,73 @@
|
||||
import WebIDL
|
||||
|
||||
def WebIDLTest(parser, harness):
|
||||
parser.parse("""
|
||||
interface SpecialMethods {
|
||||
getter long long (unsigned long index);
|
||||
setter long long (unsigned long index, long long value);
|
||||
creator long long (unsigned long index, long long value);
|
||||
deleter long long (unsigned long index);
|
||||
getter boolean (DOMString name);
|
||||
setter boolean (DOMString name, boolean value);
|
||||
creator boolean (DOMString name, boolean value);
|
||||
deleter boolean (DOMString name);
|
||||
};
|
||||
|
||||
interface SpecialMethodsCombination {
|
||||
getter deleter long long (unsigned long index);
|
||||
setter creator long long (unsigned long index, long long value);
|
||||
getter deleter boolean (DOMString name);
|
||||
setter creator boolean (DOMString name, boolean value);
|
||||
};
|
||||
""")
|
||||
|
||||
results = parser.finish()
|
||||
|
||||
def checkMethod(method, QName, name,
|
||||
static=False, getter=False, setter=False, creator=False,
|
||||
deleter=False, legacycaller=False, stringifier=False):
|
||||
harness.ok(isinstance(method, WebIDL.IDLMethod),
|
||||
"Should be an IDLMethod")
|
||||
harness.check(method.identifier.QName(), QName, "Method has the right QName")
|
||||
harness.check(method.identifier.name, name, "Method has the right name")
|
||||
harness.check(method.isStatic(), static, "Method has the correct static value")
|
||||
harness.check(method.isGetter(), getter, "Method has the correct getter value")
|
||||
harness.check(method.isSetter(), setter, "Method has the correct setter value")
|
||||
harness.check(method.isCreator(), creator, "Method has the correct creator value")
|
||||
harness.check(method.isDeleter(), deleter, "Method has the correct deleter value")
|
||||
harness.check(method.isLegacycaller(), legacycaller, "Method has the correct legacycaller value")
|
||||
harness.check(method.isStringifier(), stringifier, "Method has the correct stringifier value")
|
||||
|
||||
harness.check(len(results), 2, "Expect 2 interfaces")
|
||||
|
||||
iface = results[0]
|
||||
harness.check(len(iface.members), 8, "Expect 8 members")
|
||||
|
||||
checkMethod(iface.members[0], "::SpecialMethods::__indexedgetter", "__indexedgetter",
|
||||
getter=True)
|
||||
checkMethod(iface.members[1], "::SpecialMethods::__indexedsetter", "__indexedsetter",
|
||||
setter=True)
|
||||
checkMethod(iface.members[2], "::SpecialMethods::__indexedcreator", "__indexedcreator",
|
||||
creator=True)
|
||||
checkMethod(iface.members[3], "::SpecialMethods::__indexeddeleter", "__indexeddeleter",
|
||||
deleter=True)
|
||||
checkMethod(iface.members[4], "::SpecialMethods::__namedgetter", "__namedgetter",
|
||||
getter=True)
|
||||
checkMethod(iface.members[5], "::SpecialMethods::__namedsetter", "__namedsetter",
|
||||
setter=True)
|
||||
checkMethod(iface.members[6], "::SpecialMethods::__namedcreator", "__namedcreator",
|
||||
creator=True)
|
||||
checkMethod(iface.members[7], "::SpecialMethods::__nameddeleter", "__nameddeleter",
|
||||
deleter=True)
|
||||
|
||||
iface = results[1]
|
||||
harness.check(len(iface.members), 4, "Expect 4 members")
|
||||
|
||||
checkMethod(iface.members[0], "::SpecialMethodsCombination::__indexedgetterdeleter",
|
||||
"__indexedgetterdeleter", getter=True, deleter=True)
|
||||
checkMethod(iface.members[1], "::SpecialMethodsCombination::__indexedsettercreator",
|
||||
"__indexedsettercreator", setter=True, creator=True)
|
||||
checkMethod(iface.members[2], "::SpecialMethodsCombination::__namedgetterdeleter",
|
||||
"__namedgetterdeleter", getter=True, deleter=True)
|
||||
checkMethod(iface.members[3], "::SpecialMethodsCombination::__namedsettercreator",
|
||||
"__namedsettercreator", setter=True, creator=True)
|
62
dom/bindings/parser/tests/test_special_methods_uniqueness.py
Normal file
62
dom/bindings/parser/tests/test_special_methods_uniqueness.py
Normal file
@ -0,0 +1,62 @@
|
||||
import WebIDL
|
||||
|
||||
def WebIDLTest(parser, harness):
|
||||
threw = False
|
||||
try:
|
||||
parser.parse("""
|
||||
interface SpecialMethodUniqueness1 {
|
||||
getter deleter boolean (DOMString name);
|
||||
getter boolean (DOMString name);
|
||||
};
|
||||
""")
|
||||
|
||||
results = parser.finish()
|
||||
except:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should have thrown.")
|
||||
|
||||
threw = False
|
||||
try:
|
||||
parser.parse("""
|
||||
interface SpecialMethodUniqueness1 {
|
||||
deleter boolean (DOMString name);
|
||||
getter deleter boolean (DOMString name);
|
||||
};
|
||||
""")
|
||||
|
||||
results = parser.finish()
|
||||
except:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should have thrown.")
|
||||
|
||||
threw = False
|
||||
try:
|
||||
parser.parse("""
|
||||
interface SpecialMethodUniqueness1 {
|
||||
setter creator boolean (DOMString name);
|
||||
creator boolean (DOMString name);
|
||||
};
|
||||
""")
|
||||
|
||||
results = parser.finish()
|
||||
except:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should have thrown.")
|
||||
|
||||
threw = False
|
||||
try:
|
||||
parser.parse("""
|
||||
interface SpecialMethodUniqueness1 {
|
||||
setter boolean (DOMString name);
|
||||
creator setter boolean (DOMString name);
|
||||
};
|
||||
""")
|
||||
|
||||
results = parser.finish()
|
||||
except:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should have thrown.")
|
56
dom/bindings/parser/tests/test_treatNonCallableAsNull.py
Normal file
56
dom/bindings/parser/tests/test_treatNonCallableAsNull.py
Normal file
@ -0,0 +1,56 @@
|
||||
import WebIDL
|
||||
|
||||
def WebIDLTest(parser, harness):
|
||||
parser.parse("""
|
||||
callback Function = any(any... arguments);
|
||||
|
||||
interface TestTreatNonCallableAsNull1 {
|
||||
[TreatNonCallableAsNull] attribute Function? onfoo;
|
||||
attribute Function? onbar;
|
||||
};
|
||||
""")
|
||||
|
||||
results = parser.finish()
|
||||
|
||||
iface = results[1]
|
||||
attr = iface.members[0]
|
||||
harness.check(attr.type.treatNonCallableAsNull(), True, "Got the expected value")
|
||||
attr = iface.members[1]
|
||||
harness.check(attr.type.treatNonCallableAsNull(), False, "Got the expected value")
|
||||
|
||||
parser = parser.reset()
|
||||
|
||||
threw = False
|
||||
try:
|
||||
parser.parse("""
|
||||
callback Function = any(any... arguments);
|
||||
|
||||
interface TestTreatNonCallableAsNull2 {
|
||||
[TreatNonCallableAsNull] attribute Function onfoo;
|
||||
};
|
||||
""")
|
||||
|
||||
results = parser.finish()
|
||||
except:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should have thrown.")
|
||||
|
||||
parser = parser.reset()
|
||||
|
||||
threw = False
|
||||
try:
|
||||
parser.parse("""
|
||||
callback Function = any(any... arguments);
|
||||
|
||||
[TreatNonCallableAsNull]
|
||||
interface TestTreatNonCallableAsNull3 {
|
||||
attribute Function onfoo;
|
||||
};
|
||||
""")
|
||||
|
||||
results = parser.finish()
|
||||
except:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should have thrown.")
|
10
dom/bindings/parser/tests/test_variadic_callback.py
Normal file
10
dom/bindings/parser/tests/test_variadic_callback.py
Normal file
@ -0,0 +1,10 @@
|
||||
import WebIDL
|
||||
|
||||
def WebIDLTest(parser, harness):
|
||||
parser.parse("""
|
||||
callback TestVariadicCallback = any(any... arguments);
|
||||
""")
|
||||
|
||||
results = parser.finish()
|
||||
|
||||
harness.ok(True, "TestVariadicCallback callback parsed without error.")
|
39
dom/bindings/parser/tests/test_variadic_constraints.py
Normal file
39
dom/bindings/parser/tests/test_variadic_constraints.py
Normal file
@ -0,0 +1,39 @@
|
||||
def WebIDLTest(parser, harness):
|
||||
threw = False
|
||||
try:
|
||||
results = parser.parse("""
|
||||
interface VariadicConstraints1 {
|
||||
void foo(byte... arg1, byte arg2);
|
||||
};
|
||||
""")
|
||||
|
||||
except:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should have thrown.")
|
||||
|
||||
threw = False
|
||||
try:
|
||||
results = parser.parse("""
|
||||
interface VariadicConstraints2 {
|
||||
void foo(byte... arg1, optional byte arg2);
|
||||
};
|
||||
""")
|
||||
|
||||
except:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should have thrown.")
|
||||
|
||||
threw = False
|
||||
try:
|
||||
results = parser.parse("""
|
||||
interface VariadicConstraints3 {
|
||||
void foo(optional byte... arg1);
|
||||
};
|
||||
""")
|
||||
|
||||
except:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should have thrown.")
|
19
dom/bindings/test/Makefile.in
Normal file
19
dom/bindings/test/Makefile.in
Normal file
@ -0,0 +1,19 @@
|
||||
# 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/.
|
||||
|
||||
DEPTH = ../../..
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
relativesrcdir = dom/bindings/test
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
_TEST_FILES = \
|
||||
test_lookupGetter.html \
|
||||
$(NULL)
|
||||
|
||||
libs:: $(_TEST_FILES)
|
||||
$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/tests/$(relativesrcdir)
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user