mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 861493. When passing arguments to an Xray for a WebIDL constructor, make sure to do the argument unwrapping before entering the content compartment. r=bholley,waldo
There are several changes here: 1) Adds some MutableThis methods to Optional, Nullable, and dictionaries to effectively allow doing a const_cast without knowing the actual type being templated over. I needed this because I do not in fact know that type in the relevant code. I'm open to suggestions for a better name for this method. 2) Adds some operator& to RootedJSValue to make it look more like a JS::Value, and in particular so I can JS_WrapValue the thing in it. 3) Adds a Slot() method to NonNullLazyRootedObject, just like NonNull has. 4) Adds an operator& to LazyRootedObject to make it look more like JSObject* so I can JS_WrapObject the thing in it. 5) Implements the actual rewrapping of the arguments into the content compartment. 6) Fixes a small preexisting bug in which we didn't look at named constructors in getTypesFromDescriptor (this was causing my tests to not compile). 7) Changes Xrays to not enter the content compartment when calling a WebIDL constructor. 8) Adds some friend API to report things as not being functions.
This commit is contained in:
parent
b49ac0cc45
commit
7041704c76
@ -265,6 +265,11 @@ public:
|
||||
return mImpl.ref();
|
||||
}
|
||||
|
||||
Optional& AsMutable() const
|
||||
{
|
||||
return *const_cast<Optional*>(this);
|
||||
}
|
||||
|
||||
// If we ever decide to add conversion operators for optional arrays
|
||||
// like the ones Nullable has, we'll need to ensure that Maybe<> has
|
||||
// the boolean before the actual data.
|
||||
@ -379,6 +384,16 @@ public:
|
||||
return mValue;
|
||||
}
|
||||
|
||||
JS::Value* operator&()
|
||||
{
|
||||
return &mValue;
|
||||
}
|
||||
|
||||
const JS::Value* operator&() const
|
||||
{
|
||||
return &mValue;
|
||||
}
|
||||
|
||||
private:
|
||||
// Don't allow copy-construction of these objects, because it'll do the wrong
|
||||
// thing with our flag mCx.
|
||||
|
@ -1431,6 +1431,11 @@ public:
|
||||
MOZ_ASSERT(!empty() && ref(), "Can not alias null.");
|
||||
return *ref();
|
||||
}
|
||||
|
||||
JSObject** Slot() { // To make us look like a NonNull
|
||||
// Assert if we're empty, on purpose
|
||||
return ref().address();
|
||||
}
|
||||
};
|
||||
|
||||
class LazyRootedObject : public Maybe<JS::RootedObject>
|
||||
@ -1439,6 +1444,12 @@ public:
|
||||
operator JSObject*() const {
|
||||
return empty() ? (JSObject*) nullptr : ref();
|
||||
}
|
||||
|
||||
JSObject** operator&()
|
||||
{
|
||||
// Assert if we're empty, on purpose
|
||||
return ref().address();
|
||||
}
|
||||
};
|
||||
|
||||
// A struct that has the same layout as an nsDependentString but much
|
||||
|
@ -1080,7 +1080,7 @@ class CGClassConstructor(CGAbstractStaticMethod):
|
||||
name = self._ctor.identifier.name
|
||||
nativeName = MakeNativeName(self.descriptor.binaryNames.get(name, name))
|
||||
callGenerator = CGMethodCall(nativeName, True, self.descriptor,
|
||||
self._ctor)
|
||||
self._ctor, isConstructor=True)
|
||||
return preamble + callGenerator.define();
|
||||
|
||||
class CGClassConstructHookHolder(CGGeneric):
|
||||
@ -4031,6 +4031,93 @@ class MethodNotCreatorError(Exception):
|
||||
def __init__(self, typename):
|
||||
self.typename = typename
|
||||
|
||||
# A counter for making sure that when we're wrapping up things in
|
||||
# nested sequences we don't use the same variable name to iterate over
|
||||
# different sequences.
|
||||
sequenceWrapLevel = 0
|
||||
|
||||
def wrapTypeIntoCurrentCompartment(type, value):
|
||||
"""
|
||||
Take the thing named by "value" and if it contains "any",
|
||||
"object", or spidermonkey-interface types inside return a CGThing
|
||||
that will wrap them into the current compartment.
|
||||
"""
|
||||
if type.isAny():
|
||||
assert not type.nullable()
|
||||
return CGGeneric("if (!JS_WrapValue(cx, &%s)) {\n"
|
||||
" return false;\n"
|
||||
"}" % value)
|
||||
|
||||
if type.isObject():
|
||||
if not type.nullable():
|
||||
value = "%s.Slot()" % value
|
||||
else:
|
||||
value = "&%s" % value
|
||||
return CGGeneric("if (!JS_WrapObject(cx, %s)) {\n"
|
||||
" return false;\n"
|
||||
"}" % value)
|
||||
|
||||
if type.isSpiderMonkeyInterface():
|
||||
raise TypeError("Can't handle wrapping of spidermonkey interfaces in "
|
||||
"constructor arguments yet")
|
||||
|
||||
if type.isSequence():
|
||||
if type.nullable():
|
||||
type = type.inner
|
||||
value = "%s.AsMutable().Value()" % value
|
||||
global sequenceWrapLevel
|
||||
index = "indexName%d" % sequenceWrapLevel
|
||||
sequenceWrapLevel += 1
|
||||
wrapElement = wrapTypeIntoCurrentCompartment(type.inner,
|
||||
"%s[%s]" % (value, index))
|
||||
sequenceWrapLevel -= 1
|
||||
if not wrapElement:
|
||||
return None
|
||||
return CGWrapper(CGIndenter(wrapElement),
|
||||
pre=("for (uint32_t %s = 0; %s < %s.Length(); ++%s) {\n" %
|
||||
(index, index, value, index)),
|
||||
post="\n}")
|
||||
|
||||
if type.isDictionary():
|
||||
assert not type.nullable()
|
||||
value = "%s.AsMutable()" % value
|
||||
myDict = type.inner
|
||||
memberWraps = []
|
||||
while myDict:
|
||||
for member in myDict.members:
|
||||
memberWrap = wrapArgIntoCurrentCompartment(
|
||||
member,
|
||||
"%s.%s" % (value, CGDictionary.makeMemberName(member.identifier.name)))
|
||||
if memberWrap:
|
||||
memberWraps.append(memberWrap)
|
||||
myDict = myDict.parent
|
||||
return CGList(memberWraps, "\n") if len(memberWraps) != 0 else None
|
||||
|
||||
if type.isUnion():
|
||||
raise TypeError("Can't handle wrapping of unions in constructor "
|
||||
"arguments yet")
|
||||
|
||||
if (type.isString() or type.isPrimitive() or type.isEnum() or
|
||||
type.isGeckoInterface() or type.isCallback()):
|
||||
# All of these don't need wrapping
|
||||
return None
|
||||
|
||||
raise TypeError("Unknown type; we don't know how to wrap it in constructor "
|
||||
"arguments: %s" % type)
|
||||
|
||||
def wrapArgIntoCurrentCompartment(arg, value):
|
||||
"""
|
||||
As wrapTypeIntoCurrentCompartment but handles things being optional
|
||||
"""
|
||||
origValue = value
|
||||
isOptional = arg.optional and not arg.defaultValue
|
||||
if isOptional:
|
||||
value = value + ".AsMutable().Value()"
|
||||
wrap = wrapTypeIntoCurrentCompartment(arg.type, value)
|
||||
if wrap and isOptional:
|
||||
wrap = CGIfWrapper(wrap, "%s.WasPassed()" % origValue)
|
||||
return wrap
|
||||
|
||||
class CGPerSignatureCall(CGThing):
|
||||
"""
|
||||
This class handles the guts of generating code for a particular
|
||||
@ -4056,7 +4143,7 @@ class CGPerSignatureCall(CGThing):
|
||||
|
||||
def __init__(self, returnType, arguments, nativeMethodName, static,
|
||||
descriptor, idlNode, argConversionStartsAt=0, getter=False,
|
||||
setter=False):
|
||||
setter=False, isConstructor=False):
|
||||
assert idlNode.isMethod() == (not getter and not setter)
|
||||
assert idlNode.isAttr() == (getter or setter)
|
||||
|
||||
@ -4117,6 +4204,30 @@ if (global.Failed()) {
|
||||
lenientFloatCode=lenientFloatCode) for
|
||||
i in range(argConversionStartsAt, self.argCount)])
|
||||
|
||||
if isConstructor:
|
||||
# If we're called via an xray, we need to enter the underlying
|
||||
# object's compartment and then wrap up all of our arguments into
|
||||
# that compartment as needed. This is all happening after we've
|
||||
# already done the conversions from JS values to WebIDL (C++)
|
||||
# values, so we only need to worry about cases where there are 'any'
|
||||
# or 'object' types, or other things that we represent as actual
|
||||
# JSAPI types, present. Effectively, we're emulating a
|
||||
# CrossCompartmentWrapper, but working with the C++ types, not the
|
||||
# original list of JS::Values.
|
||||
cgThings.append(CGGeneric("Maybe<JSAutoCompartment> ac;"))
|
||||
xraySteps = [
|
||||
CGGeneric("obj = js::CheckedUnwrap(obj);\n"
|
||||
"if (!obj) {\n"
|
||||
" return false;\n"
|
||||
"}\n"
|
||||
"ac.construct(cx, obj);") ]
|
||||
xraySteps.extend(
|
||||
wrapArgIntoCurrentCompartment(arg, argname)
|
||||
for (arg, argname) in self.getArguments())
|
||||
cgThings.append(
|
||||
CGIfWrapper(CGList(xraySteps, "\n"),
|
||||
"xpc::WrapperFactory::IsXrayWrapper(obj)"))
|
||||
|
||||
cgThings.append(CGCallGenerator(
|
||||
self.getErrorReport() if self.isFallible() else None,
|
||||
self.getArguments(), argsPre, returnType,
|
||||
@ -4221,7 +4332,8 @@ class CGMethodCall(CGThing):
|
||||
A class to generate selection of a method signature from a set of
|
||||
signatures and generation of a call to that signature.
|
||||
"""
|
||||
def __init__(self, nativeMethodName, static, descriptor, method):
|
||||
def __init__(self, nativeMethodName, static, descriptor, method,
|
||||
isConstructor=False):
|
||||
CGThing.__init__(self)
|
||||
|
||||
methodName = '"%s.%s"' % (descriptor.interface.identifier.name, method.identifier.name)
|
||||
@ -4238,7 +4350,9 @@ class CGMethodCall(CGThing):
|
||||
def getPerSignatureCall(signature, argConversionStartsAt=0):
|
||||
return CGPerSignatureCall(signature[0], signature[1],
|
||||
nativeMethodName, static, descriptor,
|
||||
method, argConversionStartsAt)
|
||||
method,
|
||||
argConversionStartsAt=argConversionStartsAt,
|
||||
isConstructor=isConstructor)
|
||||
|
||||
|
||||
signatures = method.signatures()
|
||||
@ -7086,6 +7200,10 @@ class CGDictionary(CGThing):
|
||||
" NS_ENSURE_TRUE(cx, false);\n"
|
||||
" return Init(cx, json.ref());\n"
|
||||
" }\n" if not self.workers else "") +
|
||||
" ${selfName}& AsMutable() const\n"
|
||||
" {\n"
|
||||
" return *const_cast<${selfName}*>(this);\n"
|
||||
" }\n"
|
||||
"\n" +
|
||||
"\n".join(memberDecls) + "\n"
|
||||
"private:\n"
|
||||
|
@ -475,6 +475,7 @@ def getTypesFromDescriptor(descriptor):
|
||||
members = [m for m in descriptor.interface.members]
|
||||
if descriptor.interface.ctor():
|
||||
members.append(descriptor.interface.ctor())
|
||||
members.extend(descriptor.interface.namedConstructors)
|
||||
signatures = [s for m in members if m.isMethod() for s in m.signatures()]
|
||||
types = []
|
||||
for s in signatures:
|
||||
|
@ -64,6 +64,10 @@ public:
|
||||
return mIsNull;
|
||||
}
|
||||
|
||||
Nullable& AsMutable() const {
|
||||
return *const_cast<Nullable*>(this);
|
||||
}
|
||||
|
||||
// Make it possible to use a const Nullable of an array type with other
|
||||
// array types.
|
||||
template<typename U>
|
||||
|
@ -132,6 +132,18 @@ public:
|
||||
static
|
||||
already_AddRefed<TestInterface> Test(const GlobalObject&, const nsAString&,
|
||||
ErrorResult&);
|
||||
static
|
||||
already_AddRefed<TestInterface> Test2(const GlobalObject&,
|
||||
JSContext*,
|
||||
const DictForConstructor&,
|
||||
JS::Value,
|
||||
JSObject&,
|
||||
JSObject*,
|
||||
const Sequence<Dict>&,
|
||||
const Optional<JS::Value>&,
|
||||
const Optional<NonNull<JSObject> >&,
|
||||
const Optional<JSObject*>&,
|
||||
ErrorResult&);
|
||||
|
||||
// Integer types
|
||||
int8_t ReadonlyByte();
|
||||
|
@ -103,7 +103,10 @@ interface OnlyForUseInConstructor {
|
||||
Constructor(long arg1, IndirectlyImplementedInterface iface),
|
||||
// Constructor(long arg1, long arg2, (TestInterface or OnlyForUseInConstructor) arg3),
|
||||
NamedConstructor=Test,
|
||||
NamedConstructor=Test(DOMString str)
|
||||
NamedConstructor=Test(DOMString str),
|
||||
NamedConstructor=Test2(DictForConstructor dict, any any1, object obj1,
|
||||
object? obj2, sequence<Dict> seq, optional any any2,
|
||||
optional object obj3, optional object? obj4)
|
||||
]
|
||||
interface TestInterface {
|
||||
// Integer types
|
||||
@ -631,6 +634,7 @@ dictionary ParentDict : GrandparentDict {
|
||||
long c = 5;
|
||||
TestInterface someInterface;
|
||||
TestExternalInterface someExternalInterface;
|
||||
any parentAny;
|
||||
};
|
||||
|
||||
dictionary DictContainingDict {
|
||||
@ -642,6 +646,18 @@ dictionary DictContainingSequence {
|
||||
sequence<TestInterface> ourSequence2;
|
||||
};
|
||||
|
||||
dictionary DictForConstructor {
|
||||
Dict dict;
|
||||
DictContainingDict dict2;
|
||||
sequence<Dict> seq1;
|
||||
sequence<sequence<Dict>>? seq2;
|
||||
sequence<sequence<Dict>?> seq3;
|
||||
// No support for sequences of "any" or "object" as return values yet.
|
||||
object obj1;
|
||||
object? obj2;
|
||||
any any1 = null;
|
||||
};
|
||||
|
||||
interface TestIndexedGetterInterface {
|
||||
getter long item(unsigned long idx);
|
||||
readonly attribute unsigned long length;
|
||||
|
@ -62,6 +62,7 @@ MOCHITEST_CHROME_FILES = \
|
||||
test_queryCaretRect.html \
|
||||
queryCaretRectWin.html \
|
||||
queryCaretRectUnix.html \
|
||||
test_xray_event_constructor.xul \
|
||||
$(NULL)
|
||||
|
||||
ifeq (WINNT,$(OS_ARCH))
|
||||
|
@ -233,6 +233,14 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=741267
|
||||
ok(false, "Should be able to return NodeFilter from a sandbox " + e);
|
||||
}
|
||||
|
||||
try {
|
||||
var eventCtor = Components.utils.evalInSandbox("Event", sandbox);
|
||||
var e = new eventCtor("test", { bubbles: true });
|
||||
is(e.bubbles, true, "Dictionary argument should work");
|
||||
} catch (e) {
|
||||
ok(false, "Should be able to construct my event " + e);
|
||||
}
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
|
35
dom/tests/mochitest/chrome/test_xray_event_constructor.xul
Normal file
35
dom/tests/mochitest/chrome/test_xray_event_constructor.xul
Normal file
@ -0,0 +1,35 @@
|
||||
<?xml version="1.0"?>
|
||||
<?xml-stylesheet type="text/css" href="chrome://global/skin"?>
|
||||
<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=861493
|
||||
-->
|
||||
<window title="Mozilla Bug 861493"
|
||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
|
||||
|
||||
<iframe id="t" type="content"></iframe>
|
||||
|
||||
<!-- test results are displayed in the html:body -->
|
||||
<body xmlns="http://www.w3.org/1999/xhtml">
|
||||
<a href="https://bugzilla.mozilla.org/show_bug.cgi?id=861493"
|
||||
target="_blank">Mozilla Bug 861493</a>
|
||||
</body>
|
||||
|
||||
<!-- test code goes here -->
|
||||
<script type="application/javascript">
|
||||
<![CDATA[
|
||||
/** Test for Bug 861493 **/
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
addLoadEvent(function() {
|
||||
ok(Components.utils.isXrayWrapper($("t").contentWindow),
|
||||
"Should have xray");
|
||||
var e = new $("t").contentWindow.Event("test", { bubbles: true });
|
||||
is(e.bubbles, true, "Dictionary should have worked");
|
||||
SimpleTest.finish();
|
||||
})
|
||||
|
||||
]]>
|
||||
</script>
|
||||
</window>
|
@ -1057,3 +1057,9 @@ js_DefineOwnProperty(JSContext *cx, JSObject *objArg, jsid idArg,
|
||||
|
||||
return js_DefineOwnProperty(cx, HandleObject(obj), id, descriptor, bp);
|
||||
}
|
||||
|
||||
JS_FRIEND_API(JSBool)
|
||||
js_ReportIsNotFunction(JSContext *cx, const JS::Value& v)
|
||||
{
|
||||
return ReportIsNotFunction(cx, v);
|
||||
}
|
||||
|
@ -1454,4 +1454,7 @@ extern JS_FRIEND_API(JSBool)
|
||||
js_DefineOwnProperty(JSContext *cx, JSObject *objArg, jsid idArg,
|
||||
const js::PropertyDescriptor& descriptor, JSBool *bp);
|
||||
|
||||
extern JS_FRIEND_API(JSBool)
|
||||
js_ReportIsNotFunction(JSContext *cx, const JS::Value& v);
|
||||
|
||||
#endif /* jsfriendapi_h___ */
|
||||
|
@ -146,11 +146,13 @@ public:
|
||||
HandleObject wrapper, HandleObject holder,
|
||||
HandleId id, JSPropertyDescriptor *desc, unsigned flags);
|
||||
|
||||
static bool call(JSContext *cx, HandleObject wrapper, const JS::CallArgs &args)
|
||||
static bool call(JSContext *cx, HandleObject wrapper,
|
||||
const JS::CallArgs &args, js::Wrapper& baseInstance)
|
||||
{
|
||||
MOZ_NOT_REACHED("Call trap currently implemented only for XPCWNs");
|
||||
}
|
||||
static bool construct(JSContext *cx, HandleObject wrapper, const JS::CallArgs &args)
|
||||
static bool construct(JSContext *cx, HandleObject wrapper,
|
||||
const JS::CallArgs &args, js::Wrapper& baseInstance)
|
||||
{
|
||||
MOZ_NOT_REACHED("Call trap currently implemented only for XPCWNs");
|
||||
}
|
||||
@ -198,8 +200,10 @@ public:
|
||||
Handle<PropertyDescriptor> existingDesc, bool *defined);
|
||||
static bool enumerateNames(JSContext *cx, HandleObject wrapper, unsigned flags,
|
||||
AutoIdVector &props);
|
||||
static bool call(JSContext *cx, HandleObject wrapper, const JS::CallArgs &args);
|
||||
static bool construct(JSContext *cx, HandleObject wrapper, const JS::CallArgs &args);
|
||||
static bool call(JSContext *cx, HandleObject wrapper,
|
||||
const JS::CallArgs &args, js::Wrapper& baseInstance);
|
||||
static bool construct(JSContext *cx, HandleObject wrapper,
|
||||
const JS::CallArgs &args, js::Wrapper& baseInstance);
|
||||
|
||||
static bool isResolving(JSContext *cx, JSObject *holder, jsid id);
|
||||
|
||||
@ -242,8 +246,10 @@ public:
|
||||
Handle<PropertyDescriptor> existingDesc, bool *defined);
|
||||
static bool enumerateNames(JSContext *cx, HandleObject wrapper, unsigned flags,
|
||||
AutoIdVector &props);
|
||||
static bool call(JSContext *cx, HandleObject wrapper, const JS::CallArgs &args);
|
||||
static bool construct(JSContext *cx, HandleObject wrapper, const JS::CallArgs &args);
|
||||
static bool call(JSContext *cx, HandleObject wrapper,
|
||||
const JS::CallArgs &args, js::Wrapper& baseInstance);
|
||||
static bool construct(JSContext *cx, HandleObject wrapper,
|
||||
const JS::CallArgs &args, js::Wrapper& baseInstance);
|
||||
|
||||
static bool isResolving(JSContext *cx, JSObject *holder, jsid id)
|
||||
{
|
||||
@ -1128,7 +1134,8 @@ XPCWrappedNativeXrayTraits::createHolder(JSContext *cx, JSObject *wrapper)
|
||||
|
||||
bool
|
||||
XPCWrappedNativeXrayTraits::call(JSContext *cx, HandleObject wrapper,
|
||||
const JS::CallArgs &args)
|
||||
const JS::CallArgs &args,
|
||||
js::Wrapper& baseInstance)
|
||||
{
|
||||
// Run the resolve hook of the wrapped native.
|
||||
XPCWrappedNative *wn = getWN(wrapper);
|
||||
@ -1153,7 +1160,8 @@ XPCWrappedNativeXrayTraits::call(JSContext *cx, HandleObject wrapper,
|
||||
|
||||
bool
|
||||
XPCWrappedNativeXrayTraits::construct(JSContext *cx, HandleObject wrapper,
|
||||
const JS::CallArgs &args)
|
||||
const JS::CallArgs &args,
|
||||
js::Wrapper& baseInstance)
|
||||
{
|
||||
// Run the resolve hook of the wrapped native.
|
||||
XPCWrappedNative *wn = getWN(wrapper);
|
||||
@ -1237,42 +1245,55 @@ DOMXrayTraits::enumerateNames(JSContext *cx, HandleObject wrapper, unsigned flag
|
||||
}
|
||||
|
||||
bool
|
||||
DOMXrayTraits::call(JSContext *cx, HandleObject wrapper, const JS::CallArgs &args)
|
||||
DOMXrayTraits::call(JSContext *cx, HandleObject wrapper,
|
||||
const JS::CallArgs &args, js::Wrapper& baseInstance)
|
||||
{
|
||||
RootedObject obj(cx, getTargetObject(wrapper));
|
||||
{
|
||||
JSAutoCompartment ac(cx, obj);
|
||||
RootedValue thisv(cx, args.thisv());
|
||||
if (!JS_WrapValue(cx, thisv.address()))
|
||||
js::Class* clasp = js::GetObjectClass(obj);
|
||||
// What we have is either a WebIDL interface object, a WebIDL prototype
|
||||
// object, or a WebIDL instance object. WebIDL prototype objects never have
|
||||
// a clasp->call. WebIDL interface objects we want to invoke on the xray
|
||||
// compartment. WebIDL instance objects either don't have a clasp->call or
|
||||
// are using "legacycaller", which basically means plug-ins. We want to
|
||||
// call those on the content compartment.
|
||||
if (clasp->flags & JSCLASS_IS_DOMIFACEANDPROTOJSCLASS) {
|
||||
if (!clasp->call) {
|
||||
js_ReportIsNotFunction(cx, JS::ObjectValue(*wrapper));
|
||||
return false;
|
||||
args.setThis(thisv);
|
||||
for (size_t i = 0; i < args.length(); ++i) {
|
||||
if (!JS_WrapValue(cx, &args[i]))
|
||||
return false;
|
||||
}
|
||||
if (!Call(cx, thisv, obj, args.length(), args.array(), args.rval().address()))
|
||||
// call it on the Xray compartment
|
||||
if (!clasp->call(cx, args.length(), args.base()))
|
||||
return false;
|
||||
} else {
|
||||
// This is only reached for WebIDL instance objects, and in practice
|
||||
// only for plugins. Just call them on the content compartment.
|
||||
if (!baseInstance.call(cx, wrapper, args))
|
||||
return false;
|
||||
}
|
||||
return JS_WrapValue(cx, args.rval().address());
|
||||
}
|
||||
|
||||
bool
|
||||
DOMXrayTraits::construct(JSContext *cx, HandleObject wrapper, const JS::CallArgs &args)
|
||||
DOMXrayTraits::construct(JSContext *cx, HandleObject wrapper,
|
||||
const JS::CallArgs &args, js::Wrapper& baseInstance)
|
||||
{
|
||||
RootedObject obj(cx, getTargetObject(wrapper));
|
||||
MOZ_ASSERT(mozilla::dom::HasConstructor(obj));
|
||||
RootedObject newObj(cx);
|
||||
{
|
||||
JSAutoCompartment ac(cx, obj);
|
||||
for (size_t i = 0; i < args.length(); ++i) {
|
||||
if (!JS_WrapValue(cx, &args[i]))
|
||||
return false;
|
||||
js::Class* clasp = js::GetObjectClass(obj);
|
||||
// See comments in DOMXrayTraits::call() explaining what's going on here.
|
||||
if (clasp->flags & JSCLASS_IS_DOMIFACEANDPROTOJSCLASS) {
|
||||
if (!clasp->construct) {
|
||||
js_ReportIsNotFunction(cx, JS::ObjectValue(*wrapper));
|
||||
return false;
|
||||
}
|
||||
newObj = JS_New(cx, obj, args.length(), args.array());
|
||||
if (!clasp->construct(cx, args.length(), args.base()))
|
||||
return false;
|
||||
} else {
|
||||
if (!baseInstance.construct(cx, wrapper, args))
|
||||
return false;
|
||||
}
|
||||
if (!newObj || !JS_WrapObject(cx, newObj.address()))
|
||||
if (!args.rval().isObject() || !JS_WrapValue(cx, args.rval().address()))
|
||||
return false;
|
||||
args.rval().setObject(*newObj);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1854,7 +1875,7 @@ bool
|
||||
XrayWrapper<Base, Traits>::call(JSContext *cx, HandleObject wrapper, const JS::CallArgs &args)
|
||||
{
|
||||
assertEnteredPolicy(cx, wrapper, JSID_VOID);
|
||||
return Traits::call(cx, wrapper, args);
|
||||
return Traits::call(cx, wrapper, args, Base::singleton);
|
||||
}
|
||||
|
||||
template <typename Base, typename Traits>
|
||||
@ -1862,7 +1883,7 @@ bool
|
||||
XrayWrapper<Base, Traits>::construct(JSContext *cx, HandleObject wrapper, const JS::CallArgs &args)
|
||||
{
|
||||
assertEnteredPolicy(cx, wrapper, JSID_VOID);
|
||||
return Traits::construct(cx, wrapper, args);
|
||||
return Traits::construct(cx, wrapper, args, Base::singleton);
|
||||
}
|
||||
|
||||
/*
|
||||
|
Loading…
Reference in New Issue
Block a user