Bug 709569, a tool for webidl dictionary-like interfaces, r=khuey,mrbkap

This commit is contained in:
Olli Pettay 2011-12-24 00:13:46 +02:00
parent f9e354e1b3
commit 04c23412b9
21 changed files with 620 additions and 213 deletions

View File

@ -38,6 +38,7 @@
#include "nsDOMCloseEvent.h"
#include "nsContentUtils.h"
#include "DictionaryHelpers.h"
NS_IMPL_ADDREF_INHERITED(nsDOMCloseEvent, nsDOMEvent)
NS_IMPL_RELEASE_INHERITED(nsDOMCloseEvent, nsDOMEvent)
@ -89,31 +90,14 @@ nsDOMCloseEvent::InitCloseEvent(const nsAString& aType,
}
nsresult
nsDOMCloseEvent::InitFromCtor(const nsAString& aType, nsISupports* aDict,
JSContext* aCx, JSObject* aObj)
nsDOMCloseEvent::InitFromCtor(const nsAString& aType,
JSContext* aCx, jsval* aVal)
{
nsCOMPtr<nsICloseEventInit> eventInit = do_QueryInterface(aDict);
bool bubbles = false;
bool cancelable = false;
bool wasClean = false;
PRUint16 code = 0;
nsAutoString reason;
if (eventInit) {
nsresult rv = eventInit->GetBubbles(&bubbles);
NS_ENSURE_SUCCESS(rv, rv);
rv = eventInit->GetCancelable(&cancelable);
NS_ENSURE_SUCCESS(rv, rv);
rv = eventInit->GetWasClean(&wasClean);
NS_ENSURE_SUCCESS(rv, rv);
rv = eventInit->GetCode(&code);
NS_ENSURE_SUCCESS(rv, rv);
JSBool found = JS_FALSE;
if (JS_HasProperty(aCx, aObj, "reason", &found) && found) {
rv = eventInit->GetReason(reason);
NS_ENSURE_SUCCESS(rv, rv);
}
}
return InitCloseEvent(aType, bubbles, cancelable, wasClean, code, reason);
mozilla::dom::CloseEventInit d;
nsresult rv = d.Init(aCx, aVal);
NS_ENSURE_SUCCESS(rv, rv);
return InitCloseEvent(aType, d.bubbles, d.cancelable, d.wasClean, d.code,
d.reason);
}
nsresult

View File

@ -64,9 +64,8 @@ public:
NS_DECL_NSIDOMCLOSEEVENT
virtual const nsIID& EventInitIID() { return NS_GET_IID(nsICloseEventInit); }
virtual nsresult InitFromCtor(const nsAString& aType, nsISupports* aDict,
JSContext* aCx, JSObject* aObj);
virtual nsresult InitFromCtor(const nsAString& aType,
JSContext* aCx, jsval* aVal);
private:
bool mWasClean;
PRUint16 mReasonCode;

View File

@ -37,6 +37,7 @@
#include "nsDOMCustomEvent.h"
#include "nsContentUtils.h"
#include "DictionaryHelpers.h"
NS_IMPL_CYCLE_COLLECTION_CLASS(nsDOMCustomEvent)
@ -79,22 +80,13 @@ nsDOMCustomEvent::InitCustomEvent(const nsAString& aType,
}
nsresult
nsDOMCustomEvent::InitFromCtor(const nsAString& aType, nsISupports* aDict,
JSContext* aCx, JSObject* aObj)
nsDOMCustomEvent::InitFromCtor(const nsAString& aType,
JSContext* aCx, jsval* aVal)
{
nsCOMPtr<nsICustomEventInit> eventInit = do_QueryInterface(aDict);
bool bubbles = false;
bool cancelable = false;
nsCOMPtr<nsIVariant> detail;
if (eventInit) {
nsresult rv = eventInit->GetBubbles(&bubbles);
NS_ENSURE_SUCCESS(rv, rv);
rv = eventInit->GetCancelable(&cancelable);
NS_ENSURE_SUCCESS(rv, rv);
rv = eventInit->GetDetail(getter_AddRefs(detail));
NS_ENSURE_SUCCESS(rv, rv);
}
return InitCustomEvent(aType, bubbles, cancelable, detail);
mozilla::dom::CustomEventInit d;
nsresult rv = d.Init(aCx, aVal);
NS_ENSURE_SUCCESS(rv, rv);
return InitCustomEvent(aType, d.bubbles, d.cancelable, d.detail);
}
nsresult

View File

@ -59,9 +59,8 @@ public:
// Forward to base class
NS_FORWARD_TO_NSDOMEVENT
virtual const nsIID& EventInitIID() { return NS_GET_IID(nsICustomEventInit); }
virtual nsresult InitFromCtor(const nsAString& aType, nsISupports* aDict,
JSContext* aCx, JSObject* aObj);
virtual nsresult InitFromCtor(const nsAString& aType,
JSContext* aCx, jsval* aVal);
private:
nsCOMPtr<nsIVariant> mDetail;
};

View File

