From 25bd4e0e4030b3f1c0158c639c277ab656ce7082 Mon Sep 17 00:00:00 2001 From: Daniel Holbert Date: Tue, 4 Mar 2014 11:08:54 -0800 Subject: [PATCH 001/112] Bug 973701: Check NS_FRAME_OUT_OF_FLOW state bit instead of IsAbsolutelyPositioned(), when excluding out-of-flow frames from being considered as flex items. r=mats --- layout/generic/crashtests/973701-1.xhtml | 5 +++++ layout/generic/crashtests/973701-2.xhtml | 6 ++++++ layout/generic/crashtests/crashtests.list | 2 ++ layout/generic/nsFlexContainerFrame.cpp | 12 ++++++++---- layout/generic/nsIFrameInlines.h | 2 +- 5 files changed, 22 insertions(+), 5 deletions(-) create mode 100644 layout/generic/crashtests/973701-1.xhtml create mode 100644 layout/generic/crashtests/973701-2.xhtml diff --git a/layout/generic/crashtests/973701-1.xhtml b/layout/generic/crashtests/973701-1.xhtml new file mode 100644 index 00000000000..e12a7a8bdd2 --- /dev/null +++ b/layout/generic/crashtests/973701-1.xhtml @@ -0,0 +1,5 @@ + + + + + diff --git a/layout/generic/crashtests/973701-2.xhtml b/layout/generic/crashtests/973701-2.xhtml new file mode 100644 index 00000000000..9fcddd11ddb --- /dev/null +++ b/layout/generic/crashtests/973701-2.xhtml @@ -0,0 +1,6 @@ + + + + + + diff --git a/layout/generic/crashtests/crashtests.list b/layout/generic/crashtests/crashtests.list index fb913e751f7..7c6d76b207a 100644 --- a/layout/generic/crashtests/crashtests.list +++ b/layout/generic/crashtests/crashtests.list @@ -525,4 +525,6 @@ test-pref(layout.css.sticky.enabled,true) load 915475.xhtml load 943509-1.html asserts(4-8) load 944909-1.html test-pref(layout.css.sticky.enabled,true) load 949932.html +load 973701-1.xhtml +load 973701-2.xhtml load outline-on-frameset.xhtml diff --git a/layout/generic/nsFlexContainerFrame.cpp b/layout/generic/nsFlexContainerFrame.cpp index 65ba261742e..9e0cf653f39 100644 --- a/layout/generic/nsFlexContainerFrame.cpp +++ b/layout/generic/nsFlexContainerFrame.cpp @@ -1053,8 +1053,10 @@ FlexItem::FlexItem(nsIFrame* aChildFrame, mAlignSelf(aChildFrame->StylePosition()->mAlignSelf) { MOZ_ASSERT(mFrame, "expecting a non-null child frame"); - MOZ_ASSERT(!mFrame->IsAbsolutelyPositioned(), - "abspos child frames should not be treated as flex items"); + MOZ_ASSERT(mFrame->GetType() != nsGkAtoms::placeholderFrame, + "placeholder frames should not be treated as flex items"); + MOZ_ASSERT(!(mFrame->GetStateBits() & NS_FRAME_OUT_OF_FLOW), + "out-of-flow frames should not be treated as flex items"); SetFlexBaseSizeAndMainSize(aFlexBaseSize); @@ -1126,8 +1128,10 @@ FlexItem::FlexItem(nsIFrame* aChildFrame, nscoord aCrossSize) MOZ_ASSERT(NS_STYLE_VISIBILITY_COLLAPSE == mFrame->StyleVisibility()->mVisible, "Should only make struts for children with 'visibility:collapse'"); - MOZ_ASSERT(!mFrame->IsAbsolutelyPositioned(), - "abspos child frames should not be treated as flex items"); + MOZ_ASSERT(mFrame->GetType() != nsGkAtoms::placeholderFrame, + "placeholder frames should not be treated as flex items"); + MOZ_ASSERT(!(mFrame->GetStateBits() & NS_FRAME_OUT_OF_FLOW), + "out-of-flow frames should not be treated as flex items"); } nscoord diff --git a/layout/generic/nsIFrameInlines.h b/layout/generic/nsIFrameInlines.h index 9c97ffe3d39..0ac124cebfd 100644 --- a/layout/generic/nsIFrameInlines.h +++ b/layout/generic/nsIFrameInlines.h @@ -15,7 +15,7 @@ nsIFrame::IsFlexItem() const { return mParent && mParent->GetType() == nsGkAtoms::flexContainerFrame && - !IsAbsolutelyPositioned(); + !(GetStateBits() & NS_FRAME_OUT_OF_FLOW); } bool From caad7bd99e251e1e8567d8d94f9d9806a6dea628 Mon Sep 17 00:00:00 2001 From: Luke Wagner Date: Tue, 4 Mar 2014 13:24:13 -0600 Subject: [PATCH 002/112] Bug 979043 - Simplify forEachCanonicalActualArg (r=jandem) --- js/src/jit/IonFrameIterator.h | 4 ++-- js/src/jit/IonFrames.cpp | 2 +- js/src/jsfun.cpp | 8 ++++---- js/src/vm/ArgumentsObject.cpp | 7 +------ js/src/vm/Stack-inl.h | 30 ++++++++++++++++++++---------- js/src/vm/Stack.h | 12 +++--------- 6 files changed, 31 insertions(+), 32 deletions(-) diff --git a/js/src/jit/IonFrameIterator.h b/js/src/jit/IonFrameIterator.h index 653a70c1f58..d2cd699a7b7 100644 --- a/js/src/jit/IonFrameIterator.h +++ b/js/src/jit/IonFrameIterator.h @@ -217,7 +217,7 @@ class IonFrameIterator MachineState machineState() const; template - void forEachCanonicalActualArg(Op op, ReadFrameArgsBehavior behavior) const { + void unaliasedForEachActual(Op op, ReadFrameArgsBehavior behavior) const { JS_ASSERT(isBaselineJS()); unsigned nactual = numActualArgs(); @@ -476,7 +476,7 @@ class InlineFrameIteratorMaybeGC } template - void forEachCanonicalActualArg(JSContext *cx, Op op, ReadFrameArgsBehavior behavior) const { + void unaliasedForEachActual(JSContext *cx, Op op, ReadFrameArgsBehavior behavior) const { Nop nop; readFrameArgsAndLocals(cx, op, nop, nullptr, nullptr, behavior); } diff --git a/js/src/jit/IonFrames.cpp b/js/src/jit/IonFrames.cpp index 1fce1635c04..f0d14948eb9 100644 --- a/js/src/jit/IonFrames.cpp +++ b/js/src/jit/IonFrames.cpp @@ -1829,7 +1829,7 @@ InlineFrameIteratorMaybeGC::dump() const else { if (i - 2 == callee()->nargs() && numActualArgs() > callee()->nargs()) { DumpOp d(callee()->nargs()); - forEachCanonicalActualArg(GetJSContextFromJitCode(), d, ReadFrame_Overflown); + unaliasedForEachActual(GetJSContextFromJitCode(), d, ReadFrame_Overflown); } fprintf(stderr, " slot %d: ", int(i - 2 - callee()->nargs())); diff --git a/js/src/jsfun.cpp b/js/src/jsfun.cpp index bd3dd3f1e32..a3cb262583a 100644 --- a/js/src/jsfun.cpp +++ b/js/src/jsfun.cpp @@ -966,7 +966,7 @@ PushBaselineFunApplyArguments(JSContext *cx, jit::IonFrameIterator &frame, Invok args.setThis(vp[2]); /* Steps 7-8. */ - frame.forEachCanonicalActualArg(CopyTo(args.array()), jit::ReadFrame_Actuals); + frame.unaliasedForEachActual(CopyTo(args.array()), jit::ReadFrame_Actuals); return true; } #endif @@ -1024,8 +1024,8 @@ js_fun_apply(JSContext *cx, unsigned argc, Value *vp) args.setThis(vp[2]); /* Steps 7-8. */ - iter.forEachCanonicalActualArg(cx, CopyTo(args.array()), - jit::ReadFrame_Actuals); + iter.unaliasedForEachActual(cx, CopyTo(args.array()), + jit::ReadFrame_Actuals); } else { JS_ASSERT(frame.isBaselineStub()); @@ -1062,7 +1062,7 @@ js_fun_apply(JSContext *cx, unsigned argc, Value *vp) args.setThis(vp[2]); /* Steps 7-8. */ - fp->forEachUnaliasedActual(CopyTo(args.array())); + fp->unaliasedForEachActual(CopyTo(args.array())); } } else { /* Step 3. */ diff --git a/js/src/vm/ArgumentsObject.cpp b/js/src/vm/ArgumentsObject.cpp index 1d47c8f8d59..02191e3720f 100644 --- a/js/src/vm/ArgumentsObject.cpp +++ b/js/src/vm/ArgumentsObject.cpp @@ -134,13 +134,8 @@ struct CopyScriptFrameIterArgs { } void copyArgs(JSContext *cx, HeapValue *dstBase, unsigned totalArgs) const { - if (!iter_.isJit()) { - CopyStackFrameArguments(iter_.abstractFramePtr(), dstBase, totalArgs); - return; - } - /* Copy actual arguments. */ - iter_.ionForEachCanonicalActualArg(cx, CopyToHeap(dstBase)); + iter_.unaliasedForEachActual(cx, CopyToHeap(dstBase)); /* Define formals which are not part of the actuals. */ unsigned numActuals = iter_.numActualArgs(); diff --git a/js/src/vm/Stack-inl.h b/js/src/vm/Stack-inl.h index cac4a8362b9..1c82eef05fe 100644 --- a/js/src/vm/Stack-inl.h +++ b/js/src/vm/Stack-inl.h @@ -134,10 +134,9 @@ StackFrame::unaliasedActual(unsigned i, MaybeCheckAliasing checkAliasing) template inline void -StackFrame::forEachUnaliasedActual(Op op) +StackFrame::unaliasedForEachActual(Op op) { JS_ASSERT(!script()->funHasAnyAliasedFormal()); - JS_ASSERT(!script()->needsArgsObj()); const Value *argsEnd = argv() + numActualArgs(); for (const Value *p = argv(); p < argsEnd; ++p) @@ -325,17 +324,28 @@ InterpreterStack::popInlineFrame(FrameRegs ®s) template inline void -ScriptFrameIter::ionForEachCanonicalActualArg(JSContext *cx, Op op) +ScriptFrameIter::unaliasedForEachActual(JSContext *cx, Op op) { - JS_ASSERT(isJit()); + switch (data_.state_) { + case DONE: + break; + case SCRIPTED: + interpFrame()->unaliasedForEachActual(op); + return; + case JIT: #ifdef JS_ION - if (data_.ionFrames_.isOptimizedJS()) { - ionInlineFrames_.forEachCanonicalActualArg(cx, op, jit::ReadFrame_Actuals); - } else { - JS_ASSERT(data_.ionFrames_.isBaselineJS()); - data_.ionFrames_.forEachCanonicalActualArg(op, jit::ReadFrame_Actuals); - } + if (data_.ionFrames_.isOptimizedJS()) { + ionInlineFrames_.unaliasedForEachActual(cx, op, jit::ReadFrame_Actuals); + } else { + JS_ASSERT(data_.ionFrames_.isBaselineJS()); + data_.ionFrames_.unaliasedForEachActual(op, jit::ReadFrame_Actuals); + } + return; +#else + break; #endif + } + MOZ_ASSUME_UNREACHABLE("Unexpected state"); } inline void * diff --git a/js/src/vm/Stack.h b/js/src/vm/Stack.h index 791c6aebb41..12d44caff92 100644 --- a/js/src/vm/Stack.h +++ b/js/src/vm/Stack.h @@ -215,6 +215,7 @@ class AbstractFramePtr inline Value &unaliasedLocal(uint32_t i, MaybeCheckAliasing checkAliasing = CHECK_ALIASING); inline Value &unaliasedFormal(unsigned i, MaybeCheckAliasing checkAliasing = CHECK_ALIASING); inline Value &unaliasedActual(unsigned i, MaybeCheckAliasing checkAliasing = CHECK_ALIASING); + template inline void unaliasedForEachActual(JSContext *cx, Op op); inline bool prevUpToDate() const; inline void setPrevUpToDate() const; @@ -530,18 +531,13 @@ class StackFrame bool hasArgs() const { return isNonEvalFunctionFrame(); } inline Value &unaliasedFormal(unsigned i, MaybeCheckAliasing = CHECK_ALIASING); inline Value &unaliasedActual(unsigned i, MaybeCheckAliasing = CHECK_ALIASING); - template inline void forEachUnaliasedActual(Op op); + template inline void unaliasedForEachActual(Op op); bool copyRawFrameSlots(AutoValueVector *v); unsigned numFormalArgs() const { JS_ASSERT(hasArgs()); return fun()->nargs(); } unsigned numActualArgs() const { JS_ASSERT(hasArgs()); return u.nactual; } - inline Value &canonicalActualArg(unsigned i) const; - template - inline bool forEachCanonicalActualArg(Op op, unsigned start = 0, unsigned count = unsigned(-1)); - template inline bool forEachFormalArg(Op op); - /* * Arguments object * @@ -1566,6 +1562,7 @@ class ScriptFrameIter unsigned numActualArgs() const; unsigned numFormalArgs() const { return script()->functionNonDelazifying()->nargs(); } Value unaliasedActual(unsigned i, MaybeCheckAliasing = CHECK_ALIASING) const; + template inline void unaliasedForEachActual(JSContext *cx, Op op); JSObject *scopeChain() const; CallObject &callObj() const; @@ -1587,9 +1584,6 @@ class ScriptFrameIter // These are only valid for the top frame. size_t numFrameSlots() const; Value frameSlotValue(size_t index) const; - - template - inline void ionForEachCanonicalActualArg(JSContext *cx, Op op); }; #ifdef DEBUG From 7a2f4ec89ff9aee683f7dc3058779e927271effe Mon Sep 17 00:00:00 2001 From: Luke Wagner Date: Tue, 4 Mar 2014 13:24:15 -0600 Subject: [PATCH 003/112] Bug 979043 - Simplify fun_apply (r=nbp) --- js/src/jsfun.cpp | 190 ++++++++++++------------------------------ js/src/vm/Stack-inl.h | 4 +- 2 files changed, 54 insertions(+), 140 deletions(-) diff --git a/js/src/jsfun.cpp b/js/src/jsfun.cpp index a3cb262583a..c701e8992aa 100644 --- a/js/src/jsfun.cpp +++ b/js/src/jsfun.cpp @@ -919,197 +919,109 @@ fun_toSource(JSContext *cx, unsigned argc, Value *vp) bool js_fun_call(JSContext *cx, unsigned argc, Value *vp) { - RootedValue fval(cx, vp[1]); + CallArgs args = CallArgsFromVp(argc, vp); + HandleValue fval = args.thisv(); if (!js_IsCallable(fval)) { - ReportIncompatibleMethod(cx, CallReceiverFromVp(vp), &JSFunction::class_); + ReportIncompatibleMethod(cx, args, &JSFunction::class_); return false; } - Value *argv = vp + 2; - RootedValue thisv(cx, UndefinedValue()); - if (argc != 0) { - thisv = argv[0]; - - argc--; - argv++; - } - - /* Allocate stack space for fval, obj, and the args. */ - InvokeArgs args(cx); - if (!args.init(argc)) + InvokeArgs args2(cx); + if (!args2.init(args.length() ? args.length() - 1 : 0)) return false; - /* Push fval, thisv, and the args. */ - args.setCallee(fval); - args.setThis(thisv); - PodCopy(args.array(), argv, argc); + args2.setCallee(fval); + args2.setThis(args.get(0)); + PodCopy(args2.array(), args.array() + 1, args2.length()); - bool ok = Invoke(cx, args); - *vp = args.rval(); - return ok; -} - -#ifdef JS_ION -static bool -PushBaselineFunApplyArguments(JSContext *cx, jit::IonFrameIterator &frame, InvokeArgs &args, - Value *vp) -{ - unsigned length = frame.numActualArgs(); - JS_ASSERT(length <= ARGS_LENGTH_MAX); - - if (!args.init(length)) + if (!Invoke(cx, args2)) return false; - /* Push fval, obj, and aobj's elements as args. */ - args.setCallee(vp[1]); - args.setThis(vp[2]); - - /* Steps 7-8. */ - frame.unaliasedForEachActual(CopyTo(args.array()), jit::ReadFrame_Actuals); + args.rval().set(args2.rval()); return true; } -#endif -/* ES5 15.3.4.3 */ +// ES5 15.3.4.3 bool js_fun_apply(JSContext *cx, unsigned argc, Value *vp) { - /* Step 1. */ - RootedValue fval(cx, vp[1]); + CallArgs args = CallArgsFromVp(argc, vp); + + // Step 1. + HandleValue fval = args.thisv(); if (!js_IsCallable(fval)) { - ReportIncompatibleMethod(cx, CallReceiverFromVp(vp), &JSFunction::class_); + ReportIncompatibleMethod(cx, args, &JSFunction::class_); return false; } - /* Step 2. */ - if (argc < 2 || vp[3].isNullOrUndefined()) + // Step 2. + if (args.length() < 2 || args[1].isNullOrUndefined()) return js_fun_call(cx, (argc > 0) ? 1 : 0, vp); - InvokeArgs args(cx); + InvokeArgs args2(cx); - /* - * GuardFunApplyArgumentsOptimization already called IsOptimizedArguments, - * so we don't need to here. This is not an optimization: we can't rely on - * cx->fp (since natives can be called directly from JSAPI). - */ - if (vp[3].isMagic(JS_OPTIMIZED_ARGUMENTS)) { - /* - * Pretend we have been passed the 'arguments' object for the current - * function and read actuals out of the frame. - */ - /* Steps 4-6. */ + // A JS_OPTIMIZED_ARGUMENTS magic value means that 'arguments' flows into + // this apply call from a scripted caller and, as an optimization, we've + // avoided creating it since apply can simply pull the argument values from + // the calling frame (which we must do now). + if (args[1].isMagic(JS_OPTIMIZED_ARGUMENTS)) { + // Step 3-6. + ScriptFrameIter iter(cx); + JS_ASSERT(iter.numActualArgs() <= ARGS_LENGTH_MAX); + if (!args2.init(iter.numActualArgs())) + return false; -#ifdef JS_ION - // We do not want to use ScriptFrameIter to abstract here because this - // is supposed to be a fast path as opposed to ScriptFrameIter which is - // doing complex logic to settle on the next frame twice. - if (cx->currentlyRunningInJit()) { - jit::JitActivationIterator activations(cx->runtime()); - jit::IonFrameIterator frame(activations); - if (frame.isNative()) { - // Stop on the next Ion JS Frame. - ++frame; - if (frame.isOptimizedJS()) { - jit::InlineFrameIterator iter(cx, &frame); + args2.setCallee(fval); + args2.setThis(args[0]); - unsigned length = iter.numActualArgs(); - JS_ASSERT(length <= ARGS_LENGTH_MAX); - - if (!args.init(length)) - return false; - - /* Push fval, obj, and aobj's elements as args. */ - args.setCallee(fval); - args.setThis(vp[2]); - - /* Steps 7-8. */ - iter.unaliasedForEachActual(cx, CopyTo(args.array()), - jit::ReadFrame_Actuals); - } else { - JS_ASSERT(frame.isBaselineStub()); - - ++frame; - JS_ASSERT(frame.isBaselineJS()); - - if (!PushBaselineFunApplyArguments(cx, frame, args, vp)) - return false; - } - } else { - JS_ASSERT(frame.type() == jit::IonFrame_Exit); - - ++frame; - JS_ASSERT(frame.isBaselineStub()); - - ++frame; - JS_ASSERT(frame.isBaselineJS()); - - if (!PushBaselineFunApplyArguments(cx, frame, args, vp)) - return false; - } - } else -#endif - { - StackFrame *fp = cx->interpreterFrame(); - unsigned length = fp->numActualArgs(); - JS_ASSERT(length <= ARGS_LENGTH_MAX); - - if (!args.init(length)) - return false; - - /* Push fval, obj, and aobj's elements as args. */ - args.setCallee(fval); - args.setThis(vp[2]); - - /* Steps 7-8. */ - fp->unaliasedForEachActual(CopyTo(args.array())); - } + // Steps 7-8. + iter.unaliasedForEachActual(cx, CopyTo(args2.array())); } else { - /* Step 3. */ - if (!vp[3].isObject()) { + // Step 3. + if (!args[1].isObject()) { JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_BAD_APPLY_ARGS, js_apply_str); return false; } - /* - * Steps 4-5 (note erratum removing steps originally numbered 5 and 7 in - * original version of ES5). - */ - RootedObject aobj(cx, &vp[3].toObject()); + // Steps 4-5 (note erratum removing steps originally numbered 5 and 7 in + // original version of ES5). + RootedObject aobj(cx, &args[1].toObject()); uint32_t length; if (!GetLengthProperty(cx, aobj, &length)) return false; - /* Step 6. */ + // Step 6. if (length > ARGS_LENGTH_MAX) { JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_TOO_MANY_FUN_APPLY_ARGS); return false; } - if (!args.init(length)) + if (!args2.init(length)) return false; - /* Push fval, obj, and aobj's elements as args. */ - args.setCallee(fval); - args.setThis(vp[2]); + // Push fval, obj, and aobj's elements as args. + args2.setCallee(fval); + args2.setThis(args[0]); // Make sure the function is delazified before querying its arguments. - if (args.callee().is()) { - JSFunction *fun = &args.callee().as(); + if (args2.callee().is()) { + JSFunction *fun = &args2.callee().as(); if (fun->isInterpreted() && !fun->getOrCreateScript(cx)) return false; } - /* Steps 7-8. */ - if (!GetElements(cx, aobj, length, args.array())) + + // Steps 7-8. + if (!GetElements(cx, aobj, length, args2.array())) return false; } - /* Step 9. */ - if (!Invoke(cx, args)) + // Step 9. + if (!Invoke(cx, args2)) return false; - *vp = args.rval(); + args.rval().set(args2.rval()); return true; } diff --git a/js/src/vm/Stack-inl.h b/js/src/vm/Stack-inl.h index 1c82eef05fe..ed0cf59598d 100644 --- a/js/src/vm/Stack-inl.h +++ b/js/src/vm/Stack-inl.h @@ -136,7 +136,9 @@ template inline void StackFrame::unaliasedForEachActual(Op op) { - JS_ASSERT(!script()->funHasAnyAliasedFormal()); + // Don't assert !script()->funHasAnyAliasedFormal() since this function is + // called from ArgumentsObject::createUnexpected() which can access aliased + // slots. const Value *argsEnd = argv() + numActualArgs(); for (const Value *p = argv(); p < argsEnd; ++p) From 12d10d10fb32d7224133b07dabdf7491bdd82cc8 Mon Sep 17 00:00:00 2001 From: Brian Hackett Date: Tue, 4 Mar 2014 12:42:08 -0700 Subject: [PATCH 004/112] Bug 695438 - Make typed arrays native objects, allow adding new named properties, r=luke. --- js/src/builtin/Object.cpp | 6 +- js/src/jit-test/tests/basic/bug829821.js | 2 +- .../basic/typed-array-index-out-of-range.js | 29 ++ .../tests/basic/typed-array-sealed-frozen.js | 46 +- .../tests/collections/Array-of-generic-3.js | 1 + js/src/jit/BaselineIC.cpp | 22 +- js/src/jit/IonBuilder.cpp | 6 - js/src/jit/MIR.cpp | 3 +- js/src/jsapi.cpp | 26 +- js/src/jsarray.cpp | 4 +- js/src/jsinfer.cpp | 5 +- js/src/jsiter.cpp | 16 +- js/src/jsobj.cpp | 161 +++--- js/src/jsobj.h | 6 + js/src/jsobjinlines.h | 27 + js/src/vm/ObjectImpl.cpp | 13 + js/src/vm/ObjectImpl.h | 12 +- js/src/vm/OldDebugAPI.cpp | 2 +- js/src/vm/SelfHosting.cpp | 11 +- js/src/vm/Shape-inl.h | 15 + js/src/vm/Shape.h | 10 +- js/src/vm/TypedArrayObject.cpp | 489 +++++------------- js/src/vm/TypedArrayObject.h | 38 +- 23 files changed, 450 insertions(+), 500 deletions(-) create mode 100644 js/src/jit-test/tests/basic/typed-array-index-out-of-range.js diff --git a/js/src/builtin/Object.cpp b/js/src/builtin/Object.cpp index 7fd7c7e8881..a1ad7027973 100644 --- a/js/src/builtin/Object.cpp +++ b/js/src/builtin/Object.cpp @@ -145,7 +145,7 @@ js::ObjectToSource(JSContext *cx, HandleObject obj) int valcnt = 0; if (shape) { bool doGet = true; - if (obj2->isNative() && !IsImplicitDenseElement(shape)) { + if (obj2->isNative() && !IsImplicitDenseOrTypedArrayElement(shape)) { unsigned attrs = shape->attributes(); if (attrs & JSPROP_GETTER) { doGet = false; @@ -454,7 +454,7 @@ obj_lookupGetter(JSContext *cx, unsigned argc, Value *vp) return false; args.rval().setUndefined(); if (shape) { - if (pobj->isNative() && !IsImplicitDenseElement(shape)) { + if (pobj->isNative() && !IsImplicitDenseOrTypedArrayElement(shape)) { if (shape->hasGetterValue()) args.rval().set(shape->getterValue()); } @@ -490,7 +490,7 @@ obj_lookupSetter(JSContext *cx, unsigned argc, Value *vp) return false; args.rval().setUndefined(); if (shape) { - if (pobj->isNative() && !IsImplicitDenseElement(shape)) { + if (pobj->isNative() && !IsImplicitDenseOrTypedArrayElement(shape)) { if (shape->hasSetterValue()) args.rval().set(shape->setterValue()); } diff --git a/js/src/jit-test/tests/basic/bug829821.js b/js/src/jit-test/tests/basic/bug829821.js index 3dd737bea8f..9825e6e2b69 100644 --- a/js/src/jit-test/tests/basic/bug829821.js +++ b/js/src/jit-test/tests/basic/bug829821.js @@ -1,4 +1,4 @@ - +// |jit-test| error:TypeError x = []; x.unshift(Uint8ClampedArray); diff --git a/js/src/jit-test/tests/basic/typed-array-index-out-of-range.js b/js/src/jit-test/tests/basic/typed-array-index-out-of-range.js new file mode 100644 index 00000000000..681625be169 --- /dev/null +++ b/js/src/jit-test/tests/basic/typed-array-index-out-of-range.js @@ -0,0 +1,29 @@ + +// Out of bounds writes on typed arrays are uneffectful for all integers. + +var x = new Int32Array(10); + +function f() { + for (var i = -100; i < 100; i++) { + x[i] = i + 1; + if (i >= 0 && i < 10) + assertEq(x[i], i + 1); + else + assertEq(x[i], undefined); + } +} +f(); + +// Integers which don't fit in a double value's mantissa aren't really integers. + +var bigint = "" + Math.pow(2, 53); +x[bigint] = "twelve"; +assertEq(x[bigint], "twelve"); + +// Infinity and -Infinity maybe are supposed to be integers, but they aren't currently. + +x["Infinity"] = "twelve"; +assertEq(x["Infinity"], "twelve"); + +x["-Infinity"] = "twelve"; +assertEq(x["-Infinity"], "twelve"); diff --git a/js/src/jit-test/tests/basic/typed-array-sealed-frozen.js b/js/src/jit-test/tests/basic/typed-array-sealed-frozen.js index bc37144cb5a..d7be854db0d 100644 --- a/js/src/jit-test/tests/basic/typed-array-sealed-frozen.js +++ b/js/src/jit-test/tests/basic/typed-array-sealed-frozen.js @@ -1,8 +1,6 @@ // Any copyright is dedicated to the Public Domain. // http://creativecommons.org/licenses/publicdomain/ -// Typed arrays are always sealed. - load(libdir + "asserts.js") const constructors = [ @@ -20,8 +18,8 @@ const constructors = [ for (constructor of constructors) { print("testing non-empty " + constructor.name); let a = new constructor(10); - assertEq(Object.isExtensible(a), false); - assertEq(Object.isSealed(a), true); + assertEq(Object.isExtensible(a), true); + assertEq(Object.isSealed(a), false); assertEq(Object.isFrozen(a), false); // Should not throw. @@ -36,9 +34,9 @@ print(); for (constructor of constructors) { print("testing zero-length " + constructor.name); let a = new constructor(0); - assertEq(Object.isExtensible(a), false); - assertEq(Object.isSealed(a), true); - assertEq(Object.isFrozen(a), true); + assertEq(Object.isExtensible(a), true); + assertEq(Object.isSealed(a), false); + assertEq(Object.isFrozen(a), false); // Should not throw. Object.seal(a); @@ -51,3 +49,37 @@ for (constructor of constructors) { let a = new Uint8Array(1 << 24); Object.isSealed(a); Object.isFrozen(a); + +for (constructor of constructors) { + print("testing extensibility " + constructor.name); + let a = new constructor(10); + + // New named properties should show up on typed arrays. + a.foo = "twelve"; + assertEq(a.foo, "twelve"); + + // New indexed properties should not show up on typed arrays. + a[20] = "twelve"; + assertEq(a[20], undefined); + + // Watch for especially large indexed properties. + a[-10 >>> 0] = "twelve"; + assertEq(a[-10 >>> 0], undefined); + + // Watch for overly large indexed properties. + a[Math.pow(2, 53)] = "twelve"; + assertEq(a[Math.pow(2, 53)], "twelve"); + + // Don't define old properties. + Object.defineProperty(a, 5, {value: 3}); + assertEq(a[5], 0); + + // Don't define new properties. + Object.defineProperty(a, 20, {value: 3}); + assertEq(a[20], undefined); + + // Don't delete indexed properties. + a[3] = 3; + delete a[3]; + assertEq(a[3], 3); +} diff --git a/js/src/jit-test/tests/collections/Array-of-generic-3.js b/js/src/jit-test/tests/collections/Array-of-generic-3.js index 64b6ca7d90c..7288c85990d 100644 --- a/js/src/jit-test/tests/collections/Array-of-generic-3.js +++ b/js/src/jit-test/tests/collections/Array-of-generic-3.js @@ -1,3 +1,4 @@ +// |jit-test| error:TypeError // Array.of can be transplanted to builtin constructors. load(libdir + "asserts.js"); diff --git a/js/src/jit/BaselineIC.cpp b/js/src/jit/BaselineIC.cpp index f60b6f4ba25..06b223bd27a 100644 --- a/js/src/jit/BaselineIC.cpp +++ b/js/src/jit/BaselineIC.cpp @@ -3304,11 +3304,6 @@ EffectlesslyLookupProperty(JSContext *cx, HandleObject obj, HandlePropertyName n checkObj = GetDOMProxyProto(obj); if (!checkObj) return true; - } else if (obj->is() && obj->getProto()) { - // Typed array objects are non-native, but don't have any named - // properties. Just forward the lookup to the prototype, to allow - // inlining common getters like byteOffset. - checkObj = obj->getProto(); } else if (!obj->isNative()) { return true; } @@ -3328,7 +3323,7 @@ static bool IsCacheableProtoChain(JSObject *obj, JSObject *holder, bool isDOMProxy=false) { JS_ASSERT_IF(isDOMProxy, IsCacheableDOMProxy(obj)); - JS_ASSERT_IF(!isDOMProxy, obj->isNative() || obj->is()); + JS_ASSERT_IF(!isDOMProxy, obj->isNative()); // Don't handle objects which require a prototype guard. This should // be uncommon so handling it is likely not worth the complexity. @@ -3894,7 +3889,7 @@ TryAttachGetElemStub(JSContext *cx, JSScript *script, jsbytecode *pc, ICGetElem_ if (obj->isNative()) { // Check for NativeObject[int] dense accesses. - if (rhs.isInt32() && rhs.toInt32() >= 0) { + if (rhs.isInt32() && rhs.toInt32() >= 0 && !obj->is()) { IonSpew(IonSpew_BaselineIC, " Generating GetElem(Native[Int32] dense) stub"); ICGetElem_Dense::Compiler compiler(cx, stub->fallbackMonitorStub()->firstMonitorStub(), obj->lastProperty(), isCallElem); @@ -3942,10 +3937,10 @@ TryAttachGetElemStub(JSContext *cx, JSScript *script, jsbytecode *pc, ICGetElem_ return true; } - // GetElem operations on non-native objects other than typed arrays cannot - // be cached by either Baseline or Ion. Indicate this in the cache so that - // Ion does not generate a cache for this op. - if (!obj->isNative() && !obj->is()) + // GetElem operations on non-native objects cannot be cached by either + // Baseline or Ion. Indicate this in the cache so that Ion does not + // generate a cache for this op. + if (!obj->isNative()) stub->noteNonNativeAccess(); // GetElem operations which could access negative indexes generally can't @@ -4990,11 +4985,10 @@ DoSetElemFallback(JSContext *cx, BaselineFrame *frame, ICSetElem_Fallback *stub, // Try to generate new stubs. if (obj->isNative() && + !obj->is() && index.isInt32() && index.toInt32() >= 0 && !rhs.isMagic(JS_ELEMENTS_HOLE)) { - JS_ASSERT(!obj->is()); - bool addingCase; size_t protoDepth; @@ -6093,7 +6087,7 @@ TryAttachNativeGetPropStub(JSContext *cx, HandleScript script, jsbytecode *pc, return false; } - if (!isDOMProxy && !obj->isNative() && !obj->is()) + if (!isDOMProxy && !obj->isNative()) return true; bool isCallProp = (JSOp(*pc) == JSOP_CALLPROP); diff --git a/js/src/jit/IonBuilder.cpp b/js/src/jit/IonBuilder.cpp index 2759e95f90f..6f1dc05206b 100644 --- a/js/src/jit/IonBuilder.cpp +++ b/js/src/jit/IonBuilder.cpp @@ -5922,12 +5922,6 @@ IonBuilder::maybeInsertResume() static bool ClassHasEffectlessLookup(const Class *clasp, PropertyName *name) { - if (IsTypedArrayClass(clasp)) { - // Typed arrays have a lookupGeneric hook, but it only handles - // integers, not names. - JS_ASSERT(name); - return true; - } return clasp->isNative() && !clasp->ops.lookupGeneric; } diff --git a/js/src/jit/MIR.cpp b/js/src/jit/MIR.cpp index 0ce5be00463..38aadf7cb80 100644 --- a/js/src/jit/MIR.cpp +++ b/js/src/jit/MIR.cpp @@ -2933,8 +2933,9 @@ jit::ElementAccessIsDenseNative(MDefinition *obj, MDefinition *id) if (!types) return false; + // Typed arrays are native classes but do not have dense elements. const Class *clasp = types->getKnownClass(); - return clasp && clasp->isNative(); + return clasp && clasp->isNative() && !IsTypedArrayClass(clasp); } bool diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp index e5e33e954a7..8b66c1f3074 100644 --- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -2715,8 +2715,8 @@ LookupResult(JSContext *cx, HandleObject obj, HandleObject obj2, HandleId id, return true; } } - } else if (IsImplicitDenseElement(shape)) { - vp.set(obj2->getDenseElement(JSID_TO_INT(id))); + } else if (IsImplicitDenseOrTypedArrayElement(shape)) { + vp.set(obj2->getDenseOrTypedArrayElement(JSID_TO_INT(id))); return true; } else { /* Peek at the native property's slot value, without doing a Get. */ @@ -2864,9 +2864,21 @@ JS_AlreadyHasOwnPropertyById(JSContext *cx, HandleObject obj, HandleId id, bool return true; } - if (JSID_IS_INT(id) && obj->containsDenseElement(JSID_TO_INT(id))) { - *foundp = true; - return true; + // Check for an existing native property on the objct. Be careful not to + // call any lookup or resolve hooks. + + if (JSID_IS_INT(id)) { + uint32_t index = JSID_TO_INT(id); + + if (obj->containsDenseElement(index)) { + *foundp = true; + return true; + } + + if (obj->is() && index < obj->as().length()) { + *foundp = true; + return true; + } } *foundp = obj->nativeContains(cx, id); @@ -3257,9 +3269,9 @@ GetPropertyDescriptorById(JSContext *cx, HandleObject obj, HandleId id, unsigned desc.object().set(obj2); if (obj2->isNative()) { - if (IsImplicitDenseElement(shape)) { + if (IsImplicitDenseOrTypedArrayElement(shape)) { desc.setEnumerable(); - desc.value().set(obj2->getDenseElement(JSID_TO_INT(id))); + desc.value().set(obj2->getDenseOrTypedArrayElement(JSID_TO_INT(id))); } else { desc.setAttributes(shape->attributes()); desc.setGetter(shape->getter()); diff --git a/js/src/jsarray.cpp b/js/src/jsarray.cpp index 20d1abe2946..e067779129c 100644 --- a/js/src/jsarray.cpp +++ b/js/src/jsarray.cpp @@ -823,6 +823,8 @@ js::ObjectMayHaveExtraIndexedProperties(JSObject *obj) return true; if (obj->getDenseInitializedLength() > 0) return true; + if (obj->is()) + return true; } return false; @@ -2040,7 +2042,7 @@ js::array_push(JSContext *cx, unsigned argc, Value *vp) /* Fast path for native objects with dense elements. */ do { - if (!obj->isNative()) + if (!obj->isNative() || obj->is()) break; if (obj->is() && !obj->as().lengthIsWritable()) diff --git a/js/src/jsinfer.cpp b/js/src/jsinfer.cpp index 43553fd9044..3bdf893654f 100644 --- a/js/src/jsinfer.cpp +++ b/js/src/jsinfer.cpp @@ -2134,7 +2134,10 @@ static inline bool ClassCanHaveExtraProperties(const Class *clasp) { JS_ASSERT(clasp->resolve); - return clasp->resolve != JS_ResolveStub || clasp->ops.lookupGeneric || clasp->ops.getGeneric; + return clasp->resolve != JS_ResolveStub + || clasp->ops.lookupGeneric + || clasp->ops.getGeneric + || IsTypedArrayClass(clasp); } static inline bool diff --git a/js/src/jsiter.cpp b/js/src/jsiter.cpp index e1821a8d9c5..5ab62242b8f 100644 --- a/js/src/jsiter.cpp +++ b/js/src/jsiter.cpp @@ -131,13 +131,22 @@ static bool EnumerateNativeProperties(JSContext *cx, HandleObject pobj, unsigned flags, IdSet &ht, AutoIdVector *props) { - /* Collect any elements from this object. */ + /* Collect any dense elements from this object. */ size_t initlen = pobj->getDenseInitializedLength(); const Value *vp = pobj->getDenseElements(); for (size_t i = 0; i < initlen; ++i, ++vp) { if (!vp->isMagic(JS_ELEMENTS_HOLE)) { /* Dense arrays never get so large that i would not fit into an integer id. */ - if (!Enumerate(cx, pobj, INT_TO_JSID(i), true, flags, ht, props)) + if (!Enumerate(cx, pobj, INT_TO_JSID(i), /* enumerable = */ true, flags, ht, props)) + return false; + } + } + + /* Collect any typed array elements from this object. */ + if (pobj->is()) { + size_t len = pobj->as().length(); + for (size_t i = 0; i < len; i++) { + if (!Enumerate(cx, pobj, INT_TO_JSID(i), /* enumerable = */ true, flags, ht, props)) return false; } } @@ -623,6 +632,7 @@ js::GetIterator(JSContext *cx, HandleObject obj, unsigned flags, MutableHandleVa do { if (!pobj->isNative() || !pobj->hasEmptyElements() || + pobj->is() || pobj->hasUncacheableProto() || pobj->getOps()->enumerate || pobj->getClass()->enumerate != JS_EnumerateStub || @@ -1053,7 +1063,7 @@ SuppressDeletedPropertyHelper(JSContext *cx, HandleObject obj, StringPredicate p if (prop) { unsigned attrs; if (obj2->isNative()) - attrs = GetShapeAttributes(prop); + attrs = GetShapeAttributes(obj2, prop); else if (!JSObject::getGenericAttributes(cx, obj2, id, &attrs)) return false; diff --git a/js/src/jsobj.cpp b/js/src/jsobj.cpp index 78a7daa9eaf..8cc46254579 100644 --- a/js/src/jsobj.cpp +++ b/js/src/jsobj.cpp @@ -236,7 +236,7 @@ js::GetOwnPropertyDescriptor(JSContext *cx, HandleObject obj, HandleId id, bool doGet = true; if (pobj->isNative()) { - desc.setAttributes(GetShapeAttributes(shape)); + desc.setAttributes(GetShapeAttributes(pobj, shape)); if (desc.hasGetterOrSetterObject()) { doGet = false; if (desc.hasGetterObject()) @@ -599,8 +599,8 @@ DefinePropertyOnObject(JSContext *cx, HandleObject obj, HandleId id, const PropD shapeHasDefaultSetter = true, shapeHasGetterValue = false, shapeHasSetterValue = false; - uint8_t shapeAttributes = JSPROP_ENUMERATE; - if (!IsImplicitDenseElement(shape)) { + uint8_t shapeAttributes = GetShapeAttributes(obj, shape); + if (!IsImplicitDenseOrTypedArrayElement(shape)) { shapeDataDescriptor = shape->isDataDescriptor(); shapeAccessorDescriptor = shape->isAccessorDescriptor(); shapeWritable = shape->writable(); @@ -641,8 +641,8 @@ DefinePropertyOnObject(JSContext *cx, HandleObject obj, HandleId id, const PropD * avoid calling a getter; we won't need the value if it's not a * data descriptor. */ - if (IsImplicitDenseElement(shape)) { - v = obj->getDenseElement(JSID_TO_INT(id)); + if (IsImplicitDenseOrTypedArrayElement(shape)) { + v = obj->getDenseOrTypedArrayElement(JSID_TO_INT(id)); } else if (shape->isDataDescriptor()) { /* * We must rule out a non-configurable js::PropertyOp-guarded @@ -783,8 +783,8 @@ DefinePropertyOnObject(JSContext *cx, HandleObject obj, HandleId id, const PropD changed |= JSPROP_ENUMERATE; attrs = (shapeAttributes & ~changed) | (desc.attributes() & changed); - getter = IsImplicitDenseElement(shape) ? JS_PropertyStub : shape->getter(); - setter = IsImplicitDenseElement(shape) ? JS_StrictPropertyStub : shape->setter(); + getter = IsImplicitDenseOrTypedArrayElement(shape) ? JS_PropertyStub : shape->getter(); + setter = IsImplicitDenseOrTypedArrayElement(shape) ? JS_StrictPropertyStub : shape->setter(); } else if (desc.isDataDescriptor()) { unsigned unchanged = 0; if (!desc.hasConfigurable()) @@ -1084,7 +1084,7 @@ JSObject::sealOrFreeze(JSContext *cx, HandleObject obj, ImmutabilityType it) /* preventExtensions must sparsify dense objects, so we can assign to holes without checks. */ JS_ASSERT_IF(obj->isNative(), obj->getDenseCapacity() == 0); - if (obj->isNative() && !obj->inDictionaryMode()) { + if (obj->isNative() && !obj->inDictionaryMode() && !obj->is()) { /* * Seal/freeze non-dictionary objects by constructing a new shape * hierarchy mirroring the original one, which can be shared if many @@ -3066,6 +3066,7 @@ bool JSObject::growElements(ThreadSafeContext *cx, uint32_t newcap) { JS_ASSERT(nonProxyIsExtensible()); + JS_ASSERT(canHaveNonEmptyElements()); /* * When an object with CAPACITY_DOUBLING_MAX or fewer elements needs to @@ -3132,6 +3133,7 @@ void JSObject::shrinkElements(ThreadSafeContext *cx, uint32_t newcap) { JS_ASSERT(cx->isThreadLocal(this)); + JS_ASSERT(canHaveNonEmptyElements()); uint32_t oldcap = getDenseCapacity(); JS_ASSERT(newcap <= oldcap); @@ -3705,7 +3707,8 @@ DefinePropertyOrElement(typename ExecutionModeTraits::ExclusiveContextType getter == JS_PropertyStub && setter == JS_StrictPropertyStub && attrs == JSPROP_ENUMERATE && - (!obj->isIndexed() || !obj->nativeContainsPure(id))) + (!obj->isIndexed() || !obj->nativeContainsPure(id)) && + !obj->is()) { uint32_t index = JSID_TO_INT(id); bool definesPast; @@ -3755,6 +3758,13 @@ DefinePropertyOrElement(typename ExecutionModeTraits::ExclusiveContextType } } + // Don't define new indexed properties on typed arrays. + if (obj->is()) { + double index; + if (IsTypedArrayIndex(id, &index)) + return true; + } + AutoRooterGetterSetter gsRoot(cx, attrs, &getter, &setter); RootedShape shape(cx, JSObject::putProperty(cx, obj, id, getter, setter, @@ -3826,7 +3836,11 @@ js::DefineNativeProperty(ExclusiveContext *cx, HandleObject obj, HandleId id, Ha if (!NativeLookupOwnProperty(cx, obj, id, flags, &shape)) return false; if (shape) { - if (IsImplicitDenseElement(shape)) { + if (IsImplicitDenseOrTypedArrayElement(shape)) { + if (obj->is()) { + /* Ignore getter/setter properties added to typed arrays. */ + return true; + } if (!JSObject::sparsifyDenseElement(cx, obj, JSID_TO_INT(id))) return false; shape = obj->nativeLookup(cx, id); @@ -3953,7 +3967,7 @@ CallResolveOp(JSContext *cx, HandleObject obj, HandleId id, unsigned flags, } if (JSID_IS_INT(id) && objp->containsDenseElement(JSID_TO_INT(id))) { - MarkDenseElementFound(propp); + MarkDenseOrTypedArrayElementFound(propp); return true; } @@ -3979,11 +3993,26 @@ LookupOwnPropertyWithFlagsInline(ExclusiveContext *cx, // Check for a native dense element. if (JSID_IS_INT(id) && obj->containsDenseElement(JSID_TO_INT(id))) { objp.set(obj); - MarkDenseElementFound(propp); + MarkDenseOrTypedArrayElementFound(propp); *donep = true; return true; } + // Check for a typed array element. Integer lookups always finish here + // so that integer properties on the prototype are ignored even for out + // of bounds accesses. + if (obj->template is()) { + double index; + if (IsTypedArrayIndex(id, &index)) { + if (index >= 0 && index < obj->template as().length()) { + objp.set(obj); + MarkDenseOrTypedArrayElementFound(propp); + } + *donep = true; + return true; + } + } + // Check for a native property. if (Shape *shape = obj->nativeLookup(cx, id)) { objp.set(obj); @@ -4523,8 +4552,8 @@ GetPropertyHelperInline(JSContext *cx, : JSObject::getGeneric(cx, obj2Handle, obj2Handle, idHandle, vpHandle); } - if (IsImplicitDenseElement(shape)) { - vp.set(obj2->getDenseElement(JSID_TO_INT(id))); + if (IsImplicitDenseOrTypedArrayElement(shape)) { + vp.set(obj2->getDenseOrTypedArrayElement(JSID_TO_INT(id))); return true; } @@ -4557,21 +4586,34 @@ LookupPropertyPureInline(JSObject *obj, jsid id, JSObject **objp, Shape **propp) JSObject *current = obj; while (true) { - /* Search for a native dense element or property. */ - { - if (JSID_IS_INT(id) && current->containsDenseElement(JSID_TO_INT(id))) { - *objp = current; - MarkDenseElementFound(propp); - return true; - } + /* Search for a native dense element, typed array element, or property. */ - if (Shape *shape = current->nativeLookupPure(id)) { - *objp = current; - *propp = shape; + if (JSID_IS_INT(id) && current->containsDenseElement(JSID_TO_INT(id))) { + *objp = current; + MarkDenseOrTypedArrayElementFound(propp); + return true; + } + + if (current->is()) { + double index; + if (IsTypedArrayIndex(id, &index)) { + if (index >= 0 && index < obj->as().length()) { + *objp = current; + MarkDenseOrTypedArrayElementFound(propp); + } else { + *objp = nullptr; + *propp = nullptr; + } return true; } } + if (Shape *shape = current->nativeLookupPure(id)) { + *objp = current; + *propp = shape; + return true; + } + /* Fail if there's a resolve hook. */ if (current->getClass()->resolve != JS_ResolveStub) return false; @@ -4632,28 +4674,6 @@ IdIsLength(ThreadSafeContext *cx, jsid id) bool js::GetPropertyPure(ThreadSafeContext *cx, JSObject *obj, jsid id, Value *vp) { - /* Typed arrays are not native, so we fast-path them here. */ - if (obj->is()) { - TypedArrayObject *tarr = &obj->as(); - - if (JSID_IS_INT(id)) { - uint32_t index = JSID_TO_INT(id); - if (index < tarr->length()) { - MutableHandleValue vpHandle = MutableHandleValue::fromMarkedLocation(vp); - tarr->copyTypedArrayElement(index, vpHandle); - return true; - } - return false; - } - - if (IdIsLength(cx, id)) { - vp->setNumber(tarr->length()); - return true; - } - - return false; - } - /* Deal with native objects. */ JSObject *obj2; Shape *shape; @@ -4673,15 +4693,22 @@ js::GetPropertyPure(ThreadSafeContext *cx, JSObject *obj, jsid id, Value *vp) return true; } - if (IsImplicitDenseElement(shape)) { - *vp = obj2->getDenseElement(JSID_TO_INT(id)); + if (IsImplicitDenseOrTypedArrayElement(shape)) { + *vp = obj2->getDenseOrTypedArrayElement(JSID_TO_INT(id)); return true; } - /* Special case 'length' on Array. */ - if (obj->is() && IdIsLength(cx, id)) { - vp->setNumber(obj->as().length()); - return true; + /* Special case 'length' on Array and TypedArray. */ + if (IdIsLength(cx, id)) { + if (obj->is()) { + vp->setNumber(obj->as().length()); + return true; + } + + if (obj->is()) { + vp->setNumber(obj->as().length()); + return true; + } } return NativeGetPureInline(obj2, shape, vp); @@ -4936,7 +4963,7 @@ baseops::SetPropertyHelper(typename ExecutionModeTraits::ContextType cxArg PropertyOp getter = clasp->getProperty; StrictPropertyOp setter = clasp->setProperty; - if (IsImplicitDenseElement(shape)) { + if (IsImplicitDenseOrTypedArrayElement(shape)) { /* ES5 8.12.4 [[Put]] step 2, for a dense data property on pobj. */ if (pobj != obj) shape = nullptr; @@ -5013,7 +5040,7 @@ baseops::SetPropertyHelper(typename ExecutionModeTraits::ContextType cxArg } } - if (IsImplicitDenseElement(shape)) { + if (IsImplicitDenseOrTypedArrayElement(shape)) { uint32_t index = JSID_TO_INT(id); bool definesPast; if (!WouldDefinePastNonwritableLength(cxArg, obj, index, strict, &definesPast)) @@ -5026,10 +5053,8 @@ baseops::SetPropertyHelper(typename ExecutionModeTraits::ContextType cxArg } if (mode == ParallelExecution) - obj->setDenseElementIfHasType(index, vp); - else - obj->setDenseElementWithType(cxArg->asJSContext(), index, vp); - return true; + return obj->setDenseOrTypedArrayElementIfHasType(cxArg, index, vp); + return obj->setDenseOrTypedArrayElementWithType(cxArg->asJSContext(), index, vp); } if (obj->is() && id == NameToId(cxArg->names().length)) { @@ -5114,7 +5139,7 @@ baseops::GetAttributes(JSContext *cx, HandleObject obj, HandleId id, unsigned *a if (!nobj->isNative()) return JSObject::getGenericAttributes(cx, nobj, id, attrsp); - *attrsp = GetShapeAttributes(shape); + *attrsp = GetShapeAttributes(nobj, shape); return true; } @@ -5127,7 +5152,13 @@ baseops::SetAttributes(JSContext *cx, HandleObject obj, HandleId id, unsigned *a return false; if (!shape) return true; - if (nobj->isNative() && IsImplicitDenseElement(shape)) { + if (nobj->isNative() && IsImplicitDenseOrTypedArrayElement(shape)) { + if (nobj->is()) { + if (*attrsp == (JSPROP_ENUMERATE | JSPROP_PERMANENT)) + return true; + JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_CANT_SET_ARRAY_ATTRS); + return false; + } if (!JSObject::sparsifyDenseElement(cx, nobj, JSID_TO_INT(id))) return false; shape = obj->nativeLookup(cx, id); @@ -5160,7 +5191,13 @@ baseops::DeleteGeneric(JSContext *cx, HandleObject obj, HandleId id, bool *succe GCPoke(cx->runtime()); - if (IsImplicitDenseElement(shape)) { + if (IsImplicitDenseOrTypedArrayElement(shape)) { + if (obj->is()) { + // Don't delete elements from typed arrays. + *succeeded = false; + return true; + } + if (!CallJSDeletePropertyOp(cx, obj->getClass()->delProperty, obj, id, succeeded)) return false; if (!succeeded) @@ -5237,7 +5274,7 @@ js::WatchGuts(JSContext *cx, JS::HandleObject origObj, JS::HandleId id, JS::Hand bool baseops::Watch(JSContext *cx, JS::HandleObject obj, JS::HandleId id, JS::HandleObject callable) { - if (!obj->isNative()) { + if (!obj->isNative() || obj->is()) { JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_CANT_WATCH, obj->getClass()->name); return false; diff --git a/js/src/jsobj.h b/js/src/jsobj.h index 7e1cfde68bd..4c11985aa27 100644 --- a/js/src/jsobj.h +++ b/js/src/jsobj.h @@ -672,6 +672,12 @@ class JSObject : public js::ObjectImpl static inline void removeDenseElementForSparseIndex(js::ExclusiveContext *cx, js::HandleObject obj, uint32_t index); + inline js::Value getDenseOrTypedArrayElement(uint32_t idx); + inline bool setDenseOrTypedArrayElementIfHasType(js::ThreadSafeContext *cx, uint32_t index, + const js::Value &val); + inline bool setDenseOrTypedArrayElementWithType(js::ExclusiveContext *cx, uint32_t index, + const js::Value &val); + void copyDenseElements(uint32_t dstStart, const js::Value *src, uint32_t count) { JS_ASSERT(dstStart + count <= getDenseCapacity()); JSRuntime *rt = runtimeFromMainThread(); diff --git a/js/src/jsobjinlines.h b/js/src/jsobjinlines.h index 35dc5ce3c49..4a566cc9f56 100644 --- a/js/src/jsobjinlines.h +++ b/js/src/jsobjinlines.h @@ -353,6 +353,33 @@ JSObject::ensureDenseElementsPreservePackedFlag(js::ThreadSafeContext *cx, uint3 return ensureDenseElementsNoPackedCheck(cx, index, extra); } +inline js::Value +JSObject::getDenseOrTypedArrayElement(uint32_t idx) +{ + if (is()) + return as().getElement(idx); + return getDenseElement(idx); +} + +inline bool +JSObject::setDenseOrTypedArrayElementIfHasType(js::ThreadSafeContext *cx, uint32_t index, + const js::Value &val) +{ + if (is()) + return as().setElement(cx, index, val); + return setDenseElementIfHasType(index, val); +} + +inline bool +JSObject::setDenseOrTypedArrayElementWithType(js::ExclusiveContext *cx, uint32_t index, + const js::Value &val) +{ + if (is()) + return as().setElement(cx, index, val); + setDenseElementWithType(cx, index, val); + return true; +} + /* static */ inline bool JSObject::setSingletonType(js::ExclusiveContext *cx, js::HandleObject obj) { diff --git a/js/src/vm/ObjectImpl.cpp b/js/src/vm/ObjectImpl.cpp index 5879c2e248e..7132303368a 100644 --- a/js/src/vm/ObjectImpl.cpp +++ b/js/src/vm/ObjectImpl.cpp @@ -153,6 +153,19 @@ static const ObjectElements emptyElementsHeader(0, 0); HeapSlot *const js::emptyObjectElements = reinterpret_cast(uintptr_t(&emptyElementsHeader) + sizeof(ObjectElements)); +#ifdef DEBUG + +bool +ObjectImpl::canHaveNonEmptyElements() +{ + JSObject *obj = static_cast(this); + if (isNative()) + return !obj->is(); + return obj->is() || obj->is(); +} + +#endif // DEBUG + /* static */ bool ObjectElements::ConvertElementsToDoubles(JSContext *cx, uintptr_t elementsPtr) { diff --git a/js/src/vm/ObjectImpl.h b/js/src/vm/ObjectImpl.h index 37964bb2f82..dad2f0ae542 100644 --- a/js/src/vm/ObjectImpl.h +++ b/js/src/vm/ObjectImpl.h @@ -684,7 +684,8 @@ ArraySetLength(typename ExecutionModeTraits::ContextType cx, unsigned attrs, HandleValue value, bool setterIsStrict); /* - * Elements header used for all native objects. The elements component of such + * Elements header used for all objects other than non-native objects (except + * for ArrayBufferObjects!!!) and typed arrays. The elements component of such * objects offers an efficient representation for all or some of the indexed * properties of the object, using a flat array of Values rather than a shape * hierarchy stored in the object's slots. This structure is immediately @@ -1457,7 +1458,14 @@ class ObjectImpl : public gc::BarrieredCell return &fixedSlots()[2]; } - void setFixedElements() { this->elements = fixedElements(); } +#ifdef DEBUG + bool canHaveNonEmptyElements(); +#endif + + void setFixedElements() { + JS_ASSERT(canHaveNonEmptyElements()); + this->elements = fixedElements(); + } inline bool hasDynamicElements() const { /* diff --git a/js/src/vm/OldDebugAPI.cpp b/js/src/vm/OldDebugAPI.cpp index bdba177c631..7b445f2bad2 100644 --- a/js/src/vm/OldDebugAPI.cpp +++ b/js/src/vm/OldDebugAPI.cpp @@ -318,7 +318,7 @@ JS_SetWatchPoint(JSContext *cx, JSObject *obj_, jsid id_, return false; } - if (!obj->isNative()) { + if (!obj->isNative() || obj->is()) { JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_CANT_WATCH, obj->getClass()->name); return false; diff --git a/js/src/vm/SelfHosting.cpp b/js/src/vm/SelfHosting.cpp index ce91b8795e1..5da68ef948d 100644 --- a/js/src/vm/SelfHosting.cpp +++ b/js/src/vm/SelfHosting.cpp @@ -414,22 +414,21 @@ js::intrinsic_UnsafePutElements(JSContext *cx, unsigned argc, Value *vp) uint32_t elemi = base+2; JS_ASSERT(args[arri].isObject()); - JS_ASSERT(args[arri].toObject().isNative() || - args[arri].toObject().is()); + JS_ASSERT(args[arri].toObject().isNative()); JS_ASSERT(args[idxi].isInt32()); RootedObject arrobj(cx, &args[arri].toObject()); uint32_t idx = args[idxi].toInt32(); - if (arrobj->isNative()) { - JS_ASSERT(idx < arrobj->getDenseInitializedLength()); - arrobj->setDenseElementWithType(cx, idx, args[elemi]); - } else { + if (arrobj->is()) { JS_ASSERT(idx < arrobj->as().length()); RootedValue tmp(cx, args[elemi]); // XXX: Always non-strict. if (!JSObject::setElement(cx, arrobj, arrobj, idx, &tmp, false)) return false; + } else { + JS_ASSERT(idx < arrobj->getDenseInitializedLength()); + arrobj->setDenseElementWithType(cx, idx, args[elemi]); } } diff --git a/js/src/vm/Shape-inl.h b/js/src/vm/Shape-inl.h index afed46fce6d..68d6eb9e022 100644 --- a/js/src/vm/Shape-inl.h +++ b/js/src/vm/Shape-inl.h @@ -15,6 +15,7 @@ #include "vm/Interpreter.h" #include "vm/ScopeObject.h" +#include "vm/TypedArrayObject.h" #include "jsatominlines.h" #include "jscntxtinlines.h" @@ -204,6 +205,20 @@ AutoRooterGetterSetter::AutoRooterGetterSetter(ThreadSafeContext *cx, uint8_t at MOZ_GUARD_OBJECT_NOTIFIER_INIT; } +static inline uint8_t +GetShapeAttributes(JSObject *obj, Shape *shape) +{ + JS_ASSERT(obj->isNative()); + + if (IsImplicitDenseOrTypedArrayElement(shape)) { + if (obj->is()) + return JSPROP_ENUMERATE | JSPROP_PERMANENT; + return JSPROP_ENUMERATE; + } + + return shape->attributes(); +} + } /* namespace js */ #endif /* vm_Shape_inl_h */ diff --git a/js/src/vm/Shape.h b/js/src/vm/Shape.h index 061ee52ba4c..0b35862b3a5 100644 --- a/js/src/vm/Shape.h +++ b/js/src/vm/Shape.h @@ -1660,23 +1660,17 @@ MarkNonNativePropertyFound(MutableHandleShape propp) template static inline void -MarkDenseElementFound(typename MaybeRooted::MutableHandleType propp) +MarkDenseOrTypedArrayElementFound(typename MaybeRooted::MutableHandleType propp) { propp.set(reinterpret_cast(1)); } static inline bool -IsImplicitDenseElement(Shape *prop) +IsImplicitDenseOrTypedArrayElement(Shape *prop) { return prop == reinterpret_cast(1); } -static inline uint8_t -GetShapeAttributes(HandleShape shape) -{ - return IsImplicitDenseElement(shape) ? JSPROP_ENUMERATE : shape->attributes(); -} - } // namespace js #ifdef _MSC_VER diff --git a/js/src/vm/TypedArrayObject.cpp b/js/src/vm/TypedArrayObject.cpp index 07b3e5e54c9..0ab33bc67d7 100644 --- a/js/src/vm/TypedArrayObject.cpp +++ b/js/src/vm/TypedArrayObject.cpp @@ -50,7 +50,9 @@ using namespace js::gc; using namespace js::types; using mozilla::IsNaN; +using mozilla::NegativeInfinity; using mozilla::PodCopy; +using mozilla::PositiveInfinity; using JS::CanonicalizeNaN; using JS::GenericNaN; @@ -117,77 +119,6 @@ TypedArrayObject::sharedBuffer() const return &bufferValue(const_cast(this)).toObject().as(); } -bool -TypedArrayObject::obj_lookupGeneric(JSContext *cx, HandleObject tarray, HandleId id, - MutableHandleObject objp, MutableHandleShape propp) -{ - if (tarray->as().isArrayIndex(id)) { - MarkNonNativePropertyFound(propp); - objp.set(tarray); - return true; - } - - RootedObject proto(cx, tarray->getProto()); - if (!proto) { - objp.set(nullptr); - propp.set(nullptr); - return true; - } - - return JSObject::lookupGeneric(cx, proto, id, objp, propp); -} - -bool -TypedArrayObject::obj_lookupProperty(JSContext *cx, HandleObject obj, HandlePropertyName name, - MutableHandleObject objp, MutableHandleShape propp) -{ - Rooted id(cx, NameToId(name)); - return obj_lookupGeneric(cx, obj, id, objp, propp); -} - -bool -TypedArrayObject::obj_lookupElement(JSContext *cx, HandleObject tarray, uint32_t index, - MutableHandleObject objp, MutableHandleShape propp) -{ - if (index < tarray->as().length()) { - MarkNonNativePropertyFound(propp); - objp.set(tarray); - return true; - } - - RootedObject proto(cx, tarray->getProto()); - if (proto) - return JSObject::lookupElement(cx, proto, index, objp, propp); - - objp.set(nullptr); - propp.set(nullptr); - return true; -} - -bool -TypedArrayObject::obj_lookupSpecial(JSContext *cx, HandleObject obj, HandleSpecialId sid, - MutableHandleObject objp, MutableHandleShape propp) -{ - Rooted id(cx, SPECIALID_TO_JSID(sid)); - return obj_lookupGeneric(cx, obj, id, objp, propp); -} - -bool -TypedArrayObject::obj_getGenericAttributes(JSContext *cx, HandleObject obj, HandleId id, - unsigned *attrsp) -{ - *attrsp = JSPROP_PERMANENT | JSPROP_ENUMERATE; - return true; -} - -bool -TypedArrayObject::obj_setGenericAttributes(JSContext *cx, HandleObject obj, HandleId id, - unsigned *attrsp) -{ - JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_CANT_SET_ARRAY_ATTRS); - return false; -} - /* static */ int TypedArrayObject::lengthOffset() { @@ -235,8 +166,8 @@ js::ClampDoubleToUint8(const double x) return y; } -bool -js::ToDoubleForTypedArray(JSContext *cx, JS::HandleValue vp, double *d) +static bool +ToDoubleForTypedArray(ThreadSafeContext *cx, const Value &vp, double *d) { if (vp.isDouble()) { *d = vp.toDouble(); @@ -245,7 +176,7 @@ js::ToDoubleForTypedArray(JSContext *cx, JS::HandleValue vp, double *d) } else if (vp.isPrimitive()) { JS_ASSERT(vp.isString() || vp.isUndefined() || vp.isBoolean()); if (vp.isString()) { - if (!ToNumber(cx, vp, d)) + if (!StringToNumber(cx, vp.toString(), d)) return false; } else if (vp.isUndefined()) { *d = GenericNaN(); @@ -312,83 +243,18 @@ class TypedArrayObjectTemplate : public TypedArrayObject } static bool - obj_getProperty(JSContext *cx, HandleObject obj, HandleObject receiver, HandlePropertyName name, - MutableHandleValue vp) - { - RootedObject proto(cx, obj->getProto()); - if (!proto) { - vp.setUndefined(); - return true; - } - - return JSObject::getProperty(cx, proto, receiver, name, vp); - } - - static bool - obj_getElement(JSContext *cx, HandleObject tarray, HandleObject receiver, uint32_t index, - MutableHandleValue vp) - { - if (index < tarray->as().length()) { - copyIndexToValue(tarray, index, vp); - return true; - } - - vp.setUndefined(); - return true; - } - - static bool - obj_getSpecial(JSContext *cx, HandleObject obj, HandleObject receiver, HandleSpecialId sid, - MutableHandleValue vp) - { - RootedObject proto(cx, obj->getProto()); - if (!proto) { - vp.setUndefined(); - return true; - } - - return JSObject::getSpecial(cx, proto, receiver, sid, vp); - } - - static bool - obj_getGeneric(JSContext *cx, HandleObject obj, HandleObject receiver, HandleId id, - MutableHandleValue vp) - { - RootedValue idval(cx, IdToValue(id)); - - uint32_t index; - if (IsDefinitelyIndex(idval, &index)) - return obj_getElement(cx, obj, receiver, index, vp); - - Rooted sid(cx); - if (ValueIsSpecial(obj, &idval, &sid, cx)) - return obj_getSpecial(cx, obj, receiver, sid, vp); - - JSAtom *atom = ToAtom(cx, idval); - if (!atom) - return false; - - if (atom->isIndex(&index)) - return obj_getElement(cx, obj, receiver, index, vp); - - Rooted name(cx, atom->asPropertyName()); - return obj_getProperty(cx, obj, receiver, name, vp); - } - - static bool - setElementTail(JSContext *cx, HandleObject tarray, uint32_t index, - MutableHandleValue vp, bool strict) + setIndexValue(ThreadSafeContext *cx, JSObject *tarray, uint32_t index, const Value &value) { JS_ASSERT(tarray); JS_ASSERT(index < tarray->as().length()); - if (vp.isInt32()) { - setIndex(tarray, index, NativeType(vp.toInt32())); + if (value.isInt32()) { + setIndex(tarray, index, NativeType(value.toInt32())); return true; } double d; - if (!ToDoubleForTypedArray(cx, vp, &d)) + if (!ToDoubleForTypedArray(cx, value, &d)) return false; // If the array is an integer array, we only handle up to @@ -415,150 +281,6 @@ class TypedArrayObjectTemplate : public TypedArrayObject return true; } - static bool - obj_setGeneric(JSContext *cx, HandleObject tarray, HandleId id, - MutableHandleValue vp, bool strict) - { - uint32_t index; - // We can't just chain to js_SetPropertyHelper, because we're not a normal object. - if (!tarray->as().isArrayIndex(id, &index)) { - // Silent ignore is better than an exception here, because - // at some point we may want to support other properties on - // these objects. This is especially true when these arrays - // are used to implement HTML Canvas 2D's PixelArray objects, - // which used to be plain old arrays. - vp.setUndefined(); - return true; - } - - return setElementTail(cx, tarray, index, vp, strict); - } - - static bool - obj_setProperty(JSContext *cx, HandleObject obj, HandlePropertyName name, - MutableHandleValue vp, bool strict) - { - Rooted id(cx, NameToId(name)); - return obj_setGeneric(cx, obj, id, vp, strict); - } - - static bool - obj_setElement(JSContext *cx, HandleObject tarray, uint32_t index, - MutableHandleValue vp, bool strict) - { - if (index >= tarray->as().length()) { - // Silent ignore is better than an exception here, because - // at some point we may want to support other properties on - // these objects. This is especially true when these arrays - // are used to implement HTML Canvas 2D's PixelArray objects, - // which used to be plain old arrays. - vp.setUndefined(); - return true; - } - - return setElementTail(cx, tarray, index, vp, strict); - } - - static bool - obj_setSpecial(JSContext *cx, HandleObject obj, HandleSpecialId sid, - MutableHandleValue vp, bool strict) - { - Rooted id(cx, SPECIALID_TO_JSID(sid)); - return obj_setGeneric(cx, obj, id, vp, strict); - } - - static bool - obj_defineGeneric(JSContext *cx, HandleObject obj, HandleId id, HandleValue v, - PropertyOp getter, StrictPropertyOp setter, unsigned attrs) - { - RootedValue tmp(cx, v); - return obj_setGeneric(cx, obj, id, &tmp, false); - } - - static bool - obj_defineProperty(JSContext *cx, HandleObject obj, HandlePropertyName name, HandleValue v, - PropertyOp getter, StrictPropertyOp setter, unsigned attrs) - { - Rooted id(cx, NameToId(name)); - return obj_defineGeneric(cx, obj, id, v, getter, setter, attrs); - } - - static bool - obj_defineElement(JSContext *cx, HandleObject obj, uint32_t index, HandleValue v, - PropertyOp getter, StrictPropertyOp setter, unsigned attrs) - { - RootedValue tmp(cx, v); - return obj_setElement(cx, obj, index, &tmp, false); - } - - static bool - obj_defineSpecial(JSContext *cx, HandleObject obj, HandleSpecialId sid, HandleValue v, - PropertyOp getter, StrictPropertyOp setter, unsigned attrs) - { - Rooted id(cx, SPECIALID_TO_JSID(sid)); - return obj_defineGeneric(cx, obj, id, v, getter, setter, attrs); - } - - static bool - obj_deleteProperty(JSContext *cx, HandleObject obj, HandlePropertyName name, bool *succeeded) - { - *succeeded = true; - return true; - } - - static bool - obj_deleteElement(JSContext *cx, HandleObject tarray, uint32_t index, bool *succeeded) - { - if (index < tarray->as().length()) { - *succeeded = false; - return true; - } - - *succeeded = true; - return true; - } - - static bool - obj_deleteSpecial(JSContext *cx, HandleObject tarray, HandleSpecialId sid, bool *succeeded) - { - *succeeded = true; - return true; - } - - static bool - obj_enumerate(JSContext *cx, HandleObject tarray, JSIterateOp enum_op, - MutableHandleValue statep, MutableHandleId idp) - { - JS_ASSERT(tarray->is()); - - uint32_t index; - switch (enum_op) { - case JSENUMERATE_INIT_ALL: - case JSENUMERATE_INIT: - statep.setInt32(0); - idp.set(::INT_TO_JSID(tarray->as().length())); - break; - - case JSENUMERATE_NEXT: { - index = static_cast(statep.toInt32()); - uint32_t length = tarray->as().length(); - if (index < length) { - idp.set(::INT_TO_JSID(index)); - statep.setInt32(index + 1); - } else { - JS_ASSERT(index == length); - statep.setNull(); - } - break; - } - case JSENUMERATE_DESTROY: - statep.setNull(); - break; - } - - return true; - } - static TypedArrayObject * makeProtoInstance(JSContext *cx, HandleObject proto) { @@ -629,16 +351,9 @@ class TypedArrayObjectTemplate : public TypedArrayObject obj->setSlot(NEXT_VIEW_SLOT, PrivateValue(nullptr)); obj->setSlot(NEXT_BUFFER_SLOT, PrivateValue(UNSET_BUFFER_LINK)); - // Mark the object as non-extensible. We cannot simply call - // obj->preventExtensions() because that has to iterate through all - // properties, and on long arrays that is much too slow. We could - // initialize the length fields to zero to avoid that, but then it - // would just boil down to a slightly slower wrapper around the - // following code anyway: js::Shape *empty = EmptyShape::getInitialShape(cx, fastClass(), obj->getProto(), obj->getParent(), obj->getMetadata(), - gc::FINALIZE_OBJECT8_BACKGROUND, - BaseShape::NOT_EXTENSIBLE); + gc::FINALIZE_OBJECT8_BACKGROUND); if (!empty) return nullptr; obj->setLastPropertyInfallible(empty); @@ -1118,7 +833,7 @@ class TypedArrayObjectTemplate : public TypedArrayObject *(static_cast(obj->as().viewData()) + index) = val; } - static void copyIndexToValue(JSObject *tarray, uint32_t index, MutableHandleValue vp); + static Value getIndexValue(JSObject *tarray, uint32_t index); static JSObject * createSubarray(JSContext *cx, HandleObject tarrayArg, uint32_t begin, uint32_t end) @@ -1509,40 +1224,35 @@ ArrayBufferObject::createTypedArrayFromBuffer(JSContext *cx, unsigned argc, Valu // this default implementation is only valid for integer types // less than 32-bits in size. template -void -TypedArrayObjectTemplate::copyIndexToValue(JSObject *tarray, uint32_t index, - MutableHandleValue vp) +Value +TypedArrayObjectTemplate::getIndexValue(JSObject *tarray, uint32_t index) { JS_STATIC_ASSERT(sizeof(NativeType) < 4); - vp.setInt32(getIndex(tarray, index)); + return Int32Value(getIndex(tarray, index)); } namespace { // and we need to specialize for 32-bit integers and floats template<> -void -TypedArrayObjectTemplate::copyIndexToValue(JSObject *tarray, uint32_t index, - MutableHandleValue vp) +Value +TypedArrayObjectTemplate::getIndexValue(JSObject *tarray, uint32_t index) { - int32_t val = getIndex(tarray, index); - vp.setInt32(val); + return Int32Value(getIndex(tarray, index)); } template<> -void -TypedArrayObjectTemplate::copyIndexToValue(JSObject *tarray, uint32_t index, - MutableHandleValue vp) +Value +TypedArrayObjectTemplate::getIndexValue(JSObject *tarray, uint32_t index) { uint32_t val = getIndex(tarray, index); - vp.setNumber(val); + return NumberValue(val); } template<> -void -TypedArrayObjectTemplate::copyIndexToValue(JSObject *tarray, uint32_t index, - MutableHandleValue vp) +Value +TypedArrayObjectTemplate::getIndexValue(JSObject *tarray, uint32_t index) { float val = getIndex(tarray, index); double dval = val; @@ -1557,13 +1267,12 @@ TypedArrayObjectTemplate::copyIndexToValue(JSObject *tarray, uint32_t ind * This could be removed for platforms/compilers known to convert a 32-bit * non-canonical nan to a 64-bit canonical nan. */ - vp.setDouble(CanonicalizeNaN(dval)); + return DoubleValue(CanonicalizeNaN(dval)); } template<> -void -TypedArrayObjectTemplate::copyIndexToValue(JSObject *tarray, uint32_t index, - MutableHandleValue vp) +Value +TypedArrayObjectTemplate::getIndexValue(JSObject *tarray, uint32_t index) { double val = getIndex(tarray, index); @@ -1574,7 +1283,7 @@ TypedArrayObjectTemplate::copyIndexToValue(JSObject *tarray, uint32_t in * confuse the engine into interpreting a double-typed jsval as an * object-typed jsval. */ - vp.setDouble(CanonicalizeNaN(val)); + return DoubleValue(CanonicalizeNaN(val)); } } /* anonymous namespace */ @@ -2228,38 +1937,77 @@ DataViewObject::fun_setFloat64(JSContext *cx, unsigned argc, Value *vp) return CallNonGenericMethod(cx, args); } -void -TypedArrayObject::copyTypedArrayElement(uint32_t index, MutableHandleValue vp) +Value +TypedArrayObject::getElement(uint32_t index) { JS_ASSERT(index < length()); switch (type()) { case ScalarTypeDescr::TYPE_INT8: - TypedArrayObjectTemplate::copyIndexToValue(this, index, vp); + return TypedArrayObjectTemplate::getIndexValue(this, index); break; case ScalarTypeDescr::TYPE_UINT8: - TypedArrayObjectTemplate::copyIndexToValue(this, index, vp); + return TypedArrayObjectTemplate::getIndexValue(this, index); break; case ScalarTypeDescr::TYPE_UINT8_CLAMPED: - TypedArrayObjectTemplate::copyIndexToValue(this, index, vp); + return TypedArrayObjectTemplate::getIndexValue(this, index); break; case ScalarTypeDescr::TYPE_INT16: - TypedArrayObjectTemplate::copyIndexToValue(this, index, vp); + return TypedArrayObjectTemplate::getIndexValue(this, index); break; case ScalarTypeDescr::TYPE_UINT16: - TypedArrayObjectTemplate::copyIndexToValue(this, index, vp); + return TypedArrayObjectTemplate::getIndexValue(this, index); break; case ScalarTypeDescr::TYPE_INT32: - TypedArrayObjectTemplate::copyIndexToValue(this, index, vp); + return TypedArrayObjectTemplate::getIndexValue(this, index); break; case ScalarTypeDescr::TYPE_UINT32: - TypedArrayObjectTemplate::copyIndexToValue(this, index, vp); + return TypedArrayObjectTemplate::getIndexValue(this, index); break; case ScalarTypeDescr::TYPE_FLOAT32: - TypedArrayObjectTemplate::copyIndexToValue(this, index, vp); + return TypedArrayObjectTemplate::getIndexValue(this, index); break; case ScalarTypeDescr::TYPE_FLOAT64: - TypedArrayObjectTemplate::copyIndexToValue(this, index, vp); + return TypedArrayObjectTemplate::getIndexValue(this, index); + break; + default: + MOZ_ASSUME_UNREACHABLE("Unknown TypedArray type"); + break; + } +} + +bool +TypedArrayObject::setElement(ThreadSafeContext *cx, uint32_t index, const Value &value) +{ + JS_ASSERT(index < length()); + + switch (type()) { + case ScalarTypeDescr::TYPE_INT8: + return TypedArrayObjectTemplate::setIndexValue(cx, this, index, value); + break; + case ScalarTypeDescr::TYPE_UINT8: + return TypedArrayObjectTemplate::setIndexValue(cx, this, index, value); + break; + case ScalarTypeDescr::TYPE_UINT8_CLAMPED: + return TypedArrayObjectTemplate::setIndexValue(cx, this, index, value); + break; + case ScalarTypeDescr::TYPE_INT16: + return TypedArrayObjectTemplate::setIndexValue(cx, this, index, value); + break; + case ScalarTypeDescr::TYPE_UINT16: + return TypedArrayObjectTemplate::setIndexValue(cx, this, index, value); + break; + case ScalarTypeDescr::TYPE_INT32: + return TypedArrayObjectTemplate::setIndexValue(cx, this, index, value); + break; + case ScalarTypeDescr::TYPE_UINT32: + return TypedArrayObjectTemplate::setIndexValue(cx, this, index, value); + break; + case ScalarTypeDescr::TYPE_FLOAT32: + return TypedArrayObjectTemplate::setIndexValue(cx, this, index, value); + break; + case ScalarTypeDescr::TYPE_FLOAT64: + return TypedArrayObjectTemplate::setIndexValue(cx, this, index, value); break; default: MOZ_ASSUME_UNREACHABLE("Unknown TypedArray type"); @@ -2376,8 +2124,7 @@ IMPL_TYPED_ARRAY_COMBINED_UNWRAPPERS(Float64, double, double) #_typedArray, \ JSCLASS_HAS_RESERVED_SLOTS(TypedArrayObject::RESERVED_SLOTS) | \ JSCLASS_HAS_PRIVATE | JSCLASS_IMPLEMENTS_BARRIERS | \ - JSCLASS_HAS_CACHED_PROTO(JSProto_##_typedArray) | \ - Class::NON_NATIVE, \ + JSCLASS_HAS_CACHED_PROTO(JSProto_##_typedArray), \ JS_PropertyStub, /* addProperty */ \ JS_DeletePropertyStub, /* delProperty */ \ JS_PropertyStub, /* getProperty */ \ @@ -2390,35 +2137,6 @@ IMPL_TYPED_ARRAY_COMBINED_UNWRAPPERS(Float64, double, double) nullptr, /* hasInstance */ \ nullptr, /* construct */ \ ArrayBufferViewObject::trace, /* trace */ \ - JS_NULL_CLASS_SPEC, \ - JS_NULL_CLASS_EXT, \ - { \ - _typedArray##Object::obj_lookupGeneric, \ - _typedArray##Object::obj_lookupProperty, \ - _typedArray##Object::obj_lookupElement, \ - _typedArray##Object::obj_lookupSpecial, \ - _typedArray##Object::obj_defineGeneric, \ - _typedArray##Object::obj_defineProperty, \ - _typedArray##Object::obj_defineElement, \ - _typedArray##Object::obj_defineSpecial, \ - _typedArray##Object::obj_getGeneric, \ - _typedArray##Object::obj_getProperty, \ - _typedArray##Object::obj_getElement, \ - _typedArray##Object::obj_getSpecial, \ - _typedArray##Object::obj_setGeneric, \ - _typedArray##Object::obj_setProperty, \ - _typedArray##Object::obj_setElement, \ - _typedArray##Object::obj_setSpecial, \ - _typedArray##Object::obj_getGenericAttributes, \ - _typedArray##Object::obj_setGenericAttributes, \ - _typedArray##Object::obj_deleteProperty, \ - _typedArray##Object::obj_deleteElement, \ - _typedArray##Object::obj_deleteSpecial, \ - nullptr, nullptr, /* watch/unwatch */ \ - nullptr, /* slice */ \ - _typedArray##Object::obj_enumerate, \ - nullptr, /* thisObject */ \ - } \ } template @@ -2583,7 +2301,6 @@ const Class DataViewObject::class_ = { "DataView", JSCLASS_HAS_PRIVATE | JSCLASS_IMPLEMENTS_BARRIERS | - /* Bug 886622: Consider making this Class NON_NATIVE. */ JSCLASS_HAS_RESERVED_SLOTS(DataViewObject::RESERVED_SLOTS) | JSCLASS_HAS_CACHED_PROTO(JSProto_DataView), JS_PropertyStub, /* addProperty */ @@ -2782,6 +2499,58 @@ js::AsTypedArrayBuffer(HandleValue v) return v.toObject().as(); } +bool +js::StringIsTypedArrayIndex(JSLinearString *str, double *indexp) +{ + // Largest double (2^53 - 1) which can be exactly represented in the + // mantissa of a double. + static const double MAX_INTEGER = 9007199254740991; + + const jschar *s = str->chars(); + const jschar *end = s + str->length(); + + if (s == end) + return false; + + bool negative = false; + if (*s == '-') { + negative = true; + if (++s == end) + return false; + } + + if (!JS7_ISDEC(*s)) + return false; + + double index = 0; + uint32_t digit = JS7_UNDEC(*s++); + + /* Don't allow leading zeros. */ + if (digit == 0 && s != end) + return false; + + index = digit; + + for (; s < end; s++) { + if (!JS7_ISDEC(*s)) + return false; + + digit = JS7_UNDEC(*s); + + /* Watch for mantissa overflows. */ + if ((MAX_INTEGER - digit) / 10 < index) + return false; + + index = 10 * index + digit; + } + + if (negative) + index = -index; + + *indexp = index; + return true; +} + /* JS Friend API */ JS_FRIEND_API(bool) diff --git a/js/src/vm/TypedArrayObject.h b/js/src/vm/TypedArrayObject.h index 79daa3dd415..bb7fb999b54 100644 --- a/js/src/vm/TypedArrayObject.h +++ b/js/src/vm/TypedArrayObject.h @@ -40,20 +40,6 @@ class TypedArrayObject : public ArrayBufferViewObject static const Class classes[ScalarTypeDescr::TYPE_MAX]; static const Class protoClasses[ScalarTypeDescr::TYPE_MAX]; - static bool obj_lookupGeneric(JSContext *cx, HandleObject obj, HandleId id, - MutableHandleObject objp, MutableHandleShape propp); - static bool obj_lookupProperty(JSContext *cx, HandleObject obj, HandlePropertyName name, - MutableHandleObject objp, MutableHandleShape propp); - static bool obj_lookupElement(JSContext *cx, HandleObject obj, uint32_t index, - MutableHandleObject objp, MutableHandleShape propp); - static bool obj_lookupSpecial(JSContext *cx, HandleObject obj, HandleSpecialId sid, - MutableHandleObject objp, MutableHandleShape propp); - - static bool obj_getGenericAttributes(JSContext *cx, HandleObject obj, - HandleId id, unsigned *attrsp); - static bool obj_setGenericAttributes(JSContext *cx, HandleObject obj, - HandleId id, unsigned *attrsp); - static Value bufferValue(TypedArrayObject *tarr) { return tarr->getFixedSlot(BUFFER_SLOT); } @@ -92,7 +78,8 @@ class TypedArrayObject : public ArrayBufferViewObject } inline bool isArrayIndex(jsid id, uint32_t *ip = nullptr); - void copyTypedArrayElement(uint32_t index, MutableHandleValue vp); + Value getElement(uint32_t index); + bool setElement(ThreadSafeContext *cx, uint32_t index, const Value &value); void neuter(JSContext *cx); @@ -153,6 +140,25 @@ IsTypedArrayBuffer(HandleValue v); ArrayBufferObject & AsTypedArrayBuffer(HandleValue v); +bool +StringIsTypedArrayIndex(JSLinearString *str, double *indexp); + +inline bool +IsTypedArrayIndex(jsid id, double *indexp) +{ + if (JSID_IS_INT(id)) { + int32_t i = JSID_TO_INT(id); + JS_ASSERT(i >= 0); + *indexp = (double)i; + return true; + } + + if (MOZ_UNLIKELY(!JSID_IS_STRING(id))) + return false; + + return StringIsTypedArrayIndex(JSID_TO_ATOM(id), indexp); +} + static inline unsigned TypedArrayShift(ArrayBufferView::ViewType viewType) { @@ -322,8 +328,6 @@ ClampIntForUint8Array(int32_t x) return x; } -bool ToDoubleForTypedArray(JSContext *cx, JS::HandleValue vp, double *d); - extern js::ArrayBufferObject * const UNSET_BUFFER_LINK; } // namespace js From ab53fb2f5f3af582184a380d8702f25963c88c27 Mon Sep 17 00:00:00 2001 From: Marco Bonardo Date: Tue, 4 Mar 2014 21:44:21 +0100 Subject: [PATCH 005/112] Bug 435851 - dragging a folder shortcut drags the concrete folder instead. r=mano --- .../components/places/content/controller.js | 73 +++++++---- .../places/content/editBookmarkOverlay.js | 2 + browser/components/places/content/places.js | 4 +- browser/components/places/content/tree.xml | 20 ++- browser/components/places/content/treeView.js | 13 +- .../places/tests/browser/browser.ini | 1 + .../browser/browser_435851_copy_query.js | 59 +++++++++ .../browser/browser_bookmarksProperties.js | 4 + .../components/places/tests/browser/head.js | 40 ++++++ .../components/places/tests/chrome/chrome.ini | 1 + .../test_selectItems_on_nested_tree.xul | 66 ++++++++++ .../components/places/BookmarkJSONUtils.jsm | 110 ++++------------ toolkit/components/places/PlacesUtils.jsm | 46 +++---- .../test_423515_forceCopyShortcuts.js | 122 ------------------ .../places/tests/bookmarks/xpcshell.ini | 1 - 15 files changed, 284 insertions(+), 278 deletions(-) create mode 100644 browser/components/places/tests/browser/browser_435851_copy_query.js create mode 100644 browser/components/places/tests/chrome/test_selectItems_on_nested_tree.xul delete mode 100644 toolkit/components/places/tests/bookmarks/test_423515_forceCopyShortcuts.js diff --git a/browser/components/places/content/controller.js b/browser/components/places/content/controller.js index 262fe8b105a..9f31db66faa 100644 --- a/browser/components/places/content/controller.js +++ b/browser/components/places/content/controller.js @@ -291,8 +291,8 @@ PlacesController.prototype = { * @param aIsMoveCommand * True if the command for which this method is called only moves the * selected items to another container, false otherwise. - * @returns true if all nodes in the selection can be removed, - * false otherwise. + * @return true if all nodes in the selection can be removed, + * false otherwise. */ _hasRemovableSelection: function PC__hasRemovableSelection(aIsMoveCommand) { var ranges = this._view.removableSelectionRanges; @@ -356,9 +356,9 @@ PlacesController.prototype = { * Looks at the data on the clipboard to see if it is paste-able. * Paste-able data is: * - in a format that the view can receive - * @returns true if: - clipboard data is of a TYPE_X_MOZ_PLACE_* flavor, - - clipboard data is of type TEXT_UNICODE and - is a valid URI. + * @return true if: - clipboard data is of a TYPE_X_MOZ_PLACE_* flavor, + * - clipboard data is of type TEXT_UNICODE and + * is a valid URI. */ _isClipboardDataPasteable: function PC__isClipboardDataPasteable() { // if the clipboard contains TYPE_X_MOZ_PLACE_* data, it is definitely @@ -413,10 +413,10 @@ PlacesController.prototype = { * "separator" node is a separator line * "host" node is a host * - * @returns an array of objects corresponding the selected nodes. Each - * object has each of the properties above set if its corresponding - * node matches the rule. In addition, the annotations names for each - * node are set on its corresponding object as properties. + * @return an array of objects corresponding the selected nodes. Each + * object has each of the properties above set if its corresponding + * node matches the rule. In addition, the annotations names for each + * node are set on its corresponding object as properties. * Notes: * 1) This can be slow, so don't call it anywhere performance critical! * 2) A single-object array corresponding the root node is returned if @@ -503,8 +503,8 @@ PlacesController.prototype = { * the context menu item * @param aMetaData * meta data about the selection - * @returns true if the conditions (see buildContextMenu) are satisfied - * and the item can be displayed, false otherwise. + * @return true if the conditions (see buildContextMenu) are satisfied + * and the item can be displayed, false otherwise. */ _shouldShowMenuItem: function PC__shouldShowMenuItem(aMenuItem, aMetaData) { var selectiontype = aMenuItem.getAttribute("selectiontype"); @@ -782,7 +782,7 @@ PlacesController.prototype = { * Node to check for containment. * @param pastFolders * List of folders the calling function has already traversed - * @returns true if the node should be skipped, false otherwise. + * @return true if the node should be skipped, false otherwise. */ _shouldSkipNode: function PC_shouldSkipNode(node, pastFolders) { /** @@ -791,7 +791,7 @@ PlacesController.prototype = { * The node to check for containment for * @param parent * The parent container to check for containment in - * @returns true if node is a member of parent's children, false otherwise. + * @return true if node is a member of parent's children, false otherwise. */ function isContainedBy(node, parent) { var cursor = node.parent; @@ -1008,7 +1008,6 @@ PlacesController.prototype = { */ setDataTransfer: function PC_setDataTransfer(aEvent) { let dt = aEvent.dataTransfer; - let doCopy = ["copyLink", "copy", "link"].indexOf(dt.effectAllowed) != -1; let result = this._view.result; let didSuppressNotifications = result.suppressNotifications; @@ -1016,7 +1015,7 @@ PlacesController.prototype = { result.suppressNotifications = true; function addData(type, index, overrideURI) { - let wrapNode = PlacesUtils.wrapNode(node, type, overrideURI, doCopy); + let wrapNode = PlacesUtils.wrapNode(node, type, overrideURI); dt.mozSetDataAt(type, wrapNode, index); } @@ -1116,11 +1115,10 @@ PlacesController.prototype = { let livemarkInfo = this.getCachedLivemarkInfo(node); let overrideURI = livemarkInfo ? livemarkInfo.feedURI.spec : null; - let resolveShortcuts = !PlacesControllerDragHelper.canMoveNode(node); contents.forEach(function (content) { content.entries.push( - PlacesUtils.wrapNode(node, content.type, overrideURI, resolveShortcuts) + PlacesUtils.wrapNode(node, content.type, overrideURI) ); }); }, this); @@ -1262,6 +1260,13 @@ PlacesController.prototype = { if (ip.index != PlacesUtils.bookmarks.DEFAULT_INDEX) insertionIndex = ip.index + i; + // If this is not a copy, check for safety that we can move the source, + // otherwise report an error and fallback to a copy. + if (action != "copy" && !PlacesControllerDragHelper.canMoveUnwrappedNode(items[i])) { + Components.utils.reportError("Tried to move an unmovable Places node, " + + "reverting to a copy operation."); + action = "copy"; + } transactions.push( PlacesUIUtils.makeTransaction(items[i], type, ip.itemId, insertionIndex, action == "copy") @@ -1304,7 +1309,7 @@ PlacesController.prototype = { * @param aNode * a places result node. * @return true if there's a cached mozILivemarkInfo object for - * aNode, false otherwise. + * aNode, false otherwise. */ hasCachedLivemarkInfo: function PC_hasCachedLivemarkInfo(aNode) this._cachedLivemarkInfoObjects.has(aNode), @@ -1338,8 +1343,8 @@ let PlacesControllerDragHelper = { * mouse is dragging over one of its submenus * @param node * The container node - * @returns true if the user is dragging over a node within the hierarchy of - * the container, false otherwise. + * @return true if the user is dragging over a node within the hierarchy of + * the container, false otherwise. */ draggingOverChildNode: function PCDH_draggingOverChildNode(node) { let currentNode = this.currentDropTarget; @@ -1352,7 +1357,7 @@ let PlacesControllerDragHelper = { }, /** - * @returns The current active drag session. Returns null if there is none. + * @return The current active drag session. Returns null if there is none. */ getSession: function PCDH__getSession() { return this.dragService.getCurrentSession(); @@ -1438,13 +1443,28 @@ let PlacesControllerDragHelper = { return true; }, + /** + * Determines if an unwrapped node can be moved. + * + * @param aUnwrappedNode + * A node unwrapped by PlacesUtils.unwrapNodes(). + * @return True if the node can be moved, false otherwise. + */ + canMoveUnwrappedNode: function (aUnwrappedNode) { + return aUnwrappedNode.id > 0 && + !PlacesUtils.isRootItem(aUnwrappedNode.id) && + aUnwrappedNode.parent != PlacesUtils.placesRootId && + aUnwrappedNode.parent != PlacesUtils.tagsFolderId && + aUnwrappedNode.grandParentId != PlacesUtils.tagsFolderId && + !aUnwrappedNode.parentReadOnly; + }, /** * Determines if a node can be moved. * * @param aNode * A nsINavHistoryResultNode node. - * @returns True if the node can be moved, false otherwise. + * @return True if the node can be moved, false otherwise. */ canMoveNode: function PCDH_canMoveNode(aNode) { @@ -1478,7 +1498,7 @@ let PlacesControllerDragHelper = { * A bookmark folder id. * @param [optional] aParentId * The parent id of the folder. - * @returns True if the container can be moved to the target. + * @return True if the container can be moved to the target. */ canMoveContainer: function PCDH_canMoveContainer(aId, aParentId) { @@ -1555,6 +1575,13 @@ let PlacesControllerDragHelper = { transactions.push(tagTxn); } else { + // If this is not a copy, check for safety that we can move the source, + // otherwise report an error and fallback to a copy. + if (!doCopy && !PlacesControllerDragHelper.canMoveUnwrappedNode(unwrapped)) { + Components.utils.reportError("Tried to move an unmovable Places node, " + + "reverting to a copy operation."); + doCopy = true; + } transactions.push(PlacesUIUtils.makeTransaction(unwrapped, flavor, insertionPoint.itemId, index, doCopy)); diff --git a/browser/components/places/content/editBookmarkOverlay.js b/browser/components/places/content/editBookmarkOverlay.js index 03f71ac5fa1..e1105df3766 100644 --- a/browser/components/places/content/editBookmarkOverlay.js +++ b/browser/components/places/content/editBookmarkOverlay.js @@ -857,6 +857,8 @@ var gEditItemOverlay = { var txn = new PlacesCreateFolderTransaction(defaultLabel, ip.itemId, ip.index); PlacesUtils.transactionManager.doTransaction(txn); this._folderTree.focus(); + this._folderTree.selectItems([ip.itemId]); + PlacesUtils.asContainer(this._folderTree.selectedNode).containerOpen = true; this._folderTree.selectItems([this._lastNewItem]); this._folderTree.startEditing(this._folderTree.view.selection.currentIndex, this._folderTree.columns.getFirstColumn()); diff --git a/browser/components/places/content/places.js b/browser/components/places/content/places.js index 704014fde33..bcfca1391ad 100644 --- a/browser/components/places/content/places.js +++ b/browser/components/places/content/places.js @@ -62,7 +62,7 @@ var PlacesOrganizer = { for (let container of hierarchy) { switch (typeof container) { case "number": - this._places.selectItems([container]); + this._places.selectItems([container], false); break; case "string": if (container.substr(0, 6) == "place:") @@ -327,7 +327,7 @@ var PlacesOrganizer = { openFlatContainer: function PO_openFlatContainerFlatContainer(aContainer) { if (aContainer.itemId != -1) - this._places.selectItems([aContainer.itemId]); + this._places.selectItems([aContainer.itemId], false); else if (PlacesUtils.nodeIsQuery(aContainer)) this._places.selectPlaceURI(aContainer.uri); }, diff --git a/browser/components/places/content/tree.xml b/browser/components/places/content/tree.xml index 94e48b5569d..6ec5420cddf 100644 --- a/browser/components/places/content/tree.xml +++ b/browser/components/places/content/tree.xml @@ -45,7 +45,7 @@ @@ -453,8 +453,6 @@ // // If the sole selection is the bookmarks toolbar folder, we insert // into it even if it is not opened - var itemId = - PlacesUtils.getConcreteItemId(resultView.nodeForTreeIndex(max.value)); if (selection.count == 1 && resultView.isContainer(max.value) && !this.flatList) orientation = Ci.nsITreeView.DROP_ON; @@ -546,13 +544,16 @@ deferred.resolve(aLibrary), aLeftPaneRoot); + } + return deferred.promise; +} + +/** + * Waits for a clipboard operation to complete, looking for the expected type. + * + * @see waitForClipboard + * + * @param aPopulateClipboardFn + * Function to populate the clipboard. + * @param aFlavor + * Data flavor to expect. + */ +function promiseClipboard(aPopulateClipboardFn, aFlavor) { + let deferred = Promise.defer(); + waitForClipboard(function (aData) !!aData, + aPopulateClipboardFn, + function () { deferred.resolve(); }, + aFlavor); + return deferred.promise; +} + /** * Waits for completion of a clear history operation, before * proceeding with aCallback. diff --git a/browser/components/places/tests/chrome/chrome.ini b/browser/components/places/tests/chrome/chrome.ini index 31cb5e7c98c..a313e5edd0c 100644 --- a/browser/components/places/tests/chrome/chrome.ini +++ b/browser/components/places/tests/chrome/chrome.ini @@ -9,4 +9,5 @@ support-files = head.js [test_bug549491.xul] [test_bug631374_tags_selector_scroll.xul] [test_editBookmarkOverlay_tags_liveUpdate.xul] +[test_selectItems_on_nested_tree.xul] [test_treeview_date.xul] diff --git a/browser/components/places/tests/chrome/test_selectItems_on_nested_tree.xul b/browser/components/places/tests/chrome/test_selectItems_on_nested_tree.xul new file mode 100644 index 00000000000..28d9598876f --- /dev/null +++ b/browser/components/places/tests/chrome/test_selectItems_on_nested_tree.xul @@ -0,0 +1,66 @@ + + + + + + + + + + + + + + + diff --git a/toolkit/components/places/BookmarkJSONUtils.jsm b/toolkit/components/places/BookmarkJSONUtils.jsm index a76be582072..a52d7f1af6b 100644 --- a/toolkit/components/places/BookmarkJSONUtils.jsm +++ b/toolkit/components/places/BookmarkJSONUtils.jsm @@ -108,29 +108,6 @@ this.BookmarkJSONUtils = Object.freeze({ }); }, - /** - * Takes a JSON-serialized node and inserts it into the db. - * - * @param aData - * The unwrapped data blob of dropped or pasted data. - * @param aContainer - * The container the data was dropped or pasted into - * @param aIndex - * The index within the container the item was dropped or pasted at - * @return {Promise} - * @resolves an array containing of maps of old folder ids to new folder ids, - * and an array of saved search ids that need to be fixed up. - * eg: [[[oldFolder1, newFolder1]], [search1]] - * @rejects JavaScript exception. - */ - importJSONNode: function BJU_importJSONNode(aData, aContainer, aIndex, - aGrandParentId) { - let importer = new BookmarkImporter(); - // Can't make importJSONNode a task until we have made the - // runInBatchMode in BI_importFromJSON to run asynchronously. Bug 890203 - return Promise.resolve(importer.importJSONNode(aData, aContainer, aIndex, aGrandParentId)); - }, - /** * Serializes the given node (and all its descendents) as JSON * and writes the serialization to the given output stream. @@ -141,24 +118,19 @@ this.BookmarkJSONUtils = Object.freeze({ * An nsIOutputStream. NOTE: it only uses the write(str, len) * method of nsIOutputStream. The caller is responsible for * closing the stream. - * @param aIsUICommand - * Boolean - If true, modifies serialization so that each node self-contained. - * For Example, tags are serialized inline with each bookmark. - * @param aResolveShortcuts - * Converts folder shortcuts into actual folders. - * @param aExcludeItems - * An array of item ids that should not be written to the backup. * @return {Promise} * @resolves When node have been serialized and wrote to output stream. * @rejects JavaScript exception. + * + * @note This is likely to go away (bug 970291), so it's suggested to not + * add more uses of it. This is not yet firing a deprecation warning + * cause it still has some internal usage. */ - serializeNodeAsJSONToOutputStream: function BJU_serializeNodeAsJSONToOutputStream( - aNode, aStream, aIsUICommand, aResolveShortcuts, aExcludeItems) { + serializeNodeAsJSONToOutputStream: function (aNode, aStream) { let deferred = Promise.defer(); Services.tm.mainThread.dispatch(function() { try { - BookmarkNode.serializeAsJSONToOutputStream( - aNode, aStream, aIsUICommand, aResolveShortcuts, aExcludeItems); + BookmarkNode.serializeAsJSONToOutputStream(aNode, aStream); deferred.resolve(); } catch (ex) { deferred.reject(ex); @@ -553,26 +525,15 @@ let BookmarkNode = { * An nsIOutputStream. NOTE: it only uses the write(str, len) * method of nsIOutputStream. The caller is responsible for * closing the stream. - * @param aIsUICommand - * Boolean - If true, modifies serialization so that each node self-contained. - * For Example, tags are serialized inline with each bookmark. - * @param aResolveShortcuts - * Converts folder shortcuts into actual folders. - * @param aExcludeItems - * An array of item ids that should not be written to the backup. * @returns Task promise * @resolves the number of serialized uri nodes. */ - serializeAsJSONToOutputStream: function BN_serializeAsJSONToOutputStream( - aNode, aStream, aIsUICommand, aResolveShortcuts, aExcludeItems) { + serializeAsJSONToOutputStream: function (aNode, aStream) { return Task.spawn(function* () { // Serialize to stream let array = []; - let result = yield this._appendConvertedNode(aNode, null, array, - aIsUICommand, - aResolveShortcuts, - aExcludeItems); + let result = yield this._appendConvertedNode(aNode, null, array); if (result.appendedNode) { let jsonString = JSON.stringify(array[0]); aStream.write(jsonString, jsonString.length); @@ -583,8 +544,7 @@ let BookmarkNode = { }.bind(this)); }, - _appendConvertedNode: function BN__appendConvertedNode( - bNode, aIndex, aArray, aIsUICommand, aResolveShortcuts, aExcludeItems) { + _appendConvertedNode: function (bNode, aIndex, aArray) { return Task.spawn(function* () { let node = {}; let nodeCount = 0; @@ -595,7 +555,7 @@ let BookmarkNode = { if (aIndex) node.index = aIndex; - this._addGenericProperties(bNode, node, aResolveShortcuts); + this._addGenericProperties(bNode, node); let parent = bNode.parent; let grandParent = parent ? parent.parent : null; @@ -614,15 +574,14 @@ let BookmarkNode = { return { appendedNode: false, nodeCount: nodeCount }; } - yield this._addURIProperties(bNode, node, aIsUICommand); + yield this._addURIProperties(bNode, node); nodeCount++; } else if (PlacesUtils.nodeIsContainer(bNode)) { // Tag containers accept only uri nodes if (grandParent && grandParent.itemId == PlacesUtils.tagsFolderId) return { appendedNode: false, nodeCount: nodeCount }; - this._addContainerProperties(bNode, node, aIsUICommand, - aResolveShortcuts); + this._addContainerProperties(bNode, node); } else if (PlacesUtils.nodeIsSeparator(bNode)) { // Tag root accept only folder nodes // Tag containers accept only uri nodes @@ -636,10 +595,7 @@ let BookmarkNode = { if (!node.feedURI && node.type == PlacesUtils.TYPE_X_MOZ_PLACE_CONTAINER) { nodeCount += yield this._appendConvertedComplexNode(node, bNode, - aArray, - aIsUICommand, - aResolveShortcuts, - aExcludeItems) + aArray) return { appendedNode: true, nodeCount: nodeCount }; } @@ -648,8 +604,7 @@ let BookmarkNode = { }.bind(this)); }, - _addGenericProperties: function BN__addGenericProperties( - aPlacesNode, aJSNode, aResolveShortcuts) { + _addGenericProperties: function (aPlacesNode, aJSNode) { aJSNode.title = aPlacesNode.title; aJSNode.id = aPlacesNode.itemId; if (aJSNode.id != -1) { @@ -667,17 +622,7 @@ let BookmarkNode = { let annos = []; try { annos = - PlacesUtils.getAnnotationsForItem(aJSNode.id).filter(function(anno) { - // XXX should whitelist this instead, w/ a pref for - // backup/restore of non-whitelisted annos - // XXX causes JSON encoding errors, so utf-8 encode - // anno.value = unescape(encodeURIComponent(anno.value)); - if (anno.name == PlacesUtils.READ_ONLY_ANNO && aResolveShortcuts) { - // When copying a read-only node, remove the read-only annotation. - return false; - } - return true; - }); + PlacesUtils.getAnnotationsForItem(aJSNode.id); } catch(ex) {} if (annos.length != 0) aJSNode.annos = annos; @@ -686,7 +631,7 @@ let BookmarkNode = { }, _addURIProperties: function BN__addURIProperties( - aPlacesNode, aJSNode, aIsUICommand) { + aPlacesNode, aJSNode) { return Task.spawn(function() { aJSNode.type = PlacesUtils.TYPE_X_MOZ_PLACE; aJSNode.uri = aPlacesNode.uri; @@ -697,9 +642,8 @@ let BookmarkNode = { aJSNode.keyword = keyword; } - let tags = aIsUICommand ? aPlacesNode.tags : null; - if (tags) - aJSNode.tags = tags; + if (aPlacesNode.tags) + aJSNode.tags = aPlacesNode.tags; // Last character-set let uri = NetUtil.newURI(aPlacesNode.uri); @@ -715,17 +659,15 @@ let BookmarkNode = { }, _addContainerProperties: function BN__addContainerProperties( - aPlacesNode, aJSNode, aIsUICommand, aResolveShortcuts) { + aPlacesNode, aJSNode) { let concreteId = PlacesUtils.getConcreteItemId(aPlacesNode); if (concreteId != -1) { // This is a bookmark or a tag container. if (PlacesUtils.nodeIsQuery(aPlacesNode) || - (concreteId != aPlacesNode.itemId && !aResolveShortcuts)) { + concreteId != aPlacesNode.itemId) { aJSNode.type = PlacesUtils.TYPE_X_MOZ_PLACE; aJSNode.uri = aPlacesNode.uri; - // Folder shortcut - if (aIsUICommand) - aJSNode.concreteId = concreteId; + aJSNode.concreteId = concreteId; } else { // Bookmark folder or a shortcut we should convert to folder. aJSNode.type = PlacesUtils.TYPE_X_MOZ_PLACE_CONTAINER; @@ -749,9 +691,7 @@ let BookmarkNode = { } }, - _appendConvertedComplexNode: function BN__appendConvertedComplexNode( - aNode, aSourceNode, aArray, aIsUICommand, aResolveShortcuts, - aExcludeItems) { + _appendConvertedComplexNode: function (aNode, aSourceNode, aArray) { return Task.spawn(function* () { let repr = {}; let nodeCount = 0; @@ -770,11 +710,7 @@ let BookmarkNode = { let cc = aSourceNode.childCount; for (let i = 0; i < cc; ++i) { let childNode = aSourceNode.getChild(i); - if (aExcludeItems && aExcludeItems.indexOf(childNode.itemId) != -1) - continue; - let result = yield this._appendConvertedNode(aSourceNode.getChild(i), i, children, - aIsUICommand, aResolveShortcuts, - aExcludeItems); + let result = yield this._appendConvertedNode(aSourceNode.getChild(i), i, children); nodeCount += result.nodeCount; } if (!wasOpen) diff --git a/toolkit/components/places/PlacesUtils.jsm b/toolkit/components/places/PlacesUtils.jsm index dde9b524d5a..b8055135b67 100644 --- a/toolkit/components/places/PlacesUtils.jsm +++ b/toolkit/components/places/PlacesUtils.jsm @@ -478,11 +478,9 @@ this.PlacesUtils = { * Used instead of the node's URI if provided. * This is useful for wrapping a container as TYPE_X_MOZ_URL, * TYPE_HTML or TYPE_UNICODE. - * @param aForceCopy - * Does a full copy, resolving folder shortcuts. - * @returns A string serialization of the node + * @return A string serialization of the node */ - wrapNode: function PU_wrapNode(aNode, aType, aOverrideURI, aForceCopy) { + wrapNode: function PU_wrapNode(aNode, aType, aOverrideURI) { // when wrapping a node, we want all the items, even if the original // query options are excluding them. // this can happen when copying from the left hand pane of the bookmarks @@ -490,9 +488,9 @@ this.PlacesUtils = { // @return [node, shouldClose] function convertNode(cNode) { if (PlacesUtils.nodeIsFolder(cNode) && + cNode.type != Ci.nsINavHistoryResultNode.RESULT_TYPE_FOLDER_SHORTCUT && asQuery(cNode).queryOptions.excludeItems) { - let concreteId = PlacesUtils.getConcreteItemId(cNode); - return [PlacesUtils.getFolderContents(concreteId, false, true).root, true]; + return [PlacesUtils.getFolderContents(cNode.itemId, false, true).root, true]; } // If we didn't create our own query, do not alter the node's open state. @@ -530,7 +528,7 @@ this.PlacesUtils = { }; let [node, shouldClose] = convertNode(aNode); - this._serializeNodeAsJSONToOutputStream(node, writer, true, aForceCopy); + this._serializeNodeAsJSONToOutputStream(node, writer); if (shouldClose) node.containerOpen = false; @@ -1109,25 +1107,17 @@ this.PlacesUtils = { * An nsIOutputStream. NOTE: it only uses the write(str, len) * method of nsIOutputStream. The caller is responsible for * closing the stream. - * @param aIsUICommand - * Boolean - If true, modifies serialization so that each node self-contained. - * For Example, tags are serialized inline with each bookmark. - * @param aResolveShortcuts - * Converts folder shortcuts into actual folders. - * @param aExcludeItems - * An array of item ids that should not be written to the backup. */ - _serializeNodeAsJSONToOutputStream: - function PU__serializeNodeAsJSONToOutputStream(aNode, aStream, aIsUICommand, - aResolveShortcuts, - aExcludeItems) { + _serializeNodeAsJSONToOutputStream: function (aNode, aStream) { function addGenericProperties(aPlacesNode, aJSNode) { aJSNode.title = aPlacesNode.title; aJSNode.id = aPlacesNode.itemId; if (aJSNode.id != -1) { var parent = aPlacesNode.parent; - if (parent) + if (parent) { aJSNode.parent = parent.itemId; + aJSNode.parentReadOnly = PlacesUtils.nodeIsReadOnly(parent); + } var dateAdded = aPlacesNode.dateAdded; if (dateAdded) aJSNode.dateAdded = dateAdded; @@ -1145,10 +1135,6 @@ this.PlacesUtils = { //anno.value = unescape(encodeURIComponent(anno.value)); if (anno.name == PlacesUtils.LMANNO_FEEDURI) aJSNode.livemark = 1; - if (anno.name == PlacesUtils.READ_ONLY_ANNO && aResolveShortcuts) { - // When copying a read-only node, remove the read-only annotation. - return false; - } return true; }); } catch(ex) {} @@ -1168,9 +1154,8 @@ this.PlacesUtils = { aJSNode.keyword = keyword; } - var tags = aIsUICommand ? aPlacesNode.tags : null; - if (tags) - aJSNode.tags = tags; + if (aPlacesNode.tags) + aJSNode.tags = aPlacesNode.tags; // last character-set var uri = PlacesUtils._uri(aPlacesNode.uri); @@ -1190,12 +1175,11 @@ this.PlacesUtils = { if (concreteId != -1) { // This is a bookmark or a tag container. if (PlacesUtils.nodeIsQuery(aPlacesNode) || - (concreteId != aPlacesNode.itemId && !aResolveShortcuts)) { + concreteId != aPlacesNode.itemId) { aJSNode.type = PlacesUtils.TYPE_X_MOZ_PLACE; aJSNode.uri = aPlacesNode.uri; // folder shortcut - if (aIsUICommand) - aJSNode.concreteId = concreteId; + aJSNode.concreteId = concreteId; } else { // Bookmark folder or a shortcut we should convert to folder. aJSNode.type = PlacesUtils.TYPE_X_MOZ_PLACE_CONTAINER; @@ -1236,8 +1220,6 @@ this.PlacesUtils = { var cc = aSourceNode.childCount; for (var i = 0; i < cc; ++i) { var childNode = aSourceNode.getChild(i); - if (aExcludeItems && aExcludeItems.indexOf(childNode.itemId) != -1) - continue; appendConvertedNode(aSourceNode.getChild(i), i, children); } if (!wasOpen) @@ -1261,6 +1243,8 @@ this.PlacesUtils = { var parent = bNode.parent; var grandParent = parent ? parent.parent : null; + if (grandParent) + node.grandParentId = grandParent.itemId; if (PlacesUtils.nodeIsURI(bNode)) { // Tag root accept only folder nodes diff --git a/toolkit/components/places/tests/bookmarks/test_423515_forceCopyShortcuts.js b/toolkit/components/places/tests/bookmarks/test_423515_forceCopyShortcuts.js deleted file mode 100644 index 58c8a535e2b..00000000000 --- a/toolkit/components/places/tests/bookmarks/test_423515_forceCopyShortcuts.js +++ /dev/null @@ -1,122 +0,0 @@ -/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim:set ts=2 sw=2 sts=2 et: */ -/* 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/. */ - -const DEFAULT_INDEX = PlacesUtils.bookmarks.DEFAULT_INDEX; - -function run_test() { - run_next_test(); -} - -add_task(function test_force_copy() { - /* - - create folder A - - add a bookmark to it - - create a bookmark that's a place: folder shortcut to the new folder - - serialize it to JSON, forcing copy - - import JSON - - confirm that the newly imported folder is a full copy and not a shortcut - */ - - var folderA = - PlacesUtils.bookmarks.createFolder(PlacesUtils.toolbarFolderId, - "test folder", DEFAULT_INDEX); - var bookmarkURI = uri("http://test"); - PlacesUtils.bookmarks.insertBookmark(folderA, bookmarkURI, - DEFAULT_INDEX, ""); - - // create the query - var queryURI = uri("place:folder=" + folderA); - var queryTitle = "test query"; - var queryId = - PlacesUtils.bookmarks.insertBookmark(PlacesUtils.toolbarFolderId, - queryURI, DEFAULT_INDEX, queryTitle); - LOG("queryId: " + queryId); - - // create a query that's *not* a folder shortcut - var queryURI2 = uri("place:"); - var queryTitle2 = "non-folder test query"; - var queryId2 = - PlacesUtils.bookmarks.insertBookmark(PlacesUtils.toolbarFolderId, - queryURI2, DEFAULT_INDEX, queryTitle2); - - // check default state - var query = PlacesUtils.history.getNewQuery(); - query.setFolders([PlacesUtils.toolbarFolderId], 1); - var options = PlacesUtils.history.getNewQueryOptions(); - options.expandQueries = true; - var result = PlacesUtils.history.executeQuery(query, options); - var root = result.root; - root.containerOpen = true; - - // check folder query node - var queryNode = root.getChild(root.childCount-2); - do_check_eq(queryNode.type, queryNode.RESULT_TYPE_FOLDER_SHORTCUT); - do_check_eq(queryNode.title, queryTitle); - do_check_true(queryURI.equals(uri(queryNode.uri))); - queryNode.QueryInterface(Ci.nsINavHistoryContainerResultNode); - queryNode.containerOpen = true; - do_check_eq(queryNode.childCount, 1); - var bookmark = queryNode.getChild(0); - do_check_true(bookmarkURI.equals(uri(bookmark.uri))); - queryNode.containerOpen = false; - - // check non-folder query node - var queryNode2 = root.getChild(root.childCount-1); - do_check_eq(queryNode2.type, queryNode2.RESULT_TYPE_QUERY); - do_check_eq(queryNode2.title, queryTitle2); - do_check_true(queryURI2.equals(uri(queryNode2.uri))); - queryNode2.QueryInterface(Ci.nsINavHistoryContainerResultNode); - queryNode2.containerOpen = true; - do_check_eq(queryNode2.childCount, 0); - queryNode2.containerOpen = false; - - // clean up - root.containerOpen = false; - - // serialize - var stream = { - _str: "", - write: function(aData, aLen) { - this._str += aData; - } - }; - Cu.import("resource://gre/modules/BookmarkJSONUtils.jsm"); - yield BookmarkJSONUtils.serializeNodeAsJSONToOutputStream(queryNode, stream, false, true); - - LOG("SERIALIZED: " + stream._str); - - PlacesUtils.bookmarks.removeItem(queryId); - - // import - yield BookmarkJSONUtils.importJSONNode(stream._str, PlacesUtils.toolbarFolderId, -1); - - // query for node - var query = PlacesUtils.history.getNewQuery(); - query.setFolders([PlacesUtils.toolbarFolderId], 1); - var options = PlacesUtils.history.getNewQueryOptions(); - var result = PlacesUtils.history.executeQuery(query, options); - var root = result.root; - root.containerOpen = true; - - // check folder node (no longer shortcut) - var queryNode = root.getChild(root.childCount-2); - do_check_eq(queryNode.type, queryNode.RESULT_TYPE_FOLDER); - queryNode.QueryInterface(Ci.nsINavHistoryContainerResultNode); - queryNode.containerOpen = true; - do_check_eq(queryNode.childCount, 1); - var child = queryNode.getChild(0); - do_check_true(bookmarkURI.equals(uri(child.uri))); - queryNode.containerOpen = false; - - var queryNode2 = root.getChild(root.childCount-1); - do_check_eq(queryNode2.type, queryNode2.RESULT_TYPE_QUERY); - queryNode2.QueryInterface(Ci.nsINavHistoryContainerResultNode); - queryNode2.containerOpen = true; - do_check_eq(queryNode2.childCount, 0); - queryNode.containerOpen = false; - - root.containerOpen = false; -}); diff --git a/toolkit/components/places/tests/bookmarks/xpcshell.ini b/toolkit/components/places/tests/bookmarks/xpcshell.ini index 0eb1386d6c2..55563d8142a 100644 --- a/toolkit/components/places/tests/bookmarks/xpcshell.ini +++ b/toolkit/components/places/tests/bookmarks/xpcshell.ini @@ -11,7 +11,6 @@ tail = [test_405938_restore_queries.js] [test_417228-exclude-from-backup.js] [test_417228-other-roots.js] -[test_423515_forceCopyShortcuts.js] [test_424958-json-quoted-folders.js] [test_448584.js] [test_458683.js] From 5d770b192279cf2d7ca67628de729e07c017617f Mon Sep 17 00:00:00 2001 From: Terrence Cole Date: Tue, 4 Mar 2014 11:55:45 -0800 Subject: [PATCH 006/112] Bug 978353 - Do not embed nursery allocated ArrayBuffer elements in code; r=bhackett --HG-- extra : rebase_source : 781b3b4df0377d5bb04917909394f142543d0e15 --- js/src/jit-test/tests/gc/bug-978353.js | 6 ++++++ js/src/jit/IonBuilder.cpp | 17 ++++++++++------- 2 files changed, 16 insertions(+), 7 deletions(-) create mode 100644 js/src/jit-test/tests/gc/bug-978353.js diff --git a/js/src/jit-test/tests/gc/bug-978353.js b/js/src/jit-test/tests/gc/bug-978353.js new file mode 100644 index 00000000000..44635209feb --- /dev/null +++ b/js/src/jit-test/tests/gc/bug-978353.js @@ -0,0 +1,6 @@ +var arr = new Float64Array(2); +function test(m) { + arr[1] = m; +} +for(var i=0; i<20000; ++i, Array('x')) + test(0); diff --git a/js/src/jit/IonBuilder.cpp b/js/src/jit/IonBuilder.cpp index 6f1dc05206b..fdd6bf0af0c 100644 --- a/js/src/jit/IonBuilder.cpp +++ b/js/src/jit/IonBuilder.cpp @@ -7175,14 +7175,17 @@ IonBuilder::getTypedArrayElements(MDefinition *obj) if (obj->isConstant() && obj->toConstant()->value().isObject()) { TypedArrayObject *tarr = &obj->toConstant()->value().toObject().as(); void *data = tarr->viewData(); + // Bug 979449 - Optimistically embed the elements and use TI to + // invalidate if we move them. + if (!gc::IsInsideNursery(tarr->runtimeFromMainThread(), data)) { + // The 'data' pointer can change in rare circumstances + // (ArrayBufferObject::changeContents). + types::TypeObjectKey *tarrType = types::TypeObjectKey::get(tarr); + tarrType->watchStateChangeForTypedArrayBuffer(constraints()); - // The 'data' pointer can change in rare circumstances - // (ArrayBufferObject::changeContents). - types::TypeObjectKey *tarrType = types::TypeObjectKey::get(tarr); - tarrType->watchStateChangeForTypedArrayBuffer(constraints()); - - obj->setImplicitlyUsedUnchecked(); - return MConstantElements::New(alloc(), data); + obj->setImplicitlyUsedUnchecked(); + return MConstantElements::New(alloc(), data); + } } return MTypedArrayElements::New(alloc(), obj); } From 4b3ff9a53a9757269516c3fa6a7437bf2600b5ea Mon Sep 17 00:00:00 2001 From: Jonathan Watt Date: Wed, 26 Feb 2014 23:04:31 +0000 Subject: [PATCH 007/112] Bug 976739 - Allow user initiated stepping of when its value is the empty string (even if it is invalid due to the 'required' attribute being present) and step correctly if the value 0 (the default for the empty string) is not on a step. r=smaug --- content/html/content/src/HTMLInputElement.cpp | 40 ++++++++++++++----- content/html/content/src/HTMLInputElement.h | 2 +- .../forms/test_input_number_key_events.html | 34 ++++++++++++++-- 3 files changed, 62 insertions(+), 14 deletions(-) diff --git a/content/html/content/src/HTMLInputElement.cpp b/content/html/content/src/HTMLInputElement.cpp index 38f663c3a25..b05f98bcc91 100644 --- a/content/html/content/src/HTMLInputElement.cpp +++ b/content/html/content/src/HTMLInputElement.cpp @@ -2140,7 +2140,15 @@ HTMLInputElement::GetValueIfStepped(int32_t aStep, return NS_OK; } - if (GetValidityState(VALIDITY_STATE_STEP_MISMATCH) && + // If the current value isn't aligned on a step, then shift the value to the + // nearest step that will cause the addition of aStep steps (further below) + // to |value| to hit the required value. + // (Instead of using GetValidityState(VALIDITY_STATE_STEP_MISMATCH) we have + // to check HasStepMismatch and pass true as its aUseZeroIfValueNaN argument + // since we need to treat the value "" as zero for stepping purposes even + // though we don't suffer from a step mismatch when our value is the empty + // string.) + if (HasStepMismatch(true) && value != minimum && value != maximum) { if (aStep > 0) { value -= NS_floorModulo(value - GetStepBase(), step); @@ -3641,12 +3649,20 @@ HTMLInputElement::StepNumberControlForUserEvent(int32_t aDirection) // want to wipe out what they typed if they try to increment/decrement the // value. Better is to highlight the value as being invalid so that they // can correct what they typed. - // We pass 'true' for UpdateValidityUIBits' aIsFocused argument regardless - // because we need the UI to update _now_ or the user will wonder why the - // step behavior isn't functioning. - UpdateValidityUIBits(true); - UpdateState(true); - return; + // We only do this if there actually is a value typed in by/displayed to + // the user. (IsValid() can return false if the 'required' attribute is + // set and the value is the empty string.) + nsNumberControlFrame* numberControlFrame = + do_QueryFrame(GetPrimaryFrame()); + if (numberControlFrame && + !numberControlFrame->AnonTextControlIsEmpty()) { + // We pass 'true' for UpdateValidityUIBits' aIsFocused argument + // regardless because we need the UI to update _now_ or the user will + // wonder why the step behavior isn't functioning. + UpdateValidityUIBits(true); + UpdateState(true); + return; + } } Decimal newValue = Decimal::nan(); // unchanged if value will not change @@ -6433,7 +6449,7 @@ HTMLInputElement::IsRangeUnderflow() const } bool -HTMLInputElement::HasStepMismatch() const +HTMLInputElement::HasStepMismatch(bool aUseZeroIfValueNaN) const { if (!DoesStepApply()) { return false; @@ -6441,8 +6457,12 @@ HTMLInputElement::HasStepMismatch() const Decimal value = GetValueAsDecimal(); if (value.isNaN()) { - // The element can't suffer from step mismatch if it's value isn't a number. - return false; + if (aUseZeroIfValueNaN) { + value = 0; + } else { + // The element can't suffer from step mismatch if it's value isn't a number. + return false; + } } Decimal step = GetStep(); diff --git a/content/html/content/src/HTMLInputElement.h b/content/html/content/src/HTMLInputElement.h index 6393c1359f1..0648a5d9c08 100644 --- a/content/html/content/src/HTMLInputElement.h +++ b/content/html/content/src/HTMLInputElement.h @@ -256,7 +256,7 @@ public: bool HasPatternMismatch() const; bool IsRangeOverflow() const; bool IsRangeUnderflow() const; - bool HasStepMismatch() const; + bool HasStepMismatch(bool aUseZeroIfValueNaN = false) const; bool HasBadInput() const; void UpdateTooLongValidityState(); void UpdateValueMissingValidityState(); diff --git a/content/html/content/test/forms/test_input_number_key_events.html b/content/html/content/test/forms/test_input_number_key_events.html index 9f9777da8f1..0106039a03d 100644 --- a/content/html/content/test/forms/test_input_number_key_events.html +++ b/content/html/content/test/forms/test_input_number_key_events.html @@ -71,6 +71,18 @@ function getStepBase(element) { Number(element.getAttribute("value") || "NaN") || 0; } +function hasStepMismatch(element) { + var value = element.value; + if (value == "") { + value = 0; + } + var step = getStep(element); + if (step == "any") { + return false; + } + return ((value - getStepBase(element)) % step) != 0; +} + function floorModulo(x, y) { return (x - y * Math.floor(x / y)); } @@ -101,7 +113,7 @@ function expectedValueAfterStepUpOrDown(stepFactor, element) { return value; } - if (element.validity.stepMismatch && + if (hasStepMismatch(element) && value != minimum && value != maximum) { if (stepFactor > 0) { value -= floorModulo(value - getStepBase(element), step); @@ -138,8 +150,8 @@ function test() { var elem = document.getElementById("input"); elem.focus(); - elem.min = -3; - elem.max = 3; + elem.min = -5; + elem.max = 5; elem.step = 2; var defaultValue = 0; var oldVal, expectedVal; @@ -203,6 +215,22 @@ function test() { sendString("abc"); synthesizeKey(key, {}); is(elem.value, "", "Test " + key + " does nothing when the input is invalid"); + + // Test that no value does not block UI initiated stepping: + oldVal = elem.value = ""; + elem.setAttribute("required", "required"); + elem.select(); + expectedVal = expectedValAfterKeyEvent(key, elem); + synthesizeKey(key, {}); + is(elem.value, expectedVal, "Test " + key + " for number control with value set to the empty string and with the 'required' attribute set"); + + // Same again: + expectedVal = expectedValAfterKeyEvent(key, elem); + synthesizeKey(key, {}); + is(elem.value, expectedVal, "Test repeat of " + key + " for number control"); + + // Reset 'required' attribute: + elem.removeAttribute("required"); } } From 7a7fd6fa4067dc7151a992adeb4aa1f38eac24c9 Mon Sep 17 00:00:00 2001 From: Jonathan Watt Date: Thu, 27 Feb 2014 08:41:46 +0000 Subject: [PATCH 008/112] Bug 977310 - Don't update the validity states of HTMLInputElement until the parser has finished creating it. r=smaug --- content/html/content/src/HTMLInputElement.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/content/html/content/src/HTMLInputElement.cpp b/content/html/content/src/HTMLInputElement.cpp index b05f98bcc91..1784e545733 100644 --- a/content/html/content/src/HTMLInputElement.cpp +++ b/content/html/content/src/HTMLInputElement.cpp @@ -2786,7 +2786,7 @@ HTMLInputElement::SetValueInternal(const nsAString& aValue, if (!mParserCreating) { SanitizeValue(value); } - // else SanitizeValue will be called by DoneCreatingElement + // else DoneCreatingElement calls us again once mParserCreating is false if (aSetValueChanged) { SetValueChanged(true); @@ -2811,7 +2811,10 @@ HTMLInputElement::SetValueInternal(const nsAString& aValue, numberControlFrame->SetValueOfAnonTextControl(value); } } - OnValueChanged(!mParserCreating); + if (!mParserCreating) { + OnValueChanged(true); + } + // else DoneCreatingElement calls us again once mParserCreating is false } if (mType == NS_FORM_INPUT_COLOR) { From 3cfed6394428665fdde90009968ef82639108f95 Mon Sep 17 00:00:00 2001 From: Olli Pettay Date: Tue, 4 Mar 2014 23:33:12 +0200 Subject: [PATCH 009/112] Bug 979497, make sure to use the right event type atom throughout CompileEventHandlerInternal, r=jst --- dom/events/nsEventListenerManager.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/dom/events/nsEventListenerManager.cpp b/dom/events/nsEventListenerManager.cpp index 183ca62a0e7..66bb206eb97 100644 --- a/dom/events/nsEventListenerManager.cpp +++ b/dom/events/nsEventListenerManager.cpp @@ -809,7 +809,8 @@ nsEventListenerManager::CompileEventHandlerInternal(nsListenerStruct *aListenerS JS::Rooted scope(cx, listener->GetEventScope()); - nsIAtom* attrName = aListenerStruct->mTypeAtom; + nsCOMPtr typeAtom = aListenerStruct->mTypeAtom; + nsIAtom* attrName = typeAtom; if (aListenerStruct->mHandlerIsString) { // OK, we didn't find an existing compiled event handler. Flag us @@ -850,6 +851,7 @@ nsEventListenerManager::CompileEventHandlerInternal(nsListenerStruct *aListenerS body = &handlerBody; aElement = element; } + aListenerStruct = nullptr; uint32_t lineNo = 0; nsAutoCString url (NS_LITERAL_CSTRING("-moz-evil:lying-event-listener")); @@ -864,7 +866,7 @@ nsEventListenerManager::CompileEventHandlerInternal(nsListenerStruct *aListenerS uint32_t argCount; const char **argNames; nsContentUtils::GetEventArgNames(aElement->GetNameSpaceID(), - aListenerStruct->mTypeAtom, + typeAtom, &argCount, &argNames); JSAutoCompartment ac(cx, context->GetWindowProxy()); @@ -894,11 +896,13 @@ nsEventListenerManager::CompileEventHandlerInternal(nsListenerStruct *aListenerS JS::Rooted handlerFun(cx); result = nsJSUtils::CompileFunction(cx, JS::NullPtr(), options, - nsAtomCString(aListenerStruct->mTypeAtom), + nsAtomCString(typeAtom), argCount, argNames, *body, handlerFun.address()); NS_ENSURE_SUCCESS(result, result); handler = handlerFun; NS_ENSURE_TRUE(handler, NS_ERROR_FAILURE); + } else { + aListenerStruct = nullptr; } if (handler) { @@ -906,7 +910,6 @@ nsEventListenerManager::CompileEventHandlerInternal(nsListenerStruct *aListenerS // Bind it JS::Rooted boundHandler(cx); context->BindCompiledEventHandler(mTarget, scope, handler, &boundHandler); - aListenerStruct = nullptr; // Note - We pass null for aIncumbentGlobal below. We could also pass the // compilation global, but since the handler is guaranteed to be scripted, // there's no need to use an override, since the JS engine will always give From dc81f67e5172eac0bce3d65ccc5be61abc897df5 Mon Sep 17 00:00:00 2001 From: Andrew McCreight Date: Tue, 4 Mar 2014 13:33:44 -0800 Subject: [PATCH 010/112] Bug 978203 - Don't include nsWindowMemoryReporter.h in nsINode.h. r=smaug --- content/base/public/nsIDocument.h | 1 + content/base/public/nsINode.h | 11 +++++++++-- content/base/src/nsDocument.cpp | 1 + content/base/src/nsFrameMessageManager.cpp | 1 + content/svg/content/src/SVGTransform.cpp | 1 + dom/base/nsGlobalWindow.cpp | 1 + dom/base/nsWindowMemoryReporter.h | 7 ------- image/src/SurfaceCache.cpp | 1 + js/xpconnect/src/XPCComponents.cpp | 1 + js/xpconnect/src/xpcprivate.h | 1 + layout/base/nsPresShell.cpp | 1 + layout/xul/nsXULPopupManager.h | 1 + 12 files changed, 19 insertions(+), 9 deletions(-) diff --git a/content/base/public/nsIDocument.h b/content/base/public/nsIDocument.h index 10a2a8d26d0..0ef07f43679 100644 --- a/content/base/public/nsIDocument.h +++ b/content/base/public/nsIDocument.h @@ -19,6 +19,7 @@ #include "nsPIDOMWindow.h" // for use in inline functions #include "nsPropertyTable.h" // for member #include "nsTHashtable.h" // for member +#include "nsWeakReference.h" #include "mozilla/dom/DocumentBinding.h" #include "mozilla/WeakPtr.h" #include "Units.h" diff --git a/content/base/public/nsINode.h b/content/base/public/nsINode.h index ef09fa1f284..ed6618a6ac1 100644 --- a/content/base/public/nsINode.h +++ b/content/base/public/nsINode.h @@ -15,7 +15,6 @@ #include "nsNodeInfoManager.h" // for use in NodePrincipal() #include "nsPropertyTable.h" // for typedefs #include "nsTObserverArray.h" // for member -#include "nsWindowMemoryReporter.h" // for NS_DECL_SIZEOF_EXCLUDING_THIS #include "mozilla/ErrorResult.h" #include "mozilla/MemoryReporting.h" #include "mozilla/dom/EventTarget.h" // for base class @@ -244,13 +243,21 @@ private: // ever passed to Mutated(). enum { eMaxMutations = 300 }; - + // sMutationCount is a global mutation counter which is decreased by one at // every mutation. It is capped at 0 to avoid wrapping. // Its value is always between 0 and 300, inclusive. static uint32_t sMutationCount; }; +// This should be used for any nsINode sub-class that has fields of its own +// that it needs to measure; any sub-class that doesn't use it will inherit +// SizeOfExcludingThis from its super-class. SizeOfIncludingThis() need not be +// defined, it is inherited from nsINode. +// This macro isn't actually specific to nodes, and bug 956400 will move it into MFBT. +#define NS_DECL_SIZEOF_EXCLUDING_THIS \ + virtual size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const; + // Categories of node properties // 0 is global. #define DOM_USER_DATA 1 diff --git a/content/base/src/nsDocument.cpp b/content/base/src/nsDocument.cpp index 1826ac98a72..accae78ae87 100644 --- a/content/base/src/nsDocument.cpp +++ b/content/base/src/nsDocument.cpp @@ -221,6 +221,7 @@ #include "nsIMutableArray.h" #include "nsContentPermissionHelper.h" #include "mozilla/dom/DOMStringList.h" +#include "nsWindowMemoryReporter.h" using namespace mozilla; using namespace mozilla::dom; diff --git a/content/base/src/nsFrameMessageManager.cpp b/content/base/src/nsFrameMessageManager.cpp index df889d57fec..fded1caf70a 100644 --- a/content/base/src/nsFrameMessageManager.cpp +++ b/content/base/src/nsFrameMessageManager.cpp @@ -23,6 +23,7 @@ #include "nsIXULRuntime.h" #include "nsIScriptError.h" #include "nsIConsoleService.h" +#include "nsIMemoryReporter.h" #include "nsIProtocolHandler.h" #include "nsIScriptSecurityManager.h" #include "nsIJSRuntimeService.h" diff --git a/content/svg/content/src/SVGTransform.cpp b/content/svg/content/src/SVGTransform.cpp index a45e1adf66e..53ad781372b 100644 --- a/content/svg/content/src/SVGTransform.cpp +++ b/content/svg/content/src/SVGTransform.cpp @@ -12,6 +12,7 @@ #include "nsError.h" #include "nsSVGAnimatedTransformList.h" #include "nsSVGAttrTearoffTable.h" +#include "mozilla/DebugOnly.h" namespace { const double kRadPerDegree = 2.0 * M_PI / 360.0; diff --git a/dom/base/nsGlobalWindow.cpp b/dom/base/nsGlobalWindow.cpp index 053e14cdb7e..759b2889fdb 100644 --- a/dom/base/nsGlobalWindow.cpp +++ b/dom/base/nsGlobalWindow.cpp @@ -35,6 +35,7 @@ #include "nsIScriptTimeoutHandler.h" #include "nsIController.h" #include "nsScriptNameSpaceManager.h" +#include "nsWindowMemoryReporter.h" // Helper Classes #include "nsJSUtils.h" diff --git a/dom/base/nsWindowMemoryReporter.h b/dom/base/nsWindowMemoryReporter.h index 301497c9910..214b55f2a62 100644 --- a/dom/base/nsWindowMemoryReporter.h +++ b/dom/base/nsWindowMemoryReporter.h @@ -19,13 +19,6 @@ #include "mozilla/TimeStamp.h" #include "nsArenaMemoryStats.h" -// This should be used for any nsINode sub-class that has fields of its own -// that it needs to measure; any sub-class that doesn't use it will inherit -// SizeOfExcludingThis from its super-class. SizeOfIncludingThis() need not be -// defined, it is inherited from nsINode. -#define NS_DECL_SIZEOF_EXCLUDING_THIS \ - virtual size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const; - class nsWindowSizes { #define FOR_EACH_SIZE(macro) \ macro(DOM, mDOMElementNodesSize) \ diff --git a/image/src/SurfaceCache.cpp b/image/src/SurfaceCache.cpp index 972aa78242d..cad2efa2a17 100644 --- a/image/src/SurfaceCache.cpp +++ b/image/src/SurfaceCache.cpp @@ -15,6 +15,7 @@ #include "mozilla/Preferences.h" #include "mozilla/RefPtr.h" #include "mozilla/StaticPtr.h" +#include "nsIMemoryReporter.h" #include "gfx2DGlue.h" #include "gfxASurface.h" #include "gfxPattern.h" // Workaround for flaw in bug 921753 part 2. diff --git a/js/xpconnect/src/XPCComponents.cpp b/js/xpconnect/src/XPCComponents.cpp index d4a0368860c..e595db32d69 100644 --- a/js/xpconnect/src/XPCComponents.cpp +++ b/js/xpconnect/src/XPCComponents.cpp @@ -26,6 +26,7 @@ #include "nsZipArchive.h" #include "nsIDOMFile.h" #include "nsIDOMFileList.h" +#include "nsWindowMemoryReporter.h" using namespace mozilla; using namespace JS; diff --git a/js/xpconnect/src/xpcprivate.h b/js/xpconnect/src/xpcprivate.h index e64433d4963..0c7ebd87d12 100644 --- a/js/xpconnect/src/xpcprivate.h +++ b/js/xpconnect/src/xpcprivate.h @@ -82,6 +82,7 @@ #include "mozilla/GuardObjects.h" #include "mozilla/Maybe.h" #include "mozilla/MemoryReporting.h" +#include "mozilla/TimeStamp.h" #include #include diff --git a/layout/base/nsPresShell.cpp b/layout/base/nsPresShell.cpp index 4bb7e10cbe5..826476fac22 100644 --- a/layout/base/nsPresShell.cpp +++ b/layout/base/nsPresShell.cpp @@ -113,6 +113,7 @@ #include "SVGContentUtils.h" #include "nsSVGEffects.h" #include "SVGFragmentIdentifier.h" +#include "nsArenaMemoryStats.h" #include "nsPerformance.h" #include "nsRefreshDriver.h" diff --git a/layout/xul/nsXULPopupManager.h b/layout/xul/nsXULPopupManager.h index 1273ac667dc..3a325c6a54c 100644 --- a/layout/xul/nsXULPopupManager.h +++ b/layout/xul/nsXULPopupManager.h @@ -17,6 +17,7 @@ #include "nsPoint.h" #include "nsCOMPtr.h" #include "nsTArray.h" +#include "nsIObserver.h" #include "nsITimer.h" #include "nsIReflowCallback.h" #include "nsThreadUtils.h" From feda56aef280beec001039ec587750f5972415d4 Mon Sep 17 00:00:00 2001 From: Olli Pettay Date: Tue, 4 Mar 2014 23:49:02 +0200 Subject: [PATCH 011/112] Bug 979314, fix pointer events pref handling in presshell, r=mccr8 --HG-- extra : rebase_source : 9ce2767a077bfdf623186580d4793b73907e69bd --- layout/base/nsPresShell.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/layout/base/nsPresShell.cpp b/layout/base/nsPresShell.cpp index 826476fac22..34a97136b48 100644 --- a/layout/base/nsPresShell.cpp +++ b/layout/base/nsPresShell.cpp @@ -739,7 +739,7 @@ PresShell::PresShell() addedSynthMouseMove = true; } static bool addedPointerEventEnabled = false; - if (addedPointerEventEnabled) { + if (!addedPointerEventEnabled) { Preferences::AddBoolVarCache(&sPointerEventEnabled, "dom.w3c_pointer_events.enabled", true); addedPointerEventEnabled = true; From 5b63b395f3b3563bdb223f2b9e121109e3c84283 Mon Sep 17 00:00:00 2001 From: Karl Tomlinson Date: Mon, 3 Mar 2014 12:49:45 +1300 Subject: [PATCH 012/112] b=857610 rename DelayProcessor to DelayBuffer r=padenot --HG-- rename : content/media/webaudio/DelayProcessor.cpp => content/media/webaudio/DelayBuffer.cpp rename : content/media/webaudio/DelayProcessor.h => content/media/webaudio/DelayBuffer.h extra : rebase_source : be71a5abbcf067f513fbaf2967745e80383d285f --- .../{DelayProcessor.cpp => DelayBuffer.cpp} | 18 +++++++------- .../{DelayProcessor.h => DelayBuffer.h} | 12 +++++----- content/media/webaudio/DelayNode.cpp | 24 +++++++++---------- content/media/webaudio/blink/HRTFPanner.h | 6 ++--- content/media/webaudio/moz.build | 2 +- 5 files changed, 31 insertions(+), 31 deletions(-) rename content/media/webaudio/{DelayProcessor.cpp => DelayBuffer.cpp} (89%) rename content/media/webaudio/{DelayProcessor.h => DelayBuffer.h} (88%) diff --git a/content/media/webaudio/DelayProcessor.cpp b/content/media/webaudio/DelayBuffer.cpp similarity index 89% rename from content/media/webaudio/DelayProcessor.cpp rename to content/media/webaudio/DelayBuffer.cpp index 3d36e749e5d..6bac31a62d3 100644 --- a/content/media/webaudio/DelayProcessor.cpp +++ b/content/media/webaudio/DelayBuffer.cpp @@ -4,7 +4,7 @@ * 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 "DelayProcessor.h" +#include "DelayBuffer.h" #include "mozilla/PodOperations.h" #include "AudioSegment.h" @@ -12,10 +12,10 @@ namespace mozilla { void -DelayProcessor::Process(const double *aPerFrameDelays, - const float* const* aInputChannels, - float* const* aOutputChannels, - int aChannelCount, int aFramesToProcess) +DelayBuffer::Process(const double *aPerFrameDelays, + const float* const* aInputChannels, + float* const* aOutputChannels, + int aChannelCount, int aFramesToProcess) { if (!EnsureBuffer(aChannelCount)) { for (int channel = 0; channel < aChannelCount; ++channel) { @@ -77,9 +77,9 @@ DelayProcessor::Process(const double *aPerFrameDelays, } void -DelayProcessor::Process(double aDelayFrames, const float* const* aInputChannels, - float* const* aOutputChannels, int aChannelCount, - int aFramesToProcess) +DelayBuffer::Process(double aDelayFrames, const float* const* aInputChannels, + float* const* aOutputChannels, int aChannelCount, + int aFramesToProcess) { const bool firstTime = !mBuffer.Length(); double currentDelay = firstTime ? aDelayFrames : mCurrentDelay; @@ -98,7 +98,7 @@ DelayProcessor::Process(double aDelayFrames, const float* const* aInputChannels, } bool -DelayProcessor::EnsureBuffer(uint32_t aNumberOfChannels) +DelayBuffer::EnsureBuffer(uint32_t aNumberOfChannels) { if (aNumberOfChannels == 0) { return false; diff --git a/content/media/webaudio/DelayProcessor.h b/content/media/webaudio/DelayBuffer.h similarity index 88% rename from content/media/webaudio/DelayProcessor.h rename to content/media/webaudio/DelayBuffer.h index 291b83f3abf..b5a539e1bea 100644 --- a/content/media/webaudio/DelayProcessor.h +++ b/content/media/webaudio/DelayBuffer.h @@ -4,18 +4,18 @@ * 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 DelayProcessor_h_ -#define DelayProcessor_h_ +#ifndef DelayBuffer_h_ +#define DelayBuffer_h_ #include "nsTArray.h" namespace mozilla { -class DelayProcessor { +class DelayBuffer { public: // See WebAudioUtils::ComputeSmoothingRate() for frame to frame exponential // |smoothingRate| multiplier. - DelayProcessor(int aMaxDelayFrames, double aSmoothingRate) + DelayBuffer(int aMaxDelayFrames, double aSmoothingRate) : mSmoothingRate(aSmoothingRate) , mCurrentDelay(0.) , mMaxDelayFrames(aMaxDelayFrames) @@ -38,7 +38,7 @@ public: void Reset() { mBuffer.Clear(); }; int MaxDelayFrames() const { return mMaxDelayFrames; } - int BufferChannelCount() const { return mBuffer.Length(); } + int ChannelCount() const { return mBuffer.Length(); } private: bool EnsureBuffer(uint32_t aNumberOfChannels); @@ -57,4 +57,4 @@ private: } // mozilla -#endif // DelayProcessor_h_ +#endif // DelayBuffer_h_ diff --git a/content/media/webaudio/DelayNode.cpp b/content/media/webaudio/DelayNode.cpp index b54f8b0bcca..92a707f2bcc 100644 --- a/content/media/webaudio/DelayNode.cpp +++ b/content/media/webaudio/DelayNode.cpp @@ -10,7 +10,7 @@ #include "AudioNodeStream.h" #include "AudioDestinationNode.h" #include "WebAudioUtils.h" -#include "DelayProcessor.h" +#include "DelayBuffer.h" #include "PlayingRefChangeHandler.h" namespace mozilla { @@ -37,9 +37,9 @@ public: // Keep the default value in sync with the default value in DelayNode::DelayNode. , mDelay(0.f) // Use a smoothing range of 20ms - , mProcessor(aMaxDelayFrames, - WebAudioUtils::ComputeSmoothingRate(0.02, - mDestination->SampleRate())) + , mBuffer(aMaxDelayFrames, + WebAudioUtils::ComputeSmoothingRate(0.02, + mDestination->SampleRate())) , mLeftOverData(INT32_MIN) { } @@ -81,7 +81,7 @@ public: MOZ_ASSERT(aStream->SampleRate() == mDestination->SampleRate()); const uint32_t numChannels = aInput.IsNull() ? - mProcessor.BufferChannelCount() : + mBuffer.ChannelCount() : aInput.mChannelData.Length(); if (!aInput.IsNull()) { @@ -91,14 +91,14 @@ public: aStream->Graph()-> DispatchToMainThreadAfterStreamStateUpdate(refchanged.forget()); } - mLeftOverData = mProcessor.MaxDelayFrames(); + mLeftOverData = mBuffer.MaxDelayFrames(); } else if (mLeftOverData > 0) { mLeftOverData -= WEBAUDIO_BLOCK_SIZE; } else { if (mLeftOverData != INT32_MIN) { mLeftOverData = INT32_MIN; // Delete our buffered data now we no longer need it - mProcessor.Reset(); + mBuffer.Reset(); nsRefPtr refchanged = new PlayingRefChanged(aStream, PlayingRefChanged::RELEASE); @@ -136,8 +136,8 @@ public: float delayFrames = mDelay.GetValue() * sampleRate; float delayFramesClamped = inCycle ? std::max(static_cast(WEBAUDIO_BLOCK_SIZE), delayFrames) : delayFrames; - mProcessor.Process(delayFramesClamped, inputChannels, outputChannels, - numChannels, WEBAUDIO_BLOCK_SIZE); + mBuffer.Process(delayFramesClamped, inputChannels, outputChannels, + numChannels, WEBAUDIO_BLOCK_SIZE); } else { // Compute the delay values for the duration of the input AudioChunk // If this DelayNode is in a cycle, make sure the delay value is at least @@ -150,15 +150,15 @@ public: delayAtTick; computedDelay[counter] = delayAtTickClamped; } - mProcessor.Process(computedDelay, inputChannels, outputChannels, - numChannels, WEBAUDIO_BLOCK_SIZE); + mBuffer.Process(computedDelay, inputChannels, outputChannels, + numChannels, WEBAUDIO_BLOCK_SIZE); } } AudioNodeStream* mSource; AudioNodeStream* mDestination; AudioParamTimeline mDelay; - DelayProcessor mProcessor; + DelayBuffer mBuffer; // How much data we have in our buffer which needs to be flushed out when our inputs // finish. int32_t mLeftOverData; diff --git a/content/media/webaudio/blink/HRTFPanner.h b/content/media/webaudio/blink/HRTFPanner.h index 6c725a8a521..ec7d6a59f56 100644 --- a/content/media/webaudio/blink/HRTFPanner.h +++ b/content/media/webaudio/blink/HRTFPanner.h @@ -26,7 +26,7 @@ #define HRTFPanner_h #include "FFTConvolver.h" -#include "DelayProcessor.h" +#include "DelayBuffer.h" namespace mozilla { struct AudioChunk; @@ -99,8 +99,8 @@ private: FFTConvolver m_convolverL2; FFTConvolver m_convolverR2; - mozilla::DelayProcessor m_delayLineL; - mozilla::DelayProcessor m_delayLineR; + mozilla::DelayBuffer m_delayLineL; + mozilla::DelayBuffer m_delayLineR; AudioFloatArray m_tempL1; AudioFloatArray m_tempR1; diff --git a/content/media/webaudio/moz.build b/content/media/webaudio/moz.build index 84f634eec5b..cb5a206c4f3 100644 --- a/content/media/webaudio/moz.build +++ b/content/media/webaudio/moz.build @@ -62,8 +62,8 @@ UNIFIED_SOURCES += [ 'ChannelMergerNode.cpp', 'ChannelSplitterNode.cpp', 'ConvolverNode.cpp', + 'DelayBuffer.cpp', 'DelayNode.cpp', - 'DelayProcessor.cpp', 'DynamicsCompressorNode.cpp', 'FFTBlock.cpp', 'GainNode.cpp', From ab2f28f9b2ffb24859d69c6261c4602beeef4165 Mon Sep 17 00:00:00 2001 From: Karl Tomlinson Date: Mon, 3 Mar 2014 12:49:45 +1300 Subject: [PATCH 013/112] b=857610 remove unnecessary HRTFPanner loop as a block is always the same size r=padenot --HG-- extra : rebase_source : 6325ac6ad4ee25c6b0facaaec27d1a0a25772107 --- content/media/webaudio/PannerNode.cpp | 2 +- content/media/webaudio/blink/HRTFPanner.cpp | 160 +++++++++----------- content/media/webaudio/blink/HRTFPanner.h | 4 +- 3 files changed, 75 insertions(+), 91 deletions(-) diff --git a/content/media/webaudio/PannerNode.cpp b/content/media/webaudio/PannerNode.cpp index 02ad7623fe0..c4795d6ffdd 100644 --- a/content/media/webaudio/PannerNode.cpp +++ b/content/media/webaudio/PannerNode.cpp @@ -302,7 +302,7 @@ PannerNodeEngine::HRTFPanningFunction(const AudioChunk& aInput, } } - mHRTFPanner->pan(azimuth, elevation, &input, aOutput, WEBAUDIO_BLOCK_SIZE); + mHRTFPanner->pan(azimuth, elevation, &input, aOutput); } void diff --git a/content/media/webaudio/blink/HRTFPanner.cpp b/content/media/webaudio/blink/HRTFPanner.cpp index 8bc86b6ccfd..14f3f9547e9 100644 --- a/content/media/webaudio/blink/HRTFPanner.cpp +++ b/content/media/webaudio/blink/HRTFPanner.cpp @@ -40,7 +40,7 @@ namespace WebCore { const double MaxDelayTimeSeconds = 0.002; const int UninitializedAzimuth = -1; -const unsigned RenderingQuantum = 128; +const unsigned RenderingQuantum = WEBAUDIO_BLOCK_SIZE; HRTFPanner::HRTFPanner(float sampleRate, mozilla::TemporaryRef databaseLoader) : m_databaseLoader(databaseLoader) @@ -115,15 +115,15 @@ int HRTFPanner::calculateDesiredAzimuthIndexAndBlend(double azimuth, double& azi return desiredAzimuthIndex; } -void HRTFPanner::pan(double desiredAzimuth, double elevation, const AudioChunk* inputBus, AudioChunk* outputBus, TrackTicks framesToProcess) +void HRTFPanner::pan(double desiredAzimuth, double elevation, const AudioChunk* inputBus, AudioChunk* outputBus) { unsigned numInputChannels = inputBus->IsNull() ? 0 : inputBus->mChannelData.Length(); MOZ_ASSERT(numInputChannels <= 2); - MOZ_ASSERT(framesToProcess <= inputBus->mDuration); + MOZ_ASSERT(inputBus->mDuration == WEBAUDIO_BLOCK_SIZE); - bool isOutputGood = outputBus && outputBus->mChannelData.Length() == 2 && framesToProcess <= outputBus->mDuration; + bool isOutputGood = outputBus && outputBus->mChannelData.Length() == 2 && outputBus->mDuration == WEBAUDIO_BLOCK_SIZE; MOZ_ASSERT(isOutputGood); if (!isOutputGood) { @@ -197,95 +197,79 @@ void HRTFPanner::pan(double desiredAzimuth, double elevation, const AudioChunk* } } - // This algorithm currently requires that we process in power-of-two size chunks at least RenderingQuantum. - MOZ_ASSERT(framesToProcess && 0 == (framesToProcess & (framesToProcess - 1))); - MOZ_ASSERT(framesToProcess >= RenderingQuantum); + // Get the HRTFKernels and interpolated delays. + HRTFKernel* kernelL1; + HRTFKernel* kernelR1; + HRTFKernel* kernelL2; + HRTFKernel* kernelR2; + double frameDelayL1; + double frameDelayR1; + double frameDelayL2; + double frameDelayR2; + database->getKernelsFromAzimuthElevation(azimuthBlend, m_azimuthIndex1, m_elevation1, kernelL1, kernelR1, frameDelayL1, frameDelayR1); + database->getKernelsFromAzimuthElevation(azimuthBlend, m_azimuthIndex2, m_elevation2, kernelL2, kernelR2, frameDelayL2, frameDelayR2); - const unsigned framesPerSegment = RenderingQuantum; - const unsigned numberOfSegments = framesToProcess / framesPerSegment; + bool areKernelsGood = kernelL1 && kernelR1 && kernelL2 && kernelR2; + MOZ_ASSERT(areKernelsGood); + if (!areKernelsGood) { + outputBus->SetNull(outputBus->mDuration); + return; + } - for (unsigned segment = 0; segment < numberOfSegments; ++segment) { - // Get the HRTFKernels and interpolated delays. - HRTFKernel* kernelL1; - HRTFKernel* kernelR1; - HRTFKernel* kernelL2; - HRTFKernel* kernelR2; - double frameDelayL1; - double frameDelayR1; - double frameDelayL2; - double frameDelayR2; - database->getKernelsFromAzimuthElevation(azimuthBlend, m_azimuthIndex1, m_elevation1, kernelL1, kernelR1, frameDelayL1, frameDelayR1); - database->getKernelsFromAzimuthElevation(azimuthBlend, m_azimuthIndex2, m_elevation2, kernelL2, kernelR2, frameDelayL2, frameDelayR2); + MOZ_ASSERT(frameDelayL1 / sampleRate() < MaxDelayTimeSeconds && frameDelayR1 / sampleRate() < MaxDelayTimeSeconds); + MOZ_ASSERT(frameDelayL2 / sampleRate() < MaxDelayTimeSeconds && frameDelayR2 / sampleRate() < MaxDelayTimeSeconds); - bool areKernelsGood = kernelL1 && kernelR1 && kernelL2 && kernelR2; - MOZ_ASSERT(areKernelsGood); - if (!areKernelsGood) { - outputBus->SetNull(outputBus->mDuration); - return; + // Crossfade inter-aural delays based on transitions. + double frameDelayL = (1 - m_crossfadeX) * frameDelayL1 + m_crossfadeX * frameDelayL2; + double frameDelayR = (1 - m_crossfadeX) * frameDelayR1 + m_crossfadeX * frameDelayR2; + + // First run through delay lines for inter-aural time difference. + m_delayLineL.Process(frameDelayL, &sourceL, &destinationL, 1, WEBAUDIO_BLOCK_SIZE); + m_delayLineR.Process(frameDelayR, &sourceR, &destinationR, 1, WEBAUDIO_BLOCK_SIZE); + + bool needsCrossfading = m_crossfadeIncr; + + // Have the convolvers render directly to the final destination if we're not cross-fading. + float* convolutionDestinationL1 = needsCrossfading ? m_tempL1.Elements() : destinationL; + float* convolutionDestinationR1 = needsCrossfading ? m_tempR1.Elements() : destinationR; + float* convolutionDestinationL2 = needsCrossfading ? m_tempL2.Elements() : destinationL; + float* convolutionDestinationR2 = needsCrossfading ? m_tempR2.Elements() : destinationR; + + // Now do the convolutions. + // Note that we avoid doing convolutions on both sets of convolvers if we're not currently cross-fading. + + if (m_crossfadeSelection == CrossfadeSelection1 || needsCrossfading) { + m_convolverL1.process(kernelL1->fftFrame(), destinationL, convolutionDestinationL1, WEBAUDIO_BLOCK_SIZE); + m_convolverR1.process(kernelR1->fftFrame(), destinationR, convolutionDestinationR1, WEBAUDIO_BLOCK_SIZE); + } + + if (m_crossfadeSelection == CrossfadeSelection2 || needsCrossfading) { + m_convolverL2.process(kernelL2->fftFrame(), destinationL, convolutionDestinationL2, WEBAUDIO_BLOCK_SIZE); + m_convolverR2.process(kernelR2->fftFrame(), destinationR, convolutionDestinationR2, WEBAUDIO_BLOCK_SIZE); + } + + if (needsCrossfading) { + // Apply linear cross-fade. + float x = m_crossfadeX; + float incr = m_crossfadeIncr; + for (unsigned i = 0; i < WEBAUDIO_BLOCK_SIZE; ++i) { + destinationL[i] = (1 - x) * convolutionDestinationL1[i] + x * convolutionDestinationL2[i]; + destinationR[i] = (1 - x) * convolutionDestinationR1[i] + x * convolutionDestinationR2[i]; + x += incr; } + // Update cross-fade value from local. + m_crossfadeX = x; - MOZ_ASSERT(frameDelayL1 / sampleRate() < MaxDelayTimeSeconds && frameDelayR1 / sampleRate() < MaxDelayTimeSeconds); - MOZ_ASSERT(frameDelayL2 / sampleRate() < MaxDelayTimeSeconds && frameDelayR2 / sampleRate() < MaxDelayTimeSeconds); - - // Crossfade inter-aural delays based on transitions. - double frameDelayL = (1 - m_crossfadeX) * frameDelayL1 + m_crossfadeX * frameDelayL2; - double frameDelayR = (1 - m_crossfadeX) * frameDelayR1 + m_crossfadeX * frameDelayR2; - - // Calculate the source and destination pointers for the current segment. - unsigned offset = segment * framesPerSegment; - const float* segmentSourceL = sourceL ? sourceL + offset : nullptr; - const float* segmentSourceR = sourceR ? sourceR + offset : nullptr; - float* segmentDestinationL = destinationL + offset; - float* segmentDestinationR = destinationR + offset; - - // First run through delay lines for inter-aural time difference. - m_delayLineL.Process(frameDelayL, &segmentSourceL, &segmentDestinationL, 1, framesPerSegment); - m_delayLineR.Process(frameDelayR, &segmentSourceR, &segmentDestinationR, 1, framesPerSegment); - - bool needsCrossfading = m_crossfadeIncr; - - // Have the convolvers render directly to the final destination if we're not cross-fading. - float* convolutionDestinationL1 = needsCrossfading ? m_tempL1.Elements() : segmentDestinationL; - float* convolutionDestinationR1 = needsCrossfading ? m_tempR1.Elements() : segmentDestinationR; - float* convolutionDestinationL2 = needsCrossfading ? m_tempL2.Elements() : segmentDestinationL; - float* convolutionDestinationR2 = needsCrossfading ? m_tempR2.Elements() : segmentDestinationR; - - // Now do the convolutions. - // Note that we avoid doing convolutions on both sets of convolvers if we're not currently cross-fading. - - if (m_crossfadeSelection == CrossfadeSelection1 || needsCrossfading) { - m_convolverL1.process(kernelL1->fftFrame(), segmentDestinationL, convolutionDestinationL1, framesPerSegment); - m_convolverR1.process(kernelR1->fftFrame(), segmentDestinationR, convolutionDestinationR1, framesPerSegment); - } - - if (m_crossfadeSelection == CrossfadeSelection2 || needsCrossfading) { - m_convolverL2.process(kernelL2->fftFrame(), segmentDestinationL, convolutionDestinationL2, framesPerSegment); - m_convolverR2.process(kernelR2->fftFrame(), segmentDestinationR, convolutionDestinationR2, framesPerSegment); - } - - if (needsCrossfading) { - // Apply linear cross-fade. - float x = m_crossfadeX; - float incr = m_crossfadeIncr; - for (unsigned i = 0; i < framesPerSegment; ++i) { - segmentDestinationL[i] = (1 - x) * convolutionDestinationL1[i] + x * convolutionDestinationL2[i]; - segmentDestinationR[i] = (1 - x) * convolutionDestinationR1[i] + x * convolutionDestinationR2[i]; - x += incr; - } - // Update cross-fade value from local. - m_crossfadeX = x; - - if (m_crossfadeIncr > 0 && fabs(m_crossfadeX - 1) < m_crossfadeIncr) { - // We've fully made the crossfade transition from 1 -> 2. - m_crossfadeSelection = CrossfadeSelection2; - m_crossfadeX = 1; - m_crossfadeIncr = 0; - } else if (m_crossfadeIncr < 0 && fabs(m_crossfadeX) < -m_crossfadeIncr) { - // We've fully made the crossfade transition from 2 -> 1. - m_crossfadeSelection = CrossfadeSelection1; - m_crossfadeX = 0; - m_crossfadeIncr = 0; - } + if (m_crossfadeIncr > 0 && fabs(m_crossfadeX - 1) < m_crossfadeIncr) { + // We've fully made the crossfade transition from 1 -> 2. + m_crossfadeSelection = CrossfadeSelection2; + m_crossfadeX = 1; + m_crossfadeIncr = 0; + } else if (m_crossfadeIncr < 0 && fabs(m_crossfadeX) < -m_crossfadeIncr) { + // We've fully made the crossfade transition from 2 -> 1. + m_crossfadeSelection = CrossfadeSelection1; + m_crossfadeX = 0; + m_crossfadeIncr = 0; } } } diff --git a/content/media/webaudio/blink/HRTFPanner.h b/content/media/webaudio/blink/HRTFPanner.h index ec7d6a59f56..a834e201c23 100644 --- a/content/media/webaudio/blink/HRTFPanner.h +++ b/content/media/webaudio/blink/HRTFPanner.h @@ -43,8 +43,8 @@ public: HRTFPanner(float sampleRate, mozilla::TemporaryRef databaseLoader); ~HRTFPanner(); - // framesToProcess must be a power of 2 and greater than 128 - void pan(double azimuth, double elevation, const AudioChunk* inputBus, AudioChunk* outputBus, mozilla::TrackTicks framesToProcess); + // chunk durations must be 128 + void pan(double azimuth, double elevation, const AudioChunk* inputBus, AudioChunk* outputBus); void reset(); size_t fftSize() const { return m_convolverL1.fftSize(); } From 0e1f8fec0828a4e0e66defa69d9255248963b58e Mon Sep 17 00:00:00 2001 From: Karl Tomlinson Date: Mon, 3 Mar 2014 12:49:46 +1300 Subject: [PATCH 014/112] b=857610 optimize delay clamping a little, by clamping in only one place r=padenot --HG-- rename : content/media/webaudio/DelayProcessor.cpp => content/media/webaudio/DelayBuffer.cpp rename : content/media/webaudio/DelayProcessor.h => content/media/webaudio/DelayBuffer.h extra : rebase_source : 48d60cb003205a550504bcd0042ef73fc8727f97 --- content/media/webaudio/DelayBuffer.cpp | 5 +++-- content/media/webaudio/DelayBuffer.h | 3 ++- content/media/webaudio/DelayNode.cpp | 12 ++++++------ 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/content/media/webaudio/DelayBuffer.cpp b/content/media/webaudio/DelayBuffer.cpp index 6bac31a62d3..92d72fdd99e 100644 --- a/content/media/webaudio/DelayBuffer.cpp +++ b/content/media/webaudio/DelayBuffer.cpp @@ -34,8 +34,9 @@ DelayBuffer::Process(const double *aPerFrameDelays, float* output = aOutputChannels[channel]; for (int i = 0; i < aFramesToProcess; ++i) { - currentDelayFrames = clamped(aPerFrameDelays[i], - 0.0, static_cast(mMaxDelayFrames)); + currentDelayFrames = aPerFrameDelays[i]; + MOZ_ASSERT(currentDelayFrames >= 0.0); + MOZ_ASSERT(currentDelayFrames <= static_cast(mMaxDelayFrames)); // Write the input sample to the correct location in our buffer buffer[writeIndex] = input ? input[i] : 0.0f; diff --git a/content/media/webaudio/DelayBuffer.h b/content/media/webaudio/DelayBuffer.h index b5a539e1bea..06053e970d4 100644 --- a/content/media/webaudio/DelayBuffer.h +++ b/content/media/webaudio/DelayBuffer.h @@ -24,13 +24,14 @@ public: } // Process with an array of delays, in frames, for each frame. + // Each delay must be > 0 and < MaxDelayFrames(). void Process(const double *aPerFrameDelays, const float* const* aInputChannels, float* const* aOutputChannels, int aChannelCount, int aFramesToProcess); // Process with a constant delay, which will be smoothed with the previous - // delay. + // delay. The delay must be > 0 and < MaxDelayFrames(). void Process(double aDelayFrames, const float* const* aInputChannels, float* const* aOutputChannels, int aChannelCount, int aFramesToProcess); diff --git a/content/media/webaudio/DelayNode.cpp b/content/media/webaudio/DelayNode.cpp index 92a707f2bcc..458b1c699a0 100644 --- a/content/media/webaudio/DelayNode.cpp +++ b/content/media/webaudio/DelayNode.cpp @@ -129,13 +129,14 @@ public: bool inCycle = aStream->AsProcessedStream()->InCycle(); + double minDelay = inCycle ? static_cast(WEBAUDIO_BLOCK_SIZE) : 0.0; + double maxDelay = mBuffer.MaxDelayFrames(); double sampleRate = aStream->SampleRate(); if (mDelay.HasSimpleValue()) { // If this DelayNode is in a cycle, make sure the delay value is at least // one block. - float delayFrames = mDelay.GetValue() * sampleRate; - float delayFramesClamped = inCycle ? std::max(static_cast(WEBAUDIO_BLOCK_SIZE), delayFrames) : - delayFrames; + double delayFrames = mDelay.GetValue() * sampleRate; + double delayFramesClamped = clamped(delayFrames, minDelay, maxDelay); mBuffer.Process(delayFramesClamped, inputChannels, outputChannels, numChannels, WEBAUDIO_BLOCK_SIZE); } else { @@ -145,9 +146,8 @@ public: double computedDelay[WEBAUDIO_BLOCK_SIZE]; TrackTicks tick = aStream->GetCurrentPosition(); for (size_t counter = 0; counter < WEBAUDIO_BLOCK_SIZE; ++counter) { - float delayAtTick = mDelay.GetValueAtTime(tick, counter) * sampleRate; - float delayAtTickClamped = inCycle ? std::max(static_cast(WEBAUDIO_BLOCK_SIZE), delayAtTick) : - delayAtTick; + double delayAtTick = mDelay.GetValueAtTime(tick, counter) * sampleRate; + double delayAtTickClamped = clamped(delayAtTick, minDelay, maxDelay); computedDelay[counter] = delayAtTickClamped; } mBuffer.Process(computedDelay, inputChannels, outputChannels, From 5056403e1d4a9d15270a546071f5e21c64713be2 Mon Sep 17 00:00:00 2001 From: Karl Tomlinson Date: Wed, 5 Mar 2014 10:06:44 +1300 Subject: [PATCH 015/112] b=865241 test HRTF panner left/right symmetry and block-offset invariance --HG-- extra : rebase_source : 95ae651bd082760bfa5b6e45f5439408419473ad --- content/media/webaudio/test/mochitest.ini | 1 + .../test/test_pannerNodeSymmetry.html | 104 ++++++++++++++++++ 2 files changed, 105 insertions(+) create mode 100644 content/media/webaudio/test/test_pannerNodeSymmetry.html diff --git a/content/media/webaudio/test/mochitest.ini b/content/media/webaudio/test/mochitest.ini index 7735d075c55..3fe0cbc0f3c 100644 --- a/content/media/webaudio/test/mochitest.ini +++ b/content/media/webaudio/test/mochitest.ini @@ -107,6 +107,7 @@ support-files = [test_pannerNode.html] [test_pannerNodeAbove.html] [test_pannerNodeChannelCount.html] +[test_pannerNodeSymmetry.html] [test_pannerNodeTail.html] [test_pannerNode_equalPower.html] [test_periodicWave.html] diff --git a/content/media/webaudio/test/test_pannerNodeSymmetry.html b/content/media/webaudio/test/test_pannerNodeSymmetry.html new file mode 100644 index 00000000000..a4a2fc1c552 --- /dev/null +++ b/content/media/webaudio/test/test_pannerNodeSymmetry.html @@ -0,0 +1,104 @@ + + + + Test left/right symmetry and block-offset invariance of HRTF panner + + + + + +
+
+
+ + From ce878a57353722574ab1e703446944053c705b95 Mon Sep 17 00:00:00 2001 From: Karl Tomlinson Date: Wed, 5 Mar 2014 10:06:56 +1300 Subject: [PATCH 016/112] b=857610 test DelayNode channel count changes --HG-- extra : rebase_source : 99dbe2400b972fa7f0d331ae35be07f52d81071e --- content/media/webaudio/test/mochitest.ini | 1 + .../test/test_delayNodeChannelChanges.html | 97 +++++++++++++++++++ 2 files changed, 98 insertions(+) create mode 100644 content/media/webaudio/test/test_delayNodeChannelChanges.html diff --git a/content/media/webaudio/test/mochitest.ini b/content/media/webaudio/test/mochitest.ini index 3fe0cbc0f3c..0a50ac96990 100644 --- a/content/media/webaudio/test/mochitest.ini +++ b/content/media/webaudio/test/mochitest.ini @@ -79,6 +79,7 @@ support-files = [test_decodeMultichannel.html] [test_delayNode.html] [test_delayNodeAtMax.html] +[test_delayNodeChannelChanges.html] [test_delayNodeCycles.html] [test_delayNodeSmallMaxDelay.html] [test_delayNodeTailIncrease.html] diff --git a/content/media/webaudio/test/test_delayNodeChannelChanges.html b/content/media/webaudio/test/test_delayNodeChannelChanges.html new file mode 100644 index 00000000000..a95625a9ab6 --- /dev/null +++ b/content/media/webaudio/test/test_delayNodeChannelChanges.html @@ -0,0 +1,97 @@ + + + + test DelayNode channel count changes + + + + + +
+
+
+ + From 0935b39ced87629c1d3667c6faa1671ce753cf4c Mon Sep 17 00:00:00 2001 From: Karl Tomlinson Date: Wed, 5 Mar 2014 10:06:57 +1300 Subject: [PATCH 017/112] b=857610 handle DelayNode channel count changes and separate buffer read and write r=padenot The basic idea is to write out the signal that came in with the same number of channels as it had when it came in. Things get a bit more complicated when one output block may be derived from more than one input block, each having different numbers of channels. When this happens, the input blocks with fewer channels are upmixed, so as not to lose (or distort) any signal in the block with more channels. HRTFPanner no longer uses exponential decay (with time constant 20ms) for delay changes, but a smoother linear transition during cross-fade time (~45ms). --HG-- rename : content/media/webaudio/DelayProcessor.cpp => content/media/webaudio/DelayBuffer.cpp rename : content/media/webaudio/DelayProcessor.h => content/media/webaudio/DelayBuffer.h extra : rebase_source : 18453d631779cd7d0672b5325e110b107ab4237d --- content/media/AudioNodeStream.h | 24 +- content/media/AudioSegment.h | 1 + content/media/webaudio/DelayBuffer.cpp | 285 ++++++++++++++------ content/media/webaudio/DelayBuffer.h | 87 ++++-- content/media/webaudio/DelayNode.cpp | 40 +-- content/media/webaudio/PannerNode.cpp | 15 +- content/media/webaudio/blink/HRTFPanner.cpp | 42 +-- content/media/webaudio/blink/HRTFPanner.h | 3 +- 8 files changed, 317 insertions(+), 180 deletions(-) diff --git a/content/media/AudioNodeStream.h b/content/media/AudioNodeStream.h index 634d85ebf01..91d244c1b26 100644 --- a/content/media/AudioNodeStream.h +++ b/content/media/AudioNodeStream.h @@ -33,6 +33,9 @@ class AudioNodeEngine; * integrates audio processing with the MediaStreamGraph. */ class AudioNodeStream : public ProcessedMediaStream { + typedef dom::ChannelCountMode ChannelCountMode; + typedef dom::ChannelInterpretation ChannelInterpretation; + public: typedef mozilla::dom::AudioContext AudioContext; @@ -56,8 +59,8 @@ public: mMuted(false) { MOZ_ASSERT(NS_IsMainThread()); - mChannelCountMode = dom::ChannelCountMode::Max; - mChannelInterpretation = dom::ChannelInterpretation::Speakers; + mChannelCountMode = ChannelCountMode::Max; + mChannelInterpretation = ChannelInterpretation::Speakers; // AudioNodes are always producing data mHasCurrentData = true; MOZ_COUNT_CTOR(AudioNodeStream); @@ -79,8 +82,13 @@ public: // This consumes the contents of aData. aData will be emptied after this returns. void SetRawArrayData(nsTArray& aData); void SetChannelMixingParameters(uint32_t aNumberOfChannels, - dom::ChannelCountMode aChannelCountMoe, - dom::ChannelInterpretation aChannelInterpretation); + ChannelCountMode aChannelCountMoe, + ChannelInterpretation aChannelInterpretation); + ChannelInterpretation GetChannelInterpretation() + { + return mChannelInterpretation; + } + void SetAudioParamHelperStream() { MOZ_ASSERT(!mAudioParamStream, "Can only do this once"); @@ -93,8 +101,8 @@ public: void SetStreamTimeParameterImpl(uint32_t aIndex, MediaStream* aRelativeToStream, double aStreamTime); void SetChannelMixingParametersImpl(uint32_t aNumberOfChannels, - dom::ChannelCountMode aChannelCountMoe, - dom::ChannelInterpretation aChannelInterpretation); + ChannelCountMode aChannelCountMoe, + ChannelInterpretation aChannelInterpretation); virtual void ProduceOutput(GraphTime aFrom, GraphTime aTo, uint32_t aFlags) MOZ_OVERRIDE; TrackTicks GetCurrentPosition(); bool IsAudioParamStream() const @@ -171,8 +179,8 @@ protected: // The number of input channels that this stream requires. 0 means don't care. uint32_t mNumberOfInputChannels; // The mixing modes - dom::ChannelCountMode mChannelCountMode; - dom::ChannelInterpretation mChannelInterpretation; + ChannelCountMode mChannelCountMode; + ChannelInterpretation mChannelInterpretation; // Whether the stream should be marked as finished as soon // as the current time range has been computed block by block. bool mMarkAsFinishedAfterThisBlock; diff --git a/content/media/AudioSegment.h b/content/media/AudioSegment.h index 563f0f76437..a09e96bbaa4 100644 --- a/content/media/AudioSegment.h +++ b/content/media/AudioSegment.h @@ -99,6 +99,7 @@ struct AudioChunk { mDuration = aDuration; mVolume = 1.0f; } + int ChannelCount() const { return mChannelData.Length(); } TrackTicks mDuration; // in frames within the buffer nsRefPtr mBuffer; // the buffer object whose lifetime is managed; null means data is all zeroes diff --git a/content/media/webaudio/DelayBuffer.cpp b/content/media/webaudio/DelayBuffer.cpp index 92d72fdd99e..79089f799cf 100644 --- a/content/media/webaudio/DelayBuffer.cpp +++ b/content/media/webaudio/DelayBuffer.cpp @@ -7,122 +7,243 @@ #include "DelayBuffer.h" #include "mozilla/PodOperations.h" -#include "AudioSegment.h" +#include "AudioChannelFormat.h" +#include "AudioNodeEngine.h" namespace mozilla { void -DelayBuffer::Process(const double *aPerFrameDelays, - const float* const* aInputChannels, - float* const* aOutputChannels, - int aChannelCount, int aFramesToProcess) +DelayBuffer::Write(const AudioChunk& aInputChunk) { - if (!EnsureBuffer(aChannelCount)) { - for (int channel = 0; channel < aChannelCount; ++channel) { - PodZero(aOutputChannels[channel], aFramesToProcess); - } + // We must have a reference to the buffer if there are channels + MOZ_ASSERT(aInputChunk.IsNull() == !aInputChunk.mChannelData.Length()); + + if (!EnsureBuffer()) { return; } - for (int channel = 0; channel < aChannelCount; ++channel) { - double currentDelayFrames = mCurrentDelay; - int writeIndex = mWriteIndex; + if (mCurrentChunk == mLastReadChunk) { + mLastReadChunk = -1; // invalidate cache + } + mChunks[mCurrentChunk] = aInputChunk; +} - float* buffer = mBuffer[channel].Elements(); - const uint32_t bufferLength = mBuffer[channel].Length(); - const float* input = aInputChannels ? aInputChannels[channel] : nullptr; - float* output = aOutputChannels[channel]; +void +DelayBuffer::Read(const double aPerFrameDelays[WEBAUDIO_BLOCK_SIZE], + AudioChunk* aOutputChunk, + ChannelInterpretation aChannelInterpretation) +{ + int chunkCount = mChunks.Length(); + if (!chunkCount) { + aOutputChunk->SetNull(WEBAUDIO_BLOCK_SIZE); + return; + } - for (int i = 0; i < aFramesToProcess; ++i) { - currentDelayFrames = aPerFrameDelays[i]; - MOZ_ASSERT(currentDelayFrames >= 0.0); - MOZ_ASSERT(currentDelayFrames <= static_cast(mMaxDelayFrames)); + // Find the maximum number of contributing channels to determine the output + // channel count that retains all signal information. Buffered blocks will + // be upmixed if necessary. + // + // First find the range of "delay" offsets backwards from the current + // position. Note that these may be negative for frames that are after the + // current position (including i). + double minDelay = aPerFrameDelays[0]; + double maxDelay = minDelay; + for (unsigned i = 1; i < WEBAUDIO_BLOCK_SIZE; ++i) { + minDelay = std::min(minDelay, aPerFrameDelays[i] - i); + maxDelay = std::max(maxDelay, aPerFrameDelays[i] - i); + } - // Write the input sample to the correct location in our buffer - buffer[writeIndex] = input ? input[i] : 0.0f; + // Now find the chunks touched by this range and check their channel counts. + int oldestChunk = ChunkForDelay(int(maxDelay) + 1); + int youngestChunk = ChunkForDelay(minDelay); - // Now, determine the correct read position. We adjust the read position to be - // from currentDelayFrames frames in the past. We also interpolate the two input - // frames in case the read position does not match an integer index. - double readPosition = writeIndex + bufferLength - currentDelayFrames; - if (readPosition >= bufferLength) { - readPosition -= bufferLength; - } - MOZ_ASSERT(readPosition >= 0.0, "Why are we reading before the beginning of the buffer?"); - - // Here is a the reason why readIndex1 and readIndex will never be out - // of bounds. The maximum value for bufferLength is - // 180 * AudioContext.samplerate (see AudioContext::CreateDelay). The - // maximum value for mCurrentDelay is 180.0, so initially readPosition - // cannot be more than bufferLength + a fraction less than 1. Then we - // take care of that case by subtracting bufferLength from it if needed. - // So, if |bufferLength-readPosition<1.0|, readIndex1 will end up being - // zero. If |1.0<=bufferLength-readPosition<2.0|, readIndex1 will be - // bufferLength-1 and readIndex2 will be 0. - int readIndex1 = int(readPosition); - int readIndex2 = (readIndex1 + 1) % bufferLength; - double interpolationFactor = readPosition - readIndex1; - - output[i] = (1.0 - interpolationFactor) * buffer[readIndex1] + - interpolationFactor * buffer[readIndex2]; - writeIndex = (writeIndex + 1) % bufferLength; + uint32_t channelCount = 0; + for (int i = oldestChunk; true; i = (i + 1) % chunkCount) { + channelCount = GetAudioChannelsSuperset(channelCount, + mChunks[i].ChannelCount()); + if (i == youngestChunk) { + break; } + } - // Remember currentDelayFrames and writeIndex for the next ProduceAudioBlock - // call when processing the last channel. - if (channel == aChannelCount - 1) { - mCurrentDelay = currentDelayFrames; - mWriteIndex = writeIndex; + if (channelCount) { + AllocateAudioBlock(channelCount, aOutputChunk); + ReadChannels(aPerFrameDelays, aOutputChunk, + 0, channelCount, aChannelInterpretation); + } else { + aOutputChunk->SetNull(WEBAUDIO_BLOCK_SIZE); + } + + // Remember currentDelayFrames for the next ProduceAudioBlock call + mCurrentDelay = aPerFrameDelays[WEBAUDIO_BLOCK_SIZE - 1]; +} + +void +DelayBuffer::ReadChannel(const double aPerFrameDelays[WEBAUDIO_BLOCK_SIZE], + const AudioChunk* aOutputChunk, uint32_t aChannel, + ChannelInterpretation aChannelInterpretation) +{ + if (!mChunks.Length()) { + float* outputChannel = static_cast + (const_cast(aOutputChunk->mChannelData[aChannel])); + PodZero(outputChannel, WEBAUDIO_BLOCK_SIZE); + return; + } + + ReadChannels(aPerFrameDelays, aOutputChunk, + aChannel, 1, aChannelInterpretation); +} + +void +DelayBuffer::ReadChannels(const double aPerFrameDelays[WEBAUDIO_BLOCK_SIZE], + const AudioChunk* aOutputChunk, + uint32_t aFirstChannel, uint32_t aNumChannelsToRead, + ChannelInterpretation aChannelInterpretation) +{ + uint32_t totalChannelCount = aOutputChunk->mChannelData.Length(); + uint32_t readChannelsEnd = aFirstChannel + aNumChannelsToRead; + MOZ_ASSERT(readChannelsEnd <= totalChannelCount); + + if (mUpmixChannels.Length() != totalChannelCount) { + mLastReadChunk = -1; // invalidate cache + } + + float* const* outputChannels = reinterpret_cast + (const_cast(aOutputChunk->mChannelData.Elements())); + for (uint32_t channel = aFirstChannel; + channel < readChannelsEnd; ++channel) { + PodZero(outputChannels[channel], WEBAUDIO_BLOCK_SIZE); + } + + for (unsigned i = 0; i < WEBAUDIO_BLOCK_SIZE; ++i) { + double currentDelay = aPerFrameDelays[i]; + MOZ_ASSERT(currentDelay >= 0.0); + MOZ_ASSERT(currentDelay <= static_cast(mMaxDelayTicks)); + + // Interpolate two input frames in case the read position does not match + // an integer index. + // Use the larger delay, for the older frame, first, as this is more + // likely to use the cached upmixed channel arrays. + int floorDelay = int(currentDelay); + double interpolationFactor = currentDelay - floorDelay; + int positions[2]; + positions[1] = PositionForDelay(floorDelay) + i; + positions[0] = positions[1] - 1; + + for (unsigned tick = 0; tick < ArrayLength(positions); ++tick) { + int readChunk = ChunkForPosition(positions[tick]); + // mVolume is not set on default initialized chunks so handle null + // chunks specially. + if (!mChunks[readChunk].IsNull()) { + int readOffset = OffsetForPosition(positions[tick]); + UpdateUpmixChannels(readChunk, totalChannelCount, + aChannelInterpretation); + double multiplier = interpolationFactor * mChunks[readChunk].mVolume; + for (uint32_t channel = aFirstChannel; + channel < readChannelsEnd; ++channel) { + outputChannels[channel][i] += multiplier * + static_cast(mUpmixChannels[channel])[readOffset]; + } + } + + interpolationFactor = 1.0 - interpolationFactor; } } } void -DelayBuffer::Process(double aDelayFrames, const float* const* aInputChannels, - float* const* aOutputChannels, int aChannelCount, - int aFramesToProcess) +DelayBuffer::Read(double aDelayTicks, AudioChunk* aOutputChunk, + ChannelInterpretation aChannelInterpretation) { - const bool firstTime = !mBuffer.Length(); - double currentDelay = firstTime ? aDelayFrames : mCurrentDelay; + const bool firstTime = mCurrentDelay < 0.0; + double currentDelay = firstTime ? aDelayTicks : mCurrentDelay; - nsAutoTArray computedDelay; - computedDelay.SetLength(aFramesToProcess); + double computedDelay[WEBAUDIO_BLOCK_SIZE]; - for (int i = 0; i < aFramesToProcess; ++i) { + for (unsigned i = 0; i < WEBAUDIO_BLOCK_SIZE; ++i) { // If the value has changed, smoothly approach it - currentDelay += (aDelayFrames - currentDelay) * mSmoothingRate; + currentDelay += (aDelayTicks - currentDelay) * mSmoothingRate; computedDelay[i] = currentDelay; } - Process(computedDelay.Elements(), aInputChannels, aOutputChannels, - aChannelCount, aFramesToProcess); + Read(computedDelay, aOutputChunk, aChannelInterpretation); } bool -DelayBuffer::EnsureBuffer(uint32_t aNumberOfChannels) +DelayBuffer::EnsureBuffer() { - if (aNumberOfChannels == 0) { - return false; - } - if (mBuffer.Length() == 0) { - if (!mBuffer.SetLength(aNumberOfChannels)) { + if (mChunks.Length() == 0) { + // The length of the buffer is at least one block greater than the maximum + // delay so that writing an input block does not overwrite the block that + // would subsequently be read at maximum delay. Also round up to the next + // block size, so that no block of writes will need to wrap. + const int chunkCount = (mMaxDelayTicks + 2 * WEBAUDIO_BLOCK_SIZE - 1) >> + WEBAUDIO_BLOCK_SIZE_BITS; + if (!mChunks.SetLength(chunkCount)) { return false; } - // The length of the buffer is one greater than the maximum delay so that - // writing an input frame does not overwrite the frame that would - // subsequently be read at maximum delay. - const int numFrames = mMaxDelayFrames + 1; - for (uint32_t channel = 0; channel < aNumberOfChannels; ++channel) { - if (!mBuffer[channel].SetLength(numFrames)) { - return false; - } - PodZero(mBuffer[channel].Elements(), numFrames); - } - } else if (mBuffer.Length() != aNumberOfChannels) { - // TODO: Handle changes in the channel count - return false; + + mLastReadChunk = -1; } return true; } +int +DelayBuffer::PositionForDelay(int aDelay) { + // Adding mChunks.Length() keeps integers positive for defined and + // appropriate bitshift, remainder, and bitwise operations. + return ((mCurrentChunk + mChunks.Length()) * WEBAUDIO_BLOCK_SIZE) - aDelay; +} + +int +DelayBuffer::ChunkForPosition(int aPosition) +{ + MOZ_ASSERT(aPosition >= 0); + return (aPosition >> WEBAUDIO_BLOCK_SIZE_BITS) % mChunks.Length(); +} + +int +DelayBuffer::OffsetForPosition(int aPosition) +{ + MOZ_ASSERT(aPosition >= 0); + return aPosition & (WEBAUDIO_BLOCK_SIZE - 1); +} + +int +DelayBuffer::ChunkForDelay(int aDelay) +{ + return ChunkForPosition(PositionForDelay(aDelay)); +} + +void +DelayBuffer::UpdateUpmixChannels(int aNewReadChunk, uint32_t aChannelCount, + ChannelInterpretation aChannelInterpretation) +{ + if (aNewReadChunk == mLastReadChunk) { + MOZ_ASSERT(mUpmixChannels.Length() == aChannelCount); + return; + } + + static const float silenceChannel[WEBAUDIO_BLOCK_SIZE] = {}; + + mLastReadChunk = aNewReadChunk; + // Missing assignment operator is bug 976927 + mUpmixChannels.ReplaceElementsAt(0, mUpmixChannels.Length(), + mChunks[aNewReadChunk].mChannelData); + MOZ_ASSERT(mUpmixChannels.Length() <= aChannelCount); + if (mUpmixChannels.Length() < aChannelCount) { + if (aChannelInterpretation == ChannelInterpretation::Speakers) { + AudioChannelsUpMix(&mUpmixChannels, aChannelCount, silenceChannel); + MOZ_ASSERT(mUpmixChannels.Length() == aChannelCount, + "We called GetAudioChannelsSuperset to avoid this"); + } else { + // Fill up the remaining channels with zeros + for (uint32_t channel = mUpmixChannels.Length(); + channel < aChannelCount; ++channel) { + mUpmixChannels.AppendElement(silenceChannel); + } + } + } +} + } // mozilla diff --git a/content/media/webaudio/DelayBuffer.h b/content/media/webaudio/DelayBuffer.h index 06053e970d4..fff74dc9980 100644 --- a/content/media/webaudio/DelayBuffer.h +++ b/content/media/webaudio/DelayBuffer.h @@ -8,52 +8,87 @@ #define DelayBuffer_h_ #include "nsTArray.h" +#include "AudioSegment.h" +#include "mozilla/dom/AudioNodeBinding.h" // for ChannelInterpretation namespace mozilla { class DelayBuffer { + typedef dom::ChannelInterpretation ChannelInterpretation; + public: // See WebAudioUtils::ComputeSmoothingRate() for frame to frame exponential // |smoothingRate| multiplier. - DelayBuffer(int aMaxDelayFrames, double aSmoothingRate) + DelayBuffer(int aMaxDelayTicks, double aSmoothingRate) : mSmoothingRate(aSmoothingRate) - , mCurrentDelay(0.) - , mMaxDelayFrames(aMaxDelayFrames) - , mWriteIndex(0) + , mCurrentDelay(-1.0) + , mMaxDelayTicks(aMaxDelayTicks) + , mCurrentChunk(0) + // mLastReadChunk is initialized in EnsureBuffer { } - // Process with an array of delays, in frames, for each frame. - // Each delay must be > 0 and < MaxDelayFrames(). - void Process(const double *aPerFrameDelays, - const float* const* aInputChannels, - float* const* aOutputChannels, - int aChannelCount, int aFramesToProcess); + // Write a WEBAUDIO_BLOCK_SIZE block for aChannelCount channels. + void Write(const AudioChunk& aInputChunk); - // Process with a constant delay, which will be smoothed with the previous - // delay. The delay must be > 0 and < MaxDelayFrames(). - void Process(double aDelayFrames, const float* const* aInputChannels, - float* const* aOutputChannels, int aChannelCount, - int aFramesToProcess); + // Read a block with an array of delays, in ticks, for each sample frame. + // Each delay must be > 0 and < MaxDelayTicks(). + void Read(const double aPerFrameDelays[WEBAUDIO_BLOCK_SIZE], + AudioChunk* aOutputChunk, + ChannelInterpretation aChannelInterpretation); + // Read a block with a constant delay, which will be smoothed with the + // previous delay. The delay must be > 0 and < MaxDelayTicks(). + void Read(double aDelayTicks, AudioChunk* aOutputChunk, + ChannelInterpretation aChannelInterpretation); - void Reset() { mBuffer.Clear(); }; + // Read into one of the channels of aOutputChunk, given an array of + // delays in ticks. This is useful when delays are different on different + // channels. aOutputChunk must have already been allocated with at least as + // many channels as were in any of the blocks passed to Write(). + void ReadChannel(const double aPerFrameDelays[WEBAUDIO_BLOCK_SIZE], + const AudioChunk* aOutputChunk, uint32_t aChannel, + ChannelInterpretation aChannelInterpretation); - int MaxDelayFrames() const { return mMaxDelayFrames; } - int ChannelCount() const { return mBuffer.Length(); } + // Advance the buffer pointer + void NextBlock() + { + mCurrentChunk = (mCurrentChunk + 1) % mChunks.Length(); + } + + void Reset() { + mChunks.Clear(); + mCurrentDelay = -1.0; + }; + + int MaxDelayTicks() const { return mMaxDelayTicks; } private: - bool EnsureBuffer(uint32_t aNumberOfChannels); + void ReadChannels(const double aPerFrameDelays[WEBAUDIO_BLOCK_SIZE], + const AudioChunk* aOutputChunk, + uint32_t aFirstChannel, uint32_t aNumChannelsToRead, + ChannelInterpretation aChannelInterpretation); + bool EnsureBuffer(); + int PositionForDelay(int aDelay); + int ChunkForPosition(int aPosition); + int OffsetForPosition(int aPosition); + int ChunkForDelay(int aDelay); + void UpdateUpmixChannels(int aNewReadChunk, uint32_t channelCount, + ChannelInterpretation aChannelInterpretation); // Circular buffer for capturing delayed samples. - AutoFallibleTArray, 2> mBuffer; + FallibleTArray mChunks; + // Cache upmixed channel arrays. + nsAutoTArray mUpmixChannels; double mSmoothingRate; - // Current delay, in fractional frames + // Current delay, in fractional ticks double mCurrentDelay; - // Maximum delay, in frames - int mMaxDelayFrames; - // Write index for the buffer, to write the frames to the correct index of the buffer - // given the current delay. - int mWriteIndex; + // Maximum delay, in ticks + int mMaxDelayTicks; + // The current position in the circular buffer. The next write will be to + // this chunk, and the next read may begin before this chunk. + int mCurrentChunk; + // The chunk owning the pointers in mUpmixChannels + int mLastReadChunk; }; } // mozilla diff --git a/content/media/webaudio/DelayNode.cpp b/content/media/webaudio/DelayNode.cpp index 458b1c699a0..0c8fded3c34 100644 --- a/content/media/webaudio/DelayNode.cpp +++ b/content/media/webaudio/DelayNode.cpp @@ -30,14 +30,14 @@ class DelayNodeEngine : public AudioNodeEngine typedef PlayingRefChangeHandler PlayingRefChanged; public: DelayNodeEngine(AudioNode* aNode, AudioDestinationNode* aDestination, - int aMaxDelayFrames) + int aMaxDelayTicks) : AudioNodeEngine(aNode) , mSource(nullptr) , mDestination(static_cast (aDestination->Stream())) // Keep the default value in sync with the default value in DelayNode::DelayNode. , mDelay(0.f) // Use a smoothing range of 20ms - , mBuffer(aMaxDelayFrames, + , mBuffer(aMaxDelayTicks, WebAudioUtils::ComputeSmoothingRate(0.02, mDestination->SampleRate())) , mLeftOverData(INT32_MIN) @@ -80,10 +80,6 @@ public: MOZ_ASSERT(mSource == aStream, "Invalid source stream"); MOZ_ASSERT(aStream->SampleRate() == mDestination->SampleRate()); - const uint32_t numChannels = aInput.IsNull() ? - mBuffer.ChannelCount() : - aInput.mChannelData.Length(); - if (!aInput.IsNull()) { if (mLeftOverData <= 0) { nsRefPtr refchanged = @@ -91,7 +87,7 @@ public: aStream->Graph()-> DispatchToMainThreadAfterStreamStateUpdate(refchanged.forget()); } - mLeftOverData = mBuffer.MaxDelayFrames(); + mLeftOverData = mBuffer.MaxDelayTicks(); } else if (mLeftOverData > 0) { mLeftOverData -= WEBAUDIO_BLOCK_SIZE; } else { @@ -109,36 +105,20 @@ public: return; } - AllocateAudioBlock(numChannels, aOutput); - - AudioChunk input = aInput; - if (!aInput.IsNull() && aInput.mVolume != 1.0f) { - // Pre-multiply the input's volume - AllocateAudioBlock(numChannels, &input); - for (uint32_t i = 0; i < numChannels; ++i) { - const float* src = static_cast(aInput.mChannelData[i]); - float* dest = static_cast(const_cast(input.mChannelData[i])); - AudioBlockCopyChannelWithScale(src, aInput.mVolume, dest); - } - } - - const float* const* inputChannels = input.IsNull() ? nullptr : - reinterpret_cast(input.mChannelData.Elements()); - float* const* outputChannels = reinterpret_cast - (const_cast(aOutput->mChannelData.Elements())); - + mBuffer.Write(aInput); bool inCycle = aStream->AsProcessedStream()->InCycle(); double minDelay = inCycle ? static_cast(WEBAUDIO_BLOCK_SIZE) : 0.0; - double maxDelay = mBuffer.MaxDelayFrames(); + double maxDelay = mBuffer.MaxDelayTicks(); double sampleRate = aStream->SampleRate(); + ChannelInterpretation channelInterpretation = + aStream->GetChannelInterpretation(); if (mDelay.HasSimpleValue()) { // If this DelayNode is in a cycle, make sure the delay value is at least // one block. double delayFrames = mDelay.GetValue() * sampleRate; double delayFramesClamped = clamped(delayFrames, minDelay, maxDelay); - mBuffer.Process(delayFramesClamped, inputChannels, outputChannels, - numChannels, WEBAUDIO_BLOCK_SIZE); + mBuffer.Read(delayFramesClamped, aOutput, channelInterpretation); } else { // Compute the delay values for the duration of the input AudioChunk // If this DelayNode is in a cycle, make sure the delay value is at least @@ -150,9 +130,9 @@ public: double delayAtTickClamped = clamped(delayAtTick, minDelay, maxDelay); computedDelay[counter] = delayAtTickClamped; } - mBuffer.Process(computedDelay, inputChannels, outputChannels, - numChannels, WEBAUDIO_BLOCK_SIZE); + mBuffer.Read(computedDelay, aOutput, channelInterpretation); } + mBuffer.NextBlock(); } AudioNodeStream* mSource; diff --git a/content/media/webaudio/PannerNode.cpp b/content/media/webaudio/PannerNode.cpp index c4795d6ffdd..a7267221a09 100644 --- a/content/media/webaudio/PannerNode.cpp +++ b/content/media/webaudio/PannerNode.cpp @@ -279,8 +279,6 @@ void PannerNodeEngine::HRTFPanningFunction(const AudioChunk& aInput, AudioChunk* aOutput) { - int numChannels = aInput.mChannelData.Length(); - // The output of this node is always stereo, no matter what the inputs are. AllocateAudioBlock(2, aOutput); @@ -289,18 +287,7 @@ PannerNodeEngine::HRTFPanningFunction(const AudioChunk& aInput, AudioChunk input = aInput; // Gain is applied before the delay and convolution of the HRTF - if (!input.IsNull()) { - float gain = ComputeConeGain() * ComputeDistanceGain() * aInput.mVolume; - if (gain != 1.0f) { - AllocateAudioBlock(numChannels, &input); - for (int i = 0; i < numChannels; ++i) { - const float* src = static_cast(aInput.mChannelData[i]); - float* dest = - static_cast(const_cast(input.mChannelData[i])); - AudioBlockCopyChannelWithScale(src, gain, dest); - } - } - } + input.mVolume *= ComputeConeGain() * ComputeDistanceGain(); mHRTFPanner->pan(azimuth, elevation, &input, aOutput); } diff --git a/content/media/webaudio/blink/HRTFPanner.cpp b/content/media/webaudio/blink/HRTFPanner.cpp index 14f3f9547e9..1c02e0294b7 100644 --- a/content/media/webaudio/blink/HRTFPanner.cpp +++ b/content/media/webaudio/blink/HRTFPanner.cpp @@ -27,11 +27,10 @@ #include "FFTConvolver.h" #include "HRTFDatabase.h" -#include "WebAudioUtils.h" using namespace std; using namespace mozilla; -using mozilla::dom::WebAudioUtils; +using dom::ChannelInterpretation; namespace WebCore { @@ -55,10 +54,7 @@ HRTFPanner::HRTFPanner(float sampleRate, mozilla::TemporaryRef 0 ? - static_cast(inputBus->mChannelData[0]) : nullptr; - const float* sourceR = numInputChannels > 1 ? - static_cast(inputBus->mChannelData[1]) : sourceL; + // Get destination pointers. float* destinationL = static_cast(const_cast(outputBus->mChannelData[0])); float* destinationR = @@ -220,12 +211,27 @@ void HRTFPanner::pan(double desiredAzimuth, double elevation, const AudioChunk* MOZ_ASSERT(frameDelayL2 / sampleRate() < MaxDelayTimeSeconds && frameDelayR2 / sampleRate() < MaxDelayTimeSeconds); // Crossfade inter-aural delays based on transitions. - double frameDelayL = (1 - m_crossfadeX) * frameDelayL1 + m_crossfadeX * frameDelayL2; - double frameDelayR = (1 - m_crossfadeX) * frameDelayR1 + m_crossfadeX * frameDelayR2; + double frameDelaysL[WEBAUDIO_BLOCK_SIZE]; + double frameDelaysR[WEBAUDIO_BLOCK_SIZE]; + { + float x = m_crossfadeX; + float incr = m_crossfadeIncr; + for (unsigned i = 0; i < WEBAUDIO_BLOCK_SIZE; ++i) { + frameDelaysL[i] = (1 - x) * frameDelayL1 + x * frameDelayL2; + frameDelaysR[i] = (1 - x) * frameDelayR1 + x * frameDelayR2; + x += incr; + } + } // First run through delay lines for inter-aural time difference. - m_delayLineL.Process(frameDelayL, &sourceL, &destinationL, 1, WEBAUDIO_BLOCK_SIZE); - m_delayLineR.Process(frameDelayR, &sourceR, &destinationR, 1, WEBAUDIO_BLOCK_SIZE); + m_delayLine.Write(*inputBus); + // "Speakers" means a mono input is read into both outputs (with possibly + // different delays). + m_delayLine.ReadChannel(frameDelaysL, outputBus, 0, + ChannelInterpretation::Speakers); + m_delayLine.ReadChannel(frameDelaysR, outputBus, 1, + ChannelInterpretation::Speakers); + m_delayLine.NextBlock(); bool needsCrossfading = m_crossfadeIncr; @@ -283,7 +289,7 @@ int HRTFPanner::maxTailFrames() const // tailTime of the DelayKernel and the tailTime of the FFTConvolver. // The FFTConvolver has a tail time of fftSize(), including latency of // fftSize()/2. - return m_delayLineL.MaxDelayFrames() + fftSize(); + return m_delayLine.MaxDelayTicks() + fftSize(); } } // namespace WebCore diff --git a/content/media/webaudio/blink/HRTFPanner.h b/content/media/webaudio/blink/HRTFPanner.h index a834e201c23..5ea8a429ad6 100644 --- a/content/media/webaudio/blink/HRTFPanner.h +++ b/content/media/webaudio/blink/HRTFPanner.h @@ -99,8 +99,7 @@ private: FFTConvolver m_convolverL2; FFTConvolver m_convolverR2; - mozilla::DelayBuffer m_delayLineL; - mozilla::DelayBuffer m_delayLineR; + mozilla::DelayBuffer m_delayLine; AudioFloatArray m_tempL1; AudioFloatArray m_tempR1; From 79c3c6431946008cd09aee2d2118f9666fff60ed Mon Sep 17 00:00:00 2001 From: Karl Tomlinson Date: Wed, 5 Mar 2014 10:06:57 +1300 Subject: [PATCH 018/112] b=932400 allow DelayNodeEngine to produce output before input r=padenot --HG-- extra : rebase_source : 73991e2d1438862e05bb5a299a6f90935c4a51b2 --- content/media/AudioNodeEngine.h | 9 ++++++++ content/media/AudioNodeStream.cpp | 7 ------ content/media/webaudio/DelayNode.cpp | 33 +++++++++++++++++++++++----- 3 files changed, 36 insertions(+), 13 deletions(-) diff --git a/content/media/AudioNodeEngine.h b/content/media/AudioNodeEngine.h index 5b893cc2eea..66e2f0e882d 100644 --- a/content/media/AudioNodeEngine.h +++ b/content/media/AudioNodeEngine.h @@ -263,6 +263,15 @@ public: MOZ_ASSERT(mInputCount <= 1 && mOutputCount <= 1); *aOutput = aInput; } + /** + * Produce the next block of audio samples, before input is provided. + * ProduceAudioBlock() will be called later, and it then should not change + * aOutput. This is used only for DelayNodeEngine in a feedback loop. + */ + virtual void ProduceBlockBeforeInput(AudioChunk* aOutput) + { + NS_NOTREACHED("ProduceBlockBeforeInput called on wrong engine\n"); + } /** * Produce the next block of audio samples, given input samples in the aInput diff --git a/content/media/AudioNodeStream.cpp b/content/media/AudioNodeStream.cpp index a59bae6963b..861e2f2c19a 100644 --- a/content/media/AudioNodeStream.cpp +++ b/content/media/AudioNodeStream.cpp @@ -426,13 +426,6 @@ AudioNodeStream::ProduceOutput(GraphTime aFrom, GraphTime aTo, uint32_t aFlags) ObtainInputBlock(inputChunks[i], i); } bool finished = false; -#ifdef DEBUG - for (uint16_t i = 0; i < outputCount; ++i) { - // Alter mDuration so we can detect if ProduceAudioBlock fails to set - // chunks. - mLastChunks[i].mDuration--; - } -#endif if (maxInputs <= 1 && mEngine->OutputCount() <= 1) { mEngine->ProduceAudioBlock(this, inputChunks[0], &mLastChunks[0], &finished); } else { diff --git a/content/media/webaudio/DelayNode.cpp b/content/media/webaudio/DelayNode.cpp index 0c8fded3c34..ffd5e54026b 100644 --- a/content/media/webaudio/DelayNode.cpp +++ b/content/media/webaudio/DelayNode.cpp @@ -40,6 +40,7 @@ public: , mBuffer(aMaxDelayTicks, WebAudioUtils::ComputeSmoothingRate(0.02, mDestination->SampleRate())) + , mLastOutputPosition(-1) , mLeftOverData(INT32_MIN) { } @@ -75,7 +76,7 @@ public: virtual void ProduceAudioBlock(AudioNodeStream* aStream, const AudioChunk& aInput, AudioChunk* aOutput, - bool* aFinished) + bool* aFinished) MOZ_OVERRIDE { MOZ_ASSERT(mSource == aStream, "Invalid source stream"); MOZ_ASSERT(aStream->SampleRate() == mDestination->SampleRate()); @@ -107,12 +108,24 @@ public: mBuffer.Write(aInput); - bool inCycle = aStream->AsProcessedStream()->InCycle(); + UpdateOutputBlock(aOutput); + mBuffer.NextBlock(); + } + + void UpdateOutputBlock(AudioChunk* aOutput) + { + TrackTicks tick = mSource->GetCurrentPosition(); + if (tick == mLastOutputPosition) { + return; // mLastChunks is already set on the stream + } + + mLastOutputPosition = tick; + bool inCycle = mSource->AsProcessedStream()->InCycle(); double minDelay = inCycle ? static_cast(WEBAUDIO_BLOCK_SIZE) : 0.0; double maxDelay = mBuffer.MaxDelayTicks(); - double sampleRate = aStream->SampleRate(); + double sampleRate = mSource->SampleRate(); ChannelInterpretation channelInterpretation = - aStream->GetChannelInterpretation(); + mSource->GetChannelInterpretation(); if (mDelay.HasSimpleValue()) { // If this DelayNode is in a cycle, make sure the delay value is at least // one block. @@ -124,7 +137,6 @@ public: // If this DelayNode is in a cycle, make sure the delay value is at least // one block. double computedDelay[WEBAUDIO_BLOCK_SIZE]; - TrackTicks tick = aStream->GetCurrentPosition(); for (size_t counter = 0; counter < WEBAUDIO_BLOCK_SIZE; ++counter) { double delayAtTick = mDelay.GetValueAtTime(tick, counter) * sampleRate; double delayAtTickClamped = clamped(delayAtTick, minDelay, maxDelay); @@ -132,13 +144,22 @@ public: } mBuffer.Read(computedDelay, aOutput, channelInterpretation); } - mBuffer.NextBlock(); + } + + virtual void ProduceBlockBeforeInput(AudioChunk* aOutput) MOZ_OVERRIDE + { + if (mLeftOverData <= 0) { + aOutput->SetNull(WEBAUDIO_BLOCK_SIZE); + } else { + UpdateOutputBlock(aOutput); + } } AudioNodeStream* mSource; AudioNodeStream* mDestination; AudioParamTimeline mDelay; DelayBuffer mBuffer; + TrackTicks mLastOutputPosition; // How much data we have in our buffer which needs to be flushed out when our inputs // finish. int32_t mLeftOverData; From 2bb6ffd9ed4706946f2048d3929dc03213cc3923 Mon Sep 17 00:00:00 2001 From: Karl Tomlinson Date: Wed, 5 Mar 2014 10:09:49 +1300 Subject: [PATCH 019/112] b=932400 rename ProduceAudioBlock to ProcessBlock r=padenot --HG-- rename : content/media/webaudio/DelayProcessor.cpp => content/media/webaudio/DelayBuffer.cpp extra : rebase_source : ebdc7404c8d27e3a24098f21a7752df529bb44c9 --- content/media/AudioNodeEngine.h | 22 +++++++++---------- content/media/AudioNodeStream.cpp | 4 ++-- content/media/webaudio/AnalyserNode.cpp | 8 +++---- .../media/webaudio/AudioBufferSourceNode.cpp | 8 +++---- .../media/webaudio/AudioDestinationNode.cpp | 16 +++++++------- content/media/webaudio/BiquadFilterNode.cpp | 8 +++---- content/media/webaudio/ChannelMergerNode.cpp | 8 +++---- .../media/webaudio/ChannelSplitterNode.cpp | 8 +++---- content/media/webaudio/ConvolverNode.cpp | 8 +++---- content/media/webaudio/DelayBuffer.cpp | 2 +- content/media/webaudio/DelayNode.cpp | 8 +++---- .../media/webaudio/DynamicsCompressorNode.cpp | 8 +++---- content/media/webaudio/GainNode.cpp | 8 +++---- .../MediaStreamAudioDestinationNode.cpp | 8 +++---- content/media/webaudio/OscillatorNode.cpp | 8 +++---- content/media/webaudio/PannerNode.cpp | 8 +++---- .../media/webaudio/ScriptProcessorNode.cpp | 8 +++---- content/media/webaudio/WaveShaperNode.cpp | 8 +++---- 18 files changed, 78 insertions(+), 78 deletions(-) diff --git a/content/media/AudioNodeEngine.h b/content/media/AudioNodeEngine.h index 66e2f0e882d..66c32c778c9 100644 --- a/content/media/AudioNodeEngine.h +++ b/content/media/AudioNodeEngine.h @@ -255,17 +255,17 @@ public: * *aFinished is set to false by the caller. If the callee sets it to true, * we'll finish the stream and not call this again. */ - virtual void ProduceAudioBlock(AudioNodeStream* aStream, - const AudioChunk& aInput, - AudioChunk* aOutput, - bool* aFinished) + virtual void ProcessBlock(AudioNodeStream* aStream, + const AudioChunk& aInput, + AudioChunk* aOutput, + bool* aFinished) { MOZ_ASSERT(mInputCount <= 1 && mOutputCount <= 1); *aOutput = aInput; } /** * Produce the next block of audio samples, before input is provided. - * ProduceAudioBlock() will be called later, and it then should not change + * ProcessBlock() will be called later, and it then should not change * aOutput. This is used only for DelayNodeEngine in a feedback loop. */ virtual void ProduceBlockBeforeInput(AudioChunk* aOutput) @@ -276,8 +276,8 @@ public: /** * Produce the next block of audio samples, given input samples in the aInput * array. There is one input sample per active port in aInput, in order. - * This is the multi-input/output version of ProduceAudioBlock. Only one kind - * of ProduceAudioBlock is called on each node, depending on whether the + * This is the multi-input/output version of ProcessBlock. Only one kind + * of ProcessBlock is called on each node, depending on whether the * number of inputs and outputs are both 1 or not. * * aInput is always guaranteed to not contain more input AudioChunks than the @@ -288,10 +288,10 @@ public: * corresponding AudioNode, in which case it will be interpreted as a channel * of silence. */ - virtual void ProduceAudioBlocksOnPorts(AudioNodeStream* aStream, - const OutputChunks& aInput, - OutputChunks& aOutput, - bool* aFinished) + virtual void ProcessBlocksOnPorts(AudioNodeStream* aStream, + const OutputChunks& aInput, + OutputChunks& aOutput, + bool* aFinished) { MOZ_ASSERT(mInputCount > 1 || mOutputCount > 1); // Only produce one output port, and drop all other input ports. diff --git a/content/media/AudioNodeStream.cpp b/content/media/AudioNodeStream.cpp index 861e2f2c19a..79ab224bfc5 100644 --- a/content/media/AudioNodeStream.cpp +++ b/content/media/AudioNodeStream.cpp @@ -427,9 +427,9 @@ AudioNodeStream::ProduceOutput(GraphTime aFrom, GraphTime aTo, uint32_t aFlags) } bool finished = false; if (maxInputs <= 1 && mEngine->OutputCount() <= 1) { - mEngine->ProduceAudioBlock(this, inputChunks[0], &mLastChunks[0], &finished); + mEngine->ProcessBlock(this, inputChunks[0], &mLastChunks[0], &finished); } else { - mEngine->ProduceAudioBlocksOnPorts(this, inputChunks, mLastChunks, &finished); + mEngine->ProcessBlocksOnPorts(this, inputChunks, mLastChunks, &finished); } for (uint16_t i = 0; i < outputCount; ++i) { NS_ASSERTION(mLastChunks[i].GetDuration() == WEBAUDIO_BLOCK_SIZE, diff --git a/content/media/webaudio/AnalyserNode.cpp b/content/media/webaudio/AnalyserNode.cpp index da764314f6b..61c54aa18ac 100644 --- a/content/media/webaudio/AnalyserNode.cpp +++ b/content/media/webaudio/AnalyserNode.cpp @@ -57,10 +57,10 @@ public: MOZ_ASSERT(NS_IsMainThread()); } - virtual void ProduceAudioBlock(AudioNodeStream* aStream, - const AudioChunk& aInput, - AudioChunk* aOutput, - bool* aFinished) MOZ_OVERRIDE + virtual void ProcessBlock(AudioNodeStream* aStream, + const AudioChunk& aInput, + AudioChunk* aOutput, + bool* aFinished) MOZ_OVERRIDE { *aOutput = aInput; diff --git a/content/media/webaudio/AudioBufferSourceNode.cpp b/content/media/webaudio/AudioBufferSourceNode.cpp index 3257b0a07f9..6a11e072533 100644 --- a/content/media/webaudio/AudioBufferSourceNode.cpp +++ b/content/media/webaudio/AudioBufferSourceNode.cpp @@ -423,10 +423,10 @@ public: UpdateResampler(outRate, aChannels); } - virtual void ProduceAudioBlock(AudioNodeStream* aStream, - const AudioChunk& aInput, - AudioChunk* aOutput, - bool* aFinished) + virtual void ProcessBlock(AudioNodeStream* aStream, + const AudioChunk& aInput, + AudioChunk* aOutput, + bool* aFinished) { if (!mBuffer || !mBufferEnd) { aOutput->SetNull(WEBAUDIO_BLOCK_SIZE); diff --git a/content/media/webaudio/AudioDestinationNode.cpp b/content/media/webaudio/AudioDestinationNode.cpp index 9ce18c21d23..e03eff993ee 100644 --- a/content/media/webaudio/AudioDestinationNode.cpp +++ b/content/media/webaudio/AudioDestinationNode.cpp @@ -52,10 +52,10 @@ public: } } - virtual void ProduceAudioBlock(AudioNodeStream* aStream, - const AudioChunk& aInput, - AudioChunk* aOutput, - bool* aFinished) MOZ_OVERRIDE + virtual void ProcessBlock(AudioNodeStream* aStream, + const AudioChunk& aInput, + AudioChunk* aOutput, + bool* aFinished) MOZ_OVERRIDE { // Do this just for the sake of political correctness; this output // will not go anywhere. @@ -165,10 +165,10 @@ public: { } - virtual void ProduceAudioBlock(AudioNodeStream* aStream, - const AudioChunk& aInput, - AudioChunk* aOutput, - bool* aFinished) MOZ_OVERRIDE + virtual void ProcessBlock(AudioNodeStream* aStream, + const AudioChunk& aInput, + AudioChunk* aOutput, + bool* aFinished) MOZ_OVERRIDE { *aOutput = aInput; aOutput->mVolume *= mVolume; diff --git a/content/media/webaudio/BiquadFilterNode.cpp b/content/media/webaudio/BiquadFilterNode.cpp index da6cfd5e4bd..b7baade5c37 100644 --- a/content/media/webaudio/BiquadFilterNode.cpp +++ b/content/media/webaudio/BiquadFilterNode.cpp @@ -137,10 +137,10 @@ public: } } - virtual void ProduceAudioBlock(AudioNodeStream* aStream, - const AudioChunk& aInput, - AudioChunk* aOutput, - bool* aFinished) MOZ_OVERRIDE + virtual void ProcessBlock(AudioNodeStream* aStream, + const AudioChunk& aInput, + AudioChunk* aOutput, + bool* aFinished) MOZ_OVERRIDE { float inputBuffer[WEBAUDIO_BLOCK_SIZE]; diff --git a/content/media/webaudio/ChannelMergerNode.cpp b/content/media/webaudio/ChannelMergerNode.cpp index 606e060adb2..ac8bd934cd4 100644 --- a/content/media/webaudio/ChannelMergerNode.cpp +++ b/content/media/webaudio/ChannelMergerNode.cpp @@ -23,10 +23,10 @@ public: MOZ_ASSERT(NS_IsMainThread()); } - virtual void ProduceAudioBlocksOnPorts(AudioNodeStream* aStream, - const OutputChunks& aInput, - OutputChunks& aOutput, - bool* aFinished) MOZ_OVERRIDE + virtual void ProcessBlocksOnPorts(AudioNodeStream* aStream, + const OutputChunks& aInput, + OutputChunks& aOutput, + bool* aFinished) MOZ_OVERRIDE { MOZ_ASSERT(aInput.Length() >= 1, "Should have one or more input ports"); diff --git a/content/media/webaudio/ChannelSplitterNode.cpp b/content/media/webaudio/ChannelSplitterNode.cpp index 2436f539ee2..47424aef6c6 100644 --- a/content/media/webaudio/ChannelSplitterNode.cpp +++ b/content/media/webaudio/ChannelSplitterNode.cpp @@ -23,10 +23,10 @@ public: MOZ_ASSERT(NS_IsMainThread()); } - virtual void ProduceAudioBlocksOnPorts(AudioNodeStream* aStream, - const OutputChunks& aInput, - OutputChunks& aOutput, - bool* aFinished) MOZ_OVERRIDE + virtual void ProcessBlocksOnPorts(AudioNodeStream* aStream, + const OutputChunks& aInput, + OutputChunks& aOutput, + bool* aFinished) MOZ_OVERRIDE { MOZ_ASSERT(aInput.Length() == 1, "Should only have one input port"); diff --git a/content/media/webaudio/ConvolverNode.cpp b/content/media/webaudio/ConvolverNode.cpp index cea23389aaa..e6b457fb5dc 100644 --- a/content/media/webaudio/ConvolverNode.cpp +++ b/content/media/webaudio/ConvolverNode.cpp @@ -101,10 +101,10 @@ public: mNormalize, mSampleRate); } - virtual void ProduceAudioBlock(AudioNodeStream* aStream, - const AudioChunk& aInput, - AudioChunk* aOutput, - bool* aFinished) + virtual void ProcessBlock(AudioNodeStream* aStream, + const AudioChunk& aInput, + AudioChunk* aOutput, + bool* aFinished) { if (!mReverb) { *aOutput = aInput; diff --git a/content/media/webaudio/DelayBuffer.cpp b/content/media/webaudio/DelayBuffer.cpp index 79089f799cf..be6eaf43ba9 100644 --- a/content/media/webaudio/DelayBuffer.cpp +++ b/content/media/webaudio/DelayBuffer.cpp @@ -74,7 +74,7 @@ DelayBuffer::Read(const double aPerFrameDelays[WEBAUDIO_BLOCK_SIZE], aOutputChunk->SetNull(WEBAUDIO_BLOCK_SIZE); } - // Remember currentDelayFrames for the next ProduceAudioBlock call + // Remember currentDelayFrames for the next ProcessBlock call mCurrentDelay = aPerFrameDelays[WEBAUDIO_BLOCK_SIZE - 1]; } diff --git a/content/media/webaudio/DelayNode.cpp b/content/media/webaudio/DelayNode.cpp index ffd5e54026b..97607af1f3f 100644 --- a/content/media/webaudio/DelayNode.cpp +++ b/content/media/webaudio/DelayNode.cpp @@ -73,10 +73,10 @@ public: } } - virtual void ProduceAudioBlock(AudioNodeStream* aStream, - const AudioChunk& aInput, - AudioChunk* aOutput, - bool* aFinished) MOZ_OVERRIDE + virtual void ProcessBlock(AudioNodeStream* aStream, + const AudioChunk& aInput, + AudioChunk* aOutput, + bool* aFinished) MOZ_OVERRIDE { MOZ_ASSERT(mSource == aStream, "Invalid source stream"); MOZ_ASSERT(aStream->SampleRate() == mDestination->SampleRate()); diff --git a/content/media/webaudio/DynamicsCompressorNode.cpp b/content/media/webaudio/DynamicsCompressorNode.cpp index 5ea9fb89da0..050e9d372b1 100644 --- a/content/media/webaudio/DynamicsCompressorNode.cpp +++ b/content/media/webaudio/DynamicsCompressorNode.cpp @@ -93,10 +93,10 @@ public: } } - virtual void ProduceAudioBlock(AudioNodeStream* aStream, - const AudioChunk& aInput, - AudioChunk* aOutput, - bool* aFinished) MOZ_OVERRIDE + virtual void ProcessBlock(AudioNodeStream* aStream, + const AudioChunk& aInput, + AudioChunk* aOutput, + bool* aFinished) MOZ_OVERRIDE { if (aInput.IsNull()) { // Just output silence diff --git a/content/media/webaudio/GainNode.cpp b/content/media/webaudio/GainNode.cpp index 39c3cf09d13..3d93ff37403 100644 --- a/content/media/webaudio/GainNode.cpp +++ b/content/media/webaudio/GainNode.cpp @@ -58,10 +58,10 @@ public: } } - virtual void ProduceAudioBlock(AudioNodeStream* aStream, - const AudioChunk& aInput, - AudioChunk* aOutput, - bool* aFinished) + virtual void ProcessBlock(AudioNodeStream* aStream, + const AudioChunk& aInput, + AudioChunk* aOutput, + bool* aFinished) { MOZ_ASSERT(mSource == aStream, "Invalid source stream"); diff --git a/content/media/webaudio/MediaStreamAudioDestinationNode.cpp b/content/media/webaudio/MediaStreamAudioDestinationNode.cpp index 475ce3a0962..fd55614fb88 100644 --- a/content/media/webaudio/MediaStreamAudioDestinationNode.cpp +++ b/content/media/webaudio/MediaStreamAudioDestinationNode.cpp @@ -36,10 +36,10 @@ public: MOZ_ASSERT(mOutputStream); } - virtual void ProduceAudioBlock(AudioNodeStream* aStream, - const AudioChunk& aInput, - AudioChunk* aOutput, - bool* aFinished) MOZ_OVERRIDE + virtual void ProcessBlock(AudioNodeStream* aStream, + const AudioChunk& aInput, + AudioChunk* aOutput, + bool* aFinished) MOZ_OVERRIDE { *aOutput = aInput; StreamBuffer::Track* track = mOutputStream->EnsureTrack(MEDIA_STREAM_DEST_TRACK_ID, diff --git a/content/media/webaudio/OscillatorNode.cpp b/content/media/webaudio/OscillatorNode.cpp index d3b731239c2..26bbaf134e9 100644 --- a/content/media/webaudio/OscillatorNode.cpp +++ b/content/media/webaudio/OscillatorNode.cpp @@ -410,10 +410,10 @@ public: aOutput->SetNull(WEBAUDIO_BLOCK_SIZE); } - virtual void ProduceAudioBlock(AudioNodeStream* aStream, - const AudioChunk& aInput, - AudioChunk* aOutput, - bool* aFinished) MOZ_OVERRIDE + virtual void ProcessBlock(AudioNodeStream* aStream, + const AudioChunk& aInput, + AudioChunk* aOutput, + bool* aFinished) MOZ_OVERRIDE { MOZ_ASSERT(mSource == aStream, "Invalid source stream"); diff --git a/content/media/webaudio/PannerNode.cpp b/content/media/webaudio/PannerNode.cpp index a7267221a09..95a89465ab4 100644 --- a/content/media/webaudio/PannerNode.cpp +++ b/content/media/webaudio/PannerNode.cpp @@ -133,10 +133,10 @@ public: } } - virtual void ProduceAudioBlock(AudioNodeStream* aStream, - const AudioChunk& aInput, - AudioChunk* aOutput, - bool *aFinished) MOZ_OVERRIDE + virtual void ProcessBlock(AudioNodeStream* aStream, + const AudioChunk& aInput, + AudioChunk* aOutput, + bool *aFinished) MOZ_OVERRIDE { if (aInput.IsNull()) { // mLeftOverData != INT_MIN means that the panning model was HRTF and a diff --git a/content/media/webaudio/ScriptProcessorNode.cpp b/content/media/webaudio/ScriptProcessorNode.cpp index 1e5b1b8541b..69405fcfc29 100644 --- a/content/media/webaudio/ScriptProcessorNode.cpp +++ b/content/media/webaudio/ScriptProcessorNode.cpp @@ -239,10 +239,10 @@ public: mSource = aSource; } - virtual void ProduceAudioBlock(AudioNodeStream* aStream, - const AudioChunk& aInput, - AudioChunk* aOutput, - bool* aFinished) MOZ_OVERRIDE + virtual void ProcessBlock(AudioNodeStream* aStream, + const AudioChunk& aInput, + AudioChunk* aOutput, + bool* aFinished) MOZ_OVERRIDE { MutexAutoLock lock(NodeMutex()); diff --git a/content/media/webaudio/WaveShaperNode.cpp b/content/media/webaudio/WaveShaperNode.cpp index 71e041d2cb1..43a5d5fb765 100644 --- a/content/media/webaudio/WaveShaperNode.cpp +++ b/content/media/webaudio/WaveShaperNode.cpp @@ -202,10 +202,10 @@ public: } } - virtual void ProduceAudioBlock(AudioNodeStream* aStream, - const AudioChunk& aInput, - AudioChunk* aOutput, - bool* aFinished) + virtual void ProcessBlock(AudioNodeStream* aStream, + const AudioChunk& aInput, + AudioChunk* aOutput, + bool* aFinished) { uint32_t channelCount = aInput.mChannelData.Length(); if (!mCurve.Length() || !channelCount) { From 7f18d462d4d11e9a580d24954d5ea191b6fec788 Mon Sep 17 00:00:00 2001 From: Karl Tomlinson Date: Wed, 5 Mar 2014 10:53:55 +1300 Subject: [PATCH 020/112] b=932400 rename ProduceOutput to ProcessInput r=roc --HG-- extra : transplant_source : m0%91%3D%99%EB.%20%28%BD%B4%F4%A5%3F%0C%13%22%BA%FD%06 --- content/media/AudioNodeExternalInputStream.cpp | 4 ++-- content/media/AudioNodeExternalInputStream.h | 2 +- content/media/AudioNodeStream.cpp | 2 +- content/media/AudioNodeStream.h | 2 +- content/media/MediaStreamGraph.cpp | 8 ++++---- content/media/MediaStreamGraph.h | 8 ++++---- content/media/TrackUnionStream.h | 2 +- 7 files changed, 14 insertions(+), 14 deletions(-) diff --git a/content/media/AudioNodeExternalInputStream.cpp b/content/media/AudioNodeExternalInputStream.cpp index 5fdf8a134c5..daeaad7c7b2 100644 --- a/content/media/AudioNodeExternalInputStream.cpp +++ b/content/media/AudioNodeExternalInputStream.cpp @@ -324,8 +324,8 @@ ConvertSegmentToAudioBlock(AudioSegment* aSegment, AudioChunk* aBlock) } void -AudioNodeExternalInputStream::ProduceOutput(GraphTime aFrom, GraphTime aTo, - uint32_t aFlags) +AudioNodeExternalInputStream::ProcessInput(GraphTime aFrom, GraphTime aTo, + uint32_t aFlags) { // According to spec, number of outputs is always 1. mLastChunks.SetLength(1); diff --git a/content/media/AudioNodeExternalInputStream.h b/content/media/AudioNodeExternalInputStream.h index 9710a229279..06134d3752f 100644 --- a/content/media/AudioNodeExternalInputStream.h +++ b/content/media/AudioNodeExternalInputStream.h @@ -25,7 +25,7 @@ public: AudioNodeExternalInputStream(AudioNodeEngine* aEngine, TrackRate aSampleRate); ~AudioNodeExternalInputStream(); - virtual void ProduceOutput(GraphTime aFrom, GraphTime aTo, uint32_t aFlags) MOZ_OVERRIDE; + virtual void ProcessInput(GraphTime aFrom, GraphTime aTo, uint32_t aFlags) MOZ_OVERRIDE; private: // For storing pointers and data about input tracks, like the last TrackTick which diff --git a/content/media/AudioNodeStream.cpp b/content/media/AudioNodeStream.cpp index 79ab224bfc5..1e77f7f2df5 100644 --- a/content/media/AudioNodeStream.cpp +++ b/content/media/AudioNodeStream.cpp @@ -399,7 +399,7 @@ AudioNodeStream::UpMixDownMixChunk(const AudioChunk* aChunk, // The MediaStreamGraph guarantees that this is actually one block, for // AudioNodeStreams. void -AudioNodeStream::ProduceOutput(GraphTime aFrom, GraphTime aTo, uint32_t aFlags) +AudioNodeStream::ProcessInput(GraphTime aFrom, GraphTime aTo, uint32_t aFlags) { EnsureTrack(AUDIO_TRACK, mSampleRate); // No more tracks will be coming diff --git a/content/media/AudioNodeStream.h b/content/media/AudioNodeStream.h index 91d244c1b26..3c15e7830f1 100644 --- a/content/media/AudioNodeStream.h +++ b/content/media/AudioNodeStream.h @@ -103,7 +103,7 @@ public: void SetChannelMixingParametersImpl(uint32_t aNumberOfChannels, ChannelCountMode aChannelCountMoe, ChannelInterpretation aChannelInterpretation); - virtual void ProduceOutput(GraphTime aFrom, GraphTime aTo, uint32_t aFlags) MOZ_OVERRIDE; + virtual void ProcessInput(GraphTime aFrom, GraphTime aTo, uint32_t aFlags) MOZ_OVERRIDE; TrackTicks GetCurrentPosition(); bool IsAudioParamStream() const { diff --git a/content/media/MediaStreamGraph.cpp b/content/media/MediaStreamGraph.cpp index 9ea8cc57859..3a14b850700 100644 --- a/content/media/MediaStreamGraph.cpp +++ b/content/media/MediaStreamGraph.cpp @@ -1102,7 +1102,7 @@ MediaStreamGraphImpl::ProduceDataForStreamsBlockByBlock(uint32_t aStreamIndex, for (uint32_t i = aStreamIndex; i < mStreams.Length(); ++i) { ProcessedMediaStream* ps = mStreams[i]->AsProcessedStream(); if (ps) { - ps->ProduceOutput(t, next, (next == aTo) ? ProcessedMediaStream::ALLOW_FINISH : 0); + ps->ProcessInput(t, next, (next == aTo) ? ProcessedMediaStream::ALLOW_FINISH : 0); } } t = next; @@ -1211,7 +1211,7 @@ MediaStreamGraphImpl::RunThread() // Play stream contents. bool allBlockedForever = true; - // True when we've done ProduceOutput for all processed streams. + // True when we've done ProcessInput for all processed streams. bool doneAllProducing = false; // Figure out what each stream wants to do for (uint32_t i = 0; i < mStreams.Length(); ++i) { @@ -1237,8 +1237,8 @@ MediaStreamGraphImpl::RunThread() ticksProcessed += TimeToTicksRoundDown(n->SampleRate(), mStateComputedTime - prevComputedTime); doneAllProducing = true; } else { - ps->ProduceOutput(prevComputedTime, mStateComputedTime, - ProcessedMediaStream::ALLOW_FINISH); + ps->ProcessInput(prevComputedTime, mStateComputedTime, + ProcessedMediaStream::ALLOW_FINISH); NS_WARN_IF_FALSE(stream->mBuffer.GetEnd() >= GraphTimeToStreamTime(stream, mStateComputedTime), "Stream did not produce enough data"); diff --git a/content/media/MediaStreamGraph.h b/content/media/MediaStreamGraph.h index cbff7e4c3ad..299fff48d70 100644 --- a/content/media/MediaStreamGraph.h +++ b/content/media/MediaStreamGraph.h @@ -906,7 +906,7 @@ protected: /** * This stream processes zero or more input streams in parallel to produce * its output. The details of how the output is produced are handled by - * subclasses overriding the ProduceOutput method. + * subclasses overriding the ProcessInput method. */ class ProcessedMediaStream : public MediaStream { public: @@ -962,7 +962,7 @@ public: * This will be called on streams that have finished. Most stream types should * just return immediately if IsFinishedOnGraphThread(), but some may wish to * update internal state (see AudioNodeStream). - * ProduceOutput is allowed to call FinishOnGraphThread only if ALLOW_FINISH + * ProcessInput is allowed to call FinishOnGraphThread only if ALLOW_FINISH * is in aFlags. (This flag will be set when aTo >= mStateComputedTime, i.e. * when we've producing the last block of data we need to produce.) Otherwise * we can get into a situation where we've determined the stream should not @@ -972,7 +972,7 @@ public: enum { ALLOW_FINISH = 0x01 }; - virtual void ProduceOutput(GraphTime aFrom, GraphTime aTo, uint32_t aFlags) = 0; + virtual void ProcessInput(GraphTime aFrom, GraphTime aTo, uint32_t aFlags) = 0; void SetAutofinishImpl(bool aAutofinish) { mAutofinish = aAutofinish; } /** @@ -1065,7 +1065,7 @@ public: * Dispatches a runnable that will run on the main thread after all * main-thread stream state has been next updated. * Should only be called during MediaStreamListener callbacks or during - * ProcessedMediaStream::ProduceOutput(). + * ProcessedMediaStream::ProcessInput(). */ void DispatchToMainThreadAfterStreamStateUpdate(already_AddRefed aRunnable) { diff --git a/content/media/TrackUnionStream.h b/content/media/TrackUnionStream.h index 18dad814887..c3abb6ccbab 100644 --- a/content/media/TrackUnionStream.h +++ b/content/media/TrackUnionStream.h @@ -39,7 +39,7 @@ public: } ProcessedMediaStream::RemoveInput(aPort); } - virtual void ProduceOutput(GraphTime aFrom, GraphTime aTo, uint32_t aFlags) MOZ_OVERRIDE + virtual void ProcessInput(GraphTime aFrom, GraphTime aTo, uint32_t aFlags) MOZ_OVERRIDE { if (IsFinishedOnGraphThread()) { return; From 0adbf0d8877e4ed51faf3b4f7d364c91b963a60a Mon Sep 17 00:00:00 2001 From: John Schoenick Date: Wed, 26 Feb 2014 14:48:40 -0800 Subject: [PATCH 021/112] Bug 976924 - Ensure we're not racing with async plugin teardown events. r=gfritzsche --- dom/plugins/test/mochitest/test_bug852315.html | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/dom/plugins/test/mochitest/test_bug852315.html b/dom/plugins/test/mochitest/test_bug852315.html index 2cbf8a2c208..b60a548b781 100644 --- a/dom/plugins/test/mochitest/test_bug852315.html +++ b/dom/plugins/test/mochitest/test_bug852315.html @@ -38,8 +38,11 @@ i.addEventListener("load", function loadfunc() { i.removeEventListener("load", loadfunc); i.src = "about:blank"; SimpleTest.executeSoon(function() { - ok(destroyran, "OnDestroy callback ran and did not crash"); - SimpleTest.finish(); + // Ensure this event doesn't race with CheckPluginStopEvent + SimpleTest.executeSoon(function() { + ok(destroyran, "OnDestroy callback ran and did not crash"); + SimpleTest.finish(); + }); }); }); document.body.appendChild(i); From 55ae71a452d64c5cf9745a7dc0beddd63867d66a Mon Sep 17 00:00:00 2001 From: Wes Kocher Date: Tue, 4 Mar 2014 14:15:33 -0800 Subject: [PATCH 022/112] Backed out changeset 3f8a7062ad8d (bug 978203) for build bustage on a CLOSED TREE --- content/base/public/nsIDocument.h | 1 - content/base/public/nsINode.h | 11 ++--------- content/base/src/nsDocument.cpp | 1 - content/base/src/nsFrameMessageManager.cpp | 1 - content/svg/content/src/SVGTransform.cpp | 1 - dom/base/nsGlobalWindow.cpp | 1 - dom/base/nsWindowMemoryReporter.h | 7 +++++++ image/src/SurfaceCache.cpp | 1 - js/xpconnect/src/XPCComponents.cpp | 1 - js/xpconnect/src/xpcprivate.h | 1 - layout/base/nsPresShell.cpp | 1 - layout/xul/nsXULPopupManager.h | 1 - 12 files changed, 9 insertions(+), 19 deletions(-) diff --git a/content/base/public/nsIDocument.h b/content/base/public/nsIDocument.h index 0ef07f43679..10a2a8d26d0 100644 --- a/content/base/public/nsIDocument.h +++ b/content/base/public/nsIDocument.h @@ -19,7 +19,6 @@ #include "nsPIDOMWindow.h" // for use in inline functions #include "nsPropertyTable.h" // for member #include "nsTHashtable.h" // for member -#include "nsWeakReference.h" #include "mozilla/dom/DocumentBinding.h" #include "mozilla/WeakPtr.h" #include "Units.h" diff --git a/content/base/public/nsINode.h b/content/base/public/nsINode.h index ed6618a6ac1..ef09fa1f284 100644 --- a/content/base/public/nsINode.h +++ b/content/base/public/nsINode.h @@ -15,6 +15,7 @@ #include "nsNodeInfoManager.h" // for use in NodePrincipal() #include "nsPropertyTable.h" // for typedefs #include "nsTObserverArray.h" // for member +#include "nsWindowMemoryReporter.h" // for NS_DECL_SIZEOF_EXCLUDING_THIS #include "mozilla/ErrorResult.h" #include "mozilla/MemoryReporting.h" #include "mozilla/dom/EventTarget.h" // for base class @@ -243,21 +244,13 @@ private: // ever passed to Mutated(). enum { eMaxMutations = 300 }; - + // sMutationCount is a global mutation counter which is decreased by one at // every mutation. It is capped at 0 to avoid wrapping. // Its value is always between 0 and 300, inclusive. static uint32_t sMutationCount; }; -// This should be used for any nsINode sub-class that has fields of its own -// that it needs to measure; any sub-class that doesn't use it will inherit -// SizeOfExcludingThis from its super-class. SizeOfIncludingThis() need not be -// defined, it is inherited from nsINode. -// This macro isn't actually specific to nodes, and bug 956400 will move it into MFBT. -#define NS_DECL_SIZEOF_EXCLUDING_THIS \ - virtual size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const; - // Categories of node properties // 0 is global. #define DOM_USER_DATA 1 diff --git a/content/base/src/nsDocument.cpp b/content/base/src/nsDocument.cpp index accae78ae87..1826ac98a72 100644 --- a/content/base/src/nsDocument.cpp +++ b/content/base/src/nsDocument.cpp @@ -221,7 +221,6 @@ #include "nsIMutableArray.h" #include "nsContentPermissionHelper.h" #include "mozilla/dom/DOMStringList.h" -#include "nsWindowMemoryReporter.h" using namespace mozilla; using namespace mozilla::dom; diff --git a/content/base/src/nsFrameMessageManager.cpp b/content/base/src/nsFrameMessageManager.cpp index fded1caf70a..df889d57fec 100644 --- a/content/base/src/nsFrameMessageManager.cpp +++ b/content/base/src/nsFrameMessageManager.cpp @@ -23,7 +23,6 @@ #include "nsIXULRuntime.h" #include "nsIScriptError.h" #include "nsIConsoleService.h" -#include "nsIMemoryReporter.h" #include "nsIProtocolHandler.h" #include "nsIScriptSecurityManager.h" #include "nsIJSRuntimeService.h" diff --git a/content/svg/content/src/SVGTransform.cpp b/content/svg/content/src/SVGTransform.cpp index 53ad781372b..a45e1adf66e 100644 --- a/content/svg/content/src/SVGTransform.cpp +++ b/content/svg/content/src/SVGTransform.cpp @@ -12,7 +12,6 @@ #include "nsError.h" #include "nsSVGAnimatedTransformList.h" #include "nsSVGAttrTearoffTable.h" -#include "mozilla/DebugOnly.h" namespace { const double kRadPerDegree = 2.0 * M_PI / 360.0; diff --git a/dom/base/nsGlobalWindow.cpp b/dom/base/nsGlobalWindow.cpp index 759b2889fdb..053e14cdb7e 100644 --- a/dom/base/nsGlobalWindow.cpp +++ b/dom/base/nsGlobalWindow.cpp @@ -35,7 +35,6 @@ #include "nsIScriptTimeoutHandler.h" #include "nsIController.h" #include "nsScriptNameSpaceManager.h" -#include "nsWindowMemoryReporter.h" // Helper Classes #include "nsJSUtils.h" diff --git a/dom/base/nsWindowMemoryReporter.h b/dom/base/nsWindowMemoryReporter.h index 214b55f2a62..301497c9910 100644 --- a/dom/base/nsWindowMemoryReporter.h +++ b/dom/base/nsWindowMemoryReporter.h @@ -19,6 +19,13 @@ #include "mozilla/TimeStamp.h" #include "nsArenaMemoryStats.h" +// This should be used for any nsINode sub-class that has fields of its own +// that it needs to measure; any sub-class that doesn't use it will inherit +// SizeOfExcludingThis from its super-class. SizeOfIncludingThis() need not be +// defined, it is inherited from nsINode. +#define NS_DECL_SIZEOF_EXCLUDING_THIS \ + virtual size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const; + class nsWindowSizes { #define FOR_EACH_SIZE(macro) \ macro(DOM, mDOMElementNodesSize) \ diff --git a/image/src/SurfaceCache.cpp b/image/src/SurfaceCache.cpp index cad2efa2a17..972aa78242d 100644 --- a/image/src/SurfaceCache.cpp +++ b/image/src/SurfaceCache.cpp @@ -15,7 +15,6 @@ #include "mozilla/Preferences.h" #include "mozilla/RefPtr.h" #include "mozilla/StaticPtr.h" -#include "nsIMemoryReporter.h" #include "gfx2DGlue.h" #include "gfxASurface.h" #include "gfxPattern.h" // Workaround for flaw in bug 921753 part 2. diff --git a/js/xpconnect/src/XPCComponents.cpp b/js/xpconnect/src/XPCComponents.cpp index e595db32d69..d4a0368860c 100644 --- a/js/xpconnect/src/XPCComponents.cpp +++ b/js/xpconnect/src/XPCComponents.cpp @@ -26,7 +26,6 @@ #include "nsZipArchive.h" #include "nsIDOMFile.h" #include "nsIDOMFileList.h" -#include "nsWindowMemoryReporter.h" using namespace mozilla; using namespace JS; diff --git a/js/xpconnect/src/xpcprivate.h b/js/xpconnect/src/xpcprivate.h index 0c7ebd87d12..e64433d4963 100644 --- a/js/xpconnect/src/xpcprivate.h +++ b/js/xpconnect/src/xpcprivate.h @@ -82,7 +82,6 @@ #include "mozilla/GuardObjects.h" #include "mozilla/Maybe.h" #include "mozilla/MemoryReporting.h" -#include "mozilla/TimeStamp.h" #include #include diff --git a/layout/base/nsPresShell.cpp b/layout/base/nsPresShell.cpp index 34a97136b48..ab05c120930 100644 --- a/layout/base/nsPresShell.cpp +++ b/layout/base/nsPresShell.cpp @@ -113,7 +113,6 @@ #include "SVGContentUtils.h" #include "nsSVGEffects.h" #include "SVGFragmentIdentifier.h" -#include "nsArenaMemoryStats.h" #include "nsPerformance.h" #include "nsRefreshDriver.h" diff --git a/layout/xul/nsXULPopupManager.h b/layout/xul/nsXULPopupManager.h index 3a325c6a54c..1273ac667dc 100644 --- a/layout/xul/nsXULPopupManager.h +++ b/layout/xul/nsXULPopupManager.h @@ -17,7 +17,6 @@ #include "nsPoint.h" #include "nsCOMPtr.h" #include "nsTArray.h" -#include "nsIObserver.h" #include "nsITimer.h" #include "nsIReflowCallback.h" #include "nsThreadUtils.h" From cfe6f6fd0a2fbd31caf80488c19febf20266d355 Mon Sep 17 00:00:00 2001 From: Ehsan Akhgari Date: Tue, 4 Mar 2014 17:19:24 -0500 Subject: [PATCH 023/112] Bug 976886 - Port RCINCLUDE to moz.build; r=mshal --HG-- extra : rebase_source : e8a75bc01c3f57516a1a1307de3d170ea07ca1ac --- browser/app/Makefile.in | 1 - browser/app/moz.build | 1 + browser/metro/shell/commandexecutehandler/Makefile.in | 1 - browser/metro/shell/commandexecutehandler/moz.build | 2 ++ dom/plugins/ipc/hangui/Makefile.in | 2 -- dom/plugins/ipc/hangui/moz.build | 2 ++ python/mozbuild/mozbuild/frontend/emitter.py | 1 + python/mozbuild/mozbuild/frontend/sandbox_symbols.py | 6 ++++++ .../mozbuild/test/backend/data/variable_passthru/moz.build | 1 + .../mozbuild/mozbuild/test/backend/test_recursivemake.py | 3 +++ .../test/frontend/data/variable-passthru/moz.build | 1 + python/mozbuild/mozbuild/test/frontend/test_emitter.py | 1 + toolkit/components/maintenanceservice/Makefile.in | 2 -- toolkit/components/maintenanceservice/moz.build | 2 ++ toolkit/crashreporter/client/Makefile.in | 1 - toolkit/crashreporter/client/moz.build | 1 + toolkit/library/Makefile.in | 4 ---- toolkit/library/moz.build | 7 ++++--- toolkit/mozapps/update/updater/Makefile.in | 1 - toolkit/mozapps/update/updater/moz.build | 1 + webapprt/win/Makefile.in | 2 -- webapprt/win/moz.build | 2 ++ xulrunner/app/Makefile.in | 1 - xulrunner/app/moz.build | 3 +++ xulrunner/stub/Makefile.in | 4 ---- xulrunner/stub/moz.build | 1 + 26 files changed, 32 insertions(+), 22 deletions(-) diff --git a/browser/app/Makefile.in b/browser/app/Makefile.in index ad0ecbab38c..7bf91b613f7 100644 --- a/browser/app/Makefile.in +++ b/browser/app/Makefile.in @@ -55,7 +55,6 @@ NSDISTMODE = copy include $(topsrcdir)/config/config.mk ifeq ($(OS_ARCH),WINNT) -RCINCLUDE = splash.rc # Rebuild firefox.exe if the manifest changes - it's included by splash.rc. # (this dependency should really be just for firefox.exe, not other targets) # Note the manifest file exists in the tree, so we use the explicit filename diff --git a/browser/app/moz.build b/browser/app/moz.build index 07fed1c0380..24b862e3f3f 100644 --- a/browser/app/moz.build +++ b/browser/app/moz.build @@ -39,6 +39,7 @@ if CONFIG['_MSC_VER']: WIN32_EXE_LDFLAGS += ['-ENTRY:wmainCRTStartup'] if CONFIG['OS_ARCH'] == 'WINNT': + RCINCLUDE = 'splash.rc' DEFINES['MOZ_PHOENIX'] = True # Control the default heap size. diff --git a/browser/metro/shell/commandexecutehandler/Makefile.in b/browser/metro/shell/commandexecutehandler/Makefile.in index c5559bb1ef4..4436b3fdc76 100644 --- a/browser/metro/shell/commandexecutehandler/Makefile.in +++ b/browser/metro/shell/commandexecutehandler/Makefile.in @@ -5,7 +5,6 @@ include $(topsrcdir)/config/config.mk DIST_PROGRAM = CommandExecuteHandler$(BIN_SUFFIX) -RCINCLUDE = CommandExecuteHandler.rc # Don't link against mozglue.dll MOZ_GLUE_LDFLAGS = diff --git a/browser/metro/shell/commandexecutehandler/moz.build b/browser/metro/shell/commandexecutehandler/moz.build index cd2ac7912ba..e29b41b1e15 100644 --- a/browser/metro/shell/commandexecutehandler/moz.build +++ b/browser/metro/shell/commandexecutehandler/moz.build @@ -18,3 +18,5 @@ for var in ('UNICODE', '_UNICODE', 'NS_NO_XPCOM'): DEFINES[var] = True NO_PGO = True + +RCINCLUDE = 'CommandExecuteHandler.rc' diff --git a/dom/plugins/ipc/hangui/Makefile.in b/dom/plugins/ipc/hangui/Makefile.in index b4631dc739d..12b5a73b7a3 100644 --- a/dom/plugins/ipc/hangui/Makefile.in +++ b/dom/plugins/ipc/hangui/Makefile.in @@ -4,8 +4,6 @@ OS_LIBS = $(call EXPAND_LIBNAME,comctl32) -RCINCLUDE = HangUIDlg.rc - STL_FLAGS = \ -D_HAS_EXCEPTIONS=0 \ $(NULL) diff --git a/dom/plugins/ipc/hangui/moz.build b/dom/plugins/ipc/hangui/moz.build index 90b72b76243..8dc87816b88 100644 --- a/dom/plugins/ipc/hangui/moz.build +++ b/dom/plugins/ipc/hangui/moz.build @@ -18,3 +18,5 @@ DEFINES['NS_NO_XPCOM'] = True if CONFIG['GNU_CC']: WIN32_EXE_LDFLAGS += ['-municode'] + +RCINCLUDE = 'HangUIDlg.rc' diff --git a/python/mozbuild/mozbuild/frontend/emitter.py b/python/mozbuild/mozbuild/frontend/emitter.py index 6795aa28411..f795c8a82c9 100644 --- a/python/mozbuild/mozbuild/frontend/emitter.py +++ b/python/mozbuild/mozbuild/frontend/emitter.py @@ -241,6 +241,7 @@ class TreeMetadataEmitter(LoggingMixin): 'OS_LIBS', 'RCFILE', 'RESFILE', + 'RCINCLUDE', 'DEFFILE', 'SDK_LIBRARY', 'WIN32_EXE_LDFLAGS', diff --git a/python/mozbuild/mozbuild/frontend/sandbox_symbols.py b/python/mozbuild/mozbuild/frontend/sandbox_symbols.py index ac8cbbcddad..c1140b8090f 100644 --- a/python/mozbuild/mozbuild/frontend/sandbox_symbols.py +++ b/python/mozbuild/mozbuild/frontend/sandbox_symbols.py @@ -349,6 +349,12 @@ VARIABLES = { This variable can only be used on Windows. """, None), + 'RCINCLUDE': (unicode, unicode, + """The resource script file to be included in the default .res file. + + This variable can only be used on Windows. + """, None), + 'DEFFILE': (unicode, unicode, """The program .def (module definition) file. diff --git a/python/mozbuild/mozbuild/test/backend/data/variable_passthru/moz.build b/python/mozbuild/mozbuild/test/backend/data/variable_passthru/moz.build index 8b0b99bbc7d..68404559926 100644 --- a/python/mozbuild/mozbuild/test/backend/data/variable_passthru/moz.build +++ b/python/mozbuild/mozbuild/test/backend/data/variable_passthru/moz.build @@ -38,6 +38,7 @@ DELAYLOAD_DLLS = ['foo.dll', 'bar.dll'] RCFILE = 'foo.rc' RESFILE = 'bar.res' +RCINCLUDE = 'bar.rc' DEFFILE = 'baz.def' USE_STATIC_LIBS = True diff --git a/python/mozbuild/mozbuild/test/backend/test_recursivemake.py b/python/mozbuild/mozbuild/test/backend/test_recursivemake.py index a4823fbea38..5a714e27e47 100644 --- a/python/mozbuild/mozbuild/test/backend/test_recursivemake.py +++ b/python/mozbuild/mozbuild/test/backend/test_recursivemake.py @@ -334,6 +334,9 @@ class TestRecursiveMakeBackend(BackendTester): 'RESFILE': [ 'RESFILE := bar.res', ], + 'RCINCLUDE': [ + 'RCINCLUDE := bar.rc', + ], 'DEFFILE': [ 'DEFFILE := baz.def', ], diff --git a/python/mozbuild/mozbuild/test/frontend/data/variable-passthru/moz.build b/python/mozbuild/mozbuild/test/frontend/data/variable-passthru/moz.build index 19df3d11418..d9b6c9a7c6d 100644 --- a/python/mozbuild/mozbuild/test/frontend/data/variable-passthru/moz.build +++ b/python/mozbuild/mozbuild/test/frontend/data/variable-passthru/moz.build @@ -44,6 +44,7 @@ DELAYLOAD_DLLS = ['foo.dll', 'bar.dll'] RCFILE = 'foo.rc' RESFILE = 'bar.res' +RCINCLUDE = 'bar.rc' DEFFILE = 'baz.def' USE_STATIC_LIBS = True diff --git a/python/mozbuild/mozbuild/test/frontend/test_emitter.py b/python/mozbuild/mozbuild/test/frontend/test_emitter.py index d4aae3ed085..f1de4654c5a 100644 --- a/python/mozbuild/mozbuild/test/frontend/test_emitter.py +++ b/python/mozbuild/mozbuild/test/frontend/test_emitter.py @@ -174,6 +174,7 @@ class TestEmitterBasic(unittest.TestCase): USE_DELAYIMP=True, RCFILE='foo.rc', RESFILE='bar.res', + RCINCLUDE='bar.rc', DEFFILE='baz.def', USE_STATIC_LIBS=True, MOZBUILD_CFLAGS=['-fno-exceptions', '-w'], diff --git a/toolkit/components/maintenanceservice/Makefile.in b/toolkit/components/maintenanceservice/Makefile.in index 885c4fe06c5..efff5dabbf3 100644 --- a/toolkit/components/maintenanceservice/Makefile.in +++ b/toolkit/components/maintenanceservice/Makefile.in @@ -16,8 +16,6 @@ else LIBS += $(call EXPAND_LIBNAME_PATH,updatecommon,../../mozapps/update/common) endif -RCINCLUDE = maintenanceservice.rc - OS_LIBS += $(call EXPAND_LIBNAME,comctl32 ws2_32 shell32) ifndef MOZ_WINCONSOLE diff --git a/toolkit/components/maintenanceservice/moz.build b/toolkit/components/maintenanceservice/moz.build index fa62779a7b9..25a3e823ca5 100644 --- a/toolkit/components/maintenanceservice/moz.build +++ b/toolkit/components/maintenanceservice/moz.build @@ -32,3 +32,5 @@ USE_STATIC_LIBS = True if CONFIG['_MSC_VER']: WIN32_EXE_LDFLAGS += ['-ENTRY:wmainCRTStartup'] + +RCINCLUDE = 'maintenanceservice.rc' diff --git a/toolkit/crashreporter/client/Makefile.in b/toolkit/crashreporter/client/Makefile.in index 7e137d4a86c..55fe1c53138 100644 --- a/toolkit/crashreporter/client/Makefile.in +++ b/toolkit/crashreporter/client/Makefile.in @@ -19,7 +19,6 @@ ifeq ($(OS_ARCH),WINNT) LIBS += \ $(DEPTH)/toolkit/crashreporter/breakpad-windows-libxul/$(LIB_PREFIX)google_breakpad_libxul_s.$(LIB_SUFFIX) $(NULL) -RCINCLUDE = crashreporter.rc OS_LIBS += $(call EXPAND_LIBNAME,comctl32 shell32 wininet shlwapi) MOZ_WINCONSOLE = 0 endif diff --git a/toolkit/crashreporter/client/moz.build b/toolkit/crashreporter/client/moz.build index 4978ba693e0..4c8a5fe3bf4 100644 --- a/toolkit/crashreporter/client/moz.build +++ b/toolkit/crashreporter/client/moz.build @@ -43,3 +43,4 @@ if CONFIG['MOZ_ENABLE_GTK']: 'crashreporter_unix_common.cpp' ] +RCINCLUDE = 'crashreporter.rc' diff --git a/toolkit/library/Makefile.in b/toolkit/library/Makefile.in index 5a313f071e3..9d7aab8709c 100644 --- a/toolkit/library/Makefile.in +++ b/toolkit/library/Makefile.in @@ -24,10 +24,6 @@ SHARED_LIBRARY_LIBS += \ $(foreach component,$(COMPONENT_LIBS),$(DEPTH)/staticlib/$(LIB_PREFIX)$(component).$(LIB_SUFFIX)) \ $(NULL) -ifeq ($(OS_ARCH)_$(GNU_CC),WINNT_) -RCINCLUDE = xulrunner.rc -endif - # dependent libraries ifdef MOZ_B2G_BT_BLUEZ #{ ifeq (gonk,$(MOZ_WIDGET_TOOLKIT)) diff --git a/toolkit/library/moz.build b/toolkit/library/moz.build index e521453e986..e49cbdcdd86 100644 --- a/toolkit/library/moz.build +++ b/toolkit/library/moz.build @@ -16,9 +16,10 @@ if CONFIG['OS_ARCH'] == 'WINNT': ] if not CONFIG['GNU_CC']: LOCAL_INCLUDES += [ - '/widget/windows', - '/xpcom/base', - ] + '/widget/windows', + '/xpcom/base', + ] + RCINCLUDE = 'xulrunner.rc' # component libraries additional_defines = ( diff --git a/toolkit/mozapps/update/updater/Makefile.in b/toolkit/mozapps/update/updater/Makefile.in index 1eff712d4d3..4e0f79cbc18 100644 --- a/toolkit/mozapps/update/updater/Makefile.in +++ b/toolkit/mozapps/update/updater/Makefile.in @@ -20,7 +20,6 @@ LIBS += \ ifeq ($(OS_ARCH),WINNT) LIBS += $(call EXPAND_LIBNAME_PATH,verifymar,$(DEPTH)/modules/libmar/verify) -RCINCLUDE = updater.rc OS_LIBS += $(call EXPAND_LIBNAME,comctl32 ws2_32 shell32 shlwapi) endif diff --git a/toolkit/mozapps/update/updater/moz.build b/toolkit/mozapps/update/updater/moz.build index 2a803ea6343..add81dae3a0 100644 --- a/toolkit/mozapps/update/updater/moz.build +++ b/toolkit/mozapps/update/updater/moz.build @@ -20,6 +20,7 @@ if CONFIG['OS_ARCH'] == 'WINNT': 'progressui_win.cpp', 'win_dirent.cpp', ] + RCINCLUDE = 'updater.rc' DEFINES['UNICODE'] = True DEFINES['_UNICODE'] = True USE_STATIC_LIBS = True diff --git a/webapprt/win/Makefile.in b/webapprt/win/Makefile.in index 82c3a80cff5..2409c291dd5 100644 --- a/webapprt/win/Makefile.in +++ b/webapprt/win/Makefile.in @@ -30,8 +30,6 @@ DEFINES += -DAPP_VERSION=$(APP_VERSION) OS_LIBS += $(call EXPAND_LIBNAME,shell32) -RCINCLUDE = webapprt.rc - # Uninstaller ifdef LOCALE_MERGEDIR PPL_LOCALE_ARGS = \ diff --git a/webapprt/win/moz.build b/webapprt/win/moz.build index ae455f471e3..dc5a3333676 100644 --- a/webapprt/win/moz.build +++ b/webapprt/win/moz.build @@ -39,3 +39,5 @@ if CONFIG['_MSC_VER']: # Set it to 256k. See bug 127069. if not CONFIG['GNU_CC']: LDFLAGS += ['/HEAP:0x40000'] + +RCINCLUDE = 'webapprt.rc' diff --git a/xulrunner/app/Makefile.in b/xulrunner/app/Makefile.in index 792f4a93a70..db866a90cbc 100644 --- a/xulrunner/app/Makefile.in +++ b/xulrunner/app/Makefile.in @@ -34,7 +34,6 @@ include $(topsrcdir)/config/config.mk ifeq ($(OS_ARCH),WINNT) OS_LIBS += $(call EXPAND_LIBNAME,comctl32 comdlg32 uuid shell32 ole32 oleaut32 version winspool) -RCINCLUDE = splash.rc endif include $(topsrcdir)/config/rules.mk diff --git a/xulrunner/app/moz.build b/xulrunner/app/moz.build index 0812544c07c..659437fbcbd 100644 --- a/xulrunner/app/moz.build +++ b/xulrunner/app/moz.build @@ -42,3 +42,6 @@ if CONFIG['_MSC_VER']: # Set it to 256k. See bug 127069. if CONFIG['OS_ARCH'] == 'WINNT' and not CONFIG['GNU_CC']: LDFLAGS += ['/HEAP:0x40000'] + +if CONFIG['OS_ARCH'] == 'WINNT': + RCINCLUDE = 'splash.rc' diff --git a/xulrunner/stub/Makefile.in b/xulrunner/stub/Makefile.in index 81978dc7f61..f4b5f6fd24d 100644 --- a/xulrunner/stub/Makefile.in +++ b/xulrunner/stub/Makefile.in @@ -18,10 +18,6 @@ LIBS += \ $(NULL) endif -ifeq ($(OS_ARCH),WINNT) -RCINCLUDE = xulrunner-stub.rc -endif - ifndef MOZ_WINCONSOLE ifdef MOZ_DEBUG MOZ_WINCONSOLE = 1 diff --git a/xulrunner/stub/moz.build b/xulrunner/stub/moz.build index ae8d82d5eae..2558369005d 100644 --- a/xulrunner/stub/moz.build +++ b/xulrunner/stub/moz.build @@ -36,3 +36,4 @@ if CONFIG['_MSC_VER']: if CONFIG['OS_ARCH'] == 'WINNT': DEFINES['MOZ_XULRUNNER'] = True + RCINCLUDE = 'xulrunner-stub.rc' From bd48456594ad6f8165d6160e1b419de0e569f5ce Mon Sep 17 00:00:00 2001 From: Terrence Cole Date: Mon, 3 Mar 2014 18:41:58 -0800 Subject: [PATCH 024/112] Bug 978387 - Mark the ArrayBufferObject view list weakly during minor collections; r=sfink --HG-- extra : rebase_source : c085f148836a8d23b8e6d1276625a1dd169cbbf1 --- js/src/gc/Marking.cpp | 29 ++++++++++++-- js/src/gc/Marking.h | 14 +++++-- js/src/gc/Nursery.cpp | 43 +++++++++++---------- js/src/gc/StoreBuffer.cpp | 2 +- js/src/vm/ArrayBufferObject.cpp | 67 ++++++++++++++------------------- 5 files changed, 90 insertions(+), 65 deletions(-) diff --git a/js/src/gc/Marking.cpp b/js/src/gc/Marking.cpp index ad48f4db972..0954b76f967 100644 --- a/js/src/gc/Marking.cpp +++ b/js/src/gc/Marking.cpp @@ -366,9 +366,19 @@ IsAboutToBeFinalized(T **thingp) return !(*thingp)->isMarked(); } +template +T * +UpdateIfRelocated(JSRuntime *rt, T **thingp) +{ + JS_ASSERT(thingp); + if (*thingp && rt->isHeapMinorCollecting()) + IsAboutToBeFinalized(thingp); + return *thingp; +} + #define DeclMarkerImpl(base, type) \ void \ -Mark##base(JSTracer *trc, BarrieredPtr *thing, const char *name) \ +Mark##base(JSTracer *trc, BarrieredPtr *thing, const char *name) \ { \ Mark(trc, thing, name); \ } \ @@ -409,7 +419,7 @@ Is##base##Marked(type **thingp) } \ \ bool \ -Is##base##Marked(BarrieredPtr *thingp) \ +Is##base##Marked(BarrieredPtr *thingp) \ { \ return IsMarked(thingp->unsafeGet()); \ } \ @@ -421,11 +431,24 @@ Is##base##AboutToBeFinalized(type **thingp) } \ \ bool \ -Is##base##AboutToBeFinalized(BarrieredPtr *thingp) \ +Is##base##AboutToBeFinalized(BarrieredPtr *thingp) \ { \ return IsAboutToBeFinalized(thingp->unsafeGet()); \ +} \ + \ +type * \ +Update##base##IfRelocated(JSRuntime *rt, BarrieredPtr *thingp) \ +{ \ + return UpdateIfRelocated(rt, thingp->unsafeGet()); \ +} \ + \ +type * \ +Update##base##IfRelocated(JSRuntime *rt, type **thingp) \ +{ \ + return UpdateIfRelocated(rt, thingp); \ } + DeclMarkerImpl(BaseShape, BaseShape) DeclMarkerImpl(BaseShape, UnownedBaseShape) DeclMarkerImpl(JitCode, jit::JitCode) diff --git a/js/src/gc/Marking.h b/js/src/gc/Marking.h index 961e7a506ee..16404fe4abe 100644 --- a/js/src/gc/Marking.h +++ b/js/src/gc/Marking.h @@ -80,17 +80,25 @@ namespace gc { * IsObjectMarked(JSObject **thing); * This function is indended to be used in rare cases in code used to mark * GC things. It indicates whether the object is currently marked. + * + * UpdateObjectIfRelocated(JSObject **thingp); + * In some circumstances -- e.g. optional weak marking -- it is necessary + * to look at the pointer before marking it strongly or weakly. In these + * cases, the following must be called to update the pointer before use. */ + #define DeclMarker(base, type) \ -void Mark##base(JSTracer *trc, BarrieredPtr *thing, const char *name); \ +void Mark##base(JSTracer *trc, BarrieredPtr *thing, const char *name); \ void Mark##base##Root(JSTracer *trc, type **thingp, const char *name); \ void Mark##base##Unbarriered(JSTracer *trc, type **thingp, const char *name); \ void Mark##base##Range(JSTracer *trc, size_t len, HeapPtr *thing, const char *name); \ void Mark##base##RootRange(JSTracer *trc, size_t len, type **thing, const char *name); \ bool Is##base##Marked(type **thingp); \ -bool Is##base##Marked(BarrieredPtr *thingp); \ +bool Is##base##Marked(BarrieredPtr *thingp); \ bool Is##base##AboutToBeFinalized(type **thingp); \ -bool Is##base##AboutToBeFinalized(BarrieredPtr *thingp); \ +bool Is##base##AboutToBeFinalized(BarrieredPtr *thingp); \ +type *Update##base##IfRelocated(JSRuntime *rt, BarrieredPtr *thingp); \ +type *Update##base##IfRelocated(JSRuntime *rt, type **thingp); DeclMarker(BaseShape, BaseShape) DeclMarker(BaseShape, UnownedBaseShape) diff --git a/js/src/gc/Nursery.cpp b/js/src/gc/Nursery.cpp index 50693dc4160..a204ff2b035 100644 --- a/js/src/gc/Nursery.cpp +++ b/js/src/gc/Nursery.cpp @@ -722,10 +722,10 @@ js::Nursery::collect(JSRuntime *rt, JS::gcreason::Reason reason, TypeObjectList AutoStopVerifyingBarriers av(rt, false); - /* Move objects pointed to by roots from the nursery to the major heap. */ + // Move objects pointed to by roots from the nursery to the major heap. MinorCollectionTracer trc(rt, this); - /* Mark the store buffer. This must happen first. */ + // Mark the store buffer. This must happen first. StoreBuffer &sb = rt->gcStoreBuffer; TIME_START(markValues); sb.markValues(&trc); @@ -771,25 +771,31 @@ js::Nursery::collect(JSRuntime *rt, JS::gcreason::Reason reason, TypeObjectList rt->newObjectCache.clearNurseryObjects(rt); TIME_END(clearNewObjectCache); - /* - * Most of the work is done here. This loop iterates over objects that have - * been moved to the major heap. If these objects have any outgoing pointers - * to the nursery, then those nursery objects get moved as well, until no - * objects are left to move. That is, we iterate to a fixed point. - */ + // Most of the work is done here. This loop iterates over objects that have + // been moved to the major heap. If these objects have any outgoing pointers + // to the nursery, then those nursery objects get moved as well, until no + // objects are left to move. That is, we iterate to a fixed point. TIME_START(collectToFP); TenureCountCache tenureCounts; collectToFixedPoint(&trc, tenureCounts); TIME_END(collectToFP); + // Update the array buffer object's view lists. + TIME_START(sweepArrayBufferViewList); + for (CompartmentsIter c(rt, SkipAtoms); !c.done(); c.next()) { + if (c->gcLiveArrayBuffers) + ArrayBufferObject::sweep(c); + } + TIME_END(sweepArrayBufferViewList); + + // Update any slot or element pointers whose destination has been tenured. TIME_START(updateJitActivations); #ifdef JS_ION - /* Update any slot or element pointers whose destination has been tenured. */ js::jit::UpdateJitActivationsForMinorGC(rt, &trc); #endif TIME_END(updateJitActivations); - /* Resize the nursery. */ + // Resize the nursery. TIME_START(resize); double promotionRate = trc.tenuredSize / double(allocationEnd() - start()); if (promotionRate > 0.05) @@ -798,11 +804,11 @@ js::Nursery::collect(JSRuntime *rt, JS::gcreason::Reason reason, TypeObjectList shrinkAllocableSpace(); TIME_END(resize); - TIME_START(pretenure); // If we are promoting the nursery, or exhausted the store buffer with // pointers to nursery things, which will force a collection well before // the nursery is full, look for object types that are getting promoted // excessively and try to pretenure them. + TIME_START(pretenure); if (pretenureTypes && (promotionRate > 0.8 || reason == JS::gcreason::FULL_STORE_BUFFER)) { for (size_t i = 0; i < ArrayLength(tenureCounts.entries); i++) { const TenureCount &entry = tenureCounts.entries[i]; @@ -812,7 +818,7 @@ js::Nursery::collect(JSRuntime *rt, JS::gcreason::Reason reason, TypeObjectList } TIME_END(pretenure); - /* Sweep. */ + // Sweep. TIME_START(freeHugeSlots); freeHugeSlots(rt); TIME_END(freeHugeSlots); @@ -825,11 +831,9 @@ js::Nursery::collect(JSRuntime *rt, JS::gcreason::Reason reason, TypeObjectList rt->gcStoreBuffer.clear(); TIME_END(clearStoreBuffer); - /* - * We ignore gcMaxBytes when allocating for minor collection. However, if we - * overflowed, we disable the nursery. The next time we allocate, we'll fail - * because gcBytes >= gcMaxBytes. - */ + // We ignore gcMaxBytes when allocating for minor collection. However, if we + // overflowed, we disable the nursery. The next time we allocate, we'll fail + // because gcBytes >= gcMaxBytes. if (rt->gcBytes >= rt->gcMaxBytes) disable(); @@ -842,13 +846,13 @@ js::Nursery::collect(JSRuntime *rt, JS::gcreason::Reason reason, TypeObjectList static bool printedHeader = false; if (!printedHeader) { fprintf(stderr, - "MinorGC: Reason PRate Size Time mkVals mkClls mkSlts mkWCll mkRVal mkRCll mkGnrc ckTbls mkRntm mkDbgr clrNOC collct updtIn resize pretnr frSlts clrSB sweep\n"); + "MinorGC: Reason PRate Size Time mkVals mkClls mkSlts mkWCll mkRVal mkRCll mkGnrc ckTbls mkRntm mkDbgr clrNOC collct swpABO updtIn resize pretnr frSlts clrSB sweep\n"); printedHeader = true; } #define FMT " %6" PRIu64 fprintf(stderr, - "MinorGC: %20s %5.1f%% %4d" FMT FMT FMT FMT FMT FMT FMT FMT FMT FMT FMT FMT FMT FMT FMT FMT FMT FMT FMT "\n", + "MinorGC: %20s %5.1f%% %4d" FMT FMT FMT FMT FMT FMT FMT FMT FMT FMT FMT FMT FMT FMT FMT FMT FMT FMT FMT FMT "\n", js::gcstats::ExplainReason(reason), promotionRate * 100, numActiveChunks_, @@ -865,6 +869,7 @@ js::Nursery::collect(JSRuntime *rt, JS::gcreason::Reason reason, TypeObjectList TIME_TOTAL(markDebugger), TIME_TOTAL(clearNewObjectCache), TIME_TOTAL(collectToFP), + TIME_TOTAL(sweepArrayBufferViewList), TIME_TOTAL(updateJitActivations), TIME_TOTAL(resize), TIME_TOTAL(pretenure), diff --git a/js/src/gc/StoreBuffer.cpp b/js/src/gc/StoreBuffer.cpp index 8dcdf081b88..089e5d7a193 100644 --- a/js/src/gc/StoreBuffer.cpp +++ b/js/src/gc/StoreBuffer.cpp @@ -100,7 +100,7 @@ StoreBuffer::MonoTypeBuffer::handleOverflow(StoreBuffer *owner) * compacting unless the buffer is totally full. */ if (storage_->availableInCurrentChunk() < sizeof(T)) - compact(owner); + maybeCompact(owner); } } diff --git a/js/src/vm/ArrayBufferObject.cpp b/js/src/vm/ArrayBufferObject.cpp index cdf74994523..5244cbb7cda 100644 --- a/js/src/vm/ArrayBufferObject.cpp +++ b/js/src/vm/ArrayBufferObject.cpp @@ -821,6 +821,9 @@ ArrayBufferObject::obj_trace(JSTracer *trc, JSObject *obj) obj->setPrivateUnbarriered(delegate); } + if (!IS_GC_MARKING_TRACER(trc) && !trc->runtime->isHeapMinorCollecting()) + return; + // ArrayBufferObjects need to maintain a list of possibly-weak pointers to // their views. The straightforward way to update the weak pointers would // be in the views' finalizers, but giving views finalizers means they @@ -834,69 +837,55 @@ ArrayBufferObject::obj_trace(JSTracer *trc, JSObject *obj) // then swept to prune out their dead views. ArrayBufferObject &buffer = AsArrayBuffer(obj); - ArrayBufferViewObject *viewsHead = GetViewList(&buffer); + ArrayBufferViewObject *viewsHead = UpdateObjectIfRelocated(trc->runtime, + &GetViewListRef(&buffer)); if (!viewsHead) return; - // During minor collections, mark weak pointers on the buffer strongly. - if (trc->runtime->isHeapMinorCollecting()) { - MarkObject(trc, &GetViewListRef(&buffer), "arraybuffer.viewlist"); - ArrayBufferViewObject *prior = GetViewList(&buffer); - for (ArrayBufferViewObject *view = prior->nextView(); - view; - prior = view, view = view->nextView()) - { - MarkObjectUnbarriered(trc, &view, "arraybuffer.views"); - prior->setNextView(view); - } - return; - } - + viewsHead = UpdateObjectIfRelocated(trc->runtime, &GetViewListRef(&buffer)); ArrayBufferViewObject *firstView = viewsHead; if (firstView->nextView() == nullptr) { // Single view: mark it, but only if we're actually doing a GC pass // right now. Otherwise, the tracing pass for barrier verification will // fail if we add another view and the pointer becomes weak. - if (IS_GC_MARKING_TRACER(trc)) - MarkObject(trc, &GetViewListRef(&buffer), "arraybuffer.singleview"); + MarkObject(trc, &GetViewListRef(&buffer), "arraybuffer.singleview"); } else { // Multiple views: do not mark, but append buffer to list. - if (IS_GC_MARKING_TRACER(trc)) { - // obj_trace may be called multiple times before sweep(), so avoid - // adding this buffer to the list multiple times. - if (firstView->bufferLink() == UNSET_BUFFER_LINK) { - JS_ASSERT(obj->compartment() == firstView->compartment()); - ArrayBufferObject **bufList = &obj->compartment()->gcLiveArrayBuffers; - firstView->setBufferLink(*bufList); - *bufList = &AsArrayBuffer(obj); - } else { + // obj_trace may be called multiple times before sweep(), so avoid + // adding this buffer to the list multiple times. + if (firstView->bufferLink() == UNSET_BUFFER_LINK) { + JS_ASSERT(obj->compartment() == firstView->compartment()); + ArrayBufferObject **bufList = &obj->compartment()->gcLiveArrayBuffers; + firstView->setBufferLink(*bufList); + *bufList = &AsArrayBuffer(obj); + } else { #ifdef DEBUG - bool found = false; - for (ArrayBufferObject *p = obj->compartment()->gcLiveArrayBuffers; - p; - p = GetViewList(p)->bufferLink()) + bool found = false; + for (ArrayBufferObject *p = obj->compartment()->gcLiveArrayBuffers; + p; + p = GetViewList(p)->bufferLink()) + { + if (p == obj) { - if (p == obj) - { - JS_ASSERT(!found); - found = true; - } + JS_ASSERT(!found); + found = true; } -#endif } +#endif } } } -void +/* static */ void ArrayBufferObject::sweep(JSCompartment *compartment) { + JSRuntime *rt = compartment->runtimeFromMainThread(); ArrayBufferObject *buffer = compartment->gcLiveArrayBuffers; JS_ASSERT(buffer != UNSET_BUFFER_LINK); compartment->gcLiveArrayBuffers = nullptr; while (buffer) { - ArrayBufferViewObject *viewsHead = GetViewList(buffer); + ArrayBufferViewObject *viewsHead = UpdateObjectIfRelocated(rt, &GetViewListRef(buffer)); JS_ASSERT(viewsHead); ArrayBufferObject *nextBuffer = viewsHead->bufferLink(); @@ -914,7 +903,7 @@ ArrayBufferObject::sweep(JSCompartment *compartment) view->setNextView(prevLiveView); prevLiveView = view; } - view = nextView; + view = UpdateObjectIfRelocated(rt, &nextView); } SetViewList(buffer, prevLiveView); From 456aba523b17af04c39ecbeb7985310bf1d639e4 Mon Sep 17 00:00:00 2001 From: Steve Fink Date: Tue, 4 Mar 2014 14:01:28 -0800 Subject: [PATCH 025/112] Bug 979142 - Only test filterPar when enabled, r=jandem --HG-- extra : rebase_source : cf964b090cdc3ca3879f3d9e8f9eb3fbc8cdbaeb --- js/src/jit-test/tests/gc/bug-975959.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/js/src/jit-test/tests/gc/bug-975959.js b/js/src/jit-test/tests/gc/bug-975959.js index 654eb267bcd..1487c61cc46 100644 --- a/js/src/jit-test/tests/gc/bug-975959.js +++ b/js/src/jit-test/tests/gc/bug-975959.js @@ -1,3 +1,6 @@ +if (!getBuildConfiguration().parallelJS) + quit(0); + try { y = z = []; y[1] = x From 6ac720fff862b52bd08f8d842eb0b22250a54445 Mon Sep 17 00:00:00 2001 From: Ben Turner Date: Tue, 4 Mar 2014 15:09:23 -0800 Subject: [PATCH 026/112] Bug 975695, r=khuey. --- dom/workers/RuntimeService.cpp | 2 +- dom/workers/WorkerPrivate.cpp | 29 +++++++++++++++++++---------- dom/workers/WorkerPrivate.h | 9 +++++++-- 3 files changed, 27 insertions(+), 13 deletions(-) diff --git a/dom/workers/RuntimeService.cpp b/dom/workers/RuntimeService.cpp index b9e8d079cf7..30362e1cc4a 100644 --- a/dom/workers/RuntimeService.cpp +++ b/dom/workers/RuntimeService.cpp @@ -2583,7 +2583,7 @@ WorkerThreadPrimaryRunnable::Run() mThread->SetWorker(nullptr); - mWorkerPrivate->ScheduleDeletion(); + mWorkerPrivate->ScheduleDeletion(WorkerPrivate::WorkerRan); // It is no longer safe to touch mWorkerPrivate. mWorkerPrivate = nullptr; diff --git a/dom/workers/WorkerPrivate.cpp b/dom/workers/WorkerPrivate.cpp index fd9047b71f6..f5921e84fd2 100644 --- a/dom/workers/WorkerPrivate.cpp +++ b/dom/workers/WorkerPrivate.cpp @@ -2349,7 +2349,7 @@ WorkerPrivateParent::NotifyPrivate(JSContext* aCx, Status aStatus) #endif // Worker never got a chance to run, go ahead and delete it. - self->ScheduleDeletion(); + self->ScheduleDeletion(WorkerPrivate::WorkerNeverRan); return true; } @@ -4251,13 +4251,13 @@ WorkerPrivate::IsOnCurrentThread(bool* aIsOnCurrentThread) } void -WorkerPrivate::ScheduleDeletion() +WorkerPrivate::ScheduleDeletion(WorkerRanOrNot aRanOrNot) { AssertIsOnWorkerThread(); MOZ_ASSERT(mChildWorkers.IsEmpty()); MOZ_ASSERT(mSyncLoopStack.IsEmpty()); - ClearMainEventQueue(); + ClearMainEventQueue(aRanOrNot); if (WorkerPrivate* parent = GetParent()) { nsRefPtr runnable = @@ -4474,18 +4474,27 @@ WorkerPrivate::ProcessAllControlRunnablesLocked() } void -WorkerPrivate::ClearMainEventQueue() +WorkerPrivate::ClearMainEventQueue(WorkerRanOrNot aRanOrNot) { AssertIsOnWorkerThread(); - nsIThread* currentThread = NS_GetCurrentThread(); - MOZ_ASSERT(currentThread); - MOZ_ASSERT(!mCancelAllPendingRunnables); mCancelAllPendingRunnables = true; - NS_ProcessPendingEvents(currentThread); - MOZ_ASSERT(!NS_HasPendingEvents(currentThread)); + if (WorkerNeverRan == aRanOrNot) { + for (uint32_t count = mPreStartRunnables.Length(), index = 0; + index < count; + index++) { + nsRefPtr runnable = mPreStartRunnables[index].forget(); + static_cast(runnable.get())->Run(); + } + } else { + nsIThread* currentThread = NS_GetCurrentThread(); + MOZ_ASSERT(currentThread); + + NS_ProcessPendingEvents(currentThread); + MOZ_ASSERT(!NS_HasPendingEvents(currentThread)); + } MOZ_ASSERT(mCancelAllPendingRunnables); mCancelAllPendingRunnables = false; @@ -5031,7 +5040,7 @@ WorkerPrivate::NotifyInternal(JSContext* aCx, Status aStatus) // If this is the first time our status has changed then we need to clear the // main event queue. if (previousStatus == Running) { - ClearMainEventQueue(); + ClearMainEventQueue(WorkerRan); } // If we've run the close handler, we don't need to do anything else. diff --git a/dom/workers/WorkerPrivate.h b/dom/workers/WorkerPrivate.h index ce66719b3cc..263b5f3076e 100644 --- a/dom/workers/WorkerPrivate.h +++ b/dom/workers/WorkerPrivate.h @@ -915,8 +915,13 @@ public: void UpdateJSWorkerMemoryParameterInternal(JSContext* aCx, JSGCParamKey key, uint32_t aValue); + enum WorkerRanOrNot { + WorkerNeverRan = 0, + WorkerRan + }; + void - ScheduleDeletion(); + ScheduleDeletion(WorkerRanOrNot aRanOrNot); bool BlockAndCollectRuntimeStats(JS::RuntimeStats* aRtStats); @@ -1047,7 +1052,7 @@ private: LoadInfo& aLoadInfo); void - ClearMainEventQueue(); + ClearMainEventQueue(WorkerRanOrNot aRanOrNot); bool MayContinueRunning() From a9cc6a06aca7ba0596d462d5f3d8128a3f17c6dd Mon Sep 17 00:00:00 2001 From: Ben Turner Date: Tue, 4 Mar 2014 15:10:44 -0800 Subject: [PATCH 027/112] Bug 934142, remove faulty assertion. r=khuey. --- dom/ipc/Blob.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/dom/ipc/Blob.cpp b/dom/ipc/Blob.cpp index 08c8b6920b6..3842ac2373e 100644 --- a/dom/ipc/Blob.cpp +++ b/dom/ipc/Blob.cpp @@ -1080,10 +1080,6 @@ RemoteBlob::MaybeSetInputStream(const ConstructorParamsType& aParams) mInputStreamParams = aParams.optionalInputStreamParams().get_InputStreamParams(); } - else { - MOZ_ASSERT(aParams.blobParams().type() == - ChildBlobConstructorParams::TMysteryBlobConstructorParams); - } } template <> From 6d6e9c420b0a2c6ae8a46bab4c805db6cf175035 Mon Sep 17 00:00:00 2001 From: Andrew McCreight Date: Tue, 4 Mar 2014 15:39:42 -0800 Subject: [PATCH 028/112] Bug 978203 - Don't include nsWindowMemoryReporter.h in nsINode.h. r=smaug --- content/base/public/nsIDocument.h | 1 + content/base/public/nsINode.h | 11 +++++++++-- content/base/src/nsDocument.cpp | 1 + content/base/src/nsFrameMessageManager.cpp | 1 + content/svg/content/src/SVGTransform.cpp | 1 + dom/base/nsGlobalWindow.cpp | 1 + dom/base/nsWindowMemoryReporter.h | 7 ------- editor/libeditor/base/IMETextTxn.cpp | 1 + image/src/SurfaceCache.cpp | 1 + js/xpconnect/src/XPCComponents.cpp | 1 + js/xpconnect/src/xpcprivate.h | 1 + layout/base/nsPresShell.cpp | 1 + layout/xul/nsXULPopupManager.h | 1 + 13 files changed, 20 insertions(+), 9 deletions(-) diff --git a/content/base/public/nsIDocument.h b/content/base/public/nsIDocument.h index 10a2a8d26d0..0ef07f43679 100644 --- a/content/base/public/nsIDocument.h +++ b/content/base/public/nsIDocument.h @@ -19,6 +19,7 @@ #include "nsPIDOMWindow.h" // for use in inline functions #include "nsPropertyTable.h" // for member #include "nsTHashtable.h" // for member +#include "nsWeakReference.h" #include "mozilla/dom/DocumentBinding.h" #include "mozilla/WeakPtr.h" #include "Units.h" diff --git a/content/base/public/nsINode.h b/content/base/public/nsINode.h index ef09fa1f284..ed6618a6ac1 100644 --- a/content/base/public/nsINode.h +++ b/content/base/public/nsINode.h @@ -15,7 +15,6 @@ #include "nsNodeInfoManager.h" // for use in NodePrincipal() #include "nsPropertyTable.h" // for typedefs #include "nsTObserverArray.h" // for member -#include "nsWindowMemoryReporter.h" // for NS_DECL_SIZEOF_EXCLUDING_THIS #include "mozilla/ErrorResult.h" #include "mozilla/MemoryReporting.h" #include "mozilla/dom/EventTarget.h" // for base class @@ -244,13 +243,21 @@ private: // ever passed to Mutated(). enum { eMaxMutations = 300 }; - + // sMutationCount is a global mutation counter which is decreased by one at // every mutation. It is capped at 0 to avoid wrapping. // Its value is always between 0 and 300, inclusive. static uint32_t sMutationCount; }; +// This should be used for any nsINode sub-class that has fields of its own +// that it needs to measure; any sub-class that doesn't use it will inherit +// SizeOfExcludingThis from its super-class. SizeOfIncludingThis() need not be +// defined, it is inherited from nsINode. +// This macro isn't actually specific to nodes, and bug 956400 will move it into MFBT. +#define NS_DECL_SIZEOF_EXCLUDING_THIS \ + virtual size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const; + // Categories of node properties // 0 is global. #define DOM_USER_DATA 1 diff --git a/content/base/src/nsDocument.cpp b/content/base/src/nsDocument.cpp index 1826ac98a72..accae78ae87 100644 --- a/content/base/src/nsDocument.cpp +++ b/content/base/src/nsDocument.cpp @@ -221,6 +221,7 @@ #include "nsIMutableArray.h" #include "nsContentPermissionHelper.h" #include "mozilla/dom/DOMStringList.h" +#include "nsWindowMemoryReporter.h" using namespace mozilla; using namespace mozilla::dom; diff --git a/content/base/src/nsFrameMessageManager.cpp b/content/base/src/nsFrameMessageManager.cpp index df889d57fec..fded1caf70a 100644 --- a/content/base/src/nsFrameMessageManager.cpp +++ b/content/base/src/nsFrameMessageManager.cpp @@ -23,6 +23,7 @@ #include "nsIXULRuntime.h" #include "nsIScriptError.h" #include "nsIConsoleService.h" +#include "nsIMemoryReporter.h" #include "nsIProtocolHandler.h" #include "nsIScriptSecurityManager.h" #include "nsIJSRuntimeService.h" diff --git a/content/svg/content/src/SVGTransform.cpp b/content/svg/content/src/SVGTransform.cpp index a45e1adf66e..53ad781372b 100644 --- a/content/svg/content/src/SVGTransform.cpp +++ b/content/svg/content/src/SVGTransform.cpp @@ -12,6 +12,7 @@ #include "nsError.h" #include "nsSVGAnimatedTransformList.h" #include "nsSVGAttrTearoffTable.h" +#include "mozilla/DebugOnly.h" namespace { const double kRadPerDegree = 2.0 * M_PI / 360.0; diff --git a/dom/base/nsGlobalWindow.cpp b/dom/base/nsGlobalWindow.cpp index 053e14cdb7e..759b2889fdb 100644 --- a/dom/base/nsGlobalWindow.cpp +++ b/dom/base/nsGlobalWindow.cpp @@ -35,6 +35,7 @@ #include "nsIScriptTimeoutHandler.h" #include "nsIController.h" #include "nsScriptNameSpaceManager.h" +#include "nsWindowMemoryReporter.h" // Helper Classes #include "nsJSUtils.h" diff --git a/dom/base/nsWindowMemoryReporter.h b/dom/base/nsWindowMemoryReporter.h index 301497c9910..214b55f2a62 100644 --- a/dom/base/nsWindowMemoryReporter.h +++ b/dom/base/nsWindowMemoryReporter.h @@ -19,13 +19,6 @@ #include "mozilla/TimeStamp.h" #include "nsArenaMemoryStats.h" -// This should be used for any nsINode sub-class that has fields of its own -// that it needs to measure; any sub-class that doesn't use it will inherit -// SizeOfExcludingThis from its super-class. SizeOfIncludingThis() need not be -// defined, it is inherited from nsINode. -#define NS_DECL_SIZEOF_EXCLUDING_THIS \ - virtual size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const; - class nsWindowSizes { #define FOR_EACH_SIZE(macro) \ macro(DOM, mDOMElementNodesSize) \ diff --git a/editor/libeditor/base/IMETextTxn.cpp b/editor/libeditor/base/IMETextTxn.cpp index 7f9b9313b80..9eaf1843743 100644 --- a/editor/libeditor/base/IMETextTxn.cpp +++ b/editor/libeditor/base/IMETextTxn.cpp @@ -4,6 +4,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "IMETextTxn.h" +#include "mozilla/DebugOnly.h" // for DebugOnly #include "mozilla/mozalloc.h" // for operator new #include "mozilla/TextEvents.h" // for TextRangeStyle #include "nsAString.h" // for nsAString_internal::Length, etc diff --git a/image/src/SurfaceCache.cpp b/image/src/SurfaceCache.cpp index 972aa78242d..cad2efa2a17 100644 --- a/image/src/SurfaceCache.cpp +++ b/image/src/SurfaceCache.cpp @@ -15,6 +15,7 @@ #include "mozilla/Preferences.h" #include "mozilla/RefPtr.h" #include "mozilla/StaticPtr.h" +#include "nsIMemoryReporter.h" #include "gfx2DGlue.h" #include "gfxASurface.h" #include "gfxPattern.h" // Workaround for flaw in bug 921753 part 2. diff --git a/js/xpconnect/src/XPCComponents.cpp b/js/xpconnect/src/XPCComponents.cpp index d4a0368860c..e595db32d69 100644 --- a/js/xpconnect/src/XPCComponents.cpp +++ b/js/xpconnect/src/XPCComponents.cpp @@ -26,6 +26,7 @@ #include "nsZipArchive.h" #include "nsIDOMFile.h" #include "nsIDOMFileList.h" +#include "nsWindowMemoryReporter.h" using namespace mozilla; using namespace JS; diff --git a/js/xpconnect/src/xpcprivate.h b/js/xpconnect/src/xpcprivate.h index e64433d4963..0c7ebd87d12 100644 --- a/js/xpconnect/src/xpcprivate.h +++ b/js/xpconnect/src/xpcprivate.h @@ -82,6 +82,7 @@ #include "mozilla/GuardObjects.h" #include "mozilla/Maybe.h" #include "mozilla/MemoryReporting.h" +#include "mozilla/TimeStamp.h" #include #include diff --git a/layout/base/nsPresShell.cpp b/layout/base/nsPresShell.cpp index ab05c120930..34a97136b48 100644 --- a/layout/base/nsPresShell.cpp +++ b/layout/base/nsPresShell.cpp @@ -113,6 +113,7 @@ #include "SVGContentUtils.h" #include "nsSVGEffects.h" #include "SVGFragmentIdentifier.h" +#include "nsArenaMemoryStats.h" #include "nsPerformance.h" #include "nsRefreshDriver.h" diff --git a/layout/xul/nsXULPopupManager.h b/layout/xul/nsXULPopupManager.h index 1273ac667dc..3a325c6a54c 100644 --- a/layout/xul/nsXULPopupManager.h +++ b/layout/xul/nsXULPopupManager.h @@ -17,6 +17,7 @@ #include "nsPoint.h" #include "nsCOMPtr.h" #include "nsTArray.h" +#include "nsIObserver.h" #include "nsITimer.h" #include "nsIReflowCallback.h" #include "nsThreadUtils.h" From c374245688cf6413dda8ca3b98f2542d5a067d5d Mon Sep 17 00:00:00 2001 From: Geoff Brown Date: Tue, 4 Mar 2014 17:02:04 -0700 Subject: [PATCH 029/112] Bug 936226 - Update test manifests for Android x86 --- layout/reftests/bugs/reftest.list | 2 +- testing/mochitest/androidx86.json | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/layout/reftests/bugs/reftest.list b/layout/reftests/bugs/reftest.list index d1e06eb4473..24ca7e44890 100644 --- a/layout/reftests/bugs/reftest.list +++ b/layout/reftests/bugs/reftest.list @@ -1650,7 +1650,7 @@ skip-if(Android||B2G) random-if(winWidget) == 632781-verybig.html 632781-ref.htm == 632781-normalsize.html 632781-ref.html == 633344-1.html 633344-1-ref.html == 634232-1.html 634232-1-ref.html -fails-if(Android) == 635302-1.html 635302-1-ref.html +fails-if(Android&&AndroidVersion<17) == 635302-1.html 635302-1-ref.html skip-if(B2G) random-if(d2d) fails-if(Android) fuzzy-if(winWidget&&!d2d,1,11) == 635373-1.html 635373-1-ref.html skip-if(B2G) random-if(d2d) fails-if(Android) fuzzy-if(winWidget&&!d2d,1,15) == 635373-2.html 635373-2-ref.html skip-if(B2G) random-if(d2d) fails-if(Android) fuzzy-if(winWidget&&!d2d,1,15) == 635373-3.html 635373-3-ref.html diff --git a/testing/mochitest/androidx86.json b/testing/mochitest/androidx86.json index 75a82856227..a2072e2ba14 100644 --- a/testing/mochitest/androidx86.json +++ b/testing/mochitest/androidx86.json @@ -119,6 +119,7 @@ "dom/datastore/tests/test_sync.html": "x86 only bug 936226", "image/test/mochitest/test_bug490949.html": "x86 only", "image/test/mochitest/test_bug497665.html": "x86 only", + "image/test/mochitest/test_bug601470.html": "x86 only", "image/test/mochitest/test_bug671906.html": "x86 only", "image/test/mochitest/test_bug89419-1.html": "x86 only", "image/test/mochitest/test_bug89419-2.html": "x86 only", From ff66e08eeb1c62fb8ceca8b03850dba8ab609020 Mon Sep 17 00:00:00 2001 From: Geoff Brown Date: Tue, 4 Mar 2014 17:02:04 -0700 Subject: [PATCH 030/112] Bug 979552 - Disable some robocop tests on Android 2.3 --- mobile/android/base/tests/robocop.ini | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/mobile/android/base/tests/robocop.ini b/mobile/android/base/tests/robocop.ini index 16e2de8c210..080d52ca99d 100644 --- a/mobile/android/base/tests/robocop.ini +++ b/mobile/android/base/tests/robocop.ini @@ -6,6 +6,8 @@ skip-if = android_version == "10" # disabled on x86 only; bug 936216 skip-if = processor == "x86" [testAddSearchEngine] +# disabled on Android 2.3; bug 979552 +skip-if = android_version == "10" [testAdobeFlash] skip-if = processor == "x86" [testAwesomebar] @@ -15,6 +17,8 @@ skip-if = processor == "x86" # [testBookmark] # see bug 915350 [testBookmarksPanel] [testBookmarkFolders] +# disabled on Android 2.3; bug 979552 +skip-if = android_version == "10" # [testBookmarklets] # see bug 915350 # [testBookmarkKeyword] # see bug 915350 [testBrowserProvider] @@ -37,8 +41,8 @@ skip-if = processor == "x86" # disabled on x86 only; bug 957185 skip-if = processor == "x86" [testImportFromAndroid] -# disabled on x86 only; bug 900664 -skip-if = processor == "x86" +# disabled on x86 and 2.3; bug 900664, 979552 +skip-if = android_version == "10" || processor == "x86" [testInputUrlBar] [testJarReader] [testLinkContextMenu] @@ -72,12 +76,16 @@ skip-if = processor == "x86" skip-if = processor == "x86" [testSessionOOMRestore] [testSettingsMenuItems] +# disabled on Android 2.3; bug 979552 +skip-if = android_version == "10" # [testShareLink] # see bug 915897 [testSystemPages] # disabled on x86 only; bug 907383 skip-if = processor == "x86" # [testThumbnails] # see bug 813107 [testTitleBar] +# disabled on Android 2.3; bug 979552 +skip-if = android_version == "10" # [testVkbOverlap] # see bug 907274 # Using JavascriptTest From 99badfbe5c05d9777df7d5f1e7c891e6f0aca2d9 Mon Sep 17 00:00:00 2001 From: Geoff Brown Date: Tue, 4 Mar 2014 17:02:04 -0700 Subject: [PATCH 031/112] Bug 979548 - Disable testSearchSuggestions on Android 2.3 --- mobile/android/base/tests/robocop.ini | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mobile/android/base/tests/robocop.ini b/mobile/android/base/tests/robocop.ini index 080d52ca99d..9f24e4d67ab 100644 --- a/mobile/android/base/tests/robocop.ini +++ b/mobile/android/base/tests/robocop.ini @@ -69,8 +69,8 @@ skip-if = processor == "x86" # disabled on x86 only; bug 936224 # skip-if = processor == "x86" [testSearchSuggestions] -# disabled on x86 only; bug 907768 -skip-if = processor == "x86" +# disabled on x86 and 2.3; bug 907768, 979548 +skip-if = android_version == "10" || processor == "x86" [testSessionOOMSave] # disabled on x86 only; bug 945395 skip-if = processor == "x86" From a42d0d5a857b2cc55533fc7f3e47210aebabef24 Mon Sep 17 00:00:00 2001 From: Geoff Brown Date: Tue, 4 Mar 2014 17:02:04 -0700 Subject: [PATCH 032/112] Bug 979597 - Disable testAboutHomeVisibility on Android 2.3 --- mobile/android/base/tests/robocop.ini | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mobile/android/base/tests/robocop.ini b/mobile/android/base/tests/robocop.ini index 9f24e4d67ab..b9e2da24ff0 100644 --- a/mobile/android/base/tests/robocop.ini +++ b/mobile/android/base/tests/robocop.ini @@ -109,5 +109,7 @@ skip-if = android_version == "10" # Using UITest #[testAboutHomePageNavigation] # see bug 947550, bug 979038 and bug 977952 [testAboutHomeVisibility] +# disabled on Android 2.3; bug 979597 +skip-if = android_version == "10" [testInputConnection] [testSessionHistory] From 2815dd7afa81cc280d6812ad4912047fe8a7eb73 Mon Sep 17 00:00:00 2001 From: Geoff Brown Date: Tue, 4 Mar 2014 17:02:04 -0700 Subject: [PATCH 033/112] Bug 979600 - Disable testSessionOOMRestore on Android 2.3 --- mobile/android/base/tests/robocop.ini | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mobile/android/base/tests/robocop.ini b/mobile/android/base/tests/robocop.ini index b9e2da24ff0..5b0137fe70d 100644 --- a/mobile/android/base/tests/robocop.ini +++ b/mobile/android/base/tests/robocop.ini @@ -75,6 +75,8 @@ skip-if = android_version == "10" || processor == "x86" # disabled on x86 only; bug 945395 skip-if = processor == "x86" [testSessionOOMRestore] +# disabled on Android 2.3; bug 979600 +skip-if = android_version == "10" [testSettingsMenuItems] # disabled on Android 2.3; bug 979552 skip-if = android_version == "10" From 39dde5b626514d731ef3797e2b5692c7060d3cf2 Mon Sep 17 00:00:00 2001 From: Geoff Brown Date: Tue, 4 Mar 2014 17:02:04 -0700 Subject: [PATCH 034/112] Bug 979603 - Disable testBrowserProvider, testMasterPassword, testSystemPages on Android 2.3 --- mobile/android/base/tests/robocop.ini | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/mobile/android/base/tests/robocop.ini b/mobile/android/base/tests/robocop.ini index 5b0137fe70d..87ecac15132 100644 --- a/mobile/android/base/tests/robocop.ini +++ b/mobile/android/base/tests/robocop.ini @@ -22,6 +22,8 @@ skip-if = android_version == "10" # [testBookmarklets] # see bug 915350 # [testBookmarkKeyword] # see bug 915350 [testBrowserProvider] +# disabled on 2.3; bug 979603 +skip-if = android_version == "10" [testBrowserSearchVisibility] [testClearPrivateData] # disabled on x86 only; bug 948591 @@ -51,6 +53,8 @@ skip-if = android_version == "10" || processor == "x86" [testLoad] [testMailToContextMenu] [testMasterPassword] +# disabled on 2.3; bug 979603 +skip-if = android_version == "10" [testNewTab] [testOverscroll] [testPanCorrectness] @@ -82,8 +86,8 @@ skip-if = android_version == "10" skip-if = android_version == "10" # [testShareLink] # see bug 915897 [testSystemPages] -# disabled on x86 only; bug 907383 -skip-if = processor == "x86" +# disabled on x86 and 2.3; bug 907383, 979603 +skip-if = android_version == "10" || processor == "x86" # [testThumbnails] # see bug 813107 [testTitleBar] # disabled on Android 2.3; bug 979552 From 4933eb56e6390820687cc66e915e880f06355189 Mon Sep 17 00:00:00 2001 From: Geoff Brown Date: Tue, 4 Mar 2014 17:02:04 -0700 Subject: [PATCH 035/112] Bug 979612 - Disable testPictureLinkContextMenu on Android 2.3 --- mobile/android/base/tests/robocop.ini | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mobile/android/base/tests/robocop.ini b/mobile/android/base/tests/robocop.ini index 87ecac15132..d884de6e827 100644 --- a/mobile/android/base/tests/robocop.ini +++ b/mobile/android/base/tests/robocop.ini @@ -64,6 +64,8 @@ skip-if = processor == "x86" [testPasswordProvider] # [testPermissions] # see bug 757475 [testPictureLinkContextMenu] +# disabled on Android 2.3; bug 979612 +skip-if = android_version == "10" [testPrefsObserver] [testPrivateBrowsing] [testPromptGridInput] From 41fe2d4159e96a114e8ad8f0fe98133e005035d6 Mon Sep 17 00:00:00 2001 From: Geoff Brown Date: Tue, 4 Mar 2014 17:02:05 -0700 Subject: [PATCH 036/112] Bug 979615 - Disable testBookmarksPanel on Android 2.3 --- mobile/android/base/tests/robocop.ini | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mobile/android/base/tests/robocop.ini b/mobile/android/base/tests/robocop.ini index d884de6e827..b540b20fce6 100644 --- a/mobile/android/base/tests/robocop.ini +++ b/mobile/android/base/tests/robocop.ini @@ -16,6 +16,8 @@ skip-if = processor == "x86" skip-if = processor == "x86" # [testBookmark] # see bug 915350 [testBookmarksPanel] +# disabled on 2.3; bug 979615 +skip-if = android_version == "10" [testBookmarkFolders] # disabled on Android 2.3; bug 979552 skip-if = android_version == "10" From b3e49137e42c8d8793f8e8b33863fdf4d56c66d5 Mon Sep 17 00:00:00 2001 From: Geoff Brown Date: Tue, 4 Mar 2014 17:02:05 -0700 Subject: [PATCH 037/112] Bug 948591 - Disable testClearPrivateData on Android 2.3 --- mobile/android/base/tests/robocop.ini | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mobile/android/base/tests/robocop.ini b/mobile/android/base/tests/robocop.ini index b540b20fce6..c96ad1ede22 100644 --- a/mobile/android/base/tests/robocop.ini +++ b/mobile/android/base/tests/robocop.ini @@ -28,8 +28,8 @@ skip-if = android_version == "10" skip-if = android_version == "10" [testBrowserSearchVisibility] [testClearPrivateData] -# disabled on x86 only; bug 948591 -skip-if = processor == "x86" +# disabled on x86 and 2.3; bug 948591 +skip-if = android_version == "10" || processor == "x86" [testDistribution] [testDoorHanger] [testFindInPage] From f2a3a2be8ae1b8f6437fbd52c07761940ef215c0 Mon Sep 17 00:00:00 2001 From: Geoff Brown Date: Tue, 4 Mar 2014 17:02:05 -0700 Subject: [PATCH 038/112] Bug 979620 - Disable testGetUserMedia on Android 2.3 --- mobile/android/base/tests/robocop.ini | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mobile/android/base/tests/robocop.ini b/mobile/android/base/tests/robocop.ini index c96ad1ede22..1407928dd7c 100644 --- a/mobile/android/base/tests/robocop.ini +++ b/mobile/android/base/tests/robocop.ini @@ -40,6 +40,8 @@ skip-if = android_version == "10" skip-if = processor == "x86" [testFormHistory] [testGetUserMedia] +# disabled on 2.3; bug 979620 +skip-if = android_version == "10" # [testHistory] # see bug 915350 [testHomeBanner] # disabled on x86 only; bug 957185 From e215b0dd7d11ef99e3b0d7fd9c556ea5464b73d4 Mon Sep 17 00:00:00 2001 From: Geoff Brown Date: Tue, 4 Mar 2014 17:02:05 -0700 Subject: [PATCH 039/112] Bug 979621 - Disable testNewTab on Android 2.3 --- mobile/android/base/tests/robocop.ini | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mobile/android/base/tests/robocop.ini b/mobile/android/base/tests/robocop.ini index 1407928dd7c..00c309409bf 100644 --- a/mobile/android/base/tests/robocop.ini +++ b/mobile/android/base/tests/robocop.ini @@ -60,6 +60,8 @@ skip-if = android_version == "10" || processor == "x86" # disabled on 2.3; bug 979603 skip-if = android_version == "10" [testNewTab] +# disabled on 2.3; bug 979621 +skip-if = android_version == "10" [testOverscroll] [testPanCorrectness] # disabled on x86 only; bug 927476 From 97df06cc1db0e35c58951bca10927adbfc679847 Mon Sep 17 00:00:00 2001 From: Andrew McCreight Date: Tue, 4 Mar 2014 16:21:48 -0800 Subject: [PATCH 040/112] Bug 979047, part 1 - Only clear mBeginSliceTime in EndCycleCollectionCallback. r=smaug Run FinishCycleCollectionSlice only once per slice, and only if we've previously run PrepareForCycleCollectionSlice. --- dom/base/nsJSEnvironment.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/dom/base/nsJSEnvironment.cpp b/dom/base/nsJSEnvironment.cpp index 330679921ce..d5dcc0ed45f 100644 --- a/dom/base/nsJSEnvironment.cpp +++ b/dom/base/nsJSEnvironment.cpp @@ -2000,9 +2000,15 @@ struct CycleCollectorStats void FinishCycleCollectionSlice() { + if (mBeginSliceTime.IsNull()) { + // We already called this method from EndCycleCollectionCallback for this slice. + return; + } + uint32_t sliceTime = TimeUntilNow(mBeginSliceTime); mMaxSliceTime = std::max(mMaxSliceTime, sliceTime); mTotalSliceTime += sliceTime; + mBeginSliceTime = TimeStamp(); MOZ_ASSERT(mExtraForgetSkippableCalls == 0, "Forget to reset extra forget skippable calls?"); } @@ -2197,7 +2203,9 @@ nsJSContext::EndCycleCollectionCallback(CycleCollectorResults &aResults) nsJSContext::KillICCTimer(); - // Update timing information for the current slice before we log it. + // Update timing information for the current slice before we log it, if + // we previously called PrepareForCycleCollectionSlice(). During shutdown + // CCs, this won't happen. gCCStats.FinishCycleCollectionSlice(); sCCollectedWaitingForGC += aResults.mFreedRefCounted + aResults.mFreedGCed; From b6b53568d52644833d9bf7ab10e1a2054823b572 Mon Sep 17 00:00:00 2001 From: Andrew McCreight Date: Tue, 4 Mar 2014 16:21:48 -0800 Subject: [PATCH 041/112] Bug 979047, part 2 - Remove unused endGCTime assignments. r=smaug --- dom/base/nsJSEnvironment.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/dom/base/nsJSEnvironment.cpp b/dom/base/nsJSEnvironment.cpp index d5dcc0ed45f..4ecdbb1fad8 100644 --- a/dom/base/nsJSEnvironment.cpp +++ b/dom/base/nsJSEnvironment.cpp @@ -2069,15 +2069,11 @@ CycleCollectorStats::PrepareForCycleCollectionSlice(int32_t aExtraForgetSkippabl mBeginSliceTime = TimeStamp::Now(); // Before we begin the cycle collection, make sure there is no active GC. - TimeStamp endGCTime; if (sCCLockedOut) { mAnyLockedOut = true; FinishAnyIncrementalGC(); - endGCTime = TimeStamp::Now(); - uint32_t gcTime = TimeBetween(mBeginSliceTime, endGCTime); + uint32_t gcTime = TimeBetween(mBeginSliceTime, TimeStamp::Now()); mMaxGCDuration = std::max(mMaxGCDuration, gcTime); - } else { - endGCTime = mBeginSliceTime; } mExtraForgetSkippableCalls = aExtraForgetSkippableCalls; From 14d6458449853539b8be51d2f452df923facc883 Mon Sep 17 00:00:00 2001 From: Andrew McCreight Date: Tue, 4 Mar 2014 16:21:48 -0800 Subject: [PATCH 042/112] Bug 979047, part 3 - Make sure we trigger a GC after a current ICC when we poke the GC. r=smaug --- dom/base/nsJSEnvironment.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/dom/base/nsJSEnvironment.cpp b/dom/base/nsJSEnvironment.cpp index 4ecdbb1fad8..fbd1f7cb680 100644 --- a/dom/base/nsJSEnvironment.cpp +++ b/dom/base/nsJSEnvironment.cpp @@ -2504,6 +2504,13 @@ nsJSContext::PokeGC(JS::gcreason::Reason aReason, int aDelay) return; } + if (sICCTimer) { + // Make sure GC is called after the current CC completes. + // No need to set sNeedsFullCC because we are currently running a CC. + sNeedsGCAfterCC = true; + return; + } + CallCreateInstance("@mozilla.org/timer;1", &sGCTimer); if (!sGCTimer) { From 150f32e6313e11bd85c9f947c816d08683ab0e46 Mon Sep 17 00:00:00 2001 From: Andrew McCreight Date: Tue, 4 Mar 2014 16:21:48 -0800 Subject: [PATCH 043/112] Bug 979047, part 4 - Run ICCSliceTime() after PrepareForCollectionSlice. r=smaug This way we take into account time spent finishing off a GC, or something. --- dom/base/nsJSEnvironment.cpp | 8 ++++---- dom/base/nsJSEnvironment.h | 6 ++---- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/dom/base/nsJSEnvironment.cpp b/dom/base/nsJSEnvironment.cpp index fbd1f7cb680..d8337ad1ebc 100644 --- a/dom/base/nsJSEnvironment.cpp +++ b/dom/base/nsJSEnvironment.cpp @@ -2124,7 +2124,7 @@ nsJSContext::CycleCollectNow(nsICycleCollectorListener *aListener, //static void -nsJSContext::RunCycleCollectorSlice(int64_t aSliceTime) +nsJSContext::RunCycleCollectorSlice() { if (!NS_IsMainThread()) { return; @@ -2135,7 +2135,7 @@ nsJSContext::RunCycleCollectorSlice(int64_t aSliceTime) // Ideally, the slice time would be decreased by the amount of // time spent on PrepareForCycleCollection(). gCCStats.PrepareForCycleCollectionSlice(); - nsCycleCollector_collectSlice(aSliceTime); + nsCycleCollector_collectSlice(ICCSliceTime()); gCCStats.FinishCycleCollectionSlice(); } @@ -2160,7 +2160,7 @@ ICCTimerFired(nsITimer* aTimer, void* aClosure) } } - nsJSContext::RunCycleCollectorSlice(ICCSliceTime()); + nsJSContext::RunCycleCollectorSlice(); } //static @@ -2436,7 +2436,7 @@ CCTimerFired(nsITimer *aTimer, void *aClosure) // We are in the final timer fire and still meet the conditions for // triggering a CC. Let RunCycleCollectorSlice finish the current IGC, if // any because that will allow us to include the GC time in the CC pause. - nsJSContext::RunCycleCollectorSlice(ICCSliceTime()); + nsJSContext::RunCycleCollectorSlice(); } } else if ((sPreviousSuspectedCount + 100) <= suspected) { // Only do a forget skippable if there are more than a few new objects. diff --git a/dom/base/nsJSEnvironment.h b/dom/base/nsJSEnvironment.h index f356ccdd09e..e862f7897b9 100644 --- a/dom/base/nsJSEnvironment.h +++ b/dom/base/nsJSEnvironment.h @@ -110,10 +110,8 @@ public: static void CycleCollectNow(nsICycleCollectorListener *aListener = nullptr, int32_t aExtraForgetSkippableCalls = 0); - // If aSliceTime is negative, the CC will run to completion. If aSliceTime - // is 0, only a minimum quantum of work will be done. Otherwise, aSliceTime - // will be used as the time budget for the slice, in ms. - static void RunCycleCollectorSlice(int64_t aSliceTime); + // Run a cycle collector slice, using a heuristic to decide how long to run it. + static void RunCycleCollectorSlice(); static void BeginCycleCollectionCallback(); static void EndCycleCollectionCallback(mozilla::CycleCollectorResults &aResults); From b08be36469fa0af728c18ca2a6ae7c7678b8a5a3 Mon Sep 17 00:00:00 2001 From: Andrew McCreight Date: Tue, 4 Mar 2014 16:21:48 -0800 Subject: [PATCH 044/112] Bug 979047, part 5 - Make sure we have at least one early forgetSkippable timer fire. r=smaug With ICC, ccDelay can get close to NS_CC_SKIPPABLE_DELAY, but we want to always want to run at least one forgetSkippable before the actual CC. --- dom/base/nsJSEnvironment.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/dom/base/nsJSEnvironment.cpp b/dom/base/nsJSEnvironment.cpp index d8337ad1ebc..b159953bd7b 100644 --- a/dom/base/nsJSEnvironment.cpp +++ b/dom/base/nsJSEnvironment.cpp @@ -181,7 +181,7 @@ static uint32_t sCCollectedWaitingForGC; static uint32_t sLikelyShortLivingObjectsNeedingGC; static bool sPostGCEventsToConsole; static bool sPostGCEventsToObserver; -static uint32_t sCCTimerFireCount = 0; +static int32_t sCCTimerFireCount = 0; static uint32_t sMinForgetSkippableTime = UINT32_MAX; static uint32_t sMaxForgetSkippableTime = 0; static uint32_t sTotalForgetSkippableTime = 0; @@ -2420,8 +2420,9 @@ CCTimerFired(nsITimer *aTimer, void *aClosure) // During early timer fires, we only run forgetSkippable. During the first // late timer fire, we decide if we are going to have a second and final - // late timer fire, where we may begin to run the CC. - uint32_t numEarlyTimerFires = ccDelay / NS_CC_SKIPPABLE_DELAY - 2; + // late timer fire, where we may begin to run the CC. Should run at least one + // early timer fire to allow cleanup before the CC. + int32_t numEarlyTimerFires = std::max((int32_t)ccDelay / NS_CC_SKIPPABLE_DELAY - 2, 1); bool isLateTimerFire = sCCTimerFireCount > numEarlyTimerFires; uint32_t suspected = nsCycleCollector_suspectedCount(); if (isLateTimerFire && ShouldTriggerCC(suspected)) { From 70a03075f7c7b2edd7064cb8d62ce8975e2e688e Mon Sep 17 00:00:00 2001 From: Daniel Schattenkirchner Date: Tue, 4 Mar 2014 14:09:37 -0800 Subject: [PATCH 045/112] Bug 921761 - margin-collapsing test suite, wave 8; dynamic and additional cases for margins of a BFC; Multi-column margins; margins given in percent and em; r=dholbert --HG-- rename : layout/reftests/margin-collapsing/block-abs-pos-1.html => layout/reftests/margin-collapsing/block-abs-pos-1-dyn.html rename : layout/reftests/margin-collapsing/block-abs-pos-2.html => layout/reftests/margin-collapsing/block-abs-pos-2-dyn.html rename : layout/reftests/margin-collapsing/block-float-1a.html => layout/reftests/margin-collapsing/block-float-1a-dyn.html rename : layout/reftests/margin-collapsing/block-float-1b.html => layout/reftests/margin-collapsing/block-float-1b-dyn.html rename : layout/reftests/margin-collapsing/block-float-2a.html => layout/reftests/margin-collapsing/block-float-2a-dyn.html rename : layout/reftests/margin-collapsing/block-float-2b.html => layout/reftests/margin-collapsing/block-float-2b-dyn.html rename : layout/reftests/margin-collapsing/block-no-content-1a.html => layout/reftests/margin-collapsing/block-no-content-1a-dyn.html rename : layout/reftests/margin-collapsing/block-no-content-1b.html => layout/reftests/margin-collapsing/block-no-content-1b-dyn.html rename : layout/reftests/margin-collapsing/block-no-content-1c.html => layout/reftests/margin-collapsing/block-no-content-1c-dyn.html rename : layout/reftests/margin-collapsing/block-no-content-2a.html => layout/reftests/margin-collapsing/block-no-content-2a-dyn.html rename : layout/reftests/margin-collapsing/block-no-content-2b.html => layout/reftests/margin-collapsing/block-no-content-2b-dyn.html rename : layout/reftests/margin-collapsing/block-no-content-2c.html => layout/reftests/margin-collapsing/block-no-content-2c-dyn.html rename : layout/reftests/margin-collapsing/block-no-content-2d.html => layout/reftests/margin-collapsing/block-no-content-2d-dyn.html rename : layout/reftests/margin-collapsing/block-no-content-3.html => layout/reftests/margin-collapsing/block-no-content-3a-dyn.html rename : layout/reftests/margin-collapsing/block-no-content-3.html => layout/reftests/margin-collapsing/block-no-content-3a.html rename : layout/reftests/margin-collapsing/block-no-content-4.html => layout/reftests/margin-collapsing/block-no-content-4a-dyn.html rename : layout/reftests/margin-collapsing/block-no-content-4.html => layout/reftests/margin-collapsing/block-no-content-4a.html rename : layout/reftests/margin-collapsing/block-overflow-1.html => layout/reftests/margin-collapsing/block-overflow-1-dyn.html rename : layout/reftests/margin-collapsing/block-overflow-2.html => layout/reftests/margin-collapsing/block-overflow-2-dyn.html rename : layout/reftests/margin-collapsing/block-overflow-3.html => layout/reftests/margin-collapsing/block-overflow-3-dyn.html rename : layout/reftests/margin-collapsing/block-overflow-4.html => layout/reftests/margin-collapsing/block-overflow-4-dyn.html rename : layout/reftests/margin-collapsing/block-overflow-5a.html => layout/reftests/margin-collapsing/block-overflow-5a-dyn.html rename : layout/reftests/margin-collapsing/block-overflow-5b.html => layout/reftests/margin-collapsing/block-overflow-5b-dyn.html rename : layout/reftests/margin-collapsing/block-overflow-5c.html => layout/reftests/margin-collapsing/block-overflow-5c-dyn.html rename : layout/reftests/margin-collapsing/block-overflow-5d.html => layout/reftests/margin-collapsing/block-overflow-5d-dyn.html rename : layout/reftests/margin-collapsing/block-percent-1.html => layout/reftests/margin-collapsing/block-percent-1-dyn.html rename : layout/reftests/margin-collapsing/fieldset-child-1.html => layout/reftests/margin-collapsing/fieldset-child-1-dyn.html rename : layout/reftests/margin-collapsing/fieldset-sibling-1a.html => layout/reftests/margin-collapsing/fieldset-sibling-1a-dyn.html rename : layout/reftests/margin-collapsing/fieldset-sibling-1b.html => layout/reftests/margin-collapsing/fieldset-sibling-1b-dyn.html rename : layout/reftests/margin-collapsing/fieldset-sibling-1c.html => layout/reftests/margin-collapsing/fieldset-sibling-1c-dyn.html rename : layout/reftests/margin-collapsing/fieldset-sibling-2a.html => layout/reftests/margin-collapsing/fieldset-sibling-2a-dyn.html rename : layout/reftests/margin-collapsing/fieldset-sibling-2b.html => layout/reftests/margin-collapsing/fieldset-sibling-2b-dyn.html rename : layout/reftests/margin-collapsing/fieldset-sibling-2c.html => layout/reftests/margin-collapsing/fieldset-sibling-2c-dyn.html rename : layout/reftests/margin-collapsing/inline-block-child-1.html => layout/reftests/margin-collapsing/inline-block-child-1-dyn.html rename : layout/reftests/margin-collapsing/inline-block-child-2.html => layout/reftests/margin-collapsing/inline-block-child-2-dyn.html rename : layout/reftests/margin-collapsing/inline-block-sibling-1a.html => layout/reftests/margin-collapsing/inline-block-sibling-1a-dyn.html rename : layout/reftests/margin-collapsing/inline-block-sibling-1b.html => layout/reftests/margin-collapsing/inline-block-sibling-1b-dyn.html rename : layout/reftests/margin-collapsing/inline-block-sibling-1c.html => layout/reftests/margin-collapsing/inline-block-sibling-1c-dyn.html rename : layout/reftests/margin-collapsing/inline-block-sibling-2.html => layout/reftests/margin-collapsing/inline-block-sibling-2-dyn.html rename : layout/reftests/margin-collapsing/table-caption-1a.html => layout/reftests/margin-collapsing/table-caption-1a-dyn.html rename : layout/reftests/margin-collapsing/table-caption-1b.html => layout/reftests/margin-collapsing/table-caption-1b-dyn.html rename : layout/reftests/margin-collapsing/table-caption-2a.html => layout/reftests/margin-collapsing/table-caption-2a-dyn.html rename : layout/reftests/margin-collapsing/table-caption-2b.html => layout/reftests/margin-collapsing/table-caption-2b-dyn.html rename : layout/reftests/margin-collapsing/table-caption-2c.html => layout/reftests/margin-collapsing/table-caption-2c-dyn.html rename : layout/reftests/margin-collapsing/table-caption-bottom-1.html => layout/reftests/margin-collapsing/table-caption-bottom-1-dyn.html rename : layout/reftests/margin-collapsing/table-caption-bottom-2.html => layout/reftests/margin-collapsing/table-caption-bottom-2-dyn.html rename : layout/reftests/margin-collapsing/table-caption-top-1.html => layout/reftests/margin-collapsing/table-caption-top-1-dyn.html rename : layout/reftests/margin-collapsing/table-caption-top-2.html => layout/reftests/margin-collapsing/table-caption-top-2-dyn.html --- .../block-abs-pos-1-dyn.html | 39 ++++++ .../block-abs-pos-2-dyn.html | 31 +++++ .../block-em-length-1-dyn.html | 31 +++++ .../block-em-length-1-ref.html | 27 ++++ .../margin-collapsing/block-em-length-1.html | 25 ++++ .../margin-collapsing/block-float-1a-dyn.html | 28 ++++ .../margin-collapsing/block-float-1b-dyn.html | 28 ++++ .../margin-collapsing/block-float-2a-dyn.html | 34 +++++ .../margin-collapsing/block-float-2b-dyn.html | 34 +++++ .../margin-collapsing/block-float-3a-dyn.html | 36 +++++ .../margin-collapsing/block-float-3a-ref.html | 23 ++++ .../margin-collapsing/block-float-3a.html | 29 +++++ .../margin-collapsing/block-float-3b-dyn.html | 36 +++++ .../margin-collapsing/block-float-3b-ref.html | 23 ++++ .../margin-collapsing/block-float-3b.html | 29 +++++ .../block-no-content-1a-dyn.html | 23 ++++ .../block-no-content-1b-dyn.html | 23 ++++ .../block-no-content-1c-dyn.html | 23 ++++ .../block-no-content-1d-dyn.html | 23 ++++ .../block-no-content-1d.html | 20 +++ .../block-no-content-2a-dyn.html | 32 +++++ .../block-no-content-2b-dyn.html | 32 +++++ .../block-no-content-2c-dyn.html | 32 +++++ .../block-no-content-2d-dyn.html | 32 +++++ .../block-no-content-2e-dyn.html | 32 +++++ .../block-no-content-2e.html | 26 ++++ .../block-no-content-3a-dyn.html | 36 +++++ ...ontent-3.html => block-no-content-3a.html} | 0 .../block-no-content-3b-dyn.html | 35 +++++ .../block-no-content-3b.html | 29 +++++ .../block-no-content-3c-dyn.html | 35 +++++ .../block-no-content-3c.html | 29 +++++ .../block-no-content-4a-dyn.html | 36 +++++ ...ontent-4.html => block-no-content-4a.html} | 0 .../block-no-content-4b-dyn.html | 35 +++++ .../block-no-content-4b.html | 29 +++++ .../block-no-content-4c-dyn.html | 35 +++++ .../block-no-content-4c.html | 29 +++++ .../block-no-content-5-ref.html | 21 +++ .../block-no-content-5a-dyn.html | 32 +++++ .../block-no-content-5a.html | 26 ++++ .../block-no-content-5b-dyn.html | 32 +++++ .../block-no-content-5b.html | 26 ++++ .../block-no-content-6-dyn.html | 34 +++++ .../block-no-content-6-ref.html | 24 ++++ .../margin-collapsing/block-no-content-6.html | 28 ++++ .../block-no-content-7-dyn.html | 27 ++++ .../block-no-content-7-ref.html | 19 +++ .../margin-collapsing/block-no-content-7.html | 21 +++ .../block-no-content-8-dyn.html | 34 +++++ .../block-no-content-8-ref.html | 30 +++++ .../margin-collapsing/block-no-content-8.html | 28 ++++ .../block-overflow-1-dyn.html | 35 +++++ .../block-overflow-2-dyn.html | 35 +++++ .../block-overflow-3-dyn.html | 36 +++++ .../block-overflow-4-dyn.html | 37 ++++++ .../block-overflow-5a-dyn.html | 35 +++++ .../block-overflow-5b-dyn.html | 35 +++++ .../block-overflow-5c-dyn.html | 34 +++++ .../block-overflow-5d-dyn.html | 35 +++++ .../block-percent-1-dyn.html | 32 +++++ .../margin-collapsing/block-percent-1.html | 2 +- .../block-percent-2-dyn.html | 38 ++++++ .../block-percent-2-ref.html | 33 +++++ .../margin-collapsing/block-percent-2.html | 31 +++++ .../caption-child-1-dyn.html | 40 ++++++ .../caption-child-1-ref.html | 27 ++++ .../margin-collapsing/caption-child-1.html | 33 +++++ .../margin-collapsing/column-child-1-dyn.html | 32 +++++ .../margin-collapsing/column-child-1-ref.html | 26 ++++ .../margin-collapsing/column-child-1.html | 26 ++++ .../column-sibling-1-ref.html | 25 ++++ .../column-sibling-1a-dyn.html | 37 ++++++ .../margin-collapsing/column-sibling-1a.html | 29 +++++ .../column-sibling-1b-dyn.html | 37 ++++++ .../margin-collapsing/column-sibling-1b.html | 29 +++++ .../column-sibling-1c-dyn.html | 37 ++++++ .../margin-collapsing/column-sibling-1c.html | 29 +++++ .../column-sibling-2-ref.html | 21 +++ .../column-sibling-2a-dyn.html | 35 +++++ .../margin-collapsing/column-sibling-2a.html | 27 ++++ .../column-sibling-2b-dyn.html | 35 +++++ .../margin-collapsing/column-sibling-2b.html | 27 ++++ .../column-sibling-2c-dyn.html | 35 +++++ .../margin-collapsing/column-sibling-2c.html | 27 ++++ .../fieldset-child-1-dyn.html | 35 +++++ .../fieldset-sibling-1a-dyn.html | 36 +++++ .../fieldset-sibling-1b-dyn.html | 36 +++++ .../fieldset-sibling-1c-dyn.html | 36 +++++ .../fieldset-sibling-1c.html | 2 +- .../fieldset-sibling-2a-dyn.html | 34 +++++ .../fieldset-sibling-2b-dyn.html | 34 +++++ .../fieldset-sibling-2c-dyn.html | 34 +++++ .../inline-block-child-1-dyn.html | 30 +++++ .../inline-block-child-2-dyn.html | 26 ++++ .../inline-block-child-3-dyn.html | 29 +++++ .../inline-block-child-3-ref.html | 22 ++++ .../inline-block-child-3.html | 22 ++++ .../inline-block-sibling-1a-dyn.html | 36 +++++ .../inline-block-sibling-1b-dyn.html | 36 +++++ .../inline-block-sibling-1c-dyn.html | 36 +++++ .../inline-block-sibling-2-dyn.html | 38 ++++++ .../reftests/margin-collapsing/reftest.list | 123 +++++++++++++++++- .../table-caption-1a-dyn.html | 41 ++++++ .../table-caption-1b-dyn.html | 41 ++++++ .../table-caption-1c-dyn.html | 41 ++++++ .../margin-collapsing/table-caption-1c.html | 34 +++++ .../table-caption-2a-dyn.html | 36 +++++ .../table-caption-2b-dyn.html | 36 +++++ .../table-caption-2c-dyn.html | 36 +++++ .../table-caption-bottom-1-dyn.html | 48 +++++++ .../table-caption-bottom-2-dyn.html | 43 ++++++ .../table-caption-bottom-outside-1-dyn.html | 48 +++++++ .../table-caption-bottom-outside-1.html | 41 ++++++ .../table-caption-bottom-outside-2-dyn.html | 43 ++++++ .../table-caption-bottom-outside-2.html | 36 +++++ .../table-caption-top-1-dyn.html | 48 +++++++ .../table-caption-top-2-dyn.html | 43 ++++++ .../table-caption-top-outside-1-dyn.html | 48 +++++++ .../table-caption-top-outside-1.html | 41 ++++++ .../table-caption-top-outside-2-dyn.html | 43 ++++++ .../table-caption-top-outside-2.html | 36 +++++ 122 files changed, 3916 insertions(+), 5 deletions(-) create mode 100644 layout/reftests/margin-collapsing/block-abs-pos-1-dyn.html create mode 100644 layout/reftests/margin-collapsing/block-abs-pos-2-dyn.html create mode 100644 layout/reftests/margin-collapsing/block-em-length-1-dyn.html create mode 100644 layout/reftests/margin-collapsing/block-em-length-1-ref.html create mode 100644 layout/reftests/margin-collapsing/block-em-length-1.html create mode 100644 layout/reftests/margin-collapsing/block-float-1a-dyn.html create mode 100644 layout/reftests/margin-collapsing/block-float-1b-dyn.html create mode 100644 layout/reftests/margin-collapsing/block-float-2a-dyn.html create mode 100644 layout/reftests/margin-collapsing/block-float-2b-dyn.html create mode 100644 layout/reftests/margin-collapsing/block-float-3a-dyn.html create mode 100644 layout/reftests/margin-collapsing/block-float-3a-ref.html create mode 100644 layout/reftests/margin-collapsing/block-float-3a.html create mode 100644 layout/reftests/margin-collapsing/block-float-3b-dyn.html create mode 100644 layout/reftests/margin-collapsing/block-float-3b-ref.html create mode 100644 layout/reftests/margin-collapsing/block-float-3b.html create mode 100644 layout/reftests/margin-collapsing/block-no-content-1a-dyn.html create mode 100644 layout/reftests/margin-collapsing/block-no-content-1b-dyn.html create mode 100644 layout/reftests/margin-collapsing/block-no-content-1c-dyn.html create mode 100644 layout/reftests/margin-collapsing/block-no-content-1d-dyn.html create mode 100644 layout/reftests/margin-collapsing/block-no-content-1d.html create mode 100644 layout/reftests/margin-collapsing/block-no-content-2a-dyn.html create mode 100644 layout/reftests/margin-collapsing/block-no-content-2b-dyn.html create mode 100644 layout/reftests/margin-collapsing/block-no-content-2c-dyn.html create mode 100644 layout/reftests/margin-collapsing/block-no-content-2d-dyn.html create mode 100644 layout/reftests/margin-collapsing/block-no-content-2e-dyn.html create mode 100644 layout/reftests/margin-collapsing/block-no-content-2e.html create mode 100644 layout/reftests/margin-collapsing/block-no-content-3a-dyn.html rename layout/reftests/margin-collapsing/{block-no-content-3.html => block-no-content-3a.html} (100%) create mode 100644 layout/reftests/margin-collapsing/block-no-content-3b-dyn.html create mode 100644 layout/reftests/margin-collapsing/block-no-content-3b.html create mode 100644 layout/reftests/margin-collapsing/block-no-content-3c-dyn.html create mode 100644 layout/reftests/margin-collapsing/block-no-content-3c.html create mode 100644 layout/reftests/margin-collapsing/block-no-content-4a-dyn.html rename layout/reftests/margin-collapsing/{block-no-content-4.html => block-no-content-4a.html} (100%) create mode 100644 layout/reftests/margin-collapsing/block-no-content-4b-dyn.html create mode 100644 layout/reftests/margin-collapsing/block-no-content-4b.html create mode 100644 layout/reftests/margin-collapsing/block-no-content-4c-dyn.html create mode 100644 layout/reftests/margin-collapsing/block-no-content-4c.html create mode 100644 layout/reftests/margin-collapsing/block-no-content-5-ref.html create mode 100644 layout/reftests/margin-collapsing/block-no-content-5a-dyn.html create mode 100644 layout/reftests/margin-collapsing/block-no-content-5a.html create mode 100644 layout/reftests/margin-collapsing/block-no-content-5b-dyn.html create mode 100644 layout/reftests/margin-collapsing/block-no-content-5b.html create mode 100644 layout/reftests/margin-collapsing/block-no-content-6-dyn.html create mode 100644 layout/reftests/margin-collapsing/block-no-content-6-ref.html create mode 100644 layout/reftests/margin-collapsing/block-no-content-6.html create mode 100644 layout/reftests/margin-collapsing/block-no-content-7-dyn.html create mode 100644 layout/reftests/margin-collapsing/block-no-content-7-ref.html create mode 100644 layout/reftests/margin-collapsing/block-no-content-7.html create mode 100644 layout/reftests/margin-collapsing/block-no-content-8-dyn.html create mode 100644 layout/reftests/margin-collapsing/block-no-content-8-ref.html create mode 100644 layout/reftests/margin-collapsing/block-no-content-8.html create mode 100644 layout/reftests/margin-collapsing/block-overflow-1-dyn.html create mode 100644 layout/reftests/margin-collapsing/block-overflow-2-dyn.html create mode 100644 layout/reftests/margin-collapsing/block-overflow-3-dyn.html create mode 100644 layout/reftests/margin-collapsing/block-overflow-4-dyn.html create mode 100644 layout/reftests/margin-collapsing/block-overflow-5a-dyn.html create mode 100644 layout/reftests/margin-collapsing/block-overflow-5b-dyn.html create mode 100644 layout/reftests/margin-collapsing/block-overflow-5c-dyn.html create mode 100644 layout/reftests/margin-collapsing/block-overflow-5d-dyn.html create mode 100644 layout/reftests/margin-collapsing/block-percent-1-dyn.html create mode 100644 layout/reftests/margin-collapsing/block-percent-2-dyn.html create mode 100644 layout/reftests/margin-collapsing/block-percent-2-ref.html create mode 100644 layout/reftests/margin-collapsing/block-percent-2.html create mode 100644 layout/reftests/margin-collapsing/caption-child-1-dyn.html create mode 100644 layout/reftests/margin-collapsing/caption-child-1-ref.html create mode 100644 layout/reftests/margin-collapsing/caption-child-1.html create mode 100644 layout/reftests/margin-collapsing/column-child-1-dyn.html create mode 100644 layout/reftests/margin-collapsing/column-child-1-ref.html create mode 100644 layout/reftests/margin-collapsing/column-child-1.html create mode 100644 layout/reftests/margin-collapsing/column-sibling-1-ref.html create mode 100644 layout/reftests/margin-collapsing/column-sibling-1a-dyn.html create mode 100644 layout/reftests/margin-collapsing/column-sibling-1a.html create mode 100644 layout/reftests/margin-collapsing/column-sibling-1b-dyn.html create mode 100644 layout/reftests/margin-collapsing/column-sibling-1b.html create mode 100644 layout/reftests/margin-collapsing/column-sibling-1c-dyn.html create mode 100644 layout/reftests/margin-collapsing/column-sibling-1c.html create mode 100644 layout/reftests/margin-collapsing/column-sibling-2-ref.html create mode 100644 layout/reftests/margin-collapsing/column-sibling-2a-dyn.html create mode 100644 layout/reftests/margin-collapsing/column-sibling-2a.html create mode 100644 layout/reftests/margin-collapsing/column-sibling-2b-dyn.html create mode 100644 layout/reftests/margin-collapsing/column-sibling-2b.html create mode 100644 layout/reftests/margin-collapsing/column-sibling-2c-dyn.html create mode 100644 layout/reftests/margin-collapsing/column-sibling-2c.html create mode 100644 layout/reftests/margin-collapsing/fieldset-child-1-dyn.html create mode 100644 layout/reftests/margin-collapsing/fieldset-sibling-1a-dyn.html create mode 100644 layout/reftests/margin-collapsing/fieldset-sibling-1b-dyn.html create mode 100644 layout/reftests/margin-collapsing/fieldset-sibling-1c-dyn.html create mode 100644 layout/reftests/margin-collapsing/fieldset-sibling-2a-dyn.html create mode 100644 layout/reftests/margin-collapsing/fieldset-sibling-2b-dyn.html create mode 100644 layout/reftests/margin-collapsing/fieldset-sibling-2c-dyn.html create mode 100644 layout/reftests/margin-collapsing/inline-block-child-1-dyn.html create mode 100644 layout/reftests/margin-collapsing/inline-block-child-2-dyn.html create mode 100644 layout/reftests/margin-collapsing/inline-block-child-3-dyn.html create mode 100644 layout/reftests/margin-collapsing/inline-block-child-3-ref.html create mode 100644 layout/reftests/margin-collapsing/inline-block-child-3.html create mode 100644 layout/reftests/margin-collapsing/inline-block-sibling-1a-dyn.html create mode 100644 layout/reftests/margin-collapsing/inline-block-sibling-1b-dyn.html create mode 100644 layout/reftests/margin-collapsing/inline-block-sibling-1c-dyn.html create mode 100644 layout/reftests/margin-collapsing/inline-block-sibling-2-dyn.html create mode 100644 layout/reftests/margin-collapsing/table-caption-1a-dyn.html create mode 100644 layout/reftests/margin-collapsing/table-caption-1b-dyn.html create mode 100644 layout/reftests/margin-collapsing/table-caption-1c-dyn.html create mode 100644 layout/reftests/margin-collapsing/table-caption-1c.html create mode 100644 layout/reftests/margin-collapsing/table-caption-2a-dyn.html create mode 100644 layout/reftests/margin-collapsing/table-caption-2b-dyn.html create mode 100644 layout/reftests/margin-collapsing/table-caption-2c-dyn.html create mode 100644 layout/reftests/margin-collapsing/table-caption-bottom-1-dyn.html create mode 100644 layout/reftests/margin-collapsing/table-caption-bottom-2-dyn.html create mode 100644 layout/reftests/margin-collapsing/table-caption-bottom-outside-1-dyn.html create mode 100644 layout/reftests/margin-collapsing/table-caption-bottom-outside-1.html create mode 100644 layout/reftests/margin-collapsing/table-caption-bottom-outside-2-dyn.html create mode 100644 layout/reftests/margin-collapsing/table-caption-bottom-outside-2.html create mode 100644 layout/reftests/margin-collapsing/table-caption-top-1-dyn.html create mode 100644 layout/reftests/margin-collapsing/table-caption-top-2-dyn.html create mode 100644 layout/reftests/margin-collapsing/table-caption-top-outside-1-dyn.html create mode 100644 layout/reftests/margin-collapsing/table-caption-top-outside-1.html create mode 100644 layout/reftests/margin-collapsing/table-caption-top-outside-2-dyn.html create mode 100644 layout/reftests/margin-collapsing/table-caption-top-outside-2.html diff --git a/layout/reftests/margin-collapsing/block-abs-pos-1-dyn.html b/layout/reftests/margin-collapsing/block-abs-pos-1-dyn.html new file mode 100644 index 00000000000..d71584e2d86 --- /dev/null +++ b/layout/reftests/margin-collapsing/block-abs-pos-1-dyn.html @@ -0,0 +1,39 @@ + + + + + + + + +
+
+
+ + diff --git a/layout/reftests/margin-collapsing/block-abs-pos-2-dyn.html b/layout/reftests/margin-collapsing/block-abs-pos-2-dyn.html new file mode 100644 index 00000000000..e59e53e84be --- /dev/null +++ b/layout/reftests/margin-collapsing/block-abs-pos-2-dyn.html @@ -0,0 +1,31 @@ + + + + + + + + +
+
+
+ + diff --git a/layout/reftests/margin-collapsing/block-em-length-1-dyn.html b/layout/reftests/margin-collapsing/block-em-length-1-dyn.html new file mode 100644 index 00000000000..961f28753f0 --- /dev/null +++ b/layout/reftests/margin-collapsing/block-em-length-1-dyn.html @@ -0,0 +1,31 @@ + + + + + + + +
+
+ + diff --git a/layout/reftests/margin-collapsing/block-em-length-1-ref.html b/layout/reftests/margin-collapsing/block-em-length-1-ref.html new file mode 100644 index 00000000000..848a2382fd4 --- /dev/null +++ b/layout/reftests/margin-collapsing/block-em-length-1-ref.html @@ -0,0 +1,27 @@ + + + + + + +
+
+
+ + diff --git a/layout/reftests/margin-collapsing/block-em-length-1.html b/layout/reftests/margin-collapsing/block-em-length-1.html new file mode 100644 index 00000000000..bc66603140c --- /dev/null +++ b/layout/reftests/margin-collapsing/block-em-length-1.html @@ -0,0 +1,25 @@ + + + + + + +
+
+ + diff --git a/layout/reftests/margin-collapsing/block-float-1a-dyn.html b/layout/reftests/margin-collapsing/block-float-1a-dyn.html new file mode 100644 index 00000000000..072f3d372fa --- /dev/null +++ b/layout/reftests/margin-collapsing/block-float-1a-dyn.html @@ -0,0 +1,28 @@ + + + + + + + +
+
+ + diff --git a/layout/reftests/margin-collapsing/block-float-1b-dyn.html b/layout/reftests/margin-collapsing/block-float-1b-dyn.html new file mode 100644 index 00000000000..89e7bd5664d --- /dev/null +++ b/layout/reftests/margin-collapsing/block-float-1b-dyn.html @@ -0,0 +1,28 @@ + + + + + + + +
+
+ + diff --git a/layout/reftests/margin-collapsing/block-float-2a-dyn.html b/layout/reftests/margin-collapsing/block-float-2a-dyn.html new file mode 100644 index 00000000000..8d1f27fd438 --- /dev/null +++ b/layout/reftests/margin-collapsing/block-float-2a-dyn.html @@ -0,0 +1,34 @@ + + + + + + + +
+
+
+
+ + diff --git a/layout/reftests/margin-collapsing/block-float-2b-dyn.html b/layout/reftests/margin-collapsing/block-float-2b-dyn.html new file mode 100644 index 00000000000..08a0c8a433f --- /dev/null +++ b/layout/reftests/margin-collapsing/block-float-2b-dyn.html @@ -0,0 +1,34 @@ + + + + + + + +
+
+
+
+ + diff --git a/layout/reftests/margin-collapsing/block-float-3a-dyn.html b/layout/reftests/margin-collapsing/block-float-3a-dyn.html new file mode 100644 index 00000000000..be25f763958 --- /dev/null +++ b/layout/reftests/margin-collapsing/block-float-3a-dyn.html @@ -0,0 +1,36 @@ + + + + + + + +
+
+
+
+ + diff --git a/layout/reftests/margin-collapsing/block-float-3a-ref.html b/layout/reftests/margin-collapsing/block-float-3a-ref.html new file mode 100644 index 00000000000..7b776b279f2 --- /dev/null +++ b/layout/reftests/margin-collapsing/block-float-3a-ref.html @@ -0,0 +1,23 @@ + + + + + + +
+
+
+
+
+ + diff --git a/layout/reftests/margin-collapsing/block-float-3a.html b/layout/reftests/margin-collapsing/block-float-3a.html new file mode 100644 index 00000000000..639e72b8bb9 --- /dev/null +++ b/layout/reftests/margin-collapsing/block-float-3a.html @@ -0,0 +1,29 @@ + + + + + + +
+
+
+
+ + diff --git a/layout/reftests/margin-collapsing/block-float-3b-dyn.html b/layout/reftests/margin-collapsing/block-float-3b-dyn.html new file mode 100644 index 00000000000..1fd4431a215 --- /dev/null +++ b/layout/reftests/margin-collapsing/block-float-3b-dyn.html @@ -0,0 +1,36 @@ + + + + + + + +
+
+
+
+ + diff --git a/layout/reftests/margin-collapsing/block-float-3b-ref.html b/layout/reftests/margin-collapsing/block-float-3b-ref.html new file mode 100644 index 00000000000..2e6734c3703 --- /dev/null +++ b/layout/reftests/margin-collapsing/block-float-3b-ref.html @@ -0,0 +1,23 @@ + + + + + + +
+
+
+
+
+ + diff --git a/layout/reftests/margin-collapsing/block-float-3b.html b/layout/reftests/margin-collapsing/block-float-3b.html new file mode 100644 index 00000000000..c2ecd8d2a13 --- /dev/null +++ b/layout/reftests/margin-collapsing/block-float-3b.html @@ -0,0 +1,29 @@ + + + + + + +
+
+
+
+ + diff --git a/layout/reftests/margin-collapsing/block-no-content-1a-dyn.html b/layout/reftests/margin-collapsing/block-no-content-1a-dyn.html new file mode 100644 index 00000000000..e167d73c305 --- /dev/null +++ b/layout/reftests/margin-collapsing/block-no-content-1a-dyn.html @@ -0,0 +1,23 @@ + + + + + + + +
+
+
+ + diff --git a/layout/reftests/margin-collapsing/block-no-content-1b-dyn.html b/layout/reftests/margin-collapsing/block-no-content-1b-dyn.html new file mode 100644 index 00000000000..d82839a6e78 --- /dev/null +++ b/layout/reftests/margin-collapsing/block-no-content-1b-dyn.html @@ -0,0 +1,23 @@ + + + + + + + +
+
+
+ + diff --git a/layout/reftests/margin-collapsing/block-no-content-1c-dyn.html b/layout/reftests/margin-collapsing/block-no-content-1c-dyn.html new file mode 100644 index 00000000000..fe87796340c --- /dev/null +++ b/layout/reftests/margin-collapsing/block-no-content-1c-dyn.html @@ -0,0 +1,23 @@ + + + + + + + +
+
+
+ + diff --git a/layout/reftests/margin-collapsing/block-no-content-1d-dyn.html b/layout/reftests/margin-collapsing/block-no-content-1d-dyn.html new file mode 100644 index 00000000000..2bb68ad7747 --- /dev/null +++ b/layout/reftests/margin-collapsing/block-no-content-1d-dyn.html @@ -0,0 +1,23 @@ + + + + + + + +
+
+
+ + diff --git a/layout/reftests/margin-collapsing/block-no-content-1d.html b/layout/reftests/margin-collapsing/block-no-content-1d.html new file mode 100644 index 00000000000..63bb28eb48a --- /dev/null +++ b/layout/reftests/margin-collapsing/block-no-content-1d.html @@ -0,0 +1,20 @@ + + + + + + +
+
+
+ + diff --git a/layout/reftests/margin-collapsing/block-no-content-2a-dyn.html b/layout/reftests/margin-collapsing/block-no-content-2a-dyn.html new file mode 100644 index 00000000000..c0339efc098 --- /dev/null +++ b/layout/reftests/margin-collapsing/block-no-content-2a-dyn.html @@ -0,0 +1,32 @@ + + + + + + + +
+
+
+ + diff --git a/layout/reftests/margin-collapsing/block-no-content-2b-dyn.html b/layout/reftests/margin-collapsing/block-no-content-2b-dyn.html new file mode 100644 index 00000000000..a278a2d3173 --- /dev/null +++ b/layout/reftests/margin-collapsing/block-no-content-2b-dyn.html @@ -0,0 +1,32 @@ + + + + + + + +
+
+
+ + diff --git a/layout/reftests/margin-collapsing/block-no-content-2c-dyn.html b/layout/reftests/margin-collapsing/block-no-content-2c-dyn.html new file mode 100644 index 00000000000..212222d297b --- /dev/null +++ b/layout/reftests/margin-collapsing/block-no-content-2c-dyn.html @@ -0,0 +1,32 @@ + + + + + + + +
+
+
+ + diff --git a/layout/reftests/margin-collapsing/block-no-content-2d-dyn.html b/layout/reftests/margin-collapsing/block-no-content-2d-dyn.html new file mode 100644 index 00000000000..2c546d0415f --- /dev/null +++ b/layout/reftests/margin-collapsing/block-no-content-2d-dyn.html @@ -0,0 +1,32 @@ + + + + + + + +
+
+
+ + diff --git a/layout/reftests/margin-collapsing/block-no-content-2e-dyn.html b/layout/reftests/margin-collapsing/block-no-content-2e-dyn.html new file mode 100644 index 00000000000..d27fc524da9 --- /dev/null +++ b/layout/reftests/margin-collapsing/block-no-content-2e-dyn.html @@ -0,0 +1,32 @@ + + + + + + + +
+
+
+ + diff --git a/layout/reftests/margin-collapsing/block-no-content-2e.html b/layout/reftests/margin-collapsing/block-no-content-2e.html new file mode 100644 index 00000000000..bb0896d0db3 --- /dev/null +++ b/layout/reftests/margin-collapsing/block-no-content-2e.html @@ -0,0 +1,26 @@ + + + + + + +
+
+
+ + diff --git a/layout/reftests/margin-collapsing/block-no-content-3a-dyn.html b/layout/reftests/margin-collapsing/block-no-content-3a-dyn.html new file mode 100644 index 00000000000..a74e8e402bc --- /dev/null +++ b/layout/reftests/margin-collapsing/block-no-content-3a-dyn.html @@ -0,0 +1,36 @@ + + + + + + + +
+
+
+
+
+ + diff --git a/layout/reftests/margin-collapsing/block-no-content-3.html b/layout/reftests/margin-collapsing/block-no-content-3a.html similarity index 100% rename from layout/reftests/margin-collapsing/block-no-content-3.html rename to layout/reftests/margin-collapsing/block-no-content-3a.html diff --git a/layout/reftests/margin-collapsing/block-no-content-3b-dyn.html b/layout/reftests/margin-collapsing/block-no-content-3b-dyn.html new file mode 100644 index 00000000000..aae9c716539 --- /dev/null +++ b/layout/reftests/margin-collapsing/block-no-content-3b-dyn.html @@ -0,0 +1,35 @@ + + + + + + + +
+
+
+
+
+ + diff --git a/layout/reftests/margin-collapsing/block-no-content-3b.html b/layout/reftests/margin-collapsing/block-no-content-3b.html new file mode 100644 index 00000000000..00f81516316 --- /dev/null +++ b/layout/reftests/margin-collapsing/block-no-content-3b.html @@ -0,0 +1,29 @@ + + + + + + +
+
+
+
+
+ + diff --git a/layout/reftests/margin-collapsing/block-no-content-3c-dyn.html b/layout/reftests/margin-collapsing/block-no-content-3c-dyn.html new file mode 100644 index 00000000000..b4942b4932f --- /dev/null +++ b/layout/reftests/margin-collapsing/block-no-content-3c-dyn.html @@ -0,0 +1,35 @@ + + + + + + + +
+
+
+
+
+ + diff --git a/layout/reftests/margin-collapsing/block-no-content-3c.html b/layout/reftests/margin-collapsing/block-no-content-3c.html new file mode 100644 index 00000000000..39ad02c6210 --- /dev/null +++ b/layout/reftests/margin-collapsing/block-no-content-3c.html @@ -0,0 +1,29 @@ + + + + + + +
+
+
+
+
+ + diff --git a/layout/reftests/margin-collapsing/block-no-content-4a-dyn.html b/layout/reftests/margin-collapsing/block-no-content-4a-dyn.html new file mode 100644 index 00000000000..f8fe446d59f --- /dev/null +++ b/layout/reftests/margin-collapsing/block-no-content-4a-dyn.html @@ -0,0 +1,36 @@ + + + + + + + +
+
+
+
+
+ + diff --git a/layout/reftests/margin-collapsing/block-no-content-4.html b/layout/reftests/margin-collapsing/block-no-content-4a.html similarity index 100% rename from layout/reftests/margin-collapsing/block-no-content-4.html rename to layout/reftests/margin-collapsing/block-no-content-4a.html diff --git a/layout/reftests/margin-collapsing/block-no-content-4b-dyn.html b/layout/reftests/margin-collapsing/block-no-content-4b-dyn.html new file mode 100644 index 00000000000..d4fcf2c36a5 --- /dev/null +++ b/layout/reftests/margin-collapsing/block-no-content-4b-dyn.html @@ -0,0 +1,35 @@ + + + + + + + +
+
+
+
+
+ + diff --git a/layout/reftests/margin-collapsing/block-no-content-4b.html b/layout/reftests/margin-collapsing/block-no-content-4b.html new file mode 100644 index 00000000000..4faf50c21e0 --- /dev/null +++ b/layout/reftests/margin-collapsing/block-no-content-4b.html @@ -0,0 +1,29 @@ + + + + + + +
+
+
+
+
+ + diff --git a/layout/reftests/margin-collapsing/block-no-content-4c-dyn.html b/layout/reftests/margin-collapsing/block-no-content-4c-dyn.html new file mode 100644 index 00000000000..2f5d81750d5 --- /dev/null +++ b/layout/reftests/margin-collapsing/block-no-content-4c-dyn.html @@ -0,0 +1,35 @@ + + + + + + + +
+
+
+
+
+ + diff --git a/layout/reftests/margin-collapsing/block-no-content-4c.html b/layout/reftests/margin-collapsing/block-no-content-4c.html new file mode 100644 index 00000000000..0b6daef65ef --- /dev/null +++ b/layout/reftests/margin-collapsing/block-no-content-4c.html @@ -0,0 +1,29 @@ + + + + + + +
+
+
+
+
+ + diff --git a/layout/reftests/margin-collapsing/block-no-content-5-ref.html b/layout/reftests/margin-collapsing/block-no-content-5-ref.html new file mode 100644 index 00000000000..df55ad5424e --- /dev/null +++ b/layout/reftests/margin-collapsing/block-no-content-5-ref.html @@ -0,0 +1,21 @@ + + + + + + +
+
+
+
+
+ + diff --git a/layout/reftests/margin-collapsing/block-no-content-5a-dyn.html b/layout/reftests/margin-collapsing/block-no-content-5a-dyn.html new file mode 100644 index 00000000000..699755aa619 --- /dev/null +++ b/layout/reftests/margin-collapsing/block-no-content-5a-dyn.html @@ -0,0 +1,32 @@ + + + + + + + +
+
+
+
+
+ + diff --git a/layout/reftests/margin-collapsing/block-no-content-5a.html b/layout/reftests/margin-collapsing/block-no-content-5a.html new file mode 100644 index 00000000000..3926ecd2988 --- /dev/null +++ b/layout/reftests/margin-collapsing/block-no-content-5a.html @@ -0,0 +1,26 @@ + + + + + + +
+
+
+
+
+ + diff --git a/layout/reftests/margin-collapsing/block-no-content-5b-dyn.html b/layout/reftests/margin-collapsing/block-no-content-5b-dyn.html new file mode 100644 index 00000000000..7310942520d --- /dev/null +++ b/layout/reftests/margin-collapsing/block-no-content-5b-dyn.html @@ -0,0 +1,32 @@ + + + + + + + +
+
+
+
+
+ + diff --git a/layout/reftests/margin-collapsing/block-no-content-5b.html b/layout/reftests/margin-collapsing/block-no-content-5b.html new file mode 100644 index 00000000000..39814db731b --- /dev/null +++ b/layout/reftests/margin-collapsing/block-no-content-5b.html @@ -0,0 +1,26 @@ + + + + + + +
+
+
+
+
+ + diff --git a/layout/reftests/margin-collapsing/block-no-content-6-dyn.html b/layout/reftests/margin-collapsing/block-no-content-6-dyn.html new file mode 100644 index 00000000000..c870817e963 --- /dev/null +++ b/layout/reftests/margin-collapsing/block-no-content-6-dyn.html @@ -0,0 +1,34 @@ + + + + + + + +
+
+
+
+ + diff --git a/layout/reftests/margin-collapsing/block-no-content-6-ref.html b/layout/reftests/margin-collapsing/block-no-content-6-ref.html new file mode 100644 index 00000000000..a982b3cbc0a --- /dev/null +++ b/layout/reftests/margin-collapsing/block-no-content-6-ref.html @@ -0,0 +1,24 @@ + + + + + + +
+
+
+
+ + diff --git a/layout/reftests/margin-collapsing/block-no-content-6.html b/layout/reftests/margin-collapsing/block-no-content-6.html new file mode 100644 index 00000000000..3bc17bfa913 --- /dev/null +++ b/layout/reftests/margin-collapsing/block-no-content-6.html @@ -0,0 +1,28 @@ + + + + + + +
+
+
+
+ + diff --git a/layout/reftests/margin-collapsing/block-no-content-7-dyn.html b/layout/reftests/margin-collapsing/block-no-content-7-dyn.html new file mode 100644 index 00000000000..d150442695b --- /dev/null +++ b/layout/reftests/margin-collapsing/block-no-content-7-dyn.html @@ -0,0 +1,27 @@ + + + + + + + +
+
+
+ + diff --git a/layout/reftests/margin-collapsing/block-no-content-7-ref.html b/layout/reftests/margin-collapsing/block-no-content-7-ref.html new file mode 100644 index 00000000000..777047603b0 --- /dev/null +++ b/layout/reftests/margin-collapsing/block-no-content-7-ref.html @@ -0,0 +1,19 @@ + + + + + + +
+
+
+ + diff --git a/layout/reftests/margin-collapsing/block-no-content-7.html b/layout/reftests/margin-collapsing/block-no-content-7.html new file mode 100644 index 00000000000..4ededc1e29d --- /dev/null +++ b/layout/reftests/margin-collapsing/block-no-content-7.html @@ -0,0 +1,21 @@ + + + + + + +
+
+
+ + diff --git a/layout/reftests/margin-collapsing/block-no-content-8-dyn.html b/layout/reftests/margin-collapsing/block-no-content-8-dyn.html new file mode 100644 index 00000000000..8eea3bb005a --- /dev/null +++ b/layout/reftests/margin-collapsing/block-no-content-8-dyn.html @@ -0,0 +1,34 @@ + + + + + + + +
+
+
+
+
+ + diff --git a/layout/reftests/margin-collapsing/block-no-content-8-ref.html b/layout/reftests/margin-collapsing/block-no-content-8-ref.html new file mode 100644 index 00000000000..f2f666e9bfb --- /dev/null +++ b/layout/reftests/margin-collapsing/block-no-content-8-ref.html @@ -0,0 +1,30 @@ + + + + + + +
+
+
+
+
+
+
+ + diff --git a/layout/reftests/margin-collapsing/block-no-content-8.html b/layout/reftests/margin-collapsing/block-no-content-8.html new file mode 100644 index 00000000000..23d703e9c67 --- /dev/null +++ b/layout/reftests/margin-collapsing/block-no-content-8.html @@ -0,0 +1,28 @@ + + + + + + +
+
+
+
+
+ + diff --git a/layout/reftests/margin-collapsing/block-overflow-1-dyn.html b/layout/reftests/margin-collapsing/block-overflow-1-dyn.html new file mode 100644 index 00000000000..5981abdbb8d --- /dev/null +++ b/layout/reftests/margin-collapsing/block-overflow-1-dyn.html @@ -0,0 +1,35 @@ + + + + + + + +
+
+
+
+
+ + diff --git a/layout/reftests/margin-collapsing/block-overflow-2-dyn.html b/layout/reftests/margin-collapsing/block-overflow-2-dyn.html new file mode 100644 index 00000000000..7fee2a812ee --- /dev/null +++ b/layout/reftests/margin-collapsing/block-overflow-2-dyn.html @@ -0,0 +1,35 @@ + + + + + + + +
+
+
+
+
+ + diff --git a/layout/reftests/margin-collapsing/block-overflow-3-dyn.html b/layout/reftests/margin-collapsing/block-overflow-3-dyn.html new file mode 100644 index 00000000000..0f2b6468716 --- /dev/null +++ b/layout/reftests/margin-collapsing/block-overflow-3-dyn.html @@ -0,0 +1,36 @@ + + + + + + + +
+
+
+
+
+ + diff --git a/layout/reftests/margin-collapsing/block-overflow-4-dyn.html b/layout/reftests/margin-collapsing/block-overflow-4-dyn.html new file mode 100644 index 00000000000..e8d49258d1f --- /dev/null +++ b/layout/reftests/margin-collapsing/block-overflow-4-dyn.html @@ -0,0 +1,37 @@ + + + + + + + + +
+
+
+
+
+ + diff --git a/layout/reftests/margin-collapsing/block-overflow-5a-dyn.html b/layout/reftests/margin-collapsing/block-overflow-5a-dyn.html new file mode 100644 index 00000000000..8e0607619ea --- /dev/null +++ b/layout/reftests/margin-collapsing/block-overflow-5a-dyn.html @@ -0,0 +1,35 @@ + + + + + + + +
+
+
+ + diff --git a/layout/reftests/margin-collapsing/block-overflow-5b-dyn.html b/layout/reftests/margin-collapsing/block-overflow-5b-dyn.html new file mode 100644 index 00000000000..3c041d86885 --- /dev/null +++ b/layout/reftests/margin-collapsing/block-overflow-5b-dyn.html @@ -0,0 +1,35 @@ + + + + + + + +
+
+
+ + diff --git a/layout/reftests/margin-collapsing/block-overflow-5c-dyn.html b/layout/reftests/margin-collapsing/block-overflow-5c-dyn.html new file mode 100644 index 00000000000..731f2fa6003 --- /dev/null +++ b/layout/reftests/margin-collapsing/block-overflow-5c-dyn.html @@ -0,0 +1,34 @@ + + + + + + + +
+
+
+ + diff --git a/layout/reftests/margin-collapsing/block-overflow-5d-dyn.html b/layout/reftests/margin-collapsing/block-overflow-5d-dyn.html new file mode 100644 index 00000000000..cd5a969d426 --- /dev/null +++ b/layout/reftests/margin-collapsing/block-overflow-5d-dyn.html @@ -0,0 +1,35 @@ + + + + + + + +
+
+
+ + diff --git a/layout/reftests/margin-collapsing/block-percent-1-dyn.html b/layout/reftests/margin-collapsing/block-percent-1-dyn.html new file mode 100644 index 00000000000..780e95a7213 --- /dev/null +++ b/layout/reftests/margin-collapsing/block-percent-1-dyn.html @@ -0,0 +1,32 @@ + + + + + + + +
+
+
+
+ + diff --git a/layout/reftests/margin-collapsing/block-percent-1.html b/layout/reftests/margin-collapsing/block-percent-1.html index 1450efa3163..3344bd0b23a 100644 --- a/layout/reftests/margin-collapsing/block-percent-1.html +++ b/layout/reftests/margin-collapsing/block-percent-1.html @@ -3,7 +3,7 @@ + + + +
+
+
+
+
+
+ + diff --git a/layout/reftests/margin-collapsing/block-percent-2-ref.html b/layout/reftests/margin-collapsing/block-percent-2-ref.html new file mode 100644 index 00000000000..d9efe6bfb57 --- /dev/null +++ b/layout/reftests/margin-collapsing/block-percent-2-ref.html @@ -0,0 +1,33 @@ + + + + + + +
+
+
+
+
+
+
+ + diff --git a/layout/reftests/margin-collapsing/block-percent-2.html b/layout/reftests/margin-collapsing/block-percent-2.html new file mode 100644 index 00000000000..0137dc9b9f8 --- /dev/null +++ b/layout/reftests/margin-collapsing/block-percent-2.html @@ -0,0 +1,31 @@ + + + + + + +
+
+
+
+
+
+ + diff --git a/layout/reftests/margin-collapsing/caption-child-1-dyn.html b/layout/reftests/margin-collapsing/caption-child-1-dyn.html new file mode 100644 index 00000000000..1dfe6009076 --- /dev/null +++ b/layout/reftests/margin-collapsing/caption-child-1-dyn.html @@ -0,0 +1,40 @@ + + + + + + + +
+
+
+
+
+
+
+ + diff --git a/layout/reftests/margin-collapsing/caption-child-1-ref.html b/layout/reftests/margin-collapsing/caption-child-1-ref.html new file mode 100644 index 00000000000..5ebbe846536 --- /dev/null +++ b/layout/reftests/margin-collapsing/caption-child-1-ref.html @@ -0,0 +1,27 @@ + + + + + + +
+
+
+
+
+
+
+ + diff --git a/layout/reftests/margin-collapsing/caption-child-1.html b/layout/reftests/margin-collapsing/caption-child-1.html new file mode 100644 index 00000000000..e54ad40e42d --- /dev/null +++ b/layout/reftests/margin-collapsing/caption-child-1.html @@ -0,0 +1,33 @@ + + + + + + +
+
+
+
+
+
+
+ + diff --git a/layout/reftests/margin-collapsing/column-child-1-dyn.html b/layout/reftests/margin-collapsing/column-child-1-dyn.html new file mode 100644 index 00000000000..58781e91512 --- /dev/null +++ b/layout/reftests/margin-collapsing/column-child-1-dyn.html @@ -0,0 +1,32 @@ + + + + + + + +
+
+
+
+
+ + diff --git a/layout/reftests/margin-collapsing/column-child-1-ref.html b/layout/reftests/margin-collapsing/column-child-1-ref.html new file mode 100644 index 00000000000..7715129b64f --- /dev/null +++ b/layout/reftests/margin-collapsing/column-child-1-ref.html @@ -0,0 +1,26 @@ + + + + + + +
+
+
+
+
+
+
+ + diff --git a/layout/reftests/margin-collapsing/column-child-1.html b/layout/reftests/margin-collapsing/column-child-1.html new file mode 100644 index 00000000000..bc557f8059f --- /dev/null +++ b/layout/reftests/margin-collapsing/column-child-1.html @@ -0,0 +1,26 @@ + + + + + + +
+
+
+
+
+ + diff --git a/layout/reftests/margin-collapsing/column-sibling-1-ref.html b/layout/reftests/margin-collapsing/column-sibling-1-ref.html new file mode 100644 index 00000000000..1c7c66311f6 --- /dev/null +++ b/layout/reftests/margin-collapsing/column-sibling-1-ref.html @@ -0,0 +1,25 @@ + + + + + + +
+
+
+
+
+ + diff --git a/layout/reftests/margin-collapsing/column-sibling-1a-dyn.html b/layout/reftests/margin-collapsing/column-sibling-1a-dyn.html new file mode 100644 index 00000000000..c7a05c68ff2 --- /dev/null +++ b/layout/reftests/margin-collapsing/column-sibling-1a-dyn.html @@ -0,0 +1,37 @@ + + + + + + + +
+
+
+ + diff --git a/layout/reftests/margin-collapsing/column-sibling-1a.html b/layout/reftests/margin-collapsing/column-sibling-1a.html new file mode 100644 index 00000000000..2f2a1e84ee3 --- /dev/null +++ b/layout/reftests/margin-collapsing/column-sibling-1a.html @@ -0,0 +1,29 @@ + + + + + + +
+
+
+ + diff --git a/layout/reftests/margin-collapsing/column-sibling-1b-dyn.html b/layout/reftests/margin-collapsing/column-sibling-1b-dyn.html new file mode 100644 index 00000000000..26949a434ac --- /dev/null +++ b/layout/reftests/margin-collapsing/column-sibling-1b-dyn.html @@ -0,0 +1,37 @@ + + + + + + + +
+
+
+ + diff --git a/layout/reftests/margin-collapsing/column-sibling-1b.html b/layout/reftests/margin-collapsing/column-sibling-1b.html new file mode 100644 index 00000000000..1bf4dfed6a5 --- /dev/null +++ b/layout/reftests/margin-collapsing/column-sibling-1b.html @@ -0,0 +1,29 @@ + + + + + + +
+
+
+ + diff --git a/layout/reftests/margin-collapsing/column-sibling-1c-dyn.html b/layout/reftests/margin-collapsing/column-sibling-1c-dyn.html new file mode 100644 index 00000000000..9a0c9dc890d --- /dev/null +++ b/layout/reftests/margin-collapsing/column-sibling-1c-dyn.html @@ -0,0 +1,37 @@ + + + + + + + +
+
+
+ + diff --git a/layout/reftests/margin-collapsing/column-sibling-1c.html b/layout/reftests/margin-collapsing/column-sibling-1c.html new file mode 100644 index 00000000000..90446d65cf8 --- /dev/null +++ b/layout/reftests/margin-collapsing/column-sibling-1c.html @@ -0,0 +1,29 @@ + + + + + + +
+
+
+ + diff --git a/layout/reftests/margin-collapsing/column-sibling-2-ref.html b/layout/reftests/margin-collapsing/column-sibling-2-ref.html new file mode 100644 index 00000000000..3d160baaa35 --- /dev/null +++ b/layout/reftests/margin-collapsing/column-sibling-2-ref.html @@ -0,0 +1,21 @@ + + + + + + +
+
+
+
+
+ + diff --git a/layout/reftests/margin-collapsing/column-sibling-2a-dyn.html b/layout/reftests/margin-collapsing/column-sibling-2a-dyn.html new file mode 100644 index 00000000000..643f7b98f8b --- /dev/null +++ b/layout/reftests/margin-collapsing/column-sibling-2a-dyn.html @@ -0,0 +1,35 @@ + + + + + + + +
+
+
+ + diff --git a/layout/reftests/margin-collapsing/column-sibling-2a.html b/layout/reftests/margin-collapsing/column-sibling-2a.html new file mode 100644 index 00000000000..e4753529030 --- /dev/null +++ b/layout/reftests/margin-collapsing/column-sibling-2a.html @@ -0,0 +1,27 @@ + + + + + + +
+
+
+ + diff --git a/layout/reftests/margin-collapsing/column-sibling-2b-dyn.html b/layout/reftests/margin-collapsing/column-sibling-2b-dyn.html new file mode 100644 index 00000000000..85df871b49b --- /dev/null +++ b/layout/reftests/margin-collapsing/column-sibling-2b-dyn.html @@ -0,0 +1,35 @@ + + + + + + + +
+
+
+ + diff --git a/layout/reftests/margin-collapsing/column-sibling-2b.html b/layout/reftests/margin-collapsing/column-sibling-2b.html new file mode 100644 index 00000000000..484674559b6 --- /dev/null +++ b/layout/reftests/margin-collapsing/column-sibling-2b.html @@ -0,0 +1,27 @@ + + + + + + +
+
+
+ + diff --git a/layout/reftests/margin-collapsing/column-sibling-2c-dyn.html b/layout/reftests/margin-collapsing/column-sibling-2c-dyn.html new file mode 100644 index 00000000000..d9e89ec5e53 --- /dev/null +++ b/layout/reftests/margin-collapsing/column-sibling-2c-dyn.html @@ -0,0 +1,35 @@ + + + + + + + +
+
+
+ + diff --git a/layout/reftests/margin-collapsing/column-sibling-2c.html b/layout/reftests/margin-collapsing/column-sibling-2c.html new file mode 100644 index 00000000000..9adff98160d --- /dev/null +++ b/layout/reftests/margin-collapsing/column-sibling-2c.html @@ -0,0 +1,27 @@ + + + + + + +
+
+
+ + diff --git a/layout/reftests/margin-collapsing/fieldset-child-1-dyn.html b/layout/reftests/margin-collapsing/fieldset-child-1-dyn.html new file mode 100644 index 00000000000..295432e5c35 --- /dev/null +++ b/layout/reftests/margin-collapsing/fieldset-child-1-dyn.html @@ -0,0 +1,35 @@ + + + + + + + +
+
+
+
+
+ + diff --git a/layout/reftests/margin-collapsing/fieldset-sibling-1a-dyn.html b/layout/reftests/margin-collapsing/fieldset-sibling-1a-dyn.html new file mode 100644 index 00000000000..c99607db615 --- /dev/null +++ b/layout/reftests/margin-collapsing/fieldset-sibling-1a-dyn.html @@ -0,0 +1,36 @@ + + + + + + + +
+
+
+ + diff --git a/layout/reftests/margin-collapsing/fieldset-sibling-1b-dyn.html b/layout/reftests/margin-collapsing/fieldset-sibling-1b-dyn.html new file mode 100644 index 00000000000..a7d1e40a3c3 --- /dev/null +++ b/layout/reftests/margin-collapsing/fieldset-sibling-1b-dyn.html @@ -0,0 +1,36 @@ + + + + + + + +
+
+
+ + diff --git a/layout/reftests/margin-collapsing/fieldset-sibling-1c-dyn.html b/layout/reftests/margin-collapsing/fieldset-sibling-1c-dyn.html new file mode 100644 index 00000000000..91e97ced1f5 --- /dev/null +++ b/layout/reftests/margin-collapsing/fieldset-sibling-1c-dyn.html @@ -0,0 +1,36 @@ + + + + + + + +
+
+
+ + diff --git a/layout/reftests/margin-collapsing/fieldset-sibling-1c.html b/layout/reftests/margin-collapsing/fieldset-sibling-1c.html index 14eb77ad72d..e525761d498 100644 --- a/layout/reftests/margin-collapsing/fieldset-sibling-1c.html +++ b/layout/reftests/margin-collapsing/fieldset-sibling-1c.html @@ -4,7 +4,7 @@ + + + +
+
+
+ + diff --git a/layout/reftests/margin-collapsing/fieldset-sibling-2b-dyn.html b/layout/reftests/margin-collapsing/fieldset-sibling-2b-dyn.html new file mode 100644 index 00000000000..8b8a2eac343 --- /dev/null +++ b/layout/reftests/margin-collapsing/fieldset-sibling-2b-dyn.html @@ -0,0 +1,34 @@ + + + + + + + +
+
+
+ + diff --git a/layout/reftests/margin-collapsing/fieldset-sibling-2c-dyn.html b/layout/reftests/margin-collapsing/fieldset-sibling-2c-dyn.html new file mode 100644 index 00000000000..76f3827c4fd --- /dev/null +++ b/layout/reftests/margin-collapsing/fieldset-sibling-2c-dyn.html @@ -0,0 +1,34 @@ + + + + + + + +
+
+
+ + diff --git a/layout/reftests/margin-collapsing/inline-block-child-1-dyn.html b/layout/reftests/margin-collapsing/inline-block-child-1-dyn.html new file mode 100644 index 00000000000..6376b99d80d --- /dev/null +++ b/layout/reftests/margin-collapsing/inline-block-child-1-dyn.html @@ -0,0 +1,30 @@ + + + + + + + +
+
+
+ + diff --git a/layout/reftests/margin-collapsing/inline-block-child-2-dyn.html b/layout/reftests/margin-collapsing/inline-block-child-2-dyn.html new file mode 100644 index 00000000000..3ffee5dc0ca --- /dev/null +++ b/layout/reftests/margin-collapsing/inline-block-child-2-dyn.html @@ -0,0 +1,26 @@ + + + + + + + +
Hello Kitty
+ + diff --git a/layout/reftests/margin-collapsing/inline-block-child-3-dyn.html b/layout/reftests/margin-collapsing/inline-block-child-3-dyn.html new file mode 100644 index 00000000000..98f56d360f8 --- /dev/null +++ b/layout/reftests/margin-collapsing/inline-block-child-3-dyn.html @@ -0,0 +1,29 @@ + + + + + + + +
Hello Kitty
+ + diff --git a/layout/reftests/margin-collapsing/inline-block-child-3-ref.html b/layout/reftests/margin-collapsing/inline-block-child-3-ref.html new file mode 100644 index 00000000000..6ca83dd06eb --- /dev/null +++ b/layout/reftests/margin-collapsing/inline-block-child-3-ref.html @@ -0,0 +1,22 @@ + + + + + + +
Hello Kitty
+ + diff --git a/layout/reftests/margin-collapsing/inline-block-child-3.html b/layout/reftests/margin-collapsing/inline-block-child-3.html new file mode 100644 index 00000000000..e0bd8ae1db4 --- /dev/null +++ b/layout/reftests/margin-collapsing/inline-block-child-3.html @@ -0,0 +1,22 @@ + + + + + + +
Hello Kitty
+ + diff --git a/layout/reftests/margin-collapsing/inline-block-sibling-1a-dyn.html b/layout/reftests/margin-collapsing/inline-block-sibling-1a-dyn.html new file mode 100644 index 00000000000..a3224b8e732 --- /dev/null +++ b/layout/reftests/margin-collapsing/inline-block-sibling-1a-dyn.html @@ -0,0 +1,36 @@ + + + + + + + +
+
+
+
+ + diff --git a/layout/reftests/margin-collapsing/inline-block-sibling-1b-dyn.html b/layout/reftests/margin-collapsing/inline-block-sibling-1b-dyn.html new file mode 100644 index 00000000000..14d656756e8 --- /dev/null +++ b/layout/reftests/margin-collapsing/inline-block-sibling-1b-dyn.html @@ -0,0 +1,36 @@ + + + + + + + +
+
+
+
+ + diff --git a/layout/reftests/margin-collapsing/inline-block-sibling-1c-dyn.html b/layout/reftests/margin-collapsing/inline-block-sibling-1c-dyn.html new file mode 100644 index 00000000000..be14f2870a6 --- /dev/null +++ b/layout/reftests/margin-collapsing/inline-block-sibling-1c-dyn.html @@ -0,0 +1,36 @@ + + + + + + + +
+
+
+
+ + diff --git a/layout/reftests/margin-collapsing/inline-block-sibling-2-dyn.html b/layout/reftests/margin-collapsing/inline-block-sibling-2-dyn.html new file mode 100644 index 00000000000..be0847ac031 --- /dev/null +++ b/layout/reftests/margin-collapsing/inline-block-sibling-2-dyn.html @@ -0,0 +1,38 @@ + + + + + + + +
+
+
+
+ + diff --git a/layout/reftests/margin-collapsing/reftest.list b/layout/reftests/margin-collapsing/reftest.list index 42ed7068987..6edc5dcdf32 100644 --- a/layout/reftests/margin-collapsing/reftest.list +++ b/layout/reftests/margin-collapsing/reftest.list @@ -514,12 +514,47 @@ fails == block-max-height-last-child-9a-dyn.html block-max-height-last-child-9-r == block-no-content-1a.html block-no-content-1-ref.html == block-no-content-1b.html block-no-content-1-ref.html == block-no-content-1c.html block-no-content-1-ref.html +== block-no-content-1d.html block-no-content-1-ref.html == block-no-content-2a.html block-no-content-2-ref.html == block-no-content-2b.html block-no-content-2-ref.html == block-no-content-2c.html block-no-content-2-ref.html == block-no-content-2d.html block-no-content-2-ref.html -== block-no-content-3.html block-no-content-3-ref.html -== block-no-content-4.html block-no-content-4-ref.html +== block-no-content-2e.html block-no-content-2-ref.html +== block-no-content-3a.html block-no-content-3-ref.html +== block-no-content-3b.html block-no-content-3-ref.html +== block-no-content-3c.html block-no-content-3-ref.html +== block-no-content-4a.html block-no-content-4-ref.html +== block-no-content-4b.html block-no-content-4-ref.html +== block-no-content-4c.html block-no-content-4-ref.html +== block-no-content-5a.html block-no-content-5-ref.html +== block-no-content-5b.html block-no-content-5-ref.html +== block-no-content-6.html block-no-content-6-ref.html +== block-no-content-7.html block-no-content-7-ref.html +# "If the top margin of a box with non-zero computed 'min-height' and 'auto' +# computed 'height' collapses with the bottom margin of its last in-flow +# child, then the child's bottom margin does not collapse with the parent's +# bottom margin." +== block-no-content-8.html block-no-content-8-ref.html +== block-no-content-1a-dyn.html block-no-content-1-ref.html +== block-no-content-1b-dyn.html block-no-content-1-ref.html +== block-no-content-1c-dyn.html block-no-content-1-ref.html +== block-no-content-1d-dyn.html block-no-content-1-ref.html +== block-no-content-2a-dyn.html block-no-content-2-ref.html +== block-no-content-2b-dyn.html block-no-content-2-ref.html +== block-no-content-2c-dyn.html block-no-content-2-ref.html +== block-no-content-2d-dyn.html block-no-content-2-ref.html +== block-no-content-2e-dyn.html block-no-content-2-ref.html +== block-no-content-3a-dyn.html block-no-content-3-ref.html +== block-no-content-3b-dyn.html block-no-content-3-ref.html +== block-no-content-3c-dyn.html block-no-content-3-ref.html +== block-no-content-4a-dyn.html block-no-content-4-ref.html +== block-no-content-4b-dyn.html block-no-content-4-ref.html +== block-no-content-4c-dyn.html block-no-content-4-ref.html +== block-no-content-5a-dyn.html block-no-content-5-ref.html +== block-no-content-5b-dyn.html block-no-content-5-ref.html +== block-no-content-6-dyn.html block-no-content-6-ref.html +== block-no-content-7-dyn.html block-no-content-7-ref.html +== block-no-content-8-dyn.html block-no-content-8-ref.html # These tests are similar to the no-content ones, except that some boxes # have height: 0; declared on them. == block-zero-height-1a.html block-zero-height-1a-ref.html @@ -552,6 +587,14 @@ skip-if(B2G) == block-overflow-4.html block-overflow-4-ref2.html == block-overflow-5c.html block-overflow-5c-ref2.html == block-overflow-5d.html block-overflow-5-ref.html == block-overflow-5d.html block-overflow-5-ref2.html +== block-overflow-1-dyn.html block-overflow-1-ref2.html +== block-overflow-2-dyn.html block-overflow-2-ref2.html +skip-if(B2G) == block-overflow-3-dyn.html block-overflow-3-ref2.html # bug 773482 +skip-if(B2G) == block-overflow-4-dyn.html block-overflow-4-ref2.html +== block-overflow-5a-dyn.html block-overflow-5-ref2.html +== block-overflow-5b-dyn.html block-overflow-5-ref2.html +== block-overflow-5c-dyn.html block-overflow-5c-ref2.html +== block-overflow-5d-dyn.html block-overflow-5-ref2.html # * 'fieldset' elements, per HTML5 (Candidate Recommendation 6 August 2013): # §10.3.13 (The fieldset and legend elements): "The fieldset element is # expected to establish a new block formatting context." @@ -564,7 +607,14 @@ skip-if(B2G) == block-overflow-4.html block-overflow-4-ref2.html == fieldset-sibling-2a.html fieldset-sibling-2-ref2.html == fieldset-sibling-2b.html fieldset-sibling-2-ref2.html == fieldset-sibling-2c.html fieldset-sibling-2-ref2.html +== fieldset-sibling-1a-dyn.html fieldset-sibling-1-ref.html +== fieldset-sibling-1b-dyn.html fieldset-sibling-1-ref.html +== fieldset-sibling-1c-dyn.html fieldset-sibling-1-ref.html +== fieldset-sibling-2a-dyn.html fieldset-sibling-2-ref2.html +== fieldset-sibling-2b-dyn.html fieldset-sibling-2-ref2.html +== fieldset-sibling-2c-dyn.html fieldset-sibling-2-ref2.html == fieldset-child-1.html fieldset-child-1-ref.html +== fieldset-child-1-dyn.html fieldset-child-1-ref.html # * Tables, per CSS 2.1 §17.4 (Tables in the visual formatting model): # "The table wrapper box establishes a block formatting context." # "The table wrapper box is a 'block' box if the table is block-level [...]" @@ -602,13 +652,37 @@ skip-if(B2G) == table-sibling-3-dyn.html table-sibling-3-ref.html # bug 773482 # table-captions, though, if they share the same caption-side. == table-caption-1a.html table-caption-1-ref.html == table-caption-1b.html table-caption-1-ref.html +== table-caption-1c.html table-caption-1-ref.html == table-caption-2a.html table-caption-2-ref.html == table-caption-2b.html table-caption-2-ref.html == table-caption-2c.html table-caption-2-ref.html +== table-caption-1a-dyn.html table-caption-1-ref.html +== table-caption-1b-dyn.html table-caption-1-ref.html +== table-caption-1c-dyn.html table-caption-1-ref.html +== table-caption-2a-dyn.html table-caption-2-ref.html +== table-caption-2b-dyn.html table-caption-2-ref.html +== table-caption-2c-dyn.html table-caption-2-ref.html +# Note: CSS 2.1 suggests that the 'caption-side' values 'top-outside' and +# 'bottom-outside' will be used in a future CSS Module to restore the +# CSS 2 definition of 'top' and 'bottom' (which is different from CSS 2.1's). +# Since Bug #659828 was fixed, 'top-outside' and 'bottom-outside' act as an +# alias for the CSS 2.1 values 'top' and 'bottom' respectively. == table-caption-top-1.html table-caption-top-1-ref.html == table-caption-top-2.html table-caption-top-2-ref.html +== table-caption-top-outside-1.html table-caption-top-1-ref.html +== table-caption-top-outside-2.html table-caption-top-1-ref.html == table-caption-bottom-1.html table-caption-bottom-1-ref.html == table-caption-bottom-2.html table-caption-bottom-2-ref.html +== table-caption-bottom-outside-1.html table-caption-bottom-1-ref.html +== table-caption-bottom-outside-2.html table-caption-bottom-1-ref.html +== table-caption-top-1-dyn.html table-caption-top-1-ref.html +== table-caption-top-2-dyn.html table-caption-top-1-ref.html +== table-caption-top-outside-1-dyn.html table-caption-top-1-ref.html +== table-caption-top-outside-2-dyn.html table-caption-top-2-ref.html +== table-caption-bottom-1-dyn.html table-caption-bottom-1-ref.html +== table-caption-bottom-2-dyn.html table-caption-bottom-1-ref.html +== table-caption-bottom-outside-1-dyn.html table-caption-bottom-1-ref.html +== table-caption-bottom-outside-2-dyn.html table-caption-bottom-1-ref.html fails == caption-sibling-1a.html caption-sibling-1-ref.html # Bug 144517 != caption-sibling-1a.html caption-sibling-1-noref.html fails == caption-sibling-1b.html caption-sibling-1-ref.html # Bug 144517 @@ -623,6 +697,25 @@ fails == caption-sibling-1c-dyn.html caption-sibling-1-ref.html # Bug 144517 != caption-sibling-1c-dyn.html caption-sibling-1-noref2.html fails == caption-sibling-2-dyn.html caption-sibling-2-ref.html # Bug 144517 != caption-sibling-2-dyn.html caption-sibling-2-noref.html +== caption-child-1.html caption-child-1-ref.html +== caption-child-1-dyn.html caption-child-1-ref.html +# * Multi-column elements, per CSS Multi-column Layout Module +# (Candidate Recommendation 12 April 2011): +# "A multi-column element establishes a new block formatting context [...]" +== column-sibling-1a.html column-sibling-1-ref.html +== column-sibling-1b.html column-sibling-1-ref.html +== column-sibling-1c.html column-sibling-1-ref.html +== column-sibling-1a-dyn.html column-sibling-1-ref.html +== column-sibling-1b-dyn.html column-sibling-1-ref.html +== column-sibling-1c-dyn.html column-sibling-1-ref.html +== column-sibling-2a.html column-sibling-2-ref.html +== column-sibling-2b.html column-sibling-2-ref.html +== column-sibling-2c.html column-sibling-2-ref.html +== column-sibling-2a-dyn.html column-sibling-2-ref.html +== column-sibling-2b-dyn.html column-sibling-2-ref.html +== column-sibling-2c-dyn.html column-sibling-2-ref.html +== column-child-1.html column-child-1-ref.html +== column-child-1-dyn.html column-child-1-ref.html # * inline-block boxes # "Margins of inline-block boxes do not collapse # (not even with their in-flow children)." @@ -631,15 +724,25 @@ fails == caption-sibling-2-dyn.html caption-sibling-2-ref.html # Bug 144517 == inline-block-sibling-1c.html inline-block-sibling-1-ref.html == inline-block-sibling-2.html inline-block-sibling-2-ref.html != inline-block-sibling-2.html inline-block-sibling-2-noref.html +== inline-block-sibling-1a-dyn.html inline-block-sibling-1-ref.html +== inline-block-sibling-1b-dyn.html inline-block-sibling-1-ref.html +== inline-block-sibling-1c-dyn.html inline-block-sibling-1-ref.html +== inline-block-sibling-2-dyn.html inline-block-sibling-2-ref.html == inline-block-child-1.html inline-block-child-1-ref.html == inline-block-child-2.html inline-block-child-2-ref.html != inline-block-child-2.html inline-block-child-2-noref.html +== inline-block-child-3.html inline-block-child-3-ref.html +== inline-block-child-1-dyn.html inline-block-child-1-ref.html +== inline-block-child-2-dyn.html inline-block-child-2-ref.html +== inline-block-child-3-dyn.html inline-block-child-3-ref.html # * absolutely positioned elements # "Margins of absolutely positioned boxes do not collapse # (not even with their in-flow children)." == block-abs-pos-1.html block-abs-pos-1-ref.html == block-abs-pos-2.html block-abs-pos-2-ref.html == block-abs-pos-2.html block-abs-pos-2-ref2.html +== block-abs-pos-1-dyn.html block-abs-pos-1-ref.html +== block-abs-pos-2-dyn.html block-abs-pos-2-ref2.html # * Floats # "Margins between a floated box and any other box do not collapse # (not even between a float and its in-flow children)." @@ -653,6 +756,14 @@ fails == caption-sibling-2-dyn.html caption-sibling-2-ref.html # Bug 144517 != block-float-2a.html block-float-2a-noref.html == block-float-2b.html block-float-2b-ref.html != block-float-2b.html block-float-2b-noref.html +== block-float-3a.html block-float-3a-ref.html +== block-float-3b.html block-float-3b-ref.html +== block-float-1a-dyn.html block-float-1a-ref.html +== block-float-1b-dyn.html block-float-1b-ref.html +== block-float-2a-dyn.html block-float-2a-ref.html +== block-float-2b-dyn.html block-float-2b-ref.html +== block-float-3a-dyn.html block-float-3a-ref.html +== block-float-3b-dyn.html block-float-3b-ref.html # Tests for various cases where clearance is applied and collapsing is # prevented or only allows for certain margins. fails == block-clear-1a.html block-clear-1a-ref.html # Bug 451791 @@ -740,8 +851,14 @@ fails == block-clear-7g-left.html block-clear-7efgh-left-ref2.html # Bug 493380 == block-html-body-1.html block-html-body-1-ref.html == block-html-body-1.html block-html-body-1-ref2.html != block-html-body-1.html block-html-body-1-noref.html -# Other tests. +# Some basic tests for margins given in percent and em. == block-percent-1.html block-percent-1-ref.html +== block-percent-1-dyn.html block-percent-1-ref.html +== block-percent-2.html block-percent-2-ref.html +== block-percent-2-dyn.html block-percent-2-ref.html +== block-em-length-1.html block-em-length-1-ref.html +== block-em-length-1-dyn.html block-em-length-1-ref.html +# Other tests. == dynamic-add-text-1.html dynamic-add-text-1-ref.html # Bug 467321 == scrollable-vertical-margin.html scrollable-vertical-margin-ref.html == scrollable-horizontal-margin.html scrollable-horizontal-margin-ref.html diff --git a/layout/reftests/margin-collapsing/table-caption-1a-dyn.html b/layout/reftests/margin-collapsing/table-caption-1a-dyn.html new file mode 100644 index 00000000000..d70070d14cb --- /dev/null +++ b/layout/reftests/margin-collapsing/table-caption-1a-dyn.html @@ -0,0 +1,41 @@ + + + + + + + +
+
+
+
+
+ + diff --git a/layout/reftests/margin-collapsing/table-caption-1b-dyn.html b/layout/reftests/margin-collapsing/table-caption-1b-dyn.html new file mode 100644 index 00000000000..8dc7c29211f --- /dev/null +++ b/layout/reftests/margin-collapsing/table-caption-1b-dyn.html @@ -0,0 +1,41 @@ + + + + + + + +
+
+
+
+
+ + diff --git a/layout/reftests/margin-collapsing/table-caption-1c-dyn.html b/layout/reftests/margin-collapsing/table-caption-1c-dyn.html new file mode 100644 index 00000000000..4e386b5f661 --- /dev/null +++ b/layout/reftests/margin-collapsing/table-caption-1c-dyn.html @@ -0,0 +1,41 @@ + + + + + + + +
+
+
+
+
+ + diff --git a/layout/reftests/margin-collapsing/table-caption-1c.html b/layout/reftests/margin-collapsing/table-caption-1c.html new file mode 100644 index 00000000000..b7956a130b6 --- /dev/null +++ b/layout/reftests/margin-collapsing/table-caption-1c.html @@ -0,0 +1,34 @@ + + + + + + +
+
+
+
+
+ + diff --git a/layout/reftests/margin-collapsing/table-caption-2a-dyn.html b/layout/reftests/margin-collapsing/table-caption-2a-dyn.html new file mode 100644 index 00000000000..d9943ca7201 --- /dev/null +++ b/layout/reftests/margin-collapsing/table-caption-2a-dyn.html @@ -0,0 +1,36 @@ + + + + + + + +
+
+
+
+
+ + diff --git a/layout/reftests/margin-collapsing/table-caption-2b-dyn.html b/layout/reftests/margin-collapsing/table-caption-2b-dyn.html new file mode 100644 index 00000000000..90f55e03240 --- /dev/null +++ b/layout/reftests/margin-collapsing/table-caption-2b-dyn.html @@ -0,0 +1,36 @@ + + + + + + + +
+
+
+
+
+ + diff --git a/layout/reftests/margin-collapsing/table-caption-2c-dyn.html b/layout/reftests/margin-collapsing/table-caption-2c-dyn.html new file mode 100644 index 00000000000..6d79c3cd300 --- /dev/null +++ b/layout/reftests/margin-collapsing/table-caption-2c-dyn.html @@ -0,0 +1,36 @@ + + + + + + + +
+
+
+
+
+ + diff --git a/layout/reftests/margin-collapsing/table-caption-bottom-1-dyn.html b/layout/reftests/margin-collapsing/table-caption-bottom-1-dyn.html new file mode 100644 index 00000000000..dd456eb4702 --- /dev/null +++ b/layout/reftests/margin-collapsing/table-caption-bottom-1-dyn.html @@ -0,0 +1,48 @@ + + + + + + + +
+
+
+
+
+
+ + diff --git a/layout/reftests/margin-collapsing/table-caption-bottom-2-dyn.html b/layout/reftests/margin-collapsing/table-caption-bottom-2-dyn.html new file mode 100644 index 00000000000..7363e73cd9c --- /dev/null +++ b/layout/reftests/margin-collapsing/table-caption-bottom-2-dyn.html @@ -0,0 +1,43 @@ + + + + + + + +
+
+
+
+
+
+ + diff --git a/layout/reftests/margin-collapsing/table-caption-bottom-outside-1-dyn.html b/layout/reftests/margin-collapsing/table-caption-bottom-outside-1-dyn.html new file mode 100644 index 00000000000..c31a8e6ef9c --- /dev/null +++ b/layout/reftests/margin-collapsing/table-caption-bottom-outside-1-dyn.html @@ -0,0 +1,48 @@ + + + + + + + +
+
+
+
+
+
+ + diff --git a/layout/reftests/margin-collapsing/table-caption-bottom-outside-1.html b/layout/reftests/margin-collapsing/table-caption-bottom-outside-1.html new file mode 100644 index 00000000000..5a4c9c7c827 --- /dev/null +++ b/layout/reftests/margin-collapsing/table-caption-bottom-outside-1.html @@ -0,0 +1,41 @@ + + + + + + +
+
+
+
+
+
+ + diff --git a/layout/reftests/margin-collapsing/table-caption-bottom-outside-2-dyn.html b/layout/reftests/margin-collapsing/table-caption-bottom-outside-2-dyn.html new file mode 100644 index 00000000000..c1d6595afc7 --- /dev/null +++ b/layout/reftests/margin-collapsing/table-caption-bottom-outside-2-dyn.html @@ -0,0 +1,43 @@ + + + + + + + +
+
+
+
+
+
+ + diff --git a/layout/reftests/margin-collapsing/table-caption-bottom-outside-2.html b/layout/reftests/margin-collapsing/table-caption-bottom-outside-2.html new file mode 100644 index 00000000000..c730424e77b --- /dev/null +++ b/layout/reftests/margin-collapsing/table-caption-bottom-outside-2.html @@ -0,0 +1,36 @@ + + + + + + +
+
+
+
+
+
+ + diff --git a/layout/reftests/margin-collapsing/table-caption-top-1-dyn.html b/layout/reftests/margin-collapsing/table-caption-top-1-dyn.html new file mode 100644 index 00000000000..8e456adebc9 --- /dev/null +++ b/layout/reftests/margin-collapsing/table-caption-top-1-dyn.html @@ -0,0 +1,48 @@ + + + + + + + +
+
+
+
+
+
+ + diff --git a/layout/reftests/margin-collapsing/table-caption-top-2-dyn.html b/layout/reftests/margin-collapsing/table-caption-top-2-dyn.html new file mode 100644 index 00000000000..01dd40ad85a --- /dev/null +++ b/layout/reftests/margin-collapsing/table-caption-top-2-dyn.html @@ -0,0 +1,43 @@ + + + + + + + +
+
+
+
+
+
+ + diff --git a/layout/reftests/margin-collapsing/table-caption-top-outside-1-dyn.html b/layout/reftests/margin-collapsing/table-caption-top-outside-1-dyn.html new file mode 100644 index 00000000000..3767070f97c --- /dev/null +++ b/layout/reftests/margin-collapsing/table-caption-top-outside-1-dyn.html @@ -0,0 +1,48 @@ + + + + + + + +
+
+
+
+
+
+ + diff --git a/layout/reftests/margin-collapsing/table-caption-top-outside-1.html b/layout/reftests/margin-collapsing/table-caption-top-outside-1.html new file mode 100644 index 00000000000..f159d429724 --- /dev/null +++ b/layout/reftests/margin-collapsing/table-caption-top-outside-1.html @@ -0,0 +1,41 @@ + + + + + + +
+
+
+
+
+
+ + diff --git a/layout/reftests/margin-collapsing/table-caption-top-outside-2-dyn.html b/layout/reftests/margin-collapsing/table-caption-top-outside-2-dyn.html new file mode 100644 index 00000000000..f01fa94f88d --- /dev/null +++ b/layout/reftests/margin-collapsing/table-caption-top-outside-2-dyn.html @@ -0,0 +1,43 @@ + + + + + + + +
+
+
+
+
+
+ + diff --git a/layout/reftests/margin-collapsing/table-caption-top-outside-2.html b/layout/reftests/margin-collapsing/table-caption-top-outside-2.html new file mode 100644 index 00000000000..d5516f8c7e1 --- /dev/null +++ b/layout/reftests/margin-collapsing/table-caption-top-outside-2.html @@ -0,0 +1,36 @@ + + + + + + +
+
+
+
+
+
+ + From d26caa0d749f0a68bbba8c9da412cb1b0a725c4c Mon Sep 17 00:00:00 2001 From: Masayuki Nakano Date: Wed, 5 Mar 2014 09:37:43 +0900 Subject: [PATCH 046/112] Bug 975688 part.28 Rename nsDOMEvent to mozilla::dom::Event r=smaug --HG-- rename : dom/events/nsDOMEvent.cpp => dom/events/Event.cpp rename : dom/events/nsDOMEvent.h => dom/events/Event.h --- accessible/src/base/DocManager.cpp | 2 +- accessible/src/generic/RootAccessible.cpp | 6 +- content/base/public/nsIDocument.h | 6 +- content/base/src/nsDocument.cpp | 4 +- content/base/src/nsINode.cpp | 8 +- content/base/src/nsObjectLoadingContent.cpp | 6 +- content/html/content/src/UndoManager.cpp | 4 +- content/html/document/src/nsHTMLDocument.h | 1 - .../media/webaudio/AudioProcessingEvent.cpp | 10 +- content/media/webaudio/AudioProcessingEvent.h | 8 +- .../webaudio/OfflineAudioCompletionEvent.cpp | 10 +- .../webaudio/OfflineAudioCompletionEvent.h | 8 +- content/xul/content/src/nsXULElement.cpp | 4 +- .../xul/content/src/nsXULPopupListener.cpp | 2 +- dom/base/MessagePort.cpp | 4 +- dom/base/Navigator.cpp | 2 +- dom/base/nsDOMClassInfoID.h | 9 +- dom/base/nsGlobalWindow.cpp | 6 +- dom/base/nsGlobalWindow.h | 2 +- dom/base/nsScreen.cpp | 4 +- dom/battery/BatteryManager.cpp | 1 - dom/bindings/Bindings.conf | 1 - dom/bindings/Codegen.py | 2 +- dom/devicestorage/nsDeviceStorage.cpp | 1 - dom/events/AnimationEvent.cpp | 10 +- dom/events/AnimationEvent.h | 8 +- dom/events/BeforeUnloadEvent.cpp | 6 +- dom/events/BeforeUnloadEvent.h | 12 +- dom/events/ClipboardEvent.cpp | 12 +- dom/events/ClipboardEvent.h | 8 +- dom/events/CommandEvent.cpp | 13 +- dom/events/CommandEvent.h | 10 +- dom/events/DataContainerEvent.cpp | 13 +- dom/events/DataContainerEvent.h | 12 +- dom/events/DeviceMotionEvent.cpp | 10 +- dom/events/DeviceMotionEvent.h | 12 +- dom/events/{nsDOMEvent.cpp => Event.cpp} | 281 ++++++++++-------- dom/events/{nsDOMEvent.h => Event.h} | 113 +++---- dom/events/EventTarget.h | 4 +- dom/events/MessageEvent.cpp | 19 +- dom/events/MessageEvent.h | 11 +- dom/events/MouseEvent.cpp | 20 +- dom/events/MutationEvent.cpp | 12 +- dom/events/MutationEvent.h | 10 +- dom/events/NotifyAudioAvailableEvent.cpp | 16 +- dom/events/NotifyAudioAvailableEvent.h | 12 +- dom/events/NotifyPaintEvent.cpp | 14 +- dom/events/NotifyPaintEvent.h | 12 +- dom/events/ScrollAreaEvent.cpp | 4 +- dom/events/ScrollAreaEvent.h | 4 +- dom/events/SpeechRecognitionError.cpp | 9 +- dom/events/SpeechRecognitionError.h | 4 +- dom/events/Touch.cpp | 6 +- dom/events/TransitionEvent.cpp | 10 +- dom/events/TransitionEvent.h | 8 +- dom/events/UIEvent.cpp | 50 ++-- dom/events/UIEvent.h | 18 +- dom/events/XULCommandEvent.h | 6 +- dom/events/moz.build | 4 +- dom/events/nsAsyncDOMEvent.cpp | 2 +- dom/events/nsEventDispatcher.cpp | 2 +- dom/events/nsEventListenerManager.cpp | 6 +- dom/events/nsEventStateManager.cpp | 4 +- dom/events/nsEventStateManager.h | 4 +- dom/events/nsJSEventListener.cpp | 1 - dom/file/LockedFile.cpp | 2 +- dom/indexedDB/AsyncConnectionHelper.h | 2 - dom/indexedDB/IDBEvents.cpp | 8 +- dom/indexedDB/IDBEvents.h | 14 +- dom/indexedDB/OpenDatabaseHelper.cpp | 4 +- dom/indexedDB/ipc/IndexedDBChild.cpp | 2 +- dom/interfaces/events/nsIDOMEvent.idl | 6 +- dom/mobileconnection/src/MobileConnection.cpp | 1 - dom/network/src/Connection.cpp | 1 - dom/power/WakeLock.cpp | 2 +- dom/smil/TimeEvent.cpp | 18 +- dom/smil/TimeEvent.h | 10 +- dom/speakermanager/SpeakerManager.cpp | 2 +- dom/src/notification/Notification.cpp | 1 - dom/src/offline/nsDOMOfflineResourceList.cpp | 1 + dom/src/offline/nsDOMOfflineResourceList.h | 1 - dom/telephony/CallEvent.cpp | 10 +- dom/telephony/CallEvent.h | 11 +- dom/time/TimeChangeObserver.cpp | 1 - dom/voicemail/Voicemail.h | 1 - dom/workers/MessagePort.cpp | 2 +- dom/workers/SharedWorker.cpp | 2 +- dom/xbl/nsXBLEventHandler.cpp | 2 +- dom/xbl/nsXBLService.cpp | 8 +- .../webBrowser/nsDocShellTreeOwner.cpp | 2 +- .../src/nsAutoWindowStateHelper.cpp | 4 +- js/xpconnect/src/event_impl_gen.py | 13 +- js/xpconnect/src/nsDOMQS.h | 4 +- layout/base/nsPresShell.cpp | 5 +- layout/generic/nsImageMap.cpp | 4 +- layout/printing/nsPrintPreviewListener.cpp | 2 +- layout/xul/nsXULPopupManager.cpp | 2 +- layout/xul/nsXULTooltipListener.cpp | 2 +- .../satchel/nsFormFillController.cpp | 4 +- widget/BasicEvents.h | 10 +- widget/cocoa/nsMenuUtilsX.mm | 4 +- xpfe/appshell/src/nsXULWindow.cpp | 5 +- 102 files changed, 531 insertions(+), 545 deletions(-) rename dom/events/{nsDOMEvent.cpp => Event.cpp} (81%) rename dom/events/{nsDOMEvent.h => Event.h} (70%) diff --git a/accessible/src/base/DocManager.cpp b/accessible/src/base/DocManager.cpp index 91ebd3f564d..7a2db75fd95 100644 --- a/accessible/src/base/DocManager.cpp +++ b/accessible/src/base/DocManager.cpp @@ -15,9 +15,9 @@ #include "Logging.h" #endif +#include "mozilla/dom/Event.h" // for nsIDOMEvent::InternalDOMEvent() #include "nsCURILoader.h" #include "nsDocShellLoadTypes.h" -#include "nsDOMEvent.h" #include "nsIChannel.h" #include "nsIDOMDocument.h" #include "nsEventListenerManager.h" diff --git a/accessible/src/generic/RootAccessible.cpp b/accessible/src/generic/RootAccessible.cpp index 82ffbdf4e4a..d7e77522582 100644 --- a/accessible/src/generic/RootAccessible.cpp +++ b/accessible/src/generic/RootAccessible.cpp @@ -28,6 +28,7 @@ #include "nsIAccessibleRelation.h" #include "nsIDocShellTreeItem.h" #include "nsIDocShellTreeOwner.h" +#include "mozilla/dom/Event.h" #include "mozilla/dom/EventTarget.h" #include "nsIDOMDataContainerEvent.h" #include "nsIDOMXULMultSelectCntrlEl.h" @@ -39,7 +40,6 @@ #include "nsIWebBrowserChrome.h" #include "nsReadableUtils.h" #include "nsFocusManager.h" -#include "nsDOMEvent.h" #ifdef MOZ_XUL #include "nsIXULDocument.h" @@ -234,7 +234,7 @@ NS_IMETHODIMP RootAccessible::HandleEvent(nsIDOMEvent* aDOMEvent) { MOZ_ASSERT(aDOMEvent); - nsDOMEvent* event = aDOMEvent->InternalDOMEvent(); + Event* event = aDOMEvent->InternalDOMEvent(); nsCOMPtr origTargetNode = do_QueryInterface(event->GetOriginalTarget()); if (!origTargetNode) return NS_OK; @@ -266,7 +266,7 @@ void RootAccessible::ProcessDOMEvent(nsIDOMEvent* aDOMEvent) { MOZ_ASSERT(aDOMEvent); - nsDOMEvent* event = aDOMEvent->InternalDOMEvent(); + Event* event = aDOMEvent->InternalDOMEvent(); nsCOMPtr origTargetNode = do_QueryInterface(event->GetOriginalTarget()); nsAutoString eventType; diff --git a/content/base/public/nsIDocument.h b/content/base/public/nsIDocument.h index 0ef07f43679..ae5f193e8e9 100644 --- a/content/base/public/nsIDocument.h +++ b/content/base/public/nsIDocument.h @@ -80,7 +80,6 @@ class nsWindowSizes; class nsSmallVoidArray; class nsDOMCaretPosition; class nsViewportInfo; -class nsDOMEvent; class nsIGlobalObject; class nsCSSSelectorList; @@ -103,6 +102,7 @@ class DOMImplementation; class DOMStringList; class Element; struct ElementRegistrationOptions; +class Event; class EventTarget; class FrameRequestCallback; class HTMLBodyElement; @@ -2066,8 +2066,8 @@ public: already_AddRefed ImportNode(nsINode& aNode, bool aDeep, mozilla::ErrorResult& rv) const; nsINode* AdoptNode(nsINode& aNode, mozilla::ErrorResult& rv); - already_AddRefed CreateEvent(const nsAString& aEventType, - mozilla::ErrorResult& rv) const; + already_AddRefed + CreateEvent(const nsAString& aEventType, mozilla::ErrorResult& rv) const; already_AddRefed CreateRange(mozilla::ErrorResult& rv); already_AddRefed CreateNodeIterator(nsINode& aRoot, uint32_t aWhatToShow, diff --git a/content/base/src/nsDocument.cpp b/content/base/src/nsDocument.cpp index accae78ae87..62b87010644 100644 --- a/content/base/src/nsDocument.cpp +++ b/content/base/src/nsDocument.cpp @@ -193,6 +193,7 @@ #include "nsIAppsService.h" #include "mozilla/dom/BindingUtils.h" #include "mozilla/dom/DocumentFragment.h" +#include "mozilla/dom/Event.h" #include "mozilla/dom/HTMLBodyElement.h" #include "mozilla/dom/HTMLInputElement.h" #include "mozilla/dom/NodeFilterBinding.h" @@ -203,7 +204,6 @@ #include "nsDOMCaretPosition.h" #include "nsIDOMHTMLTextAreaElement.h" #include "nsViewportInfo.h" -#include "nsDOMEvent.h" #include "nsIContentPermissionPrompt.h" #include "mozilla/StaticPtr.h" #include "nsITextControlElement.h" @@ -7649,7 +7649,7 @@ nsDocument::CreateEvent(const nsAString& aEventType, nsIDOMEvent** aReturn) return rv.ErrorCode(); } -already_AddRefed +already_AddRefed nsIDocument::CreateEvent(const nsAString& aEventType, ErrorResult& rv) const { nsIPresShell *shell = GetShell(); diff --git a/content/base/src/nsINode.cpp b/content/base/src/nsINode.cpp index a478082b410..ba76cd344e7 100644 --- a/content/base/src/nsINode.cpp +++ b/content/base/src/nsINode.cpp @@ -18,6 +18,9 @@ #include "mozilla/Likely.h" #include "mozilla/MemoryReporting.h" #include "mozilla/Telemetry.h" +#include "mozilla/dom/Element.h" +#include "mozilla/dom/Event.h" +#include "mozilla/dom/ShadowRoot.h" #include "nsAsyncDOMEvent.h" #include "nsAttrValueOrString.h" #include "nsBindingManager.h" @@ -41,7 +44,6 @@ #include "nsFocusManager.h" #include "nsFrameManager.h" #include "nsFrameSelection.h" -#include "mozilla/dom/Element.h" #include "nsGenericHTMLElement.h" #include "nsGkAtoms.h" #include "nsIAnonymousContentCreator.h" @@ -96,11 +98,9 @@ #include "nsCSSParser.h" #include "HTMLLegendElement.h" #include "nsWrapperCacheInlines.h" -#include "mozilla/dom/ShadowRoot.h" #include "WrapperFactory.h" #include "DocumentType.h" #include -#include "nsDOMEvent.h" #include "nsGlobalWindow.h" #include "nsDOMMutationObserver.h" @@ -2633,7 +2633,7 @@ nsINode::GetAttributes() } bool -EventTarget::DispatchEvent(nsDOMEvent& aEvent, +EventTarget::DispatchEvent(Event& aEvent, ErrorResult& aRv) { bool result = false; diff --git a/content/base/src/nsObjectLoadingContent.cpp b/content/base/src/nsObjectLoadingContent.cpp index 8e4dd833ddc..adfd7c4aae8 100644 --- a/content/base/src/nsObjectLoadingContent.cpp +++ b/content/base/src/nsObjectLoadingContent.cpp @@ -69,18 +69,18 @@ #include "nsIContentSecurityPolicy.h" #include "nsIChannelPolicy.h" #include "nsChannelPolicy.h" -#include "mozilla/dom/Element.h" #include "GeckoProfiler.h" #include "nsObjectFrame.h" #include "nsDOMClassInfo.h" #include "nsWrapperCacheInlines.h" #include "nsDOMJSUtils.h" -#include "nsDOMEvent.h" #include "nsWidgetsCID.h" #include "nsContentCID.h" #include "mozilla/BasicEvents.h" #include "mozilla/dom/BindingUtils.h" +#include "mozilla/dom/Element.h" +#include "mozilla/dom/Event.h" #include "mozilla/Telemetry.h" #ifdef XP_WIN @@ -307,7 +307,7 @@ nsPluginCrashedEvent::Run() } ErrorResult rv; - nsRefPtr event = + nsRefPtr event = doc->CreateEvent(NS_LITERAL_STRING("datacontainerevents"), rv); nsCOMPtr containerEvent(do_QueryObject(event)); if (!containerEvent) { diff --git a/content/html/content/src/UndoManager.cpp b/content/html/content/src/UndoManager.cpp index e1761cfbf79..e8e4550ab00 100644 --- a/content/html/content/src/UndoManager.cpp +++ b/content/html/content/src/UndoManager.cpp @@ -6,8 +6,8 @@ #include "mozilla/dom/UndoManager.h" #include "mozilla/dom/DOMTransactionBinding.h" +#include "mozilla/dom/Event.h" #include "nsDOMClassInfoID.h" -#include "nsDOMEvent.h" #include "nsIClassInfo.h" #include "nsIDOMDocument.h" #include "nsIXPCScriptable.h" @@ -1142,7 +1142,7 @@ UndoManager::DispatchTransactionEvent(JSContext* aCx, const nsAString& aType, return; } - nsRefPtr event = mHostNode->OwnerDoc()->CreateEvent( + nsRefPtr event = mHostNode->OwnerDoc()->CreateEvent( NS_LITERAL_STRING("domtransaction"), aRv); if (aRv.Failed()) { return; diff --git a/content/html/document/src/nsHTMLDocument.h b/content/html/document/src/nsHTMLDocument.h index 9797e7dd82c..7d261d5788c 100644 --- a/content/html/document/src/nsHTMLDocument.h +++ b/content/html/document/src/nsHTMLDocument.h @@ -20,7 +20,6 @@ #include "nsICommandManager.h" #include "mozilla/dom/HTMLSharedElement.h" -#include "nsDOMEvent.h" class nsIEditor; class nsIParser; diff --git a/content/media/webaudio/AudioProcessingEvent.cpp b/content/media/webaudio/AudioProcessingEvent.cpp index 977abe929fa..7fa885d9dae 100644 --- a/content/media/webaudio/AudioProcessingEvent.cpp +++ b/content/media/webaudio/AudioProcessingEvent.cpp @@ -11,19 +11,19 @@ namespace mozilla { namespace dom { -NS_IMPL_CYCLE_COLLECTION_INHERITED_3(AudioProcessingEvent, nsDOMEvent, +NS_IMPL_CYCLE_COLLECTION_INHERITED_3(AudioProcessingEvent, Event, mInputBuffer, mOutputBuffer, mNode) NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(AudioProcessingEvent) -NS_INTERFACE_MAP_END_INHERITING(nsDOMEvent) +NS_INTERFACE_MAP_END_INHERITING(Event) -NS_IMPL_ADDREF_INHERITED(AudioProcessingEvent, nsDOMEvent) -NS_IMPL_RELEASE_INHERITED(AudioProcessingEvent, nsDOMEvent) +NS_IMPL_ADDREF_INHERITED(AudioProcessingEvent, Event) +NS_IMPL_RELEASE_INHERITED(AudioProcessingEvent, Event) AudioProcessingEvent::AudioProcessingEvent(ScriptProcessorNode* aOwner, nsPresContext* aPresContext, WidgetEvent* aEvent) - : nsDOMEvent(aOwner, aPresContext, aEvent) + : Event(aOwner, aPresContext, aEvent) , mPlaybackTime(0.0) , mNode(aOwner) { diff --git a/content/media/webaudio/AudioProcessingEvent.h b/content/media/webaudio/AudioProcessingEvent.h index 78762ed9407..471476d7623 100644 --- a/content/media/webaudio/AudioProcessingEvent.h +++ b/content/media/webaudio/AudioProcessingEvent.h @@ -7,14 +7,14 @@ #ifndef AudioProcessingEvent_h_ #define AudioProcessingEvent_h_ -#include "nsDOMEvent.h" #include "AudioBuffer.h" #include "ScriptProcessorNode.h" +#include "mozilla/dom/Event.h" namespace mozilla { namespace dom { -class AudioProcessingEvent : public nsDOMEvent +class AudioProcessingEvent : public Event { public: AudioProcessingEvent(ScriptProcessorNode* aOwner, @@ -22,8 +22,8 @@ public: WidgetEvent* aEvent); NS_DECL_ISUPPORTS_INHERITED - NS_FORWARD_TO_NSDOMEVENT - NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(AudioProcessingEvent, nsDOMEvent) + NS_FORWARD_TO_EVENT + NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(AudioProcessingEvent, Event) virtual JSObject* WrapObject(JSContext* aCx, JS::Handle aScope) MOZ_OVERRIDE; diff --git a/content/media/webaudio/OfflineAudioCompletionEvent.cpp b/content/media/webaudio/OfflineAudioCompletionEvent.cpp index 6c01c512cbb..10e953ab31c 100644 --- a/content/media/webaudio/OfflineAudioCompletionEvent.cpp +++ b/content/media/webaudio/OfflineAudioCompletionEvent.cpp @@ -11,19 +11,19 @@ namespace mozilla { namespace dom { -NS_IMPL_CYCLE_COLLECTION_INHERITED_1(OfflineAudioCompletionEvent, nsDOMEvent, +NS_IMPL_CYCLE_COLLECTION_INHERITED_1(OfflineAudioCompletionEvent, Event, mRenderedBuffer) NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(OfflineAudioCompletionEvent) -NS_INTERFACE_MAP_END_INHERITING(nsDOMEvent) +NS_INTERFACE_MAP_END_INHERITING(Event) -NS_IMPL_ADDREF_INHERITED(OfflineAudioCompletionEvent, nsDOMEvent) -NS_IMPL_RELEASE_INHERITED(OfflineAudioCompletionEvent, nsDOMEvent) +NS_IMPL_ADDREF_INHERITED(OfflineAudioCompletionEvent, Event) +NS_IMPL_RELEASE_INHERITED(OfflineAudioCompletionEvent, Event) OfflineAudioCompletionEvent::OfflineAudioCompletionEvent(AudioContext* aOwner, nsPresContext* aPresContext, WidgetEvent* aEvent) - : nsDOMEvent(aOwner, aPresContext, aEvent) + : Event(aOwner, aPresContext, aEvent) { SetIsDOMBinding(); } diff --git a/content/media/webaudio/OfflineAudioCompletionEvent.h b/content/media/webaudio/OfflineAudioCompletionEvent.h index 6d64d3d1d50..af1449a48b8 100644 --- a/content/media/webaudio/OfflineAudioCompletionEvent.h +++ b/content/media/webaudio/OfflineAudioCompletionEvent.h @@ -7,15 +7,15 @@ #ifndef OfflineAudioCompletionEvent_h_ #define OfflineAudioCompletionEvent_h_ -#include "nsDOMEvent.h" #include "AudioBuffer.h" +#include "mozilla/dom/Event.h" namespace mozilla { namespace dom { class AudioContext; -class OfflineAudioCompletionEvent : public nsDOMEvent +class OfflineAudioCompletionEvent : public Event { public: OfflineAudioCompletionEvent(AudioContext* aOwner, @@ -23,8 +23,8 @@ public: WidgetEvent* aEvent); NS_DECL_ISUPPORTS_INHERITED - NS_FORWARD_TO_NSDOMEVENT - NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(OfflineAudioCompletionEvent, nsDOMEvent) + NS_FORWARD_TO_EVENT + NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(OfflineAudioCompletionEvent, Event) virtual JSObject* WrapObject(JSContext* aCx, JS::Handle aScope) MOZ_OVERRIDE; diff --git a/content/xul/content/src/nsXULElement.cpp b/content/xul/content/src/nsXULElement.cpp index f73dd865e81..4ab593ef8ae 100644 --- a/content/xul/content/src/nsXULElement.cpp +++ b/content/xul/content/src/nsXULElement.cpp @@ -58,7 +58,7 @@ #include "nsIXULTemplateBuilder.h" #include "nsLayoutCID.h" #include "nsContentCID.h" -#include "nsDOMEvent.h" +#include "mozilla/dom/Event.h" #include "nsRDFCID.h" #include "nsStyleConsts.h" #include "nsXPIDLString.h" @@ -1185,7 +1185,7 @@ nsXULElement::PreHandleEvent(nsEventChainPreVisitor& aVisitor) // handling. nsCOMPtr domEvent = aVisitor.mDOMEvent; while (domEvent) { - nsDOMEvent* event = domEvent->InternalDOMEvent(); + Event* event = domEvent->InternalDOMEvent(); NS_ENSURE_STATE(!SameCOMIdentity(event->GetOriginalTarget(), commandContent)); nsCOMPtr commandEvent = diff --git a/content/xul/content/src/nsXULPopupListener.cpp b/content/xul/content/src/nsXULPopupListener.cpp index 4f124a14785..f9dd3c09895 100644 --- a/content/xul/content/src/nsXULPopupListener.cpp +++ b/content/xul/content/src/nsXULPopupListener.cpp @@ -32,6 +32,7 @@ #include "nsHTMLReflowState.h" #include "nsIObjectLoadingContent.h" #include "mozilla/Preferences.h" +#include "mozilla/dom/Event.h" // for nsIDOMEvent::InternalDOMEvent() #include "mozilla/dom/EventTarget.h" #include "mozilla/dom/FragmentOrElement.h" @@ -43,7 +44,6 @@ #include "nsViewManager.h" #include "nsError.h" #include "nsMenuFrame.h" -#include "nsDOMEvent.h" using namespace mozilla; using namespace mozilla::dom; diff --git a/dom/base/MessagePort.cpp b/dom/base/MessagePort.cpp index 435569a6af9..bd9eb670320 100644 --- a/dom/base/MessagePort.cpp +++ b/dom/base/MessagePort.cpp @@ -4,6 +4,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "MessagePort.h" +#include "mozilla/dom/Event.h" #include "mozilla/dom/MessageChannel.h" #include "mozilla/dom/MessagePortBinding.h" #include "mozilla/dom/StructuredCloneTags.h" @@ -11,7 +12,6 @@ #include "nsContentUtils.h" #include "nsEventDispatcher.h" #include "nsPresContext.h" -#include "nsDOMEvent.h" #include "nsIDocument.h" #include "nsIDOMFile.h" @@ -259,7 +259,7 @@ PostMessageRunnable::Run() } ErrorResult error; - nsRefPtr event = + nsRefPtr event = doc->CreateEvent(NS_LITERAL_STRING("MessageEvent"), error); if (error.Failed()) { return NS_OK; diff --git a/dom/base/Navigator.cpp b/dom/base/Navigator.cpp index 9ffe2b18555..542688a2e25 100644 --- a/dom/base/Navigator.cpp +++ b/dom/base/Navigator.cpp @@ -35,7 +35,7 @@ #include "mozilla/ClearOnShutdown.h" #include "mozilla/StaticPtr.h" #include "Connection.h" -#include "nsDOMEvent.h" +#include "mozilla/dom/Event.h" // for nsIDOMEvent::InternalDOMEvent() #include "nsGlobalWindow.h" #ifdef MOZ_B2G_RIL #include "mozilla/dom/IccManager.h" diff --git a/dom/base/nsDOMClassInfoID.h b/dom/base/nsDOMClassInfoID.h index decb36846ae..98f6da1a85e 100644 --- a/dom/base/nsDOMClassInfoID.h +++ b/dom/base/nsDOMClassInfoID.h @@ -54,18 +54,18 @@ DOMCI_CASTABLE_NODECL_INTERFACE(mozilla::dom::Element, mozilla::dom::Element,\ /* If this is ever removed, the IID for EventTarget can go away */ \ DOMCI_CASTABLE_NODECL_INTERFACE(mozilla::dom::EventTarget, \ mozilla::dom::EventTarget, 2, _extra) \ -DOMCI_CASTABLE_INTERFACE(nsDOMEvent, nsIDOMEvent, 3, _extra) \ +DOMCI_CASTABLE_NODECL_INTERFACE(mozilla::dom::Event, nsIDOMEvent, 3, _extra) \ DOMCI_CASTABLE_INTERFACE(nsIDocument, nsIDocument, 4, _extra) \ DOMCI_CASTABLE_INTERFACE(nsDocument, nsIDocument, 5, _extra) \ DOMCI_CASTABLE_INTERFACE(nsGenericHTMLElement, nsIContent, 6, _extra) \ DOMCI_CASTABLE_INTERFACE(nsHTMLDocument, nsIDocument, 7, _extra) \ DOMCI_CASTABLE_INTERFACE(nsStyledElement, nsStyledElement, 8, _extra) \ DOMCI_CASTABLE_INTERFACE(nsSVGElement, nsIContent, 9, _extra) \ -/* NOTE: When removing the casts below, remove the nsDOMEventBase class */ \ +/* NOTE: When removing the casts below, remove the dom::EventBase class */ \ DOMCI_CASTABLE_NODECL_INTERFACE(mozilla::dom::MouseEvent, \ - nsDOMEventBase, 10, _extra) \ + mozilla::dom::EventBase, 10, _extra) \ DOMCI_CASTABLE_NODECL_INTERFACE(mozilla::dom::UIEvent, \ - nsDOMEventBase, 11, _extra) \ + mozilla::dom::EventBase, 11, _extra) \ DOMCI_CASTABLE_INTERFACE(nsGlobalWindow, nsIDOMEventTarget, 12, _extra) // Make sure all classes mentioned in DOMCI_CASTABLE_INTERFACES @@ -78,6 +78,7 @@ DOMCI_CASTABLE_INTERFACES(unused) namespace mozilla { namespace dom { class Element; +class Event; class EventTarget; class MouseEvent; class UIEvent; diff --git a/dom/base/nsGlobalWindow.cpp b/dom/base/nsGlobalWindow.cpp index 759b2889fdb..524cf865ad7 100644 --- a/dom/base/nsGlobalWindow.cpp +++ b/dom/base/nsGlobalWindow.cpp @@ -5573,7 +5573,7 @@ bool nsGlobalWindow::DispatchResizeEvent(const nsIntSize& aSize) { ErrorResult res; - nsRefPtr domEvent = + nsRefPtr domEvent = mDoc->CreateEvent(NS_LITERAL_STRING("CustomEvent"), res); if (res.Failed()) { return false; @@ -13060,7 +13060,7 @@ NS_IMETHODIMP nsGlobalChromeWindow::BeginWindowMove(nsIDOMEvent *aMouseDownEvent, nsIDOMElement* aPanel) { NS_ENSURE_TRUE(aMouseDownEvent, NS_ERROR_FAILURE); - nsDOMEvent* mouseDownEvent = aMouseDownEvent->InternalDOMEvent(); + Event* mouseDownEvent = aMouseDownEvent->InternalDOMEvent(); NS_ENSURE_TRUE(mouseDownEvent, NS_ERROR_FAILURE); nsCOMPtr panel = do_QueryInterface(aPanel); @@ -13072,7 +13072,7 @@ nsGlobalChromeWindow::BeginWindowMove(nsIDOMEvent *aMouseDownEvent, nsIDOMElemen } void -nsGlobalWindow::BeginWindowMove(nsDOMEvent& aMouseDownEvent, Element* aPanel, +nsGlobalWindow::BeginWindowMove(Event& aMouseDownEvent, Element* aPanel, ErrorResult& aError) { nsCOMPtr widget; diff --git a/dom/base/nsGlobalWindow.h b/dom/base/nsGlobalWindow.h index 0d6f2abc482..de7e40bc0db 100644 --- a/dom/base/nsGlobalWindow.h +++ b/dom/base/nsGlobalWindow.h @@ -975,7 +975,7 @@ public: void NotifyDefaultButtonLoaded(mozilla::dom::Element& aDefaultButton, mozilla::ErrorResult& aError); nsIMessageBroadcaster* GetMessageManager(mozilla::ErrorResult& aError); - void BeginWindowMove(nsDOMEvent& aMouseDownEvent, + void BeginWindowMove(mozilla::dom::Event& aMouseDownEvent, mozilla::dom::Element* aPanel, mozilla::ErrorResult& aError); diff --git a/dom/base/nsScreen.cpp b/dom/base/nsScreen.cpp index 9c634dee32f..320ab29a4ea 100644 --- a/dom/base/nsScreen.cpp +++ b/dom/base/nsScreen.cpp @@ -4,6 +4,8 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "mozilla/Hal.h" +#include "mozilla/dom/Event.h" // for nsIDOMEvent::InternalDOMEvent() +#include "mozilla/dom/ScreenBinding.h" #include "nsScreen.h" #include "nsIDocument.h" #include "nsIDocShell.h" @@ -12,9 +14,7 @@ #include "nsCOMPtr.h" #include "nsIDocShellTreeItem.h" #include "nsLayoutUtils.h" -#include "nsDOMEvent.h" #include "nsJSUtils.h" -#include "mozilla/dom/ScreenBinding.h" #include "nsDeviceContext.h" using namespace mozilla; diff --git a/dom/battery/BatteryManager.cpp b/dom/battery/BatteryManager.cpp index 1653e7695c5..b6138f4156c 100644 --- a/dom/battery/BatteryManager.cpp +++ b/dom/battery/BatteryManager.cpp @@ -8,7 +8,6 @@ #include "BatteryManager.h" #include "nsIDOMClassInfo.h" #include "Constants.h" -#include "nsDOMEvent.h" #include "mozilla/Preferences.h" #include "nsDOMEventTargetHelper.h" #include "mozilla/dom/BatteryManagerBinding.h" diff --git a/dom/bindings/Bindings.conf b/dom/bindings/Bindings.conf index 5d65ffd151f..0b8d1acd1b7 100644 --- a/dom/bindings/Bindings.conf +++ b/dom/bindings/Bindings.conf @@ -373,7 +373,6 @@ DOMInterfaces = { }, 'Event': { - 'nativeType': 'nsDOMEvent', 'implicitJSContext': [ 'defaultPrevented', 'preventDefault' ], }, diff --git a/dom/bindings/Codegen.py b/dom/bindings/Codegen.py index 00e482a7ecc..e0d20f50389 100644 --- a/dom/bindings/Codegen.py +++ b/dom/bindings/Codegen.py @@ -12072,7 +12072,7 @@ class CGEventClass(CGBindingImplClass): dropJS += " mozilla::DropJSObjects(this);\n" # Just override CGClass and do our own thing nativeType = self.descriptor.nativeType.split('::')[-1] - ctorParams = ("aOwner, nullptr, nullptr" if self.parentType == "nsDOMEvent" + ctorParams = ("aOwner, nullptr, nullptr" if self.parentType == "Event" else "aOwner") classImpl = """ NS_IMPL_CYCLE_COLLECTION_CLASS(${nativeType}) diff --git a/dom/devicestorage/nsDeviceStorage.cpp b/dom/devicestorage/nsDeviceStorage.cpp index c616f184b63..1a762b40b38 100644 --- a/dom/devicestorage/nsDeviceStorage.cpp +++ b/dom/devicestorage/nsDeviceStorage.cpp @@ -22,7 +22,6 @@ #include "mozilla/Services.h" #include "nsAutoPtr.h" -#include "nsDOMEvent.h" #include "nsServiceManagerUtils.h" #include "nsIFile.h" #include "nsIDirectoryEnumerator.h" diff --git a/dom/events/AnimationEvent.cpp b/dom/events/AnimationEvent.cpp index eb0a1f3abf2..706c3c41212 100644 --- a/dom/events/AnimationEvent.cpp +++ b/dom/events/AnimationEvent.cpp @@ -13,8 +13,8 @@ namespace dom { AnimationEvent::AnimationEvent(EventTarget* aOwner, nsPresContext* aPresContext, InternalAnimationEvent* aEvent) - : nsDOMEvent(aOwner, aPresContext, - aEvent ? aEvent : new InternalAnimationEvent(false, 0)) + : Event(aOwner, aPresContext, + aEvent ? aEvent : new InternalAnimationEvent(false, 0)) { if (aEvent) { mEventIsInternal = false; @@ -27,10 +27,10 @@ AnimationEvent::AnimationEvent(EventTarget* aOwner, NS_INTERFACE_MAP_BEGIN(AnimationEvent) NS_INTERFACE_MAP_ENTRY(nsIDOMAnimationEvent) -NS_INTERFACE_MAP_END_INHERITING(nsDOMEvent) +NS_INTERFACE_MAP_END_INHERITING(Event) -NS_IMPL_ADDREF_INHERITED(AnimationEvent, nsDOMEvent) -NS_IMPL_RELEASE_INHERITED(AnimationEvent, nsDOMEvent) +NS_IMPL_ADDREF_INHERITED(AnimationEvent, Event) +NS_IMPL_RELEASE_INHERITED(AnimationEvent, Event) //static already_AddRefed diff --git a/dom/events/AnimationEvent.h b/dom/events/AnimationEvent.h index fafd671a9b7..1b63518fee5 100644 --- a/dom/events/AnimationEvent.h +++ b/dom/events/AnimationEvent.h @@ -5,17 +5,17 @@ #ifndef mozilla_dom_AnimationEvent_h_ #define mozilla_dom_AnimationEvent_h_ -#include "nsDOMEvent.h" -#include "nsIDOMAnimationEvent.h" #include "mozilla/EventForwards.h" +#include "mozilla/dom/Event.h" #include "mozilla/dom/AnimationEventBinding.h" +#include "nsIDOMAnimationEvent.h" class nsAString; namespace mozilla { namespace dom { -class AnimationEvent : public nsDOMEvent, +class AnimationEvent : public Event, public nsIDOMAnimationEvent { public: @@ -24,7 +24,7 @@ public: InternalAnimationEvent* aEvent); NS_DECL_ISUPPORTS_INHERITED - NS_FORWARD_TO_NSDOMEVENT + NS_FORWARD_TO_EVENT NS_DECL_NSIDOMANIMATIONEVENT static already_AddRefed diff --git a/dom/events/BeforeUnloadEvent.cpp b/dom/events/BeforeUnloadEvent.cpp index ea56fb4155b..c1feff04f2b 100644 --- a/dom/events/BeforeUnloadEvent.cpp +++ b/dom/events/BeforeUnloadEvent.cpp @@ -8,12 +8,12 @@ namespace mozilla { namespace dom { -NS_IMPL_ADDREF_INHERITED(BeforeUnloadEvent, nsDOMEvent) -NS_IMPL_RELEASE_INHERITED(BeforeUnloadEvent, nsDOMEvent) +NS_IMPL_ADDREF_INHERITED(BeforeUnloadEvent, Event) +NS_IMPL_RELEASE_INHERITED(BeforeUnloadEvent, Event) NS_INTERFACE_MAP_BEGIN(BeforeUnloadEvent) NS_INTERFACE_MAP_ENTRY(nsIDOMBeforeUnloadEvent) -NS_INTERFACE_MAP_END_INHERITING(nsDOMEvent) +NS_INTERFACE_MAP_END_INHERITING(Event) NS_IMETHODIMP BeforeUnloadEvent::SetReturnValue(const nsAString& aReturnValue) diff --git a/dom/events/BeforeUnloadEvent.h b/dom/events/BeforeUnloadEvent.h index dd8ed0b4306..3824d090c1b 100644 --- a/dom/events/BeforeUnloadEvent.h +++ b/dom/events/BeforeUnloadEvent.h @@ -6,21 +6,21 @@ #ifndef mozilla_dom_BeforeUnloadEvent_h_ #define mozilla_dom_BeforeUnloadEvent_h_ -#include "nsIDOMBeforeUnloadEvent.h" -#include "nsDOMEvent.h" #include "mozilla/dom/BeforeUnloadEventBinding.h" +#include "mozilla/dom/Event.h" +#include "nsIDOMBeforeUnloadEvent.h" namespace mozilla { namespace dom { -class BeforeUnloadEvent : public nsDOMEvent, +class BeforeUnloadEvent : public Event, public nsIDOMBeforeUnloadEvent { public: BeforeUnloadEvent(EventTarget* aOwner, nsPresContext* aPresContext, WidgetEvent* aEvent) - : nsDOMEvent(aOwner, aPresContext, aEvent) + : Event(aOwner, aPresContext, aEvent) { } @@ -32,8 +32,8 @@ public: NS_DECL_ISUPPORTS_INHERITED - // Forward to nsDOMEvent - NS_FORWARD_TO_NSDOMEVENT + // Forward to Event + NS_FORWARD_TO_EVENT // nsIDOMBeforeUnloadEvent Interface NS_DECL_NSIDOMBEFOREUNLOADEVENT diff --git a/dom/events/ClipboardEvent.cpp b/dom/events/ClipboardEvent.cpp index f4d06309b87..a2286ce54bd 100644 --- a/dom/events/ClipboardEvent.cpp +++ b/dom/events/ClipboardEvent.cpp @@ -14,8 +14,8 @@ namespace dom { ClipboardEvent::ClipboardEvent(EventTarget* aOwner, nsPresContext* aPresContext, InternalClipboardEvent* aEvent) - : nsDOMEvent(aOwner, aPresContext, aEvent ? aEvent : - new InternalClipboardEvent(false, 0)) + : Event(aOwner, aPresContext, + aEvent ? aEvent : new InternalClipboardEvent(false, 0)) { if (aEvent) { mEventIsInternal = false; @@ -27,10 +27,10 @@ ClipboardEvent::ClipboardEvent(EventTarget* aOwner, NS_INTERFACE_MAP_BEGIN(ClipboardEvent) NS_INTERFACE_MAP_ENTRY(nsIDOMClipboardEvent) -NS_INTERFACE_MAP_END_INHERITING(nsDOMEvent) +NS_INTERFACE_MAP_END_INHERITING(Event) -NS_IMPL_ADDREF_INHERITED(ClipboardEvent, nsDOMEvent) -NS_IMPL_RELEASE_INHERITED(ClipboardEvent, nsDOMEvent) +NS_IMPL_ADDREF_INHERITED(ClipboardEvent, Event) +NS_IMPL_RELEASE_INHERITED(ClipboardEvent, Event) nsresult ClipboardEvent::InitClipboardEvent(const nsAString& aType, @@ -53,7 +53,7 @@ ClipboardEvent::InitClipboardEvent(const nsAString& aType, bool aCanBubble, DataTransfer* aClipboardData, ErrorResult& aError) { - aError = nsDOMEvent::InitEvent(aType, aCanBubble, aCancelable); + aError = Event::InitEvent(aType, aCanBubble, aCancelable); if (aError.Failed()) { return; } diff --git a/dom/events/ClipboardEvent.h b/dom/events/ClipboardEvent.h index 802ea3013d7..8a0a8ad5ec6 100644 --- a/dom/events/ClipboardEvent.h +++ b/dom/events/ClipboardEvent.h @@ -6,16 +6,16 @@ #ifndef mozilla_dom_ClipboardEvent_h_ #define mozilla_dom_ClipboardEvent_h_ -#include "nsIDOMClipboardEvent.h" -#include "nsDOMEvent.h" #include "mozilla/EventForwards.h" #include "mozilla/dom/ClipboardEventBinding.h" +#include "mozilla/dom/Event.h" +#include "nsIDOMClipboardEvent.h" namespace mozilla { namespace dom { class DataTransfer; -class ClipboardEvent : public nsDOMEvent, +class ClipboardEvent : public Event, public nsIDOMClipboardEvent { public: @@ -28,7 +28,7 @@ public: NS_DECL_NSIDOMCLIPBOARDEVENT // Forward to base class - NS_FORWARD_TO_NSDOMEVENT + NS_FORWARD_TO_EVENT virtual JSObject* WrapObject(JSContext* aCx, JS::Handle aScope) MOZ_OVERRIDE diff --git a/dom/events/CommandEvent.cpp b/dom/events/CommandEvent.cpp index 8d9a95eab4e..51f56c84dea 100644 --- a/dom/events/CommandEvent.cpp +++ b/dom/events/CommandEvent.cpp @@ -13,8 +13,9 @@ namespace dom { CommandEvent::CommandEvent(EventTarget* aOwner, nsPresContext* aPresContext, WidgetCommandEvent* aEvent) - : nsDOMEvent(aOwner, aPresContext, aEvent ? aEvent : - new WidgetCommandEvent(false, nullptr, nullptr, nullptr)) + : Event(aOwner, aPresContext, + aEvent ? aEvent : + new WidgetCommandEvent(false, nullptr, nullptr, nullptr)) { mEvent->time = PR_Now(); if (aEvent) { @@ -26,10 +27,10 @@ CommandEvent::CommandEvent(EventTarget* aOwner, NS_INTERFACE_MAP_BEGIN(CommandEvent) NS_INTERFACE_MAP_ENTRY(nsIDOMCommandEvent) -NS_INTERFACE_MAP_END_INHERITING(nsDOMEvent) +NS_INTERFACE_MAP_END_INHERITING(Event) -NS_IMPL_ADDREF_INHERITED(CommandEvent, nsDOMEvent) -NS_IMPL_RELEASE_INHERITED(CommandEvent, nsDOMEvent) +NS_IMPL_ADDREF_INHERITED(CommandEvent, Event) +NS_IMPL_RELEASE_INHERITED(CommandEvent, Event) NS_IMETHODIMP CommandEvent::GetCommand(nsAString& aCommand) @@ -49,7 +50,7 @@ CommandEvent::InitCommandEvent(const nsAString& aTypeArg, bool aCancelableArg, const nsAString& aCommand) { - nsresult rv = nsDOMEvent::InitEvent(aTypeArg, aCanBubbleArg, aCancelableArg); + nsresult rv = Event::InitEvent(aTypeArg, aCanBubbleArg, aCancelableArg); NS_ENSURE_SUCCESS(rv, rv); mEvent->AsCommandEvent()->command = do_GetAtom(aCommand); diff --git a/dom/events/CommandEvent.h b/dom/events/CommandEvent.h index 16854a313bc..f13a720e80c 100644 --- a/dom/events/CommandEvent.h +++ b/dom/events/CommandEvent.h @@ -6,15 +6,15 @@ #ifndef mozilla_dom_CommandEvent_h_ #define mozilla_dom_CommandEvent_h_ -#include "nsIDOMCommandEvent.h" -#include "nsDOMEvent.h" -#include "mozilla/dom/CommandEventBinding.h" #include "mozilla/EventForwards.h" +#include "mozilla/dom/CommandEventBinding.h" +#include "mozilla/dom/Event.h" +#include "nsIDOMCommandEvent.h" namespace mozilla { namespace dom { -class CommandEvent : public nsDOMEvent, +class CommandEvent : public Event, public nsIDOMCommandEvent { public: @@ -27,7 +27,7 @@ public: NS_DECL_NSIDOMCOMMANDEVENT // Forward to base class - NS_FORWARD_TO_NSDOMEVENT + NS_FORWARD_TO_EVENT virtual JSObject* WrapObject(JSContext* aCx, JS::Handle aScope) MOZ_OVERRIDE diff --git a/dom/events/DataContainerEvent.cpp b/dom/events/DataContainerEvent.cpp index 1522065bedc..f338fcc95f2 100644 --- a/dom/events/DataContainerEvent.cpp +++ b/dom/events/DataContainerEvent.cpp @@ -13,27 +13,26 @@ namespace dom { DataContainerEvent::DataContainerEvent(EventTarget* aOwner, nsPresContext* aPresContext, WidgetEvent* aEvent) - : nsDOMEvent(aOwner, aPresContext, aEvent) + : Event(aOwner, aPresContext, aEvent) { } NS_IMPL_CYCLE_COLLECTION_CLASS(DataContainerEvent) -NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(DataContainerEvent, nsDOMEvent) +NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(DataContainerEvent, Event) tmp->mData.Clear(); NS_IMPL_CYCLE_COLLECTION_UNLINK_END -NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(DataContainerEvent, - nsDOMEvent) +NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(DataContainerEvent, Event) tmp->mData.EnumerateRead(TraverseEntry, &cb); NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END -NS_IMPL_ADDREF_INHERITED(DataContainerEvent, nsDOMEvent) -NS_IMPL_RELEASE_INHERITED(DataContainerEvent, nsDOMEvent) +NS_IMPL_ADDREF_INHERITED(DataContainerEvent, Event) +NS_IMPL_RELEASE_INHERITED(DataContainerEvent, Event) NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(DataContainerEvent) NS_INTERFACE_MAP_ENTRY(nsIDOMDataContainerEvent) -NS_INTERFACE_MAP_END_INHERITING(nsDOMEvent) +NS_INTERFACE_MAP_END_INHERITING(Event) NS_IMETHODIMP DataContainerEvent::GetData(const nsAString& aKey, nsIVariant** aData) diff --git a/dom/events/DataContainerEvent.h b/dom/events/DataContainerEvent.h index f8b621f4769..4cc42edd5b6 100644 --- a/dom/events/DataContainerEvent.h +++ b/dom/events/DataContainerEvent.h @@ -6,15 +6,15 @@ #ifndef mozilla_dom_DataContainerEvent_h_ #define mozilla_dom_DataContainerEvent_h_ -#include "nsIDOMDataContainerEvent.h" -#include "nsDOMEvent.h" -#include "nsInterfaceHashtable.h" #include "mozilla/dom/DataContainerEventBinding.h" +#include "mozilla/dom/Event.h" +#include "nsIDOMDataContainerEvent.h" +#include "nsInterfaceHashtable.h" namespace mozilla { namespace dom { -class DataContainerEvent : public nsDOMEvent, +class DataContainerEvent : public Event, public nsIDOMDataContainerEvent { public: @@ -24,9 +24,9 @@ public: NS_DECL_ISUPPORTS_INHERITED - NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(DataContainerEvent, nsDOMEvent) + NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(DataContainerEvent, Event) - NS_FORWARD_TO_NSDOMEVENT + NS_FORWARD_TO_EVENT NS_DECL_NSIDOMDATACONTAINEREVENT diff --git a/dom/events/DeviceMotionEvent.cpp b/dom/events/DeviceMotionEvent.cpp index 60ce251dd99..b0d424fd342 100644 --- a/dom/events/DeviceMotionEvent.cpp +++ b/dom/events/DeviceMotionEvent.cpp @@ -14,16 +14,16 @@ namespace dom { * DeviceMotionEvent *****************************************************************************/ -NS_IMPL_CYCLE_COLLECTION_INHERITED_3(DeviceMotionEvent, nsDOMEvent, +NS_IMPL_CYCLE_COLLECTION_INHERITED_3(DeviceMotionEvent, Event, mAcceleration, mAccelerationIncludingGravity, mRotationRate) -NS_IMPL_ADDREF_INHERITED(DeviceMotionEvent, nsDOMEvent) -NS_IMPL_RELEASE_INHERITED(DeviceMotionEvent, nsDOMEvent) +NS_IMPL_ADDREF_INHERITED(DeviceMotionEvent, Event) +NS_IMPL_RELEASE_INHERITED(DeviceMotionEvent, Event) NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(DeviceMotionEvent) -NS_INTERFACE_MAP_END_INHERITING(nsDOMEvent) +NS_INTERFACE_MAP_END_INHERITING(Event) void DeviceMotionEvent::InitDeviceMotionEvent( @@ -36,7 +36,7 @@ DeviceMotionEvent::InitDeviceMotionEvent( Nullable aInterval, ErrorResult& aRv) { - aRv = nsDOMEvent::InitEvent(aType, aCanBubble, aCancelable); + aRv = Event::InitEvent(aType, aCanBubble, aCancelable); if (aRv.Failed()) { return; } diff --git a/dom/events/DeviceMotionEvent.h b/dom/events/DeviceMotionEvent.h index df63cfd8c3e..13654ecc9b8 100644 --- a/dom/events/DeviceMotionEvent.h +++ b/dom/events/DeviceMotionEvent.h @@ -5,9 +5,9 @@ #ifndef mozilla_dom_DeviceMotionEvent_h_ #define mozilla_dom_DeviceMotionEvent_h_ -#include "nsDOMEvent.h" #include "mozilla/Attributes.h" #include "mozilla/dom/DeviceMotionEventBinding.h" +#include "mozilla/dom/Event.h" namespace mozilla { namespace dom { @@ -88,23 +88,23 @@ protected: Nullable mX, mY, mZ; }; -class DeviceMotionEvent MOZ_FINAL : public nsDOMEvent +class DeviceMotionEvent MOZ_FINAL : public Event { public: DeviceMotionEvent(EventTarget* aOwner, nsPresContext* aPresContext, WidgetEvent* aEvent) - : nsDOMEvent(aOwner, aPresContext, aEvent) + : Event(aOwner, aPresContext, aEvent) { } NS_DECL_ISUPPORTS_INHERITED - // Forward to nsDOMEvent - NS_FORWARD_TO_NSDOMEVENT + // Forward to Event + NS_FORWARD_TO_EVENT - NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(DeviceMotionEvent, nsDOMEvent) + NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(DeviceMotionEvent, Event) virtual JSObject* WrapObject(JSContext* aCx, JS::Handle aScope) MOZ_OVERRIDE diff --git a/dom/events/nsDOMEvent.cpp b/dom/events/Event.cpp similarity index 81% rename from dom/events/nsDOMEvent.cpp rename to dom/events/Event.cpp index ee63fa6bd8c..543c5b5f186 100644 --- a/dom/events/nsDOMEvent.cpp +++ b/dom/events/Event.cpp @@ -3,62 +3,58 @@ * 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 "base/basictypes.h" - #include "AccessCheck.h" +#include "base/basictypes.h" #include "ipc/IPCMessageUtils.h" -#include "nsCOMPtr.h" -#include "nsError.h" -#include "nsDOMEvent.h" -#include "nsEventStateManager.h" -#include "nsIFrame.h" -#include "nsIContent.h" -#include "nsIPresShell.h" -#include "nsIDocument.h" +#include "mozilla/dom/Event.h" #include "mozilla/ContentEvents.h" #include "mozilla/InternalMutationEvent.h" #include "mozilla/MiscEvents.h" #include "mozilla/MouseEvents.h" +#include "mozilla/Preferences.h" #include "mozilla/TextEvents.h" #include "mozilla/TouchEvents.h" #include "nsContentUtils.h" -#include "nsJSEnvironment.h" -#include "mozilla/Preferences.h" -#include "nsLayoutUtils.h" -#include "nsIScrollableFrame.h" -#include "nsDOMEventTargetHelper.h" -#include "nsPIWindowRoot.h" -#include "nsGlobalWindow.h" +#include "nsCOMPtr.h" #include "nsDeviceContext.h" - -using namespace mozilla; -using namespace mozilla::dom; +#include "nsDOMEventTargetHelper.h" +#include "nsError.h" +#include "nsEventStateManager.h" +#include "nsGlobalWindow.h" +#include "nsIFrame.h" +#include "nsIContent.h" +#include "nsIDocument.h" +#include "nsIPresShell.h" +#include "nsIScrollableFrame.h" +#include "nsJSEnvironment.h" +#include "nsLayoutUtils.h" +#include "nsPIWindowRoot.h" namespace mozilla { namespace dom { + namespace workers { extern bool IsCurrentThreadRunningChromeWorker(); } // namespace workers -} // namespace dom -} // namespace mozilla static char *sPopupAllowedEvents; - -nsDOMEvent::nsDOMEvent(mozilla::dom::EventTarget* aOwner, - nsPresContext* aPresContext, WidgetEvent* aEvent) +Event::Event(EventTarget* aOwner, + nsPresContext* aPresContext, + WidgetEvent* aEvent) { ConstructorInit(aOwner, aPresContext, aEvent); } -nsDOMEvent::nsDOMEvent(nsPIDOMWindow* aParent) +Event::Event(nsPIDOMWindow* aParent) { ConstructorInit(static_cast(aParent), nullptr, nullptr); } void -nsDOMEvent::ConstructorInit(mozilla::dom::EventTarget* aOwner, - nsPresContext* aPresContext, WidgetEvent* aEvent) +Event::ConstructorInit(EventTarget* aOwner, + nsPresContext* aPresContext, + WidgetEvent* aEvent) { SetIsDOMBinding(); SetOwner(aOwner); @@ -80,13 +76,13 @@ nsDOMEvent::ConstructorInit(mozilla::dom::EventTarget* aOwner, (derived from WidgetEvent). To do this, it should take care to pass a non-nullptr aEvent to this ctor, e.g.: - nsDOMFooEvent::nsDOMFooEvent(..., WidgetEvent* aEvent) - : nsDOMEvent(..., aEvent ? aEvent : new nsFooEvent()) + FooEvent::FooEvent(..., WidgetEvent* aEvent) + : Event(..., aEvent ? aEvent : new WidgetEvent()) Then, to override the mEventIsInternal assignments done by the base ctor, it should do this in its own ctor: - nsDOMFooEvent::nsDOMFooEvent(..., WidgetEvent* aEvent) + FooEvent::FooEvent(..., WidgetEvent* aEvent) ... { ... @@ -107,7 +103,7 @@ nsDOMEvent::ConstructorInit(mozilla::dom::EventTarget* aOwner, } void -nsDOMEvent::InitPresContextData(nsPresContext* aPresContext) +Event::InitPresContextData(nsPresContext* aPresContext) { mPresContext = aPresContext; // Get the explicit original target (if it's anonymous make it null) @@ -120,31 +116,31 @@ nsDOMEvent::InitPresContextData(nsPresContext* aPresContext) } } -nsDOMEvent::~nsDOMEvent() +Event::~Event() { - NS_ASSERT_OWNINGTHREAD(nsDOMEvent); + NS_ASSERT_OWNINGTHREAD(Event); if (mEventIsInternal && mEvent) { delete mEvent; } } -NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsDOMEvent) +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(Event) NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY NS_INTERFACE_MAP_ENTRY(nsISupports) NS_INTERFACE_MAP_ENTRY(nsIDOMEvent) NS_INTERFACE_MAP_END -NS_IMPL_CYCLE_COLLECTING_ADDREF(nsDOMEvent) -NS_IMPL_CYCLE_COLLECTING_RELEASE(nsDOMEvent) +NS_IMPL_CYCLE_COLLECTING_ADDREF(Event) +NS_IMPL_CYCLE_COLLECTING_RELEASE(Event) -NS_IMPL_CYCLE_COLLECTION_CLASS(nsDOMEvent) +NS_IMPL_CYCLE_COLLECTION_CLASS(Event) -NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsDOMEvent) +NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(Event) NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER NS_IMPL_CYCLE_COLLECTION_TRACE_END -NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsDOMEvent) +NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(Event) if (tmp->mEventIsInternal) { tmp->mEvent->target = nullptr; tmp->mEvent->currentTarget = nullptr; @@ -182,7 +178,7 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsDOMEvent) NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER NS_IMPL_CYCLE_COLLECTION_UNLINK_END -NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsDOMEvent) +NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(Event) if (tmp->mEventIsInternal) { NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mEvent->target) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mEvent->currentTarget) @@ -227,7 +223,7 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsDOMEvent) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END bool -nsDOMEvent::IsChrome(JSContext* aCx) const +Event::IsChrome(JSContext* aCx) const { return mIsMainThreadEvent ? xpc::AccessCheck::isChrome(js::GetContextCompartment(aCx)) : @@ -235,7 +231,8 @@ nsDOMEvent::IsChrome(JSContext* aCx) const } // nsIDOMEventInterface -NS_METHOD nsDOMEvent::GetType(nsAString& aType) +NS_METHOD +Event::GetType(nsAString& aType) { if (!mIsMainThreadEvent || !mEvent->typeString.IsEmpty()) { aType = mEvent->typeString; @@ -263,26 +260,26 @@ GetDOMEventTarget(nsIDOMEventTarget* aTarget) } EventTarget* -nsDOMEvent::GetTarget() const +Event::GetTarget() const { return GetDOMEventTarget(mEvent->target); } NS_METHOD -nsDOMEvent::GetTarget(nsIDOMEventTarget** aTarget) +Event::GetTarget(nsIDOMEventTarget** aTarget) { NS_IF_ADDREF(*aTarget = GetTarget()); return NS_OK; } EventTarget* -nsDOMEvent::GetCurrentTarget() const +Event::GetCurrentTarget() const { return GetDOMEventTarget(mEvent->currentTarget); } NS_IMETHODIMP -nsDOMEvent::GetCurrentTarget(nsIDOMEventTarget** aCurrentTarget) +Event::GetCurrentTarget(nsIDOMEventTarget** aCurrentTarget) { NS_IF_ADDREF(*aCurrentTarget = GetCurrentTarget()); return NS_OK; @@ -292,7 +289,7 @@ nsDOMEvent::GetCurrentTarget(nsIDOMEventTarget** aCurrentTarget) // Get the actual event target node (may have been retargeted for mouse events) // already_AddRefed -nsDOMEvent::GetTargetFromFrame() +Event::GetTargetFromFrame() { if (!mPresContext) { return nullptr; } @@ -307,7 +304,7 @@ nsDOMEvent::GetTargetFromFrame() } EventTarget* -nsDOMEvent::GetExplicitOriginalTarget() const +Event::GetExplicitOriginalTarget() const { if (mExplicitOriginalTarget) { return mExplicitOriginalTarget; @@ -316,14 +313,14 @@ nsDOMEvent::GetExplicitOriginalTarget() const } NS_IMETHODIMP -nsDOMEvent::GetExplicitOriginalTarget(nsIDOMEventTarget** aRealEventTarget) +Event::GetExplicitOriginalTarget(nsIDOMEventTarget** aRealEventTarget) { NS_IF_ADDREF(*aRealEventTarget = GetExplicitOriginalTarget()); return NS_OK; } EventTarget* -nsDOMEvent::GetOriginalTarget() const +Event::GetOriginalTarget() const { if (mEvent->originalTarget) { return GetDOMEventTarget(mEvent->originalTarget); @@ -333,20 +330,20 @@ nsDOMEvent::GetOriginalTarget() const } NS_IMETHODIMP -nsDOMEvent::GetOriginalTarget(nsIDOMEventTarget** aOriginalTarget) +Event::GetOriginalTarget(nsIDOMEventTarget** aOriginalTarget) { NS_IF_ADDREF(*aOriginalTarget = GetOriginalTarget()); return NS_OK; } NS_IMETHODIMP_(void) -nsDOMEvent::SetTrusted(bool aTrusted) +Event::SetTrusted(bool aTrusted) { mEvent->mFlags.mIsTrusted = aTrusted; } bool -nsDOMEvent::Init(mozilla::dom::EventTarget* aGlobal) +Event::Init(mozilla::dom::EventTarget* aGlobal) { if (!mIsMainThreadEvent) { return nsContentUtils::ThreadsafeIsCallerChrome(); @@ -366,15 +363,15 @@ nsDOMEvent::Init(mozilla::dom::EventTarget* aGlobal) return trusted; } -//static -already_AddRefed -nsDOMEvent::Constructor(const mozilla::dom::GlobalObject& aGlobal, - const nsAString& aType, - const mozilla::dom::EventInit& aParam, - mozilla::ErrorResult& aRv) +// static +already_AddRefed +Event::Constructor(const GlobalObject& aGlobal, + const nsAString& aType, + const EventInit& aParam, + ErrorResult& aRv) { nsCOMPtr t = do_QueryInterface(aGlobal.GetAsSupports()); - nsRefPtr e = new nsDOMEvent(t, nullptr, nullptr); + nsRefPtr e = new Event(t, nullptr, nullptr); bool trusted = e->Init(t); aRv = e->InitEvent(aType, aParam.mBubbles, aParam.mCancelable); e->SetTrusted(trusted); @@ -382,7 +379,7 @@ nsDOMEvent::Constructor(const mozilla::dom::GlobalObject& aGlobal, } uint16_t -nsDOMEvent::EventPhase() const +Event::EventPhase() const { // Note, remember to check that this works also // if or when Bug 235441 is fixed. @@ -401,42 +398,42 @@ nsDOMEvent::EventPhase() const } NS_IMETHODIMP -nsDOMEvent::GetEventPhase(uint16_t* aEventPhase) +Event::GetEventPhase(uint16_t* aEventPhase) { *aEventPhase = EventPhase(); return NS_OK; } NS_IMETHODIMP -nsDOMEvent::GetBubbles(bool* aBubbles) +Event::GetBubbles(bool* aBubbles) { *aBubbles = Bubbles(); return NS_OK; } NS_IMETHODIMP -nsDOMEvent::GetCancelable(bool* aCancelable) +Event::GetCancelable(bool* aCancelable) { *aCancelable = Cancelable(); return NS_OK; } NS_IMETHODIMP -nsDOMEvent::GetTimeStamp(uint64_t* aTimeStamp) +Event::GetTimeStamp(uint64_t* aTimeStamp) { *aTimeStamp = TimeStamp(); return NS_OK; } NS_IMETHODIMP -nsDOMEvent::StopPropagation() +Event::StopPropagation() { mEvent->mFlags.mPropagationStopped = true; return NS_OK; } NS_IMETHODIMP -nsDOMEvent::StopImmediatePropagation() +Event::StopImmediatePropagation() { mEvent->mFlags.mPropagationStopped = true; mEvent->mFlags.mImmediatePropagationStopped = true; @@ -444,14 +441,14 @@ nsDOMEvent::StopImmediatePropagation() } NS_IMETHODIMP -nsDOMEvent::GetIsTrusted(bool *aIsTrusted) +Event::GetIsTrusted(bool* aIsTrusted) { *aIsTrusted = IsTrusted(); return NS_OK; } NS_IMETHODIMP -nsDOMEvent::PreventDefault() +Event::PreventDefault() { // This method is called only from C++ code which must handle default action // of this event. So, pass true always. @@ -460,7 +457,7 @@ nsDOMEvent::PreventDefault() } void -nsDOMEvent::PreventDefault(JSContext* aCx) +Event::PreventDefault(JSContext* aCx) { MOZ_ASSERT(aCx, "JS context must be specified"); @@ -472,7 +469,7 @@ nsDOMEvent::PreventDefault(JSContext* aCx) } void -nsDOMEvent::PreventDefaultInternal(bool aCalledByDefaultHandler) +Event::PreventDefaultInternal(bool aCalledByDefaultHandler) { if (!mEvent->mFlags.mCancelable) { return; @@ -511,7 +508,7 @@ nsDOMEvent::PreventDefaultInternal(bool aCalledByDefaultHandler) } void -nsDOMEvent::SetEventType(const nsAString& aEventTypeArg) +Event::SetEventType(const nsAString& aEventTypeArg) { if (mIsMainThreadEvent) { mEvent->userType = @@ -525,7 +522,9 @@ nsDOMEvent::SetEventType(const nsAString& aEventTypeArg) } NS_IMETHODIMP -nsDOMEvent::InitEvent(const nsAString& aEventTypeArg, bool aCanBubbleArg, bool aCancelableArg) +Event::InitEvent(const nsAString& aEventTypeArg, + bool aCanBubbleArg, + bool aCancelableArg) { // Make sure this event isn't already being dispatched. NS_ENSURE_TRUE(!mEvent->mFlags.mIsBeingDispatched, NS_OK); @@ -552,9 +551,9 @@ nsDOMEvent::InitEvent(const nsAString& aEventTypeArg, bool aCanBubbleArg, bool a } NS_IMETHODIMP -nsDOMEvent::DuplicatePrivateData() +Event::DuplicatePrivateData() { - NS_ASSERTION(mEvent, "No WidgetEvent for nsDOMEvent duplication!"); + NS_ASSERTION(mEvent, "No WidgetEvent for Event duplication!"); if (mEventIsInternal) { return NS_OK; } @@ -568,7 +567,7 @@ nsDOMEvent::DuplicatePrivateData() } NS_IMETHODIMP -nsDOMEvent::SetTarget(nsIDOMEventTarget* aTarget) +Event::SetTarget(nsIDOMEventTarget* aTarget) { #ifdef DEBUG { @@ -584,19 +583,19 @@ nsDOMEvent::SetTarget(nsIDOMEventTarget* aTarget) } NS_IMETHODIMP_(bool) -nsDOMEvent::IsDispatchStopped() +Event::IsDispatchStopped() { return mEvent->mFlags.mPropagationStopped; } NS_IMETHODIMP_(WidgetEvent*) -nsDOMEvent::GetInternalNSEvent() +Event::GetInternalNSEvent() { return mEvent; } -NS_IMETHODIMP_(nsDOMEvent*) -nsDOMEvent::InternalDOMEvent() +NS_IMETHODIMP_(Event*) +Event::InternalDOMEvent() { return this; } @@ -607,7 +606,7 @@ static bool PopupAllowedForEvent(const char *eventName) { if (!sPopupAllowedEvents) { - nsDOMEvent::PopupAllowedEventsChanged(); + Event::PopupAllowedEventsChanged(); if (!sPopupAllowedEvents) { return false; @@ -643,7 +642,7 @@ PopupAllowedForEvent(const char *eventName) // static PopupControlState -nsDOMEvent::GetEventPopupControlState(WidgetEvent* aEvent) +Event::GetEventPopupControlState(WidgetEvent* aEvent) { // generally if an event handler is running, new windows are disallowed. // check for exceptions: @@ -657,12 +656,14 @@ nsDOMEvent::GetEventPopupControlState(WidgetEvent* aEvent) if (nsEventStateManager::IsHandlingUserInput()) { switch(aEvent->message) { case NS_FORM_SELECTED : - if (::PopupAllowedForEvent("select")) + if (PopupAllowedForEvent("select")) { abuse = openControlled; + } break; case NS_FORM_CHANGE : - if (::PopupAllowedForEvent("change")) + if (PopupAllowedForEvent("change")) { abuse = openControlled; + } break; } } @@ -674,8 +675,9 @@ nsDOMEvent::GetEventPopupControlState(WidgetEvent* aEvent) if (nsEventStateManager::IsHandlingUserInput()) { switch(aEvent->message) { case NS_FORM_INPUT : - if (::PopupAllowedForEvent("input")) + if (PopupAllowedForEvent("input")) { abuse = openControlled; + } break; } } @@ -687,8 +689,9 @@ nsDOMEvent::GetEventPopupControlState(WidgetEvent* aEvent) if (nsEventStateManager::IsHandlingUserInput()) { switch(aEvent->message) { case NS_FORM_CHANGE : - if (::PopupAllowedForEvent("change")) + if (PopupAllowedForEvent("change")) { abuse = openControlled; + } break; case NS_XUL_COMMAND: abuse = openControlled; @@ -702,21 +705,24 @@ nsDOMEvent::GetEventPopupControlState(WidgetEvent* aEvent) switch(aEvent->message) { case NS_KEY_PRESS : // return key on focused button. see note at NS_MOUSE_CLICK. - if (key == nsIDOMKeyEvent::DOM_VK_RETURN) + if (key == nsIDOMKeyEvent::DOM_VK_RETURN) { abuse = openAllowed; - else if (::PopupAllowedForEvent("keypress")) + } else if (PopupAllowedForEvent("keypress")) { abuse = openControlled; + } break; case NS_KEY_UP : // space key on focused button. see note at NS_MOUSE_CLICK. - if (key == nsIDOMKeyEvent::DOM_VK_SPACE) + if (key == nsIDOMKeyEvent::DOM_VK_SPACE) { abuse = openAllowed; - else if (::PopupAllowedForEvent("keyup")) + } else if (PopupAllowedForEvent("keyup")) { abuse = openControlled; + } break; case NS_KEY_DOWN : - if (::PopupAllowedForEvent("keydown")) + if (PopupAllowedForEvent("keydown")) { abuse = openControlled; + } break; } } @@ -742,24 +748,28 @@ nsDOMEvent::GetEventPopupControlState(WidgetEvent* aEvent) aEvent->AsMouseEvent()->button == WidgetMouseEvent::eLeftButton) { switch(aEvent->message) { case NS_MOUSE_BUTTON_UP : - if (::PopupAllowedForEvent("mouseup")) + if (PopupAllowedForEvent("mouseup")) { abuse = openControlled; + } break; case NS_MOUSE_BUTTON_DOWN : - if (::PopupAllowedForEvent("mousedown")) + if (PopupAllowedForEvent("mousedown")) { abuse = openControlled; + } break; case NS_MOUSE_CLICK : /* Click events get special treatment because of their historical status as a more legitimate event handler. If click popups are enabled in the prefs, clear the popup status completely. */ - if (::PopupAllowedForEvent("click")) + if (PopupAllowedForEvent("click")) { abuse = openAllowed; + } break; case NS_MOUSE_DOUBLECLICK : - if (::PopupAllowedForEvent("dblclick")) + if (PopupAllowedForEvent("dblclick")) { abuse = openControlled; + } break; } } @@ -771,12 +781,14 @@ nsDOMEvent::GetEventPopupControlState(WidgetEvent* aEvent) if (nsEventStateManager::IsHandlingUserInput()) { switch(aEvent->message) { case NS_FORM_SUBMIT : - if (::PopupAllowedForEvent("submit")) + if (PopupAllowedForEvent("submit")) { abuse = openControlled; + } break; case NS_FORM_RESET : - if (::PopupAllowedForEvent("reset")) + if (PopupAllowedForEvent("reset")) { abuse = openControlled; + } break; } } @@ -790,7 +802,7 @@ nsDOMEvent::GetEventPopupControlState(WidgetEvent* aEvent) // static void -nsDOMEvent::PopupAllowedEventsChanged() +Event::PopupAllowedEventsChanged() { if (sPopupAllowedEvents) { nsMemory::Free(sPopupAllowedEvents); @@ -805,7 +817,7 @@ nsDOMEvent::PopupAllowedEventsChanged() // static void -nsDOMEvent::Shutdown() +Event::Shutdown() { if (sPopupAllowedEvents) { nsMemory::Free(sPopupAllowedEvents); @@ -813,9 +825,9 @@ nsDOMEvent::Shutdown() } nsIntPoint -nsDOMEvent::GetScreenCoords(nsPresContext* aPresContext, - WidgetEvent* aEvent, - LayoutDeviceIntPoint aPoint) +Event::GetScreenCoords(nsPresContext* aPresContext, + WidgetEvent* aEvent, + LayoutDeviceIntPoint aPoint) { if (nsEventStateManager::sIsPointerLocked) { return nsEventStateManager::sLastScreenPoint; @@ -844,17 +856,15 @@ nsDOMEvent::GetScreenCoords(nsPresContext* aPresContext, nsPresContext::AppUnitsToIntCSSPixels(offset.y * factor)); } -//static +// static CSSIntPoint -nsDOMEvent::GetPageCoords(nsPresContext* aPresContext, - WidgetEvent* aEvent, - LayoutDeviceIntPoint aPoint, - CSSIntPoint aDefaultPoint) +Event::GetPageCoords(nsPresContext* aPresContext, + WidgetEvent* aEvent, + LayoutDeviceIntPoint aPoint, + CSSIntPoint aDefaultPoint) { - CSSIntPoint pagePoint = nsDOMEvent::GetClientCoords(aPresContext, - aEvent, - aPoint, - aDefaultPoint); + CSSIntPoint pagePoint = + Event::GetClientCoords(aPresContext, aEvent, aPoint, aDefaultPoint); // If there is some scrolling, add scroll info to client point. if (aPresContext && aPresContext->GetPresShell()) { @@ -870,10 +880,10 @@ nsDOMEvent::GetPageCoords(nsPresContext* aPresContext, // static CSSIntPoint -nsDOMEvent::GetClientCoords(nsPresContext* aPresContext, - WidgetEvent* aEvent, - LayoutDeviceIntPoint aPoint, - CSSIntPoint aDefaultPoint) +Event::GetClientCoords(nsPresContext* aPresContext, + WidgetEvent* aEvent, + LayoutDeviceIntPoint aPoint, + CSSIntPoint aDefaultPoint) { if (nsEventStateManager::sIsPointerLocked) { return nsEventStateManager::sLastClientPoint; @@ -908,10 +918,11 @@ nsDOMEvent::GetClientCoords(nsPresContext* aPresContext, return CSSIntPoint::FromAppUnitsRounded(pt); } -// To be called ONLY by nsDOMEvent::GetType (which has the additional +// To be called ONLY by Event::GetType (which has the additional // logic for handling user-defined events). // static -const char* nsDOMEvent::GetEventName(uint32_t aEventType) +const char* +Event::GetEventName(uint32_t aEventType) { switch(aEventType) { #define ID_TO_EVENT(name_, _id, _type, _struct) \ @@ -925,12 +936,12 @@ const char* nsDOMEvent::GetEventName(uint32_t aEventType) // create and that are not user defined events since this function and // SetEventType are incomplete. (But fixing that requires fixing the // arrays in nsEventListenerManager too, since the events for which - // this is a problem generally *are* created by nsDOMEvent.) + // this is a problem generally *are* created by Event.) return nullptr; } bool -nsDOMEvent::DefaultPrevented(JSContext* aCx) const +Event::DefaultPrevented(JSContext* aCx) const { MOZ_ASSERT(aCx, "JS context must be specified"); @@ -948,7 +959,7 @@ nsDOMEvent::DefaultPrevented(JSContext* aCx) const } bool -nsDOMEvent::GetPreventDefault() const +Event::GetPreventDefault() const { if (mOwner) { if (nsIDocument* doc = mOwner->GetExtantDoc()) { @@ -962,7 +973,7 @@ nsDOMEvent::GetPreventDefault() const } NS_IMETHODIMP -nsDOMEvent::GetPreventDefault(bool* aReturn) +Event::GetPreventDefault(bool* aReturn) { NS_ENSURE_ARG_POINTER(aReturn); *aReturn = GetPreventDefault(); @@ -970,7 +981,7 @@ nsDOMEvent::GetPreventDefault(bool* aReturn) } NS_IMETHODIMP -nsDOMEvent::GetDefaultPrevented(bool* aReturn) +Event::GetDefaultPrevented(bool* aReturn) { NS_ENSURE_ARG_POINTER(aReturn); // This method must be called by only event handlers implemented by C++. @@ -981,7 +992,7 @@ nsDOMEvent::GetDefaultPrevented(bool* aReturn) } NS_IMETHODIMP_(void) -nsDOMEvent::Serialize(IPC::Message* aMsg, bool aSerializeInterfaceType) +Event::Serialize(IPC::Message* aMsg, bool aSerializeInterfaceType) { if (aSerializeInterfaceType) { IPC::WriteParam(aMsg, NS_LITERAL_STRING("event")); @@ -999,7 +1010,7 @@ nsDOMEvent::Serialize(IPC::Message* aMsg, bool aSerializeInterfaceType) } NS_IMETHODIMP_(bool) -nsDOMEvent::Deserialize(const IPC::Message* aMsg, void** aIter) +Event::Deserialize(const IPC::Message* aMsg, void** aIter) { nsString type; NS_ENSURE_TRUE(IPC::ReadParam(aMsg, aIter, &type), false); @@ -1021,7 +1032,7 @@ nsDOMEvent::Deserialize(const IPC::Message* aMsg, void** aIter) } NS_IMETHODIMP_(void) -nsDOMEvent::SetOwner(mozilla::dom::EventTarget* aOwner) +Event::SetOwner(mozilla::dom::EventTarget* aOwner) { mOwner = nullptr; @@ -1057,12 +1068,18 @@ nsDOMEvent::SetOwner(mozilla::dom::EventTarget* aOwner) #endif } -nsresult NS_NewDOMEvent(nsIDOMEvent** aInstancePtrResult, - mozilla::dom::EventTarget* aOwner, - nsPresContext* aPresContext, - WidgetEvent* aEvent) +} // namespace dom +} // namespace mozilla + +using namespace mozilla; +using namespace mozilla::dom; + +nsresult +NS_NewDOMEvent(nsIDOMEvent** aInstancePtrResult, + EventTarget* aOwner, + nsPresContext* aPresContext, + WidgetEvent* aEvent) { - nsRefPtr it = - new nsDOMEvent(aOwner, aPresContext, aEvent); + Event* it = new Event(aOwner, aPresContext, aEvent); return CallQueryInterface(it, aInstancePtrResult); } diff --git a/dom/events/nsDOMEvent.h b/dom/events/Event.h similarity index 70% rename from dom/events/nsDOMEvent.h rename to dom/events/Event.h index c08fb65a6e2..19c4f71fae5 100644 --- a/dom/events/nsDOMEvent.h +++ b/dom/events/Event.h @@ -3,8 +3,8 @@ * 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 nsDOMEvent_h__ -#define nsDOMEvent_h__ +#ifndef mozilla_dom_Event_h_ +#define mozilla_dom_Event_h_ #include "mozilla/Attributes.h" #include "mozilla/BasicEvents.h" @@ -26,29 +26,31 @@ class nsPresContext; namespace mozilla { namespace dom { + class EventTarget; class ErrorEvent; -} -} // Dummy class so we can cast through it to get from nsISupports to -// nsDOMEvent subclasses with only two non-ambiguous static casts. -class nsDOMEventBase : public nsIDOMEvent +// Event subclasses with only two non-ambiguous static casts. +class EventBase : public nsIDOMEvent { }; -class nsDOMEvent : public nsDOMEventBase, - public nsWrapperCache +class Event : public EventBase, + public nsWrapperCache { public: - nsDOMEvent(mozilla::dom::EventTarget* aOwner, nsPresContext* aPresContext, - mozilla::WidgetEvent* aEvent); - nsDOMEvent(nsPIDOMWindow* aWindow); - virtual ~nsDOMEvent(); + Event(EventTarget* aOwner, + nsPresContext* aPresContext, + WidgetEvent* aEvent); + Event(nsPIDOMWindow* aWindow); + virtual ~Event(); + private: - void ConstructorInit(mozilla::dom::EventTarget* aOwner, + void ConstructorInit(EventTarget* aOwner, nsPresContext* aPresContext, - mozilla::WidgetEvent* aEvent); + WidgetEvent* aEvent); + public: void GetParentObject(nsIScriptGlobalObject** aParentObject) { @@ -59,7 +61,7 @@ public: } } - static nsDOMEvent* FromSupports(nsISupports* aSupports) + static Event* FromSupports(nsISupports* aSupports) { nsIDOMEvent* event = static_cast(aSupports); @@ -74,11 +76,11 @@ public: MOZ_ASSERT(target_qi == event, "Uh, fix QI!"); } #endif - return static_cast(event); + return static_cast(event); } NS_DECL_CYCLE_COLLECTING_ISUPPORTS - NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(nsDOMEvent) + NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(Event) nsISupports* GetParentObject() { @@ -88,10 +90,10 @@ public: virtual JSObject* WrapObject(JSContext* aCx, JS::Handle aScope) MOZ_OVERRIDE { - return mozilla::dom::EventBinding::Wrap(aCx, aScope, this); + return EventBinding::Wrap(aCx, aScope, this); } - virtual mozilla::dom::ErrorEvent* AsErrorEvent() + virtual ErrorEvent* AsErrorEvent() { return nullptr; } @@ -102,41 +104,37 @@ public: void InitPresContextData(nsPresContext* aPresContext); // Returns true if the event should be trusted. - bool Init(mozilla::dom::EventTarget* aGlobal); + bool Init(EventTarget* aGlobal); - static PopupControlState GetEventPopupControlState( - mozilla::WidgetEvent* aEvent); + static PopupControlState GetEventPopupControlState(WidgetEvent* aEvent); static void PopupAllowedEventsChanged(); static void Shutdown(); static const char* GetEventName(uint32_t aEventType); - static mozilla::CSSIntPoint - GetClientCoords(nsPresContext* aPresContext, - mozilla::WidgetEvent* aEvent, - mozilla::LayoutDeviceIntPoint aPoint, - mozilla::CSSIntPoint aDefaultPoint); - static mozilla::CSSIntPoint - GetPageCoords(nsPresContext* aPresContext, - mozilla::WidgetEvent* aEvent, - mozilla::LayoutDeviceIntPoint aPoint, - mozilla::CSSIntPoint aDefaultPoint); - static nsIntPoint - GetScreenCoords(nsPresContext* aPresContext, - mozilla::WidgetEvent* aEvent, - mozilla::LayoutDeviceIntPoint aPoint); + static CSSIntPoint GetClientCoords(nsPresContext* aPresContext, + WidgetEvent* aEvent, + LayoutDeviceIntPoint aPoint, + CSSIntPoint aDefaultPoint); + static CSSIntPoint GetPageCoords(nsPresContext* aPresContext, + WidgetEvent* aEvent, + LayoutDeviceIntPoint aPoint, + CSSIntPoint aDefaultPoint); + static nsIntPoint GetScreenCoords(nsPresContext* aPresContext, + WidgetEvent* aEvent, + LayoutDeviceIntPoint aPoint); - static already_AddRefed Constructor(const mozilla::dom::GlobalObject& aGlobal, - const nsAString& aType, - const mozilla::dom::EventInit& aParam, - mozilla::ErrorResult& aRv); + static already_AddRefed Constructor(const GlobalObject& aGlobal, + const nsAString& aType, + const EventInit& aParam, + ErrorResult& aRv); // Implemented as xpidl method // void GetType(nsString& aRetval) {} - mozilla::dom::EventTarget* GetTarget() const; - mozilla::dom::EventTarget* GetCurrentTarget() const; + EventTarget* GetTarget() const; + EventTarget* GetCurrentTarget() const; uint16_t EventPhase() const; @@ -196,13 +194,13 @@ public: } void InitEvent(const nsAString& aType, bool aBubbles, bool aCancelable, - mozilla::ErrorResult& aRv) + ErrorResult& aRv) { aRv = InitEvent(aType, aBubbles, aCancelable); } - mozilla::dom::EventTarget* GetOriginalTarget() const; - mozilla::dom::EventTarget* GetExplicitOriginalTarget() const; + EventTarget* GetOriginalTarget() const; + EventTarget* GetExplicitOriginalTarget() const; bool GetPreventDefault() const; @@ -228,15 +226,18 @@ protected: mozilla::WidgetEvent* mEvent; nsRefPtr mPresContext; - nsCOMPtr mExplicitOriginalTarget; + nsCOMPtr mExplicitOriginalTarget; nsCOMPtr mOwner; // nsPIDOMWindow for now. bool mEventIsInternal; bool mPrivateDataDuplicated; bool mIsMainThreadEvent; }; -#define NS_FORWARD_TO_NSDOMEVENT \ - NS_FORWARD_NSIDOMEVENT(nsDOMEvent::) +} // namespace dom +} // namespace mozilla + +#define NS_FORWARD_TO_EVENT \ + NS_FORWARD_NSIDOMEVENT(Event::) #define NS_FORWARD_NSIDOMEVENT_NO_SERIALIZATION_NO_DUPLICATION(_to) \ NS_IMETHOD GetType(nsAString& aType){ return _to GetType(aType); } \ @@ -257,24 +258,24 @@ protected: NS_IMETHOD GetIsTrusted(bool* aIsTrusted) { return _to GetIsTrusted(aIsTrusted); } \ NS_IMETHOD SetTarget(nsIDOMEventTarget *aTarget) { return _to SetTarget(aTarget); } \ NS_IMETHOD_(bool) IsDispatchStopped(void) { return _to IsDispatchStopped(); } \ - NS_IMETHOD_(mozilla::WidgetEvent*) GetInternalNSEvent(void) { return _to GetInternalNSEvent(); } \ + NS_IMETHOD_(WidgetEvent*) GetInternalNSEvent(void) { return _to GetInternalNSEvent(); } \ NS_IMETHOD_(void) SetTrusted(bool aTrusted) { _to SetTrusted(aTrusted); } \ - NS_IMETHOD_(void) SetOwner(mozilla::dom::EventTarget* aOwner) { _to SetOwner(aOwner); } \ - NS_IMETHOD_(nsDOMEvent *) InternalDOMEvent(void) { return _to InternalDOMEvent(); } + NS_IMETHOD_(void) SetOwner(EventTarget* aOwner) { _to SetOwner(aOwner); } \ + NS_IMETHOD_(Event*) InternalDOMEvent() { return _to InternalDOMEvent(); } -#define NS_FORWARD_TO_NSDOMEVENT_NO_SERIALIZATION_NO_DUPLICATION \ - NS_FORWARD_NSIDOMEVENT_NO_SERIALIZATION_NO_DUPLICATION(nsDOMEvent::) +#define NS_FORWARD_TO_EVENT_NO_SERIALIZATION_NO_DUPLICATION \ + NS_FORWARD_NSIDOMEVENT_NO_SERIALIZATION_NO_DUPLICATION(Event::) inline nsISupports* -ToSupports(nsDOMEvent* e) +ToSupports(mozilla::dom::Event* e) { return static_cast(e); } inline nsISupports* -ToCanonicalSupports(nsDOMEvent* e) +ToCanonicalSupports(mozilla::dom::Event* e) { return static_cast(e); } -#endif // nsDOMEvent_h__ +#endif // mozilla_dom_Event_h_ diff --git a/dom/events/EventTarget.h b/dom/events/EventTarget.h index 8ac04ba23f7..6ecf323fa0b 100644 --- a/dom/events/EventTarget.h +++ b/dom/events/EventTarget.h @@ -10,7 +10,6 @@ #include "nsWrapperCache.h" #include "nsIAtom.h" -class nsDOMEvent; class nsIDOMWindow; class nsIDOMEventListener; @@ -20,6 +19,7 @@ class ErrorResult; namespace dom { +class Event; class EventListener; class EventHandlerNonNull; template struct Nullable; @@ -48,7 +48,7 @@ public: EventListener* aCallback, bool aCapture, ErrorResult& aRv); - bool DispatchEvent(nsDOMEvent& aEvent, ErrorResult& aRv); + bool DispatchEvent(Event& aEvent, ErrorResult& aRv); // Note, this takes the type in onfoo form! EventHandlerNonNull* GetEventHandler(const nsAString& aType) diff --git a/dom/events/MessageEvent.cpp b/dom/events/MessageEvent.cpp index fd974df9aa4..9f78dce8ae0 100644 --- a/dom/events/MessageEvent.cpp +++ b/dom/events/MessageEvent.cpp @@ -18,34 +18,34 @@ namespace dom { NS_IMPL_CYCLE_COLLECTION_CLASS(MessageEvent) -NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(MessageEvent, nsDOMEvent) +NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(MessageEvent, Event) tmp->mData = JSVAL_VOID; NS_IMPL_CYCLE_COLLECTION_UNLINK(mWindowSource) NS_IMPL_CYCLE_COLLECTION_UNLINK(mPortSource) NS_IMPL_CYCLE_COLLECTION_UNLINK(mPorts) NS_IMPL_CYCLE_COLLECTION_UNLINK_END -NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(MessageEvent, nsDOMEvent) +NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(MessageEvent, Event) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mWindowSource) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPortSource) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPorts) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END -NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(MessageEvent, nsDOMEvent) +NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(MessageEvent, Event) NS_IMPL_CYCLE_COLLECTION_TRACE_JSVAL_MEMBER_CALLBACK(mData) NS_IMPL_CYCLE_COLLECTION_TRACE_END NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(MessageEvent) NS_INTERFACE_MAP_ENTRY(nsIDOMMessageEvent) -NS_INTERFACE_MAP_END_INHERITING(nsDOMEvent) +NS_INTERFACE_MAP_END_INHERITING(Event) -NS_IMPL_ADDREF_INHERITED(MessageEvent, nsDOMEvent) -NS_IMPL_RELEASE_INHERITED(MessageEvent, nsDOMEvent) +NS_IMPL_ADDREF_INHERITED(MessageEvent, Event) +NS_IMPL_RELEASE_INHERITED(MessageEvent, Event) MessageEvent::MessageEvent(EventTarget* aOwner, nsPresContext* aPresContext, WidgetEvent* aEvent) - : nsDOMEvent(aOwner, aPresContext, aEvent) + : Event(aOwner, aPresContext, aEvent) , mData(JSVAL_VOID) { } @@ -156,8 +156,7 @@ MessageEvent::Constructor(const GlobalObject& aGlobal, ports.AppendElement(aParam.mPorts.Value().Value()[i].get()); } - event->mPorts = new MessagePortList(static_cast(event), - ports); + event->mPorts = new MessagePortList(static_cast(event), ports); } return event.forget(); @@ -172,7 +171,7 @@ MessageEvent::InitMessageEvent(const nsAString& aType, const nsAString& aLastEventId, nsIDOMWindow* aSource) { - nsresult rv = nsDOMEvent::InitEvent(aType, aCanBubble, aCancelable); + nsresult rv = Event::InitEvent(aType, aCanBubble, aCancelable); NS_ENSURE_SUCCESS(rv, rv); mData = aData; diff --git a/dom/events/MessageEvent.h b/dom/events/MessageEvent.h index 70f557cb1d2..a83814e4718 100644 --- a/dom/events/MessageEvent.h +++ b/dom/events/MessageEvent.h @@ -6,9 +6,9 @@ #ifndef mozilla_dom_MessageEvent_h_ #define mozilla_dom_MessageEvent_h_ -#include "nsIDOMMessageEvent.h" -#include "nsDOMEvent.h" +#include "mozilla/dom/Event.h" #include "nsCycleCollectionParticipant.h" +#include "nsIDOMMessageEvent.h" namespace mozilla { namespace dom { @@ -26,7 +26,7 @@ class OwningWindowProxyOrMessagePort; * See http://www.whatwg.org/specs/web-apps/current-work/#messageevent for * further details. */ -class MessageEvent : public nsDOMEvent, +class MessageEvent : public Event, public nsIDOMMessageEvent { public: @@ -36,13 +36,12 @@ public: ~MessageEvent(); NS_DECL_ISUPPORTS_INHERITED - NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(MessageEvent, - nsDOMEvent) + NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(MessageEvent, Event) NS_DECL_NSIDOMMESSAGEEVENT // Forward to base class - NS_FORWARD_TO_NSDOMEVENT + NS_FORWARD_TO_EVENT virtual JSObject* WrapObject(JSContext* aCx, JS::Handle aScope) MOZ_OVERRIDE; diff --git a/dom/events/MouseEvent.cpp b/dom/events/MouseEvent.cpp index a2029a702d0..9f5571bcc6c 100644 --- a/dom/events/MouseEvent.cpp +++ b/dom/events/MouseEvent.cpp @@ -324,9 +324,7 @@ MouseEvent::GetScreenX(int32_t* aScreenX) int32_t MouseEvent::ScreenX() { - return nsDOMEvent::GetScreenCoords(mPresContext, - mEvent, - mEvent->refPoint).x; + return Event::GetScreenCoords(mPresContext, mEvent, mEvent->refPoint).x; } NS_IMETHODIMP @@ -340,9 +338,7 @@ MouseEvent::GetScreenY(int32_t* aScreenY) int32_t MouseEvent::ScreenY() { - return nsDOMEvent::GetScreenCoords(mPresContext, - mEvent, - mEvent->refPoint).y; + return Event::GetScreenCoords(mPresContext, mEvent, mEvent->refPoint).y; } @@ -357,10 +353,8 @@ MouseEvent::GetClientX(int32_t* aClientX) int32_t MouseEvent::ClientX() { - return nsDOMEvent::GetClientCoords(mPresContext, - mEvent, - mEvent->refPoint, - mClientPoint).x; + return Event::GetClientCoords(mPresContext, mEvent, mEvent->refPoint, + mClientPoint).x; } NS_IMETHODIMP @@ -374,10 +368,8 @@ MouseEvent::GetClientY(int32_t* aClientY) int32_t MouseEvent::ClientY() { - return nsDOMEvent::GetClientCoords(mPresContext, - mEvent, - mEvent->refPoint, - mClientPoint).y; + return Event::GetClientCoords(mPresContext, mEvent, mEvent->refPoint, + mClientPoint).y; } bool diff --git a/dom/events/MutationEvent.cpp b/dom/events/MutationEvent.cpp index d3a784eda54..54773e71d39 100644 --- a/dom/events/MutationEvent.cpp +++ b/dom/events/MutationEvent.cpp @@ -15,18 +15,18 @@ namespace dom { MutationEvent::MutationEvent(EventTarget* aOwner, nsPresContext* aPresContext, InternalMutationEvent* aEvent) - : nsDOMEvent(aOwner, aPresContext, - aEvent ? aEvent : new InternalMutationEvent(false, 0)) + : Event(aOwner, aPresContext, + aEvent ? aEvent : new InternalMutationEvent(false, 0)) { mEventIsInternal = (aEvent == nullptr); } NS_INTERFACE_MAP_BEGIN(MutationEvent) NS_INTERFACE_MAP_ENTRY(nsIDOMMutationEvent) -NS_INTERFACE_MAP_END_INHERITING(nsDOMEvent) +NS_INTERFACE_MAP_END_INHERITING(Event) -NS_IMPL_ADDREF_INHERITED(MutationEvent, nsDOMEvent) -NS_IMPL_RELEASE_INHERITED(MutationEvent, nsDOMEvent) +NS_IMPL_ADDREF_INHERITED(MutationEvent, Event) +NS_IMPL_RELEASE_INHERITED(MutationEvent, Event) already_AddRefed MutationEvent::GetRelatedNode() @@ -95,7 +95,7 @@ MutationEvent::InitMutationEvent(const nsAString& aTypeArg, const nsAString& aAttrNameArg, uint16_t aAttrChangeArg) { - nsresult rv = nsDOMEvent::InitEvent(aTypeArg, aCanBubbleArg, aCancelableArg); + nsresult rv = Event::InitEvent(aTypeArg, aCanBubbleArg, aCancelableArg); NS_ENSURE_SUCCESS(rv, rv); InternalMutationEvent* mutation = mEvent->AsMutationEvent(); diff --git a/dom/events/MutationEvent.h b/dom/events/MutationEvent.h index 4b18320abfa..869479a8678 100644 --- a/dom/events/MutationEvent.h +++ b/dom/events/MutationEvent.h @@ -6,16 +6,16 @@ #ifndef mozilla_dom_MutationEvent_h_ #define mozilla_dom_MutationEvent_h_ +#include "mozilla/EventForwards.h" +#include "mozilla/dom/Event.h" +#include "mozilla/dom/MutationEventBinding.h" #include "nsIDOMMutationEvent.h" #include "nsINode.h" -#include "nsDOMEvent.h" -#include "mozilla/dom/MutationEventBinding.h" -#include "mozilla/EventForwards.h" namespace mozilla { namespace dom { -class MutationEvent : public nsDOMEvent, +class MutationEvent : public Event, public nsIDOMMutationEvent { public: @@ -28,7 +28,7 @@ public: NS_DECL_NSIDOMMUTATIONEVENT // Forward to base class - NS_FORWARD_TO_NSDOMEVENT + NS_FORWARD_TO_EVENT virtual JSObject* WrapObject(JSContext* aCx, JS::Handle aScope) MOZ_OVERRIDE diff --git a/dom/events/NotifyAudioAvailableEvent.cpp b/dom/events/NotifyAudioAvailableEvent.cpp index 4f43f3fc338..e6fa57d6d3f 100644 --- a/dom/events/NotifyAudioAvailableEvent.cpp +++ b/dom/events/NotifyAudioAvailableEvent.cpp @@ -20,7 +20,7 @@ NotifyAudioAvailableEvent::NotifyAudioAvailableEvent( float* aFrameBuffer, uint32_t aFrameBufferLength, float aTime) - : nsDOMEvent(aOwner, aPresContext, aEvent) + : Event(aOwner, aPresContext, aEvent) , mFrameBuffer(aFrameBuffer) , mFrameBufferLength(aFrameBufferLength) , mTime(aTime) @@ -33,13 +33,13 @@ NotifyAudioAvailableEvent::NotifyAudioAvailableEvent( } } -NS_IMPL_ADDREF_INHERITED(NotifyAudioAvailableEvent, nsDOMEvent) -NS_IMPL_RELEASE_INHERITED(NotifyAudioAvailableEvent, nsDOMEvent) +NS_IMPL_ADDREF_INHERITED(NotifyAudioAvailableEvent, Event) +NS_IMPL_RELEASE_INHERITED(NotifyAudioAvailableEvent, Event) NS_IMPL_CYCLE_COLLECTION_CLASS(NotifyAudioAvailableEvent) NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(NotifyAudioAvailableEvent, - nsDOMEvent) + Event) if (tmp->mCachedArray) { tmp->mCachedArray = nullptr; DropJSObjects(tmp); @@ -47,17 +47,17 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(NotifyAudioAvailableEvent, NS_IMPL_CYCLE_COLLECTION_UNLINK_END NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(NotifyAudioAvailableEvent, - nsDOMEvent) + Event) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(NotifyAudioAvailableEvent, - nsDOMEvent) + Event) NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mCachedArray) NS_IMPL_CYCLE_COLLECTION_TRACE_END NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(NotifyAudioAvailableEvent) NS_INTERFACE_MAP_ENTRY(nsIDOMNotifyAudioAvailableEvent) -NS_INTERFACE_MAP_END_INHERITING(nsDOMEvent) +NS_INTERFACE_MAP_END_INHERITING(Event) NotifyAudioAvailableEvent::~NotifyAudioAvailableEvent() { @@ -117,7 +117,7 @@ NotifyAudioAvailableEvent::InitAudioAvailableEvent(const nsAString& aType, // that if we exit due to some error, the memory will be freed. Otherwise, // the framebuffer's memory will be freed when this event is destroyed. nsAutoArrayPtr frameBuffer(aFrameBuffer); - nsresult rv = nsDOMEvent::InitEvent(aType, aCanBubble, aCancelable); + nsresult rv = Event::InitEvent(aType, aCanBubble, aCancelable); NS_ENSURE_SUCCESS(rv, rv); mFrameBuffer = frameBuffer.forget(); diff --git a/dom/events/NotifyAudioAvailableEvent.h b/dom/events/NotifyAudioAvailableEvent.h index 6061288d4a4..74e183392b3 100644 --- a/dom/events/NotifyAudioAvailableEvent.h +++ b/dom/events/NotifyAudioAvailableEvent.h @@ -7,17 +7,17 @@ #ifndef mozilla_dom_NotifyAudioAvailableEvent_h_ #define mozilla_dom_NotifyAudioAvailableEvent_h_ -#include "nsIDOMNotifyAudioAvailableEvent.h" -#include "nsDOMEvent.h" -#include "nsCycleCollectionParticipant.h" +#include "mozilla/dom/Event.h" #include "mozilla/dom/NotifyAudioAvailableEventBinding.h" +#include "nsCycleCollectionParticipant.h" +#include "nsIDOMNotifyAudioAvailableEvent.h" class nsPresContext; namespace mozilla { namespace dom { -class NotifyAudioAvailableEvent : public nsDOMEvent, +class NotifyAudioAvailableEvent : public Event, public nsIDOMNotifyAudioAvailableEvent { public: @@ -31,10 +31,10 @@ public: NS_DECL_ISUPPORTS_INHERITED NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED( - NotifyAudioAvailableEvent, nsDOMEvent) + NotifyAudioAvailableEvent, Event) NS_DECL_NSIDOMNOTIFYAUDIOAVAILABLEEVENT - NS_FORWARD_NSIDOMEVENT(nsDOMEvent::) + NS_FORWARD_NSIDOMEVENT(Event::) ~NotifyAudioAvailableEvent(); diff --git a/dom/events/NotifyPaintEvent.cpp b/dom/events/NotifyPaintEvent.cpp index 4d9dc9e8ded..29b9eef326f 100644 --- a/dom/events/NotifyPaintEvent.cpp +++ b/dom/events/NotifyPaintEvent.cpp @@ -19,7 +19,7 @@ NotifyPaintEvent::NotifyPaintEvent(EventTarget* aOwner, WidgetEvent* aEvent, uint32_t aEventType, nsInvalidateRequestList* aInvalidateRequests) -: nsDOMEvent(aOwner, aPresContext, aEvent) + : Event(aOwner, aPresContext, aEvent) { if (mEvent) { mEvent->message = aEventType; @@ -31,10 +31,10 @@ NotifyPaintEvent::NotifyPaintEvent(EventTarget* aOwner, NS_INTERFACE_MAP_BEGIN(NotifyPaintEvent) NS_INTERFACE_MAP_ENTRY(nsIDOMNotifyPaintEvent) -NS_INTERFACE_MAP_END_INHERITING(nsDOMEvent) +NS_INTERFACE_MAP_END_INHERITING(Event) -NS_IMPL_ADDREF_INHERITED(NotifyPaintEvent, nsDOMEvent) -NS_IMPL_RELEASE_INHERITED(NotifyPaintEvent, nsDOMEvent) +NS_IMPL_ADDREF_INHERITED(NotifyPaintEvent, Event) +NS_IMPL_RELEASE_INHERITED(NotifyPaintEvent, Event) nsRegion NotifyPaintEvent::GetRegion() @@ -105,7 +105,7 @@ NotifyPaintEvent::GetPaintRequests(nsISupports** aResult) already_AddRefed NotifyPaintEvent::PaintRequests() { - nsDOMEvent* parent = this; + Event* parent = this; nsRefPtr requests = new nsPaintRequestList(parent); if (nsContentUtils::IsCallerChrome()) { @@ -127,7 +127,7 @@ NotifyPaintEvent::Serialize(IPC::Message* aMsg, IPC::WriteParam(aMsg, NS_LITERAL_STRING("notifypaintevent")); } - nsDOMEvent::Serialize(aMsg, false); + Event::Serialize(aMsg, false); uint32_t length = mInvalidateRequests.Length(); IPC::WriteParam(aMsg, length); @@ -140,7 +140,7 @@ NotifyPaintEvent::Serialize(IPC::Message* aMsg, NS_IMETHODIMP_(bool) NotifyPaintEvent::Deserialize(const IPC::Message* aMsg, void** aIter) { - NS_ENSURE_TRUE(nsDOMEvent::Deserialize(aMsg, aIter), false); + NS_ENSURE_TRUE(Event::Deserialize(aMsg, aIter), false); uint32_t length = 0; NS_ENSURE_TRUE(IPC::ReadParam(aMsg, aIter, &length), false); diff --git a/dom/events/NotifyPaintEvent.h b/dom/events/NotifyPaintEvent.h index 9f5f0996a70..b067fc498ae 100644 --- a/dom/events/NotifyPaintEvent.h +++ b/dom/events/NotifyPaintEvent.h @@ -7,10 +7,10 @@ #define mozilla_dom_NotifyPaintEvent_h_ #include "mozilla/Attributes.h" -#include "nsIDOMNotifyPaintEvent.h" -#include "nsDOMEvent.h" -#include "nsPresContext.h" +#include "mozilla/dom/Event.h" #include "mozilla/dom/NotifyPaintEventBinding.h" +#include "nsIDOMNotifyPaintEvent.h" +#include "nsPresContext.h" class nsPaintRequestList; @@ -20,7 +20,7 @@ namespace dom { class DOMRect; class DOMRectList; -class NotifyPaintEvent : public nsDOMEvent, +class NotifyPaintEvent : public Event, public nsIDOMNotifyPaintEvent { @@ -36,10 +36,10 @@ public: NS_DECL_NSIDOMNOTIFYPAINTEVENT // Forward to base class - NS_FORWARD_TO_NSDOMEVENT_NO_SERIALIZATION_NO_DUPLICATION + NS_FORWARD_TO_EVENT_NO_SERIALIZATION_NO_DUPLICATION NS_IMETHOD DuplicatePrivateData() MOZ_OVERRIDE { - return nsDOMEvent::DuplicatePrivateData(); + return Event::DuplicatePrivateData(); } NS_IMETHOD_(void) Serialize(IPC::Message* aMsg, bool aSerializeInterfaceType) MOZ_OVERRIDE; NS_IMETHOD_(bool) Deserialize(const IPC::Message* aMsg, void** aIter) MOZ_OVERRIDE; diff --git a/dom/events/ScrollAreaEvent.cpp b/dom/events/ScrollAreaEvent.cpp index 587fb54d3b4..89428dc68b0 100644 --- a/dom/events/ScrollAreaEvent.cpp +++ b/dom/events/ScrollAreaEvent.cpp @@ -70,7 +70,7 @@ ScrollAreaEvent::Serialize(IPC::Message* aMsg, IPC::WriteParam(aMsg, NS_LITERAL_STRING("scrollareaevent")); } - nsDOMEvent::Serialize(aMsg, false); + Event::Serialize(aMsg, false); IPC::WriteParam(aMsg, X()); IPC::WriteParam(aMsg, Y()); @@ -81,7 +81,7 @@ ScrollAreaEvent::Serialize(IPC::Message* aMsg, NS_IMETHODIMP_(bool) ScrollAreaEvent::Deserialize(const IPC::Message* aMsg, void** aIter) { - NS_ENSURE_TRUE(nsDOMEvent::Deserialize(aMsg, aIter), false); + NS_ENSURE_TRUE(Event::Deserialize(aMsg, aIter), false); float x, y, width, height; NS_ENSURE_TRUE(IPC::ReadParam(aMsg, aIter, &x), false); diff --git a/dom/events/ScrollAreaEvent.h b/dom/events/ScrollAreaEvent.h index dbd56468f20..7f9c180b479 100644 --- a/dom/events/ScrollAreaEvent.h +++ b/dom/events/ScrollAreaEvent.h @@ -30,10 +30,10 @@ public: NS_FORWARD_NSIDOMUIEVENT(UIEvent::) - NS_FORWARD_TO_NSDOMEVENT_NO_SERIALIZATION_NO_DUPLICATION + NS_FORWARD_TO_EVENT_NO_SERIALIZATION_NO_DUPLICATION NS_IMETHOD DuplicatePrivateData() { - return nsDOMEvent::DuplicatePrivateData(); + return Event::DuplicatePrivateData(); } NS_IMETHOD_(void) Serialize(IPC::Message* aMsg, bool aSerializeInterfaceType) MOZ_OVERRIDE; NS_IMETHOD_(bool) Deserialize(const IPC::Message* aMsg, void** aIter) MOZ_OVERRIDE; diff --git a/dom/events/SpeechRecognitionError.cpp b/dom/events/SpeechRecognitionError.cpp index 5befc62f2df..75e5c3f00ef 100644 --- a/dom/events/SpeechRecognitionError.cpp +++ b/dom/events/SpeechRecognitionError.cpp @@ -12,9 +12,10 @@ SpeechRecognitionError::SpeechRecognitionError( mozilla::dom::EventTarget* aOwner, nsPresContext* aPresContext, WidgetEvent* aEvent) -: nsDOMEvent(aOwner, aPresContext, aEvent), - mError() -{} + : Event(aOwner, aPresContext, aEvent) + , mError() +{ +} SpeechRecognitionError::~SpeechRecognitionError() {} @@ -40,7 +41,7 @@ SpeechRecognitionError::InitSpeechRecognitionError(const nsAString& aType, const nsAString& aMessage, ErrorResult& aRv) { - aRv = nsDOMEvent::InitEvent(aType, aCanBubble, aCancelable); + aRv = Event::InitEvent(aType, aCanBubble, aCancelable); NS_ENSURE_SUCCESS_VOID(aRv.ErrorCode()); mError = aError; diff --git a/dom/events/SpeechRecognitionError.h b/dom/events/SpeechRecognitionError.h index db1ea13b4cb..35cc2f10cf6 100644 --- a/dom/events/SpeechRecognitionError.h +++ b/dom/events/SpeechRecognitionError.h @@ -6,13 +6,13 @@ #ifndef SpeechRecognitionError_h__ #define SpeechRecognitionError_h__ -#include "nsDOMEvent.h" +#include "mozilla/dom/Event.h" #include "mozilla/dom/SpeechRecognitionErrorBinding.h" namespace mozilla { namespace dom { -class SpeechRecognitionError : public nsDOMEvent +class SpeechRecognitionError : public Event { public: SpeechRecognitionError(mozilla::dom::EventTarget* aOwner, diff --git a/dom/events/Touch.cpp b/dom/events/Touch.cpp index c5ef4f2ac87..f707d050924 100644 --- a/dom/events/Touch.cpp +++ b/dom/events/Touch.cpp @@ -106,13 +106,13 @@ Touch::InitializePoints(nsPresContext* aPresContext, WidgetEvent* aEvent) if (mPointsInitialized) { return; } - mClientPoint = nsDOMEvent::GetClientCoords( + mClientPoint = Event::GetClientCoords( aPresContext, aEvent, LayoutDeviceIntPoint::FromUntyped(mRefPoint), mClientPoint); - mPagePoint = nsDOMEvent::GetPageCoords( + mPagePoint = Event::GetPageCoords( aPresContext, aEvent, LayoutDeviceIntPoint::FromUntyped(mRefPoint), mClientPoint); - mScreenPoint = nsDOMEvent::GetScreenCoords(aPresContext, aEvent, + mScreenPoint = Event::GetScreenCoords(aPresContext, aEvent, LayoutDeviceIntPoint::FromUntyped(mRefPoint)); mPointsInitialized = true; } diff --git a/dom/events/TransitionEvent.cpp b/dom/events/TransitionEvent.cpp index dc016d633fa..24aa9cfdbc4 100644 --- a/dom/events/TransitionEvent.cpp +++ b/dom/events/TransitionEvent.cpp @@ -13,8 +13,8 @@ namespace dom { TransitionEvent::TransitionEvent(EventTarget* aOwner, nsPresContext* aPresContext, InternalTransitionEvent* aEvent) - : nsDOMEvent(aOwner, aPresContext, - aEvent ? aEvent : new InternalTransitionEvent(false, 0)) + : Event(aOwner, aPresContext, + aEvent ? aEvent : new InternalTransitionEvent(false, 0)) { if (aEvent) { mEventIsInternal = false; @@ -27,10 +27,10 @@ TransitionEvent::TransitionEvent(EventTarget* aOwner, NS_INTERFACE_MAP_BEGIN(TransitionEvent) NS_INTERFACE_MAP_ENTRY(nsIDOMTransitionEvent) -NS_INTERFACE_MAP_END_INHERITING(nsDOMEvent) +NS_INTERFACE_MAP_END_INHERITING(Event) -NS_IMPL_ADDREF_INHERITED(TransitionEvent, nsDOMEvent) -NS_IMPL_RELEASE_INHERITED(TransitionEvent, nsDOMEvent) +NS_IMPL_ADDREF_INHERITED(TransitionEvent, Event) +NS_IMPL_RELEASE_INHERITED(TransitionEvent, Event) // static already_AddRefed diff --git a/dom/events/TransitionEvent.h b/dom/events/TransitionEvent.h index 5bab83b8e05..194f6ba4629 100644 --- a/dom/events/TransitionEvent.h +++ b/dom/events/TransitionEvent.h @@ -5,17 +5,17 @@ #ifndef mozilla_dom_TransitionEvent_h_ #define mozilla_dom_TransitionEvent_h_ -#include "nsDOMEvent.h" -#include "nsIDOMTransitionEvent.h" #include "mozilla/EventForwards.h" +#include "mozilla/dom/Event.h" #include "mozilla/dom/TransitionEventBinding.h" +#include "nsIDOMTransitionEvent.h" class nsAString; namespace mozilla { namespace dom { -class TransitionEvent : public nsDOMEvent, +class TransitionEvent : public Event, public nsIDOMTransitionEvent { public: @@ -24,7 +24,7 @@ public: InternalTransitionEvent* aEvent); NS_DECL_ISUPPORTS_INHERITED - NS_FORWARD_TO_NSDOMEVENT + NS_FORWARD_TO_EVENT NS_DECL_NSIDOMTRANSITIONEVENT static already_AddRefed diff --git a/dom/events/UIEvent.cpp b/dom/events/UIEvent.cpp index d40b93cc42d..f634ec38977 100644 --- a/dom/events/UIEvent.cpp +++ b/dom/events/UIEvent.cpp @@ -26,8 +26,8 @@ namespace dom { UIEvent::UIEvent(EventTarget* aOwner, nsPresContext* aPresContext, WidgetGUIEvent* aEvent) - : nsDOMEvent(aOwner, aPresContext, - aEvent ? aEvent : new InternalUIEvent(false, 0)) + : Event(aOwner, aPresContext, + aEvent ? aEvent : new InternalUIEvent(false, 0)) , mClientPoint(0, 0) , mLayerPoint(0, 0) , mPagePoint(0, 0) @@ -94,15 +94,15 @@ UIEvent::Constructor(const GlobalObject& aGlobal, return e.forget(); } -NS_IMPL_CYCLE_COLLECTION_INHERITED_1(UIEvent, nsDOMEvent, +NS_IMPL_CYCLE_COLLECTION_INHERITED_1(UIEvent, Event, mView) -NS_IMPL_ADDREF_INHERITED(UIEvent, nsDOMEvent) -NS_IMPL_RELEASE_INHERITED(UIEvent, nsDOMEvent) +NS_IMPL_ADDREF_INHERITED(UIEvent, Event) +NS_IMPL_RELEASE_INHERITED(UIEvent, Event) NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(UIEvent) NS_INTERFACE_MAP_ENTRY(nsIDOMUIEvent) -NS_INTERFACE_MAP_END_INHERITING(nsDOMEvent) +NS_INTERFACE_MAP_END_INHERITING(Event) static nsIntPoint DevPixelsToCSSPixels(const LayoutDeviceIntPoint& aPoint, @@ -162,7 +162,7 @@ UIEvent::InitUIEvent(const nsAString& typeArg, nsCOMPtr view = do_QueryInterface(viewArg); NS_ENSURE_TRUE(view, NS_ERROR_INVALID_ARG); } - nsresult rv = nsDOMEvent::InitEvent(typeArg, canBubbleArg, cancelableArg); + nsresult rv = Event::InitEvent(typeArg, canBubbleArg, cancelableArg); NS_ENSURE_SUCCESS(rv, rv); mDetail = detailArg; @@ -186,10 +186,8 @@ UIEvent::PageX() const return mPagePoint.x; } - return nsDOMEvent::GetPageCoords(mPresContext, - mEvent, - mEvent->refPoint, - mClientPoint).x; + return Event::GetPageCoords(mPresContext, mEvent, mEvent->refPoint, + mClientPoint).x; } NS_IMETHODIMP @@ -207,10 +205,8 @@ UIEvent::PageY() const return mPagePoint.y; } - return nsDOMEvent::GetPageCoords(mPresContext, - mEvent, - mEvent->refPoint, - mClientPoint).y; + return Event::GetPageCoords(mPresContext, mEvent, mEvent->refPoint, + mClientPoint).y; } NS_IMETHODIMP @@ -360,21 +356,17 @@ UIEvent::IsChar() const NS_IMETHODIMP UIEvent::DuplicatePrivateData() { - mClientPoint = nsDOMEvent::GetClientCoords(mPresContext, - mEvent, - mEvent->refPoint, - mClientPoint); + mClientPoint = + Event::GetClientCoords(mPresContext, mEvent, mEvent->refPoint, + mClientPoint); mMovementPoint = GetMovementPoint(); mLayerPoint = GetLayerPoint(); - mPagePoint = nsDOMEvent::GetPageCoords(mPresContext, - mEvent, - mEvent->refPoint, - mClientPoint); + mPagePoint = + Event::GetPageCoords(mPresContext, mEvent, mEvent->refPoint, mClientPoint); // GetScreenPoint converts mEvent->refPoint to right coordinates. - nsIntPoint screenPoint = nsDOMEvent::GetScreenCoords(mPresContext, - mEvent, - mEvent->refPoint); - nsresult rv = nsDOMEvent::DuplicatePrivateData(); + nsIntPoint screenPoint = + Event::GetScreenCoords(mPresContext, mEvent, mEvent->refPoint); + nsresult rv = Event::DuplicatePrivateData(); if (NS_SUCCEEDED(rv)) { mEvent->refPoint = LayoutDeviceIntPoint::FromUntyped(screenPoint); } @@ -388,7 +380,7 @@ UIEvent::Serialize(IPC::Message* aMsg, bool aSerializeInterfaceType) IPC::WriteParam(aMsg, NS_LITERAL_STRING("uievent")); } - nsDOMEvent::Serialize(aMsg, false); + Event::Serialize(aMsg, false); int32_t detail = 0; GetDetail(&detail); @@ -398,7 +390,7 @@ UIEvent::Serialize(IPC::Message* aMsg, bool aSerializeInterfaceType) NS_IMETHODIMP_(bool) UIEvent::Deserialize(const IPC::Message* aMsg, void** aIter) { - NS_ENSURE_TRUE(nsDOMEvent::Deserialize(aMsg, aIter), false); + NS_ENSURE_TRUE(Event::Deserialize(aMsg, aIter), false); NS_ENSURE_TRUE(IPC::ReadParam(aMsg, aIter, &mDetail), false); return true; } diff --git a/dom/events/UIEvent.h b/dom/events/UIEvent.h index 87d0db49b38..82f68634052 100644 --- a/dom/events/UIEvent.h +++ b/dom/events/UIEvent.h @@ -7,19 +7,19 @@ #define mozilla_dom_UIEvent_h_ #include "mozilla/Attributes.h" -#include "nsIDOMUIEvent.h" -#include "nsDOMEvent.h" -#include "nsLayoutUtils.h" +#include "mozilla/dom/Event.h" #include "mozilla/dom/UIEventBinding.h" -#include "nsPresContext.h" #include "nsDeviceContext.h" +#include "nsIDOMUIEvent.h" +#include "nsLayoutUtils.h" +#include "nsPresContext.h" class nsINode; namespace mozilla { namespace dom { -class UIEvent : public nsDOMEvent, +class UIEvent : public Event, public nsIDOMUIEvent { public: @@ -28,13 +28,13 @@ public: WidgetGUIEvent* aEvent); NS_DECL_ISUPPORTS_INHERITED - NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(UIEvent, nsDOMEvent) + NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(UIEvent, Event) // nsIDOMUIEvent Interface NS_DECL_NSIDOMUIEVENT - // Forward to nsDOMEvent - NS_FORWARD_TO_NSDOMEVENT_NO_SERIALIZATION_NO_DUPLICATION + // Forward to Event + NS_FORWARD_TO_EVENT_NO_SERIALIZATION_NO_DUPLICATION NS_IMETHOD DuplicatePrivateData() MOZ_OVERRIDE; NS_IMETHOD_(void) Serialize(IPC::Message* aMsg, bool aSerializeInterfaceType) MOZ_OVERRIDE; NS_IMETHOD_(bool) Deserialize(const IPC::Message* aMsg, void** aIter) MOZ_OVERRIDE; @@ -175,7 +175,7 @@ protected: #define NS_FORWARD_TO_UIEVENT \ NS_FORWARD_NSIDOMUIEVENT(UIEvent::) \ - NS_FORWARD_TO_NSDOMEVENT_NO_SERIALIZATION_NO_DUPLICATION \ + NS_FORWARD_TO_EVENT_NO_SERIALIZATION_NO_DUPLICATION \ NS_IMETHOD DuplicatePrivateData() \ { \ return UIEvent::DuplicatePrivateData(); \ diff --git a/dom/events/XULCommandEvent.h b/dom/events/XULCommandEvent.h index 5d4702a26d9..c21d7c3185d 100644 --- a/dom/events/XULCommandEvent.h +++ b/dom/events/XULCommandEvent.h @@ -42,9 +42,9 @@ public: bool ShiftKey(); bool MetaKey(); - already_AddRefed GetSourceEvent() + already_AddRefed GetSourceEvent() { - nsRefPtr e = + nsRefPtr e = mSourceEvent ? mSourceEvent->InternalDOMEvent() : nullptr; return e.forget(); } @@ -55,7 +55,7 @@ public: int32_t aDetail, bool aCtrlKey, bool aAltKey, bool aShiftKey, bool aMetaKey, - nsDOMEvent* aSourceEvent, + Event* aSourceEvent, ErrorResult& aRv) { aRv = InitCommandEvent(aType, aCanBubble, aCancelable, aView, aDetail, diff --git a/dom/events/moz.build b/dom/events/moz.build index a53182737d7..14503654eeb 100644 --- a/dom/events/moz.build +++ b/dom/events/moz.build @@ -15,7 +15,6 @@ XPIDL_MODULE = 'content_events' EXPORTS += [ 'nsAsyncDOMEvent.h', - 'nsDOMEvent.h', 'nsDOMEventTargetHelper.h', 'nsDOMKeyNameList.h', 'nsEventDispatcher.h', @@ -41,6 +40,7 @@ EXPORTS.mozilla.dom += [ 'DataTransfer.h', 'DeviceMotionEvent.h', 'DragEvent.h', + 'Event.h', 'EventTarget.h', 'FocusEvent.h', 'KeyboardEvent.h', @@ -74,6 +74,7 @@ UNIFIED_SOURCES += [ 'DataTransfer.cpp', 'DeviceMotionEvent.cpp', 'DragEvent.cpp', + 'Event.cpp', 'EventTarget.cpp', 'FocusEvent.cpp', 'KeyboardEvent.cpp', @@ -85,7 +86,6 @@ UNIFIED_SOURCES += [ 'NotifyPaintEvent.cpp', 'nsAsyncDOMEvent.cpp', 'nsContentEventHandler.cpp', - 'nsDOMEvent.cpp', 'nsDOMEventTargetHelper.cpp', 'nsEventDispatcher.cpp', 'nsEventListenerManager.cpp', diff --git a/dom/events/nsAsyncDOMEvent.cpp b/dom/events/nsAsyncDOMEvent.cpp index 79bd7a1b547..aba5ae231c1 100644 --- a/dom/events/nsAsyncDOMEvent.cpp +++ b/dom/events/nsAsyncDOMEvent.cpp @@ -7,8 +7,8 @@ #include "nsIDOMEvent.h" #include "nsContentUtils.h" #include "nsEventDispatcher.h" -#include "nsDOMEvent.h" #include "mozilla/BasicEvents.h" +#include "mozilla/dom/Event.h" // for nsIDOMEvent::InternalDOMEvent() #include "mozilla/dom/EventTarget.h" using namespace mozilla; diff --git a/dom/events/nsEventDispatcher.cpp b/dom/events/nsEventDispatcher.cpp index f5b319bbb6d..af358db6617 100644 --- a/dom/events/nsEventDispatcher.cpp +++ b/dom/events/nsEventDispatcher.cpp @@ -610,7 +610,7 @@ nsEventDispatcher::Dispatch(nsISupports* aTarget, aEvent->mFlags.mDispatchedAtLeastOnce = true; if (!externalDOMEvent && preVisitor.mDOMEvent) { - // An nsDOMEvent was created while dispatching the event. + // An dom::Event was created while dispatching the event. // Duplicate private data if someone holds a pointer to it. nsrefcnt rc = 0; NS_RELEASE2(preVisitor.mDOMEvent, rc); diff --git a/dom/events/nsEventListenerManager.cpp b/dom/events/nsEventListenerManager.cpp index 66bb206eb97..fc367734646 100644 --- a/dom/events/nsEventListenerManager.cpp +++ b/dom/events/nsEventListenerManager.cpp @@ -13,7 +13,7 @@ #undef CreateEvent #include "nsISupports.h" -#include "nsDOMEvent.h" +#include "mozilla/dom/Event.h" #include "nsEventListenerManager.h" #include "nsIDOMEventListener.h" #include "nsGkAtoms.h" @@ -137,7 +137,7 @@ nsEventListenerManager::RemoveAllListeners() void nsEventListenerManager::Shutdown() { - nsDOMEvent::Shutdown(); + Event::Shutdown(); } NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(nsEventListenerManager, AddRef) @@ -991,7 +991,7 @@ nsEventListenerManager::HandleEventInternal(nsPresContext* aPresContext, nsAutoTObserverArray::EndLimitedIterator iter(mListeners); Maybe popupStatePusher; if (mIsMainThreadELM) { - popupStatePusher.construct(nsDOMEvent::GetEventPopupControlState(aEvent)); + popupStatePusher.construct(Event::GetEventPopupControlState(aEvent)); } bool hasListener = false; diff --git a/dom/events/nsEventStateManager.cpp b/dom/events/nsEventStateManager.cpp index 13e62dfc089..2c35bd5a565 100644 --- a/dom/events/nsEventStateManager.cpp +++ b/dom/events/nsEventStateManager.cpp @@ -10,6 +10,7 @@ #include "mozilla/MouseEvents.h" #include "mozilla/TextEvents.h" #include "mozilla/TouchEvents.h" +#include "mozilla/dom/Event.h" #include "mozilla/dom/TabParent.h" #include "mozilla/dom/UIEvent.h" @@ -25,7 +26,6 @@ #include "nsIWidget.h" #include "nsPresContext.h" #include "nsIPresShell.h" -#include "nsDOMEvent.h" #include "nsGkAtoms.h" #include "nsIFormControl.h" #include "nsIComboboxControlFrame.h" @@ -5918,7 +5918,7 @@ nsEventStateManager::Prefs::OnChange(const char* aPrefName, void*) { nsDependentCString prefName(aPrefName); if (prefName.EqualsLiteral("dom.popup_allowed_events")) { - nsDOMEvent::PopupAllowedEventsChanged(); + Event::PopupAllowedEventsChanged(); } } diff --git a/dom/events/nsEventStateManager.h b/dom/events/nsEventStateManager.h index 2086d209b7b..4b15b7ca434 100644 --- a/dom/events/nsEventStateManager.h +++ b/dom/events/nsEventStateManager.h @@ -219,13 +219,13 @@ public: // Holds the point in screen coords that a mouse event was dispatched to, // before we went into pointer lock mode. This is constantly updated while // the pointer is not locked, but we don't update it while the pointer is - // locked. This is used by nsDOMEvent::GetScreenCoords() to make mouse + // locked. This is used by dom::Event::GetScreenCoords() to make mouse // events' screen coord appear frozen at the last mouse position while // the pointer is locked. static nsIntPoint sLastScreenPoint; // Holds the point in client coords of the last mouse event. Used by - // nsDOMEvent::GetClientCoords() to make mouse events' client coords appear + // dom::Event::GetClientCoords() to make mouse events' client coords appear // frozen at the last mouse position while the pointer is locked. static mozilla::CSSIntPoint sLastClientPoint; diff --git a/dom/events/nsJSEventListener.cpp b/dom/events/nsJSEventListener.cpp index 0ca3ce277da..d589699d8c3 100644 --- a/dom/events/nsJSEventListener.cpp +++ b/dom/events/nsJSEventListener.cpp @@ -21,7 +21,6 @@ #include "mozilla/Likely.h" #include "mozilla/dom/ErrorEvent.h" #include "mozilla/dom/UnionTypes.h" -#include "nsDOMEvent.h" #ifdef DEBUG diff --git a/dom/file/LockedFile.cpp b/dom/file/LockedFile.cpp index 390673dfaf0..b6d5bd18066 100644 --- a/dom/file/LockedFile.cpp +++ b/dom/file/LockedFile.cpp @@ -7,6 +7,7 @@ #include "LockedFile.h" #include "nsIAppShell.h" +#include "nsIDOMEvent.h" #include "nsIDOMFile.h" #include "nsIFileStorage.h" #include "nsISeekableStream.h" @@ -15,7 +16,6 @@ #include "nsEventDispatcher.h" #include "nsNetUtil.h" #include "nsDOMClassInfoID.h" -#include "nsDOMEvent.h" #include "nsJSUtils.h" #include "nsStringStream.h" #include "nsWidgetsCID.h" diff --git a/dom/indexedDB/AsyncConnectionHelper.h b/dom/indexedDB/AsyncConnectionHelper.h index b461777e601..7ec764ce698 100644 --- a/dom/indexedDB/AsyncConnectionHelper.h +++ b/dom/indexedDB/AsyncConnectionHelper.h @@ -17,8 +17,6 @@ #include "nsIEventTarget.h" #include "nsIRunnable.h" -#include "nsDOMEvent.h" - class mozIStorageConnection; BEGIN_INDEXEDDB_NAMESPACE diff --git a/dom/indexedDB/IDBEvents.cpp b/dom/indexedDB/IDBEvents.cpp index f84192838ad..2eb99cef895 100644 --- a/dom/indexedDB/IDBEvents.cpp +++ b/dom/indexedDB/IDBEvents.cpp @@ -84,7 +84,7 @@ IDBVersionChangeEvent::CreateRunnableInternal(mozilla::dom::EventTarget* aTarget uint64_t aOldVersion, uint64_t aNewVersion) { - nsRefPtr event = + nsRefPtr event = CreateInternal(aTarget, aType, aOldVersion, aNewVersion); NS_ENSURE_TRUE(event, nullptr); @@ -92,9 +92,9 @@ IDBVersionChangeEvent::CreateRunnableInternal(mozilla::dom::EventTarget* aTarget return runnable.forget(); } -NS_IMPL_ADDREF_INHERITED(IDBVersionChangeEvent, nsDOMEvent) -NS_IMPL_RELEASE_INHERITED(IDBVersionChangeEvent, nsDOMEvent) +NS_IMPL_ADDREF_INHERITED(IDBVersionChangeEvent, Event) +NS_IMPL_RELEASE_INHERITED(IDBVersionChangeEvent, Event) NS_INTERFACE_MAP_BEGIN(IDBVersionChangeEvent) NS_INTERFACE_MAP_ENTRY(IDBVersionChangeEvent) -NS_INTERFACE_MAP_END_INHERITING(nsDOMEvent) +NS_INTERFACE_MAP_END_INHERITING(Event) diff --git a/dom/indexedDB/IDBEvents.h b/dom/indexedDB/IDBEvents.h index 90b8ba659b5..00deaefddcd 100644 --- a/dom/indexedDB/IDBEvents.h +++ b/dom/indexedDB/IDBEvents.h @@ -11,7 +11,7 @@ #include "nsIRunnable.h" -#include "nsDOMEvent.h" +#include "mozilla/dom/Event.h" #include "mozilla/dom/Nullable.h" #include "mozilla/dom/indexedDB/IDBObjectStore.h" #include "mozilla/dom/IDBVersionChangeEventBinding.h" @@ -46,11 +46,11 @@ CreateGenericEvent(mozilla::dom::EventTarget* aOwner, Bubbles aBubbles, Cancelable aCancelable); -class IDBVersionChangeEvent : public nsDOMEvent +class IDBVersionChangeEvent : public Event { public: NS_DECL_ISUPPORTS_INHERITED - NS_FORWARD_TO_NSDOMEVENT + NS_FORWARD_TO_EVENT NS_DECLARE_STATIC_IID_ACCESSOR(IDBVERSIONCHANGEEVENT_IID) virtual JSObject* WrapObject(JSContext* aCx, @@ -85,7 +85,7 @@ public: : mozilla::dom::Nullable(); } - inline static already_AddRefed + inline static already_AddRefed Create(mozilla::dom::EventTarget* aOwner, int64_t aOldVersion, int64_t aNewVersion) @@ -95,7 +95,7 @@ public: aOldVersion, aNewVersion); } - inline static already_AddRefed + inline static already_AddRefed CreateBlocked(mozilla::dom::EventTarget* aOwner, uint64_t aOldVersion, uint64_t aNewVersion) @@ -104,7 +104,7 @@ public: aOldVersion, aNewVersion); } - inline static already_AddRefed + inline static already_AddRefed CreateUpgradeNeeded(mozilla::dom::EventTarget* aOwner, uint64_t aOldVersion, uint64_t aNewVersion) @@ -136,7 +136,7 @@ public: protected: IDBVersionChangeEvent(mozilla::dom::EventTarget* aOwner) - : nsDOMEvent(aOwner, nullptr, nullptr) + : Event(aOwner, nullptr, nullptr) { SetIsDOMBinding(); } diff --git a/dom/indexedDB/OpenDatabaseHelper.cpp b/dom/indexedDB/OpenDatabaseHelper.cpp index 97b4e4b769d..8e5e44e4555 100644 --- a/dom/indexedDB/OpenDatabaseHelper.cpp +++ b/dom/indexedDB/OpenDatabaseHelper.cpp @@ -1672,7 +1672,7 @@ public: } // Otherwise fire a versionchange event. - nsRefPtr event = + nsRefPtr event = IDBVersionChangeEvent::Create(database, mOldVersion, mNewVersion); NS_ENSURE_TRUE(event, NS_ERROR_FAILURE); @@ -1684,7 +1684,7 @@ public: // then fire the blocked event. for (uint32_t index = 0; index < count; index++) { if (!mWaitingDatabases[index]->IsClosed()) { - nsRefPtr event = + nsRefPtr event = IDBVersionChangeEvent::CreateBlocked(mRequest, mOldVersion, mNewVersion); NS_ENSURE_TRUE(event, NS_ERROR_FAILURE); diff --git a/dom/indexedDB/ipc/IndexedDBChild.cpp b/dom/indexedDB/ipc/IndexedDBChild.cpp index 0c115e7fdd1..ae607556e27 100644 --- a/dom/indexedDB/ipc/IndexedDBChild.cpp +++ b/dom/indexedDB/ipc/IndexedDBChild.cpp @@ -141,7 +141,7 @@ public: return NS_OK; } - nsRefPtr event = + nsRefPtr event = IDBVersionChangeEvent::Create(mDatabase, mOldVersion, mNewVersion); MOZ_ASSERT(event); diff --git a/dom/interfaces/events/nsIDOMEvent.idl b/dom/interfaces/events/nsIDOMEvent.idl index f3eabd56c53..f3877bea387 100644 --- a/dom/interfaces/events/nsIDOMEvent.idl +++ b/dom/interfaces/events/nsIDOMEvent.idl @@ -8,7 +8,7 @@ interface nsIDOMEventTarget; [ptr] native WidgetEventPtr(mozilla::WidgetEvent); -[ptr] native nsDOMEventPtr(nsDOMEvent); +[ptr] native DOMEventPtr(mozilla::dom::Event); [ptr] native IPCMessagePtr(IPC::Message); [ptr] native ConstIPCMessagePtr(const IPC::Message); [ptr] native EventTargetPtr(mozilla::dom::EventTarget); @@ -18,7 +18,6 @@ interface nsIDOMEventTarget; #endif #include "mozilla/EventForwards.h" -class nsDOMEvent; class nsPresContext; class nsInvalidateRequestList; namespace IPC { @@ -26,6 +25,7 @@ class Message; } namespace mozilla { namespace dom { +class Event; class EventTarget; } // namespace dom } // namespace mozilla @@ -212,7 +212,7 @@ interface nsIDOMEvent : nsISupports in boolean aSerializeInterfaceType); [notxpcom] boolean Deserialize(in ConstIPCMessagePtr aMsg, out voidPtr aIter); [noscript,notxpcom] void SetOwner(in EventTargetPtr aOwner); - [notxpcom] nsDOMEventPtr InternalDOMEvent(); + [notxpcom] DOMEventPtr InternalDOMEvent(); }; dictionary EventInit diff --git a/dom/mobileconnection/src/MobileConnection.cpp b/dom/mobileconnection/src/MobileConnection.cpp index ec3a0938bcf..f15cebacd39 100644 --- a/dom/mobileconnection/src/MobileConnection.cpp +++ b/dom/mobileconnection/src/MobileConnection.cpp @@ -11,7 +11,6 @@ #include "mozilla/dom/MozOtaStatusEvent.h" #include "mozilla/dom/USSDReceivedEvent.h" #include "mozilla/Preferences.h" -#include "nsDOMEvent.h" #include "nsIDOMClassInfo.h" #include "nsIDOMDOMRequest.h" #include "nsIPermissionManager.h" diff --git a/dom/network/src/Connection.cpp b/dom/network/src/Connection.cpp index 338e69691a8..d1708f1ae69 100644 --- a/dom/network/src/Connection.cpp +++ b/dom/network/src/Connection.cpp @@ -9,7 +9,6 @@ #include "mozilla/dom/MozConnectionBinding.h" #include "nsIDOMClassInfo.h" #include "mozilla/Preferences.h" -#include "nsDOMEvent.h" #include "Constants.h" /** diff --git a/dom/power/WakeLock.cpp b/dom/power/WakeLock.cpp index a1842a2ba72..25b91faa817 100644 --- a/dom/power/WakeLock.cpp +++ b/dom/power/WakeLock.cpp @@ -5,10 +5,10 @@ #include "WakeLock.h" #include "mozilla/dom/ContentParent.h" +#include "mozilla/dom/Event.h" // for nsIDOMEvent::InternalDOMEvent() #include "mozilla/dom/MozWakeLockBinding.h" #include "mozilla/Hal.h" #include "mozilla/HalWakeLock.h" -#include "nsDOMEvent.h" #include "nsError.h" #include "nsIDocument.h" #include "nsIDOMWindow.h" diff --git a/dom/smil/TimeEvent.cpp b/dom/smil/TimeEvent.cpp index 65c0d37765c..a58375774b1 100644 --- a/dom/smil/TimeEvent.cpp +++ b/dom/smil/TimeEvent.cpp @@ -14,9 +14,9 @@ namespace dom { TimeEvent::TimeEvent(EventTarget* aOwner, nsPresContext* aPresContext, WidgetEvent* aEvent) - : nsDOMEvent(aOwner, aPresContext, - aEvent ? aEvent : new InternalUIEvent(false, 0)), - mDetail(0) + : Event(aOwner, aPresContext, + aEvent ? aEvent : new InternalUIEvent(false, 0)) + , mDetail(0) { SetIsDOMBinding(); if (aEvent) { @@ -44,15 +44,15 @@ TimeEvent::TimeEvent(EventTarget* aOwner, } } -NS_IMPL_CYCLE_COLLECTION_INHERITED_1(TimeEvent, nsDOMEvent, +NS_IMPL_CYCLE_COLLECTION_INHERITED_1(TimeEvent, Event, mView) -NS_IMPL_ADDREF_INHERITED(TimeEvent, nsDOMEvent) -NS_IMPL_RELEASE_INHERITED(TimeEvent, nsDOMEvent) +NS_IMPL_ADDREF_INHERITED(TimeEvent, Event) +NS_IMPL_RELEASE_INHERITED(TimeEvent, Event) NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(TimeEvent) NS_INTERFACE_MAP_ENTRY(nsIDOMTimeEvent) -NS_INTERFACE_MAP_END_INHERITING(nsDOMEvent) +NS_INTERFACE_MAP_END_INHERITING(Event) NS_IMETHODIMP TimeEvent::GetView(nsIDOMWindow** aView) @@ -74,8 +74,8 @@ TimeEvent::InitTimeEvent(const nsAString& aTypeArg, nsIDOMWindow* aViewArg, int32_t aDetailArg) { - nsresult rv = nsDOMEvent::InitEvent(aTypeArg, false /*doesn't bubble*/, - false /*can't cancel*/); + nsresult rv = Event::InitEvent(aTypeArg, false /*doesn't bubble*/, + false /*can't cancel*/); NS_ENSURE_SUCCESS(rv, rv); mDetail = aDetailArg; diff --git a/dom/smil/TimeEvent.h b/dom/smil/TimeEvent.h index a3cd91ca98f..7f0d60b1414 100644 --- a/dom/smil/TimeEvent.h +++ b/dom/smil/TimeEvent.h @@ -6,14 +6,14 @@ #ifndef mozilla_dom_TimeEvent_h_ #define mozilla_dom_TimeEvent_h_ -#include "nsIDOMTimeEvent.h" -#include "nsDOMEvent.h" +#include "mozilla/dom/Event.h" #include "mozilla/dom/TimeEventBinding.h" +#include "nsIDOMTimeEvent.h" namespace mozilla { namespace dom { -class TimeEvent MOZ_FINAL : public nsDOMEvent, +class TimeEvent MOZ_FINAL : public Event, public nsIDOMTimeEvent { public: @@ -23,13 +23,13 @@ public: // nsISupports interface: NS_DECL_ISUPPORTS_INHERITED - NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(TimeEvent, nsDOMEvent) + NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(TimeEvent, Event) // nsIDOMTimeEvent interface: NS_DECL_NSIDOMTIMEEVENT // Forward to base class - NS_FORWARD_TO_NSDOMEVENT + NS_FORWARD_TO_EVENT virtual JSObject* WrapObject(JSContext* aCx, JS::Handle aScope) MOZ_OVERRIDE diff --git a/dom/speakermanager/SpeakerManager.cpp b/dom/speakermanager/SpeakerManager.cpp index d9ba574a0e8..109202add12 100644 --- a/dom/speakermanager/SpeakerManager.cpp +++ b/dom/speakermanager/SpeakerManager.cpp @@ -4,12 +4,12 @@ #include "SpeakerManager.h" #include "nsIDOMClassInfo.h" +#include "nsIDOMEvent.h" #include "nsIDOMEventListener.h" #include "SpeakerManagerService.h" #include "nsIPermissionManager.h" #include "nsIInterfaceRequestorUtils.h" #include "nsIDocShell.h" -#include "nsDOMEvent.h" #include "AudioChannelService.h" using namespace mozilla::dom; diff --git a/dom/src/notification/Notification.cpp b/dom/src/notification/Notification.cpp index 37504d05126..c9dbaa9b88b 100644 --- a/dom/src/notification/Notification.cpp +++ b/dom/src/notification/Notification.cpp @@ -10,7 +10,6 @@ #include "mozilla/Preferences.h" #include "TabChild.h" #include "nsContentUtils.h" -#include "nsDOMEvent.h" #include "nsIAlertsService.h" #include "nsIAppsService.h" #include "nsIContentPermissionPrompt.h" diff --git a/dom/src/offline/nsDOMOfflineResourceList.cpp b/dom/src/offline/nsDOMOfflineResourceList.cpp index b2833bf18fa..1c94faad604 100644 --- a/dom/src/offline/nsDOMOfflineResourceList.cpp +++ b/dom/src/offline/nsDOMOfflineResourceList.cpp @@ -4,6 +4,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "nsDOMOfflineResourceList.h" +#include "nsIDOMEvent.h" #include "nsIScriptSecurityManager.h" #include "nsError.h" #include "mozilla/dom/DOMStringList.h" diff --git a/dom/src/offline/nsDOMOfflineResourceList.h b/dom/src/offline/nsDOMOfflineResourceList.h index 8a302673edb..715ef7ac3b7 100644 --- a/dom/src/offline/nsDOMOfflineResourceList.h +++ b/dom/src/offline/nsDOMOfflineResourceList.h @@ -19,7 +19,6 @@ #include "nsWeakReference.h" #include "nsCOMArray.h" #include "nsIDOMEventListener.h" -#include "nsDOMEvent.h" #include "nsIObserver.h" #include "nsIScriptContext.h" #include "nsCycleCollectionParticipant.h" diff --git a/dom/telephony/CallEvent.cpp b/dom/telephony/CallEvent.cpp index 5984f0372f9..472f590bf03 100644 --- a/dom/telephony/CallEvent.cpp +++ b/dom/telephony/CallEvent.cpp @@ -32,19 +32,19 @@ CallEvent::WrapObject(JSContext* aCx, JS::Handle aScope) NS_IMPL_CYCLE_COLLECTION_CLASS(CallEvent) -NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(CallEvent, nsDOMEvent) +NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(CallEvent, Event) NS_IMPL_CYCLE_COLLECTION_UNLINK(mCall) NS_IMPL_CYCLE_COLLECTION_UNLINK_END -NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(CallEvent, nsDOMEvent) +NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(CallEvent, Event) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCall) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END -NS_IMPL_ADDREF_INHERITED(CallEvent, nsDOMEvent) -NS_IMPL_RELEASE_INHERITED(CallEvent, nsDOMEvent) +NS_IMPL_ADDREF_INHERITED(CallEvent, Event) +NS_IMPL_RELEASE_INHERITED(CallEvent, Event) NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(CallEvent) -NS_INTERFACE_MAP_END_INHERITING(nsDOMEvent) +NS_INTERFACE_MAP_END_INHERITING(Event) // WebIDL diff --git a/dom/telephony/CallEvent.h b/dom/telephony/CallEvent.h index a87c3721255..6135d1ff5cd 100644 --- a/dom/telephony/CallEvent.h +++ b/dom/telephony/CallEvent.h @@ -7,23 +7,22 @@ #ifndef mozilla_dom_telephony_callevent_h #define mozilla_dom_telephony_callevent_h +#include "mozilla/dom/Event.h" #include "mozilla/dom/telephony/TelephonyCommon.h" -#include "nsDOMEvent.h" - namespace mozilla { namespace dom { struct CallEventInit; -class CallEvent MOZ_FINAL : public nsDOMEvent +class CallEvent MOZ_FINAL : public Event { nsRefPtr mCall; public: NS_DECL_ISUPPORTS_INHERITED - NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(CallEvent, nsDOMEvent) - NS_FORWARD_TO_NSDOMEVENT + NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(CallEvent, Event) + NS_FORWARD_TO_EVENT virtual JSObject* WrapObject(JSContext* aCx, JS::Handle aScope) MOZ_OVERRIDE; @@ -44,7 +43,7 @@ private: CallEvent(EventTarget* aOwner, nsPresContext* aPresContext, WidgetEvent* aEvent) - : nsDOMEvent(aOwner, aPresContext, aEvent) + : Event(aOwner, aPresContext, aEvent) { SetIsDOMBinding(); } diff --git a/dom/time/TimeChangeObserver.cpp b/dom/time/TimeChangeObserver.cpp index 2d74a7786b4..96c76e7f348 100644 --- a/dom/time/TimeChangeObserver.cpp +++ b/dom/time/TimeChangeObserver.cpp @@ -13,7 +13,6 @@ #include "mozilla/Services.h" #include "mozilla/StaticPtr.h" #include "nsPIDOMWindow.h" -#include "nsDOMEvent.h" #include "nsContentUtils.h" #include "nsIObserverService.h" #include "nsIDocument.h" diff --git a/dom/voicemail/Voicemail.h b/dom/voicemail/Voicemail.h index 5da306ea22c..6eb77dcf9ae 100644 --- a/dom/voicemail/Voicemail.h +++ b/dom/voicemail/Voicemail.h @@ -9,7 +9,6 @@ #include "mozilla/Attributes.h" #include "mozilla/ErrorResult.h" -#include "nsDOMEvent.h" #include "nsDOMEventTargetHelper.h" #include "nsIVoicemailProvider.h" diff --git a/dom/workers/MessagePort.cpp b/dom/workers/MessagePort.cpp index f476d79d0ab..800da33f31f 100644 --- a/dom/workers/MessagePort.cpp +++ b/dom/workers/MessagePort.cpp @@ -6,8 +6,8 @@ #include "MessagePort.h" #include "mozilla/dom/MessagePortBinding.h" -#include "nsDOMEvent.h" #include "nsEventDispatcher.h" +#include "nsIDOMEvent.h" #include "SharedWorker.h" #include "WorkerPrivate.h" diff --git a/dom/workers/SharedWorker.cpp b/dom/workers/SharedWorker.cpp index 9722556a6a5..63e691fe228 100644 --- a/dom/workers/SharedWorker.cpp +++ b/dom/workers/SharedWorker.cpp @@ -10,9 +10,9 @@ #include "mozilla/Preferences.h" #include "mozilla/dom/SharedWorkerBinding.h" #include "nsContentUtils.h" -#include "nsDOMEvent.h" #include "nsEventDispatcher.h" #include "nsIClassInfoImpl.h" +#include "nsIDOMEvent.h" #include "MessagePort.h" #include "RuntimeService.h" diff --git a/dom/xbl/nsXBLEventHandler.cpp b/dom/xbl/nsXBLEventHandler.cpp index 44dbf147456..000759150af 100644 --- a/dom/xbl/nsXBLEventHandler.cpp +++ b/dom/xbl/nsXBLEventHandler.cpp @@ -4,13 +4,13 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "nsCOMPtr.h" -#include "nsDOMEvent.h" #include "nsIAtom.h" #include "nsIDOMEventListener.h" #include "nsIDOMKeyEvent.h" #include "nsIDOMMouseEvent.h" #include "nsXBLPrototypeHandler.h" #include "nsContentUtils.h" +#include "mozilla/dom/Event.h" // for nsIDOMEvent::InternalDOMEvent() #include "mozilla/dom/EventTarget.h" using namespace mozilla::dom; diff --git a/dom/xbl/nsXBLService.cpp b/dom/xbl/nsXBLService.cpp index fb6bd1f35c3..e6d41da056e 100644 --- a/dom/xbl/nsXBLService.cpp +++ b/dom/xbl/nsXBLService.cpp @@ -45,16 +45,16 @@ #include "nsIScriptSecurityManager.h" #include "nsIScriptError.h" #include "nsXBLSerialize.h" -#include "nsDOMEvent.h" #include "nsEventListenerManager.h" #ifdef MOZ_XUL #include "nsXULPrototypeCache.h" #endif #include "nsIDOMEventListener.h" -#include "mozilla/Preferences.h" -#include "mozilla/dom/Element.h" #include "mozilla/Attributes.h" +#include "mozilla/Preferences.h" +#include "mozilla/dom/Event.h" +#include "mozilla/dom/Element.h" using namespace mozilla; using namespace mozilla::dom; @@ -287,7 +287,7 @@ nsXBLStreamListener::HandleEvent(nsIDOMEvent* aEvent) // Get the binding document; note that we don't hold onto it in this object // to avoid creating a cycle - nsDOMEvent* event = aEvent->InternalDOMEvent(); + Event* event = aEvent->InternalDOMEvent(); EventTarget* target = event->GetCurrentTarget(); nsCOMPtr bindingDocument = do_QueryInterface(target); NS_ASSERTION(bindingDocument, "Event not targeted at document?!"); diff --git a/embedding/browser/webBrowser/nsDocShellTreeOwner.cpp b/embedding/browser/webBrowser/nsDocShellTreeOwner.cpp index fd498fb203c..d9cc265ae1f 100644 --- a/embedding/browser/webBrowser/nsDocShellTreeOwner.cpp +++ b/embedding/browser/webBrowser/nsDocShellTreeOwner.cpp @@ -65,7 +65,7 @@ #include "nsIDOMDragEvent.h" #include "nsIConstraintValidation.h" #include "mozilla/Attributes.h" -#include "nsDOMEvent.h" +#include "mozilla/dom/Event.h" // for nsIDOMEvent::InternalDOMEvent() using namespace mozilla; using namespace mozilla::dom; diff --git a/embedding/components/windowwatcher/src/nsAutoWindowStateHelper.cpp b/embedding/components/windowwatcher/src/nsAutoWindowStateHelper.cpp index a3cae9a111b..7b00e8149f6 100644 --- a/embedding/components/windowwatcher/src/nsAutoWindowStateHelper.cpp +++ b/embedding/components/windowwatcher/src/nsAutoWindowStateHelper.cpp @@ -5,7 +5,7 @@ #include "nsAutoWindowStateHelper.h" -#include "nsDOMEvent.h" +#include "mozilla/dom/Event.h" #include "nsIDocument.h" #include "nsIDOMEvent.h" #include "nsIDOMWindow.h" @@ -59,7 +59,7 @@ nsAutoWindowStateHelper::DispatchEventToChrome(const char *aEventName) } ErrorResult rv; - nsRefPtr event = doc->CreateEvent(NS_LITERAL_STRING("Events"), rv); + nsRefPtr event = doc->CreateEvent(NS_LITERAL_STRING("Events"), rv); if (rv.Failed()) { return false; } diff --git a/js/xpconnect/src/event_impl_gen.py b/js/xpconnect/src/event_impl_gen.py index 280113ae588..7be9433a19f 100644 --- a/js/xpconnect/src/event_impl_gen.py +++ b/js/xpconnect/src/event_impl_gen.py @@ -58,10 +58,7 @@ def firstCap(str): return str[0].upper() + str[1:] def getBaseName(iface): - basename = ("%s" % iface.base[6:]) - if (basename == "Event"): - basename = "nsDOMEvent" - return basename + return ("%s" % iface.base[6:]) def print_header_file(fd, conf): fd.write("#ifndef _gen_mozilla_idl_generated_events_h_\n" @@ -88,7 +85,7 @@ def print_classes_file(fd, conf): fd.write("#ifndef _gen_mozilla_idl_generated_event_declarations_h_\n") fd.write("#define _gen_mozilla_idl_generated_event_declarations_h_\n\n") - fd.write("#include \"nsDOMEvent.h\"\n"); + fd.write("#include \"mozilla/dom/Event.h\"\n"); includes = [] for s in conf.special_includes: if not s in includes: @@ -154,12 +151,10 @@ def print_class_declaration(eventname, iface, fd, conf): fd.write(" virtual ~%s();\n\n" % classname) fd.write(" NS_DECL_ISUPPORTS_INHERITED\n") fd.write(" NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(%s, %s)\n" % (classname, basename)) - fd.write(" NS_FORWARD_TO_NSDOMEVENT\n") + fd.write(" NS_FORWARD_TO_EVENT\n") for baseiface in baseinterfaces: baseimpl = ("%s" % baseiface.name[6:]) - if (baseimpl == "Event"): - baseimpl = "nsDOMEvent" fd.write(" NS_FORWARD_%s(%s::)\n" % (baseiface.name.upper(), baseimpl)) fd.write(" NS_DECL_%s\n" % iface.name.upper()) @@ -251,7 +246,7 @@ def print_cpp_file(fd, conf): fd.write("/* THIS FILE IS AUTOGENERATED - DO NOT EDIT */\n\n") fd.write('#include "GeneratedEventClasses.h"\n') fd.write('#include "xpcprivate.h"\n'); - fd.write('#include "nsDOMEvent.h"\n'); + fd.write('#include "mozilla/dom/Event.h"\n'); fd.write('#include "mozilla/dom/EventTarget.h"\n'); for e in conf.simple_events: diff --git a/js/xpconnect/src/nsDOMQS.h b/js/xpconnect/src/nsDOMQS.h index 98fe9a56c49..0e3827460a7 100644 --- a/js/xpconnect/src/nsDOMQS.h +++ b/js/xpconnect/src/nsDOMQS.h @@ -16,7 +16,7 @@ #include "nsHTMLDocument.h" #include "nsICSSDeclaration.h" #include "nsSVGElement.h" -#include "nsDOMEvent.h" +#include "mozilla/dom/Event.h" #include "mozilla/dom/UIEvent.h" #include "mozilla/dom/MouseEvent.h" #include "mozilla/dom/EventTargetBinding.h" @@ -57,7 +57,7 @@ NEW_BINDING(nsIDocument, Document); NEW_BINDING(nsDocument, Document); NEW_BINDING(nsHTMLDocument, HTMLDocument); NEW_BINDING(nsSVGElement, SVGElement); -NEW_BINDING(nsDOMEvent, Event); +NEW_BINDING(mozilla::dom::Event, Event); NEW_BINDING(mozilla::dom::UIEvent, UIEvent); NEW_BINDING(mozilla::dom::MouseEvent, MouseEvent); diff --git a/layout/base/nsPresShell.cpp b/layout/base/nsPresShell.cpp index 34a97136b48..0ea8ca05dfd 100644 --- a/layout/base/nsPresShell.cpp +++ b/layout/base/nsPresShell.cpp @@ -40,6 +40,7 @@ #include "nsPresContext.h" #include "nsIContent.h" #include "mozilla/dom/Element.h" +#include "mozilla/dom/Event.h" // for Event::GetEventPopupControlState() #include "mozilla/dom/ShadowRoot.h" #include "nsIDocument.h" #include "nsCSSStyleSheet.h" @@ -55,7 +56,6 @@ #include "nsTArray.h" #include "nsCOMArray.h" #include "nsContainerFrame.h" -#include "nsDOMEvent.h" #include "nsISelection.h" #include "mozilla/Selection.h" #include "nsGkAtoms.h" @@ -7213,7 +7213,8 @@ PresShell::HandleEventInternal(WidgetEvent* aEvent, nsEventStatus* aStatus) nsEventStateManager::GetActiveEventStateManager() == manager); } - nsAutoPopupStatePusher popupStatePusher(nsDOMEvent::GetEventPopupControlState(aEvent)); + nsAutoPopupStatePusher popupStatePusher( + Event::GetEventPopupControlState(aEvent)); // FIXME. If the event was reused, we need to clear the old target, // bug 329430 diff --git a/layout/generic/nsImageMap.cpp b/layout/generic/nsImageMap.cpp index 8d7133b281c..5fd24485d20 100644 --- a/layout/generic/nsImageMap.cpp +++ b/layout/generic/nsImageMap.cpp @@ -7,12 +7,12 @@ #include "nsImageMap.h" +#include "mozilla/dom/Element.h" +#include "mozilla/dom/Event.h" // for nsIDOMEvent::InternalDOMEvent() #include "nsString.h" -#include "nsDOMEvent.h" #include "nsReadableUtils.h" #include "nsRenderingContext.h" #include "nsPresContext.h" -#include "mozilla/dom/Element.h" #include "nsNameSpaceManager.h" #include "nsGkAtoms.h" #include "nsImageFrame.h" diff --git a/layout/printing/nsPrintPreviewListener.cpp b/layout/printing/nsPrintPreviewListener.cpp index 33cc2c317c4..14393b0d54f 100644 --- a/layout/printing/nsPrintPreviewListener.cpp +++ b/layout/printing/nsPrintPreviewListener.cpp @@ -8,7 +8,7 @@ #include "mozilla/TextEvents.h" #include "mozilla/dom/Element.h" -#include "nsDOMEvent.h" +#include "mozilla/dom/Event.h" // for nsIDOMEvent::InternalDOMEvent() #include "nsIDOMWindow.h" #include "nsPIDOMWindow.h" #include "nsIDOMElement.h" diff --git a/layout/xul/nsXULPopupManager.cpp b/layout/xul/nsXULPopupManager.cpp index c0ec0bbcfa9..8e56d26c6da 100644 --- a/layout/xul/nsXULPopupManager.cpp +++ b/layout/xul/nsXULPopupManager.cpp @@ -12,7 +12,6 @@ #include "nsMenuBarListener.h" #include "nsContentUtils.h" #include "nsIDOMDocument.h" -#include "nsDOMEvent.h" #include "nsIDOMEvent.h" #include "nsIDOMXULElement.h" #include "nsIXULDocument.h" @@ -37,6 +36,7 @@ #include "nsFrameManager.h" #include "nsIObserverService.h" #include "mozilla/dom/Element.h" +#include "mozilla/dom/Event.h" // for nsIDOMEvent::InternalDOMEvent() #include "mozilla/LookAndFeel.h" #include "mozilla/MouseEvents.h" #include "mozilla/Services.h" diff --git a/layout/xul/nsXULTooltipListener.cpp b/layout/xul/nsXULTooltipListener.cpp index 6a85bc2544b..421b87cb884 100644 --- a/layout/xul/nsXULTooltipListener.cpp +++ b/layout/xul/nsXULTooltipListener.cpp @@ -5,7 +5,6 @@ #include "nsXULTooltipListener.h" -#include "nsDOMEvent.h" #include "nsIDOMMouseEvent.h" #include "nsIDOMXULDocument.h" #include "nsIDOMXULElement.h" @@ -30,6 +29,7 @@ #include "mozilla/Preferences.h" #include "mozilla/LookAndFeel.h" #include "mozilla/dom/Element.h" +#include "mozilla/dom/Event.h" // for nsIDOMEvent::InternalDOMEvent() using namespace mozilla; using namespace mozilla::dom; diff --git a/toolkit/components/satchel/nsFormFillController.cpp b/toolkit/components/satchel/nsFormFillController.cpp index 54a3a871296..4c6ac393a19 100644 --- a/toolkit/components/satchel/nsFormFillController.cpp +++ b/toolkit/components/satchel/nsFormFillController.cpp @@ -5,6 +5,8 @@ #include "nsFormFillController.h" +#include "mozilla/dom/Element.h" +#include "mozilla/dom/Event.h" // for nsIDOMEvent::InternalDOMEvent() #include "nsIFormAutoComplete.h" #include "nsIInputListAutoComplete.h" #include "nsIAutoCompleteSimpleResult.h" @@ -32,9 +34,7 @@ #include "nsToolkitCompsCID.h" #include "nsEmbedCID.h" #include "nsIDOMNSEditableElement.h" -#include "mozilla/dom/Element.h" #include "nsContentUtils.h" -#include "nsDOMEvent.h" #include "nsILoadContext.h" using namespace mozilla::dom; diff --git a/widget/BasicEvents.h b/widget/BasicEvents.h index ade6f311a0a..fd2f7e61996 100644 --- a/widget/BasicEvents.h +++ b/widget/BasicEvents.h @@ -499,20 +499,20 @@ public: // If mInSystemGroup is true, the event is being dispatched in system group. bool mInSystemGroup: 1; // If mCancelable is true, the event can be consumed. I.e., calling - // nsDOMEvent::PreventDefault() can prevent the default action. + // dom::Event::PreventDefault() can prevent the default action. bool mCancelable : 1; // If mBubbles is true, the event can bubble. Otherwise, cannot be handled // in bubbling phase. bool mBubbles : 1; - // If mPropagationStopped is true, nsDOMEvent::StopPropagation() or - // nsDOMEvent::StopImmediatePropagation() has been called. + // If mPropagationStopped is true, dom::Event::StopPropagation() or + // dom::Event::StopImmediatePropagation() has been called. bool mPropagationStopped : 1; // If mImmediatePropagationStopped is true, - // nsDOMEvent::StopImmediatePropagation() has been called. + // dom::Event::StopImmediatePropagation() has been called. // Note that mPropagationStopped must be true when this is true. bool mImmediatePropagationStopped : 1; // If mDefaultPrevented is true, the event has been consumed. - // E.g., nsDOMEvent::PreventDefault() has been called or + // E.g., dom::Event::PreventDefault() has been called or // the default action has been performed. bool mDefaultPrevented : 1; // If mDefaultPreventedByContent is true, the event has been diff --git a/widget/cocoa/nsMenuUtilsX.mm b/widget/cocoa/nsMenuUtilsX.mm index dcccc53b609..e55a50756cd 100644 --- a/widget/cocoa/nsMenuUtilsX.mm +++ b/widget/cocoa/nsMenuUtilsX.mm @@ -3,6 +3,7 @@ * 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 "mozilla/dom/Event.h" #include "nsMenuUtilsX.h" #include "nsMenuBarX.h" #include "nsMenuX.h" @@ -11,7 +12,6 @@ #include "nsObjCExceptions.h" #include "nsCocoaUtils.h" #include "nsCocoaWindow.h" -#include "nsDOMEvent.h" #include "nsGkAtoms.h" #include "nsIDocument.h" #include "nsIDOMDocument.h" @@ -27,7 +27,7 @@ void nsMenuUtilsX::DispatchCommandTo(nsIContent* aTargetContent) nsIDocument* doc = aTargetContent->OwnerDoc(); if (doc) { ErrorResult rv; - nsRefPtr event = + nsRefPtr event = doc->CreateEvent(NS_LITERAL_STRING("xulcommandevent"), rv); nsCOMPtr command = do_QueryObject(event); diff --git a/xpfe/appshell/src/nsXULWindow.cpp b/xpfe/appshell/src/nsXULWindow.cpp index 9f6f1d4358c..7153ebe6073 100644 --- a/xpfe/appshell/src/nsXULWindow.cpp +++ b/xpfe/appshell/src/nsXULWindow.cpp @@ -51,7 +51,6 @@ #include "nsPresContext.h" #include "nsContentUtils.h" #include "nsWebShellWindow.h" // get rid of this one, too... -#include "nsDOMEvent.h" #include "nsGlobalWindow.h" #include "prenv.h" @@ -59,6 +58,7 @@ #include "mozilla/Preferences.h" #include "mozilla/dom/BarProps.h" #include "mozilla/dom/Element.h" +#include "mozilla/dom/Event.h" #include "mozilla/dom/ScriptSettings.h" using namespace mozilla; @@ -230,7 +230,8 @@ NS_IMETHODIMP nsXULWindow::SetZLevel(uint32_t aLevel) nsCOMPtr doc = cv->GetDocument(); if (doc) { ErrorResult rv; - nsRefPtr event = doc->CreateEvent(NS_LITERAL_STRING("Events"),rv); + nsRefPtr event = + doc->CreateEvent(NS_LITERAL_STRING("Events"),rv); if (event) { event->InitEvent(NS_LITERAL_STRING("windowZLevel"), true, false); From bf09c6f469a05babf5f6128fe401678b01e0feaf Mon Sep 17 00:00:00 2001 From: Ehsan Akhgari Date: Tue, 4 Mar 2014 19:39:06 -0500 Subject: [PATCH 047/112] Bug 976896 - Port STL_FLAGS to moz.build; r=mshal --- b2g/app/Makefile.in | 2 -- b2g/app/moz.build | 2 ++ browser/app/Makefile.in | 2 -- browser/app/moz.build | 2 ++ build/stlport/Makefile.in | 1 - build/stlport/moz.build | 1 + build/unix/stdc++compat/Makefile.in | 1 - build/unix/stdc++compat/moz.build | 2 ++ config/config.mk | 4 ++-- dom/plugins/ipc/hangui/Makefile.in | 4 ---- dom/plugins/ipc/hangui/moz.build | 3 +++ dom/plugins/test/testplugin/testplugin.mk | 3 --- dom/plugins/test/testplugin/testplugin.mozbuild | 3 +++ embedding/tests/winEmbed/Makefile.in | 2 -- embedding/tests/winEmbed/moz.build | 2 ++ gfx/angle/src/libEGL/Makefile.in | 3 --- gfx/angle/src/libEGL/moz.build | 3 +++ gfx/angle/src/libGLESv2/Makefile.in | 3 --- gfx/angle/src/libGLESv2/moz.build | 3 +++ media/omx-plugin/Makefile.in | 3 --- media/omx-plugin/froyo/Makefile.in | 3 --- media/omx-plugin/froyo/moz.build | 2 ++ media/omx-plugin/gb/Makefile.in | 3 --- media/omx-plugin/gb/moz.build | 2 ++ media/omx-plugin/gb235/Makefile.in | 3 --- media/omx-plugin/gb235/moz.build | 2 ++ media/omx-plugin/hc/Makefile.in | 3 --- media/omx-plugin/hc/moz.build | 2 ++ media/omx-plugin/kk/Makefile.in | 3 --- media/omx-plugin/kk/moz.build | 2 ++ .../lib/froyo/libstagefright/Makefile.in | 3 --- .../lib/froyo/libstagefright/moz.build | 2 ++ .../omx-plugin/lib/gb/libstagefright/Makefile.in | 3 --- media/omx-plugin/lib/gb/libstagefright/moz.build | 2 ++ .../libstagefright_color_conversion/Makefile.in | 3 --- .../gb/libstagefright_color_conversion/moz.build | 2 ++ media/omx-plugin/lib/gb/libutils/Makefile.in | 16 ---------------- media/omx-plugin/lib/gb/libutils/moz.build | 2 ++ .../lib/gb235/libstagefright/Makefile.in | 3 --- .../lib/gb235/libstagefright/moz.build | 2 ++ .../omx-plugin/lib/hc/libstagefright/Makefile.in | 3 --- media/omx-plugin/lib/hc/libstagefright/moz.build | 2 ++ .../lib/ics/libstagefright/Makefile.in | 3 --- .../omx-plugin/lib/ics/libstagefright/moz.build | 2 ++ media/omx-plugin/lib/ics/libutils/Makefile.in | 16 ---------------- media/omx-plugin/lib/ics/libutils/moz.build | 2 ++ .../lib/ics/libvideoeditorplayer/Makefile.in | 3 --- .../lib/ics/libvideoeditorplayer/moz.build | 3 +++ media/omx-plugin/moz.build | 3 +++ memory/build/replace_malloc.h | 3 ++- memory/mozalloc/Makefile.in | 5 ----- memory/mozalloc/moz.build | 3 +++ memory/replace/defs.mk | 1 - memory/replace/dmd/Makefile.in | 2 -- memory/replace/dmd/moz.build | 2 ++ memory/replace/dummy/moz.build | 2 ++ memory/replace/jemalloc/moz.build | 2 ++ memory/replace/moz.build | 2 ++ mfbt/Makefile.in | 2 -- mfbt/moz.build | 2 ++ mfbt/tests/Makefile.in | 2 -- mfbt/tests/moz.build | 2 ++ mobile/android/app/Makefile.in | 2 -- mobile/android/app/moz.build | 1 + mozglue/android/Makefile.in | 2 -- mozglue/android/moz.build | 2 ++ mozglue/build/Makefile.in | 2 -- mozglue/build/moz.build | 1 + mozglue/linker/Makefile.in | 2 -- mozglue/linker/moz.build | 2 ++ mozglue/tests/Makefile.in | 2 -- mozglue/tests/moz.build | 1 + profile/dirserviceprovider/src/Makefile.in | 7 ------- profile/dirserviceprovider/src/moz.build | 2 ++ python/mozbuild/mozbuild/frontend/emitter.py | 1 + .../mozbuild/frontend/sandbox_symbols.py | 5 +++++ .../backend/data/variable_passthru/moz.build | 2 ++ .../mozbuild/test/backend/test_recursivemake.py | 3 +++ .../frontend/data/variable-passthru/moz.build | 2 ++ .../mozbuild/test/frontend/test_emitter.py | 1 + security/sandbox/Makefile.in | 1 - security/sandbox/moz.build | 2 ++ .../sandbox/win/src/sandboxbroker/Makefile.in | 1 - security/sandbox/win/src/sandboxbroker/moz.build | 1 + testing/mochitest/ssltunnel/Makefile.in | 4 ---- testing/mochitest/ssltunnel/moz.build | 4 ++++ .../components/maintenanceservice/Makefile.in | 1 - toolkit/components/maintenanceservice/moz.build | 2 ++ .../breakpad-windows-libxul/Makefile.in | 5 ----- .../breakpad-windows-libxul/moz.build | 2 ++ .../breakpad-windows-standalone/Makefile.in | 2 -- .../breakpad-windows-standalone/moz.build | 2 ++ toolkit/crashreporter/client/Makefile.in | 4 ---- toolkit/crashreporter/client/moz.build | 4 ++++ .../google-breakpad/src/common/linux/Makefile.in | 2 +- .../google-breakpad/src/common/linux/moz.build | 2 +- toolkit/crashreporter/injector/Makefile.in | 1 - toolkit/crashreporter/injector/moz.build | 2 ++ toolkit/mozapps/update/updater/Makefile.in | 1 - toolkit/mozapps/update/updater/moz.build | 1 + tools/trace-malloc/lib/Makefile.in | 6 ------ tools/trace-malloc/lib/moz.build | 2 ++ webapprt/gtk2/Makefile.in | 2 -- webapprt/gtk2/moz.build | 2 ++ webapprt/mac/Makefile.in | 2 -- webapprt/mac/moz.build | 2 ++ webapprt/win/Makefile.in | 2 -- webapprt/win/moz.build | 2 ++ widget/gonk/libdisplay/Makefile.in | 2 -- widget/gonk/libdisplay/moz.build | 2 ++ widget/gonk/nativewindow/Makefile.in | 16 ---------------- widget/gonk/nativewindow/moz.build | 2 ++ xpcom/glue/nomozalloc/Makefile.in | 3 --- xpcom/glue/nomozalloc/moz.build | 3 +++ xpcom/glue/standalone/Makefile.in | 3 --- xpcom/glue/standalone/moz.build | 2 ++ xpcom/glue/standalone/staticruntime/Makefile.in | 3 --- xpcom/glue/standalone/staticruntime/moz.build | 3 +++ xpcom/glue/staticruntime/Makefile.in | 3 --- xpcom/glue/staticruntime/moz.build | 3 +++ xulrunner/app/Makefile.in | 2 -- xulrunner/app/moz.build | 2 ++ xulrunner/stub/Makefile.in | 2 -- xulrunner/stub/moz.build | 2 ++ 124 files changed, 144 insertions(+), 192 deletions(-) delete mode 100644 media/omx-plugin/lib/gb/libutils/Makefile.in delete mode 100644 media/omx-plugin/lib/ics/libutils/Makefile.in delete mode 100644 profile/dirserviceprovider/src/Makefile.in delete mode 100644 toolkit/crashreporter/breakpad-windows-libxul/Makefile.in delete mode 100644 tools/trace-malloc/lib/Makefile.in delete mode 100644 widget/gonk/nativewindow/Makefile.in diff --git a/b2g/app/Makefile.in b/b2g/app/Makefile.in index e5c1683bc87..bf5568895bd 100644 --- a/b2g/app/Makefile.in +++ b/b2g/app/Makefile.in @@ -28,8 +28,6 @@ LIBS += \ endif endif -STL_FLAGS= - LIBS += $(JEMALLOC_LIBS) LIBS += \ diff --git a/b2g/app/moz.build b/b2g/app/moz.build index 37fa6189b5f..58c21fc4b22 100644 --- a/b2g/app/moz.build +++ b/b2g/app/moz.build @@ -41,3 +41,5 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk': ] LDFLAGS += ['-Wl,--export-dynamic'] + +DISABLE_STL_WRAPPING = True diff --git a/browser/app/Makefile.in b/browser/app/Makefile.in index 7bf91b613f7..f69dc7f3587 100644 --- a/browser/app/Makefile.in +++ b/browser/app/Makefile.in @@ -26,8 +26,6 @@ endif #} LIBXUL_SDK # Build a binary bootstrapping with XRE_main -STL_FLAGS= - LIBS += \ $(XPCOM_STANDALONE_GLUE_LDOPTS) \ $(NULL) diff --git a/browser/app/moz.build b/browser/app/moz.build index 24b862e3f3f..e8ff06ba896 100644 --- a/browser/app/moz.build +++ b/browser/app/moz.build @@ -52,3 +52,5 @@ if CONFIG['OS_ARCH'] == 'WINNT': # Set it to 256k. See bug 127069. if CONFIG['OS_ARCH'] == 'WINNT' and not CONFIG['GNU_CC']: LDFLAGS += ['/HEAP:0x40000'] + +DISABLE_STL_WRAPPING = True diff --git a/build/stlport/Makefile.in b/build/stlport/Makefile.in index 8093271d4e9..f0ea7da915b 100644 --- a/build/stlport/Makefile.in +++ b/build/stlport/Makefile.in @@ -3,7 +3,6 @@ # You can obtain one at http://mozilla.org/MPL/2.0/. MODULES = stlport -STL_FLAGS = # Force to build a static library, instead of a fake library, without # installing it in dist/lib. diff --git a/build/stlport/moz.build b/build/stlport/moz.build index 0a0be7c8be8..3d632754f69 100644 --- a/build/stlport/moz.build +++ b/build/stlport/moz.build @@ -52,3 +52,4 @@ LOCAL_INCLUDES += [ 'stlport', ] +DISABLE_STL_WRAPPING = True diff --git a/build/unix/stdc++compat/Makefile.in b/build/unix/stdc++compat/Makefile.in index b9ef76d1b6e..615af1b49f5 100644 --- a/build/unix/stdc++compat/Makefile.in +++ b/build/unix/stdc++compat/Makefile.in @@ -2,7 +2,6 @@ # 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/. -STL_FLAGS = NO_EXPAND_LIBS = 1 include $(topsrcdir)/config/rules.mk diff --git a/build/unix/stdc++compat/moz.build b/build/unix/stdc++compat/moz.build index 739879e83b1..d9247607920 100644 --- a/build/unix/stdc++compat/moz.build +++ b/build/unix/stdc++compat/moz.build @@ -17,3 +17,5 @@ if CONFIG['MOZ_LIBSTDCXX_HOST_VERSION']: FORCE_STATIC_LIB = True NO_PGO = True + +DISABLE_STL_WRAPPING = True diff --git a/config/config.mk b/config/config.mk index 50b9d9f340d..4873ef332e5 100644 --- a/config/config.mk +++ b/config/config.mk @@ -590,7 +590,7 @@ endif endif COMPILE_CFLAGS = $(VISIBILITY_FLAGS) $(DEFINES) $(INCLUDES) $(DSO_CFLAGS) $(DSO_PIC_CFLAGS) $(RTL_FLAGS) $(OS_CPPFLAGS) $(OS_COMPILE_CFLAGS) $(CFLAGS) $(MOZBUILD_CFLAGS) $(EXTRA_COMPILE_FLAGS) -COMPILE_CXXFLAGS = $(STL_FLAGS) $(VISIBILITY_FLAGS) $(DEFINES) $(INCLUDES) $(DSO_CFLAGS) $(DSO_PIC_CFLAGS) $(RTL_FLAGS) $(OS_CPPFLAGS) $(OS_COMPILE_CXXFLAGS) $(CXXFLAGS) $(MOZBUILD_CXXFLAGS) $(EXTRA_COMPILE_FLAGS) +COMPILE_CXXFLAGS = $(if $(DISABLE_STL_WRAPPING),,$(STL_FLAGS)) $(VISIBILITY_FLAGS) $(DEFINES) $(INCLUDES) $(DSO_CFLAGS) $(DSO_PIC_CFLAGS) $(RTL_FLAGS) $(OS_CPPFLAGS) $(OS_COMPILE_CXXFLAGS) $(CXXFLAGS) $(MOZBUILD_CXXFLAGS) $(EXTRA_COMPILE_FLAGS) COMPILE_CMFLAGS = $(OS_COMPILE_CMFLAGS) $(MOZBUILD_CMFLAGS) $(EXTRA_COMPILE_FLAGS) COMPILE_CMMFLAGS = $(OS_COMPILE_CMMFLAGS) $(MOZBUILD_CMMFLAGS) $(EXTRA_COMPILE_FLAGS) ASFLAGS += $(EXTRA_ASSEMBLER_FLAGS) @@ -900,7 +900,7 @@ DEFINES += -DUNICODE -D_UNICODE LOCAL_INCLUDES += -I'$(MOZ_DIRECTX_SDK_PATH)/include' endif -STL_FLAGS= +DISABLE_STL_WRAPPING := 1 # Skip most Mozilla-specific include locations. INCLUDES = -I. $(LOCAL_INCLUDES) -I$(DEPTH)/dist/include endif diff --git a/dom/plugins/ipc/hangui/Makefile.in b/dom/plugins/ipc/hangui/Makefile.in index 12b5a73b7a3..00bd5acfdf4 100644 --- a/dom/plugins/ipc/hangui/Makefile.in +++ b/dom/plugins/ipc/hangui/Makefile.in @@ -4,10 +4,6 @@ OS_LIBS = $(call EXPAND_LIBNAME,comctl32) -STL_FLAGS = \ - -D_HAS_EXCEPTIONS=0 \ - $(NULL) - MOZ_GLUE_LDFLAGS = include $(topsrcdir)/config/rules.mk diff --git a/dom/plugins/ipc/hangui/moz.build b/dom/plugins/ipc/hangui/moz.build index 8dc87816b88..0b2fc403a48 100644 --- a/dom/plugins/ipc/hangui/moz.build +++ b/dom/plugins/ipc/hangui/moz.build @@ -15,6 +15,9 @@ UNIFIED_SOURCES += [ include('/ipc/chromium/chromium-config.mozbuild') DEFINES['NS_NO_XPCOM'] = True +DEFINES['_HAS_EXCEPTIONS'] = 0 + +DISABLE_STL_WRAPPING = True if CONFIG['GNU_CC']: WIN32_EXE_LDFLAGS += ['-municode'] diff --git a/dom/plugins/test/testplugin/testplugin.mk b/dom/plugins/test/testplugin/testplugin.mk index 80a096afa0d..87fa2e37491 100644 --- a/dom/plugins/test/testplugin/testplugin.mk +++ b/dom/plugins/test/testplugin/testplugin.mk @@ -3,9 +3,6 @@ # 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/. -# Don't use STL wrappers; nptest isn't Gecko code -STL_FLAGS = - ifeq ($(MOZ_WIDGET_TOOLKIT),qt) include $(topsrcdir)/config/config.mk CXXFLAGS += $(MOZ_QT_CFLAGS) diff --git a/dom/plugins/test/testplugin/testplugin.mozbuild b/dom/plugins/test/testplugin/testplugin.mozbuild index ec506ba2fb0..97d41d69735 100644 --- a/dom/plugins/test/testplugin/testplugin.mozbuild +++ b/dom/plugins/test/testplugin/testplugin.mozbuild @@ -42,6 +42,9 @@ FORCE_SHARED_LIB = True # must link statically with the CRT; nptest isn't Gecko code USE_STATIC_LIBS = True +# Don't use STL wrappers; nptest isn't Gecko code +DISABLE_STL_WRAPPING = True + if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows': RCFILE = 'nptest.rc' RESFILE = 'nptest.res' diff --git a/embedding/tests/winEmbed/Makefile.in b/embedding/tests/winEmbed/Makefile.in index c4895ada9f9..25534b1ac87 100644 --- a/embedding/tests/winEmbed/Makefile.in +++ b/embedding/tests/winEmbed/Makefile.in @@ -32,8 +32,6 @@ LIBS = \ $(XPCOM_STANDALONE_GLUE_LDOPTS) \ $(NULL) -STL_FLAGS= - OS_LIBS += $(call EXPAND_LIBNAME,ole32 comdlg32 shell32 version) include $(topsrcdir)/config/rules.mk diff --git a/embedding/tests/winEmbed/moz.build b/embedding/tests/winEmbed/moz.build index 9d68e125d9b..350d9e430c3 100644 --- a/embedding/tests/winEmbed/moz.build +++ b/embedding/tests/winEmbed/moz.build @@ -31,3 +31,5 @@ else: # # Set it to 256k. See bug 127069. LDFLAGS += ['/HEAP:0x40000'] + +DISABLE_STL_WRAPPING = True diff --git a/gfx/angle/src/libEGL/Makefile.in b/gfx/angle/src/libEGL/Makefile.in index 26ee6635b2b..be9fc078ab7 100644 --- a/gfx/angle/src/libEGL/Makefile.in +++ b/gfx/angle/src/libEGL/Makefile.in @@ -2,9 +2,6 @@ # 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/. -# ANGLE uses the STL, so we can't use our derpy STL wrappers. -STL_FLAGS = - ifndef GNU_CC # Enable unwind semantics for exception handlers in response to warning C4530. OS_CPPFLAGS += -EHsc diff --git a/gfx/angle/src/libEGL/moz.build b/gfx/angle/src/libEGL/moz.build index fd61d51afa3..6890cf70ede 100644 --- a/gfx/angle/src/libEGL/moz.build +++ b/gfx/angle/src/libEGL/moz.build @@ -45,3 +45,6 @@ DEFINES['ANGLE_COMPILE_OPTIMIZATION_LEVEL'] = 'D3DCOMPILE_OPTIMIZATION_LEVEL1' RCFILE = SRCDIR + '/libEGL.rc' DEFFILE = SRCDIR + '/libEGL.def' + +# ANGLE uses the STL, so we can't use our derpy STL wrappers. +DISABLE_STL_WRAPPING = True diff --git a/gfx/angle/src/libGLESv2/Makefile.in b/gfx/angle/src/libGLESv2/Makefile.in index 00002a2b6b0..ae8cc4f944c 100644 --- a/gfx/angle/src/libGLESv2/Makefile.in +++ b/gfx/angle/src/libGLESv2/Makefile.in @@ -2,9 +2,6 @@ # 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/. -# ANGLE uses the STL, so we can't use our derpy STL wrappers. -STL_FLAGS = - ifndef GNU_CC # Enable unwind semantics for exception handlers in response to warning C4530. OS_CPPFLAGS += -EHsc diff --git a/gfx/angle/src/libGLESv2/moz.build b/gfx/angle/src/libGLESv2/moz.build index 5b55b960288..790dac06390 100644 --- a/gfx/angle/src/libGLESv2/moz.build +++ b/gfx/angle/src/libGLESv2/moz.build @@ -199,3 +199,6 @@ DEFINES['ANGLE_COMPILE_OPTIMIZATION_LEVEL'] = 'D3DCOMPILE_OPTIMIZATION_LEVEL1' RCFILE = SRCDIR + '/libGLESv2.rc' DEFFILE = SRCDIR + '/libGLESv2.def' + +# ANGLE uses the STL, so we can't use our derpy STL wrappers. +DISABLE_STL_WRAPPING = True diff --git a/media/omx-plugin/Makefile.in b/media/omx-plugin/Makefile.in index 812c1767b07..a8e3fd0a78f 100644 --- a/media/omx-plugin/Makefile.in +++ b/media/omx-plugin/Makefile.in @@ -12,9 +12,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -# Don't use STL wrappers; this isn't Gecko code -STL_FLAGS = - include $(topsrcdir)/config/rules.mk ifeq ($(MOZ_WIDGET_TOOLKIT),gonk) diff --git a/media/omx-plugin/froyo/Makefile.in b/media/omx-plugin/froyo/Makefile.in index 567cdff2f35..3ef91b2da64 100644 --- a/media/omx-plugin/froyo/Makefile.in +++ b/media/omx-plugin/froyo/Makefile.in @@ -12,9 +12,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -# Don't use STL wrappers; this isn't Gecko code -STL_FLAGS = - include $(topsrcdir)/config/rules.mk EXTRA_DSO_LDOPTS += \ diff --git a/media/omx-plugin/froyo/moz.build b/media/omx-plugin/froyo/moz.build index 4d51ea03cd9..f04155c4a03 100644 --- a/media/omx-plugin/froyo/moz.build +++ b/media/omx-plugin/froyo/moz.build @@ -18,3 +18,5 @@ LOCAL_INCLUDES += [ '../include/froyo/media/stagefright/openmax', ] +# Don't use STL wrappers; this isn't Gecko code +DISABLE_STL_WRAPPING = True diff --git a/media/omx-plugin/gb/Makefile.in b/media/omx-plugin/gb/Makefile.in index bf80ffc9b8e..6261176b211 100644 --- a/media/omx-plugin/gb/Makefile.in +++ b/media/omx-plugin/gb/Makefile.in @@ -12,9 +12,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -# Don't use STL wrappers; this isn't Gecko code -STL_FLAGS = - include $(topsrcdir)/config/rules.mk EXTRA_DSO_LDOPTS += \ diff --git a/media/omx-plugin/gb/moz.build b/media/omx-plugin/gb/moz.build index ff7024bd69e..3829c3b9c05 100644 --- a/media/omx-plugin/gb/moz.build +++ b/media/omx-plugin/gb/moz.build @@ -18,3 +18,5 @@ LOCAL_INCLUDES += [ '../include/gb/media/stagefright/openmax', ] +# Don't use STL wrappers; this isn't Gecko code +DISABLE_STL_WRAPPING = True diff --git a/media/omx-plugin/gb235/Makefile.in b/media/omx-plugin/gb235/Makefile.in index 83c23623a1b..6fda5a5639f 100644 --- a/media/omx-plugin/gb235/Makefile.in +++ b/media/omx-plugin/gb235/Makefile.in @@ -12,9 +12,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -# Don't use STL wrappers; this isn't Gecko code -STL_FLAGS = - include $(topsrcdir)/config/rules.mk EXTRA_DSO_LDOPTS += \ diff --git a/media/omx-plugin/gb235/moz.build b/media/omx-plugin/gb235/moz.build index 7089c67931d..fc2b8b76a46 100644 --- a/media/omx-plugin/gb235/moz.build +++ b/media/omx-plugin/gb235/moz.build @@ -18,3 +18,5 @@ LOCAL_INCLUDES += [ '../include/gb/media/stagefright/openmax', ] +# Don't use STL wrappers; this isn't Gecko code +DISABLE_STL_WRAPPING = True diff --git a/media/omx-plugin/hc/Makefile.in b/media/omx-plugin/hc/Makefile.in index 3b854cab30b..fe26b7596dc 100644 --- a/media/omx-plugin/hc/Makefile.in +++ b/media/omx-plugin/hc/Makefile.in @@ -12,9 +12,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -# Don't use STL wrappers; this isn't Gecko code -STL_FLAGS = - include $(topsrcdir)/config/rules.mk EXTRA_DSO_LDOPTS += \ diff --git a/media/omx-plugin/hc/moz.build b/media/omx-plugin/hc/moz.build index 16d7b373f43..513a554bfe9 100644 --- a/media/omx-plugin/hc/moz.build +++ b/media/omx-plugin/hc/moz.build @@ -18,3 +18,5 @@ LOCAL_INCLUDES += [ '../include/gb/media/stagefright/openmax', ] +# Don't use STL wrappers; this isn't Gecko code +DISABLE_STL_WRAPPING = True diff --git a/media/omx-plugin/kk/Makefile.in b/media/omx-plugin/kk/Makefile.in index 7c2a95e8cf7..9e6be39d253 100644 --- a/media/omx-plugin/kk/Makefile.in +++ b/media/omx-plugin/kk/Makefile.in @@ -12,9 +12,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -# Don't use STL wrappers; this isn't Gecko code -STL_FLAGS = - include $(topsrcdir)/config/rules.mk EXTRA_DSO_LDOPTS += \ diff --git a/media/omx-plugin/kk/moz.build b/media/omx-plugin/kk/moz.build index 88fde1abdfc..183965dd9d1 100644 --- a/media/omx-plugin/kk/moz.build +++ b/media/omx-plugin/kk/moz.build @@ -18,3 +18,5 @@ LOCAL_INCLUDES += [ '../include/ics/media/stagefright/openmax', ] +# Don't use STL wrappers; this isn't Gecko code +DISABLE_STL_WRAPPING = True diff --git a/media/omx-plugin/lib/froyo/libstagefright/Makefile.in b/media/omx-plugin/lib/froyo/libstagefright/Makefile.in index 0b840e60929..a6272b4ea70 100644 --- a/media/omx-plugin/lib/froyo/libstagefright/Makefile.in +++ b/media/omx-plugin/lib/froyo/libstagefright/Makefile.in @@ -12,9 +12,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -# Don't use STL wrappers; this isn't Gecko code -STL_FLAGS = - include $(topsrcdir)/config/rules.mk EXTRA_DSO_LDOPTS += \ diff --git a/media/omx-plugin/lib/froyo/libstagefright/moz.build b/media/omx-plugin/lib/froyo/libstagefright/moz.build index 9ea4c9e1fcd..cd9c2e48483 100644 --- a/media/omx-plugin/lib/froyo/libstagefright/moz.build +++ b/media/omx-plugin/lib/froyo/libstagefright/moz.build @@ -19,3 +19,5 @@ LOCAL_INCLUDES += [ '/media/omx-plugin/include/froyo/media/stagefright/openmax', ] +# Don't use STL wrappers; this isn't Gecko code +DISABLE_STL_WRAPPING = True diff --git a/media/omx-plugin/lib/gb/libstagefright/Makefile.in b/media/omx-plugin/lib/gb/libstagefright/Makefile.in index 0b840e60929..a6272b4ea70 100644 --- a/media/omx-plugin/lib/gb/libstagefright/Makefile.in +++ b/media/omx-plugin/lib/gb/libstagefright/Makefile.in @@ -12,9 +12,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -# Don't use STL wrappers; this isn't Gecko code -STL_FLAGS = - include $(topsrcdir)/config/rules.mk EXTRA_DSO_LDOPTS += \ diff --git a/media/omx-plugin/lib/gb/libstagefright/moz.build b/media/omx-plugin/lib/gb/libstagefright/moz.build index 35374f1b479..9adcb0ece2c 100644 --- a/media/omx-plugin/lib/gb/libstagefright/moz.build +++ b/media/omx-plugin/lib/gb/libstagefright/moz.build @@ -19,3 +19,5 @@ LOCAL_INCLUDES += [ '/media/omx-plugin/include/gb/media/stagefright/openmax', ] +# Don't use STL wrappers; this isn't Gecko code +DISABLE_STL_WRAPPING = True diff --git a/media/omx-plugin/lib/gb/libstagefright_color_conversion/Makefile.in b/media/omx-plugin/lib/gb/libstagefright_color_conversion/Makefile.in index 73c08c97b3c..0039e347ccd 100644 --- a/media/omx-plugin/lib/gb/libstagefright_color_conversion/Makefile.in +++ b/media/omx-plugin/lib/gb/libstagefright_color_conversion/Makefile.in @@ -12,9 +12,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -# Don't use STL wrappers; this isn't Gecko code -STL_FLAGS = - include $(topsrcdir)/config/rules.mk # EXTRA_DSO_LDOPTS += \ diff --git a/media/omx-plugin/lib/gb/libstagefright_color_conversion/moz.build b/media/omx-plugin/lib/gb/libstagefright_color_conversion/moz.build index b8ff7785dbc..94dd14641dd 100644 --- a/media/omx-plugin/lib/gb/libstagefright_color_conversion/moz.build +++ b/media/omx-plugin/lib/gb/libstagefright_color_conversion/moz.build @@ -19,3 +19,5 @@ LOCAL_INCLUDES += [ '/media/omx-plugin/include/gb/media/stagefright/openmax', ] +# Don't use STL wrappers; this isn't Gecko code +DISABLE_STL_WRAPPING = True diff --git a/media/omx-plugin/lib/gb/libutils/Makefile.in b/media/omx-plugin/lib/gb/libutils/Makefile.in deleted file mode 100644 index f664dc3c4ec..00000000000 --- a/media/omx-plugin/lib/gb/libutils/Makefile.in +++ /dev/null @@ -1,16 +0,0 @@ -# Copyright 2012 Mozilla Foundation and Mozilla contributors -# -# Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# Don't use STL wrappers; this isn't Gecko code -STL_FLAGS = diff --git a/media/omx-plugin/lib/gb/libutils/moz.build b/media/omx-plugin/lib/gb/libutils/moz.build index 6fc8df848fa..5baea328af2 100644 --- a/media/omx-plugin/lib/gb/libutils/moz.build +++ b/media/omx-plugin/lib/gb/libutils/moz.build @@ -19,3 +19,5 @@ LOCAL_INCLUDES += [ '/media/omx-plugin/include/gb/media/stagefright/openmax', ] +# Don't use STL wrappers; this isn't Gecko code +DISABLE_STL_WRAPPING = True diff --git a/media/omx-plugin/lib/gb235/libstagefright/Makefile.in b/media/omx-plugin/lib/gb235/libstagefright/Makefile.in index 0b840e60929..a6272b4ea70 100644 --- a/media/omx-plugin/lib/gb235/libstagefright/Makefile.in +++ b/media/omx-plugin/lib/gb235/libstagefright/Makefile.in @@ -12,9 +12,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -# Don't use STL wrappers; this isn't Gecko code -STL_FLAGS = - include $(topsrcdir)/config/rules.mk EXTRA_DSO_LDOPTS += \ diff --git a/media/omx-plugin/lib/gb235/libstagefright/moz.build b/media/omx-plugin/lib/gb235/libstagefright/moz.build index 35374f1b479..9adcb0ece2c 100644 --- a/media/omx-plugin/lib/gb235/libstagefright/moz.build +++ b/media/omx-plugin/lib/gb235/libstagefright/moz.build @@ -19,3 +19,5 @@ LOCAL_INCLUDES += [ '/media/omx-plugin/include/gb/media/stagefright/openmax', ] +# Don't use STL wrappers; this isn't Gecko code +DISABLE_STL_WRAPPING = True diff --git a/media/omx-plugin/lib/hc/libstagefright/Makefile.in b/media/omx-plugin/lib/hc/libstagefright/Makefile.in index 0b840e60929..a6272b4ea70 100644 --- a/media/omx-plugin/lib/hc/libstagefright/Makefile.in +++ b/media/omx-plugin/lib/hc/libstagefright/Makefile.in @@ -12,9 +12,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -# Don't use STL wrappers; this isn't Gecko code -STL_FLAGS = - include $(topsrcdir)/config/rules.mk EXTRA_DSO_LDOPTS += \ diff --git a/media/omx-plugin/lib/hc/libstagefright/moz.build b/media/omx-plugin/lib/hc/libstagefright/moz.build index 35374f1b479..9adcb0ece2c 100644 --- a/media/omx-plugin/lib/hc/libstagefright/moz.build +++ b/media/omx-plugin/lib/hc/libstagefright/moz.build @@ -19,3 +19,5 @@ LOCAL_INCLUDES += [ '/media/omx-plugin/include/gb/media/stagefright/openmax', ] +# Don't use STL wrappers; this isn't Gecko code +DISABLE_STL_WRAPPING = True diff --git a/media/omx-plugin/lib/ics/libstagefright/Makefile.in b/media/omx-plugin/lib/ics/libstagefright/Makefile.in index 2cb717b1a21..bb94a747f31 100644 --- a/media/omx-plugin/lib/ics/libstagefright/Makefile.in +++ b/media/omx-plugin/lib/ics/libstagefright/Makefile.in @@ -12,9 +12,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -# Don't use STL wrappers; this isn't Gecko code -STL_FLAGS = - include $(topsrcdir)/config/rules.mk EXTRA_DSO_LDOPTS += \ diff --git a/media/omx-plugin/lib/ics/libstagefright/moz.build b/media/omx-plugin/lib/ics/libstagefright/moz.build index e629f4c66cb..fed780fa9a1 100644 --- a/media/omx-plugin/lib/ics/libstagefright/moz.build +++ b/media/omx-plugin/lib/ics/libstagefright/moz.build @@ -19,3 +19,5 @@ LOCAL_INCLUDES += [ '/media/omx-plugin/include/ics/media/stagefright/openmax', ] +# Don't use STL wrappers; this isn't Gecko code +DISABLE_STL_WRAPPING = True diff --git a/media/omx-plugin/lib/ics/libutils/Makefile.in b/media/omx-plugin/lib/ics/libutils/Makefile.in deleted file mode 100644 index f664dc3c4ec..00000000000 --- a/media/omx-plugin/lib/ics/libutils/Makefile.in +++ /dev/null @@ -1,16 +0,0 @@ -# Copyright 2012 Mozilla Foundation and Mozilla contributors -# -# Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# Don't use STL wrappers; this isn't Gecko code -STL_FLAGS = diff --git a/media/omx-plugin/lib/ics/libutils/moz.build b/media/omx-plugin/lib/ics/libutils/moz.build index 2fa0558fced..e938d5c25c5 100644 --- a/media/omx-plugin/lib/ics/libutils/moz.build +++ b/media/omx-plugin/lib/ics/libutils/moz.build @@ -19,3 +19,5 @@ LOCAL_INCLUDES += [ '/media/omx-plugin/include/ics/media/stagefright/openmax', ] +# Don't use STL wrappers; this isn't Gecko code +DISABLE_STL_WRAPPING = True diff --git a/media/omx-plugin/lib/ics/libvideoeditorplayer/Makefile.in b/media/omx-plugin/lib/ics/libvideoeditorplayer/Makefile.in index 2f1af133e62..d5219102fe1 100644 --- a/media/omx-plugin/lib/ics/libvideoeditorplayer/Makefile.in +++ b/media/omx-plugin/lib/ics/libvideoeditorplayer/Makefile.in @@ -12,9 +12,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -# Don't use STL wrappers; this isn't Gecko code -STL_FLAGS = - include $(topsrcdir)/config/rules.mk INCLUDES += \ diff --git a/media/omx-plugin/lib/ics/libvideoeditorplayer/moz.build b/media/omx-plugin/lib/ics/libvideoeditorplayer/moz.build index 40e83bca89d..af91a68498f 100644 --- a/media/omx-plugin/lib/ics/libvideoeditorplayer/moz.build +++ b/media/omx-plugin/lib/ics/libvideoeditorplayer/moz.build @@ -13,3 +13,6 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] != 'gonk': LIBRARY_NAME = 'videoeditorplayer' FORCE_SHARED_LIB = True + +# Don't use STL wrappers; this isn't Gecko code +DISABLE_STL_WRAPPING = True diff --git a/media/omx-plugin/moz.build b/media/omx-plugin/moz.build index 10c89eb5174..bb217ba7034 100644 --- a/media/omx-plugin/moz.build +++ b/media/omx-plugin/moz.build @@ -53,3 +53,6 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk': 'hardware/libhardware/include', ] ] + +# Don't use STL wrappers; this isn't Gecko code +DISABLE_STL_WRAPPING = True diff --git a/memory/build/replace_malloc.h b/memory/build/replace_malloc.h index 371e824ad1e..1feb4fe3267 100644 --- a/memory/build/replace_malloc.h +++ b/memory/build/replace_malloc.h @@ -54,7 +54,8 @@ * Makefile.in: * MOZ_GLUE_LDFLAGS = # Don't link against mozglue * WRAP_LDFLAGS = # Never wrap malloc function calls with -Wl,--wrap - * STL_FLAGS = # Avoid STL wrapping + * and the following to the implementation's moz.build: + * DISABLE_STL_WRAPPING = True # Avoid STL wrapping * * If your replace-malloc implementation lives under memory/replace, these * are taken care of by memory/replace/defs.mk. diff --git a/memory/mozalloc/Makefile.in b/memory/mozalloc/Makefile.in index 4aee791c7ed..bec80e2182e 100644 --- a/memory/mozalloc/Makefile.in +++ b/memory/mozalloc/Makefile.in @@ -3,11 +3,6 @@ # 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/. -STL_FLAGS = -ifdef _MSC_VER -STL_FLAGS = -D_HAS_EXCEPTIONS=0 -endif - DIST_INSTALL = 1 ifneq (,$(filter WINNT,$(OS_ARCH))) diff --git a/memory/mozalloc/moz.build b/memory/mozalloc/moz.build index 7a4a9ae5616..15978235b7f 100644 --- a/memory/mozalloc/moz.build +++ b/memory/mozalloc/moz.build @@ -22,6 +22,7 @@ if CONFIG['WRAP_STL_INCLUDES']: if CONFIG['GNU_CXX']: EXPORTS.mozilla += ['throw_gcc.h'] elif CONFIG['_MSC_VER']: + DEFINES['_HAS_EXCEPTIONS'] = 0 if build_msvc_wrappers: EXPORTS.mozilla += [ 'msvc_raise_wrappers.h', @@ -69,3 +70,5 @@ DEFINES['_GNU_SOURCE'] = True TEST_TOOL_DIRS += ['tests'] GENERATED_INCLUDES += ['/xpcom'] + +DISABLE_STL_WRAPPING = True diff --git a/memory/replace/defs.mk b/memory/replace/defs.mk index 68d1b8c9273..6bfb5d9b04c 100644 --- a/memory/replace/defs.mk +++ b/memory/replace/defs.mk @@ -1,3 +1,2 @@ MOZ_GLUE_LDFLAGS = # Don't link against mozglue WRAP_LDFLAGS = # Never wrap malloc function calls with -Wl,--wrap -STL_FLAGS = # Avoid STL wrapping diff --git a/memory/replace/dmd/Makefile.in b/memory/replace/dmd/Makefile.in index ea585d81c80..f5006f56e8d 100644 --- a/memory/replace/dmd/Makefile.in +++ b/memory/replace/dmd/Makefile.in @@ -7,8 +7,6 @@ WRAP_LDFLAGS = MOZ_GLUE_LDFLAGS= -STL_FLAGS = - ifeq ($(OS_ARCH),WINNT) OS_LIBS += $(call EXPAND_LIBNAME,dbghelp) endif diff --git a/memory/replace/dmd/moz.build b/memory/replace/dmd/moz.build index 8c08f84d498..59bb34bb8e0 100644 --- a/memory/replace/dmd/moz.build +++ b/memory/replace/dmd/moz.build @@ -26,3 +26,5 @@ DEFINES['MOZ_NO_MOZALLOC'] = True if CONFIG['MOZ_OPTIMIZE']: DEFINES['MOZ_OPTIMIZE'] = True + +DISABLE_STL_WRAPPING = True diff --git a/memory/replace/dummy/moz.build b/memory/replace/dummy/moz.build index b9931b3baf1..7d2c185c85e 100644 --- a/memory/replace/dummy/moz.build +++ b/memory/replace/dummy/moz.build @@ -12,3 +12,5 @@ SOURCES += [ LIBRARY_NAME = 'replace_malloc' FORCE_SHARED_LIB = True + +DISABLE_STL_WRAPPING = True diff --git a/memory/replace/jemalloc/moz.build b/memory/replace/jemalloc/moz.build index 22f5a7aefa2..85197b2235b 100644 --- a/memory/replace/jemalloc/moz.build +++ b/memory/replace/jemalloc/moz.build @@ -28,3 +28,5 @@ DEFINES['MOZ_REPLACE_JEMALLOC'] = True GENERATED_INCLUDES += ['../../jemalloc/src/include'] if CONFIG['_MSC_VER']: LOCAL_INCLUDES += ['/memory/jemalloc/src/include/msvc_compat'] + +DISABLE_STL_WRAPPING = True diff --git a/memory/replace/moz.build b/memory/replace/moz.build index cb00e573fa9..abd231e8400 100644 --- a/memory/replace/moz.build +++ b/memory/replace/moz.build @@ -7,3 +7,5 @@ # Build jemalloc3 as a replace-malloc lib when building with mozjemalloc if not CONFIG['MOZ_JEMALLOC']: DIRS += ['jemalloc'] + +DISABLE_STL_WRAPPING = True diff --git a/mfbt/Makefile.in b/mfbt/Makefile.in index ded3e30ce19..6fbe8159b2d 100644 --- a/mfbt/Makefile.in +++ b/mfbt/Makefile.in @@ -1,5 +1,3 @@ # 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/. - -STL_FLAGS = diff --git a/mfbt/moz.build b/mfbt/moz.build index d5594ef750a..e4ec5107f46 100644 --- a/mfbt/moz.build +++ b/mfbt/moz.build @@ -89,3 +89,5 @@ SOURCES += [ 'Compression.cpp', 'decimal/Decimal.cpp', ] + +DISABLE_STL_WRAPPING = True diff --git a/mfbt/tests/Makefile.in b/mfbt/tests/Makefile.in index 77d167b19c0..c154f9aa480 100644 --- a/mfbt/tests/Makefile.in +++ b/mfbt/tests/Makefile.in @@ -2,8 +2,6 @@ # 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/. -STL_FLAGS = - # in order to prevent rules.mk from trying to link to libraries that are # not available to MFBT, we have to reset these MOZ_GLUE*_LDFLAGS before including it # and LIBS_ after including it. For WRAP_LDFLAGS, it shouldn't matter. diff --git a/mfbt/tests/moz.build b/mfbt/tests/moz.build index 3a701d985b7..2163a5f3279 100644 --- a/mfbt/tests/moz.build +++ b/mfbt/tests/moz.build @@ -29,3 +29,5 @@ if not CONFIG['MOZ_ASAN']: # Since we link directly with MFBT object files, define IMPL_MFBT DEFINES['IMPL_MFBT'] = True + +DISABLE_STL_WRAPPING = True diff --git a/mobile/android/app/Makefile.in b/mobile/android/app/Makefile.in index 74ed77201a7..8aaa75ad435 100644 --- a/mobile/android/app/Makefile.in +++ b/mobile/android/app/Makefile.in @@ -8,8 +8,6 @@ PREF_JS_EXPORTS = $(srcdir)/mobile.js ifndef LIBXUL_SDK ifneq (Android,$(OS_TARGET)) -STL_FLAGS= - LIBS += \ $(XPCOM_STANDALONE_GLUE_LDOPTS) \ $(NULL) diff --git a/mobile/android/app/moz.build b/mobile/android/app/moz.build index 963d4ee98dd..735ac4a3c1f 100644 --- a/mobile/android/app/moz.build +++ b/mobile/android/app/moz.build @@ -14,6 +14,7 @@ if not CONFIG['LIBXUL_SDK']: '/xpcom/base', '/xpcom/build', ] + DISABLE_STL_WRAPPING = True for var in ('APP_NAME', 'APP_VERSION'): DEFINES[var] = CONFIG['MOZ_%s' % var] diff --git a/mozglue/android/Makefile.in b/mozglue/android/Makefile.in index faa3246e8bc..3c8062a29a5 100644 --- a/mozglue/android/Makefile.in +++ b/mozglue/android/Makefile.in @@ -2,8 +2,6 @@ # 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/. -STL_FLAGS= - include $(topsrcdir)/config/rules.mk prcpucfg.h: $(topsrcdir)/nsprpub/pr/include/md/_linux.cfg diff --git a/mozglue/android/moz.build b/mozglue/android/moz.build index 3d8389220a9..37baa923e4d 100644 --- a/mozglue/android/moz.build +++ b/mozglue/android/moz.build @@ -48,3 +48,5 @@ LOCAL_INCLUDES += [ '/toolkit/components/startup', '/xpcom/build', ] + +DISABLE_STL_WRAPPING = True diff --git a/mozglue/build/Makefile.in b/mozglue/build/Makefile.in index ab6d88125df..6c83b36dc43 100644 --- a/mozglue/build/Makefile.in +++ b/mozglue/build/Makefile.in @@ -50,8 +50,6 @@ EXTRA_DSO_LDOPTS += \ $(call EXPAND_LIBNAME,version) \ $(NULL) -STL_FLAGS= - endif ifeq (Darwin_1,$(OS_TARGET)_$(MOZ_REPLACE_MALLOC)) diff --git a/mozglue/build/moz.build b/mozglue/build/moz.build index 3b01cf2be56..d4130460183 100644 --- a/mozglue/build/moz.build +++ b/mozglue/build/moz.build @@ -32,6 +32,7 @@ if CONFIG['OS_TARGET'] == 'WINNT': 'WindowsDllBlocklist.cpp', ] DEFFILE = 'mozglue.def' + DISABLE_STL_WRAPPING = True if CONFIG['MOZ_NUWA_PROCESS']: EXPORTS.ipc += [ diff --git a/mozglue/linker/Makefile.in b/mozglue/linker/Makefile.in index 2e1e372d223..e4351daf85b 100644 --- a/mozglue/linker/Makefile.in +++ b/mozglue/linker/Makefile.in @@ -2,8 +2,6 @@ # 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/. -STL_FLAGS = - HOST_LIBS = -lz include $(topsrcdir)/config/rules.mk diff --git a/mozglue/linker/moz.build b/mozglue/linker/moz.build index d953c9b400a..36c859b420b 100644 --- a/mozglue/linker/moz.build +++ b/mozglue/linker/moz.build @@ -24,3 +24,5 @@ HOST_PROGRAM = 'szip' FINAL_LIBRARY = 'mozglue' DEFINES['IMPL_MFBT'] = True + +DISABLE_STL_WRAPPING = True diff --git a/mozglue/tests/Makefile.in b/mozglue/tests/Makefile.in index 6ec472d08e8..d93c6fdb4f7 100644 --- a/mozglue/tests/Makefile.in +++ b/mozglue/tests/Makefile.in @@ -3,8 +3,6 @@ # You can obtain one at http://mozilla.org/MPL/2.0/. ifdef MOZ_LINKER -STL_FLAGS = - # Only link against the linker, not mozglue MOZ_GLUE_PROGRAM_LDFLAGS = MOZ_GLUE_LDFLAGS = diff --git a/mozglue/tests/moz.build b/mozglue/tests/moz.build index e15e447e617..a0dbb6bc834 100644 --- a/mozglue/tests/moz.build +++ b/mozglue/tests/moz.build @@ -15,3 +15,4 @@ if CONFIG['MOZ_LINKER']: 'TestZip', ] LOCAL_INCLUDES += ['../linker'] + DISABLE_STL_WRAPPING = True diff --git a/profile/dirserviceprovider/src/Makefile.in b/profile/dirserviceprovider/src/Makefile.in deleted file mode 100644 index 5032b1cf7c2..00000000000 --- a/profile/dirserviceprovider/src/Makefile.in +++ /dev/null @@ -1,7 +0,0 @@ -# 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 $(topsrcdir)/config/rules.mk - -STL_FLAGS = diff --git a/profile/dirserviceprovider/src/moz.build b/profile/dirserviceprovider/src/moz.build index 7c4ab1b3746..688df62d006 100644 --- a/profile/dirserviceprovider/src/moz.build +++ b/profile/dirserviceprovider/src/moz.build @@ -13,3 +13,5 @@ LIBRARY_NAME = 'profdirserviceprovidersa_s' FORCE_STATIC_LIB = True DEFINES['XPCOM_GLUE'] = 1 + +DISABLE_STL_WRAPPING = True diff --git a/python/mozbuild/mozbuild/frontend/emitter.py b/python/mozbuild/mozbuild/frontend/emitter.py index f795c8a82c9..275d81cf69a 100644 --- a/python/mozbuild/mozbuild/frontend/emitter.py +++ b/python/mozbuild/mozbuild/frontend/emitter.py @@ -217,6 +217,7 @@ class TreeMetadataEmitter(LoggingMixin): 'ANDROID_GENERATED_RESFILES', 'ANDROID_RES_DIRS', 'CPP_UNIT_TESTS', + 'DISABLE_STL_WRAPPING', 'EXPORT_LIBRARY', 'EXTRA_ASSEMBLER_FLAGS', 'EXTRA_COMPILE_FLAGS', diff --git a/python/mozbuild/mozbuild/frontend/sandbox_symbols.py b/python/mozbuild/mozbuild/frontend/sandbox_symbols.py index c1140b8090f..238b5771ee5 100644 --- a/python/mozbuild/mozbuild/frontend/sandbox_symbols.py +++ b/python/mozbuild/mozbuild/frontend/sandbox_symbols.py @@ -178,6 +178,11 @@ VARIABLES = { delimiters. """, None), + 'DISABLE_STL_WRAPPING': (bool, bool, + """Disable the wrappers for STL which allow it to work with C++ exceptions + disabled. + """, 'binaries'), + 'EXPORT_LIBRARY': (bool, bool, """Install the library to the static libraries folder. """, None), diff --git a/python/mozbuild/mozbuild/test/backend/data/variable_passthru/moz.build b/python/mozbuild/mozbuild/test/backend/data/variable_passthru/moz.build index 68404559926..aa9bcb5aa17 100644 --- a/python/mozbuild/mozbuild/test/backend/data/variable_passthru/moz.build +++ b/python/mozbuild/mozbuild/test/backend/data/variable_passthru/moz.build @@ -47,3 +47,5 @@ CFLAGS += ['-fno-exceptions', '-w'] CXXFLAGS += ['-fcxx-exceptions', '-include foo.h'] LDFLAGS += ['-framework Foo', '-x'] WIN32_EXE_LDFLAGS += ['-subsystem:console'] + +DISABLE_STL_WRAPPING = True diff --git a/python/mozbuild/mozbuild/test/backend/test_recursivemake.py b/python/mozbuild/mozbuild/test/backend/test_recursivemake.py index 5a714e27e47..3d7a2cc7822 100644 --- a/python/mozbuild/mozbuild/test/backend/test_recursivemake.py +++ b/python/mozbuild/mozbuild/test/backend/test_recursivemake.py @@ -269,6 +269,9 @@ class TestRecursiveMakeBackend(BackendTester): 'CSRCS += bar.c', 'CSRCS += foo.c', ], + 'DISABLE_STL_WRAPPING': [ + 'DISABLE_STL_WRAPPING := 1', + ], 'EXTRA_COMPONENTS': [ 'EXTRA_COMPONENTS += bar.js', 'EXTRA_COMPONENTS += foo.js', diff --git a/python/mozbuild/mozbuild/test/frontend/data/variable-passthru/moz.build b/python/mozbuild/mozbuild/test/frontend/data/variable-passthru/moz.build index d9b6c9a7c6d..4fbba04676d 100644 --- a/python/mozbuild/mozbuild/test/frontend/data/variable-passthru/moz.build +++ b/python/mozbuild/mozbuild/test/frontend/data/variable-passthru/moz.build @@ -53,3 +53,5 @@ CFLAGS += ['-fno-exceptions', '-w'] CXXFLAGS += ['-fcxx-exceptions', '-include foo.h'] LDFLAGS += ['-framework Foo', '-x'] WIN32_EXE_LDFLAGS += ['-subsystem:console'] + +DISABLE_STL_WRAPPING = True diff --git a/python/mozbuild/mozbuild/test/frontend/test_emitter.py b/python/mozbuild/mozbuild/test/frontend/test_emitter.py index f1de4654c5a..0bf986964ae 100644 --- a/python/mozbuild/mozbuild/test/frontend/test_emitter.py +++ b/python/mozbuild/mozbuild/test/frontend/test_emitter.py @@ -151,6 +151,7 @@ class TestEmitterBasic(unittest.TestCase): CMMSRCS=['fans.mm', 'tans.mm'], CSRCS=['fans.c', 'tans.c'], CPP_UNIT_TESTS=['foo.cpp'], + DISABLE_STL_WRAPPING=True, EXPORT_LIBRARY=True, EXTRA_COMPONENTS=['fans.js', 'tans.js'], EXTRA_PP_COMPONENTS=['fans.pp.js', 'tans.pp.js'], diff --git a/security/sandbox/Makefile.in b/security/sandbox/Makefile.in index 67133c4cd6a..05cc77d5967 100644 --- a/security/sandbox/Makefile.in +++ b/security/sandbox/Makefile.in @@ -3,7 +3,6 @@ # file, You can obtain one at http://mozilla.org/MPL/2.0/. ifeq ($(OS_ARCH),WINNT) -STL_FLAGS = MOZ_GLUE_LDFLAGS = endif diff --git a/security/sandbox/moz.build b/security/sandbox/moz.build index 40c2502892f..5263fb19396 100644 --- a/security/sandbox/moz.build +++ b/security/sandbox/moz.build @@ -128,3 +128,5 @@ elif CONFIG['OS_ARCH'] == 'WINNT': LOCAL_INCLUDES += ['/security/sandbox/chromium'] LOCAL_INCLUDES += ['/security'] LOCAL_INCLUDES += ['/nsprpub'] + + DISABLE_STL_WRAPPING = True diff --git a/security/sandbox/win/src/sandboxbroker/Makefile.in b/security/sandbox/win/src/sandboxbroker/Makefile.in index c1eb29a145c..9393b2dfa2e 100644 --- a/security/sandbox/win/src/sandboxbroker/Makefile.in +++ b/security/sandbox/win/src/sandboxbroker/Makefile.in @@ -3,7 +3,6 @@ # file, You can obtain one at http://mozilla.org/MPL/2.0/. # MOZ_GLUE_LDFLAGS = -STL_FLAGS = SHARED_LIBRARY_LIBS += \ ../../../$(LIB_PREFIX)sandbox_s.$(LIB_SUFFIX) \ diff --git a/security/sandbox/win/src/sandboxbroker/moz.build b/security/sandbox/win/src/sandboxbroker/moz.build index bc2972582f5..04ad0ee924e 100644 --- a/security/sandbox/win/src/sandboxbroker/moz.build +++ b/security/sandbox/win/src/sandboxbroker/moz.build @@ -27,3 +27,4 @@ LOCAL_INCLUDES += [ '/security/sandbox/chromium', ] +DISABLE_STL_WRAPPING = True diff --git a/testing/mochitest/ssltunnel/Makefile.in b/testing/mochitest/ssltunnel/Makefile.in index 9936c4eb5ac..16214651cc2 100644 --- a/testing/mochitest/ssltunnel/Makefile.in +++ b/testing/mochitest/ssltunnel/Makefile.in @@ -3,10 +3,6 @@ # 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/. -# This isn't XPCOM code, but it wants to use STL, so disable the STL -# wrappers -STL_FLAGS = - LIBS = \ $(NSPR_LIBS) \ $(NSS_LIBS) \ diff --git a/testing/mochitest/ssltunnel/moz.build b/testing/mochitest/ssltunnel/moz.build index 862474cb660..835e3237925 100644 --- a/testing/mochitest/ssltunnel/moz.build +++ b/testing/mochitest/ssltunnel/moz.build @@ -9,3 +9,7 @@ PROGRAM = 'ssltunnel' SOURCES += [ 'ssltunnel.cpp', ] + +# This isn't XPCOM code, but it wants to use STL, so disable the STL +# wrappers +DISABLE_STL_WRAPPING = True diff --git a/toolkit/components/maintenanceservice/Makefile.in b/toolkit/components/maintenanceservice/Makefile.in index efff5dabbf3..78374c7d763 100644 --- a/toolkit/components/maintenanceservice/Makefile.in +++ b/toolkit/components/maintenanceservice/Makefile.in @@ -8,7 +8,6 @@ DIST_PROGRAM = maintenanceservice$(BIN_SUFFIX) # bug 725876 MOZ_GLUE_LDFLAGS = MOZ_GLUE_PROGRAM_LDFLAGS = -STL_FLAGS= ifeq ($(OS_ARCH),WINNT) LIBS += $(call EXPAND_LIBNAME_PATH,updatecommon-standalone,../../mozapps/update/common-standalone) diff --git a/toolkit/components/maintenanceservice/moz.build b/toolkit/components/maintenanceservice/moz.build index 25a3e823ca5..06532c3ba06 100644 --- a/toolkit/components/maintenanceservice/moz.build +++ b/toolkit/components/maintenanceservice/moz.build @@ -34,3 +34,5 @@ if CONFIG['_MSC_VER']: WIN32_EXE_LDFLAGS += ['-ENTRY:wmainCRTStartup'] RCINCLUDE = 'maintenanceservice.rc' + +DISABLE_STL_WRAPPING = True diff --git a/toolkit/crashreporter/breakpad-windows-libxul/Makefile.in b/toolkit/crashreporter/breakpad-windows-libxul/Makefile.in deleted file mode 100644 index ded3e30ce19..00000000000 --- a/toolkit/crashreporter/breakpad-windows-libxul/Makefile.in +++ /dev/null @@ -1,5 +0,0 @@ -# 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/. - -STL_FLAGS = diff --git a/toolkit/crashreporter/breakpad-windows-libxul/moz.build b/toolkit/crashreporter/breakpad-windows-libxul/moz.build index 3edea575e54..1e44df18ef4 100644 --- a/toolkit/crashreporter/breakpad-windows-libxul/moz.build +++ b/toolkit/crashreporter/breakpad-windows-libxul/moz.build @@ -28,3 +28,5 @@ SOURCES += objs_common SOURCES += objs_crash_generation SOURCES += objs_handler SOURCES += objs_sender + +DISABLE_STL_WRAPPING = True diff --git a/toolkit/crashreporter/breakpad-windows-standalone/Makefile.in b/toolkit/crashreporter/breakpad-windows-standalone/Makefile.in index 134d32419bb..9a0b3a6d1a1 100644 --- a/toolkit/crashreporter/breakpad-windows-standalone/Makefile.in +++ b/toolkit/crashreporter/breakpad-windows-standalone/Makefile.in @@ -3,5 +3,3 @@ # file, You can obtain one at http://mozilla.org/MPL/2.0/. MOZ_GLUE_LDFLAGS = - -STL_FLAGS = diff --git a/toolkit/crashreporter/breakpad-windows-standalone/moz.build b/toolkit/crashreporter/breakpad-windows-standalone/moz.build index cdde55ddddb..3e2917657c9 100644 --- a/toolkit/crashreporter/breakpad-windows-standalone/moz.build +++ b/toolkit/crashreporter/breakpad-windows-standalone/moz.build @@ -22,3 +22,5 @@ SOURCES += objs_crash_generation SOURCES += objs_handler USE_STATIC_LIBS = True + +DISABLE_STL_WRAPPING = True diff --git a/toolkit/crashreporter/client/Makefile.in b/toolkit/crashreporter/client/Makefile.in index 55fe1c53138..c36b44e825c 100644 --- a/toolkit/crashreporter/client/Makefile.in +++ b/toolkit/crashreporter/client/Makefile.in @@ -3,10 +3,6 @@ # 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/. -# Don't use the STL wrappers in the crashreporter clients; they don't -# link with -lmozalloc, and it really doesn't matter here anyway. -STL_FLAGS = - ifneq ($(OS_TARGET),Android) DIST_PROGRAM = crashreporter$(BIN_SUFFIX) diff --git a/toolkit/crashreporter/client/moz.build b/toolkit/crashreporter/client/moz.build index 4c8a5fe3bf4..b7ce83256f0 100644 --- a/toolkit/crashreporter/client/moz.build +++ b/toolkit/crashreporter/client/moz.build @@ -44,3 +44,7 @@ if CONFIG['MOZ_ENABLE_GTK']: ] RCINCLUDE = 'crashreporter.rc' + +# Don't use the STL wrappers in the crashreporter clients; they don't +# link with -lmozalloc, and it really doesn't matter here anyway. +DISABLE_STL_WRAPPING = True diff --git a/toolkit/crashreporter/google-breakpad/src/common/linux/Makefile.in b/toolkit/crashreporter/google-breakpad/src/common/linux/Makefile.in index 3c153aa26bf..a35acea48e6 100644 --- a/toolkit/crashreporter/google-breakpad/src/common/linux/Makefile.in +++ b/toolkit/crashreporter/google-breakpad/src/common/linux/Makefile.in @@ -10,4 +10,4 @@ endif include $(topsrcdir)/config/rules.mk # See https://bugzilla.mozilla.org/show_bug.cgi?id=741348#c11 -file_id.$(OBJ_SUFFIX): STL_FLAGS= +file_id.$(OBJ_SUFFIX): DISABLE_STL_WRAPPING := 1 diff --git a/toolkit/crashreporter/google-breakpad/src/common/linux/moz.build b/toolkit/crashreporter/google-breakpad/src/common/linux/moz.build index 701324f0094..7fa7da5049d 100644 --- a/toolkit/crashreporter/google-breakpad/src/common/linux/moz.build +++ b/toolkit/crashreporter/google-breakpad/src/common/linux/moz.build @@ -12,7 +12,7 @@ UNIFIED_SOURCES += [ 'safe_readlink.cc', ] -# file_id.cc cannot be built in unified mode because it uses a custom STL_FLAGS +# file_id.cc cannot be built in unified mode because it uses a custom DISABLE_STL_WRAPPING SOURCES += [ 'file_id.cc', ] diff --git a/toolkit/crashreporter/injector/Makefile.in b/toolkit/crashreporter/injector/Makefile.in index 7e58cfdf01b..2dc367f8645 100644 --- a/toolkit/crashreporter/injector/Makefile.in +++ b/toolkit/crashreporter/injector/Makefile.in @@ -2,7 +2,6 @@ # 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/. -STL_FLAGS = MOZ_GLUE_LDFLAGS = include $(topsrcdir)/config/rules.mk diff --git a/toolkit/crashreporter/injector/moz.build b/toolkit/crashreporter/injector/moz.build index 697b6fe8f42..1f706d20ec1 100644 --- a/toolkit/crashreporter/injector/moz.build +++ b/toolkit/crashreporter/injector/moz.build @@ -24,3 +24,5 @@ if CONFIG['GNU_CC']: LDFLAGS += ['-Wl,-e,_DummyEntryPoint@12'] else: LDFLAGS += ['-ENTRY:DummyEntryPoint'] + +DISABLE_STL_WRAPPING = True diff --git a/toolkit/mozapps/update/updater/Makefile.in b/toolkit/mozapps/update/updater/Makefile.in index 4e0f79cbc18..a457bfda1c3 100644 --- a/toolkit/mozapps/update/updater/Makefile.in +++ b/toolkit/mozapps/update/updater/Makefile.in @@ -33,7 +33,6 @@ OS_LIBS += -framework Cocoa endif ifeq (gonk,$(MOZ_WIDGET_TOOLKIT)) #{ -STL_FLAGS = OS_LIBS += -lcutils -lsysutils # clear out all the --wrap flags and remove dependency on mozglue for Gonk WRAP_LDFLAGS := diff --git a/toolkit/mozapps/update/updater/moz.build b/toolkit/mozapps/update/updater/moz.build index add81dae3a0..5777b3cfbbc 100644 --- a/toolkit/mozapps/update/updater/moz.build +++ b/toolkit/mozapps/update/updater/moz.build @@ -44,6 +44,7 @@ elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk': 'automounter_gonk.cpp', 'progressui_gonk.cpp', ] + DISABLE_STL_WRAPPING = True if have_progressui == 0: SOURCES += [ diff --git a/tools/trace-malloc/lib/Makefile.in b/tools/trace-malloc/lib/Makefile.in deleted file mode 100644 index c9a4972166d..00000000000 --- a/tools/trace-malloc/lib/Makefile.in +++ /dev/null @@ -1,6 +0,0 @@ -# -# 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/. - -STL_FLAGS = diff --git a/tools/trace-malloc/lib/moz.build b/tools/trace-malloc/lib/moz.build index 2f734db0cdc..4ebdadc2499 100644 --- a/tools/trace-malloc/lib/moz.build +++ b/tools/trace-malloc/lib/moz.build @@ -30,3 +30,5 @@ if CONFIG['WRAP_SYSTEM_INCLUDES']: DEFINES['MOZ_NO_MOZALLOC'] = True DEFFILE = SRCDIR + '/tm.def' + +DISABLE_STL_WRAPPING = True diff --git a/webapprt/gtk2/Makefile.in b/webapprt/gtk2/Makefile.in index 4b0f9e035af..38d8057c4a7 100644 --- a/webapprt/gtk2/Makefile.in +++ b/webapprt/gtk2/Makefile.in @@ -2,8 +2,6 @@ # 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/. -STL_FLAGS= - LIBS = \ $(XPCOM_STANDALONE_GLUE_LDOPTS) \ $(MOZ_GTK2_LIBS) \ diff --git a/webapprt/gtk2/moz.build b/webapprt/gtk2/moz.build index 56a033386b0..18fb764754e 100644 --- a/webapprt/gtk2/moz.build +++ b/webapprt/gtk2/moz.build @@ -20,3 +20,5 @@ LOCAL_INCLUDES += [ '/xpcom/base', '/xpcom/build', ] + +DISABLE_STL_WRAPPING = True diff --git a/webapprt/mac/Makefile.in b/webapprt/mac/Makefile.in index dfcf4bebd95..18b6f8d9fc4 100644 --- a/webapprt/mac/Makefile.in +++ b/webapprt/mac/Makefile.in @@ -11,8 +11,6 @@ NSDISTMODE = copy MOZ_GLUE_LDFLAGS = MOZ_GLUE_PROGRAM_LDFLAGS = -STL_FLAGS= - LIBS = \ $(XPCOM_STANDALONE_GLUE_LDOPTS) \ $(NULL) diff --git a/webapprt/mac/moz.build b/webapprt/mac/moz.build index 6e3e0d70588..4327892c833 100644 --- a/webapprt/mac/moz.build +++ b/webapprt/mac/moz.build @@ -18,3 +18,5 @@ LOCAL_INCLUDES += [ '/xpcom/base', '/xpcom/build', ] + +DISABLE_STL_WRAPPING = True diff --git a/webapprt/win/Makefile.in b/webapprt/win/Makefile.in index 2409c291dd5..5b246197c96 100644 --- a/webapprt/win/Makefile.in +++ b/webapprt/win/Makefile.in @@ -6,8 +6,6 @@ # to dynamically link into our executable, as we copy it to arbitrary locations. MOZ_GLUE_LDFLAGS = -STL_FLAGS= - LIBS = \ $(XPCOM_STANDALONE_STATICRUNTIME_GLUE_LDOPTS) \ $(NULL) diff --git a/webapprt/win/moz.build b/webapprt/win/moz.build index dc5a3333676..fdbc1fb70ae 100644 --- a/webapprt/win/moz.build +++ b/webapprt/win/moz.build @@ -41,3 +41,5 @@ if not CONFIG['GNU_CC']: LDFLAGS += ['/HEAP:0x40000'] RCINCLUDE = 'webapprt.rc' + +DISABLE_STL_WRAPPING = True diff --git a/widget/gonk/libdisplay/Makefile.in b/widget/gonk/libdisplay/Makefile.in index 9c82cdf28a0..af214b59779 100644 --- a/widget/gonk/libdisplay/Makefile.in +++ b/widget/gonk/libdisplay/Makefile.in @@ -12,8 +12,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -STL_FLAGS= - include $(topsrcdir)/config/rules.mk CXXFLAGS += \ diff --git a/widget/gonk/libdisplay/moz.build b/widget/gonk/libdisplay/moz.build index 66902278358..f5fdd598051 100644 --- a/widget/gonk/libdisplay/moz.build +++ b/widget/gonk/libdisplay/moz.build @@ -43,3 +43,5 @@ include('/ipc/chromium/chromium-config.mozbuild') FORCE_STATIC_LIB = True DEFINES['XPCOM_GLUE'] = True + +DISABLE_STL_WRAPPING = True diff --git a/widget/gonk/nativewindow/Makefile.in b/widget/gonk/nativewindow/Makefile.in deleted file mode 100644 index 101958c89aa..00000000000 --- a/widget/gonk/nativewindow/Makefile.in +++ /dev/null @@ -1,16 +0,0 @@ -# Copyright 2013 Mozilla Foundation and Mozilla contributors -# -# Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -STL_FLAGS= - -include $(topsrcdir)/config/rules.mk diff --git a/widget/gonk/nativewindow/moz.build b/widget/gonk/nativewindow/moz.build index 33ee66d6f89..331bd9a9066 100644 --- a/widget/gonk/nativewindow/moz.build +++ b/widget/gonk/nativewindow/moz.build @@ -74,3 +74,5 @@ FAIL_ON_WARNINGS = True include('/ipc/chromium/chromium-config.mozbuild') FINAL_LIBRARY = 'xul' + +DISABLE_STL_WRAPPING = True diff --git a/xpcom/glue/nomozalloc/Makefile.in b/xpcom/glue/nomozalloc/Makefile.in index 0501b940c96..3bec2c73e95 100644 --- a/xpcom/glue/nomozalloc/Makefile.in +++ b/xpcom/glue/nomozalloc/Makefile.in @@ -6,9 +6,6 @@ DIST_INSTALL = 1 -# Don't use STL wrappers here (i.e. wrapped ); they require mozalloc -STL_FLAGS = - include $(topsrcdir)/config/rules.mk ifdef _MSC_VER diff --git a/xpcom/glue/nomozalloc/moz.build b/xpcom/glue/nomozalloc/moz.build index 22cbf41c682..2ca8cda2c71 100644 --- a/xpcom/glue/nomozalloc/moz.build +++ b/xpcom/glue/nomozalloc/moz.build @@ -39,3 +39,6 @@ LOCAL_INCLUDES += [ # avoids "msvcrp" and assembly dependencies from creeping into the directives # for this library on Windows. USE_STATIC_LIBS = True + +# Don't use STL wrappers here (i.e. wrapped ); they require mozalloc +DISABLE_STL_WRAPPING = True diff --git a/xpcom/glue/standalone/Makefile.in b/xpcom/glue/standalone/Makefile.in index 08dfaf04ad5..f21c25153ca 100644 --- a/xpcom/glue/standalone/Makefile.in +++ b/xpcom/glue/standalone/Makefile.in @@ -6,9 +6,6 @@ DIST_INSTALL = 1 -# Don't use STL wrappers here (i.e. wrapped ); they require mozalloc -STL_FLAGS = - include $(topsrcdir)/config/rules.mk ifdef _MSC_VER diff --git a/xpcom/glue/standalone/moz.build b/xpcom/glue/standalone/moz.build index b50e16bb828..7259b019720 100644 --- a/xpcom/glue/standalone/moz.build +++ b/xpcom/glue/standalone/moz.build @@ -42,3 +42,5 @@ LOCAL_INCLUDES += [ '../../build', ] +# Don't use STL wrappers here (i.e. wrapped ); they require mozalloc +DISABLE_STL_WRAPPING = True diff --git a/xpcom/glue/standalone/staticruntime/Makefile.in b/xpcom/glue/standalone/staticruntime/Makefile.in index 161e578b6d5..734fcaadbcf 100644 --- a/xpcom/glue/standalone/staticruntime/Makefile.in +++ b/xpcom/glue/standalone/staticruntime/Makefile.in @@ -5,9 +5,6 @@ DIST_INSTALL = 1 -# Don't use STL wrappers here (i.e. wrapped ); they require mozalloc -STL_FLAGS = - include $(topsrcdir)/config/rules.mk ifdef _MSC_VER diff --git a/xpcom/glue/standalone/staticruntime/moz.build b/xpcom/glue/standalone/staticruntime/moz.build index d10cb36beed..2a94f323b50 100644 --- a/xpcom/glue/standalone/staticruntime/moz.build +++ b/xpcom/glue/standalone/staticruntime/moz.build @@ -36,3 +36,6 @@ LOCAL_INCLUDES += [ # Statically link to the CRT on Windows USE_STATIC_LIBS = True + +# Don't use STL wrappers here (i.e. wrapped ); they require mozalloc +DISABLE_STL_WRAPPING = True diff --git a/xpcom/glue/staticruntime/Makefile.in b/xpcom/glue/staticruntime/Makefile.in index a5daa703726..3bec2c73e95 100644 --- a/xpcom/glue/staticruntime/Makefile.in +++ b/xpcom/glue/staticruntime/Makefile.in @@ -6,9 +6,6 @@ DIST_INSTALL = 1 -# Don't use STL wrappers here (i.e. wrapped ); they require mozalloc -STL_FLAGS = - include $(topsrcdir)/config/rules.mk ifdef _MSC_VER diff --git a/xpcom/glue/staticruntime/moz.build b/xpcom/glue/staticruntime/moz.build index 22cd15f0182..e0f46473327 100644 --- a/xpcom/glue/staticruntime/moz.build +++ b/xpcom/glue/staticruntime/moz.build @@ -34,3 +34,6 @@ LOCAL_INCLUDES += [ # Statically link to the CRT on Windows USE_STATIC_LIBS = True + +# Don't use STL wrappers here (i.e. wrapped ); they require mozalloc +DISABLE_STL_WRAPPING = True diff --git a/xulrunner/app/Makefile.in b/xulrunner/app/Makefile.in index db866a90cbc..5a3ffae5ac1 100644 --- a/xulrunner/app/Makefile.in +++ b/xulrunner/app/Makefile.in @@ -8,8 +8,6 @@ GARBAGE += $(addprefix $(DIST)/bin/defaults/pref/,xulrunner.js) DEFINES += -DAB_CD=$(AB_CD) -STL_FLAGS= - ifeq (cocoa,$(MOZ_WIDGET_TOOLKIT)) TK_LIBS := -framework Cocoa $(TK_LIBS) endif diff --git a/xulrunner/app/moz.build b/xulrunner/app/moz.build index 659437fbcbd..23c5ae23670 100644 --- a/xulrunner/app/moz.build +++ b/xulrunner/app/moz.build @@ -45,3 +45,5 @@ if CONFIG['OS_ARCH'] == 'WINNT' and not CONFIG['GNU_CC']: if CONFIG['OS_ARCH'] == 'WINNT': RCINCLUDE = 'splash.rc' + +DISABLE_STL_WRAPPING = True diff --git a/xulrunner/stub/Makefile.in b/xulrunner/stub/Makefile.in index f4b5f6fd24d..89437002df5 100644 --- a/xulrunner/stub/Makefile.in +++ b/xulrunner/stub/Makefile.in @@ -5,8 +5,6 @@ # Don't create a dependency on mozglue MOZ_GLUE_LDFLAGS = -STL_FLAGS= - LIBS = \ $(XPCOM_STANDALONE_STATICRUNTIME_GLUE_LDOPTS) \ $(NULL) diff --git a/xulrunner/stub/moz.build b/xulrunner/stub/moz.build index 2558369005d..52334d3ca69 100644 --- a/xulrunner/stub/moz.build +++ b/xulrunner/stub/moz.build @@ -37,3 +37,5 @@ if CONFIG['_MSC_VER']: if CONFIG['OS_ARCH'] == 'WINNT': DEFINES['MOZ_XULRUNNER'] = True RCINCLUDE = 'xulrunner-stub.rc' + +DISABLE_STL_WRAPPING = True From 8886b9baac6709ee41c735fe1ebdde7eb294f980 Mon Sep 17 00:00:00 2001 From: Terrence Cole Date: Mon, 17 Feb 2014 17:39:14 -0800 Subject: [PATCH 048/112] Bug 969012 - Use a second register for object allocation; r=jandem --HG-- extra : rebase_source : 2cbc07d17ed3cf84fbc2590745a4c22a62ee573c --- js/src/jit/CodeGenerator.cpp | 67 ++++++----- js/src/jit/CodeGenerator.h | 6 +- js/src/jit/IonBuilder.cpp | 2 +- js/src/jit/IonMacroAssembler.cpp | 161 +++++++++++++++++--------- js/src/jit/IonMacroAssembler.h | 47 ++++---- js/src/jit/LIR-Common.h | 58 ++++++++-- js/src/jit/Lowering.cpp | 12 +- js/src/jit/arm/MacroAssembler-arm.cpp | 8 -- js/src/jit/arm/MacroAssembler-arm.h | 14 +++ js/src/jit/x86/MacroAssembler-x86.h | 6 + 10 files changed, 245 insertions(+), 136 deletions(-) diff --git a/js/src/jit/CodeGenerator.cpp b/js/src/jit/CodeGenerator.cpp index a6c62289f6f..c0898ce5227 100644 --- a/js/src/jit/CodeGenerator.cpp +++ b/js/src/jit/CodeGenerator.cpp @@ -964,6 +964,7 @@ CodeGenerator::visitLambda(LLambda *lir) { Register scopeChain = ToRegister(lir->scopeChain()); Register output = ToRegister(lir->output()); + Register tempReg = ToRegister(lir->temp()); const LambdaFunctionInfo &info = lir->mir()->info(); OutOfLineCode *ool = oolCallVM(LambdaInfo, lir, (ArgList(), ImmGCPtr(info.fun), scopeChain), @@ -973,8 +974,8 @@ CodeGenerator::visitLambda(LLambda *lir) JS_ASSERT(!info.singletonType); - masm.newGCThing(output, info.fun, ool->entry(), gc::DefaultHeap); - masm.initGCThing(output, info.fun); + masm.newGCThing(output, tempReg, info.fun, ool->entry(), gc::DefaultHeap); + masm.initGCThing(output, tempReg, info.fun); emitLambdaInit(output, scopeChain, info); @@ -983,7 +984,7 @@ CodeGenerator::visitLambda(LLambda *lir) } void -CodeGenerator::emitLambdaInit(const Register &output, const Register &scopeChain, +CodeGenerator::emitLambdaInit(Register output, Register scopeChain, const LambdaFunctionInfo &info) { // Initialize nargs and flags. We do this with a single uint32 to avoid @@ -3396,6 +3397,7 @@ CodeGenerator::visitNewArray(LNewArray *lir) { JS_ASSERT(gen->info().executionMode() == SequentialExecution); Register objReg = ToRegister(lir->output()); + Register tempReg = ToRegister(lir->temp()); JSObject *templateObject = lir->mir()->templateObject(); DebugOnly count = lir->mir()->count(); @@ -3408,8 +3410,8 @@ CodeGenerator::visitNewArray(LNewArray *lir) if (!addOutOfLineCode(ool)) return false; - masm.newGCThing(objReg, templateObject, ool->entry(), lir->mir()->initialHeap()); - masm.initGCThing(objReg, templateObject); + masm.newGCThing(objReg, tempReg, templateObject, ool->entry(), lir->mir()->initialHeap()); + masm.initGCThing(objReg, tempReg, templateObject); masm.bind(ool->rejoin()); return true; @@ -3485,6 +3487,7 @@ CodeGenerator::visitNewObject(LNewObject *lir) { JS_ASSERT(gen->info().executionMode() == SequentialExecution); Register objReg = ToRegister(lir->output()); + Register tempReg = ToRegister(lir->temp()); JSObject *templateObject = lir->mir()->templateObject(); if (lir->mir()->shouldUseVM()) @@ -3494,8 +3497,8 @@ CodeGenerator::visitNewObject(LNewObject *lir) if (!addOutOfLineCode(ool)) return false; - masm.newGCThing(objReg, templateObject, ool->entry(), lir->mir()->initialHeap()); - masm.initGCThing(objReg, templateObject); + masm.newGCThing(objReg, tempReg, templateObject, ool->entry(), lir->mir()->initialHeap()); + masm.initGCThing(objReg, tempReg, templateObject); masm.bind(ool->rejoin()); return true; @@ -3517,7 +3520,8 @@ static const VMFunction NewDeclEnvObjectInfo = bool CodeGenerator::visitNewDeclEnvObject(LNewDeclEnvObject *lir) { - Register obj = ToRegister(lir->output()); + Register objReg = ToRegister(lir->output()); + Register tempReg = ToRegister(lir->temp()); JSObject *templateObj = lir->mir()->templateObj(); CompileInfo &info = lir->mir()->block()->info(); @@ -3525,12 +3529,12 @@ CodeGenerator::visitNewDeclEnvObject(LNewDeclEnvObject *lir) OutOfLineCode *ool = oolCallVM(NewDeclEnvObjectInfo, lir, (ArgList(), ImmGCPtr(info.funMaybeLazy()), Imm32(gc::DefaultHeap)), - StoreRegisterTo(obj)); + StoreRegisterTo(objReg)); if (!ool) return false; - masm.newGCThing(obj, templateObj, ool->entry(), gc::DefaultHeap); - masm.initGCThing(obj, templateObj); + masm.newGCThing(objReg, tempReg, templateObj, ool->entry(), gc::DefaultHeap); + masm.initGCThing(objReg, tempReg, templateObj); masm.bind(ool->rejoin()); return true; } @@ -3543,7 +3547,8 @@ static const VMFunction NewCallObjectInfo = bool CodeGenerator::visitNewCallObject(LNewCallObject *lir) { - Register obj = ToRegister(lir->output()); + Register objReg = ToRegister(lir->output()); + Register tempReg = ToRegister(lir->temp()); JSObject *templateObj = lir->mir()->templateObject(); @@ -3555,14 +3560,14 @@ CodeGenerator::visitNewCallObject(LNewCallObject *lir) ImmGCPtr(templateObj->lastProperty()), ImmGCPtr(templateObj->hasSingletonType() ? nullptr : templateObj->type()), ToRegister(lir->slots())), - StoreRegisterTo(obj)); + StoreRegisterTo(objReg)); } else { ool = oolCallVM(NewCallObjectInfo, lir, (ArgList(), ImmGCPtr(lir->mir()->block()->info().script()), ImmGCPtr(templateObj->lastProperty()), ImmGCPtr(templateObj->hasSingletonType() ? nullptr : templateObj->type()), ImmPtr(nullptr)), - StoreRegisterTo(obj)); + StoreRegisterTo(objReg)); } if (!ool) return false; @@ -3571,11 +3576,11 @@ CodeGenerator::visitNewCallObject(LNewCallObject *lir) // Objects can only be given singleton types in VM calls. masm.jump(ool->entry()); } else { - masm.newGCThing(obj, templateObj, ool->entry(), gc::DefaultHeap); - masm.initGCThing(obj, templateObj); + masm.newGCThing(objReg, tempReg, templateObj, ool->entry(), gc::DefaultHeap); + masm.initGCThing(objReg, tempReg, templateObj); if (lir->slots()->isRegister()) - masm.storePtr(ToRegister(lir->slots()), Address(obj, JSObject::offsetOfSlots())); + masm.storePtr(ToRegister(lir->slots()), Address(objReg, JSObject::offsetOfSlots())); } masm.bind(ool->rejoin()); @@ -3661,8 +3666,8 @@ CodeGenerator::visitNewStringObject(LNewStringObject *lir) if (!ool) return false; - masm.newGCThing(output, templateObj, ool->entry(), gc::DefaultHeap); - masm.initGCThing(output, templateObj); + masm.newGCThing(output, temp, templateObj, ool->entry(), gc::DefaultHeap); + masm.initGCThing(output, temp, templateObj); masm.loadStringLength(input, temp); @@ -3704,9 +3709,8 @@ public: }; bool -CodeGenerator::emitAllocateGCThingPar(LInstruction *lir, const Register &objReg, - const Register &cxReg, const Register &tempReg1, - const Register &tempReg2, JSObject *templateObj) +CodeGenerator::emitAllocateGCThingPar(LInstruction *lir, Register objReg, Register cxReg, + Register tempReg1, Register tempReg2, JSObject *templateObj) { gc::AllocKind allocKind = templateObj->tenuredGetAllocKind(); OutOfLineNewGCThingPar *ool = new(alloc()) OutOfLineNewGCThingPar(lir, allocKind, objReg, cxReg); @@ -3715,7 +3719,7 @@ CodeGenerator::emitAllocateGCThingPar(LInstruction *lir, const Register &objReg, masm.newGCThingPar(objReg, cxReg, tempReg1, tempReg2, templateObj, ool->entry()); masm.bind(ool->rejoin()); - masm.initGCThing(objReg, templateObj); + masm.initGCThing(objReg, tempReg1, templateObj); return true; } @@ -3899,6 +3903,7 @@ CodeGenerator::visitCreateThisWithTemplate(LCreateThisWithTemplate *lir) gc::AllocKind allocKind = templateObject->tenuredGetAllocKind(); gc::InitialHeap initialHeap = lir->mir()->initialHeap(); Register objReg = ToRegister(lir->output()); + Register tempReg = ToRegister(lir->temp()); OutOfLineCode *ool = oolCallVM(NewGCObjectInfo, lir, (ArgList(), Imm32(allocKind), Imm32(initialHeap)), @@ -3907,11 +3912,11 @@ CodeGenerator::visitCreateThisWithTemplate(LCreateThisWithTemplate *lir) return false; // Allocate. If the FreeList is empty, call to VM, which may GC. - masm.newGCThing(objReg, templateObject, ool->entry(), lir->mir()->initialHeap()); + masm.newGCThing(objReg, tempReg, templateObject, ool->entry(), lir->mir()->initialHeap()); // Initialize based on the templateObject. masm.bind(ool->rejoin()); - masm.initGCThing(objReg, templateObject); + masm.initGCThing(objReg, tempReg, templateObject); return true; } @@ -4865,7 +4870,7 @@ JitCompartment::generateStringConcatStub(JSContext *cx, ExecutionMode mode) // Allocate a new rope. switch (mode) { case SequentialExecution: - masm.newGCString(output, &failure); + masm.newGCString(output, temp3, &failure); break; case ParallelExecution: masm.push(temp1); @@ -4910,7 +4915,7 @@ JitCompartment::generateStringConcatStub(JSContext *cx, ExecutionMode mode) // Allocate a JSShortString. switch (mode) { case SequentialExecution: - masm.newGCShortString(output, &failure); + masm.newGCShortString(output, temp3, &failure); break; case ParallelExecution: masm.push(temp1); @@ -5630,8 +5635,8 @@ CodeGenerator::visitArrayConcat(LArrayConcat *lir) // Try to allocate an object. JSObject *templateObj = lir->mir()->templateObj(); - masm.newGCThing(temp1, templateObj, &fail, lir->mir()->initialHeap()); - masm.initGCThing(temp1, templateObj); + masm.newGCThing(temp1, temp2, templateObj, &fail, lir->mir()->initialHeap()); + masm.initGCThing(temp1, temp2, templateObj); masm.jump(&call); { masm.bind(&fail); @@ -6002,8 +6007,8 @@ CodeGenerator::visitRest(LRest *lir) JSObject *templateObject = lir->mir()->templateObject(); Label joinAlloc, failAlloc; - masm.newGCThing(temp2, templateObject, &failAlloc, gc::DefaultHeap); - masm.initGCThing(temp2, templateObject); + masm.newGCThing(temp2, temp0, templateObject, &failAlloc, gc::DefaultHeap); + masm.initGCThing(temp2, temp0, templateObject); masm.jump(&joinAlloc); { masm.bind(&failAlloc); diff --git a/js/src/jit/CodeGenerator.h b/js/src/jit/CodeGenerator.h index bceff37aefe..007500b8479 100644 --- a/js/src/jit/CodeGenerator.h +++ b/js/src/jit/CodeGenerator.h @@ -366,13 +366,13 @@ class CodeGenerator : public CodeGeneratorSpecific bool generateBranchV(const ValueOperand &value, Label *ifTrue, Label *ifFalse, FloatRegister fr); - bool emitAllocateGCThingPar(LInstruction *lir, const Register &objReg, const Register &cxReg, - const Register &tempReg1, const Register &tempReg2, + bool emitAllocateGCThingPar(LInstruction *lir, Register objReg, Register cxReg, + Register tempReg1, Register tempReg2, JSObject *templateObj); bool emitCallToUncompiledScriptPar(LInstruction *lir, Register calleeReg); - void emitLambdaInit(const Register &resultReg, const Register &scopeChainReg, + void emitLambdaInit(Register resultReg, Register scopeChainReg, const LambdaFunctionInfo &info); bool emitFilterArgumentsOrEval(LInstruction *lir, Register string, Register temp1, diff --git a/js/src/jit/IonBuilder.cpp b/js/src/jit/IonBuilder.cpp index fdd6bf0af0c..73921f18557 100644 --- a/js/src/jit/IonBuilder.cpp +++ b/js/src/jit/IonBuilder.cpp @@ -7928,7 +7928,7 @@ IonBuilder::jsop_rest() // Unroll the argument copy loop. We don't need to do any bounds or hole // checking here. - MConstant *index; + MConstant *index = nullptr; for (unsigned i = numFormals; i < numActuals; i++) { index = MConstant::New(alloc(), Int32Value(i - numFormals)); current->add(index); diff --git a/js/src/jit/IonMacroAssembler.cpp b/js/src/jit/IonMacroAssembler.cpp index 269ec33d31b..3b3723d4abb 100644 --- a/js/src/jit/IonMacroAssembler.cpp +++ b/js/src/jit/IonMacroAssembler.cpp @@ -361,7 +361,7 @@ MacroAssembler::branchNurseryPtr(Condition cond, const Address &ptr1, const ImmM } void -MacroAssembler::moveNurseryPtr(const ImmMaybeNurseryPtr &ptr, const Register ®) +MacroAssembler::moveNurseryPtr(const ImmMaybeNurseryPtr &ptr, Register reg) { #ifdef JSGC_GENERATIONAL if (ptr.value && gc::IsInsideNursery(GetIonContext()->cx->runtime(), (void *)ptr.value)) @@ -634,7 +634,7 @@ MacroAssembler::clampDoubleToUint8(FloatRegister input, Register output) } void -MacroAssembler::newGCThing(const Register &result, gc::AllocKind allocKind, Label *fail, +MacroAssembler::newGCThing(Register result, Register temp, gc::AllocKind allocKind, Label *fail, gc::InitialHeap initialHeap /* = gc::DefaultHeap */) { // Inlined equivalent of js::gc::NewGCThing() without failure case handling. @@ -662,10 +662,9 @@ MacroAssembler::newGCThing(const Register &result, gc::AllocKind allocKind, Labe // in such cases. const Nursery &nursery = GetIonContext()->runtime->gcNursery(); loadPtr(AbsoluteAddress(nursery.addressOfPosition()), result); - addPtr(Imm32(thingSize), result); - branchPtr(Assembler::BelowOrEqual, AbsoluteAddress(nursery.addressOfCurrentEnd()), result, fail); - storePtr(result, AbsoluteAddress(nursery.addressOfPosition())); - subPtr(Imm32(thingSize), result); + computeEffectiveAddress(Address(result, thingSize), temp); + branchPtr(Assembler::BelowOrEqual, AbsoluteAddress(nursery.addressOfCurrentEnd()), temp, fail); + storePtr(temp, AbsoluteAddress(nursery.addressOfPosition())); return; } #endif // JSGC_GENERATIONAL @@ -678,37 +677,34 @@ MacroAssembler::newGCThing(const Register &result, gc::AllocKind allocKind, Labe // which the code below always re-reads. loadPtr(AbsoluteAddress(zone->addressOfFreeListFirst(allocKind)), result); branchPtr(Assembler::BelowOrEqual, AbsoluteAddress(zone->addressOfFreeListLast(allocKind)), result, fail); - - addPtr(Imm32(thingSize), result); - storePtr(result, AbsoluteAddress(zone->addressOfFreeListFirst(allocKind))); - subPtr(Imm32(thingSize), result); + computeEffectiveAddress(Address(result, thingSize), temp); + storePtr(temp, AbsoluteAddress(zone->addressOfFreeListFirst(allocKind))); } void -MacroAssembler::newGCThing(const Register &result, JSObject *templateObject, - Label *fail, gc::InitialHeap initialHeap) +MacroAssembler::newGCThing(Register result, Register temp, JSObject *templateObject, Label *fail, + gc::InitialHeap initialHeap) { gc::AllocKind allocKind = templateObject->tenuredGetAllocKind(); JS_ASSERT(allocKind >= gc::FINALIZE_OBJECT0 && allocKind <= gc::FINALIZE_OBJECT_LAST); - newGCThing(result, allocKind, fail, initialHeap); + newGCThing(result, temp, allocKind, fail, initialHeap); } void -MacroAssembler::newGCString(const Register &result, Label *fail) +MacroAssembler::newGCString(Register result, Register temp, Label *fail) { - newGCThing(result, js::gc::FINALIZE_STRING, fail); + newGCThing(result, temp, js::gc::FINALIZE_STRING, fail); } void -MacroAssembler::newGCShortString(const Register &result, Label *fail) +MacroAssembler::newGCShortString(Register result, Register temp, Label *fail) { - newGCThing(result, js::gc::FINALIZE_SHORT_STRING, fail); + newGCThing(result, temp, js::gc::FINALIZE_SHORT_STRING, fail); } void -MacroAssembler::newGCThingPar(const Register &result, const Register &cx, - const Register &tempReg1, const Register &tempReg2, +MacroAssembler::newGCThingPar(Register result, Register cx, Register tempReg1, Register tempReg2, gc::AllocKind allocKind, Label *fail) { // Similar to ::newGCThing(), except that it allocates from a custom @@ -755,8 +751,7 @@ MacroAssembler::newGCThingPar(const Register &result, const Register &cx, } void -MacroAssembler::newGCThingPar(const Register &result, const Register &cx, - const Register &tempReg1, const Register &tempReg2, +MacroAssembler::newGCThingPar(Register result, Register cx, Register tempReg1, Register tempReg2, JSObject *templateObject, Label *fail) { gc::AllocKind allocKind = templateObject->tenuredGetAllocKind(); @@ -766,69 +761,127 @@ MacroAssembler::newGCThingPar(const Register &result, const Register &cx, } void -MacroAssembler::newGCStringPar(const Register &result, const Register &cx, - const Register &tempReg1, const Register &tempReg2, +MacroAssembler::newGCStringPar(Register result, Register cx, Register tempReg1, Register tempReg2, Label *fail) { newGCThingPar(result, cx, tempReg1, tempReg2, js::gc::FINALIZE_STRING, fail); } void -MacroAssembler::newGCShortStringPar(const Register &result, const Register &cx, - const Register &tempReg1, const Register &tempReg2, - Label *fail) +MacroAssembler::newGCShortStringPar(Register result, Register cx, Register tempReg1, + Register tempReg2, Label *fail) { newGCThingPar(result, cx, tempReg1, tempReg2, js::gc::FINALIZE_SHORT_STRING, fail); } void -MacroAssembler::initGCThing(const Register &obj, JSObject *templateObject) +MacroAssembler::copySlotsFromTemplate(Register obj, Register temp, const JSObject *templateObj, + uint32_t start, uint32_t end) +{ + uint32_t nfixed = Min(templateObj->numFixedSlots(), end); + for (unsigned i = start; i < nfixed; i++) + storeValue(templateObj->getFixedSlot(i), Address(obj, JSObject::getFixedSlotOffset(i))); +} + +void +MacroAssembler::fillSlotsWithUndefined(Register obj, Register temp, const JSObject *templateObj, + uint32_t start, uint32_t end) +{ +#ifdef JS_NUNBOX32 + // We only have a single spare register, so do the initialization as two + // strided writes of the tag and body. + jsval_layout jv = JSVAL_TO_IMPL(UndefinedValue()); + uint32_t nfixed = Min(templateObj->numFixedSlots(), end); + + mov(ImmWord(jv.s.tag), temp); + for (unsigned i = start; i < nfixed; i++) + store32(temp, ToType(Address(obj, JSObject::getFixedSlotOffset(i)))); + + mov(ImmWord(jv.s.payload.i32), temp); + for (unsigned i = start; i < nfixed; i++) + store32(temp, ToPayload(Address(obj, JSObject::getFixedSlotOffset(i)))); +#else + moveValue(UndefinedValue(), temp); + uint32_t nfixed = Min(templateObj->numFixedSlots(), end); + for (unsigned i = start; i < nfixed; i++) + storePtr(temp, Address(obj, JSObject::getFixedSlotOffset(i))); +#endif +} + +static uint32_t +FindStartOfUndefinedSlots(JSObject *templateObj, uint32_t nslots) +{ + JS_ASSERT(nslots == templateObj->lastProperty()->slotSpan(templateObj->getClass())); + JS_ASSERT(nslots > 0); + for (uint32_t first = nslots; first != 0; --first) { + if (templateObj->getSlot(first - 1) != UndefinedValue()) + return first; + } + return 0; +} + +void +MacroAssembler::initGCSlots(Register obj, Register temp, JSObject *templateObj) +{ + // Slots of non-array objects are required to be initialized. + // Use the values currently in the template object. + uint32_t nslots = templateObj->lastProperty()->slotSpan(templateObj->getClass()); + if (nslots == 0) + return; + + // Attempt to group slot writes such that we minimize the amount of + // duplicated data we need to embed in code and load into registers. In + // general, most template object slots will be undefined except for any + // reserved slots. Since reserved slots come first, we split the object + // logically into independent non-UndefinedValue writes to the head and + // duplicated writes of UndefinedValue to the tail. For the majority of + // objects, the "tail" will be the entire slot range. + uint32_t startOfUndefined = FindStartOfUndefinedSlots(templateObj, nslots); + copySlotsFromTemplate(obj, temp, templateObj, 0, startOfUndefined); + fillSlotsWithUndefined(obj, temp, templateObj, startOfUndefined, nslots); +} + +void +MacroAssembler::initGCThing(Register obj, Register temp, JSObject *templateObj) { // Fast initialization of an empty object returned by NewGCThing(). - JS_ASSERT(!templateObject->hasDynamicElements()); + JS_ASSERT(!templateObj->hasDynamicElements()); - storePtr(ImmGCPtr(templateObject->lastProperty()), Address(obj, JSObject::offsetOfShape())); - storePtr(ImmGCPtr(templateObject->type()), Address(obj, JSObject::offsetOfType())); + storePtr(ImmGCPtr(templateObj->lastProperty()), Address(obj, JSObject::offsetOfShape())); + storePtr(ImmGCPtr(templateObj->type()), Address(obj, JSObject::offsetOfType())); storePtr(ImmPtr(nullptr), Address(obj, JSObject::offsetOfSlots())); - if (templateObject->is()) { - JS_ASSERT(!templateObject->getDenseInitializedLength()); + if (templateObj->is()) { + JS_ASSERT(!templateObj->getDenseInitializedLength()); int elementsOffset = JSObject::offsetOfFixedElements(); - addPtr(Imm32(elementsOffset), obj); - storePtr(obj, Address(obj, -elementsOffset + JSObject::offsetOfElements())); - addPtr(Imm32(-elementsOffset), obj); + computeEffectiveAddress(Address(obj, elementsOffset), temp); + storePtr(temp, Address(obj, JSObject::offsetOfElements())); // Fill in the elements header. - store32(Imm32(templateObject->getDenseCapacity()), + store32(Imm32(templateObj->getDenseCapacity()), Address(obj, elementsOffset + ObjectElements::offsetOfCapacity())); - store32(Imm32(templateObject->getDenseInitializedLength()), + store32(Imm32(templateObj->getDenseInitializedLength()), Address(obj, elementsOffset + ObjectElements::offsetOfInitializedLength())); - store32(Imm32(templateObject->as().length()), + store32(Imm32(templateObj->as().length()), Address(obj, elementsOffset + ObjectElements::offsetOfLength())); - store32(Imm32(templateObject->shouldConvertDoubleElements() + store32(Imm32(templateObj->shouldConvertDoubleElements() ? ObjectElements::CONVERT_DOUBLE_ELEMENTS : 0), Address(obj, elementsOffset + ObjectElements::offsetOfFlags())); + JS_ASSERT(!templateObj->hasPrivate()); } else { storePtr(ImmPtr(emptyObjectElements), Address(obj, JSObject::offsetOfElements())); - // Fixed slots of non-array objects are required to be initialized. - // Use the values currently in the template object. - size_t nslots = Min(templateObject->numFixedSlots(), - templateObject->lastProperty()->slotSpan(templateObject->getClass())); - for (unsigned i = 0; i < nslots; i++) { - storeValue(templateObject->getFixedSlot(i), - Address(obj, JSObject::getFixedSlotOffset(i))); - } - } + initGCSlots(obj, temp, templateObj); - if (templateObject->hasPrivate()) { - uint32_t nfixed = templateObject->numFixedSlots(); - storePtr(ImmPtr(templateObject->getPrivate()), - Address(obj, JSObject::getPrivateDataOffset(nfixed))); + if (templateObj->hasPrivate()) { + uint32_t nfixed = templateObj->numFixedSlots(); + storePtr(ImmPtr(templateObj->getPrivate()), + Address(obj, JSObject::getPrivateDataOffset(nfixed))); + } } } @@ -870,7 +923,7 @@ MacroAssembler::compareStrings(JSOp op, Register left, Register right, Register } void -MacroAssembler::checkInterruptFlagPar(const Register &tempReg, Label *fail) +MacroAssembler::checkInterruptFlagPar(Register tempReg, Label *fail) { #ifdef JS_THREADSAFE movePtr(ImmPtr(GetIonContext()->runtime->addressOfInterruptPar()), tempReg); @@ -1819,7 +1872,7 @@ MacroAssembler::branchIfNotInterpretedConstructor(Register fun, Register scratch } void -MacroAssembler::branchEqualTypeIfNeeded(MIRType type, MDefinition *maybeDef, const Register &tag, +MacroAssembler::branchEqualTypeIfNeeded(MIRType type, MDefinition *maybeDef, Register tag, Label *label) { if (!maybeDef || maybeDef->mightBeType(type)) { diff --git a/js/src/jit/IonMacroAssembler.h b/js/src/jit/IonMacroAssembler.h index 230428fc0d0..7e889d447db 100644 --- a/js/src/jit/IonMacroAssembler.h +++ b/js/src/jit/IonMacroAssembler.h @@ -352,13 +352,13 @@ class MacroAssembler : public MacroAssemblerSpecific } // Branches to |label| if |reg| is false. |reg| should be a C++ bool. - void branchIfFalseBool(const Register ®, Label *label) { + void branchIfFalseBool(Register reg, Label *label) { // Note that C++ bool is only 1 byte, so ignore the higher-order bits. branchTest32(Assembler::Zero, reg, Imm32(0xFF), label); } // Branches to |label| if |reg| is true. |reg| should be a C++ bool. - void branchIfTrueBool(const Register ®, Label *label) { + void branchIfTrueBool(Register reg, Label *label) { // Note that C++ bool is only 1 byte, so ignore the higher-order bits. branchTest32(Assembler::NonZero, reg, Imm32(0xFF), label); } @@ -381,10 +381,10 @@ class MacroAssembler : public MacroAssemblerSpecific loadPtr(Address(worker, ThreadPoolWorker::offsetOfSliceBounds()), dest); } - void loadJSContext(const Register &dest) { + void loadJSContext(Register dest) { loadPtr(AbsoluteAddress(GetIonContext()->runtime->addressOfJSContext()), dest); } - void loadJitActivation(const Register &dest) { + void loadJitActivation(Register dest) { loadPtr(AbsoluteAddress(GetIonContext()->runtime->addressOfActivation()), dest); } @@ -634,7 +634,7 @@ class MacroAssembler : public MacroAssemblerSpecific branch32(cond, length, Imm32(key.constant()), label); } - void branchTestNeedsBarrier(Condition cond, const Register &scratch, Label *label) { + void branchTestNeedsBarrier(Condition cond, Register scratch, Label *label) { JS_ASSERT(cond == Zero || cond == NonZero); CompileZone *zone = GetIonContext()->compartment->zone(); movePtr(ImmPtr(zone->addressOfNeedsBarrier()), scratch); @@ -690,7 +690,7 @@ class MacroAssembler : public MacroAssemblerSpecific void branchNurseryPtr(Condition cond, const Address &ptr1, const ImmMaybeNurseryPtr &ptr2, Label *label); - void moveNurseryPtr(const ImmMaybeNurseryPtr &ptr, const Register ®); + void moveNurseryPtr(const ImmMaybeNurseryPtr &ptr, Register reg); void canonicalizeDouble(FloatRegister reg) { Label notNaN; @@ -783,30 +783,31 @@ class MacroAssembler : public MacroAssemblerSpecific // Emit type case branch on tag matching if the type tag in the definition // might actually be that type. - void branchEqualTypeIfNeeded(MIRType type, MDefinition *maybeDef, const Register &tag, - Label *label); + void branchEqualTypeIfNeeded(MIRType type, MDefinition *maybeDef, Register tag, Label *label); // Inline allocation. - void newGCThing(const Register &result, gc::AllocKind allocKind, Label *fail, + void newGCThing(Register result, Register temp, gc::AllocKind allocKind, Label *fail, gc::InitialHeap initialHeap = gc::DefaultHeap); - void newGCThing(const Register &result, JSObject *templateObject, Label *fail, + void newGCThing(Register result, Register temp, JSObject *templateObject, Label *fail, gc::InitialHeap initialHeap); - void newGCString(const Register &result, Label *fail); - void newGCShortString(const Register &result, Label *fail); + void newGCString(Register result, Register temp, Label *fail); + void newGCShortString(Register result, Register temp, Label *fail); - void newGCThingPar(const Register &result, const Register &cx, - const Register &tempReg1, const Register &tempReg2, + void newGCThingPar(Register result, Register cx, Register tempReg1, Register tempReg2, gc::AllocKind allocKind, Label *fail); - void newGCThingPar(const Register &result, const Register &cx, - const Register &tempReg1, const Register &tempReg2, + void newGCThingPar(Register result, Register cx, Register tempReg1, Register tempReg2, JSObject *templateObject, Label *fail); - void newGCStringPar(const Register &result, const Register &cx, - const Register &tempReg1, const Register &tempReg2, + void newGCStringPar(Register result, Register cx, Register tempReg1, Register tempReg2, Label *fail); - void newGCShortStringPar(const Register &result, const Register &cx, - const Register &tempReg1, const Register &tempReg2, + void newGCShortStringPar(Register result, Register cx, Register tempReg1, Register tempReg2, Label *fail); - void initGCThing(const Register &obj, JSObject *templateObject); + + void copySlotsFromTemplate(Register obj, Register temp, const JSObject *templateObj, + uint32_t start, uint32_t end); + void fillSlotsWithUndefined(Register obj, Register temp, const JSObject *templateObj, + uint32_t start, uint32_t end); + void initGCSlots(Register obj, Register temp, JSObject *templateObj); + void initGCThing(Register obj, Register temp, JSObject *templateObj); // Compares two strings for equality based on the JSOP. // This checks for identical pointers, atoms and length and fails for everything else. @@ -815,7 +816,7 @@ class MacroAssembler : public MacroAssemblerSpecific // Checks the flags that signal that parallel code may need to interrupt or // abort. Branches to fail in that case. - void checkInterruptFlagPar(const Register &tempReg, Label *fail); + void checkInterruptFlagPar(Register tempReg, Label *fail); // If the JitCode that created this assembler needs to transition into the VM, // we want to store the JitCode on the stack in order to mark it during a GC. @@ -903,7 +904,7 @@ class MacroAssembler : public MacroAssemblerSpecific } // see above comment for what is returned - uint32_t callIon(const Register &callee) { + uint32_t callIon(Register callee) { leaveSPSFrame(); MacroAssemblerSpecific::callIon(callee); uint32_t ret = currentOffset(); diff --git a/js/src/jit/LIR-Common.h b/js/src/jit/LIR-Common.h index 44a1ad7ade6..1b8d8a6590f 100644 --- a/js/src/jit/LIR-Common.h +++ b/js/src/jit/LIR-Common.h @@ -328,29 +328,45 @@ class LNewSlots : public LCallInstructionHelper<1, 0, 3> } }; -class LNewArray : public LInstructionHelper<1, 0, 0> +class LNewArray : public LInstructionHelper<1, 0, 1> { public: LIR_HEADER(NewArray) + LNewArray(const LDefinition &temp) { + setTemp(0, temp); + } + const char *extraName() const { return mir()->shouldUseVM() ? "VMCall" : nullptr; } + const LDefinition *temp() { + return getTemp(0); + } + MNewArray *mir() const { return mir_->toNewArray(); } }; -class LNewObject : public LInstructionHelper<1, 0, 0> +class LNewObject : public LInstructionHelper<1, 0, 1> { public: LIR_HEADER(NewObject) + LNewObject(const LDefinition &temp) { + setTemp(0, temp); + } + const char *extraName() const { return mir()->shouldUseVM() ? "VMCall" : nullptr; } + const LDefinition *temp() { + return getTemp(0); + } + MNewObject *mir() const { return mir_->toNewObject(); } @@ -430,11 +446,19 @@ class LNewDenseArrayPar : public LCallInstructionHelper<1, 2, 3> // (1) An inline allocation of the call object is attempted. // (2) Otherwise, a callVM create a new object. // -class LNewDeclEnvObject : public LInstructionHelper<1, 0, 0> +class LNewDeclEnvObject : public LInstructionHelper<1, 0, 1> { public: LIR_HEADER(NewDeclEnvObject); + LNewDeclEnvObject(const LDefinition &temp) { + setTemp(0, temp); + } + + const LDefinition *temp() { + return getTemp(0); + } + MNewDeclEnvObject *mir() const { return mir_->toNewDeclEnvObject(); } @@ -449,13 +473,18 @@ class LNewDeclEnvObject : public LInstructionHelper<1, 0, 0> // call object. // (2) Otherwise, an inline allocation of the call object is attempted. // -class LNewCallObject : public LInstructionHelper<1, 1, 0> +class LNewCallObject : public LInstructionHelper<1, 1, 1> { public: LIR_HEADER(NewCallObject) - LNewCallObject(const LAllocation &slots) { + LNewCallObject(const LAllocation &slots, const LDefinition &temp) { setOperand(0, slots); + setTemp(0, temp); + } + + const LDefinition *temp() { + return getTemp(0); } const LAllocation *slots() { @@ -883,17 +912,22 @@ class LCreateThisWithProto : public LCallInstructionHelper<1, 2, 0> // Allocate an object for |new| on the caller-side. // Always performs object initialization with a fast path. -class LCreateThisWithTemplate : public LInstructionHelper<1, 0, 0> +class LCreateThisWithTemplate : public LInstructionHelper<1, 0, 1> { public: LIR_HEADER(CreateThisWithTemplate) - LCreateThisWithTemplate() - { } + LCreateThisWithTemplate(const LDefinition &temp) { + setTemp(0, temp); + } MCreateThisWithTemplate *mir() const { return mir_->toCreateThisWithTemplate(); } + + const LDefinition *temp() { + return getTemp(0); + } }; // Allocate a new arguments object for the frame. @@ -3396,17 +3430,21 @@ class LLambdaForSingleton : public LCallInstructionHelper<1, 1, 0> } }; -class LLambda : public LInstructionHelper<1, 1, 0> +class LLambda : public LInstructionHelper<1, 1, 1> { public: LIR_HEADER(Lambda) - LLambda(const LAllocation &scopeChain) { + LLambda(const LAllocation &scopeChain, const LDefinition &temp) { setOperand(0, scopeChain); + setTemp(0, temp); } const LAllocation *scopeChain() { return getOperand(0); } + const LDefinition *temp() { + return getTemp(0); + } const MLambda *mir() const { return mir_->toLambda(); } diff --git a/js/src/jit/Lowering.cpp b/js/src/jit/Lowering.cpp index f6e5ba026f2..bff96c4ddec 100644 --- a/js/src/jit/Lowering.cpp +++ b/js/src/jit/Lowering.cpp @@ -174,21 +174,21 @@ LIRGenerator::visitNewSlots(MNewSlots *ins) bool LIRGenerator::visitNewArray(MNewArray *ins) { - LNewArray *lir = new(alloc()) LNewArray(); + LNewArray *lir = new(alloc()) LNewArray(temp()); return define(lir, ins) && assignSafepoint(lir, ins); } bool LIRGenerator::visitNewObject(MNewObject *ins) { - LNewObject *lir = new(alloc()) LNewObject(); + LNewObject *lir = new(alloc()) LNewObject(temp()); return define(lir, ins) && assignSafepoint(lir, ins); } bool LIRGenerator::visitNewDeclEnvObject(MNewDeclEnvObject *ins) { - LNewDeclEnvObject *lir = new(alloc()) LNewDeclEnvObject(); + LNewDeclEnvObject *lir = new(alloc()) LNewDeclEnvObject(temp()); return define(lir, ins) && assignSafepoint(lir, ins); } @@ -201,7 +201,7 @@ LIRGenerator::visitNewCallObject(MNewCallObject *ins) else slots = LConstantIndex::Bogus(); - LNewCallObject *lir = new(alloc()) LNewCallObject(slots); + LNewCallObject *lir = new(alloc()) LNewCallObject(slots, temp()); if (!define(lir, ins)) return false; @@ -311,7 +311,7 @@ LIRGenerator::visitInitPropGetterSetter(MInitPropGetterSetter *ins) bool LIRGenerator::visitCreateThisWithTemplate(MCreateThisWithTemplate *ins) { - LCreateThisWithTemplate *lir = new(alloc()) LCreateThisWithTemplate(); + LCreateThisWithTemplate *lir = new(alloc()) LCreateThisWithTemplate(temp()); return define(lir, ins) && assignSafepoint(lir, ins); } @@ -2026,7 +2026,7 @@ LIRGenerator::visitLambda(MLambda *ins) return defineReturn(lir, ins) && assignSafepoint(lir, ins); } - LLambda *lir = new(alloc()) LLambda(useRegister(ins->scopeChain())); + LLambda *lir = new(alloc()) LLambda(useRegister(ins->scopeChain()), temp()); return define(lir, ins) && assignSafepoint(lir, ins); } diff --git a/js/src/jit/arm/MacroAssembler-arm.cpp b/js/src/jit/arm/MacroAssembler-arm.cpp index 1cff932432f..f0ed5ab4420 100644 --- a/js/src/jit/arm/MacroAssembler-arm.cpp +++ b/js/src/jit/arm/MacroAssembler-arm.cpp @@ -2531,14 +2531,6 @@ MacroAssemblerARMCompat::branchFloat(DoubleCondition cond, const FloatRegister & ma_b(label, ConditionFromDoubleCondition(cond)); } -// higher level tag testing code -Operand ToPayload(Operand base) { - return Operand(Register::FromCode(base.base()), base.disp()); -} -Operand ToType(Operand base) { - return Operand(Register::FromCode(base.base()), base.disp() + sizeof(void *)); -} - Assembler::Condition MacroAssemblerARMCompat::testInt32(Assembler::Condition cond, const ValueOperand &value) { diff --git a/js/src/jit/arm/MacroAssembler-arm.h b/js/src/jit/arm/MacroAssembler-arm.h index 5d6d18b6222..45ecc23b567 100644 --- a/js/src/jit/arm/MacroAssembler-arm.h +++ b/js/src/jit/arm/MacroAssembler-arm.h @@ -35,6 +35,20 @@ class MacroAssemblerARM : public Assembler // baseline IC stubs rely on lr holding the return address. Register secondScratchReg_; + // higher level tag testing code + Operand ToPayload(Operand base) { + return Operand(Register::FromCode(base.base()), base.disp()); + } + Address ToPayload(Address base) { + return ToPayload(Operand(base)).toAddress(); + } + Operand ToType(Operand base) { + return Operand(Register::FromCode(base.base()), base.disp() + sizeof(void *)); + } + Address ToType(Address base) { + return ToType(Operand(base)).toAddress(); + } + public: MacroAssemblerARM() : secondScratchReg_(lr) diff --git a/js/src/jit/x86/MacroAssembler-x86.h b/js/src/jit/x86/MacroAssembler-x86.h index 19a0675967f..69a1fd19e47 100644 --- a/js/src/jit/x86/MacroAssembler-x86.h +++ b/js/src/jit/x86/MacroAssembler-x86.h @@ -91,6 +91,9 @@ class MacroAssemblerX86 : public MacroAssemblerX86Shared Operand ToPayload(Operand base) { return base; } + Address ToPayload(Address base) { + return base; + } Operand ToType(Operand base) { switch (base.kind()) { case Operand::MEM_REG_DISP: @@ -104,6 +107,9 @@ class MacroAssemblerX86 : public MacroAssemblerX86Shared MOZ_ASSUME_UNREACHABLE("unexpected operand kind"); } } + Address ToType(Address base) { + return ToType(Operand(base)).toAddress(); + } void moveValue(const Value &val, Register type, Register data) { jsval_layout jv = JSVAL_TO_IMPL(val); movl(Imm32(jv.s.tag), type); From 2580fda51f8d32fe699dde138329ec07d42db723 Mon Sep 17 00:00:00 2001 From: Haitao Feng Date: Tue, 4 Mar 2014 20:06:25 -0500 Subject: [PATCH 049/112] Bug 943769 Part 1 -- Use macros to declare and define SIMD functions r=nmatsakis --- js/src/builtin/SIMD.cpp | 79 +++++++++++---------------------- js/src/builtin/SIMD.h | 96 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 122 insertions(+), 53 deletions(-) diff --git a/js/src/builtin/SIMD.cpp b/js/src/builtin/SIMD.cpp index 413d0f44b98..114e32dde44 100644 --- a/js/src/builtin/SIMD.cpp +++ b/js/src/builtin/SIMD.cpp @@ -874,63 +874,36 @@ Int32x4Select(JSContext *cx, unsigned argc, Value *vp) return true; } +#define DEFINE_SIMD_FLOAT32X4_FUNCTION(Name, Func, Operands, Flags, MIRId) \ +bool \ +js::simd_float32x4_##Name(JSContext *cx, unsigned argc, Value *vp) \ +{ \ + return Func(cx, argc, vp); \ +} +FLOAT32X4_FUNCTION_LIST(DEFINE_SIMD_FLOAT32X4_FUNCTION) +#undef DEFINE_SIMD_FLOAT32x4_FUNCTION + +#define DEFINE_SIMD_INT32X4_FUNCTION(Name, Func, Operands, Flags, MIRId) \ +bool \ +js::simd_int32x4_##Name(JSContext *cx, unsigned argc, Value *vp) \ +{ \ + return Func(cx, argc, vp); \ +} +INT32X4_FUNCTION_LIST(DEFINE_SIMD_INT32X4_FUNCTION) +#undef DEFINE_SIMD_INT32X4_FUNCTION + const JSFunctionSpec js::Float32x4Methods[] = { - JS_FN("abs", (Func, Float32x4>), 1, 0), - JS_FN("neg", (Func, Float32x4>), 1, 0), - JS_FN("reciprocal", (Func, Float32x4>), 1, 0), - JS_FN("reciprocalSqrt", (Func, Float32x4>), 1, 0), - JS_FN("sqrt", (Func, Float32x4>), 1, 0), - JS_FN("add", (Func, Float32x4>), 2, 0), - JS_FN("sub", (Func, Float32x4>), 2, 0), - JS_FN("div", (Func, Float32x4>), 2, 0), - JS_FN("mul", (Func, Float32x4>), 2, 0), - JS_FN("max", (Func, Float32x4>), 2, 0), - JS_FN("min", (Func, Float32x4>), 2, 0), - JS_FN("lessThan", (Func, Int32x4>), 2, 0), - JS_FN("lessThanOrEqual", (Func, Int32x4>), 2, 0), - JS_FN("greaterThan", (Func, Int32x4>), 2, 0), - JS_FN("greaterThanOrEqual", (Func, Int32x4>), 2, 0), - JS_FN("equal", (Func, Int32x4>), 2, 0), - JS_FN("notEqual", (Func, Int32x4>), 2, 0), - JS_FN("withX", (FuncWith, Float32x4>), 2, 0), - JS_FN("withY", (FuncWith, Float32x4>), 2, 0), - JS_FN("withZ", (FuncWith, Float32x4>), 2, 0), - JS_FN("withW", (FuncWith, Float32x4>), 2, 0), - JS_FN("shuffle", (FuncShuffle, Float32x4>), 2, 0), - JS_FN("shuffleMix", (FuncShuffle, Float32x4>), 3, 0), - JS_FN("scale", (FuncWith, Float32x4>), 2, 0), - JS_FN("clamp", Float32x4Clamp, 3, 0), - JS_FN("toInt32x4", (FuncConvert), 1, 0), - JS_FN("bitsToInt32x4", (FuncConvertBits), 1, 0), - JS_FN("zero", (FuncZero), 0, 0), - JS_FN("splat", (FuncSplat), 0, 0), +#define SIMD_FLOAT32X4_FUNCTION_ITEM(Name, Func, Operands, Flags, MIRId) \ + JS_FN(#Name, js::simd_float32x4_##Name, Operands, Flags), + FLOAT32X4_FUNCTION_LIST(SIMD_FLOAT32X4_FUNCTION_ITEM) +#undef SIMD_FLOAT32x4_FUNCTION_ITEM JS_FS_END }; const JSFunctionSpec js::Int32x4Methods[] = { - JS_FN("not", (Func, Int32x4>), 1, 0), - JS_FN("neg", (Func, Int32x4>), 1, 0), - JS_FN("add", (Func, Int32x4>), 2, 0), - JS_FN("sub", (Func, Int32x4>), 2, 0), - JS_FN("mul", (Func, Int32x4>), 2, 0), - JS_FN("xor", (Func, Int32x4>), 2, 0), - JS_FN("and", (Func, Int32x4>), 2, 0), - JS_FN("or", (Func, Int32x4>), 2, 0), - JS_FN("withX", (FuncWith, Int32x4>), 2, 0), - JS_FN("withY", (FuncWith, Int32x4>), 2, 0), - JS_FN("withZ", (FuncWith, Int32x4>), 2, 0), - JS_FN("withW", (FuncWith, Int32x4>), 2, 0), - JS_FN("withFlagX", (FuncWith, Int32x4>), 2, 0), - JS_FN("withFlagY", (FuncWith, Int32x4>), 2, 0), - JS_FN("withFlagZ", (FuncWith, Int32x4>), 2, 0), - JS_FN("withFlagW", (FuncWith, Int32x4>), 2, 0), - JS_FN("shuffle", (FuncShuffle, Int32x4>), 2, 0), - JS_FN("shuffleMix", (FuncShuffle, Int32x4>), 3, 0), - JS_FN("toFloat32x4", (FuncConvert), 1, 0), - JS_FN("bitsToFloat32x4", (FuncConvertBits), 1, 0), - JS_FN("zero", (FuncZero), 0, 0), - JS_FN("splat", (FuncSplat), 0, 0), - JS_FN("select", Int32x4Select, 3, 0), - JS_FN("bool", Int32x4Bool, 4, 0), +#define SIMD_INT32X4_FUNCTION_ITEM(Name, Func, Operands, Flags, MIRId) \ + JS_FN(#Name, js::simd_int32x4_##Name, Operands, Flags), + INT32X4_FUNCTION_LIST(SIMD_INT32X4_FUNCTION_ITEM) +#undef SIMD_INT32X4_FUNCTION_ITEM JS_FS_END }; diff --git a/js/src/builtin/SIMD.h b/js/src/builtin/SIMD.h index a81f743dcc3..2e2e7c9c5f6 100644 --- a/js/src/builtin/SIMD.h +++ b/js/src/builtin/SIMD.h @@ -18,6 +18,90 @@ * https://github.com/johnmccutchan/ecmascript_simd/blob/master/src/ecmascript_simd.js */ +#define FLOAT32X4_NULLARY_FUNCTION_LIST(V) \ + V(zero, (FuncZero), 0, 0, Zero) + +#define FLOAT32X4_UNARY_FUNCTION_LIST(V) \ + V(abs, (Func, Float32x4>), 1, 0, Abs) \ + V(bitsToInt32x4, (FuncConvertBits), 1, 0, BitsToInt32x4) \ + V(neg, (Func, Float32x4>), 1, 0, Neg) \ + V(reciprocal, (Func, Float32x4>), 1, 0, Reciprocal) \ + V(reciprocalSqrt, (Func, Float32x4>), 1, 0, ReciprocalSqrt) \ + V(splat, (FuncSplat), 1, 0, Splat) \ + V(sqrt, (Func, Float32x4>), 1, 0, Sqrt) \ + V(toInt32x4, (FuncConvert), 1, 0, ToInt32x4) + +#define FLOAT32X4_BINARY_FUNCTION_LIST(V) \ + V(add, (Func, Float32x4>), 2, 0, Add) \ + V(div, (Func, Float32x4>), 2, 0, Div) \ + V(equal, (Func, Int32x4>), 2, 0, Equal) \ + V(greaterThan, (Func, Int32x4>), 2, 0, GreaterThan) \ + V(greaterThanOrEqual, (Func, Int32x4>), 2, 0, GreaterThanOrEqual) \ + V(lessThan, (Func, Int32x4>), 2, 0, LessThan) \ + V(lessThanOrEqual, (Func, Int32x4>), 2, 0, LessThanOrEqual) \ + V(max, (Func, Float32x4>), 2, 0, Max) \ + V(min, (Func, Float32x4>), 2, 0, Min) \ + V(mul, (Func, Float32x4>), 2, 0, Mul) \ + V(notEqual, (Func, Int32x4>), 2, 0, NotEqual) \ + V(shuffle, (FuncShuffle, Float32x4>), 2, 0, Shuffle) \ + V(scale, (FuncWith, Float32x4>), 2, 0, Scale) \ + V(sub, (Func, Float32x4>), 2, 0, Sub) \ + V(withX, (FuncWith, Float32x4>), 2, 0, WithX) \ + V(withY, (FuncWith, Float32x4>), 2, 0, WithY) \ + V(withZ, (FuncWith, Float32x4>), 2, 0, WithZ) \ + V(withW, (FuncWith, Float32x4>), 2, 0, WithW) + +#define FLOAT32X4_TERNARY_FUNCTION_LIST(V) \ + V(clamp, Float32x4Clamp, 3, 0, Clamp) \ + V(shuffleMix, (FuncShuffle, Float32x4>), 3, 0, ShuffleMix) + +#define FLOAT32X4_FUNCTION_LIST(V) \ + FLOAT32X4_NULLARY_FUNCTION_LIST(V) \ + FLOAT32X4_UNARY_FUNCTION_LIST(V) \ + FLOAT32X4_BINARY_FUNCTION_LIST(V) \ + FLOAT32X4_TERNARY_FUNCTION_LIST(V) + +#define INT32X4_NULLARY_FUNCTION_LIST(V) \ + V(zero, (FuncZero), 0, 0, Zero) + +#define INT32X4_UNARY_FUNCTION_LIST(V) \ + V(bitsToFloat32x4, (FuncConvertBits), 1, 0, BitsToFloat32x4) \ + V(neg, (Func, Int32x4>), 1, 0, Neg) \ + V(not, (Func, Int32x4>), 1, 0, Not) \ + V(splat, (FuncSplat), 0, 0, Splat) \ + V(toFloat32x4, (FuncConvert), 1, 0, ToFloat32x4) + +#define INT32X4_BINARY_FUNCTION_LIST(V) \ + V(add, (Func, Int32x4>), 2, 0, Add) \ + V(and, (Func, Int32x4>), 2, 0, And) \ + V(mul, (Func, Int32x4>), 2, 0, Mul) \ + V(or, (Func, Int32x4>), 2, 0, Or) \ + V(sub, (Func, Int32x4>), 2, 0, Sub) \ + V(shuffle, (FuncShuffle, Int32x4>), 2, 0, Shuffle) \ + V(withFlagX, (FuncWith, Int32x4>), 2, 0, WithFlagX) \ + V(withFlagY, (FuncWith, Int32x4>), 2, 0, WithFlagY) \ + V(withFlagZ, (FuncWith, Int32x4>), 2, 0, WithFlagZ) \ + V(withFlagW, (FuncWith, Int32x4>), 2, 0, WithFlagW) \ + V(withX, (FuncWith, Int32x4>), 2, 0, WithX) \ + V(withY, (FuncWith, Int32x4>), 2, 0, WithY) \ + V(withZ, (FuncWith, Int32x4>), 2, 0, WithZ) \ + V(withW, (FuncWith, Int32x4>), 2, 0, WithW) \ + V(xor, (Func, Int32x4>), 2, 0, Xor) + +#define INT32X4_TERNARY_FUNCTION_LIST(V) \ + V(select, Int32x4Select, 3, 0, Select) \ + V(shuffleMix, (FuncShuffle, Int32x4>), 3, 0, ShuffleMix) + +#define INT32X4_QUARTERNARY_FUNCTION_LIST(V) \ + V(bool, Int32x4Bool, 4, 0, Bool) + +#define INT32X4_FUNCTION_LIST(V) \ + INT32X4_NULLARY_FUNCTION_LIST(V) \ + INT32X4_UNARY_FUNCTION_LIST(V) \ + INT32X4_BINARY_FUNCTION_LIST(V) \ + INT32X4_TERNARY_FUNCTION_LIST(V) \ + INT32X4_QUARTERNARY_FUNCTION_LIST(V) + namespace js { class SIMDObject : public JSObject @@ -73,6 +157,18 @@ struct Int32x4 { template JSObject *Create(JSContext *cx, typename V::Elem *data); +#define DECLARE_SIMD_FLOAT32X4_FUNCTION(Name, Func, Operands, Flags, MIRId) \ +extern bool \ +simd_float32x4_##Name(JSContext *cx, unsigned argc, Value *vp); +FLOAT32X4_FUNCTION_LIST(DECLARE_SIMD_FLOAT32X4_FUNCTION) +#undef DECLARE_SIMD_FLOAT32X4_FUNCTION + +#define DECLARE_SIMD_INT32x4_FUNCTION(Name, Func, Operands, Flags, MIRId) \ +extern bool \ +simd_int32x4_##Name(JSContext *cx, unsigned argc, Value *vp); +INT32X4_FUNCTION_LIST(DECLARE_SIMD_INT32x4_FUNCTION) +#undef DECLARE_SIMD_INT32x4_FUNCTION + } /* namespace js */ JSObject * From 888a5613a36f92889494593b98039addb49368dc Mon Sep 17 00:00:00 2001 From: Haitao Feng Date: Tue, 4 Mar 2014 20:06:26 -0500 Subject: [PATCH 050/112] Bug 943769 Part 2 -- Set up SIMD inlining infrastructure r=nmatsakis --- js/src/jit/IonBuilder.h | 6 +- js/src/jit/IonTypes.h | 7 + js/src/jit/MCallOptimize.cpp | 146 ++++++++++++++ js/src/jit/MIR.cpp | 115 ++++++++++- js/src/jit/MIR.h | 277 ++++++++++++++++++++++++++ js/src/jit/MOpcodes.h | 5 + js/src/jit/ParallelSafetyAnalysis.cpp | 5 + 7 files changed, 558 insertions(+), 3 deletions(-) diff --git a/js/src/jit/IonBuilder.h b/js/src/jit/IonBuilder.h index d6643a84fe0..2e8f030c3db 100644 --- a/js/src/jit/IonBuilder.h +++ b/js/src/jit/IonBuilder.h @@ -156,7 +156,7 @@ class IonBuilder : public MIRGenerator // MIR instruction MTableSwitch *ins; - // The number of current successor that get mapped into a block. + // The number of current successor that get mapped into a block. uint32_t currentBlock; } tableswitch; @@ -649,6 +649,10 @@ class IonBuilder : public MIRGenerator InliningStatus inlineMathFRound(CallInfo &callInfo); InliningStatus inlineMathFunction(CallInfo &callInfo, MMathFunction::Function function); + // SIMD natives. + InliningStatus checkSIMDArgs(CallInfo &callInfo, const MIRType *argumentTypes); + InliningStatus inlineSIMDFunction(CallInfo &callInfo, uint32_t id, uint32_t argumentCount); + // String natives. InliningStatus inlineStringObject(CallInfo &callInfo); InliningStatus inlineStringSplit(CallInfo &callInfo); diff --git a/js/src/jit/IonTypes.h b/js/src/jit/IonTypes.h index 0a7d9276ef7..b54450e147b 100644 --- a/js/src/jit/IonTypes.h +++ b/js/src/jit/IonTypes.h @@ -164,6 +164,9 @@ ValueTypeFromMIRType(MIRType type) return JSVAL_TYPE_STRING; case MIRType_Magic: return JSVAL_TYPE_MAGIC; + case MIRType_Float32x4: + case MIRType_Int32x4: + return JSVAL_TYPE_OBJECT; default: JS_ASSERT(type == MIRType_Object); return JSVAL_TYPE_OBJECT; @@ -194,6 +197,10 @@ StringFromMIRType(MIRType type) return "Float32"; case MIRType_String: return "String"; + case MIRType_Float32x4: + return "Float32x4"; + case MIRType_Int32x4: + return "Int32x4"; case MIRType_Object: return "Object"; case MIRType_Magic: diff --git a/js/src/jit/MCallOptimize.cpp b/js/src/jit/MCallOptimize.cpp index f6f1c809021..1f73973bcae 100644 --- a/js/src/jit/MCallOptimize.cpp +++ b/js/src/jit/MCallOptimize.cpp @@ -6,6 +6,7 @@ #include "jsmath.h" +#include "builtin/SIMD.h" #include "builtin/TestingFunctions.h" #include "jit/BaselineInspector.h" #include "jit/IonBuilder.h" @@ -108,6 +109,57 @@ IonBuilder::inlineNativeCall(CallInfo &callInfo, JSNative native) if (native == js::math_cbrt) return inlineMathFunction(callInfo, MMathFunction::Cbrt); + // SIMD natives. +#define INLINE_FLOAT32X4_NULLARY_FUNCTION(Name, Func, Operands, Flags, MIRId) \ + if (native == js::simd_float32x4_##Name) \ + return inlineSIMDFunction(callInfo, MSIMDNullaryFunction::Float32x4##MIRId, 0); +FLOAT32X4_NULLARY_FUNCTION_LIST(INLINE_FLOAT32X4_NULLARY_FUNCTION) +#undef INLINE_FLOAT32X4_NULLARY_FUNCTION +#define INLINE_INT32X4_NULLARY_FUNCTION(Name, Func, Operands, Flags, MIRId) \ + if (native == js::simd_int32x4_##Name) \ + return inlineSIMDFunction(callInfo, MSIMDNullaryFunction::Int32x4##MIRId, 0); +INT32X4_NULLARY_FUNCTION_LIST(INLINE_INT32X4_NULLARY_FUNCTION) +#undef INLINE_INT32X4_NULLARY_FUNCTION + +#define INLINE_FLOAT32X4_UNARY_FUNCTION(Name, Func, Operands, Flags, MIRId) \ + if (native == js::simd_float32x4_##Name) \ + return inlineSIMDFunction(callInfo, MSIMDUnaryFunction::Float32x4##MIRId, 1); +FLOAT32X4_UNARY_FUNCTION_LIST(INLINE_FLOAT32X4_UNARY_FUNCTION) +#undef INLINE_FLOAT32X4_UNARY_FUNCTION +#define INLINE_INT32X4_UNARY_FUNCTION(Name, Func, Operands, Flags, MIRId) \ + if (native == js::simd_int32x4_##Name) \ + return inlineSIMDFunction(callInfo, MSIMDUnaryFunction::Int32x4##MIRId, 1); +INT32X4_UNARY_FUNCTION_LIST(INLINE_INT32X4_UNARY_FUNCTION) +#undef INLINE_INT32X4_UNARY_FUNCTION + +#define INLINE_FLOAT32X4_BINARY_FUNCTION(Name, Func, Operands, Flags, MIRId) \ + if (native == js::simd_float32x4_##Name) \ + return inlineSIMDFunction(callInfo, MSIMDBinaryFunction::Float32x4##MIRId, 2); +FLOAT32X4_BINARY_FUNCTION_LIST(INLINE_FLOAT32X4_BINARY_FUNCTION) +#undef INLINE_FLOAT32X4_BINARY_FUNCTION +#define INLINE_INT32X4_BINARY_FUNCTION(Name, Func, Operands, Flags, MIRId) \ + if (native == js::simd_int32x4_##Name) \ + return inlineSIMDFunction(callInfo, MSIMDBinaryFunction::Int32x4##MIRId, 2); +INT32X4_BINARY_FUNCTION_LIST(INLINE_INT32X4_BINARY_FUNCTION) +#undef INLINE_INT32X4_BINARY_FUNCTION + +#define INLINE_FLOAT32X4_TERNARY_FUNCTION(Name, Func, Operands, Flags, MIRId) \ + if (native == js::simd_float32x4_##Name) \ + return inlineSIMDFunction(callInfo, MSIMDTernaryFunction::Float32x4##MIRId, 3); +FLOAT32X4_TERNARY_FUNCTION_LIST(INLINE_FLOAT32X4_TERNARY_FUNCTION) +#undef INLINE_FLOAT32X4_TERNARY_FUNCTION +#define INLINE_INT32X4_TERNARY_FUNCTION(Name, Func, Operands, Flags, MIRId) \ + if (native == js::simd_int32x4_##Name) \ + return inlineSIMDFunction(callInfo, MSIMDTernaryFunction::Int32x4##MIRId, 3); +INT32X4_TERNARY_FUNCTION_LIST(INLINE_INT32X4_TERNARY_FUNCTION) +#undef INLINE_INT32X4_TERNARY_FUNCTION + +#define INLINE_INT32X4_QUARTERNARY_FUNCTION(Name, Func, Operands, Flags, MIRId) \ + if (native == js::simd_int32x4_##Name) \ + return inlineSIMDFunction(callInfo, MSIMDQuarternaryFunction::Int32x4##MIRId, 4); +INT32X4_QUARTERNARY_FUNCTION_LIST(INLINE_INT32X4_QUARTERNARY_FUNCTION) +#undef INLINE_INT32X4_QUARTERNARY_FUNCTION + // String natives. if (native == js_String) return inlineStringObject(callInfo); @@ -216,6 +268,100 @@ IonBuilder::inlineMathFunction(CallInfo &callInfo, MMathFunction::Function funct return InliningStatus_Inlined; } +IonBuilder::InliningStatus +IonBuilder::checkSIMDArgs(CallInfo &callInfo, const MIRType *argumentTypes) +{ + for (uint32_t i = 0; i < callInfo.argc(); i++) { + MDefinition *arg = callInfo.getArg(i); + MIRType type = argumentTypes[i]; + switch (type) { + case MIRType_Float32x4: + case MIRType_Int32x4: + // SIMDTypePolicy will do the type check and un-box the typed object. + break; + + case MIRType_Int32: + case MIRType_Float32: + if (!IsNumberType(arg->type())) + return InliningStatus_NotInlined; + break; + + default: + MOZ_ASSUME_UNREACHABLE("Unknown SIMD MIR Type"); + } + } + return InliningStatus_Inlined; +} + +IonBuilder::InliningStatus +IonBuilder::inlineSIMDFunction(CallInfo &callInfo, uint32_t id, uint32_t argumentCount) +{ + if (callInfo.constructing()) + return InliningStatus_NotInlined; + + if (callInfo.argc() != argumentCount) + return InliningStatus_NotInlined; + + if (getInlineReturnType() != MIRType_Object) + return InliningStatus_NotInlined; + + MIRType *argumentTypes = nullptr; + switch (argumentCount) { + case 0: + break; + case 1: + argumentTypes = &MSIMDUnaryFunction::ArgumentTypes[id]; + break; + case 2: + argumentTypes = MSIMDBinaryFunction::ArgumentTypes[id]; + break; + case 3: + argumentTypes = MSIMDTernaryFunction::ArgumentTypes[id]; + break; + case 4: + argumentTypes = MSIMDQuarternaryFunction::ArgumentTypes[id]; + break; + default: + MOZ_ASSUME_UNREACHABLE("Unknown SIMD function argument count"); + } + InliningStatus s = checkSIMDArgs(callInfo, argumentTypes); + if (s != InliningStatus_Inlined) + return s; + + callInfo.setImplicitlyUsedUnchecked(); + + MInstruction *ins = nullptr; + switch (argumentCount) { + case 0: + ins = MSIMDNullaryFunction::New(alloc(), static_cast(id)); + break; + case 1: + ins = MSIMDUnaryFunction::New(alloc(), callInfo.getArg(0), + static_cast(id)); + break; + case 2: + ins = MSIMDBinaryFunction::New(alloc(), callInfo.getArg(0), callInfo.getArg(1), + static_cast(id)); + break; + case 3: + ins = MSIMDTernaryFunction::New(alloc(), callInfo.getArg(0), + callInfo.getArg(1), callInfo.getArg(2), + static_cast(id)); + break; + case 4: + ins = MSIMDQuarternaryFunction::New(alloc(), callInfo.getArg(0), callInfo.getArg(1), + callInfo.getArg(2), callInfo.getArg(3), + static_cast(id)); + break; + default: + MOZ_ASSUME_UNREACHABLE("Unknown SIMD function argument count"); + } + + current->add(ins); + current->push(ins); + return InliningStatus_Inlined; +} + IonBuilder::InliningStatus IonBuilder::inlineArray(CallInfo &callInfo) { diff --git a/js/src/jit/MIR.cpp b/js/src/jit/MIR.cpp index 38aadf7cb80..83a887652b0 100644 --- a/js/src/jit/MIR.cpp +++ b/js/src/jit/MIR.cpp @@ -13,6 +13,7 @@ #include "jslibmath.h" #include "jsstr.h" +#include "builtin/SIMD.h" #include "jit/BaselineInspector.h" #include "jit/IonBuilder.h" #include "jit/IonSpewer.h" @@ -624,6 +625,116 @@ MMathFunction::printOpcode(FILE *fp) const fprintf(fp, " %s", FunctionName(function())); } +const char *MSIMDNullaryFunction::Names[] = { +#define MSIMD_NULLARY_FUNCTION_NAME_TYPE(Id, Name, ReturnType) "SIMD." Name, + MSIMD_NULLARY_FUNCTION_LIST(MSIMD_NULLARY_FUNCTION_NAME_TYPE) +#undef MSIMD_NULLARY_FUNCTION_NAME_TYPE + "" +}; + +MIRType MSIMDNullaryFunction::ReturnTypes[] = { +#define MSIMD_NULLARY_FUNCTION_RETURN_TYPE(Id, Name, ReturnType) ReturnType, + MSIMD_NULLARY_FUNCTION_LIST(MSIMD_NULLARY_FUNCTION_RETURN_TYPE) +#undef MSIMD_NULLARY_FUNCTION_RETURN_TYPE + MIRType_None +}; + +const char *MSIMDUnaryFunction::Names[] = { +#define MSIMD_UNARY_FUNCTION_NAME_TYPE(Id, Name, ReturnType, ArgumentType) \ + "SIMD." Name, + MSIMD_UNARY_FUNCTION_LIST(MSIMD_UNARY_FUNCTION_NAME_TYPE) +#undef MSIMD_UNARY_FUNCTION_NAME_TYPE + "" +}; + +MIRType MSIMDUnaryFunction::ReturnTypes[] = { +#define MSIMD_UNARY_FUNCTION_RETURN_TYPE(Id, Name, ReturnType, ArgumentType) \ + ReturnType, + MSIMD_UNARY_FUNCTION_LIST(MSIMD_UNARY_FUNCTION_RETURN_TYPE) +#undef MSIMD_UNARY_FUNCTION_RETURN_TYPE + MIRType_None +}; + +MIRType MSIMDUnaryFunction::ArgumentTypes[] = { +#define MSIMD_UNARY_FUNCTION_ARGUMENT_TYPE(Id, Name, ReturnType, ArgumentType) \ + ArgumentType, + MSIMD_UNARY_FUNCTION_LIST(MSIMD_UNARY_FUNCTION_ARGUMENT_TYPE) +#undef MSIMD_UNARY_FUNCTION_ARGUMENT_TYPE + MIRType_None +}; + +const char *MSIMDBinaryFunction::Names[] = { +#define MSIMD_BINARY_FUNCTION_NAME_TYPE(Id, Name, ReturnType, Argument1Type, Argument2Type) \ + "SIMD." Name, + MSIMD_BINARY_FUNCTION_LIST(MSIMD_BINARY_FUNCTION_NAME_TYPE) +#undef MSIMD_BINARY_FUNCTION_NAME_TYPE + "" +}; + +MIRType MSIMDBinaryFunction::ReturnTypes[] = { +#define MSIMD_BINARY_FUNCTION_RETURN_TYPE(Id, Name, ReturnType, Argument1Type, Argument2Type) \ + ReturnType, + MSIMD_BINARY_FUNCTION_LIST(MSIMD_BINARY_FUNCTION_RETURN_TYPE) +#undef MSIMD_BINARY_FUNCTION_RETURN_TYPE + MIRType_None +}; + +MIRType MSIMDBinaryFunction::ArgumentTypes[][2] = { +#define MSIMD_BINARY_FUNCTION_ARGUMENTS_TYPE(Id, Name, ReturnType, Argument1Type, Argument2Type) \ + {Argument1Type, Argument2Type}, + MSIMD_BINARY_FUNCTION_LIST(MSIMD_BINARY_FUNCTION_ARGUMENTS_TYPE) +#undef MSIMD_BINARY_FUNCTION_ARGUMENTS_TYPE + {MIRType_None, MIRType_None} +}; + +const char *MSIMDTernaryFunction::Names[] = { +#define MSIMD_TERNARY_FUNCTION_NAME_TYPE(Id, Name, ReturnType, Argument1Type, Argument2Type, Argument3Type) \ + "SIMD." Name, + MSIMD_TERNARY_FUNCTION_LIST(MSIMD_TERNARY_FUNCTION_NAME_TYPE) +#undef MSIMD_TERNARY_FUNCTION_NAME_TYPE + "" +}; + +MIRType MSIMDTernaryFunction::ReturnTypes[] = { +#define MSIMD_TERNARY_FUNCTION_RETURN_TYPE(Id, Name, ReturnType, Argument1Type, Argument2Type, Argument3Type) \ + ReturnType, + MSIMD_TERNARY_FUNCTION_LIST(MSIMD_TERNARY_FUNCTION_RETURN_TYPE) +#undef MSIMD_TERNARY_FUNCTION_RETURN_TYPE + MIRType_None +}; + +MIRType MSIMDTernaryFunction::ArgumentTypes[][3] = { +#define MSIMD_TERNARY_FUNCTION_ARGUMENTS_TYPE(Id, Name, ReturnType, Argument1Type, Argument2Type, Argument3Type) \ + {Argument1Type, Argument2Type, Argument3Type}, + MSIMD_TERNARY_FUNCTION_LIST(MSIMD_TERNARY_FUNCTION_ARGUMENTS_TYPE) +#undef MSIMD_TERNARY_FUNCTION_ARGUMENTS_TYPE + {MIRType_None, MIRType_None, MIRType_None} +}; + +const char *MSIMDQuarternaryFunction::Names[] = { +#define MSIMD_QUARTERNARY_FUNCTION_NAME_TYPE(Id, Name, ReturnType, Argument1Type, Argument2Type, Argument3Type, Argument4Type) \ + "SIMD." Name, + MSIMD_QUARTERNARY_FUNCTION_LIST(MSIMD_QUARTERNARY_FUNCTION_NAME_TYPE) +#undef MSIMD_QUARTERNARY_FUNCTION_NAME_TYPE + "" +}; + +MIRType MSIMDQuarternaryFunction::ReturnTypes[] = { +#define MSIMD_QUARTERNARY_FUNCTION_RETURN_TYPE(Id, Name, ReturnType, Argument1Type, Argument2Type, Argument3Type, Argument4Type) \ + ReturnType, + MSIMD_QUARTERNARY_FUNCTION_LIST(MSIMD_QUARTERNARY_FUNCTION_RETURN_TYPE) +#undef MSIMD_QUARTERNARY_FUNCTION_RETURN_TYPE + MIRType_None +}; + +MIRType MSIMDQuarternaryFunction::ArgumentTypes[][4] = { +#define MSIMD_QUARTERNARY_FUNCTION_ARGUMENTS_TYPE(Id, Name, ReturnType, Argument1Type, Argument2Type, Argument3Type, Argument4Type) \ + {Argument1Type, Argument2Type, Argument3Type, Argument4Type}, + MSIMD_QUARTERNARY_FUNCTION_LIST(MSIMD_QUARTERNARY_FUNCTION_ARGUMENTS_TYPE) +#undef MSIMD_QUARTERNARY_FUNCTION_ARGUMENTS_TYPE + {MIRType_None, MIRType_None, MIRType_None, MIRType_None} +}; + MParameter * MParameter::New(TempAllocator &alloc, int32_t index, types::TemporaryTypeSet *types) { @@ -896,7 +1007,7 @@ MTypeBarrier::printOpcode(FILE *fp) const fprintf(fp, " "); getOperand(0)->printName(fp); } - + void MPhi::removeOperand(size_t index) { @@ -2444,7 +2555,7 @@ MCompare::evaluateConstantOperands(bool *result) int32_t comp = 0; // Default to equal. if (left != right) comp = CompareAtoms(&lhs.toString()->asAtom(), &rhs.toString()->asAtom()); - + switch (jsop_) { case JSOP_LT: *result = (comp < 0); diff --git a/js/src/jit/MIR.h b/js/src/jit/MIR.h index 6695a4e0999..5b7c1c7cf94 100644 --- a/js/src/jit/MIR.h +++ b/js/src/jit/MIR.h @@ -3936,6 +3936,283 @@ class MMathFunction void computeRange(TempAllocator &alloc); }; +#define DECLARE_COMMON_SIMD_FUNCTION(opcode) \ + static MIRType ReturnTypes[]; \ + static const char *Names[]; \ + Id id() const { \ + return id_; \ + } \ + bool congruentTo(MDefinition *ins) const { \ + if (!ins->is##opcode()) \ + return false; \ + if (ins->to##opcode()->id() != id()) \ + return false; \ + return congruentIfOperandsEqual(ins); \ + } \ + AliasSet getAliasSet() const { \ + return AliasSet::None(); \ + } \ + bool possiblyCalls() const { \ + return true; \ + } \ + void printOpcode(FILE *fp) const { \ + MDefinition::printOpcode(fp); \ + fprintf(fp, " %s", Names[id()]); \ + } + +#define MSIMD_NULLARY_FUNCTION_LIST(V) \ + V(Float32x4Zero, "float32x4.zero", MIRType_Float32x4) \ + V(Int32x4Zero, "int32x4.zero", MIRType_Int32x4) + +class MSIMDNullaryFunction + : public MNullaryInstruction +{ + public: + enum Id { +#define MSIMD_NULLARY_FUNCTION_ID(Id, Name, Type) Id, + MSIMD_NULLARY_FUNCTION_LIST(MSIMD_NULLARY_FUNCTION_ID) + NUMBER_OF_IDS +#undef MSIMD_NULLARY_FUNCTION_ID + }; + + private: + Id id_; + + MSIMDNullaryFunction(Id id) + : MNullaryInstruction(), id_(id) + { + setMovable(); + setResultType(ReturnTypes[id]); + } + + public: + INSTRUCTION_HEADER(SIMDNullaryFunction) + DECLARE_COMMON_SIMD_FUNCTION(SIMDNullaryFunction) + static MSIMDNullaryFunction *New(TempAllocator &alloc, Id id) + { + return new(alloc) MSIMDNullaryFunction(id); + } +}; + +#define MSIMD_UNARY_FUNCTION_LIST(V) \ + V(Float32x4Abs, "float32x4.abs", MIRType_Float32x4, MIRType_Float32x4) \ + V(Float32x4BitsToInt32x4, "float32x4.bitstoInt32x4", MIRType_Int32x4, MIRType_Float32x4) \ + V(Float32x4Neg, "float32x4.neg", MIRType_Float32x4, MIRType_Float32x4) \ + V(Float32x4Reciprocal, "float32x4.reciprocal", MIRType_Float32x4, MIRType_Float32x4) \ + V(Float32x4ReciprocalSqrt, "float32x4.reciprocalSqrt", MIRType_Float32x4, MIRType_Float32x4) \ + V(Float32x4Splat, "float32x4.splat", MIRType_Float32x4, MIRType_Float32) \ + V(Float32x4Sqrt, "float32x4.sqrt", MIRType_Float32x4, MIRType_Float32x4) \ + V(Float32x4ToInt32x4, "float32x4.toInt32x4", MIRType_Int32x4, MIRType_Float32x4) \ + V(Float32x4GetX, "float32x4.getX", MIRType_Float32, MIRType_Float32x4) \ + V(Float32x4GetY, "float32x4.getY", MIRType_Float32, MIRType_Float32x4) \ + V(Float32x4GetZ, "float32x4.getZ", MIRType_Float32, MIRType_Float32x4) \ + V(Float32x4GetW, "float32x4.getW", MIRType_Float32, MIRType_Float32x4) \ + V(Float32x4GetSignMask, "float32x4.getSignMask", MIRType_Int32, MIRType_Float32x4) \ + V(Int32x4BitsToFloat32x4, "int32x4.bitsToFloat32x4", MIRType_Float32x4, MIRType_Int32x4) \ + V(Int32x4Neg, "int32x4.neg", MIRType_Int32x4, MIRType_Int32x4) \ + V(Int32x4Not, "int32x4.not", MIRType_Int32x4, MIRType_Int32x4) \ + V(Int32x4Splat, "int32x4.splat", MIRType_Int32x4, MIRType_Int32) \ + V(Int32x4ToFloat32x4, "int32x4.toFloat32x4", MIRType_Float32x4, MIRType_Int32x4) \ + V(Int32x4GetX, "int32x4.getX", MIRType_Int32, MIRType_Int32x4) \ + V(Int32x4GetY, "int32x4.getY", MIRType_Int32, MIRType_Int32x4) \ + V(Int32x4GetZ, "int32x4.getZ", MIRType_Int32, MIRType_Int32x4) \ + V(Int32x4GetW, "int32x4.getW", MIRType_Int32, MIRType_Int32x4) \ + V(Int32x4GetSignMask, "int32x4.getSignMask", MIRType_Int32, MIRType_Int32x4) \ + V(Int32x4GetFlagX, "int32x4.getFlagX", MIRType_Boolean, MIRType_Int32x4) \ + V(Int32x4GetFlagY, "int32x4.getFlagY", MIRType_Boolean, MIRType_Int32x4) \ + V(Int32x4GetFlagZ, "int32x4.getFlagZ", MIRType_Boolean, MIRType_Int32x4) \ + V(Int32x4GetFlagW, "int32x4.getFlagW", MIRType_Boolean, MIRType_Int32x4) + +class MSIMDUnaryFunction + : public MUnaryInstruction +{ + public: + enum Id { +#define MSIMD_UNARY_FUNCTION_ID(Id, Name, ReturnType, ArgumentType) Id, + MSIMD_UNARY_FUNCTION_LIST(MSIMD_UNARY_FUNCTION_ID) + NUMBER_OF_IDS +#undef MSIMD_UNARY_FUNCTION_ID + }; + + static MIRType ArgumentTypes[]; + + private: + Id id_; + + MSIMDUnaryFunction(MDefinition *argument, Id id) + : MUnaryInstruction(argument), id_(id) + { + setMovable(); + setResultType(ReturnTypes[id]); + } + + public: + INSTRUCTION_HEADER(SIMDUnaryFunction) + DECLARE_COMMON_SIMD_FUNCTION(SIMDUnaryFunction) + static MSIMDUnaryFunction *New(TempAllocator &alloc, MDefinition *argument, Id id) + { + return new(alloc) MSIMDUnaryFunction(argument, id); + } + bool canProduceFloat32() const { + return type() == MIRType_Float32; + } + bool canConsumeFloat32(MUse *use) const { + return id() == Float32x4Splat; + } +#ifdef DEBUG + bool isConsistentFloat32Use(MUse *use) const { return canProduceFloat32() || canConsumeFloat32(use); } +#endif +}; + +#define MSIMD_BINARY_FUNCTION_LIST(V) \ + V(Float32x4Add, "float32x4.add", MIRType_Float32x4, MIRType_Float32x4, MIRType_Float32x4) \ + V(Float32x4Div, "float32x4.div", MIRType_Float32x4, MIRType_Float32x4, MIRType_Float32x4) \ + V(Float32x4Equal, "float32x4.equal", MIRType_Int32x4, MIRType_Float32x4, MIRType_Float32x4) \ + V(Float32x4GreaterThan, "float32x4.greaterThan", MIRType_Int32x4, MIRType_Float32x4, MIRType_Float32x4) \ + V(Float32x4GreaterThanOrEqual, "float32x4.greaterThanOrEqual", MIRType_Int32x4, MIRType_Float32x4, MIRType_Float32x4) \ + V(Float32x4LessThan, "float32x4.lessThan", MIRType_Int32x4, MIRType_Float32x4, MIRType_Float32x4) \ + V(Float32x4LessThanOrEqual, "float32x4.lessThanOrEqual", MIRType_Int32x4, MIRType_Float32x4, MIRType_Float32x4) \ + V(Float32x4Max, "float32x4.max", MIRType_Float32x4, MIRType_Float32x4, MIRType_Float32x4) \ + V(Float32x4Min, "float32x4.min", MIRType_Float32x4, MIRType_Float32x4, MIRType_Float32x4) \ + V(Float32x4Mul, "float32x4.mul", MIRType_Float32x4, MIRType_Float32x4, MIRType_Float32x4) \ + V(Float32x4NotEqual, "float32x4.notEqual", MIRType_Int32x4, MIRType_Float32x4, MIRType_Float32x4) \ + V(Float32x4Shuffle, "float32x4.shuffle", MIRType_Float32x4, MIRType_Float32x4, MIRType_Int32) \ + V(Float32x4Scale, "float32x4.scale", MIRType_Float32x4, MIRType_Float32x4, MIRType_Float32) \ + V(Float32x4Sub, "float32x4.sub", MIRType_Float32x4, MIRType_Float32x4, MIRType_Float32x4) \ + V(Float32x4WithX, "float32x4.withX", MIRType_Float32x4, MIRType_Float32x4, MIRType_Float32) \ + V(Float32x4WithY, "float32x4.withY", MIRType_Float32x4, MIRType_Float32x4, MIRType_Float32) \ + V(Float32x4WithZ, "float32x4.withZ", MIRType_Float32x4, MIRType_Float32x4, MIRType_Float32) \ + V(Float32x4WithW, "float32x4.withW", MIRType_Float32x4, MIRType_Float32x4, MIRType_Float32) \ + V(Int32x4Add, "int32x4.add", MIRType_Int32x4, MIRType_Int32x4, MIRType_Int32x4) \ + V(Int32x4And, "int32x4.and", MIRType_Int32x4, MIRType_Int32x4, MIRType_Int32x4) \ + V(Int32x4Mul, "int32x4.mul", MIRType_Int32x4, MIRType_Int32x4, MIRType_Int32x4) \ + V(Int32x4Or, "int32x4.or", MIRType_Int32x4, MIRType_Int32x4, MIRType_Int32x4) \ + V(Int32x4Sub, "int32x4.sub", MIRType_Int32x4, MIRType_Int32x4, MIRType_Int32x4) \ + V(Int32x4Shuffle, "int32x4.shuffle", MIRType_Int32x4, MIRType_Int32x4, MIRType_Int32) \ + V(Int32x4WithFlagX, "int32x4.withFlagX", MIRType_Int32x4, MIRType_Int32x4, MIRType_Boolean) \ + V(Int32x4WithFlagY, "int32x4.withFlagY", MIRType_Int32x4, MIRType_Int32x4, MIRType_Boolean) \ + V(Int32x4WithFlagZ, "int32x4.withFlagZ", MIRType_Int32x4, MIRType_Int32x4, MIRType_Boolean) \ + V(Int32x4WithFlagW, "int32x4.withFlagW", MIRType_Int32x4, MIRType_Int32x4, MIRType_Boolean) \ + V(Int32x4WithX, "int32x4.withX", MIRType_Int32x4, MIRType_Int32x4, MIRType_Int32) \ + V(Int32x4WithY, "int32x4.withY", MIRType_Int32x4, MIRType_Int32x4, MIRType_Int32) \ + V(Int32x4WithZ, "int32x4.withZ", MIRType_Int32x4, MIRType_Int32x4, MIRType_Int32) \ + V(Int32x4WithW, "int32x4.withW", MIRType_Int32x4, MIRType_Int32x4, MIRType_Int32) \ + V(Int32x4Xor, "int32x4.xor", MIRType_Int32x4, MIRType_Int32x4, MIRType_Int32x4) + +class MSIMDBinaryFunction + : public MBinaryInstruction +{ + public: + enum Id { +#define MSIMD_BINARY_FUNCTION_ID(Id, Name, Type, Argument1Type, Argument2Type) Id, + MSIMD_BINARY_FUNCTION_LIST(MSIMD_BINARY_FUNCTION_ID) + NUMBER_OF_IDS +#undef MSIMD_BINARY_FUNCTION_ID + }; + + static MIRType ArgumentTypes[][2]; + + private: + Id id_; + + MSIMDBinaryFunction(MDefinition *left, MDefinition *right, Id id) + : MBinaryInstruction(left, right), id_(id) + { + setMovable(); + setResultType(ReturnTypes[id]); + } + + public: + INSTRUCTION_HEADER(SIMDBinaryFunction) + DECLARE_COMMON_SIMD_FUNCTION(SIMDBinaryFunction) + static MSIMDBinaryFunction *New(TempAllocator &alloc, MDefinition *left, MDefinition *right, Id id) + { + return new(alloc) MSIMDBinaryFunction(left, right, id); + } + bool canConsumeFloat32(MUse *use) const { + return id() == Float32x4Scale || id() == Float32x4WithX || id() == Float32x4WithY || + id() == Float32x4WithZ || id() == Float32x4WithW; + } +#ifdef DEBUG + bool isConsistentFloat32Use(MUse *use) const { + return canConsumeFloat32(use); + } +#endif +}; + +#define MSIMD_TERNARY_FUNCTION_LIST(V) \ + V(Float32x4Clamp, "float32x4.clamp", MIRType_Float32x4, MIRType_Float32x4, MIRType_Float32x4, MIRType_Float32x4) \ + V(Float32x4ShuffleMix, "float32x4.shuffleMix", MIRType_Float32x4, MIRType_Float32x4, MIRType_Float32x4, MIRType_Int32) \ + V(Int32x4Select, "int32x4.select", MIRType_Float32x4, MIRType_Int32x4, MIRType_Float32x4, MIRType_Float32x4) \ + V(Int32x4ShuffleMix, "int32x4.shuffleMix", MIRType_Int32x4, MIRType_Int32x4, MIRType_Int32x4, MIRType_Int32) + +class MSIMDTernaryFunction + : public MTernaryInstruction +{ + public: + enum Id { +#define MSIMD_TERNARY_FUNCTION_ID(Id, Name, Type, Argument1Type, Argument2Type, Argument3Type) Id, + MSIMD_TERNARY_FUNCTION_LIST(MSIMD_TERNARY_FUNCTION_ID) + NUMBER_OF_IDS +#undef MSIMD_TERNARY_FUNCTION_ID + }; + + static MIRType ArgumentTypes[][3]; + + private: + Id id_; + + MSIMDTernaryFunction(MDefinition *first, MDefinition *second, MDefinition *third, Id id) + : MTernaryInstruction(first, second, third), id_(id) + { + setMovable(); + setResultType(ReturnTypes[id]); + } + + public: + INSTRUCTION_HEADER(SIMDTernaryFunction) + DECLARE_COMMON_SIMD_FUNCTION(SIMDTernaryFunction) + static MSIMDTernaryFunction *New(TempAllocator &alloc, MDefinition *first, MDefinition *second, MDefinition *third, Id id) + { + return new(alloc) MSIMDTernaryFunction(first, second, third, id); + } +}; + +#define MSIMD_QUARTERNARY_FUNCTION_LIST(V) \ + V(Int32x4Bool, "int32x4.bool", MIRType_Int32x4, MIRType_Boolean, MIRType_Boolean, MIRType_Boolean, MIRType_Boolean) + +class MSIMDQuarternaryFunction + : public MQuaternaryInstruction +{ + public: + enum Id { +#define MSIMD_QUARTERNARY_FUNCTION_ID(Id, Name, Type, Argument1Type, Argument2Type, Argument3Type, Argument4Type) Id, + MSIMD_QUARTERNARY_FUNCTION_LIST(MSIMD_QUARTERNARY_FUNCTION_ID) + NUMBER_OF_IDS +#undef MSIMD_QUARTERNARY_FUNCTION_ID + }; + + static MIRType ArgumentTypes[][4]; + + private: + Id id_; + + MSIMDQuarternaryFunction(MDefinition *first, MDefinition *second, MDefinition *third, MDefinition *fourth, Id id) + : MQuaternaryInstruction(first, second, third, fourth), id_(id) + { + setMovable(); + setResultType(ReturnTypes[id]); + } + + public: + INSTRUCTION_HEADER(SIMDQuarternaryFunction) + DECLARE_COMMON_SIMD_FUNCTION(SIMDQuarternaryFunction) + static MSIMDQuarternaryFunction *New(TempAllocator &alloc, MDefinition *first, MDefinition *second, MDefinition *third, MDefinition *fourth, Id id) + { + return new(alloc) MSIMDQuarternaryFunction(first, second, third, fourth, id); + } +}; + class MAdd : public MBinaryArithInstruction { // Is this instruction really an int at heart? diff --git a/js/src/jit/MOpcodes.h b/js/src/jit/MOpcodes.h index e598a711a5e..46c65100960 100644 --- a/js/src/jit/MOpcodes.h +++ b/js/src/jit/MOpcodes.h @@ -63,6 +63,11 @@ namespace jit { _(PowHalf) \ _(Random) \ _(MathFunction) \ + _(SIMDNullaryFunction) \ + _(SIMDUnaryFunction) \ + _(SIMDBinaryFunction) \ + _(SIMDTernaryFunction) \ + _(SIMDQuarternaryFunction) \ _(Add) \ _(Sub) \ _(Mul) \ diff --git a/js/src/jit/ParallelSafetyAnalysis.cpp b/js/src/jit/ParallelSafetyAnalysis.cpp index 791b38614cf..2ec4942a264 100644 --- a/js/src/jit/ParallelSafetyAnalysis.cpp +++ b/js/src/jit/ParallelSafetyAnalysis.cpp @@ -158,6 +158,11 @@ class ParallelSafetyVisitor : public MInstructionVisitor UNSAFE_OP(Atan2) UNSAFE_OP(Hypot) CUSTOM_OP(MathFunction) + SAFE_OP(SIMDNullaryFunction) + SAFE_OP(SIMDUnaryFunction) + SAFE_OP(SIMDBinaryFunction) + SAFE_OP(SIMDTernaryFunction) + SAFE_OP(SIMDQuarternaryFunction) SPECIALIZED_OP(Add, PERMIT_NUMERIC) SPECIALIZED_OP(Sub, PERMIT_NUMERIC) SPECIALIZED_OP(Mul, PERMIT_NUMERIC) From 32a6b5d8fd2aeed0b402dfc0a2cad107477cb468 Mon Sep 17 00:00:00 2001 From: Brian Birtles Date: Wed, 5 Mar 2014 10:19:15 +0900 Subject: [PATCH 051/112] Bug 972199 part 1 - Make SampleAnimations filter out animations that are yet to start; r=nrc When restoring the refresh driver after testing we can arrive at a situation where a layer has an animation that has yet to start. However, calling ElementAnimations::GetPositionInIteration with a negative value from the compositor thread is an error. This patch detects animations on the compositor thread that are yet-to-start and skips them when sampling. It also moves the activeAnimations = true line up as otherwise we would need special logic to wake up the compositor after the delay has finished. --- .../composite/AsyncCompositionManager.cpp | 20 ++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/gfx/layers/composite/AsyncCompositionManager.cpp b/gfx/layers/composite/AsyncCompositionManager.cpp index bb6e778689a..0a506536952 100644 --- a/gfx/layers/composite/AsyncCompositionManager.cpp +++ b/gfx/layers/composite/AsyncCompositionManager.cpp @@ -413,10 +413,26 @@ SampleAnimations(Layer* aLayer, TimeStamp aPoint) Animation& animation = animations[i]; AnimData& animData = animationData[i]; + activeAnimations = true; + + TimeDuration elapsedDuration = aPoint - animation.startTime(); + // Skip animations that are yet to start. + // + // Currently, this should only happen when the refresh driver is under test + // control and is made to produce a time in the past or is restored from + // test control causing it to jump backwards in time. + // + // Since activeAnimations is true, this could mean we keep compositing + // unnecessarily during the delay, but so long as this only happens while + // the refresh driver is under test control that should be ok. + if (elapsedDuration.ToSeconds() < 0) { + continue; + } + double numIterations = animation.numIterations() != -1 ? animation.numIterations() : NS_IEEEPositiveInfinity(); double positionInIteration = - ElementAnimations::GetPositionInIteration(aPoint - animation.startTime(), + ElementAnimations::GetPositionInIteration(elapsedDuration, animation.duration(), numIterations, animation.direction()); @@ -437,8 +453,6 @@ SampleAnimations(Layer* aLayer, TimeStamp aPoint) double portion = animData.mFunctions[segmentIndex]->GetValue(positionInSegment); - activeAnimations = true; - // interpolate the property Animatable interpolatedValue; SampleValue(portion, animation, animData.mStartValues[segmentIndex], From da2e87c2ff710d22668ce685335000370bc5d19d Mon Sep 17 00:00:00 2001 From: Brian Birtles Date: Wed, 5 Mar 2014 10:19:15 +0900 Subject: [PATCH 052/112] Bug 972199 part 2 - Add a crashtest for restoring the refresh driver after an advance; r=nrc In this crash test we restore the refresh driver after manually advancing it. This causes a situation where a layer has an animation that has yet to start. Prior to modifying ElementAnimations::GetPositionIteration this test case would trip an assertion there that rejected negative elapsed times when called from the compositor thread. --- layout/style/crashtests/972199-1.html | 39 +++++++++++++++++++++++++ layout/style/crashtests/crashtests.list | 1 + 2 files changed, 40 insertions(+) create mode 100644 layout/style/crashtests/972199-1.html diff --git a/layout/style/crashtests/972199-1.html b/layout/style/crashtests/972199-1.html new file mode 100644 index 00000000000..ecd57ca2a7a --- /dev/null +++ b/layout/style/crashtests/972199-1.html @@ -0,0 +1,39 @@ + + + + + + +
+ + diff --git a/layout/style/crashtests/crashtests.list b/layout/style/crashtests/crashtests.list index b4b0b245475..ce082d5b6b9 100644 --- a/layout/style/crashtests/crashtests.list +++ b/layout/style/crashtests/crashtests.list @@ -101,4 +101,5 @@ load 927734-1.html load 930270-1.html load 930270-2.html load 945048-1.html +load 972199-1.html load large_border_image_width.html From eb542f393709dc0d5be05ad537952746d5e1c95b Mon Sep 17 00:00:00 2001 From: Brian Birtles Date: Wed, 5 Mar 2014 10:19:16 +0900 Subject: [PATCH 053/112] Bug 972199 part 3 - Fix comment in ElementAnimations::GetPositionInIteration; r=nrc Make comment reflect current parameter names. --- layout/style/nsAnimationManager.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/layout/style/nsAnimationManager.h b/layout/style/nsAnimationManager.h index 9905b752a2b..69c38aedb17 100644 --- a/layout/style/nsAnimationManager.h +++ b/layout/style/nsAnimationManager.h @@ -141,7 +141,7 @@ struct ElementAnimations MOZ_FINAL // This function returns -1 for the position if the animation should not be // run (because it is not currently active and has no fill behavior), but // only does so if aAnimation is non-null; with a null aAnimation it is an - // error to give aCurrentTime < aStartTime, and fill-forwards is assumed. + // error to give aElapsedDuration < 0, and fill-forwards is assumed. // After calling GetPositionInIteration with non-null aAnimation and aEa, be // sure to call CheckNeedsRefresh on the animation manager afterwards. static double GetPositionInIteration(TimeDuration aElapsedDuration, From 1d73211714515a3ec037d2e7402bd599b3be4f43 Mon Sep 17 00:00:00 2001 From: Mihaela Velimiroviciu Date: Wed, 5 Mar 2014 12:29:44 +1100 Subject: [PATCH 054/112] Bug 959973 - Add tests for using variables in external style sheets. r=heycam,ted --- .../support/external-variable-declaration.css | 5 ++++ .../support/external-variable-font-face.css | 15 ++++++++++ .../support/external-variable-reference.css | 6 ++++ .../support/external-variable-supports.css | 4 +++ .../variable-external-declaration-01.html | 12 ++++++++ .../variable-external-font-face-01.html | 13 +++++++++ .../variable-external-reference-01.html | 12 ++++++++ .../variable-external-supports-01.html | 12 ++++++++ layout/style/test/mochitest.ini | 1 + .../test/support/external-variable-url.css | 3 ++ layout/style/test/test_variables.html | 29 ++++++++++++++++++- 11 files changed, 111 insertions(+), 1 deletion(-) create mode 100644 layout/reftests/w3c-css/submitted/variables/support/external-variable-declaration.css create mode 100644 layout/reftests/w3c-css/submitted/variables/support/external-variable-font-face.css create mode 100644 layout/reftests/w3c-css/submitted/variables/support/external-variable-reference.css create mode 100644 layout/reftests/w3c-css/submitted/variables/support/external-variable-supports.css create mode 100644 layout/reftests/w3c-css/submitted/variables/variable-external-declaration-01.html create mode 100644 layout/reftests/w3c-css/submitted/variables/variable-external-font-face-01.html create mode 100644 layout/reftests/w3c-css/submitted/variables/variable-external-reference-01.html create mode 100644 layout/reftests/w3c-css/submitted/variables/variable-external-supports-01.html create mode 100644 layout/style/test/support/external-variable-url.css diff --git a/layout/reftests/w3c-css/submitted/variables/support/external-variable-declaration.css b/layout/reftests/w3c-css/submitted/variables/support/external-variable-declaration.css new file mode 100644 index 00000000000..ec5726b4649 --- /dev/null +++ b/layout/reftests/w3c-css/submitted/variables/support/external-variable-declaration.css @@ -0,0 +1,5 @@ +p { + color: red; + var-a: green; + color: var(a); +} diff --git a/layout/reftests/w3c-css/submitted/variables/support/external-variable-font-face.css b/layout/reftests/w3c-css/submitted/variables/support/external-variable-font-face.css new file mode 100644 index 00000000000..9edf374afe6 --- /dev/null +++ b/layout/reftests/w3c-css/submitted/variables/support/external-variable-font-face.css @@ -0,0 +1,15 @@ +@font-face { + var-a: MyTestFontName; + font-family: var(a); + src: url(../../../../fonts/Ahem.ttf); +} +@font-face { + font-family: MyTestFontName2; + src: url(../../../../fonts/Ahem.ttf); +} +#a { + font-family: MyTestFontName; +} +#b { + font-family: MyTestFontName2; +} diff --git a/layout/reftests/w3c-css/submitted/variables/support/external-variable-reference.css b/layout/reftests/w3c-css/submitted/variables/support/external-variable-reference.css new file mode 100644 index 00000000000..5c912acb0a6 --- /dev/null +++ b/layout/reftests/w3c-css/submitted/variables/support/external-variable-reference.css @@ -0,0 +1,6 @@ +:root { + var-a: green; +} +p { + color: var(a); +} diff --git a/layout/reftests/w3c-css/submitted/variables/support/external-variable-supports.css b/layout/reftests/w3c-css/submitted/variables/support/external-variable-supports.css new file mode 100644 index 00000000000..e7fdd9f04a8 --- /dev/null +++ b/layout/reftests/w3c-css/submitted/variables/support/external-variable-supports.css @@ -0,0 +1,4 @@ +body { color: red; } +@supports (color:var(a)) { + p { color: green; } +} diff --git a/layout/reftests/w3c-css/submitted/variables/variable-external-declaration-01.html b/layout/reftests/w3c-css/submitted/variables/variable-external-declaration-01.html new file mode 100644 index 00000000000..bae5abf700a --- /dev/null +++ b/layout/reftests/w3c-css/submitted/variables/variable-external-declaration-01.html @@ -0,0 +1,12 @@ + + +CSS Test: Test declaring a variable in an external CSS file. + + + + + +

This text must be green.

diff --git a/layout/reftests/w3c-css/submitted/variables/variable-external-font-face-01.html b/layout/reftests/w3c-css/submitted/variables/variable-external-font-face-01.html new file mode 100644 index 00000000000..f248418120d --- /dev/null +++ b/layout/reftests/w3c-css/submitted/variables/variable-external-font-face-01.html @@ -0,0 +1,13 @@ + + +CSS Test: Test the invalid declaration and use of a variable in an @font-face rule within an external CSS. + + + + + +

This text must not be in Ahem.

+

But this text must be in Ahem.

diff --git a/layout/reftests/w3c-css/submitted/variables/variable-external-reference-01.html b/layout/reftests/w3c-css/submitted/variables/variable-external-reference-01.html new file mode 100644 index 00000000000..ee40db762cd --- /dev/null +++ b/layout/reftests/w3c-css/submitted/variables/variable-external-reference-01.html @@ -0,0 +1,12 @@ + + +CSS Test: Test the use of a variable in a non-custom property where the variable value is inherited within an external CSS. + + + + + +

This text must be green.

diff --git a/layout/reftests/w3c-css/submitted/variables/variable-external-supports-01.html b/layout/reftests/w3c-css/submitted/variables/variable-external-supports-01.html new file mode 100644 index 00000000000..dd3ad172818 --- /dev/null +++ b/layout/reftests/w3c-css/submitted/variables/variable-external-supports-01.html @@ -0,0 +1,12 @@ + + +CSS Test: Test a passing non-custom property declaration in an @supports rule where the property value contains a variable reference within an external stylesheet file. + + + + + +

This text must be green.

diff --git a/layout/style/test/mochitest.ini b/layout/style/test/mochitest.ini index 350023f5ec9..1d0aba60af7 100644 --- a/layout/style/test/mochitest.ini +++ b/layout/style/test/mochitest.ini @@ -201,6 +201,7 @@ skip-if = toolkit == 'android' [test_variable_serialization_computed.html] [test_variable_serialization_specified.html] [test_variables.html] +support-files = support/external-variable-url.css [test_viewport_units.html] [test_visited_image_loading.html] skip-if = toolkit == 'android' #TIMED_OUT diff --git a/layout/style/test/support/external-variable-url.css b/layout/style/test/support/external-variable-url.css new file mode 100644 index 00000000000..3570c552213 --- /dev/null +++ b/layout/style/test/support/external-variable-url.css @@ -0,0 +1,3 @@ +div { + var-a: url('image.png'); +} diff --git a/layout/style/test/test_variables.html b/layout/style/test/test_variables.html index c97a84d66f3..7857273d5e8 100644 --- a/layout/style/test/test_variables.html +++ b/layout/style/test/test_variables.html @@ -13,6 +13,11 @@ + + +
+ From 69b9dffd6c4726d8133dda227db930ea9e2bb5d3 Mon Sep 17 00:00:00 2001 From: Eitan Isaacson Date: Tue, 4 Mar 2014 17:49:27 -0800 Subject: [PATCH 055/112] Bug 965537 - [AccessFu] Introduce ContentControl. r=yzen --- accessible/src/jsat/AccessFu.jsm | 15 +- accessible/src/jsat/ContentControl.jsm | 269 +++++++++++++++++++++++++ accessible/src/jsat/EventManager.jsm | 39 +--- accessible/src/jsat/content-script.js | 123 +---------- accessible/src/jsat/moz.build | 1 + 5 files changed, 298 insertions(+), 149 deletions(-) create mode 100644 accessible/src/jsat/ContentControl.jsm diff --git a/accessible/src/jsat/AccessFu.jsm b/accessible/src/jsat/AccessFu.jsm index 1b542c412e1..6de780f761e 100644 --- a/accessible/src/jsat/AccessFu.jsm +++ b/accessible/src/jsat/AccessFu.jsm @@ -309,7 +309,7 @@ this.AccessFu = { case 'Accessibility:Focus': this._focused = JSON.parse(aData); if (this._focused) { - this.showCurrent(true); + this.autoMove({ forcePresent: true, noOpIfOnScreen: true }); } break; case 'Accessibility:MoveByGranularity': @@ -353,10 +353,11 @@ this.AccessFu = { // We delay this for half a second so the awesomebar could close, // and we could use the current coordinates for the content item. // XXX TODO figure out how to avoid magic wait here. - Utils.win.setTimeout( - function () { - this.showCurrent(false); - }.bind(this), 500); + this.autoMove({ + delay: 500, + forcePresent: true, + noOpIfOnScreen: true, + moveMethod: 'moveFirst' }); } break; } @@ -372,9 +373,9 @@ this.AccessFu = { } }, - showCurrent: function showCurrent(aMove) { + autoMove: function autoMove(aOptions) { let mm = Utils.getMessageManager(Utils.CurrentBrowser); - mm.sendAsyncMessage('AccessFu:ShowCurrent', { move: aMove }); + mm.sendAsyncMessage('AccessFu:AutoMove', aOptions); }, announce: function announce(aAnnouncement) { diff --git a/accessible/src/jsat/ContentControl.jsm b/accessible/src/jsat/ContentControl.jsm new file mode 100644 index 00000000000..c5b0622dffb --- /dev/null +++ b/accessible/src/jsat/ContentControl.jsm @@ -0,0 +1,269 @@ +/* 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/. */ + +let Ci = Components.interfaces; +let Cu = Components.utils; + +Cu.import("resource://gre/modules/XPCOMUtils.jsm"); +XPCOMUtils.defineLazyModuleGetter(this, 'Services', + 'resource://gre/modules/Services.jsm'); +XPCOMUtils.defineLazyModuleGetter(this, 'Utils', + 'resource://gre/modules/accessibility/Utils.jsm'); +XPCOMUtils.defineLazyModuleGetter(this, 'Logger', + 'resource://gre/modules/accessibility/Utils.jsm'); +XPCOMUtils.defineLazyModuleGetter(this, 'Roles', + 'resource://gre/modules/accessibility/Constants.jsm'); +XPCOMUtils.defineLazyModuleGetter(this, 'TraversalRules', + 'resource://gre/modules/accessibility/TraversalRules.jsm'); +XPCOMUtils.defineLazyModuleGetter(this, 'Presentation', + 'resource://gre/modules/accessibility/Presentation.jsm'); + +this.EXPORTED_SYMBOLS = ['ContentControl']; + +this.ContentControl = function ContentControl(aContentScope) { + this._contentScope = Cu.getWeakReference(aContentScope); + this._vcCache = new WeakMap(); + this._childMessageSenders = new WeakMap(); +}; + +this.ContentControl.prototype = { + messagesOfInterest: ['AccessFu:MoveCursor', + 'AccessFu:ClearCursor', + 'AccessFu:MoveToPoint', + 'AccessFu:AutoMove'], + + start: function ContentControl_start() { + let cs = this._contentScope.get(); + for (let message of this.messagesOfInterest) { + cs.addMessageListener(message, this); + } + }, + + stop: function ContentControl_stop() { + let cs = this._contentScope.get(); + for (let message of this.messagesOfInterest) { + cs.removeMessageListener(message, this); + } + }, + + get document() { + return this._contentScope.get().content.document; + }, + + get window() { + return this._contentScope.get().content; + }, + + get vc() { + return Utils.getVirtualCursor(this.document); + }, + + receiveMessage: function ContentControl_receiveMessage(aMessage) { + Logger.debug(() => { + return ['ContentControl.receiveMessage', + this.document.location.toString(), + JSON.stringify(aMessage.json)]; + }); + + try { + switch (aMessage.name) { + case 'AccessFu:MoveCursor': + this.handleMove(aMessage); + break; + case 'AccessFu:ClearCursor': + this.handleClear(aMessage); + break; + case 'AccessFu:MoveToPoint': + this.handleMoveToPoint(aMessage); + break; + case 'AccessFu:AutoMove': + this.handleAutoMove(aMessage); + break; + default: + break; + } + } catch (x) { + Logger.logException( + x, 'Error handling message: ' + JSON.stringify(aMessage.json)); + } + }, + + handleMove: function ContentControl_handleMove(aMessage) { + let origin = aMessage.json.origin; + let action = aMessage.json.action; + let vc = this.vc; + + if (origin != 'child' && this.sendToChild(vc, aMessage)) { + // Forwarded succesfully to child cursor. + return; + } + + let moved = vc[action](TraversalRules[aMessage.json.rule]); + + if (moved) { + if (origin === 'child') { + // We just stepped out of a child, clear child cursor. + Utils.getMessageManager(aMessage.target).sendAsyncMessage( + 'AccessFu:ClearCursor', {}); + } else { + // We potentially landed on a new child cursor. If so, we want to + // either be on the first or last item in the child doc. + let childAction = action; + if (action === 'moveNext') { + childAction = 'moveFirst'; + } else if (action === 'movePrevious') { + childAction = 'moveLast'; + } + + // Attempt to forward move to a potential child cursor in our + // new position. + this.sendToChild(vc, aMessage, { action: childAction}); + } + } else if (!this._childMessageSenders.has(aMessage.target)) { + // We failed to move, and the message is not from a child, so forward + // to parent. + this.sendToParent(aMessage); + } + }, + + handleMoveToPoint: function ContentControl_handleMoveToPoint(aMessage) { + let [x, y] = [aMessage.json.x, aMessage.json.y]; + let rule = TraversalRules[aMessage.json.rule]; + let vc = this.vc; + let win = this.window; + + let dpr = win.devicePixelRatio; + this.vc.moveToPoint(rule, x * dpr, y * dpr, true); + + let delta = Utils.isContentProcess ? + { x: x - win.mozInnerScreenX, y: y - win.mozInnerScreenY } : {}; + this.sendToChild(vc, aMessage, delta); + }, + + handleClear: function ContentControl_handleClear(aMessage) { + this.sendToChild(this.vc, aMessage); + this.vc.position = null; + }, + + handleAutoMove: function ContentControl_handleAutoMove(aMessage) { + this.autoMove(null, aMessage.json); + }, + + getChildCursor: function ContentControl_getChildCursor(aAccessible) { + let acc = aAccessible || this.vc.position; + if (Utils.isAliveAndVisible(acc) && acc.role === Roles.INTERNAL_FRAME) { + let domNode = acc.DOMNode; + let mm = this._childMessageSenders.get(domNode, null); + if (!mm) { + mm = Utils.getMessageManager(domNode); + mm.addWeakMessageListener('AccessFu:MoveCursor', this); + this._childMessageSenders.set(domNode, mm); + } + + return mm; + } + + return null; + }, + + sendToChild: function ContentControl_sendToChild(aVirtualCursor, + aMessage, + aReplacer) { + let mm = this.getChildCursor(aVirtualCursor.position); + if (!mm) { + return false; + } + + // XXX: This is a silly way to make a deep copy + let newJSON = JSON.parse(JSON.stringify(aMessage.json)); + newJSON.origin = 'parent'; + for (let attr in aReplacer) { + newJSON[attr] = aReplacer[attr]; + } + + mm.sendAsyncMessage(aMessage.name, newJSON); + return true; + }, + + sendToParent: function ContentControl_sendToParent(aMessage) { + // XXX: This is a silly way to make a deep copy + let newJSON = JSON.parse(JSON.stringify(aMessage.json)); + newJSON.origin = 'child'; + aMessage.target.sendAsyncMessage(aMessage.name, newJSON); + }, + + /** + * Move cursor and/or present its location. + * aOptions could have any of these fields: + * - delay: in ms, before actual move is performed. Another autoMove call + * would cancel it. Useful if we want to wait for a possible trailing + * focus move. Default 0. + * - noOpIfOnScreen: if accessible is alive and visible, don't do anything. + * - forcePresent: present cursor location, whether we move or don't. + * - moveToFocused: if there is a focused accessible move to that. This takes + * precedence over given anchor. + * - moveMethod: pivot move method to use, default is 'moveNext', + */ + autoMove: function ContentControl_autoMove(aAnchor, aOptions = {}) { + let win = this.window; + win.clearTimeout(this._autoMove); + + let moveFunc = () => { + let vc = this.vc; + let acc = aAnchor; + let rule = aOptions.onScreenOnly ? + TraversalRules.SimpleOnScreen : TraversalRules.Simple; + let forcePresentFunc = () => { + if (aOptions.forcePresent) { + this._contentScope.get().sendAsyncMessage( + 'AccessFu:Present', Presentation.pivotChanged( + vc.position, null, Ci.nsIAccessiblePivot.REASON_NONE, + vc.startOffset, vc.endOffset)); + } + }; + + if (aOptions.noOpIfOnScreen && + Utils.isAliveAndVisible(vc.position, true)) { + forcePresentFunc(); + return; + } + + if (aOptions.moveToFocused) { + acc = Utils.AccRetrieval.getAccessibleFor( + this.document.activeElement) || acc; + } + + let moved = false; + let moveMethod = aOptions.moveMethod || 'moveNext'; // default is moveNext + let moveFirstOrLast = moveMethod in ['moveFirst', 'moveLast']; + if (!moveFirstOrLast || acc) { + // We either need next/previous or there is an anchor we need to use. + moved = vc[moveFirstOrLast ? 'moveNext' : moveMethod](rule, acc, true); + } + if (moveFirstOrLast && !moved) { + // We move to first/last after no anchor move happened or succeeded. + moved = vc[moveMethod](rule); + } + + let sentToChild = this.sendToChild(vc, { + name: 'AccessFu:AutoMove', + json: aOptions + }); + + if (!moved && !sentToChild) { + forcePresentFunc(); + } + }; + + if (aOptions.delay) { + this._autoMove = win.setTimeout(moveFunc, aOptions.delay); + } else { + moveFunc(); + } + }, + + QueryInterface: XPCOMUtils.generateQI([Ci.nsISupportsWeakReference, + Ci.nsIMessageListener + ]) +}; \ No newline at end of file diff --git a/accessible/src/jsat/EventManager.jsm b/accessible/src/jsat/EventManager.jsm index 9aa035925d6..98dd1a96df0 100644 --- a/accessible/src/jsat/EventManager.jsm +++ b/accessible/src/jsat/EventManager.jsm @@ -98,18 +98,11 @@ this.EventManager.prototype = { case 'wheel': { let attempts = 0; - let vc = Utils.getVirtualCursor(this.contentScope.content.document); - let intervalId = this.contentScope.content.setInterval(() => { - if (!Utils.isAliveAndVisible(vc.position, true)) { - this.contentScope.content.clearInterval(intervalId); - let delta = aEvent.deltaX || aEvent.deltaY; - this.contentScope.content.setTimeout(() => { - vc[delta > 0 ? 'moveNext' : 'movePrevious'](TraversalRules.SimpleOnScreen); - }, 100); - } else if (++attempts > 5) { - this.contentScope.content.clearInterval(intervalId); - } - }, 150); + let delta = aEvent.deltaX || aEvent.deltaY; + this.contentScope.contentControl.autoMove( + null, + { moveMethod: delta > 0 ? 'moveNext' : 'movePrevious', + onScreenOnly: true, noOpIfOnScreen: true, delay: 500 }); break; } case 'scroll': @@ -162,11 +155,6 @@ this.EventManager.prototype = { let reason = event.reason; let oldAccessible = event.oldAccessible; - if (oldAccessible && oldAccessible.role == Roles.INTERNAL_FRAME) { - let mm = Utils.getMessageManager(oldAccessible.DOMNode); - mm.sendAsyncMessage('AccessFu:ClearCursor', {}); - } - if (this.editState.editing) { aEvent.accessibleDocument.takeFocus(); } @@ -195,8 +183,7 @@ this.EventManager.prototype = { } case Events.SCROLLING_START: { - let vc = Utils.getVirtualCursor(this.contentScope.content.document); - vc.moveNext(TraversalRules.Simple, aEvent.accessible, true); + this.contentScope.contentControl.autoMove(aEvent.accessible); break; } case Events.TEXT_CARET_MOVED: @@ -285,18 +272,14 @@ this.EventManager.prototype = { let acc = aEvent.accessible; let doc = aEvent.accessibleDocument; if (acc.role != Roles.DOCUMENT && doc.role != Roles.CHROME_WINDOW) { - this.contentScope.content.clearTimeout(this._autoMove); - let vc = Utils.getVirtualCursor(this.contentScope.content.document); - vc.moveNext(TraversalRules.Simple, acc, true); - } - break; + this.contentScope.contentControl.autoMove(acc); + } + break; } case Events.DOCUMENT_LOAD_COMPLETE: { - this._autoMove = this.contentScope.content.setTimeout(() => { - Utils.getVirtualCursor(this.contentScope.content.document) - .moveNext(TraversalRules.Simple, aEvent.accessible, true); - }, 500); + this.contentScope.contentControl.autoMove( + aEvent.accessible, { delay: 500 }); break; } } diff --git a/accessible/src/jsat/content-script.js b/accessible/src/jsat/content-script.js index c3d5fc82978..7ba86e201b4 100644 --- a/accessible/src/jsat/content-script.js +++ b/accessible/src/jsat/content-script.js @@ -20,118 +20,15 @@ XPCOMUtils.defineLazyModuleGetter(this, 'Utils', 'resource://gre/modules/accessibility/Utils.jsm'); XPCOMUtils.defineLazyModuleGetter(this, 'EventManager', 'resource://gre/modules/accessibility/EventManager.jsm'); +XPCOMUtils.defineLazyModuleGetter(this, 'ContentControl', + 'resource://gre/modules/accessibility/ContentControl.jsm'); XPCOMUtils.defineLazyModuleGetter(this, 'Roles', 'resource://gre/modules/accessibility/Constants.jsm'); Logger.debug('content-script.js'); let eventManager = null; - -function clearCursor(aMessage) { - try { - Utils.getVirtualCursor(content.document).position = null; - forwardToChild(aMessage); - } catch (x) { - Logger.logException(x); - } -} - -function moveCursor(aMessage) { - if (Logger.logLevel >= Logger.DEBUG) { - Logger.debug(aMessage.name, JSON.stringify(aMessage.json, null, ' ')); - } - - let vc = Utils.getVirtualCursor(content.document); - let origin = aMessage.json.origin; - let action = aMessage.json.action; - let rule = TraversalRules[aMessage.json.rule]; - - function moveCursorInner() { - try { - if (origin == 'parent' && - !Utils.isAliveAndVisible(vc.position)) { - // We have a bad position in this frame, move vc to last or first item. - if (action == 'moveNext') { - return vc.moveFirst(rule); - } else if (action == 'movePrevious') { - return vc.moveLast(rule); - } - } - - return vc[action](rule); - } catch (x) { - if (action == 'moveNext' || action == 'movePrevious') { - // If we are trying to move next/prev put the vc on the focused item. - let acc = Utils.AccRetrieval. - getAccessibleFor(content.document.activeElement); - return vc.moveNext(rule, acc, true); - } else { - throw x; - } - } - - return false; - } - - try { - if (origin != 'child' && - forwardToChild(aMessage, moveCursor, vc.position)) { - // We successfully forwarded the move to the child document. - return; - } - - if (moveCursorInner()) { - // If we moved, try forwarding the message to the new position, - // it may be a frame with a vc of its own. - forwardToChild(aMessage, moveCursor, vc.position); - } else { - // If we did not move, we probably reached the end or start of the - // document, go back to parent content and move us out of the iframe. - if (origin == 'parent') { - vc.position = null; - } - forwardToParent(aMessage); - } - } catch (x) { - Logger.logException(x, 'Cursor move failed'); - } -} - -function moveToPoint(aMessage) { - if (Logger.logLevel >= Logger.DEBUG) { - Logger.debug(aMessage.name, JSON.stringify(aMessage.json, null, ' ')); - } - - let vc = Utils.getVirtualCursor(content.document); - let details = aMessage.json; - let rule = TraversalRules[details.rule]; - - try { - let dpr = content.devicePixelRatio; - vc.moveToPoint(rule, details.x * dpr, details.y * dpr, true); - forwardToChild(aMessage, moveToPoint, vc.position); - } catch (x) { - Logger.logException(x, 'Failed move to point'); - } -} - -function showCurrent(aMessage) { - Logger.debug(() => { - return [aMessage.name, JSON.stringify(aMessage.json, null, ' ')]; - }); - - let vc = Utils.getVirtualCursor(content.document); - - if (!forwardToChild(vc, showCurrent, aMessage)) { - if (!vc.position && aMessage.json.move) { - vc.moveFirst(TraversalRules.Simple); - } else { - sendAsyncMessage('AccessFu:Present', Presentation.pivotChanged( - vc.position, null, Ci.nsIAccessiblePivot.REASON_NONE, - vc.startOffset, vc.endOffset)); - } - } -} +let contentControl = null; function forwardToParent(aMessage) { // XXX: This is a silly way to make a deep copy @@ -385,22 +282,23 @@ addMessageListener( if (m.json.buildApp) Utils.MozBuildApp = m.json.buildApp; - addMessageListener('AccessFu:MoveToPoint', moveToPoint); - addMessageListener('AccessFu:MoveCursor', moveCursor); - addMessageListener('AccessFu:ShowCurrent', showCurrent); addMessageListener('AccessFu:Activate', activateCurrent); addMessageListener('AccessFu:ContextMenu', activateContextMenu); addMessageListener('AccessFu:Scroll', scroll); addMessageListener('AccessFu:AdjustRange', adjustRange); addMessageListener('AccessFu:MoveCaret', moveCaret); addMessageListener('AccessFu:MoveByGranularity', moveByGranularity); - addMessageListener('AccessFu:ClearCursor', clearCursor); if (!eventManager) { eventManager = new EventManager(this); } eventManager.start(); + if (!contentControl) { + contentControl = new ContentControl(this); + } + contentControl.start(); + sendAsyncMessage('AccessFu:ContentStarted'); }); @@ -409,17 +307,14 @@ addMessageListener( function(m) { Logger.debug('AccessFu:Stop'); - removeMessageListener('AccessFu:MoveToPoint', moveToPoint); - removeMessageListener('AccessFu:MoveCursor', moveCursor); - removeMessageListener('AccessFu:ShowCurrent', showCurrent); removeMessageListener('AccessFu:Activate', activateCurrent); removeMessageListener('AccessFu:ContextMenu', activateContextMenu); removeMessageListener('AccessFu:Scroll', scroll); removeMessageListener('AccessFu:MoveCaret', moveCaret); removeMessageListener('AccessFu:MoveByGranularity', moveByGranularity); - removeMessageListener('AccessFu:ClearCursor', clearCursor); eventManager.stop(); + contentControl.stop(); }); sendAsyncMessage('AccessFu:Ready'); diff --git a/accessible/src/jsat/moz.build b/accessible/src/jsat/moz.build index 970ecc6de30..987c5687600 100644 --- a/accessible/src/jsat/moz.build +++ b/accessible/src/jsat/moz.build @@ -9,6 +9,7 @@ JS_MODULES_PATH = 'modules/accessibility' EXTRA_JS_MODULES += [ 'AccessFu.jsm', 'Constants.jsm', + 'ContentControl.jsm', 'EventManager.jsm', 'OutputGenerator.jsm', 'Presentation.jsm', From 1b35433cbc96361bd4d28e45d007ac480151ee87 Mon Sep 17 00:00:00 2001 From: Eitan Isaacson Date: Tue, 4 Mar 2014 17:49:27 -0800 Subject: [PATCH 056/112] Bug 976271 - Add dialog tests to jsat suite. r=yzen --- .../jsat/doc_content_integration.html | 44 +++++++++++++++++-- accessible/tests/mochitest/jsat/jsatcommon.js | 10 +++-- .../jsat/test_content_integration.html | 32 +++++++++++--- 3 files changed, 75 insertions(+), 11 deletions(-) diff --git a/accessible/tests/mochitest/jsat/doc_content_integration.html b/accessible/tests/mochitest/jsat/doc_content_integration.html index 8f60db9d8ba..81d55c3c835 100644 --- a/accessible/tests/mochitest/jsat/doc_content_integration.html +++ b/accessible/tests/mochitest/jsat/doc_content_integration.html @@ -12,18 +12,56 @@ '' + ''; + function showAlert() { + document.getElementById('alert').hidden = false; + } + + function hideAlert() { + document.getElementById('alert').hidden = true; + } +
Phone status bar
-
- +
+
+ +
+ diff --git a/accessible/tests/mochitest/jsat/jsatcommon.js b/accessible/tests/mochitest/jsat/jsatcommon.js index 639df5e8b22..7d3aaceb6a6 100644 --- a/accessible/tests/mochitest/jsat/jsatcommon.js +++ b/accessible/tests/mochitest/jsat/jsatcommon.js @@ -216,13 +216,17 @@ AccessFuContentTest.prototype = { if (this.currentPair) { if (this.currentPair[0] instanceof Function) { this.currentPair[0](this.mms[0]); - } else { + } else if (this.currentPair[0]) { this.mms[0].sendAsyncMessage(this.currentPair[0].name, - this.currentPair[0].json); + this.currentPair[0].json); } + + if (!this.currentPair[1]) { + this.pump(); + } } else if (this.finishedCallback) { for (var mm of this.mms) { - mm.sendAsyncMessage('AccessFu:Stop'); + mm.sendAsyncMessage('AccessFu:Stop'); } this.finishedCallback(); } diff --git a/accessible/tests/mochitest/jsat/test_content_integration.html b/accessible/tests/mochitest/jsat/test_content_integration.html index c6e2347bfb8..80c9f68a41b 100644 --- a/accessible/tests/mochitest/jsat/test_content_integration.html +++ b/accessible/tests/mochitest/jsat/test_content_integration.html @@ -125,10 +125,10 @@ // Move cursor with focus in outside document [simpleMoveNext, { speak: 'Phone status bar Traversal Rule test document' }], - [ focusFunc('button', false), { speak: 'Home button' }], + [ focusFunc('button#home', false), { speak: 'Home button' }], // Blur button and reset cursor - [focusFunc('button', true), null], + [focusFunc('button#home', true), null], [clearCursor, null], // Set focus on element outside of embedded frame while cursor is in frame @@ -136,12 +136,34 @@ { speak: 'Phone status bar Traversal Rule test document' }], [simpleMoveNext, { speak: 'wow heading level 1 such app' }], - [focusFunc('button', false), { speak: 'Home button' }] + [focusFunc('button#home', false), { speak: 'Home button' }] // XXX: Set focus on iframe itself. // XXX: Set focus on element in iframe when cursor is outside of it. // XXX: Set focus on element in iframe when cursor is in iframe. - ]); + + [clearCursor, null], + + // Open dialog in outer doc, while cursor is also in outer doc + [simpleMoveNext, + { speak: 'Phone status bar Traversal Rule test document' }], + [doc.defaultView.showAlert, + { speak: 'This is an alert! heading level 1 dialog' }], + + // XXX: Place cursor back where it was. + [doc.defaultView.hideAlert, null ], + + // Open dialog in outer doc, while cursor is in inner frame + [simpleMoveFirst, + { speak: 'Phone status bar Traversal Rule test document' }], + [simpleMoveNext, + { speak: 'wow heading level 1 such app' }], + [doc.defaultView.showAlert, + { speak: 'This is an alert! heading level 1 dialog' }], + + // XXX: Place cursor back where it was. + [doc.defaultView.hideAlert, null ] + ]); contentTest.start(function () { closeBrowserWindow(); @@ -150,7 +172,7 @@ }); iframe.src = 'data:text/html;charset=utf-8,' + doc.defaultView.frameContents; - doc.querySelector('#windows').appendChild(iframe); + doc.getElementById('appframe').appendChild(iframe); } SimpleTest.waitForExplicitFinish(); From 05be99d38f7e9b02efce6052898490c72612cc9e Mon Sep 17 00:00:00 2001 From: Eitan Isaacson Date: Tue, 4 Mar 2014 17:49:27 -0800 Subject: [PATCH 057/112] Bug 976274 - Introduce hide support. r=yzen --- accessible/src/jsat/EventManager.jsm | 27 ++++++++++------ accessible/src/jsat/Utils.jsm | 27 ++++++++++++++-- .../jsat/test_content_integration.html | 31 +++++++++++++++---- 3 files changed, 67 insertions(+), 18 deletions(-) diff --git a/accessible/src/jsat/EventManager.jsm b/accessible/src/jsat/EventManager.jsm index 98dd1a96df0..15ede982712 100644 --- a/accessible/src/jsat/EventManager.jsm +++ b/accessible/src/jsat/EventManager.jsm @@ -240,18 +240,25 @@ this.EventManager.prototype = { } case Events.HIDE: { + let evt = aEvent.QueryInterface(Ci.nsIAccessibleHideEvent); let {liveRegion, isPolite} = this._handleLiveRegion( - aEvent.QueryInterface(Ci.nsIAccessibleHideEvent), - ['removals', 'all']); - // Only handle hide if it is a relevant live region. - if (!liveRegion) { - break; + evt, ['removals', 'all']); + if (liveRegion) { + // Hide for text is handled by the EVENT_TEXT_REMOVED handler. + if (aEvent.accessible.role === Roles.TEXT_LEAF) { + break; + } + this._queueLiveEvent(Events.HIDE, liveRegion, isPolite); + } else { + let vc = Utils.getVirtualCursor(this.contentScope.content.document); + if (vc.position && + (Utils.getState(vc.position).contains(States.DEFUNCT) || + Utils.isInSubtree(vc.position, aEvent.accessible))) { + this.contentScope.contentControl.autoMove( + evt.targetPrevSibling || evt.targetParent, + { moveToFocused: true, delay: 500 }); + } } - // Hide for text is handled by the EVENT_TEXT_REMOVED handler. - if (aEvent.accessible.role === Roles.TEXT_LEAF) { - break; - } - this._queueLiveEvent(Events.HIDE, liveRegion, isPolite); break; } case Events.TEXT_INSERTED: diff --git a/accessible/src/jsat/Utils.jsm b/accessible/src/jsat/Utils.jsm index 5d61708c5f2..03b8e8be48b 100644 --- a/accessible/src/jsat/Utils.jsm +++ b/accessible/src/jsat/Utils.jsm @@ -247,6 +247,24 @@ this.Utils = { return new Rect(objX.value, objY.value, objW.value, objH.value); }, + isInSubtree: function isInSubtree(aAccessible, aSubTreeRoot) { + let acc = aAccessible; + while (acc) { + if (acc == aSubTreeRoot) { + return true; + } + + try { + acc = acc.parent; + } catch (x) { + Logger.debug('Failed to get parent:', x); + acc = null; + } + } + + return false; + }, + inHiddenSubtree: function inHiddenSubtree(aAccessible) { for (let acc=aAccessible; acc; acc=acc.parent) { let hidden = Utils.getAttributes(acc).hidden; @@ -565,8 +583,13 @@ PivotContext.prototype = { _getAncestry: function _getAncestry(aAccessible) { let ancestry = []; let parent = aAccessible; - while (parent && (parent = parent.parent)) { - ancestry.push(parent); + try { + while (parent && (parent = parent.parent)) { + ancestry.push(parent); + } + } catch (e) { + // A defunct accessible will raise an exception geting parent. + Logger.debug('Failed to get parent:', x); } return ancestry.reverse(); }, diff --git a/accessible/tests/mochitest/jsat/test_content_integration.html b/accessible/tests/mochitest/jsat/test_content_integration.html index 80c9f68a41b..184cbc27428 100644 --- a/accessible/tests/mochitest/jsat/test_content_integration.html +++ b/accessible/tests/mochitest/jsat/test_content_integration.html @@ -138,23 +138,27 @@ { speak: 'wow heading level 1 such app' }], [focusFunc('button#home', false), { speak: 'Home button' }] + // Blur button and reset cursor + [focusFunc('button#home', true), null], + [clearCursor, null], + // XXX: Set focus on iframe itself. // XXX: Set focus on element in iframe when cursor is outside of it. // XXX: Set focus on element in iframe when cursor is in iframe. - [clearCursor, null], - // Open dialog in outer doc, while cursor is also in outer doc [simpleMoveNext, { speak: 'Phone status bar Traversal Rule test document' }], [doc.defaultView.showAlert, { speak: 'This is an alert! heading level 1 dialog' }], - // XXX: Place cursor back where it was. - [doc.defaultView.hideAlert, null ], + [function () { doc.defaultView.hideAlert() }, + { speak: 'wow heading level 1 such app' }], + + [clearCursor, null], // Open dialog in outer doc, while cursor is in inner frame - [simpleMoveFirst, + [simpleMoveNext, { speak: 'Phone status bar Traversal Rule test document' }], [simpleMoveNext, { speak: 'wow heading level 1 such app' }], @@ -162,7 +166,22 @@ { speak: 'This is an alert! heading level 1 dialog' }], // XXX: Place cursor back where it was. - [doc.defaultView.hideAlert, null ] + [doc.defaultView.hideAlert, + { speak: 'many option not checked check button such app' }], + + [clearCursor, null], + + // Open dialog, then focus on something when closing + [simpleMoveNext, + { speak: 'Phone status bar Traversal Rule test document' }], + [doc.defaultView.showAlert, + { speak: 'This is an alert! heading level 1 dialog' }], + + [function () { + doc.defaultView.hideAlert(); + doc.querySelector('button#home').focus(); + }, + { speak: 'Home button Traversal Rule test document' }] ]); contentTest.start(function () { From f46941cf7a903615b3ba82da0d02795585578a1e Mon Sep 17 00:00:00 2001 From: Seth Fowler Date: Tue, 4 Mar 2014 17:59:03 -0800 Subject: [PATCH 058/112] Bug 952354 - Draw non-premultiplied alpha raster image frames if the frame is opaque. r=jrmuizel --HG-- extra : rebase_source : 62956f725b3a4765a7617a37bf79b4be2e37c739 --- image/src/RasterImage.cpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/image/src/RasterImage.cpp b/image/src/RasterImage.cpp index e31a9db0e8c..9eb378525df 100644 --- a/image/src/RasterImage.cpp +++ b/image/src/RasterImage.cpp @@ -2616,8 +2616,16 @@ RasterImage::Draw(gfxContext *aContext, NS_ENSURE_ARG_POINTER(aContext); - // We can only draw with the default decode flags - if (mFrameDecodeFlags != DECODE_FLAGS_DEFAULT) { + // We can only draw without discarding and redecoding in these cases: + // * We have the default decode flags. + // * We have exactly FLAG_DECODE_NO_PREMULTIPLY_ALPHA and the current frame + // is opaque. + bool haveDefaultFlags = (mFrameDecodeFlags == DECODE_FLAGS_DEFAULT); + bool haveSafeAlphaFlags = + (mFrameDecodeFlags == FLAG_DECODE_NO_PREMULTIPLY_ALPHA) && + FrameIsOpaque(FRAME_CURRENT); + + if (!(haveDefaultFlags || haveSafeAlphaFlags)) { if (!CanForciblyDiscardAndRedecode()) return NS_ERROR_NOT_AVAILABLE; ForceDiscard(); From 85c733191c6b4297b96e6f769a01a70d77863569 Mon Sep 17 00:00:00 2001 From: William Chen Date: Fri, 28 Feb 2014 17:45:31 -0800 Subject: [PATCH 059/112] Bug 978398 - Rename custom element callbacks from enteredView/leftView to attached/detached. r=mrbkap --- content/base/public/nsIDocument.h | 4 +- content/base/src/Element.cpp | 8 +- content/base/src/nsDocument.cpp | 36 +++---- content/base/src/nsDocument.h | 2 +- .../test_document_register_lifecycle.html | 94 +++++++++---------- .../test_document_register_stack.html | 34 +++---- dom/webidl/WebComponents.webidl | 8 +- 7 files changed, 93 insertions(+), 93 deletions(-) diff --git a/content/base/public/nsIDocument.h b/content/base/public/nsIDocument.h index ae5f193e8e9..f0409a8c721 100644 --- a/content/base/public/nsIDocument.h +++ b/content/base/public/nsIDocument.h @@ -2004,8 +2004,8 @@ public: enum ElementCallbackType { eCreated, - eEnteredView, - eLeftView, + eAttached, + eDetached, eAttributeChanged }; diff --git a/content/base/src/Element.cpp b/content/base/src/Element.cpp index d0d57d61e86..6f196b73341 100644 --- a/content/base/src/Element.cpp +++ b/content/base/src/Element.cpp @@ -1158,8 +1158,8 @@ Element::BindToTree(nsIDocument* aDocument, nsIContent* aParent, SetInDocument(); if (GetCustomElementData()) { - // Enqueue an enteredView callback for the custom element. - aDocument->EnqueueLifecycleCallback(nsIDocument::eEnteredView, this); + // Enqueue an attached callback for the custom element. + aDocument->EnqueueLifecycleCallback(nsIDocument::eAttached, this); } // Unset this flag since we now really are in a document. @@ -1321,8 +1321,8 @@ Element::UnbindFromTree(bool aDeep, bool aNullParent) document->ClearBoxObjectFor(this); if (GetCustomElementData()) { - // Enqueue a leftView callback for the custom element. - document->EnqueueLifecycleCallback(nsIDocument::eLeftView, this); + // Enqueue a detached callback for the custom element. + document->EnqueueLifecycleCallback(nsIDocument::eDetached, this); } } diff --git a/content/base/src/nsDocument.cpp b/content/base/src/nsDocument.cpp index 62b87010644..be3c5b020c6 100644 --- a/content/base/src/nsDocument.cpp +++ b/content/base/src/nsDocument.cpp @@ -331,11 +331,11 @@ CustomElementCallback::Call() static_cast(mCallback.get())->Call(mThisObject, rv); mOwnerData->mElementIsBeingCreated = false; break; - case nsIDocument::eEnteredView: - static_cast(mCallback.get())->Call(mThisObject, rv); + case nsIDocument::eAttached: + static_cast(mCallback.get())->Call(mThisObject, rv); break; - case nsIDocument::eLeftView: - static_cast(mCallback.get())->Call(mThisObject, rv); + case nsIDocument::eDetached: + static_cast(mCallback.get())->Call(mThisObject, rv); break; case nsIDocument::eAttributeChanged: static_cast(mCallback.get())->Call(mThisObject, @@ -1750,16 +1750,16 @@ CustomDefinitionsTraverse(CustomElementHashKey* aKey, cb->NoteXPCOMChild(aDefinition->mCallbacks->mCreatedCallback.Value()); } - if (callbacks->mEnteredViewCallback.WasPassed()) { + if (callbacks->mAttachedCallback.WasPassed()) { NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(*cb, - "mCustomDefinitions->mCallbacks->mEnteredViewCallback"); - cb->NoteXPCOMChild(aDefinition->mCallbacks->mEnteredViewCallback.Value()); + "mCustomDefinitions->mCallbacks->mAttachedCallback"); + cb->NoteXPCOMChild(aDefinition->mCallbacks->mAttachedCallback.Value()); } - if (callbacks->mLeftViewCallback.WasPassed()) { + if (callbacks->mDetachedCallback.WasPassed()) { NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(*cb, - "mCustomDefinitions->mCallbacks->mLeftViewCallback"); - cb->NoteXPCOMChild(aDefinition->mCallbacks->mLeftViewCallback.Value()); + "mCustomDefinitions->mCallbacks->mDetachedCallback"); + cb->NoteXPCOMChild(aDefinition->mCallbacks->mDetachedCallback.Value()); } return PL_DHASH_NEXT; @@ -5571,15 +5571,15 @@ nsDocument::EnqueueLifecycleCallback(nsIDocument::ElementCallbackType aType, } break; - case nsIDocument::eEnteredView: - if (definition->mCallbacks->mEnteredViewCallback.WasPassed()) { - func = definition->mCallbacks->mEnteredViewCallback.Value(); + case nsIDocument::eAttached: + if (definition->mCallbacks->mAttachedCallback.WasPassed()) { + func = definition->mCallbacks->mAttachedCallback.Value(); } break; - case nsIDocument::eLeftView: - if (definition->mCallbacks->mLeftViewCallback.WasPassed()) { - func = definition->mCallbacks->mLeftViewCallback.Value(); + case nsIDocument::eDetached: + if (definition->mCallbacks->mDetachedCallback.WasPassed()) { + func = definition->mCallbacks->mDetachedCallback.Value(); } break; @@ -5922,12 +5922,12 @@ nsDocument::RegisterElement(JSContext* aCx, const nsAString& aType, EnqueueLifecycleCallback(nsIDocument::eCreated, elem, nullptr, definition); if (elem->GetCurrentDoc()) { // Normally callbacks can not be enqueued until the created - // callback has been invoked, however, the entered view callback + // callback has been invoked, however, the attached callback // in element upgrade is an exception so pretend the created // callback has been invoked. elem->GetCustomElementData()->mCreatedCallbackInvoked = true; - EnqueueLifecycleCallback(nsIDocument::eEnteredView, elem, nullptr, definition); + EnqueueLifecycleCallback(nsIDocument::eAttached, elem, nullptr, definition); } } } diff --git a/content/base/src/nsDocument.h b/content/base/src/nsDocument.h index 068b27b0437..44260585f4b 100644 --- a/content/base/src/nsDocument.h +++ b/content/base/src/nsDocument.h @@ -313,7 +313,7 @@ private: // The this value to use for invocation of the callback. nsRefPtr mThisObject; nsRefPtr mCallback; - // The type of callback (eCreated, eEnteredView, etc.) + // The type of callback (eCreated, eAttached, etc.) nsIDocument::ElementCallbackType mType; // Arguments to be passed to the callback, // used by the attribute changed callback. diff --git a/dom/tests/mochitest/webcomponents/test_document_register_lifecycle.html b/dom/tests/mochitest/webcomponents/test_document_register_lifecycle.html index ea6895be566..a1826883ba1 100644 --- a/dom/tests/mochitest/webcomponents/test_document_register_lifecycle.html +++ b/dom/tests/mochitest/webcomponents/test_document_register_lifecycle.html @@ -24,8 +24,8 @@ function testRegisterUnresolved() { var helloElem = document.getElementById("hello"); var createdCallbackCalled = false; - var enteredViewCallbackCalled = false; - var leftViewCallbackCalled = false; + var attachedCallbackCalled = false; + var detachedCallbackCalled = false; var p = Object.create(HTMLElement.prototype); p.createdCallback = function() { @@ -35,17 +35,17 @@ function testRegisterUnresolved() { createdCallbackCalled = true; }; - p.enteredViewCallback = function() { - is(createdCallbackCalled, true, "Created callback should be called before enteredView"); - is(enteredViewCallbackCalled, false, "enteredView callback should only be called once in this test."); + p.attachedCallback = function() { + is(createdCallbackCalled, true, "Created callback should be called before attached"); + is(attachedCallbackCalled, false, "attached callback should only be called once in this test."); is(this, helloElem, "The 'this' value should be the custom element."); - enteredViewCallbackCalled = true; + attachedCallbackCalled = true; }; - p.leftViewCallback = function() { - is(enteredViewCallbackCalled, true, "enteredView callback should be called before leftView"); - is(leftViewCallbackCalled, false, "leftView callback should only be called once in this test."); - leftViewCallbackCalled = true; + p.detachedCallback = function() { + is(attachedCallbackCalled, true, "attached callback should be called before detached"); + is(detachedCallbackCalled, false, "detached callback should only be called once in this test."); + detachedCallbackCalled = true; is(this, helloElem, "The 'this' value should be the custom element."); runNextTest(); }; @@ -57,7 +57,7 @@ function testRegisterUnresolved() { document.registerElement("x-hello", { prototype: p }); is(createdCallbackCalled, true, "created callback should be called when control returns to script from user agent code"); - // Remove element from document to trigger leftView callback. + // Remove element from document to trigger detached callback. container.removeChild(helloElem); } @@ -67,8 +67,8 @@ function testRegisterUnresolvedExtended() { var buttonElem = document.getElementById("extbutton"); var createdCallbackCalled = false; - var enteredViewCallbackCalled = false; - var leftViewCallbackCalled = false; + var attachedCallbackCalled = false; + var detachedCallbackCalled = false; var p = Object.create(HTMLButtonElement.prototype); p.createdCallback = function() { @@ -78,17 +78,17 @@ function testRegisterUnresolvedExtended() { createdCallbackCalled = true; }; - p.enteredViewCallback = function() { - is(createdCallbackCalled, true, "Created callback should be called before enteredView"); - is(enteredViewCallbackCalled, false, "enteredView callback should only be called once in this test."); + p.attachedCallback = function() { + is(createdCallbackCalled, true, "Created callback should be called before attached"); + is(attachedCallbackCalled, false, "attached callback should only be called once in this test."); is(this, buttonElem, "The 'this' value should be the custom element."); - enteredViewCallbackCalled = true; + attachedCallbackCalled = true; }; - p.leftViewCallback = function() { - is(enteredViewCallbackCalled, true, "enteredView callback should be called before leftView"); - is(leftViewCallbackCalled, false, "leftView callback should only be called once in this test."); - leftViewCallbackCalled = true; + p.detachedCallback = function() { + is(attachedCallbackCalled, true, "attached callback should be called before detached"); + is(detachedCallbackCalled, false, "detached callback should only be called once in this test."); + detachedCallbackCalled = true; is(this, buttonElem, "The 'this' value should be the custom element."); runNextTest(); }; @@ -100,7 +100,7 @@ function testRegisterUnresolvedExtended() { document.registerElement("x-button", { prototype: p, extends: "button" }); is(createdCallbackCalled, true, "created callback should be called when control returns to script from user agent code"); - // Remove element from document to trigger leftView callback. + // Remove element from document to trigger detached callback. container.removeChild(buttonElem); } @@ -174,8 +174,8 @@ function testInnerHTMLExtendedUpgrade() { // register -> create element -> insert into document -> remove from document function testRegisterResolved() { var createdCallbackCalled = false; - var enteredViewCallbackCalled = false; - var leftViewCallbackCalled = false; + var attachedCallbackCalled = false; + var detachedCallbackCalled = false; var createdCallbackThis; @@ -186,18 +186,18 @@ function testRegisterResolved() { createdCallbackCalled = true; }; - p.enteredViewCallback = function() { - is(createdCallbackCalled, true, "created callback should be called before enteredView callback."); - is(enteredViewCallbackCalled, false, "enteredView callback should only be called on in this test."); + p.attachedCallback = function() { + is(createdCallbackCalled, true, "created callback should be called before attached callback."); + is(attachedCallbackCalled, false, "attached callback should only be called on in this test."); is(this, createdElement, "The 'this' value should be the custom element."); - enteredViewCallbackCalled = true; + attachedCallbackCalled = true; }; - p.leftViewCallback = function() { - is(enteredViewCallbackCalled, true, "enteredView callback should be called before leftView"); - is(leftViewCallbackCalled, false, "leftView callback should only be called once in this test."); + p.detachedCallback = function() { + is(attachedCallbackCalled, true, "attached callback should be called before detached"); + is(detachedCallbackCalled, false, "detached callback should only be called once in this test."); is(this, createdElement, "The 'this' value should be the custom element."); - leftViewCallbackCalled = true; + detachedCallbackCalled = true; runNextTest(); }; @@ -212,10 +212,10 @@ function testRegisterResolved() { is(createdCallbackThis, createdElement, "The 'this' value in the created callback should be the custom element."); is(createdElement.__proto__, p, "Prototype of custom element should be the registered prototype."); - // Insert element into document to trigger enteredView callback. + // Insert element into document to trigger attached callback. container.appendChild(createdElement); - // Remove element from document to trigger leftView callback. + // Remove element from document to trigger detached callback. container.removeChild(createdElement); } @@ -319,11 +319,11 @@ function testUpgradeCandidate() { function testNotInDocEnterLeave() { var p = Object.create(HTMLElement.prototype); - p.enteredView = function() { - ok(false, "enteredView should not be called when not entering the document."); + p.attached = function() { + ok(false, "attached should not be called when not entering the document."); }; - p.leftView = function() { + p.detached = function() { ok(false, "leaveView should not be called when not leaving the document."); }; @@ -343,19 +343,19 @@ function testNotInDocEnterLeave() { } function testEnterLeaveView() { - var enteredViewCallbackCalled = false; - var leftViewCallbackCalled = false; + var attachedCallbackCalled = false; + var detachedCallbackCalled = false; var p = Object.create(HTMLElement.prototype); - p.enteredViewCallback = function() { - is(enteredViewCallbackCalled, false, "enteredView callback should only be called on in this test."); - enteredViewCallbackCalled = true; + p.attachedCallback = function() { + is(attachedCallbackCalled, false, "attached callback should only be called on in this test."); + attachedCallbackCalled = true; }; - p.leftViewCallback = function() { - is(enteredViewCallbackCalled, true, "enteredView callback should be called before leftView"); - is(leftViewCallbackCalled, false, "leftView callback should only be called once in this test."); - leftViewCallbackCalled = true; + p.detachedCallback = function() { + is(attachedCallbackCalled, true, "attached callback should be called before detached"); + is(detachedCallbackCalled, false, "detached callback should only be called once in this test."); + detachedCallbackCalled = true; runNextTest(); }; @@ -363,7 +363,7 @@ function testEnterLeaveView() { document.registerElement("x-element-in-div", { prototype: p }); var customElement = document.createElement("x-element-in-div"); div.appendChild(customElement); - is(enteredViewCallbackCalled, false, "Appending a custom element to a node that is not in the document should not call the enteredView callback."); + is(attachedCallbackCalled, false, "Appending a custom element to a node that is not in the document should not call the attached callback."); container.appendChild(div); container.removeChild(div); diff --git a/dom/tests/mochitest/webcomponents/test_document_register_stack.html b/dom/tests/mochitest/webcomponents/test_document_register_stack.html index 23d78149697..34f1086549a 100644 --- a/dom/tests/mochitest/webcomponents/test_document_register_stack.html +++ b/dom/tests/mochitest/webcomponents/test_document_register_stack.html @@ -24,7 +24,7 @@ function testChangeAttributeInCreatedCallback() { var p = Object.create(HTMLElement.prototype); p.createdCallback = function() { - is(createdCallbackCalled, false, "Created callback should be called before enteredView callback."); + is(createdCallbackCalled, false, "Created callback should be called before attached callback."); createdCallbackCalled = true; is(attributeChangedCallbackCalled, false, "Attribute changed callback should not have been called prior to setting the attribute."); this.setAttribute("foo", "bar"); @@ -46,11 +46,11 @@ function testChangeAttributeInCreatedCallback() { function testChangeAttributeInEnteredViewCallback() { var p = Object.create(HTMLElement.prototype); var attributeChangedCallbackCalled = false; - var enteredViewCallbackCalled = false; + var attachedCallbackCalled = false; - p.enteredViewCallback = function() { - is(enteredViewCallbackCalled, false, "enteredView callback should be called only once in this test."); - enteredViewCallbackCalled = true; + p.attachedCallback = function() { + is(attachedCallbackCalled, false, "attached callback should be called only once in this test."); + attachedCallbackCalled = true; is(attributeChangedCallbackCalled, false, "Attribute changed callback should not be called before changing attribute."); this.setAttribute("foo", "bar"); is(attributeChangedCallbackCalled, true, "Transition from user-agent implementation to script should result in attribute changed callback being called."); @@ -58,7 +58,7 @@ function testChangeAttributeInEnteredViewCallback() { }; p.attributeChangedCallback = function() { - is(enteredViewCallbackCalled, true, "enteredView callback should have been called prior to attribute changed callback."); + is(attachedCallbackCalled, true, "attached callback should have been called prior to attribute changed callback."); is(attributeChangedCallbackCalled, false, "attributeChanged callback should only be called once in this tests."); attributeChangedCallbackCalled = true; }; @@ -72,24 +72,24 @@ function testChangeAttributeInEnteredViewCallback() { function testLeaveViewInEnteredViewCallback() { var p = Object.create(HTMLElement.prototype); - var enteredViewCallbackCalled = false; - var leftViewCallbackCalled = false; + var attachedCallbackCalled = false; + var detachedCallbackCalled = false; var container = document.getElementById("container"); - p.enteredViewCallback = function() { + p.attachedCallback = function() { is(this.parentNode, container, "Parent node should the container in which the node was appended."); - is(enteredViewCallbackCalled, false, "enteredView callback should be called only once in this test."); - enteredViewCallbackCalled = true; - is(leftViewCallbackCalled, false, "leftView callback should not be called prior to removing element from document."); + is(attachedCallbackCalled, false, "attached callback should be called only once in this test."); + attachedCallbackCalled = true; + is(detachedCallbackCalled, false, "detached callback should not be called prior to removing element from document."); container.removeChild(this); - is(leftViewCallbackCalled, true, "Transition from user-agent implementation to script should run left view callback."); + is(detachedCallbackCalled, true, "Transition from user-agent implementation to script should run left view callback."); runNextTest(); }; - p.leftViewCallback = function() { - is(leftViewCallbackCalled, false, "The left view callback should only be called once in this test."); - is(enteredViewCallbackCalled, true, "The entered view callback should be called prior to left view callback."); - leftViewCallbackCalled = true; + p.detachedCallback = function() { + is(detachedCallbackCalled, false, "The detached callback should only be called once in this test."); + is(attachedCallbackCalled, true, "The attached callback should be called prior to detached callback."); + detachedCallbackCalled = true; }; document.registerElement("x-three", { prototype: p }); diff --git a/dom/webidl/WebComponents.webidl b/dom/webidl/WebComponents.webidl index 9ed3c109099..3dfb960bc10 100644 --- a/dom/webidl/WebComponents.webidl +++ b/dom/webidl/WebComponents.webidl @@ -11,14 +11,14 @@ */ callback LifecycleCreatedCallback = void(); -callback LifecycleEnteredViewCallback = void(); -callback LifecycleLeftViewCallback = void(); +callback LifecycleAttachedCallback = void(); +callback LifecycleDetachedCallback = void(); callback LifecycleAttributeChangedCallback = void(DOMString attrName, DOMString? oldValue, DOMString? newValue); dictionary LifecycleCallbacks { LifecycleCreatedCallback? createdCallback; - LifecycleEnteredViewCallback? enteredViewCallback; - LifecycleLeftViewCallback? leftViewCallback; + LifecycleAttachedCallback? attachedCallback; + LifecycleDetachedCallback? detachedCallback; LifecycleAttributeChangedCallback? attributeChangedCallback; }; From fc175da9d15ab8963e3a6f4474be6b7264ae6629 Mon Sep 17 00:00:00 2001 From: Benjamin Smedberg Date: Tue, 4 Mar 2014 12:17:01 -0500 Subject: [PATCH 060/112] Bug 778866 - Abort from the I/O thread on abnormal shutdown of a plugin-process, in case the main thread is wedged and the Firefox process has already been killed, r=cjones --- dom/plugins/ipc/PluginModuleChild.cpp | 4 ++++ ipc/glue/MessageChannel.cpp | 6 +++++- ipc/glue/MessageChannel.h | 9 +++++++++ 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/dom/plugins/ipc/PluginModuleChild.cpp b/dom/plugins/ipc/PluginModuleChild.cpp index b71edc451b8..d8fe0ad2cac 100644 --- a/dom/plugins/ipc/PluginModuleChild.cpp +++ b/dom/plugins/ipc/PluginModuleChild.cpp @@ -144,6 +144,8 @@ PluginModuleChild::Init(const std::string& aPluginFilename, { PLUGIN_LOG_DEBUG_METHOD; + GetIPCChannel()->SetAbortOnError(true); + #ifdef XP_WIN COMMessageFilter::Initialize(this); #endif @@ -595,6 +597,8 @@ PluginModuleChild::AnswerNP_Shutdown(NPError *rv) ResetEventHooks(); #endif + GetIPCChannel()->SetAbortOnError(false); + return true; } diff --git a/ipc/glue/MessageChannel.cpp b/ipc/glue/MessageChannel.cpp index a1aa053d9a1..745d4e5a30d 100644 --- a/ipc/glue/MessageChannel.cpp +++ b/ipc/glue/MessageChannel.cpp @@ -204,7 +204,8 @@ MessageChannel::MessageChannel(MessageListener *aListener) mDispatchingSyncMessage(false), mDispatchingUrgentMessageCount(0), mRemoteStackDepthGuess(false), - mSawInterruptOutMsg(false) + mSawInterruptOutMsg(false), + mAbortOnError(false) { MOZ_COUNT_CTOR(ipc::MessageChannel); @@ -1517,6 +1518,9 @@ MessageChannel::OnChannelErrorFromLink() NotifyWorkerThread(); if (ChannelClosing != mChannelState) { + if (mAbortOnError) { + NS_RUNTIMEABORT("Aborting on channel error."); + } mChannelState = ChannelError; mMonitor->Notify(); } diff --git a/ipc/glue/MessageChannel.h b/ipc/glue/MessageChannel.h index c5bcbde261a..784e4cb64b2 100644 --- a/ipc/glue/MessageChannel.h +++ b/ipc/glue/MessageChannel.h @@ -81,6 +81,11 @@ class MessageChannel : HasResultCodes // for process links only, not thread links. void CloseWithError(); + void SetAbortOnError(bool abort) + { + mAbortOnError = true; + } + // Asynchronously send a message to the other side of the channel bool Send(Message* aMsg); @@ -623,6 +628,10 @@ class MessageChannel : HasResultCodes #ifdef OS_WIN HANDLE mEvent; #endif + + // Should the channel abort the process from the I/O thread when + // a channel error occurs? + bool mAbortOnError; }; } // namespace ipc From a3a9b7abb1fb817d94b1a74e2e297a02b74a586e Mon Sep 17 00:00:00 2001 From: Mike Conley Date: Tue, 4 Mar 2014 11:48:00 -0500 Subject: [PATCH 061/112] Bug 979034 - [Australis] Make CustomizationTabPreloader kick-off when the user opens the menu panel. r=ttaubert. --- .../customizableui/content/panelUI.js | 4 ++ .../customizableui/src/CustomizeMode.jsm | 5 ++ browser/components/nsBrowserGlue.js | 1 - browser/modules/CustomizationTabPreloader.jsm | 52 +++++-------------- 4 files changed, 21 insertions(+), 41 deletions(-) diff --git a/browser/components/customizableui/content/panelUI.js b/browser/components/customizableui/content/panelUI.js index 3902a34c586..935c740ab58 100644 --- a/browser/components/customizableui/content/panelUI.js +++ b/browser/components/customizableui/content/panelUI.js @@ -154,6 +154,10 @@ const PanelUI = { this.panel.addEventListener("popupshown", function onPopupShown() { this.removeEventListener("popupshown", onPopupShown); + // As an optimization for the customize mode transition, we preload + // about:customizing in the background once the menu panel is first + // shown. + gCustomizationTabPreloader.ensurePreloading(); deferred.resolve(); }); }); diff --git a/browser/components/customizableui/src/CustomizeMode.jsm b/browser/components/customizableui/src/CustomizeMode.jsm index f728543469c..d346b9c230f 100644 --- a/browser/components/customizableui/src/CustomizeMode.jsm +++ b/browser/components/customizableui/src/CustomizeMode.jsm @@ -269,6 +269,11 @@ CustomizeMode.prototype = { panelContents.removeAttribute("customize-transitioning"); CustomizableUI.dispatchToolboxEvent("customizationready", {}, window); + + // It's possible that we didn't enter customize mode via the menu panel, + // meaning we didn't kick off about:customizing preloading. If that's + // the case, let's kick it off for the next time we load this mode. + window.gCustomizationTabPreloader.ensurePreloading(); if (!this._wantToBeInCustomizeMode) { this.exit(); } diff --git a/browser/components/nsBrowserGlue.js b/browser/components/nsBrowserGlue.js index 82b2949ec0c..c299a6e7dc6 100644 --- a/browser/components/nsBrowserGlue.js +++ b/browser/components/nsBrowserGlue.js @@ -472,7 +472,6 @@ BrowserGlue.prototype = { PageThumbs.init(); NewTabUtils.init(); BrowserNewTabPreloader.init(); - CustomizationTabPreloader.init(); SignInToWebsiteUX.init(); PdfJs.init(); #ifdef NIGHTLY_BUILD diff --git a/browser/modules/CustomizationTabPreloader.jsm b/browser/modules/CustomizationTabPreloader.jsm index bc4c9d61021..1ccdaa0d136 100644 --- a/browser/modules/CustomizationTabPreloader.jsm +++ b/browser/modules/CustomizationTabPreloader.jsm @@ -21,12 +21,6 @@ const CUSTOMIZATION_URL = "about:customizing"; // The interval between swapping in a preload docShell and kicking off the // next preload in the background. const PRELOADER_INTERVAL_MS = 600; -// The initial delay before we start preloading our first customization page. The -// timer is started after the first 'browser-delayed-startup' has been sent. -const PRELOADER_INIT_DELAY_MS = 7000; - -const TOPIC_TIMER_CALLBACK = "timer-callback"; -const TOPIC_DELAYED_STARTUP = "browser-delayed-startup-finished"; function createTimer(obj, delay) { let timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer); @@ -42,10 +36,6 @@ function clearTimer(timer) { } this.CustomizationTabPreloader = { - init: function() { - CustomizationTabPreloaderInternal.init(); - }, - uninit: function () { CustomizationTabPreloaderInternal.uninit(); }, @@ -53,28 +43,23 @@ this.CustomizationTabPreloader = { newTab: function (aTab) { return CustomizationTabPreloaderInternal.newTab(aTab); }, + + /** + * ensurePreloading starts the preloading of the about:customizing + * content page. This function is idempotent (until a call to uninit), + * so multiple calls to it are fine. + */ + ensurePreloading: function() { + CustomizationTabPreloaderInternal.ensurePreloading(); + }, }; Object.freeze(CustomizationTabPreloader); this.CustomizationTabPreloaderInternal = { _browser: null, - _timer: null, - _observing: false, - - init: function () { - Services.obs.addObserver(this, TOPIC_DELAYED_STARTUP, false); - this._observing = true; - }, uninit: function () { - this._timer = clearTimer(this._timer); - - if (this._observing) { - Services.obs.removeObserver(this, TOPIC_DELAYED_STARTUP); - this._observing = false; - } - HostFrame.destroy(); if (this._browser) { @@ -92,23 +77,10 @@ this.CustomizationTabPreloaderInternal = { return false; }, - observe: function (aSubject, aTopic, aData) { - if (aTopic == TOPIC_DELAYED_STARTUP) { - Services.obs.removeObserver(this, TOPIC_DELAYED_STARTUP); - this._observing = false; - this._startTimer(); - } else if (aTopic == TOPIC_TIMER_CALLBACK) { - this._timer = null; - this._startPreloader(); + ensurePreloading: function () { + if (!this._browser) { + this._browser = new HiddenBrowser(); } - }, - - _startTimer: function () { - this._timer = createTimer(this, PRELOADER_INIT_DELAY_MS); - }, - - _startPreloader: function () { - this._browser = new HiddenBrowser(); } }; From 77b84a3c278bb065fb585b15228bc8a1c622c16f Mon Sep 17 00:00:00 2001 From: Blake Winton Date: Tue, 4 Mar 2014 07:18:00 -0500 Subject: [PATCH 062/112] Bug 964257 - Close the tab before flipping the deck away from the customize pane. ui-r=phlsa, r=mconley --- .../customizableui/src/CustomizeMode.jsm | 53 +++++++++---------- 1 file changed, 26 insertions(+), 27 deletions(-) diff --git a/browser/components/customizableui/src/CustomizeMode.jsm b/browser/components/customizableui/src/CustomizeMode.jsm index d346b9c230f..2938f366844 100644 --- a/browser/components/customizableui/src/CustomizeMode.jsm +++ b/browser/components/customizableui/src/CustomizeMode.jsm @@ -345,10 +345,34 @@ CustomizeMode.prototype = { yield this._doTransition(false); + let browser = document.getElementById("browser"); + if (this.browser.selectedBrowser.currentURI.spec == kAboutURI) { + let custBrowser = this.browser.selectedBrowser; + if (custBrowser.canGoBack) { + // If there's history to this tab, just go back. + // Note that this throws an exception if the previous document has a + // problematic URL (e.g. about:idontexist) + try { + custBrowser.goBack(); + } catch (ex) { + ERROR(ex); + } + } else { + // If we can't go back, we're removing the about:customization tab. + // We only do this if we're the top window for this window (so not + // a dialog window, for example). + if (window.getTopWin(true) == window) { + let customizationTab = this.browser.selectedTab; + if (this.browser.browsers.length == 1) { + window.BrowserOpenTab(); + } + this.browser.removeTab(customizationTab); + } + } + } + browser.parentNode.selectedPanel = browser; let customizer = document.getElementById("customization-container"); customizer.hidden = true; - let browser = document.getElementById("browser"); - browser.parentNode.selectedPanel = browser; window.gNavToolbox.removeEventListener("toolbarvisibilitychange", this); @@ -403,31 +427,6 @@ CustomizeMode.prototype = { mainView.setAttribute("context", this._mainViewContext); } - if (this.browser.selectedBrowser.currentURI.spec == kAboutURI) { - let custBrowser = this.browser.selectedBrowser; - if (custBrowser.canGoBack) { - // If there's history to this tab, just go back. - // Note that this throws an exception if the previous document has a - // problematic URL (e.g. about:idontexist) - try { - custBrowser.goBack(); - } catch (ex) { - ERROR(ex); - } - } else { - // If we can't go back, we're removing the about:customization tab. - // We only do this if we're the top window for this window (so not - // a dialog window, for example). - if (window.getTopWin(true) == window) { - let customizationTab = this.browser.selectedTab; - if (this.browser.browsers.length == 1) { - window.BrowserOpenTab(); - } - this.browser.removeTab(customizationTab); - } - } - } - if (this.document.documentElement._lightweightTheme) this.document.documentElement._lightweightTheme.enable(); From 2aa48a9683861421132a4af85c3e16fc01488b56 Mon Sep 17 00:00:00 2001 From: Richard Newman Date: Tue, 4 Mar 2014 12:18:26 -0800 Subject: [PATCH 063/112] Bug 961238 - Follow-up: eliminate BrowserContract dependency on DBUtils. r=trivial, DONTBUILD --- mobile/android/base/db/BrowserContract.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/mobile/android/base/db/BrowserContract.java b/mobile/android/base/db/BrowserContract.java index c632aaea6f7..9462473bdeb 100644 --- a/mobile/android/base/db/BrowserContract.java +++ b/mobile/android/base/db/BrowserContract.java @@ -372,12 +372,12 @@ public class BrowserContract { } static final String TABLE_BOOKMARKS_JOIN_IMAGES = Bookmarks.TABLE_NAME + " LEFT OUTER JOIN " + - Obsolete.TABLE_IMAGES + " ON " + DBUtils.qualifyColumn(Bookmarks.TABLE_NAME, Bookmarks.URL) + " = " + - DBUtils.qualifyColumn(Obsolete.TABLE_IMAGES, Obsolete.Images.URL); + Obsolete.TABLE_IMAGES + " ON " + Bookmarks.TABLE_NAME + "." + Bookmarks.URL + " = " + + Obsolete.TABLE_IMAGES + "." + Obsolete.Images.URL; static final String TABLE_HISTORY_JOIN_IMAGES = History.TABLE_NAME + " LEFT OUTER JOIN " + - Obsolete.TABLE_IMAGES + " ON " + DBUtils.qualifyColumn(Bookmarks.TABLE_NAME, History.URL) + " = " + - DBUtils.qualifyColumn(Obsolete.TABLE_IMAGES, Obsolete.Images.URL); + Obsolete.TABLE_IMAGES + " ON " + Bookmarks.TABLE_NAME + "." + History.URL + " = " + + Obsolete.TABLE_IMAGES + "." + Obsolete.Images.URL; static final String FAVICON_DB = "favicon_urls.db"; } From 553b10d067a423efb17338c955e568e2137e4452 Mon Sep 17 00:00:00 2001 From: Brian Nicholson Date: Tue, 4 Mar 2014 12:57:23 -0800 Subject: [PATCH 064/112] Bug 962103 - Make progress bar overlap content. r=lucasr --- mobile/android/base/GeckoApp.java | 5 +++++ .../resources/drawable-hdpi/progress.9.png | Bin 315 -> 811 bytes .../resources/drawable-mdpi/progress.9.png | Bin 255 -> 524 bytes .../resources/drawable-xhdpi/progress.9.png | Bin 440 -> 1044 bytes .../base/resources/layout/browser_toolbar.xml | 3 ++- .../base/resources/layout/gecko_app.xml | 5 ++++- 6 files changed, 11 insertions(+), 2 deletions(-) diff --git a/mobile/android/base/GeckoApp.java b/mobile/android/base/GeckoApp.java index 51e6d801845..341343fa1b2 100644 --- a/mobile/android/base/GeckoApp.java +++ b/mobile/android/base/GeckoApp.java @@ -1305,6 +1305,11 @@ public abstract class GeckoApp mGeckoLayout = (RelativeLayout) findViewById(R.id.gecko_layout); mMainLayout = (RelativeLayout) findViewById(R.id.main_layout); + // Removing the view clipping causes layout issues on < 3.0 (bug 978796). + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) { + mMainLayout.setClipChildren(true); + } + // Determine whether we should restore tabs. mShouldRestore = getSessionRestoreState(savedInstanceState); if (mShouldRestore && savedInstanceState != null) { diff --git a/mobile/android/base/resources/drawable-hdpi/progress.9.png b/mobile/android/base/resources/drawable-hdpi/progress.9.png index f3fe0bdaf5a83b22709ba611985b47d399c9cdde..ae39f6583c7ebdc21b64b8e07f169e8b7f5f1e58 100644 GIT binary patch delta 801 zcmV++1K#|*0;>j)7k?lK1^@s6k8e>v00006VoOIv0RI600RN!9r;`8x010qNS#tmY z3yA;#3yA?Y$;+((000McNliru-U0>}0v{b50l@$O0=P*;K~z}7?Uy@J+&~b9zrRP) zE^q?w!4aHt1Ls`9nH~BH&bh%xzJtq&V}~|=Kfp_|Xf^F%Mt@=uyZA{N$~#q4J<_~> z_2cgr?hfEZzf~>cyM4gMIE_2d?gYrY&^G4YfZTxmomTy|lb$@oclM?EETyoWeF1%E zg)B2&1kilu9PC{=TI((Z7&c@8*IX8|RWw*Ax^O~PL;yEB4|%PCh}2?g5erN$umqy+ zAC+0qFM;&K-GB1ytpL+Mhmq`iHGo;hG>#r{YDAsq8a%%Pkd}xAFbBR6?3kca;7s#b zS7_A7<_=dbWzdEJb?#M`%_ZqR0cxU8i9P`)I1NsX`&Mx-;4SbC_>6c(&}+~Kp!1#m zsG_E*0Q@lz0eE#3KteKvL6%a|m=y9j$@E<1wG~dlsef>J#c=Ec+R3p+E#-60qQ<48XPp&d+ zX|8@=#eWM2I!_)oFr+8buTw_^ta^#~3Y=wM^eZ6sARl+QTNhDWMtHrVH+g=V#|>Sa z(8ejtxJC3WoC+}|dNV{ms`K4T#2nKnOm7MH2I&}B^yI!ylUa zDxBSjm}0hA1fu4%ILhCy8!cb@8lb=J@`o`L6=j|9Yn-w9$Jtco{|uyWH2J@Pl)Ix; ffg0RS{&ClL!BY7Cpr8t`00000NkvXXu0mjfFO_jo delta 301 zcmZ3@wwq~!cs&~jGXn!dri;5ekYY)9^mSxl*x1kgCy^D%XDkkKcVbv~PUa<$6BXbS z;tHhyPZIe*TjKv@(f@NKL5xNg5Cejyh=N3b3R>9yHvrW#{BLCV-^%#EiRphc)Bi5! z|D8<#`&s`_VEf;~^uLGYe@8vjzj}uMO+aMHBnEhrIX9?0x zx-(ZZIu$6B>gnPb!g0O#yeD6S0f$52oaaglwyv%EpBe^8C!kz<~ua7ddYXieK##}God3WizWXo<}0wzKkiOB!}0hvieK~zY`?UYT96EP5lzvuq% zjF3QLG545j z_;$qxX-E>!0rdg-{9Bi51sG{fAHGuR8}J0g z=NLv{d(b+o%6u+?ilCB06@(h8K`BtF!a(2`VolH^@LR*ma5ry@b3N$AQYWn>cGJFf zLJ)R93MtfxGy>B}ANv32eGx!kHAC4((u=UPtv}7pkah$B`1k+-002ovPDHLkV1inn Bb5Ce!BSpGKvWf}iBG5&96`rpRzzk}g_3*-L@Z2$XM z|93F|?_yajH$54sldB}iFPPzd_<#9KPakHfw~pO`oIqg@PZ!4!j_ajoErl8kc$gg; z8y#wn@csF}Rzgc-Q!iJq8-w7ntfVx-z_S6{OV(5~Hoj`VRr$5!g_*wp&-kw0Td(EZ fx|dql_kfLQF7r_)gN*_}GZ{Qx{an^LB{Ts5Kr34~ diff --git a/mobile/android/base/resources/drawable-xhdpi/progress.9.png b/mobile/android/base/resources/drawable-xhdpi/progress.9.png index a37de873f1d150b2b0dbeeb093eddef527e25399..f9cfb79c91e5faf762e0d0140b39700b01da8502 100644 GIT binary patch delta 1036 zcmV+n1oQj21C$7m7k?@U1^@s6_)(}m00006VoOIv0RI600RN!9r;`8x010qNS#tmY z3yA;#3yA?Y$;+((000McNliru-U0>}0v8jL4$J+>~z6>J4t!B(*U?ugIY`@8qqsl0w8 z0PSzQt^+D3Rh{PEY>=+~jq~<;@zr{YfzNu#Jou%7j=xzs^Y6)xtI!3~jfB{J5 zbnR~vzzm@4(tiw}b$(vAs#G)cbv>3c;4ZwtBo8Dvq*(e02qSriyFhVzt&|W)P!HSz zCxY%U4ZsOV+TWxG&g0B1w*Z>ilh(|3m{GwBn3dm+%nv?VNyn2WTp@G6Qe~ zKLH{5Yy=3^y{>9E)*qJcTYnOPlr}h#c zkU_m8v6&RiLm6;ViD@^O?hzf%4#yE)QT61n-=Ipp2;kq98$bQBpy`5*k>=Z|x$r4x zFLtfjx_|91ZFjWFbAug-;RnK(-x6(u>9({!6lEV_?)}o&1Fvk5U+zO*bXUHvC&E<0 zX}OQSzoO@Bl7E4-tyazx`!RoTF|T+i7JLG*$`q-XpsIZMb*4;?Af*VrLR^*c$GIi- z|3x0-@*P#Wq}H+>(DOtd`b0lJ09NlOKL<;dVt-33!-4w&hS(z=vJ03Twm%+h$#~2f z3@sZE2ZnJ;wSkmZuovKl&=c)PR2+5oV`)(_eUrN^eysLW@e|E_TfZu0Hv2=`GI*d* zuSg!t<~PI!h$P?OKDr45bu|uR4;%>gJK~mLzhc^zNaQ#N7cU5(st1NjZmXh#vF-(| zHh*_x-H;MSz%;fSrU?-dQ&%F745l-KFd*#_2c$odb{HQJAB$>3i5nfR7s0$*w=}*% zm9Ys;DAmS{p;BB(ITn;6B4Ff@Npwh7qK^Px6j!L;l`!r=17e3yfTyBXKNsnrfmLY* z4OqJ~`UZ3^ru;h;6NZ)chLMOkR)XCOqJJs)9l^%;IpT;k0C$K}amalm!V{$}W6JXO z8s5FH1L%KpC&qn(AqkTqL@?!aWt^bKGUc?zD`PQQ!nBZ=xt`TmRcX*nlKI#~lSd?* zFY%9-^-J&ywt}r-{}Rks#a6Ht?D-OOcSq8T+Gp;rzW^gJak-0#X666@002ovP6b4+ GLSTYGHrgrx literal 440 zcmeAS@N?(olHy`uVBq!ia0vp^W!1~Qr?0_8TafD}v-{olg=zmerXP`r`(|76ks zKyi>D8%VYRXc)u)M#lfmO#fRM|93I}Z({sEf$e__)Bi?>|Lu(bo0$LiF#qph`rpFx zzmw^I1M~l8mjC^%|NB@$=Jc}u?`Cd2I(Z+^6v>hxzhDM$ITsNLRz?<;Bt@a`HvZRs zNBoZd9dyUO{{?RjP|-q97sn8Z%X2S0=W8+$X?w_JQSdNq*Mcomc)!<|&l58+Jm^w8 z>0iy{%lwKw7v3L=b6TUZ$e}|=+uL>4GL4Q!AqRy^$~nHBE8FVAv47J>xgw`SEnI9% z&h4DK`SHoS6}4@LGu0+V70=riniFEW{Pj%x_?n4N_hi4WQ2Jey!eZ_fye#ba&99Gs z-TQriQljAQ&bcmvGnkKUuxEKxv)^`(;o*7*|Dq#m-ifbbI6wj8>FVdQ&MBb@0FX<) A!T + android:background="@android:color/transparent" + android:clipChildren="false"> Date: Tue, 4 Mar 2014 13:00:00 -0800 Subject: [PATCH 065/112] Bug 976006 - Update bookmark star when page is saved. r=wesj --- mobile/android/base/BrowserApp.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/mobile/android/base/BrowserApp.java b/mobile/android/base/BrowserApp.java index 17a1f279686..deb79dbf230 100644 --- a/mobile/android/base/BrowserApp.java +++ b/mobile/android/base/BrowserApp.java @@ -2136,6 +2136,11 @@ abstract public class BrowserApp extends GeckoApp } save.setVisible(!GeckoProfile.get(this).inGuestMode()); + if (tab.isBookmark() || tab.isReadingListItem()) { + save.setIcon(R.drawable.ic_menu_bookmark_remove); + } else { + save.setIcon(R.drawable.ic_menu_bookmark_add); + } bookmark.setEnabled(!AboutPages.isAboutReader(tab.getURL())); bookmark.setChecked(tab.isBookmark()); From 82d7f013eb8823eb43262198af130e74208eea4b Mon Sep 17 00:00:00 2001 From: Victor Porof Date: Tue, 4 Mar 2014 16:25:19 -0500 Subject: [PATCH 066/112] Bug 973303 - Intermittent browser_net_statistics-01.js | Two real pie chart appear to be rendered correctly. - Got 0, expected 2, r=me --- .../test/browser_net_statistics-01.js | 25 +++++++++++++++---- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/browser/devtools/netmonitor/test/browser_net_statistics-01.js b/browser/devtools/netmonitor/test/browser_net_statistics-01.js index 2c7da1cc8d8..f73b6a2a494 100644 --- a/browser/devtools/netmonitor/test/browser_net_statistics-01.js +++ b/browser/devtools/netmonitor/test/browser_net_statistics-01.js @@ -40,12 +40,15 @@ function test() { is($("#empty-cache-chart").childNodes.length, 1, "There should be a real empty cache chart created now."); - is($all(".pie-chart-container:not([placeholder=true])").length, 2, - "Two real pie chart appear to be rendered correctly."); - is($all(".table-chart-container:not([placeholder=true])").length, 2, - "Two real table chart appear to be rendered correctly."); + Task.spawn(function*() { + yield until(() => $all(".pie-chart-container:not([placeholder=true])").length == 2); + ok(true, "Two real pie charts appear to be rendered correctly."); - teardown(aMonitor).then(finish); + yield until(() => $all(".table-chart-container:not([placeholder=true])").length == 2); + ok(true, "Two real table charts appear to be rendered correctly.") + + teardown(aMonitor).then(finish); + }); }); }); @@ -55,3 +58,15 @@ function test() { "The current frontend mode is correct."); }); } + +function waitForTick() { + let deferred = promise.defer(); + executeSoon(deferred.resolve); + return deferred.promise; +} + +function until(predicate) { + return Task.spawn(function*() { + while (!predicate()) yield waitForTick(); + }); +} From c0d6b525dce8fd4ca9e6ecb34e75056b186e0bea Mon Sep 17 00:00:00 2001 From: Brian Grinstead Date: Tue, 4 Mar 2014 15:25:51 -0600 Subject: [PATCH 067/112] Bug 968315 - [markup view] Current / hovered node highlighting colors need to be higher contrast;r=jwalker --- browser/themes/linux/jar.mn | 3 +- browser/themes/osx/jar.mn | 3 +- browser/themes/shared/devtools/controls.png | Bin 668 -> 0 bytes browser/themes/shared/devtools/dark-theme.css | 75 +++++++++------- .../shared/devtools/images/controls.png | Bin 0 -> 1630 bytes .../shared/devtools/images/controls@2x.png | Bin 0 -> 2045 bytes .../themes/shared/devtools/light-theme.css | 85 +++++++++++------- .../themes/shared/devtools/markup-view.css | 19 ++++ browser/themes/windows/jar.mn | 6 +- 9 files changed, 121 insertions(+), 70 deletions(-) delete mode 100644 browser/themes/shared/devtools/controls.png create mode 100644 browser/themes/shared/devtools/images/controls.png create mode 100644 browser/themes/shared/devtools/images/controls@2x.png diff --git a/browser/themes/linux/jar.mn b/browser/themes/linux/jar.mn index 0ca5f412119..c34e129263b 100644 --- a/browser/themes/linux/jar.mn +++ b/browser/themes/linux/jar.mn @@ -160,7 +160,8 @@ browser.jar: * skin/classic/browser/devtools/dark-theme.css (../shared/devtools/dark-theme.css) * skin/classic/browser/devtools/light-theme.css (../shared/devtools/light-theme.css) skin/classic/browser/devtools/filters.svg (../shared/devtools/filters.svg) - skin/classic/browser/devtools/controls.png (../shared/devtools/controls.png) + skin/classic/browser/devtools/controls.png (../shared/devtools/images/controls.png) + skin/classic/browser/devtools/controls@2x.png (../shared/devtools/images/controls@2x.png) * skin/classic/browser/devtools/widgets.css (devtools/widgets.css) skin/classic/browser/devtools/commandline-icon.png (devtools/commandline-icon.png) skin/classic/browser/devtools/command-paintflashing.png (../shared/devtools/images/command-paintflashing.png) diff --git a/browser/themes/osx/jar.mn b/browser/themes/osx/jar.mn index b6c1f008ea1..1566895454f 100644 --- a/browser/themes/osx/jar.mn +++ b/browser/themes/osx/jar.mn @@ -273,7 +273,8 @@ browser.jar: * skin/classic/browser/devtools/dark-theme.css (../shared/devtools/dark-theme.css) * skin/classic/browser/devtools/light-theme.css (../shared/devtools/light-theme.css) skin/classic/browser/devtools/filters.svg (../shared/devtools/filters.svg) - skin/classic/browser/devtools/controls.png (../shared/devtools/controls.png) + skin/classic/browser/devtools/controls.png (../shared/devtools/images/controls.png) + skin/classic/browser/devtools/controls@2x.png (../shared/devtools/images/controls@2x.png) * skin/classic/browser/devtools/widgets.css (devtools/widgets.css) skin/classic/browser/devtools/commandline-icon.png (devtools/commandline-icon.png) skin/classic/browser/devtools/command-paintflashing.png (../shared/devtools/images/command-paintflashing.png) diff --git a/browser/themes/shared/devtools/controls.png b/browser/themes/shared/devtools/controls.png deleted file mode 100644 index ebba41cd794c88fb0b4c1795bed6525d85061bd5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 668 zcmV;N0%QG&P)65K_W`j&iDsZ8YP&}!B5a!DRx%= z0WCmVT6z*HNPvchn!g~4k;IOK(!|7yyU$`7GPgIox3fD#%)RB@e*5fm^WE&s$;_DM z^Z+Dn#1xs?MwdDus?NJUx~><1*QPAhwvOfx+o^7*;l-^YX;IRqqz5@UUKW8(;D(n? zP|{uC3$O}2$;I*F^B%jwB!ZHbByCB$;|+fVo&q~&_A>>?%M!2!1bM)@8%#BWZ-5ox z6M&=_K>r%FlZa8t11fnv(qtQW3A~eZ27Ca9z&A6yO2i2A0H6027~v(E!E1@nz#od$ z>lt}k(f(NyaM*j>{kq_gWM1}0DeT)1?8Y#(8-M* zLF&>%&b8J4IJxhUb+vL3793E_T-0H;qudc0w1kuPS(hk!PFs)5JfP(4GmkFEBy?0000CD=sHs6(u7SBt;PMupB26FapQq6iN^pQl%l3@brU- z-dr}j#-vZ5_9aSMq(Bgy8Vqy0-7#NFPOl;G@h!> zo4rnenE=lfyR2e8>`Mb+F?Y{)Z6<>?9#q z+DX)c6H1g+Dk+p!6AF~DSS(7MCKPt1Enw$qcwDVlQ+l511-_uytGqIXf7oY{sW#+h|Ko{f`a015{a85Wi6^_fKt&GDj zukzREamae$VoHE5-Nmu+RFXB!QwRXkM&l}#4OPk&6iUi1c9g;aj*=>?B0*`ls(}h1 z(|FteO&%ta!u*}`pUw#!iS6j$KA8hicrr=AA&!qroD=VFz7YtLlo|Cpv*%mO z@0l8tqEr&%cG5BL@Q*j@hENn$y!QLg#XHCDAD;h0VrOK#B4ub+d%bz=`=;Cz*E2FQ zN_Reb*c~484q;9280g#&Vxptxo@{EmQ-3!9y6=))3B)Ux$6jd}CtzwS>?{2Ft#rsm<-H*YG>ojEgkye#yDq%Ah8Tr%<^oE6f)E9G`b zd))ZOQwNX zaBxKR3b`j}FCi^5RyP~xNQ+o@c4tS2ti(kw=84qV9yY;e#wB7D@q_{@xHsd^z`(Nu>FIEMUBV1<3Ii4{TWeoD|;~Uem^rzRp^7=mrRaRmE literal 0 HcmV?d00001 diff --git a/browser/themes/shared/devtools/images/controls@2x.png b/browser/themes/shared/devtools/images/controls@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..fb062516db8e49e90b5081f63bd7881ebfc5df65 GIT binary patch literal 2045 zcmbVNdsGu=7Ej6}$g5}piB>y=qGHKoLLMZNN|G@OC4vyzv@2*PnLH%Pgk*q#h#F%d zwt}k#3RVO~k%w@wP@zaUt*mTaSa4CRa-^a{vC5Hp5T$Z#CkpQV;prbc=gfTfe&6r@ z?)~oLj3Z&=dLPdvo&*BHCuRebh_5F6jr4HGzoGYYWATNIt&?L(s2a;sm=S_dg~A9B zV^C<2L`0#=PX7^!A`o0GI++}kOXK)T)Id`>F*K{eNkt$;t+kpI$}|K6U__%c3Mdad zx+s87C7^u7mNKL!F{0IN$T1^HIU8lloHQj*MOphk5M|}#1O^0C09J$EXyIE0loz~w zTy}2LDZmQ|mL{OQ3`#Cd0K}*n0oXJ)Rmot20GCGt*(@Fih679n7(oXabS94qf_xU2 z4|0IHhk|=EtJM5NNHXUO*8~(ThMD+udRA5zEh~bCnl*Hg$K%l%OgfWE#Sv6Xwh>cU zsYXl4JOhMSlxCd?)1gMd$*6$Q3`{`5BYk-VgGnlVMQpUpB??a&-KsFrK^lW@FgWk^ z0&T$(k^hGATC_!$Z9?dYhy~3sEAe`$L*|X~-2Js9ClHT@A8*#-MN#M>RGDEwj93gL zpx`Gol}^P+)GUz6QM0Hp1LROy91f4Fhy>YG5Qbq6LjkhY9MwF}>+BhkP$UnEWbs50 z8wA%y@IY3i7-B#yp->2}<3-Hd#uzP_!l*>%ed}=FbG8wGY0DRz5e0^tWhknj?}7v^ zilG)QY68S!V3ky%)ES+6n6pMNuM8n(T_&QEm{9}pBFTK+YXX2lE|05(nN$vg$)&Pj zCY!2Ib3iJ{fg{vB1dfCe4rR_>_5UW1jt50|cFO;B&ioeMj!yB_9N@~UNkWYH_?YoI zSqym(5eTk83?!6UZ#+0G(E1Dgdo)E}j`eV~)IaInZ3?|V9J~Pzh5zoqZ?Eem$^I=w zukS_Rky;t#7DCzgPQiYW$EmFg0|pnwRN0;;YoTKYgC334{<5A&}`p{7O&9e06 zvtP%ZDQj>4x%coBwdTlXT2I5hG~IJ$%;SCXCC{Q}J`KGzd^wI&GR;g5Xg*sScySqG zZ2CF5u%q)k=GmW$q3vP!?cSy;VhFb`!~Rv+sIln-^Y$Gv-)J zT^uK1KQ!&s^{qMUdn5Kp{oY2hd(o4LpvNePU8^Qv^PcdRjOCuc)hg21pI<4vD_UB$ z!$z9%NU`UU-#~pZa$V)4547AblF3_rT1eX#v^6dN_0zFUGixy4@(NLiwqAU+Mc0+Flptk#>yvWL3xb&f@qGb>;np zjX}*+T72_S_3E>0TO{WORnj{Zw+jZkGE3hZO}iOT)!$Xy)t_(G1`JiX2i3>Lm(=wGUB?H`!>g02Z=Q2GZ42~hobnpo?$$vPTw#6t zU^ge)$F)eD8$Xl!eU5I~W%J4l|0*_S?!WzPNe$`H^2VtHlUd)nSG<{2wJ*DJs5nr6 zZPbRf3XkSR?JCSa9d`w)==cvRnhC%hw#9EX^G@vqclc~%PpCG;Ek9s@(n7 z`!(k={B8x7tR+s{N4X{YEmh=i8{NAlF2umXhpo-CI>PavqLYG|DZwR+y5$Asr+4T1 zm3_`$__*O8h^~9v$;zImQ6D?}%BtDvAuUnxvf1pBl<9~1+Amn5t8op764p!P^~r}F zJ_oPfD>vWW%>*7P$2Mtviw^VzWYoB%My#y<%_F;Evm;klaA#p~$(l}wXL>lLn>V=h z<2B&h@Csr<`shhR_>E`zCq&-8QiRwWYucj-E{sk$gufI6TbmCYbVWBLy2``5+eUtr z_xunYp7YVF&;=E}1d0c|X!63lSIMs6<&xA`&?@xH$Y1OVPUY!ih1NVj>F!@h&DDKV zEypIIf+G2Iw||E1x#jSi`HWWF&^>tlUiC;o`l(ony`B;kw$K=RsjSo Date: Tue, 4 Mar 2014 22:58:51 +0100 Subject: [PATCH 068/112] Bug 976544 - Intermittent | browser_get_user_media.js | Unexpected Exception: TypeError: PopupNotifications.panel.firstChild is null - second attempt, r=Gijs. --- .../test/general/browser_get_user_media.js | 34 +++++++++++++------ 1 file changed, 24 insertions(+), 10 deletions(-) diff --git a/browser/base/content/test/general/browser_get_user_media.js b/browser/base/content/test/general/browser_get_user_media.js index 334167b70d3..7a7e2cbca7b 100644 --- a/browser/base/content/test/general/browser_get_user_media.js +++ b/browser/base/content/test/general/browser_get_user_media.js @@ -81,17 +81,31 @@ function promiseMessage(aMessage, aAction) { function promisePopupNotification(aName, aShown) { let deferred = Promise.defer(); - // If aShown is true, the notification is expected to be opened by - // default and we wait for the panel to be populated; for dismissed - // notifications, we are happy as soon as we find the icon. - waitForCondition(() => PopupNotifications.getNotification(aName) && - (!aShown || PopupNotifications.panel.firstChild), + waitForCondition(() => PopupNotifications.getNotification(aName), () => { - ok(!!PopupNotifications.getNotification(aName), - aName + " notification appeared"); - if (aShown) - ok(PopupNotifications.panel.firstChild, "notification panel populated"); - deferred.resolve(); + let notification = PopupNotifications.getNotification(aName); + ok(!!notification, aName + " notification appeared"); + + if (!notification || !aShown) { + deferred.resolve(); + return; + } + + // If aShown is true, the notification is expected to be opened by + // default, so we check that the panel has been populated. + if (PopupNotifications.panel.firstChild) { + ok(true, "notification panel populated"); + deferred.resolve(); + } + else { + todo(false, "We shouldn't have to force re-open the panel, see bug 976544"); + notification.reshow(); + waitForCondition(() => PopupNotifications.panel.firstChild, + () => { + ok(PopupNotifications.panel.firstChild, "notification panel populated"); + deferred.resolve(); + }, "timeout waiting for notification to be reshown"); + } }, "timeout waiting for popup notification " + aName); return deferred.promise; From 749004af538adea3cf9d533261a5dfd8b2f7ede6 Mon Sep 17 00:00:00 2001 From: Gijs Kruitbosch Date: Tue, 4 Mar 2014 17:10:40 -0500 Subject: [PATCH 069/112] Bug 886573 - make zoom controls display the right thing in Australis even in customize mode, r=jaws --- .../src/CustomizableWidgets.jsm | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/browser/components/customizableui/src/CustomizableWidgets.jsm b/browser/components/customizableui/src/CustomizableWidgets.jsm index 0ae0cc6af01..9a35add5a92 100644 --- a/browser/components/customizableui/src/CustomizableWidgets.jsm +++ b/browser/components/customizableui/src/CustomizableWidgets.jsm @@ -416,6 +416,11 @@ const CustomizableWidgets = [{ let zoomResetButton = node.childNodes[2]; let window = aDocument.defaultView; function updateZoomResetButton() { + let updateDisplay = true; + // Label should always show 100% in customize mode, so don't update: + if (aDocument.documentElement.hasAttribute("customizing")) { + updateDisplay = false; + } //XXXgijs in some tests we get called very early, and there's no docShell on the // tabbrowser. This breaks the zoom toolkit code (see bug 897410). Don't let that happen: let zoomFactor = 100; @@ -423,7 +428,7 @@ const CustomizableWidgets = [{ zoomFactor = Math.floor(window.ZoomManager.zoom * 100); } catch (e) {} zoomResetButton.setAttribute("label", CustomizableUI.getLocalizedProperty( - buttons[1], "label", [zoomFactor] + buttons[1], "label", [updateDisplay ? zoomFactor : 100] )); }; @@ -508,6 +513,18 @@ const CustomizableWidgets = [{ container.removeEventListener("TabSelect", updateZoomResetButton); }.bind(this), + onCustomizeStart: function(aWindow) { + if (aWindow.document == aDocument) { + updateZoomResetButton(); + } + }, + + onCustomizeEnd: function(aWindow) { + if (aWindow.document == aDocument) { + updateZoomResetButton(); + } + }, + onWidgetDrag: function(aWidgetId, aArea) { if (aWidgetId != this.id) return; From 4f700c0a6a813c67a760359e468182c55e396e1b Mon Sep 17 00:00:00 2001 From: Gijs Kruitbosch Date: Tue, 4 Mar 2014 17:10:45 -0500 Subject: [PATCH 070/112] Bug 979053 - fade in navbar and placeholder outlines when opening Australis customize mode, r=MattN --- .../components/customizableui/src/CustomizeMode.jsm | 12 ++++++++++++ .../shared/customizableui/customizeMode.inc.css | 9 +++++++-- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/browser/components/customizableui/src/CustomizeMode.jsm b/browser/components/customizableui/src/CustomizeMode.jsm index 2938f366844..4e9c317715f 100644 --- a/browser/components/customizableui/src/CustomizeMode.jsm +++ b/browser/components/customizableui/src/CustomizeMode.jsm @@ -269,6 +269,11 @@ CustomizeMode.prototype = { panelContents.removeAttribute("customize-transitioning"); CustomizableUI.dispatchToolboxEvent("customizationready", {}, window); + this._enableOutlinesTimeout = window.setTimeout(() => { + this.document.getElementById("nav-bar").setAttribute("showoutline", "true"); + this.panelUIContents.setAttribute("showoutline", "true"); + delete this._enableOutlinesTimeout; + }, 0); // It's possible that we didn't enter customize mode via the menu panel, // meaning we didn't kick off about:customizing preloading. If that's @@ -307,6 +312,13 @@ CustomizeMode.prototype = { this._handler.isExitingCustomizeMode = true; + if (this._enableOutlinesTimeout) { + this.window.clearTimeout(this._enableOutlinesTimeout); + } else { + this.document.getElementById("nav-bar").removeAttribute("showoutline"); + this.panelUIContents.removeAttribute("showoutline"); + } + this._removeExtraToolbarsIfEmpty(); CustomizableUI.removeListener(this); diff --git a/browser/themes/shared/customizableui/customizeMode.inc.css b/browser/themes/shared/customizableui/customizeMode.inc.css index ee5a04141d8..7584a36469c 100644 --- a/browser/themes/shared/customizableui/customizeMode.inc.css +++ b/browser/themes/shared/customizableui/customizeMode.inc.css @@ -56,11 +56,16 @@ #main-window[customize-entered] .customization-target:not(#PanelUI-contents):hover::before, #main-window[customize-entered] .customization-target[customizing-dragovertarget]:not(#PanelUI-contents)::before, /* nav-bar and panel outlines are always shown */ -#main-window[customize-entered] #nav-bar-customization-target.customization-target::before { +#nav-bar[showoutline=true] > #nav-bar-customization-target.customization-target::before { outline-color: rgb(102,102,102); } -#main-window[customize-entered] .panel-customization-placeholder { +#nav-bar[showoutline=true] > #nav-bar-customization-target.customization-target::before { + transition: outline-color 250ms linear; +} + +#PanelUI-contents[showoutline=true] > .panel-customization-placeholder { + transition: outline-color 250ms linear; outline-color: #bbb; } From 8dc8286603941c403bc424e69f76138b6158a07e Mon Sep 17 00:00:00 2001 From: Blake Winton Date: Tue, 4 Mar 2014 08:00:00 -0500 Subject: [PATCH 071/112] Bug 964262 - Fade in icons in customization mode. ui-r=phlsa, r=Gijs --- browser/components/customizableui/src/CustomizeMode.jsm | 8 ++++++++ .../themes/shared/customizableui/customizeMode.inc.css | 9 +++++++++ 2 files changed, 17 insertions(+) diff --git a/browser/components/customizableui/src/CustomizeMode.jsm b/browser/components/customizableui/src/CustomizeMode.jsm index 4e9c317715f..8b5a1079277 100644 --- a/browser/components/customizableui/src/CustomizeMode.jsm +++ b/browser/components/customizableui/src/CustomizeMode.jsm @@ -195,6 +195,7 @@ CustomizeMode.prototype = { // Hide the palette before starting the transition for increased perf. this.visiblePalette.hidden = true; + this.visiblePalette.removeAttribute("showing"); // Disable the button-text fade-out mask // during the transition for increased perf. @@ -262,6 +263,12 @@ CustomizeMode.prototype = { // Show the palette now that the transition has finished. this.visiblePalette.hidden = false; + window.setTimeout(() => { + // Force layout reflow to ensure the animation runs, + // and make it async so it doesn't affect the timing. + this.visiblePalette.clientTop; + this.visiblePalette.setAttribute("showing", "true"); + }, 0); this.paletteSpacer.hidden = true; this._updateEmptyPaletteNotice(); @@ -338,6 +345,7 @@ CustomizeMode.prototype = { // Hide the palette before starting the transition for increased perf. this.paletteSpacer.hidden = false; this.visiblePalette.hidden = true; + this.visiblePalette.removeAttribute("showing"); this.paletteEmptyNotice.hidden = true; // Disable the button-text fade-out mask diff --git a/browser/themes/shared/customizableui/customizeMode.inc.css b/browser/themes/shared/customizableui/customizeMode.inc.css index 7584a36469c..b7ee75d5970 100644 --- a/browser/themes/shared/customizableui/customizeMode.inc.css +++ b/browser/themes/shared/customizableui/customizeMode.inc.css @@ -176,6 +176,15 @@ toolbarpaletteitem[place="panel"] { transition: transform .3s ease-in-out; } +#customization-palette { + transition: opacity .3s ease-in-out; + opacity: 0; +} + +#customization-palette[showing="true"] { + opacity: 1; +} + toolbarpaletteitem[notransition].panel-customization-placeholder, toolbarpaletteitem[notransition][place="toolbar"], toolbarpaletteitem[notransition][place="palette"], From 8ddc0d63bd8c7550cbe33beffd259f2fd7a53011 Mon Sep 17 00:00:00 2001 From: Jared Wein Date: Tue, 4 Mar 2014 17:26:49 -0500 Subject: [PATCH 072/112] Bug 940133 - Australis: Invert icons in the tabstrip and menubar on Windows Classic. r=MattN --- browser/themes/shared/browser.inc | 1 + browser/themes/windows/browser-aero.css | 1 - browser/themes/windows/browser.css | 12 ++++++++++++ 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/browser/themes/shared/browser.inc b/browser/themes/shared/browser.inc index ecb77a83db8..ecb51c76a0d 100644 --- a/browser/themes/shared/browser.inc +++ b/browser/themes/shared/browser.inc @@ -2,3 +2,4 @@ %define primaryToolbarButtons #back-button, #forward-button, #home-button, #print-button, #downloads-button, #bookmarks-menu-button, #new-tab-button, #new-window-button, #cut-button, #copy-button, #paste-button, #fullscreen-button, #zoom-out-button, #zoom-reset-button, #zoom-in-button, #sync-button, #feed-button, #tabview-button, #webrtc-status-button, #social-share-button, #open-file-button, #find-button, #developer-button, #preferences-button, #privatebrowsing-button, #save-page-button, #switch-to-metro-button, #add-ons-button, #history-panelmenu, #nav-bar-overflow-button, #PanelUI-menu-button, #characterencoding-button, #email-link-button %define inAnyPanel :-moz-any(:not([cui-areatype="toolbar"]),.overflowedItem) +%define nestedButtons #zoom-out-button, #zoom-in-button, #cut-button, #copy-button, #paste-button diff --git a/browser/themes/windows/browser-aero.css b/browser/themes/windows/browser-aero.css index 1464cd54601..b721ff099cc 100644 --- a/browser/themes/windows/browser-aero.css +++ b/browser/themes/windows/browser-aero.css @@ -8,7 +8,6 @@ %define glassActiveBorderColor rgb(37, 44, 51) %define glassInactiveBorderColor rgb(102, 102, 102) -%define nestedButtons #zoom-out-button, #zoom-in-button, #cut-button, #copy-button, #paste-button %include downloads/indicator-aero.css diff --git a/browser/themes/windows/browser.css b/browser/themes/windows/browser.css index f91ce570399..3c9cc88ffcd 100644 --- a/browser/themes/windows/browser.css +++ b/browser/themes/windows/browser.css @@ -801,6 +801,12 @@ toolbarbutton[sdk-button="true"][cui-areatype="toolbar"] > .toolbarbutton-icon { } %endif +#main-window[tabsintitlebar]:not([inFullscreen]) :-moz-any(#TabsToolbar, #toolbar-menubar) > #bookmarks-menu-button > .toolbarbutton-menubutton-dropmarker > .dropmarker-icon:-moz-system-metric(windows-classic):not(:-moz-lwtheme), +#main-window[tabsintitlebar]:not([inFullscreen]) :-moz-any(#TabsToolbar, #toolbar-menubar) > toolbarpaletteitem > #bookmarks-menu-button > .toolbarbutton-menubutton-dropmarker > .dropmarker-icon:-moz-system-metric(windows-classic):not(:-moz-lwtheme), +#main-window[tabsintitlebar]:not([inFullscreen]) :-moz-any(#TabsToolbar, #toolbar-menubar) > toolbarpaletteitem > toolbaritem > :-moz-any(@nestedButtons@):-moz-system-metric(windows-classic):not(:-moz-lwtheme), +#main-window[tabsintitlebar]:not([inFullscreen]) :-moz-any(#TabsToolbar, #toolbar-menubar) > toolbaritem > :-moz-any(@nestedButtons@):-moz-system-metric(windows-classic):not(:-moz-lwtheme), +#main-window[tabsintitlebar]:not([inFullscreen]) :-moz-any(#TabsToolbar, #toolbar-menubar) > toolbarpaletteitem > :-moz-any(@primaryToolbarButtons@):-moz-system-metric(windows-classic):not(:-moz-lwtheme), +#main-window[tabsintitlebar]:not([inFullscreen]) :-moz-any(#TabsToolbar, #toolbar-menubar) > :-moz-any(@primaryToolbarButtons@):-moz-system-metric(windows-classic):not(:-moz-lwtheme), #home-button.bookmark-item:-moz-lwtheme-brighttext { list-style-image: url("chrome://browser/skin/Toolbar-inverted.png"); } @@ -1640,6 +1646,8 @@ toolbarbutton[type="socialmark"] > .toolbarbutton-icon { background-origin: border-box; } +#main-window[tabsintitlebar]:not([inFullscreen]) .tabbrowser-arrowscrollbox > .scrollbutton-up:-moz-system-metric(windows-classic):not(:-moz-lwtheme), +#main-window[tabsintitlebar]:not([inFullscreen]) .tabbrowser-arrowscrollbox > .scrollbutton-down:-moz-system-metric(windows-classic):not(:-moz-lwtheme), .tabbrowser-arrowscrollbox > .scrollbutton-up:-moz-lwtheme-brighttext, .tabbrowser-arrowscrollbox > .scrollbutton-down:-moz-lwtheme-brighttext { list-style-image: url(chrome://browser/skin/tabbrowser/tab-arrow-left-inverted.png); @@ -1683,6 +1691,9 @@ toolbarbutton[type="socialmark"] > .toolbarbutton-icon { -moz-image-region: auto; } +#main-window[tabsintitlebar]:not([inFullscreen]) .tabs-newtab-button:-moz-system-metric(windows-classic):not(:-moz-lwtheme), +#main-window[tabsintitlebar]:not([inFullscreen]) #TabsToolbar > #new-tab-button:-moz-system-metric(windows-classic):not(:-moz-lwtheme), +#main-window[tabsintitlebar]:not([inFullscreen]) #TabsToolbar > toolbarpaletteitem > #new-tab-button:-moz-system-metric(windows-classic):not(:-moz-lwtheme), .tabs-newtab-button:-moz-lwtheme-brighttext, #TabsToolbar > #new-tab-button:-moz-lwtheme-brighttext, #TabsToolbar > toolbarpaletteitem > #new-tab-button:-moz-lwtheme-brighttext { @@ -1697,6 +1708,7 @@ toolbarbutton[type="socialmark"] > .toolbarbutton-icon { list-style-image: url("chrome://browser/skin/toolbarbutton-dropdown-arrow.png"); } +#main-window[tabsintitlebar]:not([inFullscreen]) #alltabs-button:-moz-system-metric(windows-classic):not(:-moz-lwtheme), #alltabs-button:-moz-lwtheme-brighttext { list-style-image: url("chrome://browser/skin/toolbarbutton-dropdown-arrow-inverted.png"); } From d588cdd055e695784fd1e5b45cbd41b9dfdbb9c0 Mon Sep 17 00:00:00 2001 From: Richard Newman Date: Tue, 4 Mar 2014 14:38:11 -0800 Subject: [PATCH 073/112] Bug 966143 - Don't attempt to process a malformed password record. r=nalexander --- .../android/PasswordsRepositorySession.java | 7 +++++++ .../repositories/domain/PasswordRecord.java | 21 +++++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/mobile/android/base/sync/repositories/android/PasswordsRepositorySession.java b/mobile/android/base/sync/repositories/android/PasswordsRepositorySession.java index d40e5e387b8..e7f41a453a1 100644 --- a/mobile/android/base/sync/repositories/android/PasswordsRepositorySession.java +++ b/mobile/android/base/sync/repositories/android/PasswordsRepositorySession.java @@ -327,6 +327,13 @@ public class PasswordsRepositorySession extends } // End deletion logic. + // Validate the incoming record. + if (!remoteRecord.isValid()) { + Logger.warn(LOG_TAG, "Incoming record is invalid. Reporting store failed."); + delegate.onRecordStoreFailed(new RuntimeException("Can't store invalid password record."), record.guid); + return; + } + // Now we're processing a non-deleted incoming record. if (existingRecord == null) { trace("Looking up match for record " + remoteRecord.guid); diff --git a/mobile/android/base/sync/repositories/domain/PasswordRecord.java b/mobile/android/base/sync/repositories/domain/PasswordRecord.java index 6eecb79581c..4a0d32be2f3 100644 --- a/mobile/android/base/sync/repositories/domain/PasswordRecord.java +++ b/mobile/android/base/sync/repositories/domain/PasswordRecord.java @@ -181,4 +181,25 @@ public class PasswordRecord extends Record { + "timePasswordChanged: " + this.timePasswordChanged + ", " + "timesUsed: " + this.timesUsed; } + + /** + * A PasswordRecord is considered valid if it abides by the database + * constraints of the PasswordsProvider (moz_logins). + * + * See toolkit/components/passwordmgr/storage-mozStorage.js for the + * definitions: + * + * http://hg.mozilla.org/mozilla-central/file/00955d61cc94/toolkit/components/passwordmgr/storage-mozStorage.js#l98 + */ + public boolean isValid() { + if (this.deleted) { + return true; + } + + return this.hostname != null && + this.encryptedUsername != null && + this.encryptedPassword != null && + this.usernameField != null && + this.passwordField != null; + } } From 95576befed6c1eb0944cce353dcec8a37210d67e Mon Sep 17 00:00:00 2001 From: Matt Brubeck Date: Tue, 4 Mar 2014 16:58:33 -0800 Subject: [PATCH 074/112] Bug 972844 - Add a Maybe Later link on about:feedback intro [r=mfinkle] --- mobile/android/chrome/content/aboutFeedback.js | 6 +++--- mobile/android/chrome/content/aboutFeedback.xhtml | 3 ++- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/mobile/android/chrome/content/aboutFeedback.js b/mobile/android/chrome/content/aboutFeedback.js index 564eb47758c..ae1c59703ad 100644 --- a/mobile/android/chrome/content/aboutFeedback.js +++ b/mobile/android/chrome/content/aboutFeedback.js @@ -32,9 +32,9 @@ function init() { document.getElementById("open-play-store").addEventListener("click", openPlayStore, false); document.forms[0].addEventListener("submit", sendFeedback, false); - document.getElementById("no-thanks").addEventListener("click", function(evt) { - window.close(); - }, false); + for (let anchor of document.querySelectorAll(".no-thanks")) { + anchor.addEventListener("click", evt => window.close(), false); + } let sumoLink = Services.urlFormatter.formatURLPref("app.support.baseURL"); document.getElementById("sumo-link").href = sumoLink; diff --git a/mobile/android/chrome/content/aboutFeedback.xhtml b/mobile/android/chrome/content/aboutFeedback.xhtml index 1b77dac605c..afe5159b6ea 100644 --- a/mobile/android/chrome/content/aboutFeedback.xhtml +++ b/mobile/android/chrome/content/aboutFeedback.xhtml @@ -35,6 +35,7 @@ @@ -50,7 +51,7 @@ From e1d3d370208d4360880d0bfbdf3d6009fe8e46bf Mon Sep 17 00:00:00 2001 From: William Chen Date: Tue, 4 Mar 2014 18:06:15 -0800 Subject: [PATCH 075/112] Bug 901319 - Implement HTML spec change to Adoption Agency Algorithm to not reverse the order of nodes in the document, by removing nodes that we're not recreating from the stack of open elements. r=hsivonen --- parser/html/javasrc/TreeBuilder.java | 17 +++++++++---- parser/html/nsHtml5TreeBuilder.cpp | 14 +++++++---- .../html5lib_tree_construction/adoption02.dat | 24 +++++++++++++++++++ 3 files changed, 47 insertions(+), 8 deletions(-) diff --git a/parser/html/javasrc/TreeBuilder.java b/parser/html/javasrc/TreeBuilder.java index 4b62af7e34d..05e5a393b43 100644 --- a/parser/html/javasrc/TreeBuilder.java +++ b/parser/html/javasrc/TreeBuilder.java @@ -4638,10 +4638,22 @@ public abstract class TreeBuilder implements TokenHandler, int bookmark = formattingEltListPos; int nodePos = furthestBlockPos; StackNode lastNode = furthestBlock; // weak ref - for (int j = 0; j < 3; ++j) { + int j = 0; + for (;;) { + ++j; nodePos--; + if (nodePos == formattingEltStackPos) { + break; + } StackNode node = stack[nodePos]; // weak ref int nodeListPos = findInListOfActiveFormattingElements(node); + + if (j > 3 && nodeListPos != -1) { + removeFromListOfActiveFormattingElements(nodeListPos); + // Update position to reflect removal from list. + nodeListPos = -1; + } + if (nodeListPos == -1) { assert formattingEltStackPos < nodePos; assert bookmark < nodePos; @@ -4652,9 +4664,6 @@ public abstract class TreeBuilder implements TokenHandler, continue; } // now node is both on stack and in the list - if (nodePos == formattingEltStackPos) { - break; - } if (nodePos == furthestBlockPos) { bookmark = nodeListPos + 1; } diff --git a/parser/html/nsHtml5TreeBuilder.cpp b/parser/html/nsHtml5TreeBuilder.cpp index 88acc937afd..7d203b322e5 100644 --- a/parser/html/nsHtml5TreeBuilder.cpp +++ b/parser/html/nsHtml5TreeBuilder.cpp @@ -3557,10 +3557,19 @@ nsHtml5TreeBuilder::adoptionAgencyEndTag(nsIAtom* name) int32_t bookmark = formattingEltListPos; int32_t nodePos = furthestBlockPos; nsHtml5StackNode* lastNode = furthestBlock; - for (int32_t j = 0; j < 3; ++j) { + int32_t j = 0; + for (; ; ) { + ++j; nodePos--; + if (nodePos == formattingEltStackPos) { + break; + } nsHtml5StackNode* node = stack[nodePos]; int32_t nodeListPos = findInListOfActiveFormattingElements(node); + if (j > 3 && nodeListPos != -1) { + removeFromListOfActiveFormattingElements(nodeListPos); + nodeListPos = -1; + } if (nodeListPos == -1) { MOZ_ASSERT(formattingEltStackPos < nodePos); MOZ_ASSERT(bookmark < nodePos); @@ -3569,9 +3578,6 @@ nsHtml5TreeBuilder::adoptionAgencyEndTag(nsIAtom* name) furthestBlockPos--; continue; } - if (nodePos == formattingEltStackPos) { - break; - } if (nodePos == furthestBlockPos) { bookmark = nodeListPos + 1; } diff --git a/parser/htmlparser/tests/mochitest/html5lib_tree_construction/adoption02.dat b/parser/htmlparser/tests/mochitest/html5lib_tree_construction/adoption02.dat index e54d8033bac..8d69dccce14 100644 --- a/parser/htmlparser/tests/mochitest/html5lib_tree_construction/adoption02.dat +++ b/parser/htmlparser/tests/mochitest/html5lib_tree_construction/adoption02.dat @@ -37,3 +37,27 @@ |
| | + +#data +second
first
+#errors +3: Start tag seen without seeing a doctype first. Expected "". +25: End tag "b" violates nesting rules. +34: Stray end tag "b". +63: Stray end tag "i". +#document +| +| +| +| +| +| +| +| +| +| +| +|
+| +| "first" +| "second" From b4dd408494eb1df98a64e5f9d8bea825f3e40e66 Mon Sep 17 00:00:00 2001 From: Wes Kocher Date: Tue, 4 Mar 2014 18:22:18 -0800 Subject: [PATCH 076/112] Backed out changeset f814a1a08de6 (bug 865241) for failing at least once per push since the test landed --- content/media/webaudio/test/mochitest.ini | 1 - .../test/test_pannerNodeSymmetry.html | 104 ------------------ 2 files changed, 105 deletions(-) delete mode 100644 content/media/webaudio/test/test_pannerNodeSymmetry.html diff --git a/content/media/webaudio/test/mochitest.ini b/content/media/webaudio/test/mochitest.ini index 0a50ac96990..ae7e68dfb16 100644 --- a/content/media/webaudio/test/mochitest.ini +++ b/content/media/webaudio/test/mochitest.ini @@ -108,7 +108,6 @@ support-files = [test_pannerNode.html] [test_pannerNodeAbove.html] [test_pannerNodeChannelCount.html] -[test_pannerNodeSymmetry.html] [test_pannerNodeTail.html] [test_pannerNode_equalPower.html] [test_periodicWave.html] diff --git a/content/media/webaudio/test/test_pannerNodeSymmetry.html b/content/media/webaudio/test/test_pannerNodeSymmetry.html deleted file mode 100644 index a4a2fc1c552..00000000000 --- a/content/media/webaudio/test/test_pannerNodeSymmetry.html +++ /dev/null @@ -1,104 +0,0 @@ - - - - Test left/right symmetry and block-offset invariance of HRTF panner - - - - - -
-
-
- - From 6a4c4691a0ca6b224a11ace720505df7235fca93 Mon Sep 17 00:00:00 2001 From: Jed Davis Date: Tue, 4 Mar 2014 18:27:13 -0800 Subject: [PATCH 077/112] Bug 946407 - Reimplement DumpMemoryInfoToTempDir in terms of GetReports. r=njn This winds up exposing things in the nsIMemoryReporterManager interface that arguably don't belong at that level of abstraction -- "minimize memory usage first" and DMD -- in order to take advantage of the infrastructure that GetReports already has for managing the child processes. --- dom/ipc/ContentChild.cpp | 69 +++++---- dom/ipc/ContentChild.h | 13 +- dom/ipc/ContentParent.cpp | 26 +++- dom/ipc/ContentParent.h | 4 +- dom/ipc/PContent.ipdl | 15 +- js/xpconnect/src/XPCJSRuntime.cpp | 3 +- .../android/chrome/content/MemoryObserver.js | 2 +- xpcom/base/nsIMemoryInfoDumper.idl | 21 +-- xpcom/base/nsIMemoryReporter.idl | 27 +++- xpcom/base/nsMemoryInfoDumper.cpp | 134 +++++++++--------- xpcom/base/nsMemoryInfoDumper.h | 3 + xpcom/base/nsMemoryReporterManager.cpp | 97 +++++++++++-- xpcom/base/nsMemoryReporterManager.h | 12 +- 13 files changed, 280 insertions(+), 146 deletions(-) diff --git a/dom/ipc/ContentChild.cpp b/dom/ipc/ContentChild.cpp index 30321be37c7..e74cbe9616e 100644 --- a/dom/ipc/ContentChild.cpp +++ b/dom/ipc/ContentChild.cpp @@ -172,14 +172,24 @@ static bool sNuwaForking = false; namespace mozilla { namespace dom { -class MemoryReportRequestChild : public PMemoryReportRequestChild +class MemoryReportRequestChild : public PMemoryReportRequestChild, + public nsIRunnable { public: - MemoryReportRequestChild(); + NS_DECL_ISUPPORTS + + MemoryReportRequestChild(uint32_t aGeneration, const nsAString& aDMDDumpIdent); virtual ~MemoryReportRequestChild(); + NS_IMETHOD Run(); +private: + uint32_t mGeneration; + nsString mDMDDumpIdent; }; -MemoryReportRequestChild::MemoryReportRequestChild() +NS_IMPL_ISUPPORTS1(MemoryReportRequestChild, nsIRunnable) + +MemoryReportRequestChild::MemoryReportRequestChild(uint32_t aGeneration, const nsAString& aDMDDumpIdent) +: mGeneration(aGeneration), mDMDDumpIdent(aDMDDumpIdent) { MOZ_COUNT_CTOR(MemoryReportRequestChild); } @@ -518,9 +528,13 @@ ContentChild::InitXPCOM() } PMemoryReportRequestChild* -ContentChild::AllocPMemoryReportRequestChild(const uint32_t& generation) +ContentChild::AllocPMemoryReportRequestChild(const uint32_t& generation, + const bool &minimizeMemoryUsage, + const nsString& aDMDDumpIdent) { - return new MemoryReportRequestChild(); + MemoryReportRequestChild *actor = new MemoryReportRequestChild(generation, aDMDDumpIdent); + actor->AddRef(); + return actor; } // This is just a wrapper for InfallibleTArray that implements @@ -567,25 +581,44 @@ NS_IMPL_ISUPPORTS1( bool ContentChild::RecvPMemoryReportRequestConstructor( PMemoryReportRequestChild* child, - const uint32_t& generation) + const uint32_t& generation, + const bool& minimizeMemoryUsage, + const nsString& aDMDDumpIdent) { + MemoryReportRequestChild *actor = static_cast(child); + nsresult rv; + + if (minimizeMemoryUsage) { + nsCOMPtr mgr = do_GetService("@mozilla.org/memory-reporter-manager;1"); + rv = mgr->MinimizeMemoryUsage(actor); + // mgr will eventually call actor->Run() + } else { + rv = actor->Run(); + } + + return !NS_WARN_IF(NS_FAILED(rv)); +} + +NS_IMETHODIMP MemoryReportRequestChild::Run() +{ + ContentChild *child = static_cast(Manager()); nsCOMPtr mgr = do_GetService("@mozilla.org/memory-reporter-manager;1"); InfallibleTArray reports; nsCString process; - GetProcessName(process); - AppendProcessId(process); + child->GetProcessName(process); + child->AppendProcessId(process); // Run the reporters. The callback will turn each measurement into a // MemoryReport. nsRefPtr wrappedReports = new MemoryReportsWrapper(&reports); nsRefPtr cb = new MemoryReportCallback(process); - mgr->GetReportsForThisProcess(cb, wrappedReports); + mgr->GetReportsForThisProcessExtended(cb, wrappedReports, mDMDDumpIdent); - child->Send__delete__(child, generation, reports); - return true; + bool sent = Send__delete__(this, mGeneration, reports); + return sent ? NS_OK : NS_ERROR_FAILURE; } bool @@ -602,19 +635,7 @@ ContentChild::RecvAudioChannelNotify() bool ContentChild::DeallocPMemoryReportRequestChild(PMemoryReportRequestChild* actor) { - delete actor; - return true; -} - -bool -ContentChild::RecvDumpMemoryInfoToTempDir(const nsString& aIdentifier, - const bool& aMinimizeMemoryUsage, - const bool& aDumpChildProcesses) -{ - nsCOMPtr dumper = do_GetService("@mozilla.org/memory-info-dumper;1"); - - dumper->DumpMemoryInfoToTempDir(aIdentifier, aMinimizeMemoryUsage, - aDumpChildProcesses); + static_cast(actor)->Release(); return true; } diff --git a/dom/ipc/ContentChild.h b/dom/ipc/ContentChild.h index c20518b22cf..7bd070b76c2 100644 --- a/dom/ipc/ContentChild.h +++ b/dom/ipc/ContentChild.h @@ -115,22 +115,21 @@ public: virtual bool DeallocPIndexedDBChild(PIndexedDBChild* aActor) MOZ_OVERRIDE; virtual PMemoryReportRequestChild* - AllocPMemoryReportRequestChild(const uint32_t& generation) MOZ_OVERRIDE; - + AllocPMemoryReportRequestChild(const uint32_t& generation, + const bool &minimizeMemoryUsage, + const nsString &aDMDDumpIdent) MOZ_OVERRIDE; virtual bool DeallocPMemoryReportRequestChild(PMemoryReportRequestChild* actor) MOZ_OVERRIDE; virtual bool RecvPMemoryReportRequestConstructor(PMemoryReportRequestChild* child, - const uint32_t& generation) MOZ_OVERRIDE; + const uint32_t& generation, + const bool &minimizeMemoryUsage, + const nsString &aDMDDumpIdent) MOZ_OVERRIDE; virtual bool RecvAudioChannelNotify() MOZ_OVERRIDE; - virtual bool - RecvDumpMemoryInfoToTempDir(const nsString& aIdentifier, - const bool& aMinimizeMemoryUsage, - const bool& aDumpChildProcesses) MOZ_OVERRIDE; virtual bool RecvDumpGCAndCCLogsToFile(const nsString& aIdentifier, const bool& aDumpAllTraces, diff --git a/dom/ipc/ContentParent.cpp b/dom/ipc/ContentParent.cpp index 63cc8083959..cc2232b1d7e 100644 --- a/dom/ipc/ContentParent.cpp +++ b/dom/ipc/ContentParent.cpp @@ -2040,10 +2040,28 @@ ContentParent::Observe(nsISupports* aSubject, return NS_ERROR_NOT_AVAILABLE; } else if (!strcmp(aTopic, "child-memory-reporter-request")) { + bool isNuwa = false; #ifdef MOZ_NUWA_PROCESS - if (!IsNuwaProcess()) + isNuwa = IsNuwaProcess(); #endif - unused << SendPMemoryReportRequestConstructor((uint32_t)(uintptr_t)aData); + if (!isNuwa) { + unsigned generation; + int minimize, identOffset = -1; + nsDependentString msg(aData); + NS_ConvertUTF16toUTF8 cmsg(msg); + + if (sscanf(cmsg.get(), + "generation=%x minimize=%d DMDident=%n", + &generation, &minimize, &identOffset) < 2 + || identOffset < 0) { + return NS_ERROR_INVALID_ARG; + } + // The pre-%n part of the string should be all ASCII, so the byte + // offset in identOffset should be correct as a char offset. + MOZ_ASSERT(cmsg[identOffset - 1] == '='); + unused << SendPMemoryReportRequestConstructor( + generation, minimize, nsString(Substring(msg, identOffset))); + } } else if (!strcmp(aTopic, "child-gc-request")){ unused << SendGarbageCollect(); @@ -2504,7 +2522,9 @@ ContentParent::RecvPIndexedDBConstructor(PIndexedDBParent* aActor) } PMemoryReportRequestParent* -ContentParent::AllocPMemoryReportRequestParent(const uint32_t& generation) +ContentParent::AllocPMemoryReportRequestParent(const uint32_t& generation, + const bool &minimizeMemoryUsage, + const nsString &aDMDDumpIdent) { MemoryReportRequestParent* parent = new MemoryReportRequestParent(); return parent; diff --git a/dom/ipc/ContentParent.h b/dom/ipc/ContentParent.h index a9b5582bb7f..552f0bc306b 100644 --- a/dom/ipc/ContentParent.h +++ b/dom/ipc/ContentParent.h @@ -359,7 +359,9 @@ private: virtual bool DeallocPIndexedDBParent(PIndexedDBParent* aActor) MOZ_OVERRIDE; virtual PMemoryReportRequestParent* - AllocPMemoryReportRequestParent(const uint32_t& generation) MOZ_OVERRIDE; + AllocPMemoryReportRequestParent(const uint32_t& generation, + const bool &minimizeMemoryUsage, + const nsString &aDMDDumpIdent) MOZ_OVERRIDE; virtual bool DeallocPMemoryReportRequestParent(PMemoryReportRequestParent* actor) MOZ_OVERRIDE; virtual PTestShellParent* AllocPTestShellParent() MOZ_OVERRIDE; diff --git a/dom/ipc/PContent.ipdl b/dom/ipc/PContent.ipdl index 3ece0405e8b..46355b597bf 100644 --- a/dom/ipc/PContent.ipdl +++ b/dom/ipc/PContent.ipdl @@ -259,7 +259,7 @@ child: */ async SetProcessPrivileges(ChildPrivileges privs); - PMemoryReportRequest(uint32_t generation); + PMemoryReportRequest(uint32_t generation, bool minimizeMemoryUsage, nsString DMDDumpIdent); /** * Notify the AudioChannelService in the child processes. @@ -268,20 +268,11 @@ child: async SpeakerManagerNotify(); - /** - * Do a memory info dump to a file in our temp directory. - * - * For documentation on the args, see - * MemoryInfoDumper::dumpMemoryInfoToTempDir. - */ - async DumpMemoryInfoToTempDir(nsString identifier, - bool minimizeMemoryUsage, - bool dumpChildProcesses); /** * Dump this process's GC and CC logs. * - * For documentation on the args, see - * MemoryInfoDumper::dumpGCAndCCLogsToFile. + * For documentation on the args, see dumpGCAndCCLogsToFile in + * nsIMemoryInfoDumper.idl */ async DumpGCAndCCLogsToFile(nsString identifier, bool dumpAllTraces, diff --git a/js/xpconnect/src/XPCJSRuntime.cpp b/js/xpconnect/src/XPCJSRuntime.cpp index 07bd269768a..53ae0d67b31 100644 --- a/js/xpconnect/src/XPCJSRuntime.cpp +++ b/js/xpconnect/src/XPCJSRuntime.cpp @@ -1412,8 +1412,7 @@ XPCJSRuntime::OutOfMemoryCallback(JSContext *cx) // If this fails, it fails silently. dumper->DumpMemoryInfoToTempDir(NS_LITERAL_STRING("due-to-JS-OOM"), - /* minimizeMemoryUsage = */ false, - /* dumpChildProcesses = */ false); + /* minimizeMemoryUsage = */ false); } size_t diff --git a/mobile/android/chrome/content/MemoryObserver.js b/mobile/android/chrome/content/MemoryObserver.js index 6315ee5901c..e2362a5e445 100644 --- a/mobile/android/chrome/content/MemoryObserver.js +++ b/mobile/android/chrome/content/MemoryObserver.js @@ -60,6 +60,6 @@ var MemoryObserver = { dumpMemoryStats: function(aLabel) { let memDumper = Cc["@mozilla.org/memory-info-dumper;1"].getService(Ci.nsIMemoryInfoDumper); - memDumper.dumpMemoryInfoToTempDir(aLabel, false, true); + memDumper.dumpMemoryInfoToTempDir(aLabel, /* minimize = */ false); }, }; diff --git a/xpcom/base/nsIMemoryInfoDumper.idl b/xpcom/base/nsIMemoryInfoDumper.idl index 0ea39fd224c..b310aacfe17 100644 --- a/xpcom/base/nsIMemoryInfoDumper.idl +++ b/xpcom/base/nsIMemoryInfoDumper.idl @@ -11,7 +11,7 @@ interface nsIFinishDumpingCallback : nsISupports void callback(in nsISupports data); }; -[scriptable, builtinclass, uuid(294df03b-e2ae-4fdd-b4fc-4c66a501e0ef)] +[scriptable, builtinclass, uuid(815bf31b-f5bd-425d-85c3-4657a7a91dad)] interface nsIMemoryInfoDumper : nsISupports { /** @@ -94,19 +94,17 @@ interface nsIMemoryInfoDumper : nsISupports /** * Similar to dumpMemoryReportsToNamedFile, this method dumps gzipped memory - * reports for this process and possibly its child processes (and their - * children, recursively) to a file in the tmp directory called - * memory-reports--.json.gz (or something similar, such as - * memory-reports---1.json.gz; no existing file will be - * overwritten). + * reports for this process and its child processes to files in the tmp + * directory called memory-reports--.json.gz (or something + * similar, such as memory-reports---1.json.gz; no existing + * file will be overwritten). * * If DMD is enabled, this method also dumps gzipped DMD output to a file in * the tmp directory called dmd--.txt.gz (or something * similar; again, no existing file will be overwritten). * * @param aIdentifier this identifier will appear in the filename of our - * about:memory dump and those of our children (if aDumpChildProcesses is - * true). + * about:memory dump and those of our children. * * If the identifier is empty, the implementation may set it arbitrarily * and use that new value for its own dump and the dumps of its child @@ -116,15 +114,10 @@ interface nsIMemoryInfoDumper : nsISupports * @param aMinimizeMemoryUsage indicates whether we should run a series of * gc/cc's in an attempt to reduce our memory usage before collecting our * memory report. - * - * @param aDumpChildProcesses indicates whether we should call - * dumpMemoryInfoToTempDir in our child processes. If - * so, the child processes will also dump their children, and so on. */ void dumpMemoryInfoToTempDir( in AString aIdentifier, - in bool aMinimizeMemoryUsage, - in bool aDumpChildProcesses); + in bool aMinimizeMemoryUsage); /** * Dump GC and CC logs to files in the OS's temp directory (or in diff --git a/xpcom/base/nsIMemoryReporter.idl b/xpcom/base/nsIMemoryReporter.idl index 52f82a37766..0b61aadd35c 100644 --- a/xpcom/base/nsIMemoryReporter.idl +++ b/xpcom/base/nsIMemoryReporter.idl @@ -178,7 +178,7 @@ interface nsIFinishReportingCallback : nsISupports void callback(in nsISupports data); }; -[scriptable, builtinclass, uuid(12e08b1b-6590-4f78-996b-d9062c17e856)] +[scriptable, builtinclass, uuid(b6e5ec8a-71d9-48db-8ae9-68b4c5bbf2c3)] interface nsIMemoryReporterManager : nsISupports { /* @@ -242,6 +242,21 @@ interface nsIMemoryReporterManager : nsISupports in nsIFinishReportingCallback finishReporting, in nsISupports finishReportingData); + /* + * As above, but: If |minimizeMemoryUsage| is true, then each process will + * minimize its memory usage (see the |minimizeMemoryUsage| method) before + * gathering its report. If DMD is enabled and |DMDDumpIdent| is non-empty + * then write a DMD report to a file in the usual temporary directory (see + * |dumpMemoryInfoToTempDir| in |nsIMemoryInfoDumper|.) + */ + [noscript] void + getReportsExtended(in nsIMemoryReporterCallback handleReport, + in nsISupports handleReportData, + in nsIFinishReportingCallback finishReporting, + in nsISupports finishReportingData, + in boolean minimizeMemoryUsage, + in AString DMDDumpIdent); + /* * Get memory reports in the current process only. |handleReport| is called * for each report. @@ -249,6 +264,16 @@ interface nsIMemoryReporterManager : nsISupports void getReportsForThisProcess(in nsIMemoryReporterCallback handleReport, in nsISupports handleReportData); + /* + * As above, but if DMD is enabled and |DMDDumpIdent| is non-empty + * then write a DMD report to a file in the usual temporary directory (see + * |dumpMemoryInfoToTempDir| in |nsIMemoryInfoDumper|.) + */ + [noscript] void + getReportsForThisProcessExtended(in nsIMemoryReporterCallback handleReport, + in nsISupports handleReportData, + in AString DMDDumpIdent); + /* * The memory reporter manager, for the most part, treats reporters * registered with it as a black box. However, there are some diff --git a/xpcom/base/nsMemoryInfoDumper.cpp b/xpcom/base/nsMemoryInfoDumper.cpp index 2e21ed9d354..f2faefa34a6 100644 --- a/xpcom/base/nsMemoryInfoDumper.cpp +++ b/xpcom/base/nsMemoryInfoDumper.cpp @@ -60,25 +60,21 @@ class DumpMemoryInfoToTempDirRunnable : public nsRunnable { public: DumpMemoryInfoToTempDirRunnable(const nsAString& aIdentifier, - bool aMinimizeMemoryUsage, - bool aDumpChildProcesses) + bool aMinimizeMemoryUsage) : mIdentifier(aIdentifier) , mMinimizeMemoryUsage(aMinimizeMemoryUsage) - , mDumpChildProcesses(aDumpChildProcesses) {} NS_IMETHOD Run() { nsCOMPtr dumper = do_GetService("@mozilla.org/memory-info-dumper;1"); - dumper->DumpMemoryInfoToTempDir(mIdentifier, mMinimizeMemoryUsage, - mDumpChildProcesses); + dumper->DumpMemoryInfoToTempDir(mIdentifier, mMinimizeMemoryUsage); return NS_OK; } private: const nsString mIdentifier; const bool mMinimizeMemoryUsage; - const bool mDumpChildProcesses; }; class GCAndCCLogDumpRunnable : public nsRunnable @@ -357,8 +353,7 @@ public: bool doMMUFirst = signum == sDumpAboutMemoryAfterMMUSignum; nsRefPtr runnable = new DumpMemoryInfoToTempDirRunnable(/* identifier = */ EmptyString(), - doMMUFirst, - /* dumpChildProcesses = */ true); + doMMUFirst); NS_DispatchToMainThread(runnable); } else if (signum == sGCAndCCDumpSignum) { @@ -520,8 +515,7 @@ public: LOG("FifoWatcher dispatching memory report runnable."); nsRefPtr runnable = new DumpMemoryInfoToTempDirRunnable(/* identifier = */ EmptyString(), - doMMUMemoryReport, - /* dumpChildProcesses = */ true); + doMMUMemoryReport); NS_DispatchToMainThread(runnable); } else if (doAllTracesGCCCDump || doSmallGCCCDump) { LOG("FifoWatcher dispatching GC/CC log runnable."); @@ -830,25 +824,38 @@ DumpFooter(nsIGZFileWriter* aWriter) return NS_OK; } -static nsresult -DumpProcessMemoryReportsToGZFileWriter(nsGZFileWriter* aWriter) +class TempDirMemoryFinishCallback MOZ_FINAL : public nsIFinishReportingCallback { - nsresult rv = DumpHeader(aWriter); - NS_ENSURE_SUCCESS(rv, rv); +public: + NS_DECL_ISUPPORTS - // Process reporters. - nsCOMPtr mgr = - do_GetService("@mozilla.org/memory-reporter-manager;1"); - nsRefPtr dumpReport = new DumpReportCallback(aWriter); - mgr->GetReportsForThisProcess(dumpReport, nullptr); + TempDirMemoryFinishCallback(nsGZFileWriter *aWriter, + nsIFile *aTmpFile, + const nsCString &aFilename, + const nsString &aIdentifier) + : mrWriter(aWriter) + , mrTmpFile(aTmpFile) + , mrFilename(aFilename) + , mIdentifier(aIdentifier) + {} - return DumpFooter(aWriter); -} + NS_IMETHOD Callback(nsISupports *aData); -nsresult -DumpProcessMemoryInfoToTempDir(const nsAString& aIdentifier) +private: + nsRefPtr mrWriter; + nsCOMPtr mrTmpFile; + nsCString mrFilename; + nsString mIdentifier; +}; + +NS_IMPL_ISUPPORTS1(TempDirMemoryFinishCallback, nsIFinishReportingCallback) + +NS_IMETHODIMP +nsMemoryInfoDumper::DumpMemoryInfoToTempDir(const nsAString& aIdentifier, + bool aMinimizeMemoryUsage) { - MOZ_ASSERT(!aIdentifier.IsEmpty()); + nsString identifier(aIdentifier); + EnsureNonEmptyIdentifier(identifier); #ifdef MOZ_DMD // Clear DMD's reportedness state before running the memory reporters, to @@ -870,7 +877,12 @@ DumpProcessMemoryInfoToTempDir(const nsAString& aIdentifier) // Note that |mrFilename| is missing the "incomplete-" prefix; we'll tack // that on in a moment. nsCString mrFilename; - MakeFilename("memory-report", aIdentifier, "json.gz", mrFilename); + // The "unified" indicates that we merge the memory reports from all + // processes and write out one file, rather than a separate file for + // each process as was the case before bug 946407. This is so that + // the get_about_memory.py script in the B2G repository can + // determine when it's done waiting for files to appear. + MakeFilename("unified-memory-report", identifier, "json.gz", mrFilename); nsCOMPtr mrTmpFile; nsresult rv; @@ -886,9 +898,29 @@ DumpProcessMemoryInfoToTempDir(const nsAString& aIdentifier) return rv; // Dump the memory reports to the file. - DumpProcessMemoryReportsToGZFileWriter(mrWriter); + rv = DumpHeader(mrWriter); + if (NS_WARN_IF(NS_FAILED(rv))) + return rv; + + // Process reporters. + nsCOMPtr mgr = + do_GetService("@mozilla.org/memory-reporter-manager;1"); + nsRefPtr dumpReport = new DumpReportCallback(mrWriter); + nsRefPtr finishReport = + new TempDirMemoryFinishCallback(mrWriter, mrTmpFile, mrFilename, identifier); + rv = mgr->GetReportsExtended(dumpReport, nullptr, + finishReport, nullptr, + aMinimizeMemoryUsage, + identifier); + return rv; +} #ifdef MOZ_DMD +nsresult +nsMemoryInfoDumper::DumpDMD(const nsAString &aIdentifier) +{ + nsresult rv; + // Create a filename like dmd--.txt.gz, which will be used // if DMD is enabled. nsCString dmdFilename; @@ -916,9 +948,19 @@ DumpProcessMemoryInfoToTempDir(const nsAString& aIdentifier) dmd::Dump(w); rv = dmdWriter->Finish(); + NS_WARN_IF(NS_FAILED(rv)); + return rv; +} +#endif // MOZ_DMD + +NS_IMETHODIMP +TempDirMemoryFinishCallback::Callback(nsISupports *aData) +{ + nsresult rv; + + rv = DumpFooter(mrWriter); if (NS_WARN_IF(NS_FAILED(rv))) return rv; -#endif // MOZ_DMD // The call to Finish() deallocates the memory allocated by mrWriter's first // DUMP() call (within DumpProcessMemoryReportsToGZFileWriter()). Because @@ -978,44 +1020,6 @@ DumpProcessMemoryInfoToTempDir(const nsAString& aIdentifier) return cs->LogStringMessage(msg.get()); } -NS_IMETHODIMP -nsMemoryInfoDumper::DumpMemoryInfoToTempDir(const nsAString& aIdentifier, - bool aMinimizeMemoryUsage, - bool aDumpChildProcesses) -{ - nsString identifier(aIdentifier); - EnsureNonEmptyIdentifier(identifier); - - // Kick off memory report dumps in our child processes, if applicable. We - // do this before doing our own report because writing a report may be I/O - // bound, in which case we want to busy the CPU with other reports while we - // work on our own. - if (aDumpChildProcesses) { - nsTArray children; - ContentParent::GetAll(children); - for (uint32_t i = 0; i < children.Length(); i++) { - unused << children[i]->SendDumpMemoryInfoToTempDir( - identifier, aMinimizeMemoryUsage, aDumpChildProcesses); - } - } - - if (aMinimizeMemoryUsage) { - // Minimize memory usage, then run DumpMemoryInfoToTempDir again. - nsRefPtr callback = - new DumpMemoryInfoToTempDirRunnable(identifier, - /* minimizeMemoryUsage = */ false, - /* dumpChildProcesses = */ false); - nsCOMPtr mgr = - do_GetService("@mozilla.org/memory-reporter-manager;1"); - if (NS_WARN_IF(!mgr)) - return NS_ERROR_FAILURE; - mgr->MinimizeMemoryUsage(callback); - return NS_OK; - } - - return DumpProcessMemoryInfoToTempDir(identifier); -} - // This dumps the JSON footer and closes the file, and then calls the given // nsIFinishDumpingCallback. class FinishReportingCallback MOZ_FINAL : public nsIFinishReportingCallback diff --git a/xpcom/base/nsMemoryInfoDumper.h b/xpcom/base/nsMemoryInfoDumper.h index 166c7f9f024..d4910be4d2e 100644 --- a/xpcom/base/nsMemoryInfoDumper.h +++ b/xpcom/base/nsMemoryInfoDumper.h @@ -38,6 +38,9 @@ public: * instead. */ static nsresult OpenTempFile(const nsACString &aFilename, nsIFile* *aFile); +#ifdef MOZ_DMD + static nsresult DumpDMD(const nsAString &aIdentifier); +#endif }; #define NS_MEMORY_INFO_DUMPER_CID \ diff --git a/xpcom/base/nsMemoryReporterManager.cpp b/xpcom/base/nsMemoryReporterManager.cpp index c1399b40046..0ce5a4c3cba 100644 --- a/xpcom/base/nsMemoryReporterManager.cpp +++ b/xpcom/base/nsMemoryReporterManager.cpp @@ -8,6 +8,7 @@ #include "nsAutoPtr.h" #include "nsCOMPtr.h" #include "nsCOMArray.h" +#include "nsPrintfCString.h" #include "nsServiceManagerUtils.h" #include "nsMemoryReporterManager.h" #include "nsITimer.h" @@ -952,6 +953,23 @@ nsMemoryReporterManager::GetReports( nsIFinishReportingCallback* aFinishReporting, nsISupports* aFinishReportingData) { + return GetReportsExtended(aHandleReport, aHandleReportData, + aFinishReporting, aFinishReportingData, + /* minimize = */ false, + /* DMDident = */ nsString()); +} + +NS_IMETHODIMP +nsMemoryReporterManager::GetReportsExtended( + nsIHandleReportCallback* aHandleReport, + nsISupports* aHandleReportData, + nsIFinishReportingCallback* aFinishReporting, + nsISupports* aFinishReportingData, + bool aMinimize, + const nsAString& aDMDDumpIdent) +{ + nsresult rv; + // Memory reporters are not necessarily threadsafe, so this function must // be called from the main thread. if (!NS_IsMainThread()) { @@ -979,16 +997,19 @@ nsMemoryReporterManager::GetReports( do_GetService("@mozilla.org/observer-service;1"); NS_ENSURE_STATE(obs); - // Casting the uint32_t generation to |const char16_t*| is a hack, but - // simpler than converting the number to an actual string. + nsPrintfCString genStr("generation=%x minimize=%d DMDident=", + generation, aMinimize ? 1 : 0); + nsAutoString msg = NS_ConvertUTF8toUTF16(genStr); + msg += aDMDDumpIdent; + obs->NotifyObservers(nullptr, "child-memory-reporter-request", - (const char16_t*)(uintptr_t)generation); + msg.get()); nsCOMPtr timer = do_CreateInstance(NS_TIMER_CONTRACTID); NS_ENSURE_TRUE(timer, NS_ERROR_FAILURE); - nsresult rv = timer->InitWithFuncCallback(TimeoutCallback, - this, kTimeoutLengthMS, - nsITimer::TYPE_ONE_SHOT); + rv = timer->InitWithFuncCallback(TimeoutCallback, + this, kTimeoutLengthMS, + nsITimer::TYPE_ONE_SHOT); NS_ENSURE_SUCCESS(rv, rv); mGetReportsState = new GetReportsState(generation, @@ -997,16 +1018,40 @@ nsMemoryReporterManager::GetReports( aHandleReport, aHandleReportData, aFinishReporting, - aFinishReportingData); + aFinishReportingData, + aDMDDumpIdent); + } else { + mGetReportsState = new GetReportsState(generation, + nullptr, + /* mNumChildProcesses = */ 0, + aHandleReport, + aHandleReportData, + aFinishReporting, + aFinishReportingData, + aDMDDumpIdent); } + if (aMinimize) { + rv = MinimizeMemoryUsage(NS_NewRunnableMethod(this, &nsMemoryReporterManager::StartGettingReports)); + } else { + rv = StartGettingReports(); + } + return rv; +} + +nsresult +nsMemoryReporterManager::StartGettingReports() +{ + GetReportsState *s = mGetReportsState; + // Get reports for this process. - GetReportsForThisProcess(aHandleReport, aHandleReportData); + GetReportsForThisProcessExtended(s->mHandleReport, s->mHandleReportData, + s->mDMDDumpIdent); // If there are no child processes, we can finish up immediately. - return (mNumChildProcesses == 0) - ? aFinishReporting->Callback(aFinishReportingData) - : NS_OK; + return (s->mNumChildProcesses == 0) + ? FinishReporting() + : NS_OK; } typedef nsCOMArray MemoryReporterArray; @@ -1031,6 +1076,17 @@ NS_IMETHODIMP nsMemoryReporterManager::GetReportsForThisProcess( nsIHandleReportCallback* aHandleReport, nsISupports* aHandleReportData) +{ + return GetReportsForThisProcessExtended(aHandleReport, + aHandleReportData, + nsString()); +} + +NS_IMETHODIMP +nsMemoryReporterManager::GetReportsForThisProcessExtended( + nsIHandleReportCallback* aHandleReport, + nsISupports* aHandleReportData, + const nsAString& aDMDDumpIdent) { // Memory reporters are not necessarily threadsafe, so this function must // be called from the main thread. @@ -1038,6 +1094,14 @@ nsMemoryReporterManager::GetReportsForThisProcess( MOZ_CRASH(); } +#ifdef MOZ_DMD + if (!aDMDDumpIdent.IsEmpty()) { + // Clear DMD's reportedness state before running the memory + // reporters, to avoid spurious twice-reported warnings. + dmd::ClearReports(); + } +#endif + MemoryReporterArray allReporters; { mozilla::MutexAutoLock autoLock(mMutex); @@ -1048,6 +1112,12 @@ nsMemoryReporterManager::GetReportsForThisProcess( allReporters[i]->CollectReports(aHandleReport, aHandleReportData); } +#ifdef MOZ_DMD + if (!aDMDDumpIdent.IsEmpty()) { + return nsMemoryInfoDumper::DumpDMD(aDMDDumpIdent); + } +#endif + return NS_OK; } @@ -1136,7 +1206,7 @@ nsMemoryReporterManager::TimeoutCallback(nsITimer* aTimer, void* aData) mgr->FinishReporting(); } -void +nsresult nsMemoryReporterManager::FinishReporting() { // Memory reporting only happens on the main thread. @@ -1151,11 +1221,12 @@ nsMemoryReporterManager::FinishReporting() // Call this before deleting |mGetReportsState|. That way, if // |mFinishReportData| calls GetReports(), it will silently abort, as // required. - (void)mGetReportsState->mFinishReporting->Callback( + nsresult rv = mGetReportsState->mFinishReporting->Callback( mGetReportsState->mFinishReportingData); delete mGetReportsState; mGetReportsState = nullptr; + return rv; } static void diff --git a/xpcom/base/nsMemoryReporterManager.h b/xpcom/base/nsMemoryReporterManager.h index c23d6c894ac..2c53db2729f 100644 --- a/xpcom/base/nsMemoryReporterManager.h +++ b/xpcom/base/nsMemoryReporterManager.h @@ -117,7 +117,7 @@ public: void HandleChildReports( const uint32_t& generation, const InfallibleTArray& aChildReports); - void FinishReporting(); + nsresult FinishReporting(); // Functions that (a) implement distinguished amounts, and (b) are outside of // this module. @@ -157,9 +157,12 @@ public: private: nsresult RegisterReporterHelper(nsIMemoryReporter* aReporter, bool aForce, bool aStrongRef); + nsresult StartGettingReports(); static void TimeoutCallback(nsITimer* aTimer, void* aData); - static const uint32_t kTimeoutLengthMS = 5000; + // Note: this timeout needs to be long enough to allow for the + // possibility of DMD reports and/or running on a low-end phone. + static const uint32_t kTimeoutLengthMS = 50000; mozilla::Mutex mMutex; bool mIsRegistrationBlocked; @@ -184,13 +187,15 @@ private: nsCOMPtr mHandleReportData; nsCOMPtr mFinishReporting; nsCOMPtr mFinishReportingData; + nsString mDMDDumpIdent; GetReportsState(uint32_t aGeneration, nsITimer* aTimer, uint32_t aNumChildProcesses, nsIHandleReportCallback* aHandleReport, nsISupports* aHandleReportData, nsIFinishReportingCallback* aFinishReporting, - nsISupports* aFinishReportingData) + nsISupports* aFinishReportingData, + const nsAString &aDMDDumpIdent) : mGeneration(aGeneration) , mTimer(aTimer) , mNumChildProcesses(aNumChildProcesses) @@ -199,6 +204,7 @@ private: , mHandleReportData(aHandleReportData) , mFinishReporting(aFinishReporting) , mFinishReportingData(aFinishReportingData) + , mDMDDumpIdent(aDMDDumpIdent) { } }; From cfaafc654d791d809a2e93ef2dcb7ad50dd74d6d Mon Sep 17 00:00:00 2001 From: Jed Davis Date: Tue, 4 Mar 2014 18:27:14 -0800 Subject: [PATCH 078/112] Bug 946407 - Disable sandbox when DMDing. r=njn r=kang See also bug 956961. --- security/sandbox/linux/Sandbox.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/security/sandbox/linux/Sandbox.cpp b/security/sandbox/linux/Sandbox.cpp index 5256b7e76ad..a0076cfcbaf 100644 --- a/security/sandbox/linux/Sandbox.cpp +++ b/security/sandbox/linux/Sandbox.cpp @@ -221,6 +221,15 @@ InstallSyscallReporter(void) static int InstallSyscallFilter(void) { +#ifdef MOZ_DMD + char* e = PR_GetEnv("DMD"); + if (e && strcmp(e, "") != 0 && strcmp(e, "0") != 0) { + LOG_ERROR("SANDBOX DISABLED FOR DMD! See bug 956961."); + // Must treat this as "failure" in order to prevent infinite loop; + // cf. the PR_GET_SECCOMP check below. + return 1; + } +#endif if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) { return 1; } From 3e3cabcaaf353039689c9caf440d4d6852d49b3c Mon Sep 17 00:00:00 2001 From: Ehsan Akhgari Date: Tue, 4 Mar 2014 21:36:16 -0500 Subject: [PATCH 079/112] Bug 979681 - Correctly handle SOURCES.flags for sources with relative paths in them; r=glandium --- python/mozbuild/mozbuild/backend/recursivemake.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/mozbuild/mozbuild/backend/recursivemake.py b/python/mozbuild/mozbuild/backend/recursivemake.py index 5288a576dd3..8e6d1384f83 100644 --- a/python/mozbuild/mozbuild/backend/recursivemake.py +++ b/python/mozbuild/mozbuild/backend/recursivemake.py @@ -1091,7 +1091,7 @@ class RecursiveMakeBackend(CommonBackend): def _process_per_source_flag(self, per_source_flag, backend_file): for flag in per_source_flag.flags: - backend_file.write('%s_FLAGS += %s\n' % (per_source_flag.file_name, flag)) + backend_file.write('%s_FLAGS += %s\n' % (mozpath.basename(per_source_flag.file_name), flag)) def _process_java_jar_data(self, jar, backend_file): target = jar.name From 5421baa9d07d88e5c2858e228b619ce266d0da7c Mon Sep 17 00:00:00 2001 From: Gijs Kruitbosch Date: Tue, 4 Mar 2014 22:11:46 -0500 Subject: [PATCH 080/112] Bug 959640 - add icons to enable SDK add-ons to show default icon in Australis, rs=jaws,various-real-life-review+s --- browser/themes/linux/menuPanel.png | Bin 21339 -> 23170 bytes browser/themes/osx/menuPanel.png | Bin 24904 -> 27161 bytes browser/themes/osx/menuPanel@2x.png | Bin 55854 -> 61282 bytes browser/themes/windows/menuPanel-aero.png | Bin 25939 -> 28137 bytes browser/themes/windows/menuPanel.png | Bin 21339 -> 23170 bytes 5 files changed, 0 insertions(+), 0 deletions(-) diff --git a/browser/themes/linux/menuPanel.png b/browser/themes/linux/menuPanel.png index 5821f40bd9380b9debc7c5699f86d7026d54af4e..0fc16291d311af51e4aedaedfd616f62adf17ccb 100644 GIT binary patch literal 23170 zcmV)jK%u{hP)E?}hrMAz1Vu!#fr$0lkQPFE?>(U@AVrX-sGx$14-`Q~MCk+&3%y7W zNa!RGNSXKl_wIycv-jS;H#afCneRJaZgywR>`pmz{&UXE)~aPO)sCEYu3zXEvA%(y z&hqj9c(YH>2}f%6c)!R-_-(s}d%noSytPzPNhOt3Qb{G1R8mPLm1~gtPSg(iLiokb7QWdlgwK!-qSo+jcEWETT=R{?J>;p~^P>}W0zUnrUc|I}R12!4 zQq4{NA+cwJMubGCYz>b~D+Uz?M&q>7%0wzys3|`e}5qt!+=?qxReL?SNXvR{2r6et2z zw+i0Z2hB?N zgnb4lSLSnBE zj!s?~k(eo*w88ag>#3N}hn>zdcL}`6le}4n8r>?@0QoZ?Yg>iKK6#K=B|T#rN%hvh zVm$h2x|Lr4Dgfo<_byHU>Ib^N!ur=aA=6tl>Hf*KCc!gA(?Q!sld<`t(MQFi{-jb- z=Tjm4J`=(RRBQ4n^2PstxK|f>>VI4;8ji~sO$KiljY4LK#^7~!$aJrHgRq$SfvyF$ z1+~}y@_!!}<(`O2%03pC)?Zj?@J67%pn4VPG(S);Zvzy(M*}FPUnXU}ElBu1mDj3N zp$Lubo7!)PpmL1gDOC=DUh;c(+01~YOK12m!SAOlQE~DGbq$J2UKf+v&-T8VZ;cTB zhP-D31El`%yl1<{d(0CYow6Qfy7ls6zlX%8Zq5SmAP8|reFu+(vXz?aop+CE8lT=D z@Aw{gk3Nn1zcWfiCubehmiCggpfGRGDa)kB^rz+CL{e4-+YGRDkhptt-( zWA~G1V&+>St^Ye1U&8@BN80+AV~@n&ycZUiHp9`_wOVgfQdUvFA){dqWeOoZ^F8`RBus|_xD)b<-udG+ieRpe#l5Gfe|XA2K7D|o zJm8q+y50j%qTP0@?5@{G$83Tuj%(q8~?7<^###z1og}iG~ z<_(YZuk!<^cR08EXNQ|b{UXkP_mF7zez7?FBOw}36r#Z-0Gv5T3F&AN)HQmez{sR|acKiYpNPbno-FzVX&9`N zqmr`)2Il+TQiky!=RwI@l-7TUO)(|$H?Q$t6)6+)vjy~@l7Po+gAuIJ!COR5VcAzyx&~OwQm%1PFY`C|^ zbtTKGI#e34K9u4eO8G7+eFvG&jXseHQ?me&^zY4a&$*mF;2n|LZ?LVbGh!a*Wf`+M zLt-7Q%cyKt3|zfu1ITue{O)PLIXL8Xz8w?L<6{EdcuI7|Zt`;^8I>7AEGk=WG!R0L^=d(@M9IG#C{!{gJM zdity^OCFBqTm|NJ2G+we{fEDCE$yF?F|ii}L?q0Ph2qV2XZv%G(O8LVrMTDI3w6AU zF;rxm!{w3vc zLdJk)Fla@BqVapNQ8z2ozakSBg2#U>H^9Yxrr&cx_bEp%j?EF5k1P82&_qk955NtrXjv9{_qf@d^68tz@1hu@4gCY~>apKy* z1^xy`Bme}()N|vR{Q$%!b3x=YQMm{RBM6G|t>DDJ4$963dmD_hbu@{;d5!m&r?Mw~ z?~s^mF0ccKj#>SHk23|;NZwp#c$kO#SX#nOQ`y8NU zpw~bLJRSNvoKZG_29&Hdy@F#ZCG?W*XSJ>M#QCl*{2B;~semUa=4mMI2RXML)yJ_0 zfSMl=5nt~#`4yG8lF!01iDx;;vFxq!)o;j1c!!3F$fV2?)cX~9-%>5XPjJlTL6J#| zIj;Ib8R<88aNuq$?>Yznq3 zFlJZ6N7<~jk%^g9#Qs~808mB1s2)_B@u{dM1aqwk=G+hT3QJwal_4%BCA-uUIV9IM zZ^%+_u19+Cqn}g%1PDTX=Oe6kBXv&w^H64E{+B`)^z@Q(aH3T5Sx*M$Faa0lmyP(F z*W@!$4+)P;o#+O@YKVw~DVXb}A z8G_%Cb8F1jNtQ()9JaFl)w(ip=2@4%`Nh^Nq85wmh8K!!Mwg1q#|d%q`$C)#Aajo9 z1tP$yqX8fv9RQ+NsLm&LFOkjr1JFe9bjf%jt{77)t{zb+E(7n2yM3|!a@1vU5o?C< zu37Q$#Pp?g*rI|Ym83XWLEw&@6Q9<GkjLivNd*$u^GJqO+2#of_6!7}TuWGy_EH(eV$OFcib}``0tNCnukjx86t4sO~b}sXHKQ^WB?9+@Bp|N8rzhoXN{}_LT;MvYuopGuC@|jmZ zubq(u!B~JxQ0FM{KfAgpu|0#M9}A01-Als+7eN5QiTHb*>Ou$kInAJ(aIN8dr@oPfkaW&T&SQO^ zMDEuNj!AV_26|&1@fIJOhaxy8i|-=e%_xtw_pCAygz&@f<$TiXLgVA*ss}pW zXRg))XC>x{MkzU>UTTi0ot7hf({qGRMvkbJ zVgJkj>)?8Q@2i663f5&|5xWdReLX!e6r_6P zM|wZB#m)9tdP0o(7?xtZ?r0J084}Zvo4e^@8o)`VQGX2t^#KU#=>!Dz)W8qjkVYP~ z*w8JFJTV?D=v^WcGmc4*4^Z#{EbwKnZT{vpd7pV%rZOhIe@IMbre@0@S^m*HN8y+CNUE3xqJ&DIotn^zI<28Dkb+S#Rdjd@^+ z{gP!k+3jAVkyHeZg15)9xg4`r!GWs~Pxrk*=^+x-NyQh+)~(*G1B=%o$=?cT3yloB zu}p}U$08ZM$az~2I&JP+rDVfGk1&<=aDbqmZY;_@Dg2YNY@xcY>Z2DHUf*n8+1nAe zTWpj)jFXOt&p3qp*Et!t&%tvs2VVBI0Heob2n@ll9LHwF`N6z+j-43a5C6l!#}|}I z@W|(;oWiq>!~3k@9CQkRwE3mI&k0x=@2KeWfXD6NTj*;2@pQcD*A|9rlepgLe{;3~xjq9)pK|DCEq8pi4kk zgStQ=oKAg3_BG4E0$+;x-`;9{^dNg<9U%|t8L!~n&I*Z6wt0HU(~Niz9vR5n=(Nh0 zH8Bs<6Q`H8Y;Wj(#pr`>4$An0UU0LX`=OH-8D+XNVqTOv$+B)3Y=SX9i>(^KJR$OC z9jwc${-r0bLs5wt%aO-Vm;X{kN*plCSUr&!c_Q!Srj<7D_3d5P_n1+9XWs+juAwF3 z_7OtdJW`0uqI1NFVsVN}+#s#Y#W6Xe`6%#vSBN`?m5AF=$F->I`d%~ccGw6((M>}D zeu%F1N)J&UtsPL7_Cd*<2-jc=s5jhwiSR&tP9=)U8S^<)o{SbanPAbb2PI$@7fv%U zMT;V=XaGUc^-MYr;3sx6l>xKP(83hvLx?waYXSsChhaf4rof|zCqA_wPJv2k-a9m| zF7Ayc;deb;`w#DBX|dld!?IqT^g+>Qqn!_#wXeY?D?{$T!H?=Kk8dK;ius_pbI&yL#=d2rI#Tc|N_wM= zE9DmZ$5PA;UG5TjARN4}Lm(0wdmawa;a-)OKux&c7SslPIW8dGQbi< zC}=ptp4(zM@9ldW`mc3nki)%aQD4C+Biy^#JCd@_)%?didII6axt#0XSVzc13t7%3 z?^ z8>+a5uq=64tq;%M0U+{_+;8Je(hT>9SceP!Yq3#Y>W!Y1@6@|=h5>&X7F_8>To1r| z5$h;d@eN(4&AcsSnP@erShRdch`WaYtPB_8>c|}NcfJsN3hcC7qugUc>@rZUMlz4B z49Z>+l_PEipt=)0?*Z?YsN>eq<)V4l>9ZUQ-`Fn+HsmIIb}R)cCjIuX*pxRzW0FlL zF|IcN$OytkE1mgmuh2Jmf)c#08HZL!y(;@ehf<7*?)@w0MyC8`m!3J>;1!H{!A^cnl>k zZ%q2$p)u*{nn%uz*k`>$qT?$K06p*5W!a2?Ur+P?=)6Enr}tWcJRLn(qN2KTY{)Uk z_rZ9JbC7oo#)-`Xf!{IaieyS41(j44^N&=K9?18_Yed;)00r7cjFKdo+wsE zRNP~5z=$*m=;tHb2EgdF{3P-qFYtWIoo9eS<1j7GRY8nJ_7>RG6G4IlaAyNS78bl- zGIZ9=z(6pL1>kekQ>^`uy@hf2>15Z#0C%e>?9G4*-wU$pRkuAEkhd7ik6^rinT$g* zI3DDf))Nx!GulFdF48}%qq!mH7w0PsVJ&rG zE^)!pNdsU(yhf)e*ycWr0L$U!SuXG4Zwn|Ln*oHD>x^nGI1d1119)cI$hM)J-i{&fnOc%F z>>+=DAgrYk=uUvl0zQLTUIHhE0&=eeWi{#&tPAD)d2{X?+tiGYr+@-;e2i2IweZY6 z=%33h^mk`_JKALd6-CVdXPowXOmZ&wu6nYLIGb1GN#17)0768^GX1#Ml=Jlt6#HO= z7?(1COmg49T>#K=Fr-g{-1v+qbILhL{*>z&yW7yOA)u>u{d@%|koWYmpJmAd`r%~q zByR_GCZ3Y@DL2EA{+A;V;t6Sn`@hIrS7(BW9DhTve`y|k+c+dq*M)pt16}(v-Q2hy z5l`EBPv+w~AS1$za+h_SR_X2CzHN4U*Y64+$~Y_@ep`qK2MO`O5FzdZSh+q-13(%P z*o;_|CmN>M!{B_n9O+|1R$1jxvcgTN6{AUfp{nOG0rj9Jo~q%V6) z@c;-4jH(Cn!-6-N!p)dh_w4f_aIJ%%z^De``6baV2eB6FGYZdDyH`;3{aAQ+Nx??q zZ(hT_R?Ne^EW@(o0bWzd({05fFzQlJdr$~K-)QWmIxP1Im{DK*$tMReDBoilP&?2? z9s{1|{LTU040;UI4K%KB-=yQ>D7-(1GES$X<3z!p5A%^{jFy*WZUQy6_^v)!sMkp= zH^&gh!2g^Gz-@gsuN)SmpB;yfWlWai(XI@nZbV&f15%Dzs~!$llN2>V)Rd`3reL(Z>c{KX+JbuB1%2iX2l z>RK4W-s0j20)wM%9wP9nmu#53#%GY@E!j(_H#!IRZ&^}qF&7t_jYUZue;AKVNk)KY z9J`ovzd8j#seM;E3$t{z2M{L`P5`jk?#N^6h&VT(VD|Rr+&8wV86Qso1&xof7jf zuNe<-rkLcczhs|Cg&lHdgGv8|+E1ah=f!^7QYU@g9N~*4JY*(K^VaGOj+jT|Y2j{lU`nfd94m~psQTjO&94fg4}XYhoiM;p8rkf-*JwOJSI zbf$mtFWPe&)*C+$)~KuX`mrR<7_)|Tm1VxG>$edtdoLDG^eq;T4-n$ffkL#?fY8k$ zIbzQd0GgwA$_4E^F2o1R@@#v7d`IsUwZ`lfegHt@mgm{-?aH_3lVxrQ%_##ukAU}M zsN-?eb)WxYan~E)MwkGY-(}pnM1g3)C2$=&JvE|7V5A>n`^VDj!NDfWn-S5Xt42h9 z^)Q%bu>+0#_&<>;I&mhBI-X3yW>zQ5LK&Hl&=bqx2k&tnz{Vo-cN7qWlx`vk_o z6;2lIZOoTtJLxUM;qj(8LGTjrDwN{`eIig-TX!e5d^Rg&Wqj)s=FFkK7W&pIkr#Q^ zRO_BQVAETm6hiqf8Y|2I1&k}j5bCF$WCJ6|Cs@$9pQ*ly0jF+kN_I|`1`3SNfx7N@ zAOkD|BP?i-qK|jW&M-cUHLj%`xu=lm5kAy-xDt``~wB zpRhQ~hYdj%lzD;do5(XZILptq+tYQ#)w<=*ArP3~X_!mml$S8u^7_NPy7|cU*6Sb$ zM(xE$;|h(=+=r$aW_)3gPK3v?R2q%##-V-=yq<0$Vf4`h`mw@w1#8SG zZ;U&m>_uIt4n(-`wOL<361+w{n_ViN=_|z3{e*b3za6OD83+J$SlB?&_@DD^z-E^Q zg2n>`5%~CK=7=!>KY6&eQ@cO*mprlih`rqHK{+}1tajw7Q(`_Vjc5Zw2>?Mn2GqdU76QQ2SF{iS zV;w95!R{{jxeo5i4V*|EtgxgWprQfyWnE0H(TD@Kx%3^q7w<6-1V9+8gLyDPRec0f66-|W zSrrAF-U6iv9nF*$H=_{+9-jdwz`7yk_e#fJy~GwYe3F@CzXIW=_^!KeM7&zLcX!DrHMHt?GbEiD!`c-;4 z0Po~+Ltj6E@tli2I<^o&dCIIO>xip$%f42ob3YL0P%i6s1b)zWHcxUz*FW+gFK>e& z7?=kejXyN}(9;j^^Da;>_pj*W3V&8t7IeI_bbyqqq?i-;t89@{CpWC5fAsI=@2 z0CY&$=ni;;-k+N%b^+Av0PV$opRoWwqgUjKzX5)>AGKc}3!ro}ygs|Na`%DfXQM?<1hzBFU zvocG@6@vQ!HZ5Uq$%0kP`U=cs(m8KJ(-K7q~m2*{4?9 z*h;vSnFq+51fGXY#<*YkahJZ_)yF<7gIFg*CKfpop8dE8d65!b^a+%LnGz%$3_$sP z!sD7c067=Cu;MS)D>PCG!Q%XrNyt+vy_p$W+%-Mv5%At3TyPWmtuN>*QzH?MNr#tv zsq~cViTnWG4x#K7-cmfk%RekW?YO=^)&rSd09kh*PNHmz&EDJOT(&wlgJjO9+-+L0(+VR*={)A(n;~n7SAOPf7X!9;;XJ4IsJ{#dH@c=Z1X2v-xH~>9= zBHts1au$oH{IEQ7KO9Pu&Uw+vwL4HFvx;@Zy7 z4)9bH4ua`H6)V&$VArj8EjEZx@&#ypn#s?$DJ6hu0Uwr zk9xl8(AzMc-9A_bWkS>F0oVADCwR{ZHgP8Ct2@eg#UwwEJjWc#R6Q{d z^RkStPwya4y>4%mfoRXUdj1?Ah#VT{Y5%~}Swtfa^xC)aEbVcU?J)UmJl0i~vHfd5 zA9^(|U%Z(j#2YZ6zYcm8(L}ERq_ph;0CWIA=Aa!6-2;!%ggJR)CxFd%dWLxD0cgun z`~Ty9$`f}4BVPaj5X!LZL*PMh^$PgD26_YabcIg(N^HJp|LV_&48muD6oe$rEq9}H zYhct^#+Fhj%5u(#f)X*~JKbqa3|hJaXUUV0obhKKcn{{|#0hu6PZwChj>+@<;W?U( z^5-Cy^?tYycX0u+@@{%!8J6WKUgU*$o=x7YgLSda)4g4Zx584gU*G=TCi2E2wHI~W zR8CoY$hT$sGkza#_$B5qaS$Jz%1!Vtf#>?UQJYc62dL{FlQ4{2*|!{bSa_~>pf&# z-$(N2{DXp73?;ggHrGC)oO8Dy~RadonsRyd!4wgz}rw z8UZ-jke*FXh-K|jC2yJ55ob7z#s+?nU#`RYG0NZ6X)w>70qNGvV=Sk8cdvjT@W_fw z>1SEzlyVSy*Gvn#W^28^M_mNoO1Dp2MVYJQN1&xXNZwZD6XiJM{gLiE4;|X}UbNqC zGa0WhhdjB=t81$#$jeyHD1V?6?b5d=#}*0JZD@qO6lO&1 znov99>O~Rj{W!cW1@!8;BAZn+A$(oO4_5zKM3C}(J4VX1eWADSd??)A^DAZLOo!kr7(?WTon7D&1ZkiXnP3*^)cXz~jhrny&&(T}J`(uEg zHmIxICTBd`arvyYPV@+htnWMqIMZfj);> zdDf5L6!d)$3*G?cNwF!sr^*t9Bb$rjn* z#7Yic*8rrilCq5L-y2?jaAejl+I6ox<+Pi)ijid!YTpC}&t# z*~KoeEh>Wkjc^cAj=H>>BlhMA8}WBQ_)+oPYdPYZS$SpG_wKdRjG1}jdF1I6hCHw2 zlwIfV@EB2!!lH}CbFVHcI^7c8_asrEw5-G0v97uZqV9bn{2&mfP>66)n~}|8o0vHh zdFxf!#flGl(PJXp!&4#;^0Hbl7OGZQ*z=ver@KU6;CTqVot{Y#U{W6-=n;5nCU2P^ zyF=uC0CXKwF#?axzeH~b&riVnVFE4FFtF5q$7P$*I)Oes%SHeEOiQy24Z%Y7p~D5Z zPeg6$r6i%QBIA9~QtZDd!RcwjNIXr978I*}&b&Mk$BY-k@rqE_wA0@uX$BWQE|geo zPryz7Ci=<;f1Ac28Q!h^JqdF#kctHi#8qGxIdVcd8{ z=be%C@$BYx_RBXes$4i>$qV&VhQP=XkVJ1Ew*eQGx-FK1iSGaKr41(YwWz+5-#Gz}fBJ&yHRyZjq~x#XjPh$aX{{hEdfuIo0yjNiP* zd-ib`?gNlwlb!l`swdWI(7y_dadEe!UqX=y~oGZk!9Rl%h z_P+)2_ACT23V1e0^Z>C8>2;J#4ih2?lo$^Fpm^|(2`v;azqItA0RSFgTv|W37FH-LZ8=CdksZCO zRpKCq!c^eM{b~Y&8pJ*9+abM^-{frzVspiwu|jN$^o&q;%P-M8$t$j{@1q1*jzikA zc1w>Atw>lrn!E4_@{7ekaf2zX-VDt_$c*VX7I6J?X}xA0sB5p`z7MR}tEFY7GKm5U z%Ee5Br{Fs7fx`RHJKD+cp6zMD^X4@s@x!XY~QXL*R19}wWF%yg5YK~iuOF1{>7^de1 z0AUWsZe2sz-5`!J@+eO0&0T79xhSpvJDgYRUKG}%>6Zpz}B$lI9UY`%2 z8=ytnrub0_lX>Z#0tm=-7>Wv|&CxsXo|Sx7%Dd^w?WmW*wB}=Mjz@deb~1l1=7x68 ze<^bzV~!y7?;J<6j&llLg4Q~3!~@ADbGfo)BIHgw$DWim#xZ7Pei-w~_meVE)p0OSyx-odbCkfry*`AKxL0 z58kaE7=NAWw0v*sztCyx>vY7Hpcsu>>U8D$%xh~aC%UpR{1KkHTz%VW5ku>^2VWZ- z52AhN;_urQ-#-Nu^ri;f_!s4ua6YiEvW&02v~*QWz(J7)fRY|6L?$RJM2Nn@2wUrt zBlZF4kV2oy5sTpE$=`?XP7?5J7h=N)I2mqqo;bPH{{Jy}gqF_86VXrSi2b_|d4zJk zJLiajeT3*2C`5J;_=9f-_{aJm6mPt^bd@ozNG}ATC?0z=Agpe!e=wnbfS<@IM67y2 z>WG*}b2kD6g?S8uXkBzwmsKJ!ck73Rz5~jg(D#SCq$+vY{@29M7Hex4w(a&Bcy{e>P7KDTZE3M|hq7pAb-I#7a! z^K5@AeGmkHq0bwXx9WsKHq9zKsjkf z3y(LSgX035693W(;GI@ZZ}b+iE*LX*SH;}3ItMW(<`_L~lqI;n+4+JQeu0DQbr{(V!o6^teg6nAEHTJo&pDeO*4o7uY3IK9a7i8Ck01w-ZedlUCTbVBz_V3s1K^>+i zx(0^Fg;PdyTvZmO+rEX8b;Lh7>U>Y;zPs=2jdj=##3LCNwO>E?I5#l<7oa^K0{QCt zupy`$j=$bzGel_l*|tF@;k5eqU>^}Q2HQMaNw(h=S^qt04?JT!^(Q{FvAyFh03aEf zsxK#XGV=C7|MP(?9n7$8qyESL*~XC3lnD*JpleBn&qcnh>(oO(zi?_~*KMLdz{x;>l(#{H1B4jbTZoWO05Usq zvhYqjuqgn*IRcF6gJ^<+-7W?-Oy09zLRyp(>vG72{Yaz&AU9$ley<9xtfCj2T5ig zj6}QTyt5OFVL0yJZ*o1@%yVZu;V?XIfZMVlGT~7u0sHlGhKpQeQf4U@nAQd`--R;C zxQGJammu#&E|h?$U`W^}m0`+KDQD&Xu=X#L3J3Bxft+1J#fOWVDT^S;=Rmyc&1*r~6iurhg64k8$lJ-cb(T&lmJ2Cn6l|;AsOx zy@ZH*VU6hZ?1I44lz`Bf7+T+DBhg|FE5}#=1o-I+@PnAoDQrj%BsQL&_?-M&E)>>T zoOH%K{6Ag;L0vrnLCyxH*#=f#vpU!;Tb=?V>Ohzjd1`UvHwStIM)-N!2VwX4GzEy6 zUb=NisrVDX=8qt2^k=9j{%bG+&{rXM*0S``IE1;hkzPKVB@7>x#iYK>GGGgfs~Z#% z9}3UkDwJ!i6AYJNkvb+pGW!X2wR6M=me4C8t2c7&d&}}kr6M9Ob$Oq#*mE2J{rh1l z$;Dhdf#0Vc4A4Cw{1s0uvzldW0@~z4dJxEiN(hxyjz`S(7j)K|4~(H&l}WavK4X%{ zdouSto(nGKpnpj8U1pv(`!T4=^emcwM+M{UEzs|{Uq`n<+=_hzN6oCaw(;lS2w+zU zWAiS6kE0Tdl*#C@*hL1p;R7#Ijszr9w;w1A_JdOH8>6QNe~-b6x0-t( z@OPq&14sB|*-^mVdWYA++^YjaOS_1;wC@Sl<#*KFQ9@;(vwgbt4r}RE&|w%)#<3vp zdn%_rc@|k0=KB*kT`8Bw8)JVtBj#n88Ohyp+#3LpoXfiP&xUby2cDyV1|Y7V&WL%q z?oy%Qe0G(eV-F!PvwH+b`FgtU>ifqN8R2gKqJ0`-ZvSLcicJi#dP6MbE$5;>AAeI% z36D)#0(slCs$`uv+5_uGI**^%0~wATtc?s~BcM5*aELrKwbD7*YbJKDxX+G-|O`+sXxFdILblaJVXyAA%M_$@E+BzNW?t*`*HtHKb^LT7GU8j zG)##E6a34)6=>vkRS$k5rm&NwheuC5i3NjyJ`itXgh%j$qqC%fXS6!8!C~EU8wAB_ zRtGbRH4z-{=C>vU!fuk@FHeYN@!nT^+7D?@`dv9L=;~j@)l|B=cYg9 zccC?xF_bm}5ACdYF05EAr?~sfP$n9p-O9p}z+;l!Cq&+;V>8BjZ6fES{8p8jVL%cr>BSIE=WG1y z!ty#63)EihGumjh!s6MI|t;aRB9Tu^9-0 z)qaL{GERmDe(r@bu-l9e`->h%nEHJ^os;Oh*J(-A_dQQm!dPi(=+oDv)lHJ-efrM9 zqShIqNs(Bfp99?uDi@{%Is1{#@PvgA`ERlVps;H}yCGv=hce=Wa(6*Ce-7DGBE1P# zlrAYhwS5r7yttOskJGG?j^wc%Z?RPXfQ)q!{8X0L#TnTY9MoN235@HA{w0%%54`KhE-5DQ{uiG=x6%69K(`V?B?w z#r++W`PV-pkR?C%K-$1GmTOxVGtE@oDS3 z8xP}&erEa9elKhjA8NqoGk}#Z0a`KvUJe7u908!o2e3J|Nr;o!*HeOT|CEvna0o(y z{V%Bq`+f>H+Ve60QIs3-aE_S%68QZWd^I36u*)_P*Kzq&vj@jWD{vs?tP%^Lk&a92oaKz)HT@MDj^O*<%`k$+?H%yJ{K zRE~I^W1j~&08o98XPblHhmuWzKZ*COwiASMH{-_U$|Tl>aFAC$nR}j+l{pAc#;cA( z2zVW?`yEjHUu0-*S>MH{;T({7#O3Z16W0pyORV3=76MIgg)8pz_x(zz+BzUwDn* z;^N6@gMZYjv^Bg$?8M4o{XDq}s-tL_+>aa(RGSnOZy;Fq%=u}+< zlT{6VBt<(o6aZuIA;_4WG#=VdBphS|GWKuNWYgk55njwjy8JI=zshmSCz+Rj`M;L` zD~z2c-duMp69C!3Pf+9>zQ0~BC)wrs_gF(3VSIN1sQVFew#XI+&m*U`{V!;XL(rLU z@>u-sp1v=6aqaR3k(W31l1esy1N?-I;n*}YXxluA(Mewe{8Y-`boALc@SlY7{~4oi zq*u?jF7vxgVR75=j3Ii%GJanH3V=?!jd|pAvn+Xl*JSbp?~l#ulsZaPlHN;arhjp+ z<9$XsYA1~SksRxo3olz8*W}GQ$~Qo##kXg5T2nOXwPNu(K+0DDE8o0i2QNqH(E*?- z038RoIk5pC2voctpl2Nb&|3T7V$jL;_WR7o{46)5O^*2fIq-W?i2uDT#N_`Li+)e7 zDN1;H$sJ}7j)8Rp8mEv#OuxVa)$g_H2|~V(PzLrxVK@Pc=%B8;kR+$&{6qbae~NUs z8avGfeqxg6;~5*9EY9^X$YxSeF_yK3{n(C7jhKl#>UmQTS0(_0G7-o3@pOQm0KK+o>{IK-rvBK3*0Ve<>uo2qdnhw+REM?T@uKCBzo1B8EHF7zxl6NK42mgS zJP@S*02ak^9BUzAD^Z8#kU&h<3jj2JcNYZdz|TA=2QC+W?1wqzDvZSTy_KlMewbHf zp;q|agx{9pJ!5|Ibfev$uo^q;4YKXe!}p0CJr6^$XgTvHk*Dj>g-9Rt*+N>j%q*t# z(n0atg|T&(HpcFdvCguO9C_u~zvz?Q@NS&#V7y+3v2su{D zi|0Owe5aoX7nS&l(YrvN00j?t9wrj^s;1Pg*F0Wzq^F)^2%x73&oLOlsIjI{T!OrB zL!mj6WQzyS5U%7c6$hMJxs&Z%L1n5b>i<}NJW#eu75)Lai#?6##mE~ z#{{gmi(q9w$$rD{O}O@72cYQ=jJJizTf)4M+XMmM;QCYUwNI9%=k=uBoV~A32Wbe| zG>0Le@>pg50s*W+l>Ozy z&KwZ)vJA^gK6-slXC$ju00?dG)3tZlI7UIxV2=RdO&F`tm^-ck-mC zPadsJgAbkqvN^sGbliSmMW!&xmq#A1>XBftD#^_Fq1V5(L#4(z43UgX9LhBary-i2 z5nzm5O0n;QTgp028D>7Ua?G%fo5eJMly3o6es~@qH+^iA7!CmQUaK52zGaU17@=>I zTiCsS|yT%6q0DjSSSAOv73LOnjmK)u^^@cM_|kNC&0d333aiKR;v*4|v)>t=$3?@dAMX?|-K*O&=1w9gZ=eQ`TDYNW>@a2@;-*M0T+ zF0ndUh(+B`(XTk=Z9}#wTAf~8ye7Sbzr~8s)AOuN6RW1Yyd6B;^5CFhC{A+ z;`!G>*!Yxp+ei8Eo^iaBr)8iW7}3I!m9R1>&K@#$vnO+}GL$`oB6kffxJIQ}3p*%< zY<#v1Fa<@9v;vN0$O6i~#qF8+^&zCbSg4E=#8ZFg7yu=5Sd#5tg3(BD@2ob3u(P6OIdt~a1Y z7L}-TwfwOFkK2v!Z#EWW-BqCw8tbaA0LVlR*0-3i4ymH;^G^UEJNSv1!?`NuX_-8a zPIY``R8(!$_Mwp)8l)8!A0(ukVK5M+yHi41sTpzr6_iq>1SzFKLOO>|>CPdfV`v5# zn0I)dcdc)IYkl9p^W&Uz@4c_Zpf1WF&(j>b$mHpa8)3n3NdQTAA{*@fBsydFXV^4&z|DQ# zavq^nGr%BzyZzcCy7}bWk5?|f$^)0|61m_#iO`CjQ1uktsA&6${At4@?)Ktoyvr7w zJQDr2E}<6n7XY^$v{afcY+04-`0mDAH3xCPj9}|sj|85Jw<-eudIfb4>U~(j{`k#c zi*?x?1L+8V0{BPdYR3o}5YlYCE%{EsOYa##J+rF~n|h%~9q+}Ky0iaq&S97SzMFOh zs|U5s>YYf$&x?JMUNI=$#byJ!fv|3$-cDuQw}&aKMe32?LhT}o0?Pe*wY~~{`@tEL zTrIKU8Kd96D=cpc;wyy*n9^heZ_$nb#{XRb#aO3Xaoo5e`sJOrbkDm;R^!T$nWkr< zWvwT~M>Cnr**vbDc7Ytciw>L-!x#T_v4Z+xZQu$o+kbQxuYm2L7^T;#Sf1`L5_{>Y z!!uUYc3CJ1`}3kWpA2|V_mE$0S8Nd7PF)wMkrxl+aI~b1Pa~fq?@YOnQ)}GqK@&Ih zXl}Jnn6L15^!gU8TwttrbXwMni)r-4sn94+jg#k2lfbHq!yofMNT1$`N_0iZrq}xS zmJ`7t60hrzLLd2=(tFzEi*RW=a#e_$MI^!LsUDnb!YYDKAyxh2TzSiaP3HKWaFGTr zc2b6Ur|x7Ec3cxIoYc@<-q`m6THkg!+bLV+iv7#;wxiWP!wtU%b9zsmA&`ycSqxcO zV=8qJ_?^y@F?aiJ;Jb$TFzOn=eJ0%@+DVh8K-Rxb5tx{aIh%)A!XI&IwANccYpwk+ zy)MIK>oDRk=^je5u;$XqFZU_?WTio)K1oR2IxP7qYuda>%Mo7Eby0JN-kB>rqEcqD zi-NF>KvIat4@|!&!MPnGSvYt3V!83tTD1fFOl~?orvJ3L)e9db!nW&4vqAgN05wg_ z2TpeA1}#<3kA4KXA0b-fZ}D_k?`#^S2&fq3#$QV>edDjWHdFCKWQF?$7{m9}VPk^v zllpBvSI7(z5zQmnO%+sj-hx{4D0xF72yLLtq+I$|f74MHNwnVLcmO{KC6 z47$sOU+HQ@^U2zMRNB%_YrsaW44O+DJe?{QFp7D!6Co;OiTa1 zgH^trXd8Un2u<-;y#Sz$q(73mff%%*_0_%6TUb>o+N(Rnjq++{=wV{T&(8+BvaW9P=TpcO(Z~8-9IwzEN+oWa>Vjbq}gyTU1`OXP%v6@4q((J=zEy7y1h5Dkd zTrcBYySZU_do(G^WGe0VL5JBa`q@=zvOmIghPb=M*>H0O3OfWmF)aE%mZnA@x5`h&=f6((F3z$Hfi0z|H7zUMqSJ= z$n7ifNRF{y-J^&sVXDHjuY`AXRW~XN$gIuwV|QQ8k5d9x1O4{1aej8iD^_LXrmG(4 zfe(i{9*_CF>qL_s7wx@qBx6j;bP^lsQf{(HphqJ3l?s)?OG{9|2R5 zb7h+htK=|Ye5W0b?zm!f-kZntC-~hR8kv3PS6^*tPl8CLjC-rb{?2JYkt7OHqP}pP z=zxf3;_pZjR1iZRdtShO8koiIbFdE9crX9@{dwD{+q^vKuZbFO#QX(pmU0^bbBHj! zGAx^#TiCmrCKwzDghHbMfL#K}SV0F6PM)qTq>=2JXHf2b>L{8pX&)13ozQ^pSDQR~ zyjTLTq{E}-l+SMS#F=j{-&@4e-hMJg-~2=<gRA?zU6}+oN;JXB$e7&%#qc(>{-mwV zqo=;aqSSpnS8#_AeonKvw!3i|FazwE67sHpS`%A{c)dC+euC3-;VZu=XYy%0I;=g? zsxl%{2ovnI5F|}ftFYE=-q3guyQ1Ms{*44C@iP+K>pSmAm=^W8Z2c`qcYg?maz9ja z=wZzAS1U+0Jweef61^4o9(+u&=_pH@g#HZ`(K%GDOj&G=_~lPK2Q^!0Ib z^Dmggj~ShgVP)T#j06iS+Y~-EiZboJOMFe;D%V7?D1S?EQ;tFN!gcYo-p0X0;+T6F z2Z51+R5t4+MWfh)X>=EKvbRPB3;)4NKTfeQgDSP-Ab_Iju?AA;V7|Z?TeJ)(FH~ZF zjzOC1e^sY_g)8|gG~fk_mUstre_leTkX(@0sd~p`1TkVZPIx0fRs-GQ)~2Se!rlU1 zjVIkA%rG}uowav4L0(&C+FA$W!pffyD$HlPWkR{u@HGKG z2aEmtWx)FA?~o4E<03<+eai4bcTQiUKht83D?&-2#YWYSXS~TsYrovk1%mli$h05C z2J(@k5e%rkl|gjJDPcxzOwOyiuuP#_#t#jcJe79{nqo4Y?GD?Ttk8&7MG8hfi-x|? zB*RcZfl=YhbZD6YA@7=-sY$nA_mTVi2Wge>f8W_+c`xP8>6J)TmG*# zM{!B8Du(DohVqn865i?xFL^{igcrb3}J6$f<^9fqS9syGKonJh~K!(2Wt#t>(64 zWPg2|bYjqOYuuVZ?O9-_8!p8;P5e=e2kVWs*6RUb9ZQ$$;a|@Z!ejkZo#&>il2gX8%X#?EiaIVAXoSq^1B4whLvsCdUbez2jDR8Z>08DX@|B zyuQ+jK*1%+Ac{I(x8RKj#&<|}$ZF}z({LrA(ed^Fs;CuYZnpP)CHUJLjoh>^)&5Jq zMP|JI;deR5Sd{Jf3oYer7NNnE#DoM6+W7Ak(qqc*y!oDXJs^L69e+Y&@)^(txhTNCI$x1mh|$0r`erSSYc{?`q6ZPuHghT8@1UlL@prO5D(e0|9ISL& z;5cs?^ERuaY+TF{H`4V@3*_IQuU-fU+A0YuGIGg5J2Xh=4gZW)8TTGYZ?anN9_GgG zvWw7?{h`a~QxE`){*g6a;K2#cumy9CFXQYkr}IqXWQV7ZEUkdQ5lguzI^sm^q(fSQRmkk@P4cIV26B$b3rzEneJ$T8}t0v8!0~mp+-Drgjhv9T;CdA@CCa zP%Q+4jI;|jT?e-g4aq+;QjfZaV^R~ak$e7<>E-^^lSf`So0v34W14Z(1lTPoAT_O?m4DbarLJ@2Hs?ef=0 z2{2mHRVI4pxU-QXo%9XVB%`eOFXU{LXKP$go(4PdoElPT;dF|4B_NgSu1sv z!+CLAr6oJ#G=qA`p}Z0Nz%Q8j>^e<9hkfG*%VDuRwYmv~m77z4Gf1bUY{k#EiGT!D zBH9=F`-~6ka>Dy0Y0=wDwn~Lp&jRpt3rj4S=wF)1IHiD%n{AUm8GN(GF6yak0RsgI z8dbcSo@8N73CmNf07DiO!$P3Yht%>_*J)F$3! zydT?cgdRSE@ej2=bD)$e!RZ^qO;}gt;p!zMBr-H`+ud@fGbAh9s^2mKuQBox*vGax zw&!PQpAag{&93ued%p6-&=ArbZe2dx|H(}O9yEL zXOaT|UUmp377Kbnx#oj)BPt&km4!4pu<3csdGcP-2m9 ztZ_fSz(^6ZwO4?z006TEOPAQppiU5v2I~$VLJw#cbsb5}4Uo8X&{jAWeiIT9yn+DK zp6tbH*WD-|WQrY4>J7mp2X zL(?%KHbf<-AAfmss&#m?D!Axi3>vo3I(-qK z@bay`sWZrypVvLH8eahyk`>!$2|RU!$tNiiiXTjKjWut4Xl-wxwh-dPTWu))-3)?q zk_@qYsv9VAMa2Y2J-e_E;D5Y#w-6vjz_=8jD8V>)j-QLPRpYDt=M*KJicJzthh1;t z2w31ZsYYh?1xDShbzJg=Ej8)OSy~a{z78q8 zL$J`olpQ%w3Qs6PUzysUSMN<#_P9H=c10hmrwY{<|7&1AU|saq4=EQ*b?Efxx9+NdiRA6K7DeQUt+9<^G<@aPL?kpE9qY`>ckb^ z5VBmZL}#ftdDgkfr*txinXF2!mhQtII|Xa8UeDOc-dej|-hf6=$6u&QD#}iV-1#1Hp1h6fjQ*^;~g z6h+K{9RaYl_akbc374?vgT7Zo|A~}6H%j{AbUs4Tbk6hl$ z{%E3qa&9z}>2J$bMj~Xs5&_cdau33l(jGC=Iw}%8RmBSZ{M<#{mg7D7%T!Ry_SV*Q z(@{cE(ra|Vkp$yRH|Us9){gUTr-TLpM7h)7?`$_cXT8yKvjmw>lY>K=4!AQu-hYq+ zv8o%LUl_;@0p> zfKX!t76Zk8H59AERcT**uJ0eF3us&7|K*TK^B^hHqWubkPZcVsIR=;AgEtp5+p6_N z3HSED{G6P4=OcFpKC^g_I@*~8`z?K>voPYvsd4UwialgIK-l`Fx})3Z4T^Co{#$UC*C7=#U#3aY1I6BZu~V&FY>O_l?1Vz{siKUT3-tZ+H1WvdxA6-JKw?Q)<*6TF2TvxE+bs z{1*uK)*c6uM`UpK-=ltLLICByx}^5T8&MqrV=-31G%mAIaE=f(|_#D)*s*I#Rp07ph>}(Jq}*^*4Qr zK<)0*Bt06}qy<4*d+eN2gIRe`B-iS?JD5HP6)K}Bmb^JMiap#3(Qhb88%gU-b)YQ! zPWu_^8Mo%1xOlUe&zNxY6mSdS?!N|P^s4^vN*lr?L1@^LbwhL!p%AMkB8%YbbPc;R!D}?e2~XzfXnUiXdzD^_(FSxPb;@07cJi2nN=B1aYS z==^u`6fs4ZlkaW-9yb`hP{EBWVn-U@tQ24)JL9^5@3uh)8abOzph&(kiN|sNV*bfn>F91lVQOk zET4T-N+VYgMBI**^j?T%c$A}>A{LhRgJq6NK7$cZv3;a(_%%-kpBTD Coh{G+ literal 21339 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 S{`)Nx0C*#(46T$g4*DO^c7f>t diff --git a/browser/themes/osx/menuPanel.png b/browser/themes/osx/menuPanel.png index 30111cb8493a285e85405f709413ba05fac1c231..8b6aa254b2315eae682a966cf7567a5385d8f237 100644 GIT binary patch literal 27161 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
@jqr{4= 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 OaB|YhA1ft|L;eR)@bZoT diff --git a/browser/themes/osx/menuPanel@2x.png b/browser/themes/osx/menuPanel@2x.png index 684a1afd1598874fc887d24e6a639ac40e173182..1cc200c52e54301e2d2181ec792fb856b1f32b88 100644 GIT binary patch literal 61282 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 diff --git a/browser/themes/windows/menuPanel-aero.png b/browser/themes/windows/menuPanel-aero.png index eeeca15ac80e673b186ca0bc637e53e043853acb..2145b4db604fc0aa4ae3ed554df989b04620233a 100644 GIT binary patch literal 28137 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 literal 25939 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%0As+y_3!hQRIrsRYpqGLDtgb#$1d6raS- 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 Coh{G+ literal 21339 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 S{`)Nx0C*#(46T$g4*DO^c7f>t From 65b6a27532bdcd3e1f883393342e71b43a27f7d0 Mon Sep 17 00:00:00 2001 From: Sam Foster Date: Tue, 4 Mar 2014 19:16:07 -0800 Subject: [PATCH 081/112] Bug 974413 - Call Tab's updateViewport when a notification is closed. r=mbrubeck --- browser/metro/base/content/browser.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/browser/metro/base/content/browser.js b/browser/metro/base/content/browser.js index f282233125b..017b8fbe22d 100644 --- a/browser/metro/base/content/browser.js +++ b/browser/metro/base/content/browser.js @@ -1356,6 +1356,12 @@ Tab.prototype = { this.updateViewport(); this._delayUpdateThumbnail(); break; + case "AlertClose": { + if (this == Browser.selectedTab) { + this.updateViewport(); + } + break; + } } }, @@ -1462,6 +1468,7 @@ Tab.prototype = { Elements.browsers.insertBefore(notification, aInsertBefore); notification.dir = "reverse"; + notification.addEventListener("AlertClose", this); // let the content area manager know about this browser. ContentAreaObserver.onBrowserCreated(browser); @@ -1483,6 +1490,7 @@ Tab.prototype = { _destroyBrowser: function _destroyBrowser() { if (this._browser) { let notification = this._notification; + notification.removeEventListener("AlertClose", this); let browser = this._browser; browser.active = false; From 77244b1221eb824bc9e53f42f89d4eb8cd1fce2f Mon Sep 17 00:00:00 2001 From: Sam Foster Date: Tue, 4 Mar 2014 19:16:07 -0800 Subject: [PATCH 082/112] Bug 967793 - extended notification binding to provide child element support for the notification label. r=mbrubeck --- browser/metro/base/content/bindings.css | 3 + .../base/content/bindings/notification.xml | 80 ++++++++++++++++++- 2 files changed, 82 insertions(+), 1 deletion(-) diff --git a/browser/metro/base/content/bindings.css b/browser/metro/base/content/bindings.css index ae410f4c65f..ced50744e1a 100644 --- a/browser/metro/base/content/bindings.css +++ b/browser/metro/base/content/bindings.css @@ -52,6 +52,9 @@ autoscroller { notificationbox { -moz-binding: url('chrome://browser/content/bindings/notification.xml#notificationbox'); } +notification { + -moz-binding: url('chrome://browser/content/bindings/notification.xml#notification'); +} circularprogressindicator { -moz-binding: url('chrome://browser/content/bindings/circularprogress.xml#circular-progress-indicator'); diff --git a/browser/metro/base/content/bindings/notification.xml b/browser/metro/base/content/bindings/notification.xml index e7f8937a43b..897d5c6243d 100644 --- a/browser/metro/base/content/bindings/notification.xml +++ b/browser/metro/base/content/bindings/notification.xml @@ -41,6 +41,46 @@ this.removeEventListener("AlertClose", this.handleEvent, true); ]]> + + + + = 0; n--) { + if (notifications[n].priority < priority) + break; + insertPos = notifications[n]; + } + if (!insertPos) { + aItem.style.position = "fixed"; + aItem.style.top = "100%"; + aItem.style.marginTop = "-15px"; + aItem.style.opacity = "0"; + } + let label = aItem.label; + this.insertBefore(aItem, insertPos); + aItem.label = label; + + if (!insertPos) + this._showNotification(aItem, true, true); + + // Fire event for accessibility APIs + var event = document.createEvent("Events"); + event.initEvent("AlertActive", true, true); + aItem.dispatchEvent(event); + + return aItem; + ]]> + + @@ -76,5 +116,43 @@ - + + + + + + + + + From e22760428bc11c49beb84904ca1fb9a372d04f09 Mon Sep 17 00:00:00 2001 From: Sam Foster Date: Tue, 4 Mar 2014 19:16:07 -0800 Subject: [PATCH 083/112] Bug 967793 - Move CAO adjustment of notificationbox padding into CSS via a navbar=visible broadcaster. r=mbrubeck --- .../metro/base/content/ContentAreaObserver.js | 23 +++++-------------- browser/metro/base/content/ContextUI.js | 2 ++ browser/metro/base/content/browser-ui.js | 1 + browser/metro/base/content/browser.xul | 4 ++++ browser/metro/theme/browser.css | 9 ++++---- 5 files changed, 18 insertions(+), 21 deletions(-) diff --git a/browser/metro/base/content/ContentAreaObserver.js b/browser/metro/base/content/ContentAreaObserver.js index d7e430f425f..9ba7b0a1597 100644 --- a/browser/metro/base/content/ContentAreaObserver.js +++ b/browser/metro/base/content/ContentAreaObserver.js @@ -117,8 +117,9 @@ var ContentAreaObserver = { let newWidth = width || this.width; let newHeight = height || this.height; - if (newHeight == oldHeight && newWidth == oldWidth) + if (newHeight == oldHeight && newWidth == oldWidth) { return; + } this.styles["window-width"].width = newWidth + "px"; this.styles["window-width"].maxWidth = newWidth + "px"; @@ -132,28 +133,15 @@ var ContentAreaObserver = { }, updateContentArea: function cao_updateContentArea (width, height) { - if (Browser.selectedBrowser) { - let notificationBox = Browser.getNotificationBox(); - - // If a notification and navbar are visible together, - // make the notification appear above the navbar. - if (ContextUI.navbarVisible && !notificationBox.notificationsHidden && - notificationBox.allNotifications.length != 0) { - let navbarHeight = Elements.navbar.getBoundingClientRect().height; - notificationBox.style.paddingBottom = navbarHeight + "px"; - } else { - notificationBox.style.paddingBottom = ""; - } - } - let oldHeight = parseInt(this.styles["content-height"].height); let oldWidth = parseInt(this.styles["content-width"].width); let newWidth = width || this.width; let newHeight = height || this.contentHeight; - if (newHeight == oldHeight && newWidth == oldWidth) + if (newHeight == oldHeight && newWidth == oldWidth) { return; + } this.styles["content-height"].height = newHeight + "px"; this.styles["content-height"].maxHeight = newHeight + "px"; @@ -171,8 +159,9 @@ var ContentAreaObserver = { let newWidth = width || this.width; let newHeight = height || this.viewableHeight; - if (newHeight == oldHeight && newWidth == oldWidth) + if (newHeight == oldHeight && newWidth == oldWidth) { return; + } this.styles["viewable-height"].height = newHeight + "px"; this.styles["viewable-height"].maxHeight = newHeight + "px"; diff --git a/browser/metro/base/content/ContextUI.js b/browser/metro/base/content/ContextUI.js index fcb4fde6f24..547f5106363 100644 --- a/browser/metro/base/content/ContextUI.js +++ b/browser/metro/base/content/ContextUI.js @@ -175,6 +175,7 @@ var ContextUI = { // Display the nav bar displayNavbar: function () { Elements.navbar.show(); + Elements.chromeState.setAttribute("navbar", "visible"); ContentAreaObserver.updateContentArea(); }, @@ -189,6 +190,7 @@ var ContextUI = { if (!BrowserUI.isStartTabVisible) { Elements.autocomplete.closePopup(); Elements.navbar.dismiss(); + Elements.chromeState.removeAttribute("navbar"); ContentAreaObserver.updateContentArea(); } }, diff --git a/browser/metro/base/content/browser-ui.js b/browser/metro/base/content/browser-ui.js index 31e65574a13..35bc704e797 100644 --- a/browser/metro/base/content/browser-ui.js +++ b/browser/metro/base/content/browser-ui.js @@ -32,6 +32,7 @@ let Elements = {}; ["urlbarState", "bcast_urlbarState"], ["loadingState", "bcast_loadingState"], ["windowState", "bcast_windowState"], + ["chromeState", "bcast_chromeState"], ["mainKeyset", "mainKeyset"], ["stack", "stack"], ["tabList", "tabs"], diff --git a/browser/metro/base/content/browser.xul b/browser/metro/base/content/browser.xul index b6b97e7b288..7f7e5fafc52 100644 --- a/browser/metro/base/content/browser.xul +++ b/browser/metro/base/content/browser.xul @@ -69,6 +69,8 @@ viewstate=""/> + @@ -399,6 +401,8 @@ Desktop browser's sync prefs. + diff --git a/browser/metro/theme/browser.css b/browser/metro/theme/browser.css index 9e957133b23..f892d6ce021 100644 --- a/browser/metro/theme/browser.css +++ b/browser/metro/theme/browser.css @@ -251,10 +251,6 @@ documenttab[selected] .documenttab-selection:-moz-locale-dir(rtl) { /* Start UI ----------------------------------------------------------------- */ -#content-viewport[startpage] .active-tab-notificationbox { - padding-bottom: @toolbar_height@; -} - #urlbar-autocomplete[viewstate="snapped"], #urlbar-autocomplete[viewstate="portrait"]{ -moz-box-orient: vertical; @@ -505,6 +501,11 @@ documenttab[selected] .documenttab-selection:-moz-locale-dir(rtl) { visibility: hidden; } +#content-viewport[navbar="visible"] .active-tab-notificationbox:not([count="0"]):not([notificationsVisible="false"]) { + padding-bottom: @toolbar_height@; +} + + /* Progress meter ---------------------------------------------------------- */ #progress-container { From 45db6abe3f8e7452abbeb614a5b61cb0b48b6c19 Mon Sep 17 00:00:00 2001 From: Sam Foster Date: Tue, 4 Mar 2014 19:16:07 -0800 Subject: [PATCH 084/112] Bug 967793 - Add tests for metro notification bindings and adoptNotification method. r=azasypkin --- .../tests/mochitest/browser_notifications.js | 95 +++++++++++++++++++ browser/metro/base/tests/mochitest/head.js | 6 ++ browser/metro/base/tests/mochitest/metro.ini | 1 + 3 files changed, 102 insertions(+) create mode 100644 browser/metro/base/tests/mochitest/browser_notifications.js diff --git a/browser/metro/base/tests/mochitest/browser_notifications.js b/browser/metro/base/tests/mochitest/browser_notifications.js new file mode 100644 index 00000000000..2213406a6e3 --- /dev/null +++ b/browser/metro/base/tests/mochitest/browser_notifications.js @@ -0,0 +1,95 @@ +/* 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/. */ + +"use strict"; + +function test() { + runTests(); +} + +function cleanup() { + let notificationBox = Browser.getNotificationBox(); + notificationBox && notificationBox.removeAllNotifications(true); +} + +const XHTML_NS = "http://www.w3.org/1999/xhtml"; + +function createTestNotification(aLabel, aID) { + let notificationBox = Browser.getNotificationBox(); + let notn = notificationBox.appendNotification(aLabel || "some label", aID || "test-notification", + "", notificationBox.PRIORITY_INFO_LOW, []); + return notn; +} + +gTests.push({ + desc: "Verify notification bindings are correct", + run: function () { + let notificationBox = Browser.getNotificationBox(); + let notn = createTestNotification(); + + let binding = notn && getComputedStyle(notn).MozBinding; + is(binding, + "url(\"chrome://browser/content/bindings/notification.xml#notification\")", + "notification has expected binding"); + + is(getComputedStyle(notificationBox).MozBinding, + "url(\"chrome://browser/content/bindings/notification.xml#notificationbox\")", + "notificationbox has expected binding"); + }, + tearDown: cleanup +}); + +gTests.push({ + desc: "Check label property handling", + run: function () { + let notn = createTestNotification("the label"); + is(notn.label, "the label"); + + let doc = notn.ownerDocument; + let fragment = doc.createDocumentFragment(); + try { + let boldLabel = doc.createElementNS(XHTML_NS, "b"); + boldLabel.innerHTML = 'The label'; + fragment.appendChild(boldLabel); + notn.label = fragment; + } catch (ex) { + ok(!ex, "Exception creating notification label with markup: "+ex.message); + } + + // expect to get a documentFragment back when the label has markup + let labelNode = notn.label; + is(labelNode.nodeType, + Components.interfaces.nsIDOMNode.DOCUMENT_FRAGMENT_NODE, + "notification label getter returns documentFragment nodeType "+Components.interfaces.nsIDOMNode.DOCUMENT_FRAGMENT_NODE+", when value contains markup"); + ok(labelNode !== fragment, + "label fragment is a newly created fragment, not the one we assigned in the setter"); + ok(labelNode.querySelector("b > .foo"), + "label fragment has the expected elements in it"); + }, + tearDown: cleanup +}); + +gTests.push({ + desc: "Check adoptNotification does what we expect", + setUp: function() { + yield addTab("about:start"); + yield addTab("about:mozilla"); + }, + run: function () { + let browser = getBrowser(); + let notn = createTestNotification("label", "adopt-notification"); + let firstBox = Browser.getNotificationBox(); + let nextTab = Browser.getNextTab(Browser.getTabForBrowser(browser)); + let nextBox = Browser.getNotificationBox(nextTab.browser); + + ok(firstBox.getNotificationWithValue("adopt-notification"), "notificationbox has our notification intially"); + nextBox.adoptNotification(notn); + + ok(!firstBox.getNotificationWithValue("adopt-notification"), "after adoptNotification, original notificationbox no longer has our notification"); + ok(nextBox.getNotificationWithValue("adopt-notification"), "next notificationbox has our notification"); + }, + // leave browser in clean state for next tests + tearDown: cleanUpOpenedTabs +}); + diff --git a/browser/metro/base/tests/mochitest/head.js b/browser/metro/base/tests/mochitest/head.js index 12da0251e92..181f0d5dbf6 100644 --- a/browser/metro/base/tests/mochitest/head.js +++ b/browser/metro/base/tests/mochitest/head.js @@ -310,10 +310,16 @@ function addTab(aUrl) { function cleanUpOpenedTabs() { let tab; while(tab = gOpenedTabs.shift()) { + cleanupNotificationsForBrowser(tab.browser); Browser.closeTab(Browser.getTabFromChrome(tab.chromeTab), { forceClose: true }) } } +function cleanupNotificationsForBrowser(aBrowser) { + let notificationBox = Browser.getNotificationBox(aBrowser); + notificationBox && notificationBox.removeAllNotifications(true); +} + /** * Waits a specified number of miliseconds for a specified event to be * fired on a specified element. diff --git a/browser/metro/base/tests/mochitest/metro.ini b/browser/metro/base/tests/mochitest/metro.ini index bbdf812eb2d..5cc0d8cde8e 100644 --- a/browser/metro/base/tests/mochitest/metro.ini +++ b/browser/metro/base/tests/mochitest/metro.ini @@ -54,6 +54,7 @@ support-files = [browser_link_click.js] [browser_menu_hoverstate.js] [browser_mouse_events.js] +[browser_notifications.js] [browser_onscreen_keyboard.js] [browser_prefs_ui.js] [browser_private_browsing.js] From 38e079a17564fc66268313bd8def4224199b34b8 Mon Sep 17 00:00:00 2001 From: Sam Foster Date: Tue, 4 Mar 2014 19:16:08 -0800 Subject: [PATCH 085/112] Bug 967793 - move all download notifications to next tab when current tab gets closed. r=mbrubeck --- browser/metro/base/content/ContextUI.js | 2 ++ browser/metro/base/content/downloads.js | 27 +++++++++++++++++++------ 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/browser/metro/base/content/ContextUI.js b/browser/metro/base/content/ContextUI.js index 547f5106363..0c9fd9636a2 100644 --- a/browser/metro/base/content/ContextUI.js +++ b/browser/metro/base/content/ContextUI.js @@ -22,6 +22,7 @@ var ContextUI = { Elements.browsers.addEventListener('URLChanged', this, true); Elements.browsers.addEventListener("AlertActive", this, true); Elements.browsers.addEventListener("AlertClose", this, true); + Elements.tabList.addEventListener('TabSelect', this, true); Elements.panelUI.addEventListener('ToolPanelShown', this, false); Elements.panelUI.addEventListener('ToolPanelHidden', this, false); @@ -367,6 +368,7 @@ var ContextUI = { break; case "AlertActive": case "AlertClose": + case "TabSelect": ContentAreaObserver.updateContentArea(); break; case "MozFlyoutPanelShowing": diff --git a/browser/metro/base/content/downloads.js b/browser/metro/base/content/downloads.js index 9a77ff61ac1..48788b86f62 100644 --- a/browser/metro/base/content/downloads.js +++ b/browser/metro/base/content/downloads.js @@ -549,12 +549,27 @@ var MetroDownloadsView = { switch (aEvent.type) { case 'TabClose': { let browser = aEvent.originalTarget.linkedBrowser; - dump("DownloadNotificationsView handleEvent, got TabClose event for browser: "+browser+"\n"); - let notn = this._getNotificationWithValue("download-progress"); - if (notn && notn.defaultView == browser.contentWindow) { - let nextTab = Browser.getNextTab(aEvent.originalTarget); - let box = Browser.getNotificationBox(nextTab.linkedBrowser); - box.insertBefore(notn, box.firstChild); + let tab = Browser.getTabForBrowser(browser); + let notificationBox = Browser.getNotificationBox(browser); + + // move any download-related notification before the tab and its notificationBox goes away + // The 3 possible values should be mutually exclusive + for(let name of ["download-progress", + "save-download", + "download-complete"]) { + let notn = notificationBox.getNotificationWithValue(name); + if (!notn) { + continue; + } + + let nextTab = Browser.getNextTab(tab); + let nextBox = nextTab && Browser.getNotificationBox(nextTab.browser); + if (nextBox) { + // move notification to the next tab + nextBox.adoptNotification(notn); + } else { + // Alas, no browser to move the notifications to. + } } break; } From 73aab8c0533c50260fa53274313cf303bb854835 Mon Sep 17 00:00:00 2001 From: Sam Foster Date: Tue, 4 Mar 2014 19:16:08 -0800 Subject: [PATCH 086/112] Bug 967793 - Add test for download notification behavior when the current tab gets closed. r=azasypkin --- .../base/tests/mochitest/browser_downloads.js | 45 +++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/browser/metro/base/tests/mochitest/browser_downloads.js b/browser/metro/base/tests/mochitest/browser_downloads.js index 68cab8e2a7f..913bc7bb033 100644 --- a/browser/metro/base/tests/mochitest/browser_downloads.js +++ b/browser/metro/base/tests/mochitest/browser_downloads.js @@ -341,4 +341,49 @@ gTests.push({ including correct values for state variables (e.g. _downloadCount, _downloadsInProgress) \ and the existence of the downloaded file."); } +}); + +/** + * Make sure download notifications are moved when we close tabs. + */ +gTests.push({ + desc: "Download notifications in closed tabs", + setUp: function() { + // put up a couple notifications on the initial tab + let notificationBox = Browser.getNotificationBox(); + notificationBox.appendNotification("not important", "low-priority-thing", "", notificationBox.PRIORITY_INFO_LOW, []); + notificationBox.appendNotification("so important", "high-priority-thing", "", notificationBox.PRIORITY_CRITICAL_HIGH, []); + + // open a new tab where we'll conduct the test + yield addTab("about:mozilla"); + }, + run: function(){ + let notificationBox = Browser.getNotificationBox(); + let notn = MetroDownloadsView.showNotification("download-progress", "test message", [], + notificationBox.PRIORITY_WARNING_LOW); + Browser.closeTab(Browser.selectedTab); + + yield waitForEvent(Elements.tabList, "TabRemove"); + + // expected behavior when a tab is closed while a download notification is showing: + // * the notification remains visible as long as a next tab/browser exists + // * normal rules about priority apply + // * notifications - including any pre-existing ones - display in expected order + let nextBox = Browser.getNotificationBox(); + let currentNotification; + + ok(nextBox.getNotificationWithValue("download-progress"), "notification was moved to next tab"); + + currentNotification = nextBox.currentNotification; + is(currentNotification.value, "high-priority-thing", "high priority notification is current"); + currentNotification.close(); + + currentNotification = nextBox.currentNotification; + is(currentNotification.value, "download-progress", "download notification is next"); + currentNotification.close(); + + currentNotification = nextBox.currentNotification; + is(currentNotification.value, "low-priority-thing", "low priority notification is next"); + currentNotification.close(); + } }); \ No newline at end of file From f247026039129a5b342d7e50fb37e1b7c5916f89 Mon Sep 17 00:00:00 2001 From: Andrea Marchesini Date: Wed, 5 Mar 2014 03:22:32 +0000 Subject: [PATCH 087/112] Bug 979109 - termination string check in Console.cpp, r=smaug --- dom/base/Console.cpp | 23 ++++++++++++++++++++-- dom/base/test/mochitest.ini | 1 + dom/base/test/test_bug979109.html | 32 +++++++++++++++++++++++++++++++ 3 files changed, 54 insertions(+), 2 deletions(-) create mode 100644 dom/base/test/test_bug979109.html diff --git a/dom/base/Console.cpp b/dom/base/Console.cpp index 77678d04e07..f22ae0f9f93 100644 --- a/dom/base/Console.cpp +++ b/dom/base/Console.cpp @@ -1090,6 +1090,10 @@ Console::ProcessArguments(JSContext* aCx, } ++start; + if (start == end) { + output.Append('%'); + break; + } if (*start == '%') { output.Append(*start); @@ -1111,13 +1115,23 @@ Console::ProcessArguments(JSContext* aCx, integer = integer * 10 + *start - '0'; tmp.Append(*start); ++start; - } while (*start >= '0' && *start <= '9'); + } while (*start >= '0' && *start <= '9' && start != end); + } + + if (start == end) { + output.Append(tmp); + break; } if (*start == '.') { tmp.Append(*start); ++start; + if (start == end) { + output.Append(tmp); + break; + } + // '.' must be followed by a number. if (*start < '0' || *start > '9') { output.Append(tmp); @@ -1130,7 +1144,12 @@ Console::ProcessArguments(JSContext* aCx, mantissa = mantissa * 10 + *start - '0'; tmp.Append(*start); ++start; - } while (*start >= '0' && *start <= '9'); + } while (*start >= '0' && *start <= '9' && start != end); + + if (start == end) { + output.Append(tmp); + break; + } } char ch = *start; diff --git a/dom/base/test/mochitest.ini b/dom/base/test/mochitest.ini index dc0c690802a..b99215cd2ec 100644 --- a/dom/base/test/mochitest.ini +++ b/dom/base/test/mochitest.ini @@ -10,6 +10,7 @@ support-files = [test_appname_override.html] [test_bug913761.html] [test_bug978522.html] +[test_bug979109.html] [test_clearTimeoutIntervalNoArg.html] [test_consoleEmptyStack.html] [test_constructor-assignment.html] diff --git a/dom/base/test/test_bug979109.html b/dom/base/test/test_bug979109.html new file mode 100644 index 00000000000..dc3ee58149f --- /dev/null +++ b/dom/base/test/test_bug979109.html @@ -0,0 +1,32 @@ + + + + + + Test for Bug 979109 + + + + +Mozilla Bug 979109 + + + From f9cfcef2a3593b183ccb5d6c33e08fe289f93fbd Mon Sep 17 00:00:00 2001 From: Andrea Marchesini Date: Wed, 5 Mar 2014 03:28:20 +0000 Subject: [PATCH 088/112] Bug 966054 - MessagePort should use StructuredCloneBuffer as internal member, r=smaug --- dom/base/MessagePort.cpp | 30 ++++++------------------------ dom/base/nsGlobalWindow.cpp | 26 ++++++-------------------- 2 files changed, 12 insertions(+), 44 deletions(-) diff --git a/dom/base/MessagePort.cpp b/dom/base/MessagePort.cpp index bd9eb670320..80c5e44a95a 100644 --- a/dom/base/MessagePort.cpp +++ b/dom/base/MessagePort.cpp @@ -55,24 +55,16 @@ class PostMessageRunnable : public nsRunnable NS_DECL_NSIRUNNABLE PostMessageRunnable() - : mMessage(nullptr) - , mMessageLen(0) { } ~PostMessageRunnable() { - // Ensure that the buffer is freed - if (mMessage) { - JSAutoStructuredCloneBuffer buffer; - buffer.adopt(mMessage, mMessageLen); - } } - void SetJSData(JSAutoStructuredCloneBuffer& aBuffer) + JSAutoStructuredCloneBuffer& Buffer() { - NS_ASSERTION(!mMessage && mMessageLen == 0, "Don't call twice!"); - aBuffer.steal(&mMessage, &mMessageLen); + return mBuffer; } bool StoreISupports(nsISupports* aSupports) @@ -89,8 +81,7 @@ class PostMessageRunnable : public nsRunnable private: nsRefPtr mPort; - uint64_t* mMessage; - size_t mMessageLen; + JSAutoStructuredCloneBuffer mBuffer; nsTArray > mSupportsArray; }; @@ -225,12 +216,6 @@ PostMessageRunnable::Run() { MOZ_ASSERT(mPort); - // Ensure that the buffer is freed even if we fail to post the message - JSAutoStructuredCloneBuffer buffer; - buffer.adopt(mMessage, mMessageLen); - mMessage = nullptr; - mMessageLen = 0; - // Get the JSContext for the target window nsCOMPtr sgo = do_QueryInterface(mPort->GetOwner()); NS_ENSURE_STATE(sgo); @@ -247,7 +232,7 @@ PostMessageRunnable::Run() scInfo.mEvent = this; scInfo.mPort = mPort; - if (!buffer.read(cx, &messageData, &kPostMessageCallbacks, &scInfo)) { + if (!mBuffer.read(cx, &messageData, &kPostMessageCallbacks, &scInfo)) { return NS_ERROR_DOM_DATA_CLONE_ERR; } } @@ -364,7 +349,6 @@ MessagePort::PostMessageMoz(JSContext* aCx, JS::Handle aMessage, // We *must* clone the data here, or the JS::Value could be modified // by script - JSAutoStructuredCloneBuffer buffer; StructuredCloneInfo scInfo; scInfo.mEvent = event; scInfo.mPort = this; @@ -388,14 +372,12 @@ MessagePort::PostMessageMoz(JSContext* aCx, JS::Handle aMessage, transferable.setObject(*array); } - if (!buffer.write(aCx, aMessage, transferable, &kPostMessageCallbacks, - &scInfo)) { + if (!event->Buffer().write(aCx, aMessage, transferable, + &kPostMessageCallbacks, &scInfo)) { aRv.Throw(NS_ERROR_DOM_DATA_CLONE_ERR); return; } - event->SetJSData(buffer); - if (!mEntangledPort) { return; } diff --git a/dom/base/nsGlobalWindow.cpp b/dom/base/nsGlobalWindow.cpp index 524cf865ad7..9cefbefb444 100644 --- a/dom/base/nsGlobalWindow.cpp +++ b/dom/base/nsGlobalWindow.cpp @@ -7530,8 +7530,6 @@ class PostMessageEvent : public nsRunnable bool aTrustedCaller) : mSource(aSource), mCallerOrigin(aCallerOrigin), - mMessage(nullptr), - mMessageLen(0), mTargetWindow(aTargetWindow), mProvidedPrincipal(aProvidedPrincipal), mTrustedCaller(aTrustedCaller) @@ -7541,14 +7539,12 @@ class PostMessageEvent : public nsRunnable ~PostMessageEvent() { - NS_ASSERTION(!mMessage, "Message should have been deserialized!"); MOZ_COUNT_DTOR(PostMessageEvent); } - void SetJSData(JSAutoStructuredCloneBuffer& aBuffer) + JSAutoStructuredCloneBuffer& Buffer() { - NS_ASSERTION(!mMessage && mMessageLen == 0, "Don't call twice!"); - aBuffer.steal(&mMessage, &mMessageLen); + return mBuffer; } bool StoreISupports(nsISupports* aSupports) @@ -7558,10 +7554,9 @@ class PostMessageEvent : public nsRunnable } private: + JSAutoStructuredCloneBuffer mBuffer; nsRefPtr mSource; nsString mCallerOrigin; - uint64_t* mMessage; - size_t mMessageLen; nsRefPtr mTargetWindow; nsCOMPtr mProvidedPrincipal; bool mTrustedCaller; @@ -7709,12 +7704,6 @@ PostMessageEvent::Run() // If we bailed before this point we're going to leak mMessage, but // that's probably better than crashing. - // Ensure that the buffer is freed even if we fail to post the message - JSAutoStructuredCloneBuffer buffer; - buffer.adopt(mMessage, mMessageLen); - mMessage = nullptr; - mMessageLen = 0; - nsRefPtr targetWindow; if (mTargetWindow->IsClosedOrClosing() || !(targetWindow = mTargetWindow->GetCurrentInnerWindowInternal()) || @@ -7757,7 +7746,7 @@ PostMessageEvent::Run() scInfo.event = this; scInfo.window = targetWindow; - if (!buffer.read(cx, &messageData, &kPostMessageCallbacks, &scInfo)) { + if (!mBuffer.read(cx, &messageData, &kPostMessageCallbacks, &scInfo)) { return NS_ERROR_DOM_DATA_CLONE_ERR; } } @@ -7938,7 +7927,6 @@ nsGlobalWindow::PostMessageMoz(JSContext* aCx, JS::Handle aMessage, // We *must* clone the data here, or the JS::Value could be modified // by script - JSAutoStructuredCloneBuffer buffer; StructuredCloneInfo scInfo; scInfo.event = event; scInfo.window = this; @@ -7947,14 +7935,12 @@ nsGlobalWindow::PostMessageMoz(JSContext* aCx, JS::Handle aMessage, JS::Rooted message(aCx, aMessage); JS::Rooted transfer(aCx, aTransfer); if (NS_FAILED(callerPrin->Subsumes(principal, &scInfo.subsumes)) || - !buffer.write(aCx, message, transfer, &kPostMessageCallbacks, - &scInfo)) { + !event->Buffer().write(aCx, message, transfer, &kPostMessageCallbacks, + &scInfo)) { aError.Throw(NS_ERROR_DOM_DATA_CLONE_ERR); return; } - event->SetJSData(buffer); - aError = NS_DispatchToCurrentThread(event); } From 90007339f34c336c1bb06c810cf9b87d0ec92de5 Mon Sep 17 00:00:00 2001 From: Matthew Gregan Date: Wed, 5 Mar 2014 16:35:46 +1300 Subject: [PATCH 089/112] Bug 979096 - Rename PR_LOG uses to MSE_LOG in content/media/mediasource. r=cajbir --- content/media/mediasource/MediaSource.cpp | 16 +++++++------- .../media/mediasource/MediaSourceDecoder.cpp | 8 +++---- content/media/mediasource/SourceBuffer.cpp | 10 ++++----- .../media/mediasource/SourceBufferList.cpp | 8 +++---- .../mediasource/SourceBufferResource.cpp | 22 +++++++++---------- 5 files changed, 32 insertions(+), 32 deletions(-) diff --git a/content/media/mediasource/MediaSource.cpp b/content/media/mediasource/MediaSource.cpp index 04499bc3817..ca9cbacdb68 100644 --- a/content/media/mediasource/MediaSource.cpp +++ b/content/media/mediasource/MediaSource.cpp @@ -30,9 +30,9 @@ class JSObject; #ifdef PR_LOGGING PRLogModuleInfo* gMediaSourceLog; -#define LOG(type, msg) PR_LOG(gMediaSourceLog, type, msg) +#define MSE_DEBUG(...) PR_LOG(gMediaSourceLog, PR_LOG_DEBUG, (__VA_ARGS__)) #else -#define LOG(type, msg) +#define MSE_DEBUG(...) #endif // Arbitrary limit. @@ -123,8 +123,8 @@ MediaSource::AddSourceBuffer(const nsAString& aType, ErrorResult& aRv) } nsRefPtr sourceBuffer = new SourceBuffer(this, NS_ConvertUTF16toUTF8(mimeType)); mSourceBuffers->Append(sourceBuffer); - LOG(PR_LOG_DEBUG, ("%p AddSourceBuffer(Type=%s) -> %p", this, - NS_ConvertUTF16toUTF8(mimeType).get(), sourceBuffer.get())); + MSE_DEBUG("%p AddSourceBuffer(Type=%s) -> %p", this, + NS_ConvertUTF16toUTF8(mimeType).get(), sourceBuffer.get()); return sourceBuffer.forget(); } @@ -179,7 +179,7 @@ MediaSource::IsTypeSupported(const GlobalObject& aGlobal, bool MediaSource::Attach(MediaSourceDecoder* aDecoder) { - LOG(PR_LOG_DEBUG, ("%p Attaching decoder %p owner %p", this, aDecoder, aDecoder->GetOwner())); + MSE_DEBUG("%p Attaching decoder %p owner %p", this, aDecoder, aDecoder->GetOwner()); MOZ_ASSERT(aDecoder); if (mReadyState != MediaSourceReadyState::Closed) { return false; @@ -193,7 +193,7 @@ MediaSource::Attach(MediaSourceDecoder* aDecoder) void MediaSource::Detach() { - LOG(PR_LOG_DEBUG, ("%p Detaching decoder %p owner %p", this, mDecoder.get(), mDecoder->GetOwner())); + MSE_DEBUG("%p Detaching decoder %p owner %p", this, mDecoder.get(), mDecoder->GetOwner()); MOZ_ASSERT(mDecoder); mDecoder->DetachMediaSource(); mDecoder = nullptr; @@ -253,14 +253,14 @@ MediaSource::SetReadyState(MediaSourceReadyState aState) void MediaSource::DispatchSimpleEvent(const char* aName) { - LOG(PR_LOG_DEBUG, ("%p Dispatching event %s to MediaSource", this, aName)); + MSE_DEBUG("%p Dispatching event %s to MediaSource", this, aName); DispatchTrustedEvent(NS_ConvertUTF8toUTF16(aName)); } void MediaSource::QueueAsyncSimpleEvent(const char* aName) { - LOG(PR_LOG_DEBUG, ("%p Queuing event %s to MediaSource", this, aName)); + MSE_DEBUG("%p Queuing event %s to MediaSource", this, aName); nsCOMPtr event = new AsyncEventRunner(this, aName); NS_DispatchToMainThread(event, NS_DISPATCH_NORMAL); } diff --git a/content/media/mediasource/MediaSourceDecoder.cpp b/content/media/mediasource/MediaSourceDecoder.cpp index 9c2d1e6c76d..9e1e18706fe 100644 --- a/content/media/mediasource/MediaSourceDecoder.cpp +++ b/content/media/mediasource/MediaSourceDecoder.cpp @@ -23,9 +23,9 @@ #ifdef PR_LOGGING extern PRLogModuleInfo* gMediaSourceLog; -#define LOG(type, msg) PR_LOG(gMediaSourceLog, type, msg) +#define MSE_DEBUG(...) PR_LOG(gMediaSourceLog, PR_LOG_DEBUG, (__VA_ARGS__)) #else -#define LOG(type, msg) +#define MSE_DEBUG(...) #endif namespace mozilla { @@ -202,7 +202,7 @@ MediaSourceDecoder::CreateSubDecoder(const nsACString& aType) ReentrantMonitorAutoEnter mon(GetReentrantMonitor()); mDecoders.AppendElement(decoder); mReaders.AppendElement(reader); - LOG(PR_LOG_DEBUG, ("Registered subdecoder %p subreader %p", decoder.get(), reader.get())); + MSE_DEBUG("Registered subdecoder %p subreader %p", decoder.get(), reader.get()); mon.NotifyAll(); decoder->SetReader(reader.forget()); @@ -221,7 +221,7 @@ MediaSourceReader::ReadMetadata(MediaInfo* aInfo, MetadataTags** aTags) MediaDecoderReader* reader = readers[i]; MediaInfo mi; nsresult rv = reader->ReadMetadata(&mi, aTags); - LOG(PR_LOG_DEBUG, ("ReadMetadata on SB reader %p", reader)); + MSE_DEBUG("ReadMetadata on SB reader %p", reader); if (NS_FAILED(rv)) { return rv; } diff --git a/content/media/mediasource/SourceBuffer.cpp b/content/media/mediasource/SourceBuffer.cpp index 70fac92df35..6e74013ffe5 100644 --- a/content/media/mediasource/SourceBuffer.cpp +++ b/content/media/mediasource/SourceBuffer.cpp @@ -26,9 +26,9 @@ class JSObject; #ifdef PR_LOGGING extern PRLogModuleInfo* gMediaSourceLog; -#define LOG(type, msg) PR_LOG(gMediaSourceLog, type, msg) +#define MSE_DEBUG(...) PR_LOG(gMediaSourceLog, PR_LOG_DEBUG, (__VA_ARGS__)) #else -#define LOG(type, msg) +#define MSE_DEBUG(...) #endif namespace mozilla { @@ -289,14 +289,14 @@ SourceBuffer::WrapObject(JSContext* aCx, JS::Handle aScope) void SourceBuffer::DispatchSimpleEvent(const char* aName) { - LOG(PR_LOG_DEBUG, ("%p Dispatching event %s to SourceBuffer", this, aName)); + MSE_DEBUG("%p Dispatching event %s to SourceBuffer", this, aName); DispatchTrustedEvent(NS_ConvertUTF8toUTF16(aName)); } void SourceBuffer::QueueAsyncSimpleEvent(const char* aName) { - LOG(PR_LOG_DEBUG, ("%p Queuing event %s to SourceBuffer", this, aName)); + MSE_DEBUG("%p Queuing event %s to SourceBuffer", this, aName); nsCOMPtr event = new AsyncEventRunner(this, aName); NS_DispatchToMainThread(event, NS_DISPATCH_NORMAL); } @@ -339,7 +339,7 @@ SourceBuffer::AppendData(const uint8_t* aData, uint32_t aLength, ErrorResult& aR } // TODO: Run coded frame eviction algorithm. // TODO: Test buffer full flag. - LOG(PR_LOG_DEBUG, ("%p Append(ArrayBuffer=%u)", this, aLength)); + MSE_DEBUG("%p Append(ArrayBuffer=%u)", this, aLength); StartUpdating(); // XXX: For future reference: NDA call must run on the main thread. mDecoder->NotifyDataArrived(reinterpret_cast(aData), diff --git a/content/media/mediasource/SourceBufferList.cpp b/content/media/mediasource/SourceBufferList.cpp index ccd27e9d545..778fc98677b 100644 --- a/content/media/mediasource/SourceBufferList.cpp +++ b/content/media/mediasource/SourceBufferList.cpp @@ -22,9 +22,9 @@ class JSObject; #ifdef PR_LOGGING extern PRLogModuleInfo* gMediaSourceLog; -#define LOG(type, msg) PR_LOG(gMediaSourceLog, type, msg) +#define MSE_DEBUG(...) PR_LOG(gMediaSourceLog, PR_LOG_DEBUG, (__VA_ARGS__)) #else -#define LOG(type, msg) +#define MSE_DEBUG(...) #endif namespace mozilla { @@ -122,14 +122,14 @@ SourceBufferList::Ended() void SourceBufferList::DispatchSimpleEvent(const char* aName) { - LOG(PR_LOG_DEBUG, ("%p Dispatching event %s to SourceBufferList", this, aName)); + MSE_DEBUG("%p Dispatching event %s to SourceBufferList", this, aName); DispatchTrustedEvent(NS_ConvertUTF8toUTF16(aName)); } void SourceBufferList::QueueAsyncSimpleEvent(const char* aName) { - LOG(PR_LOG_DEBUG, ("%p Queuing event %s to SourceBufferList", this, aName)); + MSE_DEBUG("%p Queuing event %s to SourceBufferList", this, aName); nsCOMPtr event = new AsyncEventRunner(this, aName); NS_DispatchToMainThread(event, NS_DISPATCH_NORMAL); } diff --git a/content/media/mediasource/SourceBufferResource.cpp b/content/media/mediasource/SourceBufferResource.cpp index 0ea3f69b17b..f53361e7621 100644 --- a/content/media/mediasource/SourceBufferResource.cpp +++ b/content/media/mediasource/SourceBufferResource.cpp @@ -16,9 +16,9 @@ #ifdef PR_LOGGING extern PRLogModuleInfo* gMediaSourceLog; -#define LOG(type, msg) PR_LOG(gMediaSourceLog, type, msg) +#define MSE_DEBUG(...) PR_LOG(gMediaSourceLog, PR_LOG_DEBUG, (__VA_ARGS__)) #else -#define LOG(type, msg) +#define MSE_DEBUG(...) #endif namespace mozilla { @@ -33,7 +33,7 @@ nsresult SourceBufferResource::Close() { ReentrantMonitorAutoEnter mon(mMonitor); - LOG(PR_LOG_DEBUG, ("%p SBR::Close", this)); + MSE_DEBUG("%p SBR::Close", this); //MOZ_ASSERT(!mClosed); mClosed = true; mon.NotifyAll(); @@ -49,20 +49,20 @@ SourceBufferResource::Read(char* aBuffer, uint32_t aCount, uint32_t* aBytes) while (blockingRead && !mEnded && mOffset + aCount > static_cast(GetLength())) { - LOG(PR_LOG_DEBUG, ("%p SBR::Read waiting for data", this)); + MSE_DEBUG("%p SBR::Read waiting for data", this); mon.Wait(); } uint32_t available = GetLength() - mOffset; uint32_t count = std::min(aCount, available); if (!PR_GetEnv("MOZ_QUIET")) { - LOG(PR_LOG_DEBUG, ("%p SBR::Read aCount=%u length=%u offset=%u " - "available=%u count=%u, blocking=%d bufComplete=%d", - this, aCount, GetLength(), mOffset, available, count, - blockingRead, mEnded)); + MSE_DEBUG("%p SBR::Read aCount=%u length=%u offset=%u " + "available=%u count=%u, blocking=%d bufComplete=%d", + this, aCount, GetLength(), mOffset, available, count, + blockingRead, mEnded); } if (available == 0) { - LOG(PR_LOG_DEBUG, ("%p SBR::Read EOF", this)); + MSE_DEBUG("%p SBR::Read EOF", this); *aBytes = 0; return NS_OK; } @@ -160,7 +160,7 @@ SourceBufferResource::Ended() SourceBufferResource::~SourceBufferResource() { MOZ_COUNT_DTOR(SourceBufferResource); - LOG(PR_LOG_DEBUG, ("%p SBR::~SBR", this)); + MSE_DEBUG("%p SBR::~SBR", this); } SourceBufferResource::SourceBufferResource(nsIPrincipal* aPrincipal, @@ -173,7 +173,7 @@ SourceBufferResource::SourceBufferResource(nsIPrincipal* aPrincipal, , mEnded(false) { MOZ_COUNT_CTOR(SourceBufferResource); - LOG(PR_LOG_DEBUG, ("%p SBR::SBR()", this)); + MSE_DEBUG("%p SBR::SBR()", this); } } // namespace mozilla From b9478e3792f9c899e808bdef9c2560d30fc92cd4 Mon Sep 17 00:00:00 2001 From: Matthew Gregan Date: Wed, 5 Mar 2014 16:35:47 +1300 Subject: [PATCH 090/112] Bug 979099 - Refactor MediaSource's IsTypeSupported. r=cajbir --- content/media/mediasource/MediaSource.cpp | 98 +++++++++++------------ content/media/mediasource/MediaSource.h | 5 +- 2 files changed, 48 insertions(+), 55 deletions(-) diff --git a/content/media/mediasource/MediaSource.cpp b/content/media/mediasource/MediaSource.cpp index ca9cbacdb68..22325556335 100644 --- a/content/media/mediasource/MediaSource.cpp +++ b/content/media/mediasource/MediaSource.cpp @@ -40,6 +40,47 @@ static const unsigned int MAX_SOURCE_BUFFERS = 16; namespace mozilla { +static const char* const gMediaSourceTypes[6] = { + "video/webm", + "audio/webm", + "video/mp4", + "audio/mp4", + "audio/mpeg", + nullptr +}; + +static nsresult +IsTypeSupported(const nsAString& aType) +{ + if (aType.IsEmpty()) { + return NS_ERROR_DOM_INVALID_ACCESS_ERR; + } + // TODO: Further restrict this to formats in the spec. + nsContentTypeParser parser(aType); + nsAutoString mimeType; + nsresult rv = parser.GetType(mimeType); + if (NS_FAILED(rv)) { + return NS_ERROR_DOM_NOT_SUPPORTED_ERR; + } + bool found = false; + for (uint32_t i = 0; gMediaSourceTypes[i]; ++i) { + if (mimeType.EqualsASCII(gMediaSourceTypes[i])) { + found = true; + break; + } + } + if (!found) { + return NS_ERROR_DOM_NOT_SUPPORTED_ERR; + } + // Check aType against HTMLMediaElement list of MIME types. Since we've + // already restricted the container format, this acts as a specific check + // of any specified "codecs" parameter of aType. + if (dom::HTMLMediaElement::GetCanPlay(aType) == CANPLAY_NO) { + return NS_ERROR_DOM_NOT_SUPPORTED_ERR; + } + return NS_OK; +} + namespace dom { /* static */ already_AddRefed @@ -103,7 +144,9 @@ MediaSource::SetDuration(double aDuration, ErrorResult& aRv) already_AddRefed MediaSource::AddSourceBuffer(const nsAString& aType, ErrorResult& aRv) { - if (!IsTypeSupportedInternal(aType, aRv)) { + nsresult rv = mozilla::IsTypeSupported(aType); + if (NS_FAILED(rv)) { + aRv.Throw(rv); return nullptr; } if (mSourceBuffers->Length() >= MAX_SOURCE_BUFFERS) { @@ -116,7 +159,7 @@ MediaSource::AddSourceBuffer(const nsAString& aType, ErrorResult& aRv) } nsContentTypeParser parser(aType); nsAutoString mimeType; - nsresult rv = parser.GetType(mimeType); + rv = parser.GetType(mimeType); if (NS_FAILED(rv)) { aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR); return nullptr; @@ -169,11 +212,9 @@ MediaSource::EndOfStream(const Optional& aError, Er } /* static */ bool -MediaSource::IsTypeSupported(const GlobalObject& aGlobal, - const nsAString& aType) +MediaSource::IsTypeSupported(const GlobalObject&, const nsAString& aType) { - ErrorResult unused; - return IsTypeSupportedInternal(aType, unused); + return NS_SUCCEEDED(mozilla::IsTypeSupported(aType)); } bool @@ -314,51 +355,6 @@ MediaSource::EndOfStreamInternal(const Optional& aE } } -static const char* const gMediaSourceTypes[6] = { - "video/webm", - "audio/webm", - "video/mp4", - "audio/mp4", - "audio/mpeg", - nullptr -}; - -/* static */ bool -MediaSource::IsTypeSupportedInternal(const nsAString& aType, ErrorResult& aRv) -{ - if (aType.IsEmpty()) { - aRv.Throw(NS_ERROR_DOM_INVALID_ACCESS_ERR); - return false; - } - // TODO: Further restrict this to formats in the spec. - nsContentTypeParser parser(aType); - nsAutoString mimeType; - nsresult rv = parser.GetType(mimeType); - if (NS_FAILED(rv)) { - aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR); - return false; - } - bool found = false; - for (uint32_t i = 0; gMediaSourceTypes[i]; ++i) { - if (mimeType.EqualsASCII(gMediaSourceTypes[i])) { - found = true; - break; - } - } - if (!found) { - aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR); - return false; - } - // Check aType against HTMLMediaElement list of MIME types. Since we've - // already restricted the container format, this acts as a specific check - // of any specified "codecs" parameter of aType. - if (HTMLMediaElement::GetCanPlay(aType) == CANPLAY_NO) { - aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR); - return false; - } - return true; -} - nsPIDOMWindow* MediaSource::GetParentObject() const { diff --git a/content/media/mediasource/MediaSource.h b/content/media/mediasource/MediaSource.h index beb56a6327c..bc7bd5a6b6d 100644 --- a/content/media/mediasource/MediaSource.h +++ b/content/media/mediasource/MediaSource.h @@ -60,8 +60,7 @@ public: void RemoveSourceBuffer(SourceBuffer& aSourceBuffer, ErrorResult& aRv); void EndOfStream(const Optional& aError, ErrorResult& aRv); - static bool IsTypeSupported(const GlobalObject& aGlobal, - const nsAString& aType); + static bool IsTypeSupported(const GlobalObject&, const nsAString& aType); /** End WebIDL Methods. */ NS_DECL_ISUPPORTS_INHERITED @@ -100,8 +99,6 @@ private: void DurationChange(double aNewDuration, ErrorResult& aRv); void EndOfStreamInternal(const Optional& aError, ErrorResult& aRv); - static bool IsTypeSupportedInternal(const nsAString& aType, ErrorResult& aRv); - double mDuration; nsRefPtr mSourceBuffers; From a41d42b3f545bfddf3864df630120c659c4c97f0 Mon Sep 17 00:00:00 2001 From: Matthew Gregan Date: Wed, 5 Mar 2014 16:35:47 +1300 Subject: [PATCH 091/112] Bug 979100 - Refactor MediaSource's EndOfStream. r=cajbir --- content/media/mediasource/MediaSource.cpp | 59 +++++++++++------------ content/media/mediasource/MediaSource.h | 1 - 2 files changed, 27 insertions(+), 33 deletions(-) diff --git a/content/media/mediasource/MediaSource.cpp b/content/media/mediasource/MediaSource.cpp index 22325556335..624ee6f2c0b 100644 --- a/content/media/mediasource/MediaSource.cpp +++ b/content/media/mediasource/MediaSource.cpp @@ -208,7 +208,33 @@ MediaSource::EndOfStream(const Optional& aError, Er aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR); return; } - EndOfStreamInternal(aError, aRv); + + SetReadyState(MediaSourceReadyState::Ended); + mSourceBuffers->Ended(); + if (!aError.WasPassed()) { + // TODO: + // Run duration change algorithm. + // DurationChange(highestDurationOfSourceBuffers, aRv); + // if (aRv.Failed()) { + // return; + // } + // Notify media element that all data is now available. + return; + } + switch (aError.Value()) { + case MediaSourceEndOfStreamError::Network: + // TODO: If media element has a readyState of: + // HAVE_NOTHING -> run resource fetch algorithm + // > HAVE_NOTHING -> run "interrupted" steps of resource fetch + break; + case MediaSourceEndOfStreamError::Decode: + // TODO: If media element has a readyState of: + // HAVE_NOTHING -> run "unsupported" steps of resource fetch + // > HAVE_NOTHING -> run "corrupted" steps of resource fetch + break; + default: + aRv.Throw(NS_ERROR_DOM_INVALID_ACCESS_ERR); + } } /* static */ bool @@ -324,37 +350,6 @@ MediaSource::DurationChange(double aNewDuration, ErrorResult& aRv) // TODO: Update media element's duration and run element's duration change algorithm. } -void -MediaSource::EndOfStreamInternal(const Optional& aError, ErrorResult& aRv) -{ - SetReadyState(MediaSourceReadyState::Ended); - mSourceBuffers->Ended(); - if (!aError.WasPassed()) { - // TODO: - // Run duration change algorithm. - // DurationChange(highestDurationOfSourceBuffers, aRv); - // if (aRv.Failed()) { - // return; - // } - // Notify media element that all data is now available. - return; - } - switch (aError.Value()) { - case MediaSourceEndOfStreamError::Network: - // TODO: If media element has a readyState of: - // HAVE_NOTHING -> run resource fetch algorithm - // > HAVE_NOTHING -> run "interrupted" steps of resource fetch - break; - case MediaSourceEndOfStreamError::Decode: - // TODO: If media element has a readyState of: - // HAVE_NOTHING -> run "unsupported" steps of resource fetch - // > HAVE_NOTHING -> run "corrupted" steps of resource fetch - break; - default: - aRv.Throw(NS_ERROR_DOM_INVALID_ACCESS_ERR); - } -} - nsPIDOMWindow* MediaSource::GetParentObject() const { diff --git a/content/media/mediasource/MediaSource.h b/content/media/mediasource/MediaSource.h index bc7bd5a6b6d..8e1e5132aee 100644 --- a/content/media/mediasource/MediaSource.h +++ b/content/media/mediasource/MediaSource.h @@ -97,7 +97,6 @@ private: void QueueAsyncSimpleEvent(const char* aName); void DurationChange(double aNewDuration, ErrorResult& aRv); - void EndOfStreamInternal(const Optional& aError, ErrorResult& aRv); double mDuration; From 50018f6a4de6eca0fa855a87db27a779840e4376 Mon Sep 17 00:00:00 2001 From: Jim Blandy Date: Tue, 4 Mar 2014 20:09:15 -0800 Subject: [PATCH 092/112] Bug 800200: Print a deprecation warning to the console when JSD is first used. r=bholley --- js/jsd/idl/jsdIDebuggerService.idl | 16 +++++++++++++++- js/jsd/jsd_xpc.cpp | 29 ++++++++++++++++++++++++++++- js/jsd/jsd_xpc.h | 12 +++++++++++- 3 files changed, 54 insertions(+), 3 deletions(-) diff --git a/js/jsd/idl/jsdIDebuggerService.idl b/js/jsd/idl/jsdIDebuggerService.idl index 0a50b61341a..4c5b2230485 100644 --- a/js/jsd/idl/jsdIDebuggerService.idl +++ b/js/jsd/idl/jsdIDebuggerService.idl @@ -44,8 +44,12 @@ interface jsdIActivationCallback; /** * Debugger service. It is not a good idea to have more than one active client * of the debugger service. + * + * Note that all the APIs in this file are deprecated. All consumers of + * these interfaces should switch to using the new Debugger API, documented + * here: https://wiki.mozilla.org/Debugger */ -[scriptable, uuid(029b8f0a-aa84-47eb-a60f-1a4752b7ad06)] +[scriptable, uuid(39609752-2d73-4019-a324-a374dee16d3c)] interface jsdIDebuggerService : nsISupports { /** Internal use only. */ @@ -348,6 +352,16 @@ interface jsdIDebuggerService : nsISupports * @param fileName Filename to dump the heap into. */ void dumpHeap(in AUTF8String fileName); + + /** + * Suppress console warnings about using JSD, which is a deprecated API. + * + * This applies only to the next call to asyncOn; any subsequent calls + * will elicit the warning, unless you call 'acknowledgeDeprecation' + * before each of them, too. This arrangement ensures that one add-on's + * acknowledgement doesn't suppress warnings for other add-ons. + */ + void acknowledgeDeprecation(); }; /* callback interfaces */ diff --git a/js/jsd/jsd_xpc.cpp b/js/jsd/jsd_xpc.cpp index ca1c299b1b0..4c9d8a4b110 100644 --- a/js/jsd/jsd_xpc.cpp +++ b/js/jsd/jsd_xpc.cpp @@ -20,6 +20,7 @@ #include "nsICategoryManager.h" #include "nsIJSRuntimeService.h" #include "nsIThreadInternal.h" +#include "nsIScriptError.h" #include "nsTArray.h" #include "nsThreadUtils.h" #include "nsMemory.h" @@ -2463,11 +2464,30 @@ jsdService::AsyncOn (jsdIActivationCallback *activationCallback) { nsresult rv; + // Warn that JSD is deprecated, unless the caller has told us + // that they know already. + if (mDeprecationAcknowledged) { + mDeprecationAcknowledged = false; + } else if (!mWarnedAboutDeprecation) { + // In any case, warn only once. + mWarnedAboutDeprecation = true; + + // Ignore errors: simply being unable to print the message + // shouldn't (effectively) disable JSD. + nsContentUtils::ReportToConsoleNonLocalized( + NS_LITERAL_STRING("\ +The jsdIDebuggerService and its associated interfaces are deprecated. \ +Please use Debugger, via IJSDebugger, instead."), + nsIScriptError::warningFlag, + NS_LITERAL_CSTRING("JSD"), + nullptr); + } + nsCOMPtr xpc = do_GetService(nsIXPConnect::GetCID(), &rv); if (NS_FAILED(rv)) return rv; mActivationCallback = activationCallback; - + return xpc->SetDebugModeWhenPossible(true, true); } @@ -3039,6 +3059,13 @@ jsdService::ExitNestedEventLoop (uint32_t *_rval) return NS_OK; } +NS_IMETHODIMP +jsdService::AcknowledgeDeprecation() +{ + mDeprecationAcknowledged = true; + return NS_OK; +} + /* hook attribute get/set functions */ NS_IMETHODIMP diff --git a/js/jsd/jsd_xpc.h b/js/jsd/jsd_xpc.h index 013fd589047..e0639864608 100644 --- a/js/jsd/jsd_xpc.h +++ b/js/jsd/jsd_xpc.h @@ -262,7 +262,9 @@ class jsdService : public jsdIDebuggerService mNestedLoopLevel(0), mCx(0), mRuntime(0), mErrorHook(0), mBreakpointHook(0), mDebugHook(0), mDebuggerHook(0), mInterruptHook(0), mScriptHook(0), mThrowHook(0), - mTopLevelHook(0), mFunctionHook(0) + mTopLevelHook(0), mFunctionHook(0), + mWarnedAboutDeprecation(false), + mDeprecationAcknowledged(false) { } @@ -292,6 +294,14 @@ class jsdService : public jsdIDebuggerService nsCOMPtr mTopLevelHook; nsCOMPtr mFunctionHook; nsCOMPtr mActivationCallback; + + // True if we have ever printed a warning about JSD being deprecated. + // We only ever print the warning once. + bool mWarnedAboutDeprecation; + + // True if the next call to asyncOn should not produce a warning, + // because the consumer called jsdIDebuggerService::acknowledgeDeprecation. + bool mDeprecationAcknowledged; }; #endif /* JSDSERVICE_H___ */ From a63ef45bd2bf6fcdfc2918b9b6ff60c4b2ba4f93 Mon Sep 17 00:00:00 2001 From: "L. David Baron" Date: Tue, 4 Mar 2014 20:13:19 -0800 Subject: [PATCH 093/112] Fix merge error between bug 872273 (changeset 46df3fd9b0dc) and bug 946065 (changeset 243259fda9ab) and move this test to the directory where it's listed in mochitest.ini so it will actually be run. No review. Bug 979640 is filed on making this mistake harder. --HG-- rename : content/xbl/test/test_bug872273.xhtml => dom/xbl/test/test_bug872273.xhtml --- {content => dom}/xbl/test/test_bug872273.xhtml | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename {content => dom}/xbl/test/test_bug872273.xhtml (100%) diff --git a/content/xbl/test/test_bug872273.xhtml b/dom/xbl/test/test_bug872273.xhtml similarity index 100% rename from content/xbl/test/test_bug872273.xhtml rename to dom/xbl/test/test_bug872273.xhtml From c756924cf8b30b2ec2757e2d23d21df57f38d323 Mon Sep 17 00:00:00 2001 From: "L. David Baron" Date: Tue, 4 Mar 2014 20:13:19 -0800 Subject: [PATCH 094/112] Bug 976777: Truncate long source lines in script errors before sending them to the parent process. r=bent This fixes an out-of-memory foreground-tab crash that I could reliably reproduce on a 256MB Firefox OS phone, and I think also significantly reduces the number of background tabs I'm seeing killed due to low memory. --- dom/ipc/ContentChild.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/dom/ipc/ContentChild.cpp b/dom/ipc/ContentChild.cpp index e74cbe9616e..effc52f34e9 100644 --- a/dom/ipc/ContentChild.cpp +++ b/dom/ipc/ContentChild.cpp @@ -268,6 +268,16 @@ ConsoleListener::Observe(nsIConsoleMessage* aMessage) NS_ENSURE_SUCCESS(rv, rv); rv = scriptError->GetSourceLine(sourceLine); NS_ENSURE_SUCCESS(rv, rv); + + // Before we send the error to the parent process (which + // involves copying the memory), truncate any long lines. CSS + // errors in particular share the memory for long lines with + // repeated errors, but the IPC communication we're about to do + // will break that sharing, so we better truncate now. + if (sourceLine.Length() > 1000) { + sourceLine.Truncate(1000); + } + rv = scriptError->GetCategory(getter_Copies(category)); NS_ENSURE_SUCCESS(rv, rv); rv = scriptError->GetLineNumber(&lineNum); From 5be0db86fbe7290dc5d52ceb20c9245b56dd741d Mon Sep 17 00:00:00 2001 From: "L. David Baron" Date: Tue, 4 Mar 2014 20:13:20 -0800 Subject: [PATCH 095/112] Bug 621618 patch 1: Remove BindToTree overrides in nsXMLElement that exist only to make AddToIdTable/RemoveFromIdTable calls already in the base class (Element). r=bzbarsky I think this could have been done as part of Bug 700981 part 2, which moved AddToIdTable and RemoveFromIdTable calls from nsStyledElement to nsGenericElement. --- content/xml/content/src/nsXMLElement.cpp | 25 ------------------------ content/xml/content/src/nsXMLElement.h | 4 ---- 2 files changed, 29 deletions(-) diff --git a/content/xml/content/src/nsXMLElement.cpp b/content/xml/content/src/nsXMLElement.cpp index 6d04b07d782..cb6a7c4f011 100644 --- a/content/xml/content/src/nsXMLElement.cpp +++ b/content/xml/content/src/nsXMLElement.cpp @@ -133,28 +133,3 @@ nsXMLElement::ParseAttribute(int32_t aNamespaceID, return false; } - -nsresult -nsXMLElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent, - nsIContent* aBindingParent, - bool aCompileEventHandlers) -{ - nsresult rv = Element::BindToTree(aDocument, aParent, - aBindingParent, - aCompileEventHandlers); - NS_ENSURE_SUCCESS(rv, rv); - - if (aDocument && HasID() && !GetBindingParent()) { - aDocument->AddToIdTable(this, DoGetID()); - } - - return NS_OK; -} - -void -nsXMLElement::UnbindFromTree(bool aDeep, bool aNullParent) -{ - RemoveFromIdTable(); - - return Element::UnbindFromTree(aDeep, aNullParent); -} diff --git a/content/xml/content/src/nsXMLElement.h b/content/xml/content/src/nsXMLElement.h index 6f570e7679b..a497699c184 100644 --- a/content/xml/content/src/nsXMLElement.h +++ b/content/xml/content/src/nsXMLElement.h @@ -37,10 +37,6 @@ public: // nsIContent interface methods virtual nsIAtom *GetIDAttributeName() const MOZ_OVERRIDE; virtual nsIAtom* DoGetID() const MOZ_OVERRIDE; - virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent, - nsIContent* aBindingParent, - bool aCompileEventHandlers) MOZ_OVERRIDE; - virtual void UnbindFromTree(bool aDeep, bool aNullParent) MOZ_OVERRIDE; virtual nsresult UnsetAttr(int32_t aNameSpaceID, nsIAtom* aAttribute, bool aNotify) MOZ_OVERRIDE; virtual bool ParseAttribute(int32_t aNamespaceID, From ac15812b00b519d42a90f47c9acd0e25f049e22f Mon Sep 17 00:00:00 2001 From: "L. David Baron" Date: Tue, 4 Mar 2014 20:13:20 -0800 Subject: [PATCH 096/112] Bug 621618 patch 2: Make nsXMLElement reuse Element::AddToIdTable and Element::RemoveFromIdTable thoroughly. r=bzbarsky --- content/base/public/Element.h | 3 +- content/base/src/Element.cpp | 40 ++++++++++++++---------- content/xml/content/src/nsXMLElement.cpp | 4 +-- 3 files changed, 27 insertions(+), 20 deletions(-) diff --git a/content/base/public/Element.h b/content/base/public/Element.h index b55b851c829..ccd90ea6429 100644 --- a/content/base/public/Element.h +++ b/content/base/public/Element.h @@ -1088,7 +1088,8 @@ protected: * Add/remove this element to the documents id cache */ void AddToIdTable(nsIAtom* aId); - void RemoveFromIdTable(); + void RemoveFromIdTable(); // checks HasID() and uses DoGetID() + void RemoveFromIdTable(nsIAtom* aId); /** * Functions to carry out event default actions for links of all types diff --git a/content/base/src/Element.cpp b/content/base/src/Element.cpp index 6f196b73341..df679b6c370 100644 --- a/content/base/src/Element.cpp +++ b/content/base/src/Element.cpp @@ -719,23 +719,29 @@ void Element::RemoveFromIdTable() { if (HasID()) { - if (HasFlag(NODE_IS_IN_SHADOW_TREE)) { - ShadowRoot* containingShadow = GetContainingShadow(); - // Check for containingShadow because it may have - // been deleted during unlinking. - if (containingShadow) { - containingShadow->RemoveFromIdTable(this, DoGetID()); - } - } else { - nsIDocument* doc = GetCurrentDoc(); - if (doc) { - nsIAtom* id = DoGetID(); - // id can be null during mutation events evilness. Also, XUL elements - // loose their proto attributes during cc-unlink, so this can happen - // during cc-unlink too. - if (id) { - doc->RemoveFromIdTable(this, DoGetID()); - } + RemoveFromIdTable(DoGetID()); + } +} + +void +Element::RemoveFromIdTable(nsIAtom* aId) +{ + NS_ASSERTION(HasID(), "Node doesn't have an ID?"); + if (HasFlag(NODE_IS_IN_SHADOW_TREE)) { + ShadowRoot* containingShadow = GetContainingShadow(); + // Check for containingShadow because it may have + // been deleted during unlinking. + if (containingShadow) { + containingShadow->RemoveFromIdTable(this, aId); + } + } else { + nsIDocument* doc = GetCurrentDoc(); + if (doc) { + // id can be null during mutation events evilness. Also, XUL elements + // loose their proto attributes during cc-unlink, so this can happen + // during cc-unlink too. + if (aId) { + doc->RemoveFromIdTable(this, aId); } } } diff --git a/content/xml/content/src/nsXMLElement.cpp b/content/xml/content/src/nsXMLElement.cpp index cb6a7c4f011..bfd9bcc840d 100644 --- a/content/xml/content/src/nsXMLElement.cpp +++ b/content/xml/content/src/nsXMLElement.cpp @@ -84,7 +84,7 @@ nsXMLElement::NodeInfoChanged(nsINodeInfo* aOldNodeInfo) const nsAttrValue* attrVal = mAttrsAndChildren.GetAttr(aOldNodeInfo->GetIDAttributeAtom()); if (attrVal) { - doc->RemoveFromIdTable(this, attrVal->GetAtomValue()); + RemoveFromIdTable(attrVal->GetAtomValue()); } } @@ -104,7 +104,7 @@ nsXMLElement::NodeInfoChanged(nsINodeInfo* aOldNodeInfo) NS_ASSERTION(attrVal->Type() == nsAttrValue::eAtom, "Should be atom by now"); if (doc) { - doc->AddToIdTable(this, attrVal->GetAtomValue()); + AddToIdTable(attrVal->GetAtomValue()); } } } From 2367771127c940840d902d4f7c87966db868eb8b Mon Sep 17 00:00:00 2001 From: "L. David Baron" Date: Tue, 4 Mar 2014 20:13:20 -0800 Subject: [PATCH 097/112] Bug 621618 patch 3: Add FIXMEs in nsXULDocument for ID handling. r=bzbarsky --- content/xul/document/src/XULDocument.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/content/xul/document/src/XULDocument.cpp b/content/xul/document/src/XULDocument.cpp index 6129fe2c4fc..7df19b79a21 100644 --- a/content/xul/document/src/XULDocument.cpp +++ b/content/xul/document/src/XULDocument.cpp @@ -1720,6 +1720,7 @@ XULDocument::AddElementToDocumentPre(Element* aElement) // elements from prototypes. nsIAtom* id = aElement->GetID(); if (id) { + // FIXME: Shouldn't BindToTree take care of this? nsAutoScriptBlocker scriptBlocker; AddToIdTable(aElement, id); } @@ -1853,6 +1854,7 @@ XULDocument::RemoveSubtreeFromDocument(nsIContent* aContent) RemoveElementFromRefMap(aElement); nsIAtom* id = aElement->GetID(); if (id) { + // FIXME: Shouldn't UnbindFromTree take care of this? nsAutoScriptBlocker scriptBlocker; RemoveFromIdTable(aElement, id); } From af015e471f98c371263714c798bfe309b3f1282b Mon Sep 17 00:00:00 2001 From: "L. David Baron" Date: Tue, 4 Mar 2014 20:13:20 -0800 Subject: [PATCH 098/112] Bug 621618 patch 4: Make conditions in Element::RemoveFromIdTable match those in AddToIdTable, to avoid asymmetric calls to the document's functions. r=bzbarsky --- content/base/src/Element.cpp | 2 +- dom/plugins/test/mochitest/test_bug813906.html | 9 +-------- 2 files changed, 2 insertions(+), 9 deletions(-) diff --git a/content/base/src/Element.cpp b/content/base/src/Element.cpp index df679b6c370..95bce4bd6fa 100644 --- a/content/base/src/Element.cpp +++ b/content/base/src/Element.cpp @@ -736,7 +736,7 @@ Element::RemoveFromIdTable(nsIAtom* aId) } } else { nsIDocument* doc = GetCurrentDoc(); - if (doc) { + if (doc && (!IsInAnonymousSubtree() || doc->IsXUL())) { // id can be null during mutation events evilness. Also, XUL elements // loose their proto attributes during cc-unlink, so this can happen // during cc-unlink too. diff --git a/dom/plugins/test/mochitest/test_bug813906.html b/dom/plugins/test/mochitest/test_bug813906.html index 0cd95e15dc9..a059cc28b17 100644 --- a/dom/plugins/test/mochitest/test_bug813906.html +++ b/dom/plugins/test/mochitest/test_bug813906.html @@ -21,9 +21,6 @@ function f() { SimpleTest.waitForExplicitFinish(); setTestPluginEnabledState(SpecialPowers.Ci.nsIPluginTag.STATE_ENABLED); -// When the document is torn down or is removed, we hit bug 621618 -SimpleTest.expectAssertions(1); - var frameLoadCount = 0; function frameLoaded() { frameLoadCount++; @@ -33,11 +30,7 @@ function frameLoaded() { } else if (frameLoadCount == 2) { isnot(SpecialPowers.wrap(window.frame1).location.href.indexOf('chrome://'), 0, 'plugin shouldnt be able to cause navigation to chrome URLs'); - - // Make sure we trigger bug 621618 before the test finishes so the assertion - // is attributed to this test. - document.body.removeChild(document.querySelector("svg")); - SimpleTest.executeSoon(function() { SimpleTest.finish(); }); + SimpleTest.finish(); } } From 99fe2c6a0f546b3e0e2a60cc670479dd92d32181 Mon Sep 17 00:00:00 2001 From: "L. David Baron" Date: Tue, 4 Mar 2014 20:13:20 -0800 Subject: [PATCH 099/112] Bug 978648: Handle dynamic changes to @keyframes rules and keyframe rules better. r=heycam --- layout/style/nsCSSRules.cpp | 56 ++++++++++++++++++++++++-- layout/style/test/test_animations.html | 31 ++++++++++++++ 2 files changed, 84 insertions(+), 3 deletions(-) diff --git a/layout/style/nsCSSRules.cpp b/layout/style/nsCSSRules.cpp index 73e22d444d8..5d5d344beda 100644 --- a/layout/style/nsCSSRules.cpp +++ b/layout/style/nsCSSRules.cpp @@ -37,6 +37,7 @@ #include "StyleRule.h" #include "nsFont.h" #include "nsIURI.h" +#include "mozAutoDocUpdate.h" using namespace mozilla; @@ -2374,15 +2375,23 @@ nsCSSKeyframeRule::SetKeyText(const nsAString& aKeyText) InfallibleTArray newSelectors; // FIXME: pass filename and line number - if (parser.ParseKeyframeSelectorString(aKeyText, nullptr, 0, newSelectors)) { - newSelectors.SwapElements(mKeys); - } else { + if (!parser.ParseKeyframeSelectorString(aKeyText, nullptr, 0, newSelectors)) { // for now, we don't do anything if the parse fails + return NS_OK; } + nsIDocument* doc = GetDocument(); + MOZ_AUTO_DOC_UPDATE(doc, UPDATE_STYLE, true); + + newSelectors.SwapElements(mKeys); + nsCSSStyleSheet* sheet = GetStyleSheet(); if (sheet) { sheet->SetModifiedByChildRule(); + + if (doc) { + doc->StyleRuleChanged(sheet, this, this); + } } return NS_OK; @@ -2401,6 +2410,12 @@ nsCSSKeyframeRule::GetStyle(nsIDOMCSSStyleDeclaration** aStyle) void nsCSSKeyframeRule::ChangeDeclaration(css::Declaration* aDeclaration) { + // Our caller already did a BeginUpdate/EndUpdate, but with + // UPDATE_CONTENT, and we need UPDATE_STYLE to trigger work in + // PresShell::EndUpdate. + nsIDocument* doc = GetDocument(); + MOZ_AUTO_DOC_UPDATE(doc, UPDATE_STYLE, true); + // Be careful to not assign to an nsAutoPtr if we would be assigning // the thing it already holds. if (aDeclaration != mDeclaration) { @@ -2410,6 +2425,10 @@ nsCSSKeyframeRule::ChangeDeclaration(css::Declaration* aDeclaration) nsCSSStyleSheet* sheet = GetStyleSheet(); if (sheet) { sheet->SetModifiedByChildRule(); + + if (doc) { + doc->StyleRuleChanged(sheet, this, this); + } } } @@ -2533,11 +2552,22 @@ nsCSSKeyframesRule::GetName(nsAString& aName) NS_IMETHODIMP nsCSSKeyframesRule::SetName(const nsAString& aName) { + if (mName == aName) { + return NS_OK; + } + + nsIDocument* doc = GetDocument(); + MOZ_AUTO_DOC_UPDATE(doc, UPDATE_STYLE, true); + mName = aName; nsCSSStyleSheet* sheet = GetStyleSheet(); if (sheet) { sheet->SetModifiedByChildRule(); + + if (doc) { + doc->StyleRuleChanged(sheet, this, this); + } } return NS_OK; @@ -2561,7 +2591,19 @@ nsCSSKeyframesRule::AppendRule(const nsAString& aRule) nsRefPtr rule = parser.ParseKeyframeRule(aRule, nullptr, 0); if (rule) { + nsIDocument* doc = GetDocument(); + MOZ_AUTO_DOC_UPDATE(doc, UPDATE_STYLE, true); + AppendStyleRule(rule); + + nsCSSStyleSheet* sheet = GetStyleSheet(); + if (sheet) { + sheet->SetModifiedByChildRule(); + + if (doc) { + doc->StyleRuleChanged(sheet, this, this); + } + } } return NS_OK; @@ -2597,10 +2639,18 @@ nsCSSKeyframesRule::DeleteRule(const nsAString& aKey) { uint32_t index = FindRuleIndexForKey(aKey); if (index != RULE_NOT_FOUND) { + nsIDocument* doc = GetDocument(); + MOZ_AUTO_DOC_UPDATE(doc, UPDATE_STYLE, true); + mRules.RemoveObjectAt(index); + nsCSSStyleSheet* sheet = GetStyleSheet(); if (sheet) { sheet->SetModifiedByChildRule(); + + if (doc) { + doc->StyleRuleChanged(sheet, this, this); + } } } return NS_OK; diff --git a/layout/style/test/test_animations.html b/layout/style/test/test_animations.html index 0d7fb506a0e..94fe7038bfc 100644 --- a/layout/style/test/test_animations.html +++ b/layout/style/test/test_animations.html @@ -1497,6 +1497,37 @@ is(cs.marginRight, "75px", "animation-name list length is the length that matter is(cs.marginTop, "25px", "animation-name list length is the length that matters"); done_div(); +var dyn_sheet_elt = document.createElement("style"); +document.head.appendChild(dyn_sheet_elt); +var dyn_sheet = dyn_sheet_elt.sheet; +dyn_sheet.insertRule("@keyframes dyn1 { from { margin-left: 0 } 50% { margin-left: 50px } to { margin-left: 100px } }", 0); +dyn_sheet.insertRule("@keyframes dyn2 { from { margin-left: 100px } to { margin-left: 200px } }", 1); +var dyn1 = dyn_sheet.cssRules[0]; +var dyn2 = dyn_sheet.cssRules[1]; +new_div("animation: dyn1 1s linear"); +is(cs.marginLeft, "0px", "dynamic rule change test, initial state"); +advance_clock(250); +is(cs.marginLeft, "25px", "dynamic rule change test, 250ms"); +dyn2.name = "dyn1"; +is(cs.marginLeft, "125px", "dynamic rule change test, change in @keyframes name applies"); +dyn2.appendRule("50% { margin-left: 0px }"); +is(cs.marginLeft, "50px", "dynamic rule change test, @keyframes appendRule"); +var dyn2_kf1 = dyn2.cssRules[0]; // currently 0% { margin-left: 100px } +dyn2_kf1.style.marginLeft = "-100px"; +// FIXME: Bug 978833 (keyframe rules used as nsIStyleRule but doesn't follow immutability contract) +todo_is(cs.marginLeft, "-50px", "dynamic rule change test, keyframe style set"); +dyn2.name = "dyn2"; +is(cs.marginLeft, "25px", "dynamic rule change test, change in @keyframes name applies (second time)"); +var dyn1_kf2 = dyn1.cssRules[1]; // currently 50% { margin-left: 50px } +dyn1_kf2.keyText = "25%"; +is(cs.marginLeft, "50px", "dynamic rule change test, change in keyframe keyText"); +dyn1.deleteRule("25%"); +is(cs.marginLeft, "25px", "dynamic rule change test, @keyframes deleteRule"); +done_div(); +dyn_sheet_elt.parentNode.removeChild(dyn_sheet_elt); +dyn_sheet_elt = null; +dyn_sheet = null; + SpecialPowers.DOMWindowUtils.restoreNormalRefresh(); From a632cf17a5971a907bd6bb9b544d7c51dbd3181a Mon Sep 17 00:00:00 2001 From: "L. David Baron" Date: Tue, 4 Mar 2014 20:13:20 -0800 Subject: [PATCH 100/112] Bug 978903: Fix some uninitialized variable warnings in the CSS parser. r=heycam The first provides a reasonable default (failure to parse) for the case of an unknown value type (which should never happen). The second reorders two failure checks so that the one that returns early when units is uninitialized happens before the one that looks at units. --- layout/style/nsCSSParser.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/layout/style/nsCSSParser.cpp b/layout/style/nsCSSParser.cpp index cbc800c7afb..bfd4b3cd70b 100644 --- a/layout/style/nsCSSParser.cpp +++ b/layout/style/nsCSSParser.cpp @@ -2757,7 +2757,7 @@ CSSParserImpl::ParseMediaQueryExpression(nsMediaQuery* aQuery) return false; } - bool rv; + bool rv = false; switch (feature->mValueType) { case nsMediaFeature::eLength: rv = ParseNonNegativeVariant(expr->mValue, VARIANT_LENGTH, nullptr); @@ -5963,6 +5963,11 @@ CSSParserImpl::TranslateDimension(nsCSSValue& aValue, } } + if (i == ArrayLength(UnitData)) { + // Unknown unit + return false; + } + if (!mViewportUnitsEnabled && (eCSSUnit_ViewportWidth == units || eCSSUnit_ViewportHeight == units || @@ -5972,11 +5977,6 @@ CSSParserImpl::TranslateDimension(nsCSSValue& aValue, // inside an @page declaration. Fail. return false; } - - if (i == ArrayLength(UnitData)) { - // Unknown unit - return false; - } } else { // Must be a zero number... NS_ASSERTION(0 == aNumber, "numbers without units must be 0"); From 0cc7253609e6b03694b70c90f3ee8f01cdd3b74e Mon Sep 17 00:00:00 2001 From: "L. David Baron" Date: Tue, 4 Mar 2014 20:13:21 -0800 Subject: [PATCH 101/112] Bug 828173 patch 1: Add nsLayoutUtils::GetReferenceFrame. r=mattwoodrow --- layout/base/nsLayoutUtils.cpp | 16 ++++++++++++++++ layout/base/nsLayoutUtils.h | 14 ++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/layout/base/nsLayoutUtils.cpp b/layout/base/nsLayoutUtils.cpp index 932c9479b0b..64e381d266a 100644 --- a/layout/base/nsLayoutUtils.cpp +++ b/layout/base/nsLayoutUtils.cpp @@ -4787,6 +4787,22 @@ nsLayoutUtils::GetDisplayRootFrame(nsIFrame* aFrame) } } +/* static */ nsIFrame* +nsLayoutUtils::GetReferenceFrame(nsIFrame* aFrame) +{ + nsIFrame *f = aFrame; + for (;;) { + if (f->IsTransformed() || IsPopup(f)) { + return f; + } + nsIFrame* parent = GetCrossDocParentFrame(f); + if (!parent) { + return f; + } + f = parent; + } +} + /* static */ uint32_t nsLayoutUtils::GetTextRunFlagsForStyle(nsStyleContext* aStyleContext, const nsStyleFont* aStyleFont, diff --git a/layout/base/nsLayoutUtils.h b/layout/base/nsLayoutUtils.h index 636afc2d546..3b81498d2b4 100644 --- a/layout/base/nsLayoutUtils.h +++ b/layout/base/nsLayoutUtils.h @@ -1516,6 +1516,20 @@ public: */ static nsIFrame* GetDisplayRootFrame(nsIFrame* aFrame); + /** + * Get the reference frame that would be used when constructing a + * display item for this frame. (Note, however, that + * nsDisplayTransform use the reference frame appropriate for their + * parent, rather than using their own frame as a reference frame.) + * + * This duplicates some of the logic of GetDisplayRootFrame above and + * of nsDisplayListBuilder::FindReferenceFrameFor. + * + * If you have an nsDisplayListBuilder, you should get the reference + * frame from it instead of calling this. + */ + static nsIFrame* GetReferenceFrame(nsIFrame* aFrame); + /** * Get textrun construction flags determined by a given style; in particular * some combination of: From 33a1acf4a8e171aa5b714a1bf5456bd01c5bdf35 Mon Sep 17 00:00:00 2001 From: "L. David Baron" Date: Tue, 4 Mar 2014 20:13:21 -0800 Subject: [PATCH 102/112] Bug 828173 patch 2: Make Layer::AddAnimation have the caller fill in the data instead of taking parameters. r=mattwoodrow (This is a bigger simplification later in the patch queue, when I add a variant of AddAnimation called AddAnimationForNextTransaction.) --- gfx/layers/Layers.cpp | 9 +-------- gfx/layers/Layers.h | 7 ++----- layout/base/nsDisplayList.cpp | 16 ++++++++-------- 3 files changed, 11 insertions(+), 21 deletions(-) diff --git a/gfx/layers/Layers.cpp b/gfx/layers/Layers.cpp index 4388a209c30..8574afc886d 100644 --- a/gfx/layers/Layers.cpp +++ b/gfx/layers/Layers.cpp @@ -186,18 +186,11 @@ Layer::~Layer() {} Animation* -Layer::AddAnimation(TimeStamp aStart, TimeDuration aDuration, float aIterations, - int aDirection, nsCSSProperty aProperty, const AnimationData& aData) +Layer::AddAnimation() { MOZ_LAYERS_LOG_IF_SHADOWABLE(this, ("Layer::Mutated(%p) AddAnimation", this)); Animation* anim = mAnimations.AppendElement(); - anim->startTime() = aStart; - anim->duration() = aDuration; - anim->numIterations() = aIterations; - anim->direction() = aDirection; - anim->property() = aProperty; - anim->data() = aData; Mutated(); return anim; diff --git a/gfx/layers/Layers.h b/gfx/layers/Layers.h index 232c488cf54..679ffef14e9 100644 --- a/gfx/layers/Layers.h +++ b/gfx/layers/Layers.h @@ -942,11 +942,8 @@ public: } // Call AddAnimation to add a new animation to this layer from layout code. - // Caller must add segments to the returned animation. - // aStart represents the time at the *end* of the delay. - Animation* AddAnimation(mozilla::TimeStamp aStart, mozilla::TimeDuration aDuration, - float aIterations, int aDirection, - nsCSSProperty aProperty, const AnimationData& aData); + // Caller must fill in all the properties of the returned animation. + Animation* AddAnimation(); // ClearAnimations clears animations on this layer. void ClearAnimations(); // This is only called when the layer tree is updated. Do not call this from diff --git a/layout/base/nsDisplayList.cpp b/layout/base/nsDisplayList.cpp index 4b255283583..7c338e216d6 100644 --- a/layout/base/nsDisplayList.cpp +++ b/layout/base/nsDisplayList.cpp @@ -317,15 +317,15 @@ AddAnimationsForProperty(nsIFrame* aFrame, nsCSSProperty aProperty, // all data passed directly to the compositor should be in css pixels float scale = nsDeviceContext::AppUnitsPerCSSPixel(); - TimeStamp startTime = ea->mStartTime + ea->mDelay; - TimeDuration duration = ea->mIterationDuration; - float iterations = ea->mIterationCount != NS_IEEEPositiveInfinity() - ? ea->mIterationCount : -1; - int direction = ea->mDirection; + Animation* animation = aLayer->AddAnimation(); - Animation* animation = aLayer->AddAnimation(startTime, duration, - iterations, direction, - aProperty, aData); + animation->startTime() = ea->mStartTime + ea->mDelay; + animation->duration() = ea->mIterationDuration; + animation->numIterations() = + ea->mIterationCount != NS_IEEEPositiveInfinity() ? ea->mIterationCount : -1; + animation->direction() = ea->mDirection; + animation->property() = aProperty; + animation->data() = aData; for (uint32_t propIdx = 0; propIdx < ea->mProperties.Length(); propIdx++) { AnimationProperty* property = &ea->mProperties[propIdx]; From 3a3230d07ceab5c1839e369c6b092072a0c238a4 Mon Sep 17 00:00:00 2001 From: "L. David Baron" Date: Tue, 4 Mar 2014 20:13:21 -0800 Subject: [PATCH 103/112] Bug 828173 patch 3: Add a concept of pending animations to Layer, like pending transform. r=mattwoodrow --- gfx/layers/Layers.cpp | 33 +++++++++++++++++++++++++++++++++ gfx/layers/Layers.h | 9 +++++++++ 2 files changed, 42 insertions(+) diff --git a/gfx/layers/Layers.cpp b/gfx/layers/Layers.cpp index 8574afc886d..022a1ed3b1e 100644 --- a/gfx/layers/Layers.cpp +++ b/gfx/layers/Layers.cpp @@ -190,6 +190,8 @@ Layer::AddAnimation() { MOZ_LAYERS_LOG_IF_SHADOWABLE(this, ("Layer::Mutated(%p) AddAnimation", this)); + MOZ_ASSERT(!mPendingAnimations, "should have called ClearAnimations first"); + Animation* anim = mAnimations.AppendElement(); Mutated(); @@ -199,6 +201,8 @@ Layer::AddAnimation() void Layer::ClearAnimations() { + mPendingAnimations = nullptr; + if (mAnimations.IsEmpty() && mAnimationData.IsEmpty()) { return; } @@ -209,6 +213,28 @@ Layer::ClearAnimations() Mutated(); } +Animation* +Layer::AddAnimationForNextTransaction() +{ + MOZ_ASSERT(mPendingAnimations, + "should have called ClearAnimationsForNextTransaction first"); + + Animation* anim = mPendingAnimations->AppendElement(); + + return anim; +} + +void +Layer::ClearAnimationsForNextTransaction() +{ + // Ensure we have a non-null mPendingAnimations to mark a future clear. + if (!mPendingAnimations) { + mPendingAnimations = new AnimationArray; + } + + mPendingAnimations->Clear(); +} + static nsCSSValueSharedList* CreateCSSValueList(const InfallibleTArray& aFunctions) { @@ -641,6 +667,13 @@ Layer::ApplyPendingUpdatesForThisTransaction() Mutated(); } mPendingTransform = nullptr; + + if (mPendingAnimations) { + MOZ_LAYERS_LOG_IF_SHADOWABLE(this, ("Layer::Mutated(%p) PendingUpdatesForThisTransaction", this)); + mPendingAnimations->SwapElements(mAnimations); + mPendingAnimations = nullptr; + Mutated(); + } } const float diff --git a/gfx/layers/Layers.h b/gfx/layers/Layers.h index 679ffef14e9..56f04b6d648 100644 --- a/gfx/layers/Layers.h +++ b/gfx/layers/Layers.h @@ -950,6 +950,13 @@ public: // layout code. To add an animation to this layer, use AddAnimation. void SetAnimations(const AnimationArray& aAnimations); + // These are a parallel to AddAnimation and clearAnimations, except + // they add pending animations that apply only when the next + // transaction is begun. (See also + // SetBaseTransformForNextTransaction.) + Animation* AddAnimationForNextTransaction(); + void ClearAnimationsForNextTransaction(); + /** * CONSTRUCTION PHASE ONLY * If a layer is "fixed position", this determines which point on the layer @@ -1410,6 +1417,8 @@ protected: float mPostYScale; gfx::Matrix4x4 mEffectiveTransform; AnimationArray mAnimations; + // See mPendingTransform above. + nsAutoPtr mPendingAnimations; InfallibleTArray mAnimationData; float mOpacity; gfx::CompositionOp mMixBlendMode; From 6dd37cbb1872d3e67646b414bc6c7b5fd112e253 Mon Sep 17 00:00:00 2001 From: "L. David Baron" Date: Tue, 4 Mar 2014 20:13:21 -0800 Subject: [PATCH 104/112] Bug 828173 patch 3.5: Move GetTransformRootFrame to nsLayoutUtils. r=mattwoodrow --- layout/base/nsDisplayList.cpp | 15 ++++++--------- layout/base/nsLayoutUtils.cpp | 10 ++++++++++ layout/base/nsLayoutUtils.h | 13 ++++++++++++- 3 files changed, 28 insertions(+), 10 deletions(-) diff --git a/layout/base/nsDisplayList.cpp b/layout/base/nsDisplayList.cpp index 7c338e216d6..ac1eb6d99a8 100644 --- a/layout/base/nsDisplayList.cpp +++ b/layout/base/nsDisplayList.cpp @@ -61,6 +61,12 @@ using namespace mozilla::layers; using namespace mozilla::dom; typedef FrameMetrics::ViewID ViewID; +static inline nsIFrame* +GetTransformRootFrame(nsIFrame* aFrame) +{ + return nsLayoutUtils::GetTransformRootFrame(aFrame); +} + static void AddTransformFunctions(nsCSSValueList* aList, nsStyleContext* aContext, nsPresContext* aPresContext, @@ -2878,15 +2884,6 @@ nsDisplayBoxShadowInner::ComputeVisibility(nsDisplayListBuilder* aBuilder, return true; } -nsIFrame *GetTransformRootFrame(nsIFrame* aFrame) -{ - nsIFrame *parent = nsLayoutUtils::GetCrossDocParentFrame(aFrame); - while (parent && parent->Preserves3DChildren()) { - parent = nsLayoutUtils::GetCrossDocParentFrame(parent); - } - return parent; -} - nsDisplayWrapList::nsDisplayWrapList(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame, nsDisplayList* aList) : nsDisplayItem(aBuilder, aFrame) { diff --git a/layout/base/nsLayoutUtils.cpp b/layout/base/nsLayoutUtils.cpp index 64e381d266a..8d830ce0071 100644 --- a/layout/base/nsLayoutUtils.cpp +++ b/layout/base/nsLayoutUtils.cpp @@ -4803,6 +4803,16 @@ nsLayoutUtils::GetReferenceFrame(nsIFrame* aFrame) } } +/* static */ nsIFrame* +nsLayoutUtils::GetTransformRootFrame(nsIFrame* aFrame) +{ + nsIFrame *parent = nsLayoutUtils::GetCrossDocParentFrame(aFrame); + while (parent && parent->Preserves3DChildren()) { + parent = nsLayoutUtils::GetCrossDocParentFrame(parent); + } + return parent; +} + /* static */ uint32_t nsLayoutUtils::GetTextRunFlagsForStyle(nsStyleContext* aStyleContext, const nsStyleFont* aStyleFont, diff --git a/layout/base/nsLayoutUtils.h b/layout/base/nsLayoutUtils.h index 3b81498d2b4..a195d72c9b4 100644 --- a/layout/base/nsLayoutUtils.h +++ b/layout/base/nsLayoutUtils.h @@ -1520,7 +1520,8 @@ public: * Get the reference frame that would be used when constructing a * display item for this frame. (Note, however, that * nsDisplayTransform use the reference frame appropriate for their - * parent, rather than using their own frame as a reference frame.) + * GetTransformRootFrame(), rather than using their own frame as a + * reference frame.) * * This duplicates some of the logic of GetDisplayRootFrame above and * of nsDisplayListBuilder::FindReferenceFrameFor. @@ -1530,6 +1531,16 @@ public: */ static nsIFrame* GetReferenceFrame(nsIFrame* aFrame); + /** + * Get the parent of this frame, except if that parent is part of a + * preserve-3d hierarchy, get the parent of the root of the + * preserve-3d hierarchy. + * + * (This is used as the starting point for reference frame computation + * for nsDisplayTransform display items.) + */ + static nsIFrame* GetTransformRootFrame(nsIFrame* aFrame); + /** * Get textrun construction flags determined by a given style; in particular * some combination of: From 6a0c7b3f88d3ef902926170b681aae55ad68e954 Mon Sep 17 00:00:00 2001 From: "L. David Baron" Date: Tue, 4 Mar 2014 20:13:21 -0800 Subject: [PATCH 105/112] Bug 828173 patch 4: Expose AddAnimationsAndTransitionsToLayer and allow it to be called from style change handling. r=mattwoodrow --- layout/base/nsDisplayList.cpp | 82 ++++++++++++++++++++++++----------- layout/base/nsDisplayList.h | 14 ++++++ 2 files changed, 70 insertions(+), 26 deletions(-) diff --git a/layout/base/nsDisplayList.cpp b/layout/base/nsDisplayList.cpp index ac1eb6d99a8..cb53727aa35 100644 --- a/layout/base/nsDisplayList.cpp +++ b/layout/base/nsDisplayList.cpp @@ -314,7 +314,7 @@ ToTimingFunction(css::ComputedTimingFunction& aCTF) static void AddAnimationsForProperty(nsIFrame* aFrame, nsCSSProperty aProperty, ElementAnimation* ea, Layer* aLayer, - AnimationData& aData) + AnimationData& aData, bool aPending) { NS_ASSERTION(aLayer->AsContainerLayer(), "Should only animate ContainerLayer"); nsStyleContext* styleContext = aFrame->StyleContext(); @@ -323,7 +323,8 @@ AddAnimationsForProperty(nsIFrame* aFrame, nsCSSProperty aProperty, // all data passed directly to the compositor should be in css pixels float scale = nsDeviceContext::AppUnitsPerCSSPixel(); - Animation* animation = aLayer->AddAnimation(); + Animation* animation = aPending ? aLayer->AddAnimationForNextTransaction() + : aLayer->AddAnimation(); animation->startTime() = ea->mStartTime + ea->mDelay; animation->duration() = ea->mIterationDuration; @@ -367,15 +368,31 @@ AddAnimationsForProperty(nsIFrame* aFrame, nsCSSProperty aProperty, } } -static void -AddAnimationsAndTransitionsToLayer(Layer* aLayer, nsDisplayListBuilder* aBuilder, - nsDisplayItem* aItem, nsCSSProperty aProperty) +/* static */ void +nsDisplayListBuilder::AddAnimationsAndTransitionsToLayer(Layer* aLayer, + nsDisplayListBuilder* aBuilder, + nsDisplayItem* aItem, + nsIFrame* aFrame, + nsCSSProperty aProperty) { - aLayer->ClearAnimations(); + // This function can be called in two ways: from + // nsDisplay*::BuildLayer while constructing a layer (with all + // pointers non-null), or from RestyleManager's handling of + // UpdateOpacityLayer/UpdateTransformLayer hints. + MOZ_ASSERT(!aBuilder == !aItem, + "should only be called in two configurations, with both " + "aBuilder and aItem, or with neither"); + MOZ_ASSERT(!aItem || aFrame == aItem->Frame(), "frame mismatch"); - nsIFrame* frame = aItem->Frame(); + bool pending = !aBuilder; - nsIContent* content = frame->GetContent(); + if (pending) { + aLayer->ClearAnimationsForNextTransaction(); + } else { + aLayer->ClearAnimations(); + } + + nsIContent* content = aFrame->GetContent(); if (!content) { return; } @@ -390,43 +407,54 @@ AddAnimationsAndTransitionsToLayer(Layer* aLayer, nsDisplayListBuilder* aBuilder } // If the frame is not prerendered, bail out. - if (!aItem->CanUseAsyncAnimations(aBuilder)) { + // Do this check only during layer construction; during updating the + // caller is required to check it appropriately. + if (aItem && !aItem->CanUseAsyncAnimations(aBuilder)) { // AnimationManager or TransitionManager need to know that we refused to // run this animation asynchronously so that they will not throttle the // main thread animation. - frame->Properties().Set(nsIFrame::RefusedAsyncAnimation(), + aFrame->Properties().Set(nsIFrame::RefusedAsyncAnimation(), reinterpret_cast(intptr_t(true))); // We need to schedule another refresh driver run so that AnimationManager // or TransitionManager get a chance to unthrottle the animation. - frame->SchedulePaint(); + aFrame->SchedulePaint(); return; } mozilla::TimeStamp currentTime = - frame->PresContext()->RefreshDriver()->MostRecentRefresh(); + aFrame->PresContext()->RefreshDriver()->MostRecentRefresh(); AnimationData data; if (aProperty == eCSSProperty_transform) { - nsRect bounds = nsDisplayTransform::GetFrameBoundsForTransform(frame); + nsRect bounds = nsDisplayTransform::GetFrameBoundsForTransform(aFrame); // all data passed directly to the compositor should be in css pixels float scale = nsDeviceContext::AppUnitsPerCSSPixel(); gfxPoint3D offsetToTransformOrigin = - nsDisplayTransform::GetDeltaToTransformOrigin(frame, scale, &bounds); + nsDisplayTransform::GetDeltaToTransformOrigin(aFrame, scale, &bounds); gfxPoint3D offsetToPerspectiveOrigin = - nsDisplayTransform::GetDeltaToPerspectiveOrigin(frame, scale); + nsDisplayTransform::GetDeltaToPerspectiveOrigin(aFrame, scale); nscoord perspective = 0.0; - nsStyleContext* parentStyleContext = frame->StyleContext()->GetParent(); + nsStyleContext* parentStyleContext = aFrame->StyleContext()->GetParent(); if (parentStyleContext) { const nsStyleDisplay* disp = parentStyleContext->StyleDisplay(); if (disp && disp->mChildPerspective.GetUnit() == eStyleUnit_Coord) { perspective = disp->mChildPerspective.GetCoordValue(); } } - nsPoint origin = aItem->ToReferenceFrame(); + nsPoint origin; + if (aItem) { + origin = aItem->ToReferenceFrame(); + } else { + // transform display items used a reference frame computed from + // their GetTransformRootFrame(). + nsIFrame* referenceFrame = + nsLayoutUtils::GetReferenceFrame(GetTransformRootFrame(aFrame)); + origin = aFrame->GetOffsetToCrossDoc(referenceFrame); + } data = TransformData(origin, offsetToTransformOrigin, offsetToPerspectiveOrigin, bounds, perspective, - frame->PresContext()->AppUnitsPerDevPixel()); + aFrame->PresContext()->AppUnitsPerDevPixel()); } else if (aProperty == eCSSProperty_opacity) { data = null_t(); } @@ -458,8 +486,8 @@ AddAnimationsAndTransitionsToLayer(Layer* aLayer, nsDisplayListBuilder* aBuilder segment.mToValue = pt->mEndValue; segment.mTimingFunction = pt->mTimingFunction; - AddAnimationsForProperty(frame, aProperty, &anim, - aLayer, data); + AddAnimationsForProperty(aFrame, aProperty, &anim, + aLayer, data, pending); pt->mIsRunningOnCompositor = true; } @@ -473,8 +501,8 @@ AddAnimationsAndTransitionsToLayer(Layer* aLayer, nsDisplayListBuilder* aBuilder anim->IsRunningAt(currentTime))) { continue; } - AddAnimationsForProperty(frame, aProperty, anim, - aLayer, data); + AddAnimationsForProperty(aFrame, aProperty, anim, + aLayer, data, pending); } aLayer->SetAnimationGeneration(ea->mAnimationGeneration); } @@ -3195,8 +3223,9 @@ nsDisplayOpacity::BuildLayer(nsDisplayListBuilder* aBuilder, return nullptr; container->SetOpacity(mFrame->StyleDisplay()->mOpacity); - AddAnimationsAndTransitionsToLayer(container, aBuilder, - this, eCSSProperty_opacity); + nsDisplayListBuilder::AddAnimationsAndTransitionsToLayer(container, aBuilder, + this, mFrame, + eCSSProperty_opacity); return container.forget(); } @@ -4662,8 +4691,9 @@ already_AddRefed nsDisplayTransform::BuildLayer(nsDisplayListBuilder *aBu container->SetContentFlags(container->GetContentFlags() & ~Layer::CONTENT_PRESERVE_3D); } - AddAnimationsAndTransitionsToLayer(container, aBuilder, - this, eCSSProperty_transform); + nsDisplayListBuilder::AddAnimationsAndTransitionsToLayer(container, aBuilder, + this, mFrame, + eCSSProperty_transform); if (ShouldPrerenderTransformedContent(aBuilder, mFrame, false)) { container->SetUserData(nsIFrame::LayerIsPrerenderedDataKey(), /*the value is irrelevant*/nullptr); diff --git a/layout/base/nsDisplayList.h b/layout/base/nsDisplayList.h index a3687727c1d..97a51af7a4b 100644 --- a/layout/base/nsDisplayList.h +++ b/layout/base/nsDisplayList.h @@ -39,6 +39,7 @@ class nsDisplayLayerEventRegions; namespace mozilla { namespace layers { +class Layer; class ImageLayer; class ImageContainer; } //namepsace @@ -112,6 +113,7 @@ public: typedef mozilla::DisplayItemClip DisplayItemClip; typedef mozilla::DisplayListClipState DisplayListClipState; typedef nsIWidget::ThemeGeometry ThemeGeometry; + typedef mozilla::layers::Layer Layer; /** * @param aReferenceFrame the frame at the root of the subtree; its origin @@ -481,6 +483,18 @@ public: */ const DisplayItemClip* AllocateDisplayItemClip(const DisplayItemClip& aOriginal); + /** + * Transfer off main thread animations to the layer. May be called + * with aBuilder and aItem both null, but only if the caller has + * already checked that off main thread animations should be sent to + * the layer. When they are both null, the animations are added to + * the layer as pending animations. + */ + static void AddAnimationsAndTransitionsToLayer(Layer* aLayer, + nsDisplayListBuilder* aBuilder, + nsDisplayItem* aItem, + nsIFrame* aFrame, + nsCSSProperty aProperty); /** * A helper class to temporarily set the value of * mIsAtRootOfPseudoStackingContext, and temporarily From 598c0d41228cc567a4c2aa2b7f19290c3c6b3dcf Mon Sep 17 00:00:00 2001 From: "L. David Baron" Date: Tue, 4 Mar 2014 20:13:22 -0800 Subject: [PATCH 106/112] Bug 828173 patch 5: Call AddAnimationsAndTransitionsToLayer when we choose not to repaint when handling an UpdateTransformLayer hint, so that any new animations resulting from the style change get sent to the layer. r=mattwoodrow --- layout/base/RestyleManager.cpp | 12 +++++++++++- layout/generic/nsFrame.cpp | 3 ++- layout/generic/nsIFrame.h | 5 ++++- 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/layout/base/RestyleManager.cpp b/layout/base/RestyleManager.cpp index 214257d327e..b9523c7bf30 100644 --- a/layout/base/RestyleManager.cpp +++ b/layout/base/RestyleManager.cpp @@ -34,6 +34,7 @@ #include "nsContentUtils.h" #include "nsIFrameInlines.h" #include "ActiveLayerTracker.h" +#include "nsDisplayList.h" #ifdef ACCESSIBILITY #include "nsAccessibilityService.h" @@ -237,7 +238,16 @@ DoApplyRenderingChangeToTree(nsIFrame* aFrame, // layer for this frame, and not scheduling an invalidating // paint. if (!needInvalidatingPaint) { - needInvalidatingPaint |= !aFrame->TryUpdateTransformOnly(); + Layer* layer; + needInvalidatingPaint |= !aFrame->TryUpdateTransformOnly(&layer); + + if (!needInvalidatingPaint) { + // Since we're not going to paint, we need to resend animation + // data to the layer. + MOZ_ASSERT(layer, "this can't happen if there's no layer"); + nsDisplayListBuilder::AddAnimationsAndTransitionsToLayer(layer, + nullptr, nullptr, aFrame, eCSSProperty_transform); + } } } if (aChange & nsChangeHint_ChildrenOnlyTransform) { diff --git a/layout/generic/nsFrame.cpp b/layout/generic/nsFrame.cpp index e21ce0177d3..11f21b1e52a 100644 --- a/layout/generic/nsFrame.cpp +++ b/layout/generic/nsFrame.cpp @@ -4846,7 +4846,7 @@ nsIFrame::InvalidateFrameWithRect(const nsRect& aRect, uint32_t aDisplayItemKey) /*static*/ uint8_t nsIFrame::sLayerIsPrerenderedDataKey; bool -nsIFrame::TryUpdateTransformOnly() +nsIFrame::TryUpdateTransformOnly(Layer** aLayerResult) { Layer* layer = FrameLayerBuilder::GetDedicatedLayer( this, nsDisplayItem::TYPE_TRANSFORM); @@ -4885,6 +4885,7 @@ nsIFrame::TryUpdateTransformOnly() gfx::Matrix4x4 matrix; gfx::ToMatrix4x4(transform3d, matrix); layer->SetBaseTransformForNextTransaction(matrix); + *aLayerResult = layer; return true; } diff --git a/layout/generic/nsIFrame.h b/layout/generic/nsIFrame.h index d6adba47e8f..c9767e20d5e 100644 --- a/layout/generic/nsIFrame.h +++ b/layout/generic/nsIFrame.h @@ -2106,8 +2106,11 @@ public: * Try to update this frame's transform without invalidating any * content. Return true iff successful. If unsuccessful, the * caller is responsible for scheduling an invalidating paint. + * + * If the result is true, aLayerResult will be filled in with the + * transform layer for the frame. */ - bool TryUpdateTransformOnly(); + bool TryUpdateTransformOnly(Layer** aLayerResult); /** * Checks if a frame has had InvalidateFrame() called on it since the From 503c4c2bbea1a5e05d74033262b55da8d08e0808 Mon Sep 17 00:00:00 2001 From: "L. David Baron" Date: Tue, 4 Mar 2014 20:13:22 -0800 Subject: [PATCH 107/112] Bug 828173 patch 6: Remove calls to ForceLayerRerendering from the miniflush code (UpdateThrottledStyles, which flushes animations whose main thread updates are throttled without updating any other styles). r=mattwoodrow I've been wanting to remove this code for a while. I think this code is problematic for three reasons: (1) It's in the middle of code where it doesn't belong, and which ought to be handling purely-style-system things. (This is blocking me from reusing that code elsewhere, e.g., in bug 977991 and bug 960465, both of which could use it in some form.) (2) It defeats the optimization from bug 790505 whenever we do a miniflush (in other words, whenever we have any style change, whether or not it's related) (3) It means the conditions for when we decide to ship a new set of animation data to a layer doesn't cover all the cases the layer needs it. In particular, we only run this miniflush code when we have a currently running animation or transition that's running on the compositor thread. On the other hand, the UpdateTransformLayer style change handling in DoApplyRenderingChangeToTree depends on whether the frame currently has a transform layer, which can continue to be true for a bit after the animation stops. So if we need to send animations to the layer because of a transform style change that happens soon after an animation completes, our style change handling will find the existing layer and call its SetBaseTransformForNextTransaction method but never do anything that triggers layer construction. The style throttling code, in turn, will never stop doing main thread updates because the animation generation on the layer is out-of-date, and these main thread updates will keep the layer active, but they'll never show up because the stale animation data overrides the new transform that we've been setting. (At least, I think that's what was happening; it makes sense to me and matches the behavior I was observing. I didn't verify which main thread updates and which layer updates were actually happening, though.) This shows up, for example, in the animation in attachment 8384813 just halting at a corner if I'm careful not to disturb it. (I'm testing on Linux, with both accelerated layers and OMT animations explicitly enabled.) I think there are probably some other things that can be removed as followups to removing this code, because I think we made some boundary conditions intentionally incorrect so that problem (3) above wouldn't be as bad as it otherwise would have been. --- layout/style/AnimationCommon.cpp | 28 ---------------------------- 1 file changed, 28 deletions(-) diff --git a/layout/style/AnimationCommon.cpp b/layout/style/AnimationCommon.cpp index 7a1850f979a..1e6227900ff 100644 --- a/layout/style/AnimationCommon.cpp +++ b/layout/style/AnimationCommon.cpp @@ -191,28 +191,6 @@ CommonAnimationManager::ReparentBeforeAndAfter(dom::Element* aElement, } } -// Ensure that the next repaint rebuilds the layer tree for aFrame. That -// means that changes to animations on aFrame's layer are propagated to -// the compositor, which is needed for correct behaviour of new -// transitions. -static void -ForceLayerRerendering(nsIFrame* aFrame, CommonElementAnimationData* aData) -{ - if (aData->HasAnimationOfProperty(eCSSProperty_opacity)) { - if (Layer* layer = FrameLayerBuilder::GetDedicatedLayer( - aFrame, nsDisplayItem::TYPE_OPACITY)) { - layer->RemoveUserData(nsIFrame::LayerIsPrerenderedDataKey()); - } - } - - if (aData->HasAnimationOfProperty(eCSSProperty_transform)) { - if (Layer* layer = FrameLayerBuilder::GetDedicatedLayer( - aFrame, nsDisplayItem::TYPE_TRANSFORM)) { - layer->RemoveUserData(nsIFrame::LayerIsPrerenderedDataKey()); - } - } -} - nsStyleContext* CommonAnimationManager::UpdateThrottledStyle(dom::Element* aElement, nsStyleContext* aParentStyle, @@ -254,9 +232,6 @@ CommonAnimationManager::UpdateThrottledStyle(dom::Element* aElement, mPresContext->AnimationManager()->EnsureStyleRuleFor(ea); curRule.mRule = ea->mStyleRule; - - // FIXME (bug 828173): maybe not needed anymore: - ForceLayerRerendering(primaryFrame, ea); } else if (curRule.mLevel == nsStyleSet::eTransitionSheet) { ElementTransitions *et = mPresContext->TransitionManager()->GetElementTransitions( @@ -268,9 +243,6 @@ CommonAnimationManager::UpdateThrottledStyle(dom::Element* aElement, et->EnsureStyleRuleFor(mPresContext->RefreshDriver()->MostRecentRefresh()); curRule.mRule = et->mStyleRule; - - // FIXME (bug 828173): maybe not needed anymore: - ForceLayerRerendering(primaryFrame, et); } else { curRule.mRule = ruleNode->GetRule(); } From 8b4ba29d813279737e02669ebc207c88a82c7d43 Mon Sep 17 00:00:00 2001 From: "L. David Baron" Date: Tue, 4 Mar 2014 20:13:22 -0800 Subject: [PATCH 108/112] Bug 979555: Add default value for layers.offmainthreadcomposition.log-animations preference to all.js. r=dzbarsky It's good practice to have default values for all preferences in all.js. Otherwise some preference APIs throw exceptions and/or leave values uninitialized. It also makes the preference show up in about:config. Bug 875204 accidentally removed this line from all.js even though the pref was not removed. (The pref was initially added in bug 780342.) --- modules/libpref/src/init/all.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/modules/libpref/src/init/all.js b/modules/libpref/src/init/all.js index 8acc372fa28..76afe7acc5f 100644 --- a/modules/libpref/src/init/all.js +++ b/modules/libpref/src/init/all.js @@ -3976,6 +3976,9 @@ pref("layers.offmainthreadcomposition.force-basic", false); // Whether to animate simple opacity and transforms on the compositor pref("layers.offmainthreadcomposition.async-animations", false); +// Whether to log information about off main thread animations to stderr +pref("layers.offmainthreadcomposition.log-animations", false); + pref("layers.bufferrotation.enabled", true); pref("layers.componentalpha.enabled", true); From 0ff448bbbf4d51b17c053b2f07fc6ef93d46350d Mon Sep 17 00:00:00 2001 From: "L. David Baron" Date: Tue, 4 Mar 2014 20:13:22 -0800 Subject: [PATCH 109/112] Bug 979557: CanAnimatePropertyOnCompositor should return early when there's no OMT compositing, whether or not logging is enabled. r=dzbarsky This shouldn't behave differently depending on whether or not logging is enabled; that difference was introduced in bug 785648. --- layout/style/AnimationCommon.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/layout/style/AnimationCommon.cpp b/layout/style/AnimationCommon.cpp index 1e6227900ff..b3bda874625 100644 --- a/layout/style/AnimationCommon.cpp +++ b/layout/style/AnimationCommon.cpp @@ -366,10 +366,12 @@ CommonElementAnimationData::CanAnimatePropertyOnCompositor(const dom::Element *a CanAnimateFlags aFlags) { bool shouldLog = nsLayoutUtils::IsAnimationLoggingEnabled(); - if (shouldLog && !gfxPlatform::OffMainThreadCompositingEnabled()) { - nsCString message; - message.AppendLiteral("Performance warning: Compositor disabled"); - LogAsyncAnimationFailure(message); + if (!gfxPlatform::OffMainThreadCompositingEnabled()) { + if (shouldLog) { + nsCString message; + message.AppendLiteral("Performance warning: Compositor disabled"); + LogAsyncAnimationFailure(message); + } return false; } From 87283ff6543a2652c16d99fa29c682fb6ae5054c Mon Sep 17 00:00:00 2001 From: Timothy Nikkel Date: Tue, 4 Mar 2014 22:48:48 -0600 Subject: [PATCH 110/112] Bug 952354. Don't worry about premult alpha flags if the frame is opaque when calling GetFrame and CopyFrame. r=seth --- image/src/RasterImage.cpp | 17 ++++++++++++++--- image/src/RasterImage.h | 2 +- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/image/src/RasterImage.cpp b/image/src/RasterImage.cpp index 9eb378525df..4ec007faa7d 100644 --- a/image/src/RasterImage.cpp +++ b/image/src/RasterImage.cpp @@ -835,7 +835,7 @@ RasterImage::CopyFrame(uint32_t aWhichFrame, nsresult rv; - if (!ApplyDecodeFlags(aFlags)) + if (!ApplyDecodeFlags(aFlags, aWhichFrame)) return NS_ERROR_NOT_AVAILABLE; // If requested, synchronously flush any data we have lying around to the decoder @@ -896,7 +896,7 @@ RasterImage::GetFrame(uint32_t aWhichFrame, if (mInDecoder && (aFlags & imgIContainer::FLAG_SYNC_DECODE)) return nullptr; - if (!ApplyDecodeFlags(aFlags)) + if (!ApplyDecodeFlags(aFlags, aWhichFrame)) return nullptr; // If the caller requested a synchronous decode, do it @@ -1183,12 +1183,23 @@ RasterImage::InternalAddFrame(uint32_t framenum, } bool -RasterImage::ApplyDecodeFlags(uint32_t aNewFlags) +RasterImage::ApplyDecodeFlags(uint32_t aNewFlags, uint32_t aWhichFrame) { if (mFrameDecodeFlags == (aNewFlags & DECODE_FLAGS_MASK)) return true; // Not asking very much of us here. if (mDecoded) { + // If the requested frame is opaque and the current and new decode flags + // only differ in the premultiply alpha bit then we can use the existing + // frame, we don't need to discard and re-decode. + uint32_t currentNonAlphaFlags = + (mFrameDecodeFlags & DECODE_FLAGS_MASK) & ~FLAG_DECODE_NO_PREMULTIPLY_ALPHA; + uint32_t newNonAlphaFlags = + (aNewFlags & DECODE_FLAGS_MASK) & ~FLAG_DECODE_NO_PREMULTIPLY_ALPHA; + if (currentNonAlphaFlags == newNonAlphaFlags && FrameIsOpaque(aWhichFrame)) { + return true; + } + // if we can't discard, then we're screwed; we have no way // to re-decode. Similarly if we aren't allowed to do a sync // decode. diff --git a/image/src/RasterImage.h b/image/src/RasterImage.h index d166451fc26..037c3e9bcb4 100644 --- a/image/src/RasterImage.h +++ b/image/src/RasterImage.h @@ -590,7 +590,7 @@ private: nsresult DoImageDataComplete(); - bool ApplyDecodeFlags(uint32_t aNewFlags); + bool ApplyDecodeFlags(uint32_t aNewFlags, uint32_t aWhichFrame); already_AddRefed GetCurrentImage(); void UpdateImageContainer(); From 0253d42661f8aaac601b7ac48165bca88f4cdca1 Mon Sep 17 00:00:00 2001 From: "L. David Baron" Date: Tue, 4 Mar 2014 21:05:18 -0800 Subject: [PATCH 111/112] Bug 828173 bustage fix for non-unified builds: add using declaration. --- layout/base/RestyleManager.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/layout/base/RestyleManager.cpp b/layout/base/RestyleManager.cpp index b9523c7bf30..ba68a22a25a 100644 --- a/layout/base/RestyleManager.cpp +++ b/layout/base/RestyleManager.cpp @@ -42,6 +42,8 @@ namespace mozilla { +using namespace layers; + RestyleManager::RestyleManager(nsPresContext* aPresContext) : mPresContext(aPresContext) , mRebuildAllStyleData(false) From 423901ddaf25d2cc5fbe8425c9d6ec4f395e27f7 Mon Sep 17 00:00:00 2001 From: Simon Montagu Date: Tue, 4 Mar 2014 23:31:47 -0800 Subject: [PATCH 112/112] Add more logical-coordinate API to nsIFrame. Bug 735577, r=jfkthame --- layout/generic/nsIFrame.h | 54 ++++++++++++++++++++++++++++++++------- 1 file changed, 45 insertions(+), 9 deletions(-) diff --git a/layout/generic/nsIFrame.h b/layout/generic/nsIFrame.h index c9767e20d5e..8aa5415fb37 100644 --- a/layout/generic/nsIFrame.h +++ b/layout/generic/nsIFrame.h @@ -687,13 +687,50 @@ public: return nsRect(nsPoint(0, 0), mRect.Size()); } /** - * Rect and position in logical coordinates in the frame's writing mode + * Dimensions and position in logical coordinates in the frame's writing mode + * or another writing mode */ mozilla::LogicalRect GetLogicalRect(nscoord aContainerWidth) const { - return mozilla::LogicalRect(GetWritingMode(), GetRect(), aContainerWidth); + return GetLogicalRect(GetWritingMode(), aContainerWidth); } mozilla::LogicalPoint GetLogicalPosition(nscoord aContainerWidth) const { - return GetLogicalRect(aContainerWidth).Origin(GetWritingMode()); + return GetLogicalPosition(GetWritingMode(), aContainerWidth); + } + mozilla::LogicalSize GetLogicalSize() const { + return GetLogicalSize(GetWritingMode()); + } + mozilla::LogicalRect GetLogicalRect(mozilla::WritingMode aWritingMode, + nscoord aContainerWidth) const { + return mozilla::LogicalRect(aWritingMode, GetRect(), aContainerWidth); + } + mozilla::LogicalPoint GetLogicalPosition(mozilla::WritingMode aWritingMode, + nscoord aContainerWidth) const { + return GetLogicalRect(aWritingMode, aContainerWidth).Origin(aWritingMode); + } + mozilla::LogicalSize GetLogicalSize(mozilla::WritingMode aWritingMode) const { + return mozilla::LogicalSize(aWritingMode, GetSize()); + } + nscoord IStart(nscoord aContainerWidth) const { + return IStart(GetWritingMode(), aContainerWidth); + } + nscoord IStart(mozilla::WritingMode aWritingMode, + nscoord aContainerWidth) const { + return GetLogicalPosition(aWritingMode, aContainerWidth).I(aWritingMode); + } + nscoord BStart(nscoord aContainerWidth) const { + return BStart(GetWritingMode(), aContainerWidth); + } + nscoord BStart(mozilla::WritingMode aWritingMode, + nscoord aContainerWidth) const { + return GetLogicalPosition(aWritingMode, aContainerWidth).B(aWritingMode); + } + nscoord ISize() const { return ISize(GetWritingMode()); } + nscoord ISize(mozilla::WritingMode aWritingMode) const { + return GetLogicalSize(aWritingMode).ISize(aWritingMode); + } + nscoord BSize() const { return BSize(GetWritingMode()); } + nscoord BSize(mozilla::WritingMode aWritingMode) const { + return GetLogicalSize(aWritingMode).BSize(aWritingMode); } /** @@ -715,17 +752,16 @@ public: /** * Set this frame's rect from a logical rect in its own writing direction */ - void SetRectFromLogicalRect(const mozilla::LogicalRect& aRect, - nscoord aContainerWidth) { - SetRectFromLogicalRect(GetWritingMode(), aRect, aContainerWidth); + void SetRect(const mozilla::LogicalRect& aRect, nscoord aContainerWidth) { + SetRect(GetWritingMode(), aRect, aContainerWidth); } /** * Set this frame's rect from a logical rect in a different writing direction * (GetPhysicalRect will assert if the writing mode doesn't match) */ - void SetRectFromLogicalRect(mozilla::WritingMode aWritingMode, - const mozilla::LogicalRect& aRect, - nscoord aContainerWidth) { + void SetRect(mozilla::WritingMode aWritingMode, + const mozilla::LogicalRect& aRect, + nscoord aContainerWidth) { SetRect(aRect.GetPhysicalRect(aWritingMode, aContainerWidth)); } void SetSize(const nsSize& aSize) {