Merge last PGO-green changeset of mozilla-inbound to mozilla-central

This commit is contained in:
Ed Morley 2012-03-31 22:41:59 +01:00
commit 7b8f9d67b3
273 changed files with 17590 additions and 7133 deletions

View File

@ -80,6 +80,7 @@ endif
ifdef MOZ_MEMORY
tier_base_dirs += memory/jemalloc
tier_base_dirs += memory/build
endif
tier_base_dirs += \
mozglue \

View File

@ -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

View File

@ -1,2 +1,3 @@
README.txt
@DLL_PREFIX@mozutils@DLL_SUFFIX@
jssubloader/

View File

@ -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 = \

View File

@ -77,8 +77,6 @@
#define INITGUID
#include <shlobj.h>
#pragma comment(lib, "shlwapi.lib") // for SHDeleteKeyW
#include <mbstring.h>
#include <shlwapi.h>

View File

@ -1475,3 +1475,4 @@ components/nsPlacesDBFlush.js
maintenanceservice.exe
maintenanceservice_installer.exe
#endif
jssubloader/

View File

@ -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) {

View File

@ -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

View File

@ -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

View File

@ -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.

View File

@ -403,4 +403,7 @@ mozilla::dom::TraceBlackJS(JSTracer* aTrc)
if (windowsById) {
windowsById->Enumerate(TraceActiveWindowGlobal, aTrc);
}
// Mark the safe context black
nsContentUtils::TraceSafeJSContext(aTrc);
}

View File

@ -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);
}

View File

@ -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()) {

View File

@ -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)

View File

@ -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")

View File

@ -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) {

View File

@ -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()
{

View File

@ -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,

View File

@ -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>

View File

@ -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",

View File

@ -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'",

View File

@ -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",

View File

@ -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;

View File

@ -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();

View File

@ -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();
}

View File

@ -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>

View File

@ -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");

View File

@ -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;

View File

@ -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)
{

View File

@ -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);

View File

@ -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;
}

View File

@ -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; */

View File

@ -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();
};

View File

@ -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();
};

View File

@ -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

View File

@ -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();
};

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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);
}

View File

@ -76,6 +76,7 @@ DIRS += \
DIRS += \
base \
bindings \
battery \
contacts \
power \

View File

@ -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);

View File

@ -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;

View File

@ -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

View File

@ -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);

View File

@ -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;

View File

@ -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;
}
}

View File

@ -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

View File

@ -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 };

View 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
View 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

File diff suppressed because it is too large Load Diff

View 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
View 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
View 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
View 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
View 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
View 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
View 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__ */

View File

@ -0,0 +1 @@
A WebIDL parser written in Python to be used in Mozilla.

View 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

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1 @@
__all__ = ['WebIDL']

View 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()

View 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.")

View File

@ -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.")

View 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.")

View 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")

View 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)

View 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.")

View 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")

View 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")

View 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")

View 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)

View 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)])])

View File

@ -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.")

View 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.")

View 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.")

View 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()

View 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")

View 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")

View File

@ -0,0 +1,11 @@
import WebIDL
def WebIDLTest(parser, harness):
parser.parse("""
[Flippety]
interface TestExtendedAttr {
[Foopy] attribute byte b;
};
""")
results = parser.finish()

View 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.")

View 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.")

View 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")

View 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")

View File

@ -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.")

View File

@ -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.")

View 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)])])

View 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.")

View 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.")

View 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")

View 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.")

View File

@ -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.")

View 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)

View 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.")

View 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.")

View 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.")

View 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.")

View 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