mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 661980: Add ability to make interfaces scriptable but not scriptimplementable. r=bsmedberg
This commit is contained in:
parent
8bfa7dd3e7
commit
caef7c47a8
@ -53,7 +53,7 @@ interface nsIDOMBlob;
|
||||
#include "jsapi.h"
|
||||
%}
|
||||
|
||||
[scriptable, uuid(dea238a1-240f-45f4-9f07-7769bc69eb76)]
|
||||
[scriptable, builtinclass, uuid(dea238a1-240f-45f4-9f07-7769bc69eb76)]
|
||||
interface nsIXMLHttpRequestEventTarget : nsIDOMEventTarget {
|
||||
// event handler attributes
|
||||
attribute nsIDOMEventListener onabort;
|
||||
@ -64,7 +64,7 @@ interface nsIXMLHttpRequestEventTarget : nsIDOMEventTarget {
|
||||
attribute nsIDOMEventListener onloadend;
|
||||
};
|
||||
|
||||
[scriptable, uuid(09ff3682-7759-4441-a765-f70e1a1fabcf)]
|
||||
[scriptable, builtinclass, uuid(09ff3682-7759-4441-a765-f70e1a1fabcf)]
|
||||
interface nsIXMLHttpRequestUpload : nsIXMLHttpRequestEventTarget {
|
||||
// for future use
|
||||
};
|
||||
|
@ -47,7 +47,7 @@
|
||||
* http://www.w3.org/TR/DOM-Level-2-Events/
|
||||
*/
|
||||
|
||||
[scriptable, uuid(1c773b30-d1cf-11d2-bd95-00805f8ae3f4)]
|
||||
[scriptable, builtinclass, uuid(1c773b30-d1cf-11d2-bd95-00805f8ae3f4)]
|
||||
interface nsIDOMEventTarget : nsISupports
|
||||
{
|
||||
/**
|
||||
|
@ -128,13 +128,13 @@ interface nsIWorkerScope : nsIWorkerGlobalScope
|
||||
attribute nsIDOMEventListener onclose;
|
||||
};
|
||||
|
||||
[scriptable, uuid(b90b7561-b5e2-4545-84b0-280dbaaa94ea)]
|
||||
[scriptable, builtinclass, uuid(b90b7561-b5e2-4545-84b0-280dbaaa94ea)]
|
||||
interface nsIAbstractWorker : nsIDOMEventTarget
|
||||
{
|
||||
attribute nsIDOMEventListener onerror;
|
||||
};
|
||||
|
||||
[scriptable, uuid(daf945c3-8d29-4724-8939-dd383f7d27a7)]
|
||||
[scriptable, builtinclass, uuid(daf945c3-8d29-4724-8939-dd383f7d27a7)]
|
||||
interface nsIWorker : nsIAbstractWorker
|
||||
{
|
||||
void postMessage(/* in JSObject aMessage */);
|
||||
|
@ -166,8 +166,9 @@ nsXPCWrappedJSClass::GetNewOrUsed(XPCCallContext& ccx, REFNSIID aIID,
|
||||
ccx.GetXPConnect()->GetInfoForIID(&aIID, getter_AddRefs(info));
|
||||
if(info)
|
||||
{
|
||||
PRBool canScript;
|
||||
PRBool canScript, isBuiltin;
|
||||
if(NS_SUCCEEDED(info->IsScriptable(&canScript)) && canScript &&
|
||||
NS_SUCCEEDED(info->IsBuiltinClass(&isBuiltin)) && !isBuiltin &&
|
||||
nsXPConnect::IsISupportsDescendant(info))
|
||||
{
|
||||
clazz = new nsXPCWrappedJSClass(ccx, aIID, info);
|
||||
@ -295,8 +296,9 @@ nsXPCWrappedJSClass::CallQueryInterfaceOnJSObject(XPCCallContext& ccx,
|
||||
ccx.GetXPConnect()->GetInfoForIID(&aIID, getter_AddRefs(info));
|
||||
if(!info)
|
||||
return nsnull;
|
||||
PRBool canScript;
|
||||
if(NS_FAILED(info->IsScriptable(&canScript)) || !canScript)
|
||||
PRBool canScript, isBuiltin;
|
||||
if(NS_FAILED(info->IsScriptable(&canScript)) || !canScript ||
|
||||
NS_FAILED(info->IsBuiltinClass(&isBuiltin)) || isBuiltin)
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
|
@ -89,6 +89,7 @@ _TEST_FILES = bug500931_helper.html \
|
||||
test2_bug629331.html \
|
||||
test_bug618017.html \
|
||||
test_bug636097.html \
|
||||
test_bug661980.html \
|
||||
test_bug650273.html \
|
||||
file_bug650273.html \
|
||||
file_bug658560.html \
|
||||
|
62
js/src/xpconnect/tests/mochitest/test_bug661980.html
Normal file
62
js/src/xpconnect/tests/mochitest/test_bug661980.html
Normal file
@ -0,0 +1,62 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=661980
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 661980</title>
|
||||
<script type="application/javascript" src="/MochiKit/packed.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=661980">Mozilla Bug 661980</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
|
||||
/** Test for Bug 661980 **/
|
||||
|
||||
// While not currently needed, make this as similar as possible to a real
|
||||
// EventTarget just to make sure that we're tripping on the wrapping and
|
||||
// nothing else.
|
||||
var fakeTarget = {
|
||||
addEventListener: function() {},
|
||||
removeEventListener: function() {},
|
||||
dispatchEvent: function() {}
|
||||
}
|
||||
|
||||
var mouseevent = document.createEvent("MouseEvent");
|
||||
var didThrow = false;
|
||||
dump("hello nurse");
|
||||
try {
|
||||
mouseevent.initMouseEvent("mouseover",
|
||||
false, false,
|
||||
window,
|
||||
1, 2, 3, 4, 5,
|
||||
false, false, false, false,
|
||||
0,
|
||||
fakeTarget);
|
||||
}
|
||||
catch (ex) {
|
||||
didThrow = true;
|
||||
}
|
||||
ok(didThrow, "should not be able to implement EventTarget using script");
|
||||
|
||||
mouseevent.initMouseEvent("mouseout",
|
||||
false, false,
|
||||
window,
|
||||
1, 2, 3, 4, 5,
|
||||
false, false, false, false,
|
||||
0,
|
||||
document.body);
|
||||
is(mouseevent.type, "mouseout",
|
||||
"should able to implement EventTarget using Element");
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
@ -49,7 +49,7 @@
|
||||
* pointer identity.
|
||||
*/
|
||||
|
||||
[scriptable, uuid(1f341018-521a-49de-b806-1bef5c9a00b0)]
|
||||
[scriptable, builtinclass, uuid(1f341018-521a-49de-b806-1bef5c9a00b0)]
|
||||
interface nsIAtom : nsISupports
|
||||
{
|
||||
/**
|
||||
|
@ -549,6 +549,7 @@ class Interface(object):
|
||||
class InterfaceAttributes(object):
|
||||
uuid = None
|
||||
scriptable = False
|
||||
builtinclass = False
|
||||
function = False
|
||||
deprecated = False
|
||||
noscript = False
|
||||
@ -565,12 +566,16 @@ class InterfaceAttributes(object):
|
||||
def setnoscript(self):
|
||||
self.noscript = True
|
||||
|
||||
def setbuiltinclass(self):
|
||||
self.builtinclass = True
|
||||
|
||||
def setdeprecated(self):
|
||||
self.deprecated = True
|
||||
|
||||
actions = {
|
||||
'uuid': (True, setuuid),
|
||||
'scriptable': (False, setscriptable),
|
||||
'builtinclass': (False, setbuiltinclass),
|
||||
'function': (False, setfunction),
|
||||
'noscript': (False, setnoscript),
|
||||
'deprecated': (False, setdeprecated),
|
||||
@ -605,6 +610,8 @@ class InterfaceAttributes(object):
|
||||
l.append("\tuuid: %s\n" % self.uuid)
|
||||
if self.scriptable:
|
||||
l.append("\tscriptable\n")
|
||||
if self.builtinclass:
|
||||
l.append("\tbuiltinclass\n")
|
||||
if self.function:
|
||||
l.append("\tfunction\n")
|
||||
return "".join(l)
|
||||
|
@ -76,7 +76,7 @@ NS_GetXPTCallStub(REFNSIID aIID, nsIXPTCProxy* aOuter,
|
||||
NS_ENSURE_TRUE(iim, NS_ERROR_NOT_INITIALIZED);
|
||||
|
||||
xptiInterfaceEntry *iie = iim->GetInterfaceEntryForIID(&aIID);
|
||||
if (!iie || !iie->EnsureResolved())
|
||||
if (!iie || !iie->EnsureResolved() || iie->GetBuiltinClassFlag())
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsXPTCStubBase* newbase = new nsXPTCStubBase(aOuter, iie);
|
||||
|
@ -58,13 +58,14 @@ class nsXPTType;
|
||||
%}
|
||||
|
||||
/* this is NOT intended to be scriptable */
|
||||
[uuid(215DBE04-94A7-11d2-BA58-00805F8A5DD7)]
|
||||
[uuid(7de126a2-ef4b-4e3b-a952-78ce4c133e38)]
|
||||
interface nsIInterfaceInfo : nsISupports
|
||||
{
|
||||
readonly attribute string name;
|
||||
readonly attribute nsIIDPtr InterfaceIID;
|
||||
|
||||
PRBool isScriptable();
|
||||
PRBool isBuiltinClass();
|
||||
|
||||
readonly attribute nsIInterfaceInfo parent;
|
||||
|
||||
|
@ -273,6 +273,7 @@ xptiInterfaceInfoManager::VerifyAndAddEntryIfNew(XPTInterfaceDirectoryEntry* ifa
|
||||
|
||||
//XXX We should SetHeader too as part of the validation, no?
|
||||
entry->SetScriptableFlag(XPT_ID_IS_SCRIPTABLE(iface->interface_descriptor->flags));
|
||||
entry->SetBuiltinClassFlag(XPT_ID_IS_BUILTINCLASS(iface->interface_descriptor->flags));
|
||||
|
||||
mWorkingSet.mIIDTable.Put(entry->IID(), entry);
|
||||
mWorkingSet.mNameTable.Put(entry->GetTheName(), entry);
|
||||
|
@ -250,7 +250,7 @@ public:
|
||||
};
|
||||
|
||||
// Additional bit flags...
|
||||
enum {SCRIPTABLE = 4};
|
||||
enum {SCRIPTABLE = 4, BUILTINCLASS = 8};
|
||||
|
||||
PRUint8 GetResolveState() const {return mFlags.GetState();}
|
||||
|
||||
@ -261,6 +261,10 @@ public:
|
||||
{mFlags.SetFlagBit(PRUint8(SCRIPTABLE),on);}
|
||||
PRBool GetScriptableFlag() const
|
||||
{return mFlags.GetFlagBit(PRUint8(SCRIPTABLE));}
|
||||
void SetBuiltinClassFlag(PRBool on)
|
||||
{mFlags.SetFlagBit(PRUint8(BUILTINCLASS),on);}
|
||||
PRBool GetBuiltinClassFlag() const
|
||||
{return mFlags.GetFlagBit(PRUint8(BUILTINCLASS));}
|
||||
|
||||
const nsID* GetTheIID() const {return &mIID;}
|
||||
const char* GetTheName() const {return mName;}
|
||||
@ -288,6 +292,10 @@ public:
|
||||
nsresult GetName(char * *aName);
|
||||
nsresult GetIID(nsIID * *aIID);
|
||||
nsresult IsScriptable(PRBool *_retval);
|
||||
nsresult IsBuiltinClass(PRBool *_retval) {
|
||||
*_retval = GetBuiltinClassFlag();
|
||||
return NS_OK;
|
||||
}
|
||||
// Except this one.
|
||||
//nsresult GetParent(nsIInterfaceInfo * *aParent);
|
||||
nsresult GetMethodCount(PRUint16 *aMethodCount);
|
||||
@ -363,6 +371,7 @@ public:
|
||||
NS_IMETHOD GetName(char * *aName) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetName(aName); }
|
||||
NS_IMETHOD GetInterfaceIID(nsIID * *aIID) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetIID(aIID); }
|
||||
NS_IMETHOD IsScriptable(PRBool *_retval) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->IsScriptable(_retval); }
|
||||
NS_IMETHOD IsBuiltinClass(PRBool *_retval) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->IsBuiltinClass(_retval); }
|
||||
// Except this one.
|
||||
NS_IMETHOD GetParent(nsIInterfaceInfo * *aParent)
|
||||
{
|
||||
|
@ -520,6 +520,9 @@ typelib_interface(TreeState *state)
|
||||
if (IDL_tree_property_get(IDL_INTERFACE(iface).ident, "function"))
|
||||
interface_flags |= XPT_ID_FUNCTION;
|
||||
|
||||
if (IDL_tree_property_get(IDL_INTERFACE(iface).ident, "builtinclass"))
|
||||
interface_flags |= XPT_ID_BUILTINCLASS;
|
||||
|
||||
ide = FindInterfaceByName(HEADER(state)->interface_directory,
|
||||
HEADER(state)->num_interfaces, name);
|
||||
if (!ide) {
|
||||
|
@ -885,23 +885,40 @@ xpidl_list_foreach(IDL_tree p, IDL_tree_func foreach, gpointer user_data)
|
||||
gboolean
|
||||
verify_interface_declaration(IDL_tree interface_tree)
|
||||
{
|
||||
gboolean scriptable =
|
||||
IDL_tree_property_get(IDL_INTERFACE(interface_tree).ident,
|
||||
"scriptable") != NULL;
|
||||
gboolean builtinclass =
|
||||
IDL_tree_property_get(IDL_INTERFACE(interface_tree).ident,
|
||||
"builtinclass") != NULL;
|
||||
|
||||
IDL_tree iter;
|
||||
/*
|
||||
* If we have the scriptable attribute then make sure all of our direct
|
||||
* parents have it as well.
|
||||
* NOTE: We don't recurse since all interfaces will fall through here
|
||||
* NOTE: We don't recurse since all interfaces will come through here
|
||||
*/
|
||||
if (IDL_tree_property_get(IDL_INTERFACE(interface_tree).ident,
|
||||
"scriptable")) {
|
||||
if (scriptable || !builtinclass) {
|
||||
for (iter = IDL_INTERFACE(interface_tree).inheritance_spec; iter;
|
||||
iter = IDL_LIST(iter).next) {
|
||||
if (IDL_tree_property_get(
|
||||
IDL_INTERFACE(iter).ident, "scriptable") == 0) {
|
||||
if (scriptable &&
|
||||
IDL_tree_property_get(
|
||||
IDL_INTERFACE(iter).ident, "scriptable") == 0) {
|
||||
XPIDL_WARNING((interface_tree,IDL_WARNING1,
|
||||
"%s is scriptable but inherits from the non-scriptable interface %s\n",
|
||||
IDL_IDENT(IDL_INTERFACE(interface_tree).ident).str,
|
||||
IDL_IDENT(IDL_INTERFACE(iter).ident).str));
|
||||
}
|
||||
if (!builtinclass &&
|
||||
IDL_tree_property_get(
|
||||
IDL_INTERFACE(iter).ident, "builtinclass")) {
|
||||
IDL_tree_error(interface_tree,
|
||||
"%s is not [builtinclass] but extends "
|
||||
"[builtinclass] interface %s",
|
||||
IDL_IDENT(IDL_INTERFACE(interface_tree).ident).str,
|
||||
IDL_IDENT(IDL_INTERFACE(iter).ident).str);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
|
@ -264,12 +264,14 @@ struct XPTInterfaceDescriptor {
|
||||
|
||||
#define XPT_ID_SCRIPTABLE 0x80
|
||||
#define XPT_ID_FUNCTION 0x40
|
||||
#define XPT_ID_FLAGMASK 0xc0
|
||||
#define XPT_ID_BUILTINCLASS 0x20
|
||||
#define XPT_ID_FLAGMASK 0xe0
|
||||
#define XPT_ID_TAGMASK (~XPT_ID_FLAGMASK)
|
||||
#define XPT_ID_TAG(id) ((id).flags & XPT_ID_TAGMASK)
|
||||
|
||||
#define XPT_ID_IS_SCRIPTABLE(flags) (!!(flags & XPT_ID_SCRIPTABLE))
|
||||
#define XPT_ID_IS_FUNCTION(flags) (!!(flags & XPT_ID_FUNCTION))
|
||||
#define XPT_ID_IS_BUILTINCLASS(flags) (!!(flags & XPT_ID_BUILTINCLASS))
|
||||
|
||||
extern XPT_PUBLIC_API(PRBool)
|
||||
XPT_GetInterfaceIndexByName(XPTInterfaceDirectoryEntry *ide_block,
|
||||
|
@ -845,7 +845,7 @@ class Interface(object):
|
||||
|
||||
def __init__(self, name, iid=UNRESOLVED_IID, namespace="",
|
||||
resolved=False, parent=None, methods=[], constants=[],
|
||||
scriptable=False, function=False):
|
||||
scriptable=False, function=False, builtinclass=False):
|
||||
self.resolved = resolved
|
||||
#TODO: should validate IIDs!
|
||||
self.iid = iid
|
||||
@ -857,6 +857,7 @@ class Interface(object):
|
||||
self.constants = list(constants)
|
||||
self.scriptable = scriptable
|
||||
self.function = function
|
||||
self.builtinclass = builtinclass
|
||||
# For sanity, if someone constructs an Interface and passes
|
||||
# in methods or constants, then it's resolved.
|
||||
if self.methods or self.constants:
|
||||
@ -922,11 +923,13 @@ class Interface(object):
|
||||
(flags, ) = struct.unpack(">B", map[start:start + struct.calcsize(">B")])
|
||||
offset = offset + struct.calcsize(">B")
|
||||
# only the first two bits are flags
|
||||
flags &= 0xC0
|
||||
flags &= 0xE0
|
||||
if flags & 0x80:
|
||||
self.scriptable = True
|
||||
if flags & 0x40:
|
||||
self.function = True
|
||||
if flags & 0x20:
|
||||
self.builtinclass = True
|
||||
self.resolved = True
|
||||
|
||||
def write_directory_entry(self, file):
|
||||
@ -965,6 +968,8 @@ class Interface(object):
|
||||
flags |= 0x80
|
||||
if self.function:
|
||||
flags |= 0x40
|
||||
if self.builtinclass:
|
||||
flags |= 0x20
|
||||
file.write(struct.pack(">B", flags))
|
||||
|
||||
def write_names(self, file, data_pool_offset):
|
||||
@ -1260,7 +1265,9 @@ class Typelib(object):
|
||||
i.parent.name))
|
||||
out.write(""" Flags:
|
||||
Scriptable: %s
|
||||
BuiltinClass: %s
|
||||
Function: %s\n""" % (i.scriptable and "TRUE" or "FALSE",
|
||||
i.builtinclass and "TRUE" or "FALSE",
|
||||
i.function and "TRUE" or "FALSE"))
|
||||
out.write(" Methods:\n")
|
||||
if len(i.methods) == 0:
|
||||
|
Loading…
Reference in New Issue
Block a user