@ -62,6 +62,7 @@
#include "nsDOMPopStateEvent.h"
#include "mozilla/Preferences.h"
#include "nsJSUtils.h"
#include "DictionaryHelpers.h"
using namespace mozilla;
@ -409,16 +410,8 @@ nsDOMEvent::Initialize(nsISupports* aOwner, JSContext* aCx, JSObject* aObj,
nsDependentJSString type;
NS_ENSURE_STATE(type.init(aCx, jsstr));
nsCOMPtr<nsISupports> dict;
JSObject* obj = nsnull;
if (aArgc >= 2 && !JSVAL_IS_PRIMITIVE(aArgv[1])) {
obj = JSVAL_TO_OBJECT(aArgv[1]);
nsContentUtils::XPConnect()->WrapJS(aCx, obj,
EventInitIID(),
getter_AddRefs(dict));
}
nsresult rv = InitFromCtor(type, dict, aCx, obj);
nsresult rv = InitFromCtor(type, aCx, aArgc >= 2 ? &(aArgv[1]) : nsnull);
NS_ENSURE_SUCCESS(rv, rv);
SetTrusted(trusted);
@ -426,19 +419,13 @@ nsDOMEvent::Initialize(nsISupports* aOwner, JSContext* aCx, JSObject* aObj,
}
nsresult
nsDOMEvent::InitFromCtor(const nsAString& aType, nsISupports* aDict,
JSContext* aCx, JSObject* aObj)
nsDOMEvent::InitFromCtor(const nsAString& aType,
JSContext* aCx, jsval* aVal)
{
nsCOMPtr<nsIEventInit> eventInit = do_QueryInterface(aDict);
bool bubbles = false;
bool cancelable = false;
if (eventInit) {
nsresult rv = eventInit->GetBubbles(&bubbles);
NS_ENSURE_SUCCESS(rv, rv);
rv = eventInit->GetCancelable(&cancelable);
NS_ENSURE_SUCCESS(rv, rv);
}
return InitEvent(aType, bubbles, cancelable);
mozilla::dom::EventInit d;
nsresult rv = d.Init(aCx, aVal);
NS_ENSURE_SUCCESS(rv, rv);
return InitEvent(aType, d.bubbles, d.cancelable);
}
NS_IMETHODIMP

View File

@ -227,9 +227,8 @@ public:
NS_IMETHOD Initialize(nsISupports* aOwner, JSContext* aCx, JSObject* aObj,
PRUint32 aArgc, jsval* aArgv);
virtual const nsIID& EventInitIID() { return NS_GET_IID(nsIEventInit); }
virtual nsresult InitFromCtor(const nsAString& aType, nsISupports* aDict,
JSContext* aCx, JSObject* aObj);
virtual nsresult InitFromCtor(const nsAString& aType,
JSContext* aCx, jsval* aVal);
void InitPresContextData(nsPresContext* aPresContext);

View File

@ -34,6 +34,7 @@
#include "nsDOMHashChangeEvent.h"
#include "nsContentUtils.h"
#include "DictionaryHelpers.h"
NS_IMPL_ADDREF_INHERITED(nsDOMHashChangeEvent, nsDOMEvent)
NS_IMPL_RELEASE_INHERITED(nsDOMHashChangeEvent, nsDOMEvent)
@ -79,31 +80,13 @@ nsDOMHashChangeEvent::InitHashChangeEvent(const nsAString &aTypeArg,
}
nsresult
nsDOMHashChangeEvent::InitFromCtor(const nsAString& aType, nsISupports* aDict,
JSContext* aCx, JSObject* aObj)
nsDOMHashChangeEvent::InitFromCtor(const nsAString& aType,
JSContext* aCx, jsval* aVal)
{
nsCOMPtr<nsIHashChangeEventInit> eventInit = do_QueryInterface(aDict);
bool bubbles = false;
bool cancelable = false;
nsAutoString oldURL;
nsAutoString newURL;
if (eventInit) {
nsresult rv = eventInit->GetBubbles(&bubbles);
NS_ENSURE_SUCCESS(rv, rv);
rv = eventInit->GetCancelable(&cancelable);
NS_ENSURE_SUCCESS(rv, rv);
JSBool found = JS_FALSE;
if (JS_HasProperty(aCx, aObj, "oldURL", &found) && found) {
rv = eventInit->GetOldURL(oldURL);
NS_ENSURE_SUCCESS(rv, rv);
}
found = JS_FALSE;
if (JS_HasProperty(aCx, aObj, "newURL", &found) && found) {
rv = eventInit->GetNewURL(newURL);
NS_ENSURE_SUCCESS(rv, rv);
}
}
return InitHashChangeEvent(aType, bubbles, cancelable, oldURL, newURL);
mozilla::dom::HashChangeEventInit d;
nsresult rv = d.Init(aCx, aVal);
NS_ENSURE_SUCCESS(rv, rv);
return InitHashChangeEvent(aType, d.bubbles, d.cancelable, d.oldURL, d.newURL);
}
nsresult NS_NewDOMHashChangeEvent(nsIDOMEvent** aInstancePtrResult,

View File

@ -58,9 +58,8 @@ public:
NS_FORWARD_TO_NSDOMEVENT
virtual const nsIID& EventInitIID() { return NS_GET_IID(nsIHashChangeEventInit); }
virtual nsresult InitFromCtor(const nsAString& aType, nsISupports* aDict,
JSContext* aCx, JSObject* aObj);
virtual nsresult InitFromCtor(const nsAString& aType,
JSContext* aCx, jsval* aVal);
protected:
nsString mOldURL;
nsString mNewURL;

View File

@ -41,6 +41,7 @@
#include "nsGUIEvent.h"
#include "nsIContent.h"
#include "nsContentUtils.h"
#include "DictionaryHelpers.h"
nsDOMMouseEvent::nsDOMMouseEvent(nsPresContext* aPresContext,
nsInputEvent* aEvent)
@ -145,58 +146,17 @@ nsDOMMouseEvent::InitMouseEvent(const nsAString & aType, bool aCanBubble, bool a
}
nsresult
nsDOMMouseEvent::InitFromCtor(const nsAString& aType, nsISupports* aDict,
JSContext* aCx, JSObject* aObj)
nsDOMMouseEvent::InitFromCtor(const nsAString& aType,
JSContext* aCx, jsval* aVal)
{
nsCOMPtr<nsIMouseEventInit> eventInit = do_QueryInterface(aDict);
bool bubbles = false;
bool cancelable = false;
nsCOMPtr<nsIDOMWindow> view;
PRInt32 detail = 0;
PRInt32 screenX = 0;
PRInt32 screenY = 0;
PRInt32 clientX = 0;
PRInt32 clientY = 0;
bool ctrl = false;
bool alt = false;
bool shift = false;
bool meta = false;
PRUint16 button = 0;
nsCOMPtr<nsIDOMEventTarget> relatedTarget;
if (eventInit) {
nsresult rv = eventInit->GetBubbles(&bubbles);
NS_ENSURE_SUCCESS(rv, rv);
rv = eventInit->GetCancelable(&cancelable);
NS_ENSURE_SUCCESS(rv, rv);
rv = eventInit->GetView(getter_AddRefs(view));
NS_ENSURE_SUCCESS(rv, rv);
rv = eventInit->GetDetail(&detail);
NS_ENSURE_SUCCESS(rv, rv);
rv = eventInit->GetScreenX(&screenX);
NS_ENSURE_SUCCESS(rv, rv);
rv = eventInit->GetScreenY(&screenY);
NS_ENSURE_SUCCESS(rv, rv);
rv = eventInit->GetClientX(&clientX);
NS_ENSURE_SUCCESS(rv, rv);
rv = eventInit->GetClientY(&clientY);
NS_ENSURE_SUCCESS(rv, rv);
rv = eventInit->GetCtrlKey(&ctrl);
NS_ENSURE_SUCCESS(rv, rv);
rv = eventInit->GetShiftKey(&shift);
NS_ENSURE_SUCCESS(rv, rv);
rv = eventInit->GetAltKey(&alt);
NS_ENSURE_SUCCESS(rv, rv);
rv = eventInit->GetMetaKey(&meta);
NS_ENSURE_SUCCESS(rv, rv);
rv = eventInit->GetButton(&button);
NS_ENSURE_SUCCESS(rv, rv);
rv = eventInit->GetRelatedTarget(getter_AddRefs(relatedTarget));
NS_ENSURE_SUCCESS(rv, rv);
}
return InitMouseEvent(aType, bubbles, cancelable,
view, detail, screenX, screenY, clientX, clientY,
ctrl, alt, shift, meta,
button, relatedTarget);
mozilla::dom::MouseEventInit d;
nsresult rv = d.Init(aCx, aVal);
NS_ENSURE_SUCCESS(rv, rv);
return InitMouseEvent(aType, d.bubbles, d.cancelable,
d.view, d.detail, d.screenX, d.screenY,
d.clientX, d.clientY,
d.ctrlKey, d.altKey, d.shiftKey, d.metaKey,
d.button, d.relatedTarget);
}
NS_IMETHODIMP

View File

@ -60,9 +60,8 @@ public:
// Forward to base class
NS_FORWARD_TO_NSDOMUIEVENT
virtual const nsIID& EventInitIID() { return NS_GET_IID(nsIMouseEventInit); }
virtual nsresult InitFromCtor(const nsAString& aType, nsISupports* aDict,
JSContext* aCx, JSObject* aObj);
virtual nsresult InitFromCtor(const nsAString& aType,
JSContext* aCx, jsval* aVal);
protected:
// Specific implementation for a mouse event.
virtual nsresult Which(PRUint32* aWhich);

View File

@ -38,6 +38,7 @@
#include "nsDOMPageTransitionEvent.h"
#include "nsContentUtils.h"
#include "DictionaryHelpers.h"
DOMCI_DATA(PageTransitionEvent, nsDOMPageTransitionEvent)
@ -70,22 +71,13 @@ nsDOMPageTransitionEvent::InitPageTransitionEvent(const nsAString &aTypeArg,
}
nsresult
nsDOMPageTransitionEvent::InitFromCtor(const nsAString& aType, nsISupports* aDict,
JSContext* aCx, JSObject* aObj)
nsDOMPageTransitionEvent::InitFromCtor(const nsAString& aType,
JSContext* aCx, jsval* aVal)
{
nsCOMPtr<nsIPageTransitionEventInit> eventInit = do_QueryInterface(aDict);
bool bubbles = false;
bool cancelable = false;
bool persisted = false;
if (eventInit) {
nsresult rv = eventInit->GetBubbles(&bubbles);
NS_ENSURE_SUCCESS(rv, rv);
rv = eventInit->GetCancelable(&cancelable);
NS_ENSURE_SUCCESS(rv, rv);
rv = eventInit->GetPersisted(&persisted);
NS_ENSURE_SUCCESS(rv, rv);
}
return InitPageTransitionEvent(aType, bubbles, cancelable, persisted);
mozilla::dom::PageTransitionEventInit d;
nsresult rv = d.Init(aCx, aVal);
NS_ENSURE_SUCCESS(rv, rv);
return InitPageTransitionEvent(aType, d.bubbles, d.cancelable, d.persisted);
}
nsresult NS_NewDOMPageTransitionEvent(nsIDOMEvent** aInstancePtrResult,

View File

@ -56,9 +56,8 @@ public:
// Forward to base class
NS_FORWARD_TO_NSDOMEVENT
virtual const nsIID& EventInitIID() { return NS_GET_IID(nsIPageTransitionEventInit); }
virtual nsresult InitFromCtor(const nsAString& aType, nsISupports* aDict,
JSContext* aCx, JSObject* aObj);
virtual nsresult InitFromCtor(const nsAString& aType,
JSContext* aCx, jsval* aVal);
protected:
bool mPersisted;
};

View File

@ -37,6 +37,7 @@
#include "nsDOMClassInfoID.h"
#include "nsIClassInfo.h"
#include "nsIXPCScriptable.h"
#include "DictionaryHelpers.h"
NS_IMPL_CYCLE_COLLECTION_CLASS(nsDOMPopStateEvent)
@ -84,22 +85,13 @@ nsDOMPopStateEvent::InitPopStateEvent(const nsAString &aTypeArg,
}
nsresult
nsDOMPopStateEvent::InitFromCtor(const nsAString& aType, nsISupports* aDict,
JSContext* aCx, JSObject* aObj)
nsDOMPopStateEvent::InitFromCtor(const nsAString& aType,
JSContext* aCx, jsval* aVal)
{
nsCOMPtr<nsIPopStateEventInit> eventInit = do_QueryInterface(aDict);
bool bubbles = false;
bool cancelable = false;
nsCOMPtr<nsIVariant> state;
if (eventInit) {
nsresult rv = eventInit->GetBubbles(&bubbles);
NS_ENSURE_SUCCESS(rv, rv);
rv = eventInit->GetCancelable(&cancelable);
NS_ENSURE_SUCCESS(rv, rv);
rv = eventInit->GetState(getter_AddRefs(state));
NS_ENSURE_SUCCESS(rv, rv);
}
return InitPopStateEvent(aType, bubbles, cancelable, state);
mozilla::dom::PopStateEventInit d;
nsresult rv = d.Init(aCx, aVal);
NS_ENSURE_SUCCESS(rv, rv);
return InitPopStateEvent(aType, d.bubbles, d.cancelable, d.state);
}
nsresult NS_NewDOMPopStateEvent(nsIDOMEvent** aInstancePtrResult,

View File

@ -60,9 +60,8 @@ public:
NS_FORWARD_TO_NSDOMEVENT
virtual const nsIID& EventInitIID() { return NS_GET_IID(nsIPopStateEventInit); }
virtual nsresult InitFromCtor(const nsAString& aType, nsISupports* aDict,
JSContext* aCx, JSObject* aObj);
virtual nsresult InitFromCtor(const nsAString& aType,
JSContext* aCx, jsval* aVal);
protected:
nsCOMPtr<nsIVariant> mState;
};

View File

@ -51,6 +51,7 @@
#include "nsIFrame.h"
#include "nsLayoutUtils.h"
#include "nsIScrollableFrame.h"
#include "DictionaryHelpers.h"
nsDOMUIEvent::nsDOMUIEvent(nsPresContext* aPresContext, nsGUIEvent* aEvent)
: nsDOMEvent(aPresContext, aEvent ?
@ -206,25 +207,13 @@ nsDOMUIEvent::InitUIEvent(const nsAString& typeArg,
}
nsresult
nsDOMUIEvent::InitFromCtor(const nsAString& aType, nsISupports* aDict,
JSContext* aCx, JSObject* aObj)
nsDOMUIEvent::InitFromCtor(const nsAString& aType,
JSContext* aCx, jsval* aVal)
{
nsCOMPtr<nsIUIEventInit> eventInit = do_QueryInterface(aDict);
bool bubbles = false;
bool cancelable = false;
nsCOMPtr<nsIDOMWindow> view;
PRInt32 detail = 0;
if (eventInit) {
nsresult rv = eventInit->GetBubbles(&bubbles);
NS_ENSURE_SUCCESS(rv, rv);
rv = eventInit->GetCancelable(&cancelable);
NS_ENSURE_SUCCESS(rv, rv);
rv = eventInit->GetView(getter_AddRefs(view));
NS_ENSURE_SUCCESS(rv, rv);
rv = eventInit->GetDetail(&detail);
NS_ENSURE_SUCCESS(rv, rv);
}
return InitUIEvent(aType, bubbles, cancelable, view, detail);
mozilla::dom::UIEventInit d;
nsresult rv = d.Init(aCx, aVal);
NS_ENSURE_SUCCESS(rv, rv);
return InitUIEvent(aType, d.bubbles, d.cancelable, d.view, d.detail);
}
// ---- nsDOMNSUIEvent implementation -------------------

View File

@ -64,9 +64,8 @@ public:
NS_FORWARD_NSIDOMNSEVENT(nsDOMEvent::)
virtual const nsIID& EventInitIID() { return NS_GET_IID(nsIUIEventInit); }
virtual nsresult InitFromCtor(const nsAString& aType, nsISupports* aDict,
JSContext* aCx, JSObject* aObj);
virtual nsresult InitFromCtor(const nsAString& aType,
JSContext* aCx, jsval* aVal);
protected:
// Internal helper functions
nsIntPoint GetClientPoint();

View File

@ -33,6 +33,32 @@ try {
ok(ex, "First parameter is required!");
ex = false;
try {
e = new Event("foo", 123);
} catch(exp) {
ex = true;
}
ok(ex, "2nd parameter should be an object!");
ex = false;
try {
e = new Event("foo", "asdf");
} catch(exp) {
ex = true;
}
ok(ex, "2nd parameter should be an object!");
ex = false;
try {
e = new Event("foo", false);
} catch(exp) {
ex = true;
}
ok(ex, "2nd parameter should be an object!");
ex = false;
e = new Event("hello");
ok(e.type, "hello", "Wrong event type!");
ok(!e.isTrusted, "Event shouldn't be trusted!");
@ -94,11 +120,6 @@ is(e.detail, dict.detail, "Wrong event.detail!");
ok(!e.bubbles, "Event shouldn't bubble!");
ok(!e.cancelable, "Event shouldn't be cancelable!");
e = new CustomEvent("hello", 1234);
is(e.detail, null, "Wrong event.detail!");
ok(!e.bubbles, "Event shouldn't bubble!");
ok(!e.cancelable, "Event shouldn't be cancelable!");
var dict = { get detail() { throw "foo"; } };
try {

View File

@ -86,6 +86,7 @@ CPPSRCS = \
XPCQuickStubs.cpp \
dom_quickstubs.cpp \
dombindings.cpp \
DictionaryHelpers.cpp \
$(NULL)
include $(topsrcdir)/config/config.mk
@ -191,14 +192,59 @@ dombindings_gen.cpp: $(srcdir)/dombindings.conf \
--makedepend-output $(MDDEPDIR)/dombindingsgen.pp \
$(srcdir)/dombindings.conf
DictionaryHelpers.$(OBJ_SUFFIX): DictionaryHelpers.h \
DictionaryHelpers.cpp
DictionaryHelpers.h: $(srcdir)/dictionary_helper_gen.conf \
$(srcdir)/dictionary_helper_gen.py \
$(srcdir)/codegen.py \
$(topsrcdir)/xpcom/idl-parser/header.py \
$(topsrcdir)/xpcom/idl-parser/xpidl.py \
$(DEPTH)/js/src/js-confdefs.h
$(PYTHON) $(topsrcdir)/config/pythonpath.py \
-I$(topsrcdir)/other-licenses/ply \
-I$(topsrcdir)/xpcom/idl-parser \
$(srcdir)/dictionary_helper_gen.py \
-I $(DEPTH)/dist/idl \
--cachedir=$(DEPTH)/xpcom/idl-parser/cache \
--header-output DictionaryHelpers.h \
$(srcdir)/dictionary_helper_gen.conf
DictionaryHelpers.cpp: $(srcdir)/dictionary_helper_gen.conf \
$(srcdir)/dictionary_helper_gen.py \
$(srcdir)/codegen.py \
$(topsrcdir)/xpcom/idl-parser/header.py \
$(topsrcdir)/xpcom/idl-parser/xpidl.py \
$(DEPTH)/js/src/js-confdefs.h
$(PYTHON) $(topsrcdir)/config/pythonpath.py \
-I$(topsrcdir)/other-licenses/ply \
-I$(topsrcdir)/xpcom/idl-parser \
$(srcdir)/dictionary_helper_gen.py \
-I $(DEPTH)/dist/idl \
--cachedir=$(DEPTH)/xpcom/idl-parser/cache \
--header-output DictionaryHelpers.h \
--stub-output DictionaryHelpers.cpp \
--makedepend-output $(MDDEPDIR)/dictionary_helper_gen.pp \
$(srcdir)/dictionary_helper_gen.conf
_EXTRA_EXPORT_FILES = \
DictionaryHelpers.h \
$(NULL)
libs:: $(_EXTRA_EXPORT_FILES)
$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/dist/include
GARBAGE += \
dom_quickstubs.h \
dom_quickstubs.cpp \
dombindings_gen.h \
dombindings_gen.cpp \
DictionaryHelpers.h \
DictionaryHelpers.cpp \
xpidl_debug \
$(MDDEPDIR)/dom_qsgen.pp \
$(MDDEPDIR)/dombindingsgen.pp \
$(MDDEPDIR)/dictionary_helper_gen.pp \
$(wildcard $(topsrcdir)/other-licenses/ply/ply/*.pyc) \
$(wildcard $(topsrcdir)/xpcom/idl-parser/*.pyc) \
$(NULL)

View File

@ -2310,6 +2310,9 @@ XPCJSRuntime::newXPCJSRuntime(nsXPConnect* aXPConnect)
return nsnull;
}
// DefineStaticDictionaryJSVals is automatically generated.
bool DefineStaticDictionaryJSVals(JSContext* aCx);
JSBool
XPCJSRuntime::OnJSContextNew(JSContext *cx)
{
@ -2335,6 +2338,10 @@ XPCJSRuntime::OnJSContextNew(JSContext *cx)
}
ok = mozilla::dom::binding::DefineStaticJSVals(cx);
if (!ok)
return false;
ok = DefineStaticDictionaryJSVals(cx);
}
if (!ok)
return false;

View File

@ -0,0 +1,22 @@
# Dictionary interface name, interface file name
dictionaries = [
[ 'nsIEventInit', 'nsIDOMEvent.idl' ],
[ 'nsICustomEventInit', 'nsIDOMCustomEvent.idl' ],
[ 'nsIPopStateEventInit', 'nsIDOMPopStateEvent.idl' ],
[ 'nsIHashChangeEventInit', 'nsIDOMHashChangeEvent.idl' ],
[ 'nsIPageTransitionEventInit', 'nsIDOMPageTransitionEvent.idl' ],
[ 'nsICloseEventInit', 'nsIDOMCloseEvent.idl' ],
[ 'nsIUIEventInit', 'nsIDOMUIEvent.idl' ],
[ 'nsIMouseEventInit', 'nsIDOMMouseEvent.idl' ]
]
# include file names
special_includes = [
'nsContentUtils.h',
'nsIXPConnect.h'
]
# name of the type to not include using #include "typename.h"
exclude_automatic_type_include = [
'nsISupports'
]

View File

@ -0,0 +1,440 @@
#!/usr/bin/env python
# header.py - Generate C++ header files from IDL.
#
# ***** 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 mozilla.org code.
#
# The Initial Developer of the Original Code is
# Mozilla Foundation.
# Portions created by the Initial Developer are Copyright (C) 2011
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
# Olli Pettay <Olli.Pettay@helsinki.fi>
#
# Alternatively, the contents of this file may be used under the terms of
# either of 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 *****
from codegen import *
import sys, os.path, re, xpidl, itertools
# --makedepend-output support.
make_dependencies = []
make_targets = []
def strip_begin(text, suffix):
if not text.startswith(suffix):
return text
return text[len(suffix):]
def strip_end(text, suffix):
if not text.endswith(suffix):
return text
return text[:-len(suffix)]
# Copied from dombindingsgen.py
def writeMakeDependOutput(filename):
print "Creating makedepend file", filename
f = open(filename, 'w')
try:
if len(make_targets) > 0:
f.write("%s:" % makeQuote(make_targets[0]))
for filename in make_dependencies:
f.write(' \\\n\t\t%s' % makeQuote(filename))
f.write('\n\n')
for filename in make_targets[1:]:
f.write('%s: %s\n' % (makeQuote(filename), makeQuote(make_targets[0])))
finally:
f.close()
def findIDL(includePath, interfaceFileName):
for d in includePath:
# Not os.path.join: we need a forward slash even on Windows because
# this filename ends up in makedepend output.
path = d + '/' + interfaceFileName
if os.path.exists(path):
return path
raise BaseException("No IDL file found for interface %s "
"in include path %r"
% (interfaceFileName, includePath))
def loadIDL(parser, includePath, filename):
if not filename in make_dependencies:
make_dependencies.append(filename)
idl = p.parse(open(findIDL(includePath, filename)).read(), filename)
idl.resolve(includePath, p)
return idl
class Configuration:
def __init__(self, filename):
config = {}
execfile(filename, config)
self.dictionaries = config.get('dictionaries', [])
self.special_includes = config.get('special_includes', [])
self.exclude_automatic_type_include = config.get('exclude_automatic_type_include', [])
def readConfigFile(filename):
return Configuration(filename)
def firstCap(str):
return str[0].upper() + str[1:]
def attributeGetterName(a):
binaryname = a.binaryname is not None and a.binaryname or firstCap(a.name)
return "Get%s" % (binaryname)
def attributeParamlist(prefix, a):
if a.realtype.nativeType('in').endswith('*'):
l = ["getter_AddRefs(%s%s)" % (prefix, a.name.strip('* '))]
elif a.realtype.nativeType('in').count("nsAString"):
l = ["%s%s" % (prefix, a.name)]
else:
l = ["&(%s%s)" % (prefix, a.name)]
if a.implicit_jscontext:
l.insert(0, "aCx")
return ", ".join(l)
def attributeVariableTypeAndName(a):
if a.realtype.nativeType('in').endswith('*'):
l = ["nsCOMPtr<%s> %s" % (a.realtype.nativeType('in').strip('* '),
a.name)]
elif a.realtype.nativeType('in').count("nsAString"):
l = ["nsAutoString %s" % a.name]
elif a.realtype.nativeType('in').count("JS::Value"):
l = ["JS::Value %s" % a.name]
else:
l = ["%s%s" % (a.realtype.nativeType('in'),
a.name)]
return ", ".join(l)
def dict_name(iface):
return "%s" % strip_begin(iface, "nsI")
def print_header(idl, fd, conf, dictname, dicts):
for p in idl.productions:
if p.kind == 'interface' and p.name == dictname:
interfaces = []
base = p.base
baseiface = p.idl.getName(p.base, p.location)
while base != "nsISupports" and not base in dicts:
dicts.append(base)
interfaces.append(baseiface)
base = baseiface.base
baseiface = baseiface.idl.getName(baseiface.base, baseiface.location)
interfaces.reverse()
for iface in interfaces:
write_header(iface, fd)
if not p.name in dicts:
dicts.append(p.name)
write_header(p, fd)
def print_header_file(fd, conf):
fd.write("/* THIS FILE IS AUTOGENERATED - DO NOT EDIT */\n\n"
"#ifndef _gen_mozilla_idl_dictionary_helpers_h_\n"
"#define _gen_mozilla_idl_dictionary_helpers_h_\n\n")
fd.write("#include \"jsapi.h\"\n"
"#include \"nsString.h\"\n"
"#include \"nsCOMPtr.h\"\n\n")
forwards = []
attrnames = []
for d in conf.dictionaries:
idl = loadIDL(p, options.incdirs, d[1])
collect_names_and_non_primitive_attribute_types(idl, d[0], attrnames, forwards)
for c in forwards:
fd.write("class %s;\n" % c)
fd.write("\n"
"namespace mozilla {\n"
"namespace dom {\n\n")
dicts = []
for d in conf.dictionaries:
if not d[0] in set(dicts):
idl = loadIDL(p, options.incdirs, d[1])
print_header(idl, fd, conf, d[0], dicts)
fd.write("}\n"
"}\n"
"#endif\n")
def collect_names_and_non_primitive_attribute_types(idl, dictname, attrnames, forwards):
for p in idl.productions:
if p.kind == 'interface' and p.name == dictname:
interfaces = []
base = p.base
baseiface = p.idl.getName(p.base, p.location)
while base != "nsISupports":
interfaces.append(baseiface)
base = baseiface.base
baseiface = baseiface.idl.getName(baseiface.base, baseiface.location)
interfaces.reverse()
interfaces.append(p)
for iface in interfaces:
collect_names_and_non_primitive_attribute_types_from_interface(iface, attrnames, forwards)
def collect_names_and_non_primitive_attribute_types_from_interface(iface, attrnames, forwards):
for member in iface.members:
if isinstance(member, xpidl.Attribute):
if not member.name in attrnames:
attrnames.append(member.name)
if member.realtype.nativeType('in').endswith('*'):
t = member.realtype.nativeType('in').strip('* ')
if not t in forwards:
forwards.append(t)
def print_cpp(idl, fd, conf, dictname, dicts):
for p in idl.productions:
if p.kind == 'interface' and p.name == dictname:
interfaces = []
base = p.base
baseiface = p.idl.getName(p.base, p.location)
while base != "nsISupports" and not base in dicts:
dicts.append(base)
interfaces.append(baseiface)
base = baseiface.base
baseiface = baseiface.idl.getName(baseiface.base, baseiface.location)
interfaces.reverse()
for iface in interfaces:
write_cpp(iface, fd)
if not p.name in dicts:
dicts.append(p.name)
write_cpp(p, fd)
def get_jsid(name):
return ("gDictionary_id_%s" % name)
def print_cpp_file(fd, conf):
fd.write("/* THIS FILE IS AUTOGENERATED - DO NOT EDIT */\n\n")
fd.write('#include "DictionaryHelpers.h"\n')
includes = []
for s in conf.special_includes:
if not s in includes:
includes.append(strip_end(s, ".h"))
for d in conf.dictionaries:
if not d[1] in includes:
includes.append(strip_end(d[1], ".idl"))
attrnames = []
for d in conf.dictionaries:
idl = loadIDL(p, options.incdirs, d[1])
collect_names_and_non_primitive_attribute_types(idl, d[0], attrnames, includes)
for c in includes:
if not c in conf.exclude_automatic_type_include:
fd.write("#include \"%s.h\"\n" % c)
fd.write("\nusing namespace mozilla::dom;\n\n")
for a in attrnames:
fd.write("static jsid %s = JSID_VOID;\n"% get_jsid(a))
fd.write("\n"
"static bool\n"
"DefineStaticJSVal(JSContext* aCx, jsid &id, const char* aString)\n"
"{\n"
" if (JSString* str = JS_InternString(aCx, aString)) {\n"
" id = INTERNED_STRING_TO_JSID(aCx, str);\n"
" return true;\n"
" }\n"
" return false;\n"
"}\n\n"
"bool\n"
"DefineStaticDictionaryJSVals(JSContext* aCx)\n"
"{\n"
" JSAutoRequest ar(aCx);\n"
" return\n")
for a in attrnames:
fd.write(" DefineStaticJSVal(aCx, %s, \"%s\") &&\n"
% (get_jsid(a), a))
fd.write(" true;\n")
fd.write("}\n\n")
dicts = []
for d in conf.dictionaries:
if not d[0] in set(dicts):
idl = p.parse(open(findIDL(options.incdirs, d[1])).read(), d[1])
idl.resolve(options.incdirs, p)
print_cpp(idl, fd, conf, d[0], dicts)
def init_value(attribute):
realtype = attribute.realtype.nativeType('in')
realtype = realtype.strip(' ')
if realtype.endswith('*'):
return "nsnull"
if realtype == "bool":
return "false"
if realtype.count("nsAString"):
return "EmptyString()"
if realtype.count("nsACString"):
return "EmptyCString()"
if realtype.count("JS::Value"):
return "JSVAL_VOID"
return "0"
def write_header(iface, fd):
attributes = []
for member in iface.members:
if isinstance(member, xpidl.Attribute):
attributes.append(member)
fd.write("class %s" % dict_name(iface.name))
if iface.base != "nsISupports":
fd.write(" : public %s" % dict_name(iface.base))
fd.write("\n{\npublic:\n")
fd.write(" %s()" % dict_name(iface.name))
if iface.base != "nsISupports" or len(attributes) > 0:
fd.write(" :\n")
if iface.base != "nsISupports":
fd.write(" %s()" % dict_name(iface.base))
if len(attributes) > 0:
fd.write(",\n")
for i in range(len(attributes)):
fd.write(" %s(%s)" % (attributes[i].name, init_value(attributes[i])))
if i < (len(attributes) - 1):
fd.write(",")
fd.write("\n")
fd.write(" {}\n\n")
fd.write(" // If aCx or aVal is null, NS_OK is returned and \n"
" // dictionary will use the default values. \n"
" nsresult Init(JSContext* aCx, const jsval* aVal);\n")
fd.write("\n")
for member in attributes:
fd.write(" %s;\n" % attributeVariableTypeAndName(member))
fd.write("};\n\n")
def write_cpp(iface, fd):
attributes = []
for member in iface.members:
if isinstance(member, xpidl.Attribute):
attributes.append(member)
fd.write("static nsresult\n%s_InitInternal(%s& aDict, %s* aIfaceObject, JSContext* aCx, JSObject* aObj)\n" %
(dict_name(iface.name), dict_name(iface.name), iface.name))
fd.write("{\n")
if iface.base != "nsISupports":
fd.write(" nsresult rv = %s_InitInternal(aDict, aIfaceObject, aCx, aObj);\n" %
dict_name(iface.base))
fd.write(" NS_ENSURE_SUCCESS(rv, rv);\n")
fd.write(" JSBool found = PR_FALSE;\n")
for a in attributes:
fd.write(" NS_ENSURE_STATE(JS_HasPropertyById(aCx, aObj, %s, &found));\n"
% get_jsid(a.name))
fd.write(" if (found) {\n")
fd.write(" nsresult rv = aIfaceObject->%s(" % attributeGetterName(a))
fd.write("%s" % attributeParamlist("aDict.", a))
fd.write(");\n")
fd.write(" NS_ENSURE_SUCCESS(rv, rv);\n")
fd.write(" }\n")
fd.write(" return NS_OK;\n")
fd.write("}\n\n")
fd.write("nsresult\n%s::Init(JSContext* aCx, const jsval* aVal)\n" % dict_name(iface.name))
fd.write("{\n"
" if (!aCx || !aVal) {\n"
" return NS_OK;\n"
" }\n"
" NS_ENSURE_STATE(JSVAL_IS_OBJECT(*aVal));\n\n"
" JSObject* obj = JSVAL_TO_OBJECT(*aVal);\n"
" nsCxPusher pusher;\n"
" NS_ENSURE_STATE(pusher.Push(aCx, false));\n"
" JSAutoRequest ar(aCx);\n"
" JSAutoEnterCompartment ac;\n"
" NS_ENSURE_STATE(ac.enter(aCx, obj));\n")
fd.write(" nsCOMPtr<%s> dict;\n" % iface.name)
fd.write(" nsContentUtils::XPConnect()->WrapJS(aCx, obj,\n")
fd.write(" NS_GET_IID(%s),\n" % iface.name)
fd.write(" getter_AddRefs(dict));\n")
fd.write(" NS_ENSURE_TRUE(dict, NS_OK);\n")
fd.write(" return %s_InitInternal(*this, dict, aCx, obj);\n}\n\n" %
dict_name(iface.name))
if __name__ == '__main__':
from optparse import OptionParser
o = OptionParser(usage="usage: %prog [options] configfile")
o.add_option('-I', action='append', dest='incdirs', default=['.'],
help="Directory to search for imported files")
o.add_option('-o', "--stub-output",
type='string', dest='stub_output', default=None,
help="Quick stub C++ source output file", metavar="FILE")
o.add_option('--header-output', type='string', default=None,
help="Quick stub header output file", metavar="FILE")
o.add_option('--makedepend-output', type='string', default=None,
help="gnumake dependencies output file", metavar="FILE")
o.add_option('--cachedir', dest='cachedir', default='',
help="Directory in which to cache lex/parse tables.")
(options, filenames) = o.parse_args()
if len(filenames) != 1:
o.error("Exactly one config filename is needed.")
filename = filenames[0]
if options.cachedir is not None:
if not os.path.isdir(options.cachedir):
os.mkdir(options.cachedir)
sys.path.append(options.cachedir)
# Instantiate the parser.
p = xpidl.IDLParser(outputdir=options.cachedir)
conf = readConfigFile(filename)
if options.header_output is not None:
outfd = open(options.header_output, 'w')
print_header_file(outfd, conf)
outfd.close()
if options.stub_output is not None:
make_targets.append(options.stub_output)
outfd = open(options.stub_output, 'w')
print_cpp_file(outfd, conf)
outfd.close()
if options.makedepend_output is not None:
writeMakeDependOutput(options.makedepend_output)