Bug 946898. Make sure to not accidentally store COWs in the slot for [Cached] properties. r=peterv

This commit is contained in:
Boris Zbarsky 2013-12-05 16:07:33 -05:00
parent 0134bf3556
commit 919ba9e509
5 changed files with 32 additions and 21 deletions

View File

@ -4174,8 +4174,9 @@ def getMaybeWrapValueFuncForType(type):
if type.nullable():
return "MaybeWrapObjectOrNullValue"
return "MaybeWrapObjectValue"
# Spidermonkey interfaces are never DOM objects
if type.isSpiderMonkeyInterface():
# Spidermonkey interfaces are never DOM objects. Neither are sequences or
# dictionaries, since those are always plain JS objects.
if type.isSpiderMonkeyInterface() or type.isDictionary() or type.isSequence():
if type.nullable():
return "MaybeWrapNonDOMObjectOrNullValue"
return "MaybeWrapNonDOMObjectValue"
@ -5118,7 +5119,8 @@ if (!${obj}) {
(self.returnType.isGeckoInterface() and
self.descriptor.getDescriptor(self.returnType.unroll().inner.identifier.name).nativeOwnership == 'owned'))
if self.idlNode.isAttr() and self.idlNode.slotIndex is not None:
setSlot = self.idlNode.isAttr() and self.idlNode.slotIndex is not None
if setSlot:
# For the case of Cached attributes, go ahead and preserve our
# wrapper if needed. We need to do this because otherwise the
# wrapper could get garbage-collected and the cached value would
@ -5129,26 +5131,14 @@ if (!${obj}) {
# already-preserved wrapper.
if (self.idlNode.getExtendedAttribute("Cached") and
self.descriptor.wrapperCache):
preserveWrapper = " PreserveWrapper(self);\n"
preserveWrapper = "PreserveWrapper(self);\n"
else:
preserveWrapper = ""
successCode = (
"// Be careful here: Have to wrap the value into the\n"
"// compartment of reflector before storing, since we might\n"
"// be coming in via Xrays and the value is already in the\n"
"// caller compartment.\n"
"{ // Scope for tempVal\n"
" JS::Rooted<JS::Value> tempVal(cx, args.rval());\n"
" JSAutoCompartment ac(cx, reflector);\n"
" if (!%s(cx, &tempVal)) {\n"
" return false;\n"
" }\n"
" js::SetReservedSlot(reflector, %s, tempVal);\n"
"js::SetReservedSlot(reflector, %s, args.rval());\n"
"%s"
"}\n"
"return true;" %
(getMaybeWrapValueFuncForType(self.idlNode.type),
memberReservedSlot(self.idlNode), preserveWrapper))
"break;" %
(memberReservedSlot(self.idlNode), preserveWrapper))
else:
successCode = None
@ -5158,14 +5148,28 @@ if (!${obj}) {
'successCode': successCode,
}
try:
return wrapForType(self.returnType, self.descriptor,
resultTemplateValues)
wrapCode = CGGeneric(wrapForType(self.returnType, self.descriptor,
resultTemplateValues))
except MethodNotNewObjectError, err:
assert not returnsNewObject
raise TypeError("%s being returned from non-NewObject method or property %s.%s" %
(err.typename,
self.descriptor.interface.identifier.name,
self.idlNode.identifier.name))
if setSlot:
# We need to make sure that our initial wrapping is done
# in the reflector compartment, but that we finally set
# args.rval() in the caller compartment.
wrapCode = CGWrapper(
CGIndenter(wrapCode),
pre=("do { // block we break out of when done wrapping\n"
" // Make sure we wrap and store in the slot in reflector's compartment\n"
" JSAutoCompartment ac(cx, reflector);\n"),
post=("\n} while (0);\n"
"// And now make sure args.rval() is in the caller compartment\n"
"return %s(cx, args.rval());" %
getMaybeWrapValueFuncForType(self.idlNode.type)))
return wrapCode.define()
def getErrorReport(self):
jsImplemented = ""

View File

@ -342,6 +342,7 @@ public:
// Sequence types
void GetReadonlySequence(nsTArray<int32_t>&);
void GetReadonlySequenceOfDictionaries(JSContext*, nsTArray<Dict>&);
void GetReadonlyNullableSequenceOfDictionaries(JSContext*, Nullable<nsTArray<Dict> >&);
void ReceiveSequence(nsTArray<int32_t>&);
void ReceiveNullableSequence(Nullable< nsTArray<int32_t> >&);
void ReceiveSequenceOfNullableInts(nsTArray< Nullable<int32_t> >&);

View File

@ -299,6 +299,8 @@ interface TestInterface {
readonly attribute sequence<long> readonlySequence;
[Cached, Pure]
readonly attribute sequence<Dict> readonlySequenceOfDictionaries;
[Cached, Pure]
readonly attribute sequence<Dict>? readonlyNullableSequenceOfDictionaries;
sequence<long> receiveSequence();
sequence<long>? receiveNullableSequence();
sequence<long?> receiveSequenceOfNullableInts();

View File

@ -195,6 +195,8 @@ interface TestExampleInterface {
readonly attribute sequence<long> readonlySequence;
[Cached, Pure]
readonly attribute sequence<Dict> readonlySequenceOfDictionaries;
[Cached, Pure]
readonly attribute sequence<Dict>? readonlyNullableSequenceOfDictionaries;
sequence<long> receiveSequence();
sequence<long>? receiveNullableSequence();
sequence<long?> receiveSequenceOfNullableInts();

View File

@ -216,6 +216,8 @@ interface TestJSImplInterface {
readonly attribute sequence<long> readonlySequence;
[Cached, Pure]
readonly attribute sequence<Dict> readonlySequenceOfDictionaries;
[Cached, Pure]
readonly attribute sequence<Dict>? readonlyNullableSequenceOfDictionaries;
sequence<long> receiveSequence();
sequence<long>? receiveNullableSequence();
sequence<long?> receiveSequenceOfNullableInts();