From fe3eae0e74db130bceafe9022ab8bf4e46d9aace Mon Sep 17 00:00:00 2001 From: Jan de Mooij Date: Mon, 15 Sep 2014 09:52:37 +0200 Subject: [PATCH 01/53] Bug 1066197 part 2 - Remove js::IteratorNext. r=bhackett --- js/src/jit/BaselineIC.cpp | 2 +- js/src/vm/Interpreter.cpp | 17 +---------------- js/src/vm/Interpreter.h | 3 --- 3 files changed, 2 insertions(+), 20 deletions(-) diff --git a/js/src/jit/BaselineIC.cpp b/js/src/jit/BaselineIC.cpp index c17a45ee40f7..8176d45dada7 100644 --- a/js/src/jit/BaselineIC.cpp +++ b/js/src/jit/BaselineIC.cpp @@ -9927,7 +9927,7 @@ DoIteratorNextFallback(JSContext *cx, BaselineFrame *frame, ICIteratorNext_Fallb FallbackICSpew(cx, stub, "IteratorNext"); RootedObject iteratorObject(cx, &iterValue.toObject()); - if (!IteratorNext(cx, iteratorObject, res)) + if (!js_IteratorNext(cx, iteratorObject, res)) return false; // Check if debug mode toggling made the stub invalid. diff --git a/js/src/vm/Interpreter.cpp b/js/src/vm/Interpreter.cpp index ee5aa8da2cdd..ea83b93c57d6 100644 --- a/js/src/vm/Interpreter.cpp +++ b/js/src/vm/Interpreter.cpp @@ -1116,21 +1116,6 @@ JS_STATIC_ASSERT(JSOP_SETNAME_LENGTH == JSOP_SETPROP_LENGTH); JS_STATIC_ASSERT(JSOP_IFNE_LENGTH == JSOP_IFEQ_LENGTH); JS_STATIC_ASSERT(JSOP_IFNE == JSOP_IFEQ + 1); -bool -js::IteratorNext(JSContext *cx, HandleObject iterobj, MutableHandleValue rval) -{ - if (iterobj->is()) { - NativeIterator *ni = iterobj->as().getNativeIterator(); - if (ni->isKeyIter()) { - JS_ASSERT(ni->props_cursor < ni->props_end); - rval.setString(*ni->current()); - ni->incCursor(); - return true; - } - } - return js_IteratorNext(cx, iterobj, rval); -} - /* * Compute the implicit |this| parameter for a call expression where the callee * funval was resolved from an unqualified name reference to a property on obj @@ -1922,7 +1907,7 @@ CASE(JSOP_ITERNEXT) MutableHandleValue res = REGS.stackHandleAt(-1); RootedObject &obj = rootObject0; obj = ®S.sp[-2].toObject(); - if (!IteratorNext(cx, obj, res)) + if (!js_IteratorNext(cx, obj, res)) goto error; } END_CASE(JSOP_ITERNEXT) diff --git a/js/src/vm/Interpreter.h b/js/src/vm/Interpreter.h index 218a7f17a77a..91dcc2a2eef2 100644 --- a/js/src/vm/Interpreter.h +++ b/js/src/vm/Interpreter.h @@ -439,9 +439,6 @@ bool ImplicitThisOperation(JSContext *cx, HandleObject scopeObj, HandlePropertyName name, MutableHandleValue res); -bool -IteratorNext(JSContext *cx, HandleObject iterobj, MutableHandleValue rval); - bool RunOnceScriptPrologue(JSContext *cx, HandleScript script); From 983463df998d136168669586d45f74f021934734 Mon Sep 17 00:00:00 2001 From: Jan de Mooij Date: Mon, 15 Sep 2014 09:58:27 +0200 Subject: [PATCH 02/53] Bug 1066197 part 3 - Move some iterator functions into js namespace, remove js_ prefix. r=bhackett --- js/src/jit/BaselineIC.cpp | 4 ++-- js/src/jit/CodeGenerator.cpp | 4 ++-- js/src/jsapi.cpp | 2 +- js/src/jsarray.cpp | 10 ++++++---- js/src/jsiter.cpp | 24 ++++++++++++------------ js/src/jsiter.h | 22 +++++++++------------- js/src/jsobj.cpp | 4 ++-- js/src/proxy/Proxy.cpp | 2 +- js/src/vm/Interpreter.cpp | 4 ++-- 9 files changed, 37 insertions(+), 39 deletions(-) diff --git a/js/src/jit/BaselineIC.cpp b/js/src/jit/BaselineIC.cpp index 8176d45dada7..a5a4c2789874 100644 --- a/js/src/jit/BaselineIC.cpp +++ b/js/src/jit/BaselineIC.cpp @@ -9838,7 +9838,7 @@ DoIteratorMoreFallback(JSContext *cx, BaselineFrame *frame, ICIteratorMore_Fallb FallbackICSpew(cx, stub, "IteratorMore"); bool cond; - if (!js_IteratorMore(cx, iterObj, &cond)) + if (!IteratorMore(cx, iterObj, &cond)) return false; res.setBoolean(cond); @@ -9927,7 +9927,7 @@ DoIteratorNextFallback(JSContext *cx, BaselineFrame *frame, ICIteratorNext_Fallb FallbackICSpew(cx, stub, "IteratorNext"); RootedObject iteratorObject(cx, &iterValue.toObject()); - if (!js_IteratorNext(cx, iteratorObject, res)) + if (!IteratorNext(cx, iteratorObject, res)) return false; // Check if debug mode toggling made the stub invalid. diff --git a/js/src/jit/CodeGenerator.cpp b/js/src/jit/CodeGenerator.cpp index f4e0a1650468..07565e3897b6 100644 --- a/js/src/jit/CodeGenerator.cpp +++ b/js/src/jit/CodeGenerator.cpp @@ -6370,7 +6370,7 @@ LoadNativeIterator(MacroAssembler &masm, Register obj, Register dest, Label *fai } typedef bool (*IteratorNextFn)(JSContext *, HandleObject, MutableHandleValue); -static const VMFunction IteratorNextInfo = FunctionInfo(js_IteratorNext); +static const VMFunction IteratorNextInfo = FunctionInfo(IteratorNext); bool CodeGenerator::visitIteratorNext(LIteratorNext *lir) @@ -6401,7 +6401,7 @@ CodeGenerator::visitIteratorNext(LIteratorNext *lir) } typedef bool (*IteratorMoreFn)(JSContext *, HandleObject, bool *); -static const VMFunction IteratorMoreInfo = FunctionInfo(js_IteratorMore); +static const VMFunction IteratorMoreInfo = FunctionInfo(IteratorMore); bool CodeGenerator::visitIteratorMore(LIteratorMore *lir) diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp index 505e89031a01..701088f0a429 100644 --- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -6143,7 +6143,7 @@ JS_PUBLIC_API(bool) JS_ThrowStopIteration(JSContext *cx) { AssertHeapIsIdle(cx); - return js_ThrowStopIteration(cx); + return ThrowStopIteration(cx); } JS_PUBLIC_API(bool) diff --git a/js/src/jsarray.cpp b/js/src/jsarray.cpp index 274dc8946bf7..c2e27226c8fc 100644 --- a/js/src/jsarray.cpp +++ b/js/src/jsarray.cpp @@ -346,7 +346,7 @@ DeleteArrayElement(JSContext *cx, HandleObject obj, double index, bool *succeede obj->markDenseElementsNotPacked(cx); obj->setDenseElement(idx, MagicValue(JS_ELEMENTS_HOLE)); } - if (!js_SuppressDeletedElement(cx, obj, idx)) + if (!SuppressDeletedElement(cx, obj, idx)) return false; } } @@ -1377,12 +1377,14 @@ array_reverse(JSContext *cx, unsigned argc, Value *vp) orighi = obj->getDenseElement(hi); obj->setDenseElement(lo, orighi); if (orighi.isMagic(JS_ELEMENTS_HOLE) && - !js_SuppressDeletedProperty(cx, obj, INT_TO_JSID(lo))) { + !SuppressDeletedProperty(cx, obj, INT_TO_JSID(lo))) + { return false; } obj->setDenseElement(hi, origlo); if (origlo.isMagic(JS_ELEMENTS_HOLE) && - !js_SuppressDeletedProperty(cx, obj, INT_TO_JSID(hi))) { + !SuppressDeletedProperty(cx, obj, INT_TO_JSID(hi))) + { return false; } } @@ -2211,7 +2213,7 @@ js::array_shift(JSContext *cx, unsigned argc, Value *vp) if (!SetLengthProperty(cx, obj, newlen)) return false; - return js_SuppressDeletedProperty(cx, obj, INT_TO_JSID(newlen)); + return SuppressDeletedProperty(cx, obj, INT_TO_JSID(newlen)); } /* Steps 5, 10. */ diff --git a/js/src/jsiter.cpp b/js/src/jsiter.cpp index 652c13c5ce67..42dd931099b7 100644 --- a/js/src/jsiter.cpp +++ b/js/src/jsiter.cpp @@ -817,7 +817,7 @@ js::CreateItrResultObject(JSContext *cx, HandleValue value, bool done) } bool -js_ThrowStopIteration(JSContext *cx) +js::ThrowStopIteration(JSContext *cx) { JS_ASSERT(!JS_IsExceptionPending(cx)); @@ -865,15 +865,15 @@ iterator_next_impl(JSContext *cx, CallArgs args) RootedObject thisObj(cx, &args.thisv().toObject()); bool more; - if (!js_IteratorMore(cx, thisObj, &more)) + if (!IteratorMore(cx, thisObj, &more)) return false; if (!more) { - js_ThrowStopIteration(cx); + ThrowStopIteration(cx); return false; } - return js_IteratorNext(cx, thisObj, args.rval()); + return IteratorNext(cx, thisObj, args.rval()); } static bool @@ -1209,7 +1209,7 @@ public: } /* anonymous namespace */ bool -js_SuppressDeletedProperty(JSContext *cx, HandleObject obj, jsid id) +js::SuppressDeletedProperty(JSContext *cx, HandleObject obj, jsid id) { if (JSID_IS_SYMBOL(id)) return true; @@ -1221,12 +1221,12 @@ js_SuppressDeletedProperty(JSContext *cx, HandleObject obj, jsid id) } bool -js_SuppressDeletedElement(JSContext *cx, HandleObject obj, uint32_t index) +js::SuppressDeletedElement(JSContext *cx, HandleObject obj, uint32_t index) { RootedId id(cx); if (!IndexToId(cx, index, &id)) return false; - return js_SuppressDeletedProperty(cx, obj, id); + return SuppressDeletedProperty(cx, obj, id); } namespace { @@ -1248,13 +1248,13 @@ class IndexRangePredicate { } /* anonymous namespace */ bool -js_SuppressDeletedElements(JSContext *cx, HandleObject obj, uint32_t begin, uint32_t end) +js::SuppressDeletedElements(JSContext *cx, HandleObject obj, uint32_t begin, uint32_t end) { return SuppressDeletedPropertyHelper(cx, obj, IndexRangePredicate(begin, end)); } bool -js_IteratorMore(JSContext *cx, HandleObject iterobj, bool *res) +js::IteratorMore(JSContext *cx, HandleObject iterobj, bool *res) { /* Fast path for native iterators */ NativeIterator *ni = nullptr; @@ -1320,7 +1320,7 @@ js_IteratorMore(JSContext *cx, HandleObject iterobj, bool *res) } bool -js_IteratorNext(JSContext *cx, HandleObject iterobj, MutableHandleValue rval) +js::IteratorNext(JSContext *cx, HandleObject iterobj, MutableHandleValue rval) { /* Fast path for native iterators */ if (iterobj->is()) { @@ -1888,7 +1888,7 @@ SendToGenerator(JSContext *cx, JSGeneratorOp op, HandleObject obj, // if needed. rval.setUndefined(); if (op != JSGENOP_CLOSE) - ok = js_ThrowStopIteration(cx); + ok = ThrowStopIteration(cx); } } @@ -1936,7 +1936,7 @@ legacy_generator_next(JSContext *cx, CallArgs args) JSGenerator *gen = thisObj->as().getGenerator(); if (gen->state == JSGEN_CLOSED) - return js_ThrowStopIteration(cx); + return ThrowStopIteration(cx); return SendToGenerator(cx, JSGENOP_SEND, thisObj, gen, args.get(0), LegacyGenerator, args.rval()); diff --git a/js/src/jsiter.h b/js/src/jsiter.h index d555b66c2524..6d03ca89bea9 100644 --- a/js/src/jsiter.h +++ b/js/src/jsiter.h @@ -183,7 +183,7 @@ bool CloseIterator(JSContext *cx, HandleObject iterObj); bool -UnwindIteratorForException(JSContext *cx, js::HandleObject obj); +UnwindIteratorForException(JSContext *cx, HandleObject obj); void UnwindIteratorForUncatchableException(JSContext *cx, JSObject *obj); @@ -191,16 +191,14 @@ UnwindIteratorForUncatchableException(JSContext *cx, JSObject *obj); bool IteratorConstructor(JSContext *cx, unsigned argc, Value *vp); -} /* namespace js */ +extern bool +SuppressDeletedProperty(JSContext *cx, HandleObject obj, jsid id); extern bool -js_SuppressDeletedProperty(JSContext *cx, js::HandleObject obj, jsid id); +SuppressDeletedElement(JSContext *cx, HandleObject obj, uint32_t index); extern bool -js_SuppressDeletedElement(JSContext *cx, js::HandleObject obj, uint32_t index); - -extern bool -js_SuppressDeletedElements(JSContext *cx, js::HandleObject obj, uint32_t begin, uint32_t end); +SuppressDeletedElements(JSContext *cx, HandleObject obj, uint32_t begin, uint32_t end); /* * IteratorMore() indicates whether another value is available. It might @@ -208,22 +206,20 @@ js_SuppressDeletedElements(JSContext *cx, js::HandleObject obj, uint32_t begin, * picked up by IteratorNext(). The value is cached in the current context. */ extern bool -js_IteratorMore(JSContext *cx, js::HandleObject iterobj, bool *res); +IteratorMore(JSContext *cx, HandleObject iterobj, bool *res); extern bool -js_IteratorNext(JSContext *cx, js::HandleObject iterobj, js::MutableHandleValue rval); +IteratorNext(JSContext *cx, HandleObject iterobj, MutableHandleValue rval); extern bool -js_ThrowStopIteration(JSContext *cx); - -namespace js { +ThrowStopIteration(JSContext *cx); /* * Create an object of the form { value: VALUE, done: DONE }. * ES6 draft from 2013-09-05, section 25.4.3.4. */ extern JSObject * -CreateItrResultObject(JSContext *cx, js::HandleValue value, bool done); +CreateItrResultObject(JSContext *cx, HandleValue value, bool done); } /* namespace js */ diff --git a/js/src/jsobj.cpp b/js/src/jsobj.cpp index 2cb7cec39cac..dcd9810bb9a6 100644 --- a/js/src/jsobj.cpp +++ b/js/src/jsobj.cpp @@ -5749,7 +5749,7 @@ baseops::DeleteGeneric(JSContext *cx, HandleObject obj, HandleId id, bool *succe return false; obj->setDenseElementHole(cx, JSID_TO_INT(id)); - return js_SuppressDeletedProperty(cx, obj, id); + return SuppressDeletedProperty(cx, obj, id); } if (!shape->configurable()) { @@ -5763,7 +5763,7 @@ baseops::DeleteGeneric(JSContext *cx, HandleObject obj, HandleId id, bool *succe if (!succeeded) return true; - return obj->removeProperty(cx, id) && js_SuppressDeletedProperty(cx, obj, id); + return obj->removeProperty(cx, id) && SuppressDeletedProperty(cx, obj, id); } bool diff --git a/js/src/proxy/Proxy.cpp b/js/src/proxy/Proxy.cpp index 4a48dab4b1ff..7db463bf2613 100644 --- a/js/src/proxy/Proxy.cpp +++ b/js/src/proxy/Proxy.cpp @@ -712,7 +712,7 @@ js::proxy_DeleteGeneric(JSContext *cx, HandleObject obj, HandleId id, bool *succ if (!Proxy::delete_(cx, obj, id, &deleted)) return false; *succeeded = deleted; - return js_SuppressDeletedProperty(cx, obj, id); + return SuppressDeletedProperty(cx, obj, id); } void diff --git a/js/src/vm/Interpreter.cpp b/js/src/vm/Interpreter.cpp index ea83b93c57d6..44e313a6bfe8 100644 --- a/js/src/vm/Interpreter.cpp +++ b/js/src/vm/Interpreter.cpp @@ -1894,7 +1894,7 @@ CASE(JSOP_MOREITER) RootedObject &obj = rootObject0; obj = ®S.sp[-2].toObject(); bool cond; - if (!js_IteratorMore(cx, obj, &cond)) + if (!IteratorMore(cx, obj, &cond)) goto error; REGS.sp[-1].setBoolean(cond); } @@ -1907,7 +1907,7 @@ CASE(JSOP_ITERNEXT) MutableHandleValue res = REGS.stackHandleAt(-1); RootedObject &obj = rootObject0; obj = ®S.sp[-2].toObject(); - if (!js_IteratorNext(cx, obj, res)) + if (!IteratorNext(cx, obj, res)) goto error; } END_CASE(JSOP_ITERNEXT) From 81e969a67017bef2289d4ea9eb09aa63e9a65f90 Mon Sep 17 00:00:00 2001 From: David Burns Date: Mon, 15 Sep 2014 10:48:56 +0100 Subject: [PATCH 03/53] Bug 755475: Allow the getting and setting of the currently browser window position from Marionette; r=jgriffin --- .../client/marionette/marionette.py | 16 ++++++++ .../tests/unit/test_window_position.py | 34 +++++++++++++++ .../marionette/tests/unit/unit-tests.ini | 2 + testing/marionette/marionette-server.js | 41 +++++++++++++++++++ 4 files changed, 93 insertions(+) create mode 100644 testing/marionette/client/marionette/tests/unit/test_window_position.py diff --git a/testing/marionette/client/marionette/marionette.py b/testing/marionette/client/marionette/marionette.py index 52b9e3c071ae..73b499907948 100644 --- a/testing/marionette/client/marionette/marionette.py +++ b/testing/marionette/client/marionette/marionette.py @@ -888,6 +888,22 @@ class Marionette(object): self.window = self._send_message("getWindowHandle", "value") return self.window + def get_window_position(self): + """Get the current window's position + Return a dictionary with the keys x and y + :returns: a dictionary with x and y + """ + return self._send_message("getWindowPosition", "value") + + def set_window_position(self, x, y): + """ + Set the position of the current window + :param x: x coordinate for the top left of the window + :param y: y coordinate for the top left of the window + """ + response = self._send_message("setWindowPosition", "ok", x=x, y=y) + return response + @property def title(self): ''' diff --git a/testing/marionette/client/marionette/tests/unit/test_window_position.py b/testing/marionette/client/marionette/tests/unit/test_window_position.py new file mode 100644 index 000000000000..70879f8d1c98 --- /dev/null +++ b/testing/marionette/client/marionette/tests/unit/test_window_position.py @@ -0,0 +1,34 @@ +#Copyright 2007-2009 WebDriver committers +# +#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. + +from marionette_test import MarionetteTestCase +from errors import MarionetteException + +class TestWindowPosition(MarionetteTestCase): + + def test_that_we_return_the_window_position(self): + position = self.marionette.get_window_position() + self.assertTrue(isinstance(position['x'], int)) + self.assertTrue(isinstance(position['y'], int)) + + def test_that_we_can_set_the_window_position(self): + old_position = self.marionette.get_window_position() + new_position = {"x": old_position['x'] + 10, "y": old_position['y'] + 10} + self.marionette.set_window_position(new_position['x'], new_position['y']) + self.assertNotEqual(old_position['x'], new_position['x']) + self.assertNotEqual(old_position['y'], new_position['y']) + + def test_that_we_can_get_an_error_when_passing_something_other_than_integers(self): + self.assertRaises(MarionetteException, self.marionette.set_window_position, "a","b") + diff --git a/testing/marionette/client/marionette/tests/unit/unit-tests.ini b/testing/marionette/client/marionette/tests/unit/unit-tests.ini index f508bfafa554..da7cb44a81fa 100644 --- a/testing/marionette/client/marionette/tests/unit/unit-tests.ini +++ b/testing/marionette/client/marionette/tests/unit/unit-tests.ini @@ -103,6 +103,8 @@ b2g = false b2g = false [test_window_management.py] b2g = false +[test_window_position.py] +b2g = false [test_appcache.py] [test_screenshot.py] diff --git a/testing/marionette/marionette-server.js b/testing/marionette/marionette-server.js index b6ff84805267..a584c3117409 100644 --- a/testing/marionette/marionette-server.js +++ b/testing/marionette/marionette-server.js @@ -1256,6 +1256,45 @@ MarionetteServerConnection.prototype = { this.sendResponse(res, this.command_id); }, + /** + * Get the current window position. + */ + getWindowPosition: function MDA_getWindowPosition() { + this.command_id = this.getCommandId(); + let curWindow = this.getCurrentWindow(); + this.sendResponse({ x: curWindow.screenX, y: curWindow.screenY}, this.command_id); + }, + + /** + * Set the window position of the browser on the OS Window Manager + * + * @param object aRequest + * 'x': the x co-ordinate of the top/left of the window that + * it will be moved to + * 'y': the y co-ordinate of the top/left of the window that + * it will be moved to + */ + setWindowPosition: function MDA_setWindowPosition(aRequest) { + let command_id = this.command_id = this.getCommandId(); + if (appName !== "Firefox") { + this.sendError("Unable to set the window position on mobile", 61, null, + command_id); + + } + else { + let x = parseInt(aRequest.parameters.x);; + let y = parseInt(aRequest.parameters.y); + + if (isNaN(x) || isNaN(y)) { + this.sendError("x and y arguments should be integers", 13, null, command_id); + return; + } + let curWindow = this.getCurrentWindow(); + curWindow.moveTo(x, y); + this.sendOk(command_id); + } + }, + /** * Switch to a window based on name or server-assigned id. * Searches based on name, then id. @@ -2590,6 +2629,8 @@ MarionetteServerConnection.prototype.requestTypes = { "getWindowHandles": MarionetteServerConnection.prototype.getWindowHandles, "getCurrentWindowHandles": MarionetteServerConnection.prototype.getWindowHandles, // Selenium 2 compat "getWindows": MarionetteServerConnection.prototype.getWindowHandles, // deprecated + "getWindowPosition": MarionetteServerConnection.prototype.getWindowPosition, + "setWindowPosition": MarionetteServerConnection.prototype.setWindowPosition, "getActiveFrame": MarionetteServerConnection.prototype.getActiveFrame, "switchToFrame": MarionetteServerConnection.prototype.switchToFrame, "switchToWindow": MarionetteServerConnection.prototype.switchToWindow, From 3f498496ad2977478485973d997524cc95ad34f7 Mon Sep 17 00:00:00 2001 From: Markus Stange Date: Mon, 15 Sep 2014 12:12:50 +0200 Subject: [PATCH 04/53] Bug 1066270 - Add the ability to specify the filter chain in the nsFilterInstance constructor instead of always getting it from the frame. r=roc --- layout/svg/nsFilterInstance.cpp | 22 +++++++++++++--------- layout/svg/nsFilterInstance.h | 4 +++- 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/layout/svg/nsFilterInstance.cpp b/layout/svg/nsFilterInstance.cpp index acd69ba2de42..cce14c752eac 100644 --- a/layout/svg/nsFilterInstance.cpp +++ b/layout/svg/nsFilterInstance.cpp @@ -31,7 +31,8 @@ nsFilterInstance::PaintFilteredFrame(nsIFrame *aFilteredFrame, nsSVGFilterPaintCallback *aPaintCallback, const nsRegion *aDirtyArea) { - nsFilterInstance instance(aFilteredFrame, aPaintCallback, aTransform, + auto& filterChain = aFilteredFrame->StyleSVGReset()->mFilters; + nsFilterInstance instance(aFilteredFrame, filterChain, aPaintCallback, aTransform, aDirtyArea, nullptr, nullptr, nullptr); if (!instance.IsInitialized()) { return NS_OK; @@ -48,7 +49,8 @@ nsFilterInstance::GetPostFilterDirtyArea(nsIFrame *aFilteredFrame, } gfxMatrix unused; // aPaintTransform arg not used since we're not painting - nsFilterInstance instance(aFilteredFrame, nullptr, unused, nullptr, + auto& filterChain = aFilteredFrame->StyleSVGReset()->mFilters; + nsFilterInstance instance(aFilteredFrame, filterChain, nullptr, unused, nullptr, &aPreFilterDirtyRegion); if (!instance.IsInitialized()) { return nsRegion(); @@ -65,7 +67,8 @@ nsFilterInstance::GetPreFilterNeededArea(nsIFrame *aFilteredFrame, const nsRegion& aPostFilterDirtyRegion) { gfxMatrix unused; // aPaintTransform arg not used since we're not painting - nsFilterInstance instance(aFilteredFrame, nullptr, unused, + auto& filterChain = aFilteredFrame->StyleSVGReset()->mFilters; + nsFilterInstance instance(aFilteredFrame, filterChain, nullptr, unused, &aPostFilterDirtyRegion); if (!instance.IsInitialized()) { return nsRect(); @@ -93,7 +96,8 @@ nsFilterInstance::GetPostFilterBounds(nsIFrame *aFilteredFrame, } gfxMatrix unused; // aPaintTransform arg not used since we're not painting - nsFilterInstance instance(aFilteredFrame, nullptr, unused, nullptr, + auto& filterChain = aFilteredFrame->StyleSVGReset()->mFilters; + nsFilterInstance instance(aFilteredFrame, filterChain, nullptr, unused, nullptr, preFilterRegionPtr, aPreFilterBounds, aOverrideBBox); if (!instance.IsInitialized()) { @@ -104,6 +108,7 @@ nsFilterInstance::GetPostFilterBounds(nsIFrame *aFilteredFrame, } nsFilterInstance::nsFilterInstance(nsIFrame *aTargetFrame, + const nsTArray& aFilterChain, nsSVGFilterPaintCallback *aPaintCallback, const gfxMatrix& aPaintTransform, const nsRegion *aPostFilterDirtyRegion, @@ -151,7 +156,7 @@ nsFilterInstance::nsFilterInstance(nsIFrame *aTargetFrame, mFrameSpaceInCSSPxToFilterSpaceTransform.Invert(); // Build the filter graph. - rv = BuildPrimitives(); + rv = BuildPrimitives(aFilterChain); if (NS_FAILED(rv)) { return; } @@ -215,14 +220,13 @@ nsFilterInstance::FilterSpaceToUserSpace(const gfxRect& aFilterSpaceRect) const } nsresult -nsFilterInstance::BuildPrimitives() +nsFilterInstance::BuildPrimitives(const nsTArray& aFilterChain) { NS_ASSERTION(!mPrimitiveDescriptions.Length(), "expected to start building primitives from scratch"); - const nsTArray& filters = mTargetFrame->StyleSVGReset()->mFilters; - for (uint32_t i = 0; i < filters.Length(); i++) { - nsresult rv = BuildPrimitivesForFilter(filters[i]); + for (uint32_t i = 0; i < aFilterChain.Length(); i++) { + nsresult rv = BuildPrimitivesForFilter(aFilterChain[i]); if (NS_FAILED(rv)) { return rv; } diff --git a/layout/svg/nsFilterInstance.h b/layout/svg/nsFilterInstance.h index 90a67687eaba..053ca603b8b1 100644 --- a/layout/svg/nsFilterInstance.h +++ b/layout/svg/nsFilterInstance.h @@ -94,6 +94,7 @@ public: /** * @param aTargetFrame The frame of the filtered element under consideration. + * @param aFilterChain The list of filters to apply. * @param aPaintCallback [optional] The callback that Render() should use to * paint. Only required if you will call Render(). * @param aPaintTransform The transform to apply to convert to @@ -110,6 +111,7 @@ public: * element. */ nsFilterInstance(nsIFrame *aTargetFrame, + const nsTArray& aFilterChain, nsSVGFilterPaintCallback *aPaintCallback, const gfxMatrix& aPaintTransform, const nsRegion *aPostFilterDirtyRegion = nullptr, @@ -205,7 +207,7 @@ private: * filter primitives and their connections. This populates * mPrimitiveDescriptions and mInputImages. */ - nsresult BuildPrimitives(); + nsresult BuildPrimitives(const nsTArray& aFilterChain); /** * Add to the list of FilterPrimitiveDescriptions for a particular SVG From b930e582d3aa5f5a89fcf470eac237a2ae9e9136 Mon Sep 17 00:00:00 2001 From: Markus Stange Date: Mon, 15 Sep 2014 12:12:50 +0200 Subject: [PATCH 05/53] Bug 1066270 - Generalize SVG length resolution for nsIFrame-less consumers. r=roc --- content/svg/content/src/nsSVGLength2.cpp | 126 ++++++++++++++--------- content/svg/content/src/nsSVGLength2.h | 78 +++++++++++--- layout/svg/nsSVGUtils.cpp | 50 ++++++--- layout/svg/nsSVGUtils.h | 14 +-- 4 files changed, 184 insertions(+), 84 deletions(-) diff --git a/content/svg/content/src/nsSVGLength2.cpp b/content/svg/content/src/nsSVGLength2.cpp index 90c9a31d7790..2bc5083c1185 100644 --- a/content/svg/content/src/nsSVGLength2.cpp +++ b/content/svg/content/src/nsSVGLength2.cpp @@ -114,6 +114,8 @@ GetValueFromString(const nsAString& aString, return IsValidUnitType(*aUnitType); } +static float GetMMPerPixel() { return MM_PER_INCH_FLOAT / 96; } + static float FixAxisLength(float aLength) { @@ -124,22 +126,73 @@ FixAxisLength(float aLength) return aLength; } -float -nsSVGLength2::GetAxisLength(SVGSVGElement *aCtx) const +SVGElementMetrics::SVGElementMetrics(nsSVGElement* aSVGElement, + SVGSVGElement* aCtx) + : mSVGElement(aSVGElement) + , mCtx(aCtx) { - if (!aCtx) - return 1; - - return FixAxisLength(aCtx->GetLength(mCtxType)); } float -nsSVGLength2::GetAxisLength(nsIFrame *aNonSVGFrame) const +SVGElementMetrics::GetEmLength() const { - gfx::Size size = - nsSVGIntegrationUtils::GetSVGCoordContextForNonSVGFrame(aNonSVGFrame); + return SVGContentUtils::GetFontSize(mSVGElement); +} + +float +SVGElementMetrics::GetExLength() const +{ + return SVGContentUtils::GetFontXHeight(mSVGElement); +} + +float +SVGElementMetrics::GetAxisLength(uint8_t aCtxType) const +{ + if (!EnsureCtx()) { + return 1; + } + + return FixAxisLength(mCtx->GetLength(aCtxType)); +} + +bool +SVGElementMetrics::EnsureCtx() const +{ + if (!mCtx && mSVGElement) { + mCtx = mSVGElement->GetCtx(); + } + return mCtx != nullptr; +} + +NonSVGFrameUserSpaceMetrics::NonSVGFrameUserSpaceMetrics(nsIFrame* aFrame) + : mFrame(aFrame) +{ +} + +float +NonSVGFrameUserSpaceMetrics::GetEmLength() const +{ + return SVGContentUtils::GetFontSize(mFrame); +} + +float +NonSVGFrameUserSpaceMetrics::GetExLength() const +{ + return SVGContentUtils::GetFontXHeight(mFrame); +} + +gfx::Size +NonSVGFrameUserSpaceMetrics::GetSize() const +{ + return nsSVGIntegrationUtils::GetSVGCoordContextForNonSVGFrame(mFrame); +} + +float +UserSpaceMetricsWithSize::GetAxisLength(uint8_t aCtxType) const +{ + gfx::Size size = GetSize(); float length; - switch (mCtxType) { + switch (aCtxType) { case SVGContentUtils::X: length = size.width; break; @@ -161,55 +214,28 @@ float nsSVGLength2::GetUnitScaleFactor(nsSVGElement *aSVGElement, uint8_t aUnitType) const { - switch (aUnitType) { - case nsIDOMSVGLength::SVG_LENGTHTYPE_NUMBER: - case nsIDOMSVGLength::SVG_LENGTHTYPE_PX: - return 1; - case nsIDOMSVGLength::SVG_LENGTHTYPE_EMS: - return 1 / GetEmLength(aSVGElement); - case nsIDOMSVGLength::SVG_LENGTHTYPE_EXS: - return 1 / GetExLength(aSVGElement); - } - - return GetUnitScaleFactor(aSVGElement->GetCtx(), aUnitType); + return GetUnitScaleFactor(SVGElementMetrics(aSVGElement), aUnitType); } float nsSVGLength2::GetUnitScaleFactor(SVGSVGElement *aCtx, uint8_t aUnitType) const { - switch (aUnitType) { - case nsIDOMSVGLength::SVG_LENGTHTYPE_NUMBER: - case nsIDOMSVGLength::SVG_LENGTHTYPE_PX: - return 1; - case nsIDOMSVGLength::SVG_LENGTHTYPE_MM: - return GetMMPerPixel(); - case nsIDOMSVGLength::SVG_LENGTHTYPE_CM: - return GetMMPerPixel() / 10.0f; - case nsIDOMSVGLength::SVG_LENGTHTYPE_IN: - return GetMMPerPixel() / MM_PER_INCH_FLOAT; - case nsIDOMSVGLength::SVG_LENGTHTYPE_PT: - return GetMMPerPixel() * POINTS_PER_INCH_FLOAT / MM_PER_INCH_FLOAT; - case nsIDOMSVGLength::SVG_LENGTHTYPE_PC: - return GetMMPerPixel() * POINTS_PER_INCH_FLOAT / MM_PER_INCH_FLOAT / 12.0f; - case nsIDOMSVGLength::SVG_LENGTHTYPE_PERCENTAGE: - return 100.0f / GetAxisLength(aCtx); - case nsIDOMSVGLength::SVG_LENGTHTYPE_EMS: - return 1 / GetEmLength(aCtx); - case nsIDOMSVGLength::SVG_LENGTHTYPE_EXS: - return 1 / GetExLength(aCtx); - default: - NS_NOTREACHED("Unknown unit type"); - return 0; - } + return GetUnitScaleFactor(SVGElementMetrics(aCtx, aCtx), aUnitType); } float nsSVGLength2::GetUnitScaleFactor(nsIFrame *aFrame, uint8_t aUnitType) const { nsIContent* content = aFrame->GetContent(); - if (content->IsSVG()) - return GetUnitScaleFactor(static_cast(content), aUnitType); + if (content->IsSVG()) { + return GetUnitScaleFactor(SVGElementMetrics(static_cast(content)), aUnitType); + } + return GetUnitScaleFactor(NonSVGFrameUserSpaceMetrics(aFrame), aUnitType); +} +float +nsSVGLength2::GetUnitScaleFactor(const UserSpaceMetrics& aMetrics, uint8_t aUnitType) const +{ switch (aUnitType) { case nsIDOMSVGLength::SVG_LENGTHTYPE_NUMBER: case nsIDOMSVGLength::SVG_LENGTHTYPE_PX: @@ -225,11 +251,11 @@ nsSVGLength2::GetUnitScaleFactor(nsIFrame *aFrame, uint8_t aUnitType) const case nsIDOMSVGLength::SVG_LENGTHTYPE_PC: return GetMMPerPixel() * POINTS_PER_INCH_FLOAT / MM_PER_INCH_FLOAT / 12.0f; case nsIDOMSVGLength::SVG_LENGTHTYPE_PERCENTAGE: - return 100.0f / GetAxisLength(aFrame); + return 100.0f / aMetrics.GetAxisLength(mCtxType); case nsIDOMSVGLength::SVG_LENGTHTYPE_EMS: - return 1 / GetEmLength(aFrame); + return 1 / aMetrics.GetEmLength(); case nsIDOMSVGLength::SVG_LENGTHTYPE_EXS: - return 1 / GetExLength(aFrame); + return 1 / aMetrics.GetExLength(); default: NS_NOTREACHED("Unknown unit type"); return 0; diff --git a/content/svg/content/src/nsSVGLength2.h b/content/svg/content/src/nsSVGLength2.h index a9923fda8248..e2f4b0055ec0 100644 --- a/content/svg/content/src/nsSVGLength2.h +++ b/content/svg/content/src/nsSVGLength2.h @@ -16,6 +16,7 @@ #include "nsMathUtils.h" #include "nsSVGElement.h" #include "SVGContentUtils.h" +#include "mozilla/gfx/Rect.h" class nsIFrame; class nsSMILValue; @@ -29,10 +30,64 @@ class SVGSVGElement; } } +namespace mozilla { +namespace dom { + +class UserSpaceMetrics +{ +public: + virtual ~UserSpaceMetrics() {} + + virtual float GetEmLength() const = 0; + virtual float GetExLength() const = 0; + virtual float GetAxisLength(uint8_t aCtxType) const = 0; +}; + +class UserSpaceMetricsWithSize : public UserSpaceMetrics +{ +public: + virtual gfx::Size GetSize() const = 0; + virtual float GetAxisLength(uint8_t aCtxType) const MOZ_OVERRIDE; +}; + +class SVGElementMetrics : public UserSpaceMetrics +{ +public: + SVGElementMetrics(nsSVGElement* aSVGElement, + mozilla::dom::SVGSVGElement* aCtx = nullptr); + + virtual float GetEmLength() const MOZ_OVERRIDE; + virtual float GetExLength() const MOZ_OVERRIDE; + virtual float GetAxisLength(uint8_t aCtxType) const MOZ_OVERRIDE; + +private: + bool EnsureCtx() const; + + nsSVGElement* mSVGElement; + mutable mozilla::dom::SVGSVGElement* mCtx; +}; + +class NonSVGFrameUserSpaceMetrics : public UserSpaceMetricsWithSize +{ +public: + NonSVGFrameUserSpaceMetrics(nsIFrame* aFrame); + + virtual float GetEmLength() const MOZ_OVERRIDE; + virtual float GetExLength() const MOZ_OVERRIDE; + virtual gfx::Size GetSize() const MOZ_OVERRIDE; + +private: + nsIFrame* mFrame; +}; + +} +} + class nsSVGLength2 { friend class mozilla::dom::SVGAnimatedLength; friend class mozilla::DOMSVGLength; + typedef mozilla::dom::UserSpaceMetrics UserSpaceMetrics; public: void Init(uint8_t aCtxType = SVGContentUtils::XY, uint8_t aAttrEnum = 0xff, @@ -63,10 +118,15 @@ public: float GetBaseValue(nsSVGElement* aSVGElement) const { return mBaseVal / GetUnitScaleFactor(aSVGElement, mSpecifiedUnitType); } + float GetAnimValue(nsSVGElement* aSVGElement) const { return mAnimVal / GetUnitScaleFactor(aSVGElement, mSpecifiedUnitType); } float GetAnimValue(nsIFrame* aFrame) const { return mAnimVal / GetUnitScaleFactor(aFrame, mSpecifiedUnitType); } + float GetAnimValue(mozilla::dom::SVGSVGElement* aCtx) const + { return mAnimVal / GetUnitScaleFactor(aCtx, mSpecifiedUnitType); } + float GetAnimValue(const UserSpaceMetrics& aMetrics) const + { return mAnimVal / GetUnitScaleFactor(aMetrics, mSpecifiedUnitType); } uint8_t GetCtxType() const { return mCtxType; } uint8_t GetSpecifiedUnitType() const { return mSpecifiedUnitType; } @@ -77,8 +137,6 @@ public: float GetBaseValue(mozilla::dom::SVGSVGElement* aCtx) const { return mBaseVal / GetUnitScaleFactor(aCtx, mSpecifiedUnitType); } - float GetAnimValue(mozilla::dom::SVGSVGElement* aCtx) const - { return mAnimVal / GetUnitScaleFactor(aCtx, mSpecifiedUnitType); } bool HasBaseVal() const { return mIsBaseSet; @@ -106,21 +164,9 @@ private: uint8_t mCtxType; // X, Y or Unspecified bool mIsAnimated:1; bool mIsBaseSet:1; - - static float GetMMPerPixel() { return MM_PER_INCH_FLOAT / 96; } - float GetAxisLength(nsIFrame *aNonSVGFrame) const; - static float GetEmLength(nsIFrame *aFrame) - { return SVGContentUtils::GetFontSize(aFrame); } - static float GetExLength(nsIFrame *aFrame) - { return SVGContentUtils::GetFontXHeight(aFrame); } - float GetUnitScaleFactor(nsIFrame *aFrame, uint8_t aUnitType) const; - float GetMMPerPixel(mozilla::dom::SVGSVGElement *aCtx) const; - float GetAxisLength(mozilla::dom::SVGSVGElement *aCtx) const; - static float GetEmLength(nsSVGElement *aSVGElement) - { return SVGContentUtils::GetFontSize(aSVGElement); } - static float GetExLength(nsSVGElement *aSVGElement) - { return SVGContentUtils::GetFontXHeight(aSVGElement); } + float GetUnitScaleFactor(nsIFrame *aFrame, uint8_t aUnitType) const; + float GetUnitScaleFactor(const UserSpaceMetrics& aMetrics, uint8_t aUnitType) const; float GetUnitScaleFactor(nsSVGElement *aSVGElement, uint8_t aUnitType) const; float GetUnitScaleFactor(mozilla::dom::SVGSVGElement *aCtx, uint8_t aUnitType) const; diff --git a/layout/svg/nsSVGUtils.cpp b/layout/svg/nsSVGUtils.cpp index daae12a002dd..e81272819957 100644 --- a/layout/svg/nsSVGUtils.cpp +++ b/layout/svg/nsSVGUtils.cpp @@ -339,6 +339,12 @@ nsSVGUtils::UserSpace(nsIFrame *aNonSVGContext, const nsSVGLength2 *aLength) return aLength->GetAnimValue(aNonSVGContext); } +float +nsSVGUtils::UserSpace(const UserSpaceMetrics& aMetrics, const nsSVGLength2 *aLength) +{ + return aLength->GetAnimValue(aMetrics); +} + nsSVGOuterSVGFrame * nsSVGUtils::GetOuterSVGFrame(nsIFrame *aFrame) { @@ -1017,23 +1023,43 @@ nsSVGUtils::FrameSpaceInCSSPxToUserSpaceOffset(nsIFrame *aFrame) return gfxPoint(); } +static gfxRect +GetBoundingBoxRelativeRect(const nsSVGLength2 *aXYWH, + const gfxRect& aBBox) +{ + return gfxRect(aBBox.x + nsSVGUtils::ObjectSpace(aBBox, &aXYWH[0]), + aBBox.y + nsSVGUtils::ObjectSpace(aBBox, &aXYWH[1]), + nsSVGUtils::ObjectSpace(aBBox, &aXYWH[2]), + nsSVGUtils::ObjectSpace(aBBox, &aXYWH[3])); +} + gfxRect nsSVGUtils::GetRelativeRect(uint16_t aUnits, const nsSVGLength2 *aXYWH, - const gfxRect &aBBox, nsIFrame *aFrame) + const gfxRect& aBBox, + const UserSpaceMetrics& aMetrics) { - float x, y, width, height; if (aUnits == SVG_UNIT_TYPE_OBJECTBOUNDINGBOX) { - x = aBBox.X() + ObjectSpace(aBBox, &aXYWH[0]); - y = aBBox.Y() + ObjectSpace(aBBox, &aXYWH[1]); - width = ObjectSpace(aBBox, &aXYWH[2]); - height = ObjectSpace(aBBox, &aXYWH[3]); - } else { - x = UserSpace(aFrame, &aXYWH[0]); - y = UserSpace(aFrame, &aXYWH[1]); - width = UserSpace(aFrame, &aXYWH[2]); - height = UserSpace(aFrame, &aXYWH[3]); + return GetBoundingBoxRelativeRect(aXYWH, aBBox); } - return gfxRect(x, y, width, height); + return gfxRect(UserSpace(aMetrics, &aXYWH[0]), + UserSpace(aMetrics, &aXYWH[1]), + UserSpace(aMetrics, &aXYWH[2]), + UserSpace(aMetrics, &aXYWH[3])); +} + +gfxRect +nsSVGUtils::GetRelativeRect(uint16_t aUnits, const nsSVGLength2 *aXYWH, + const gfxRect& aBBox, nsIFrame *aFrame) +{ + if (aUnits == SVG_UNIT_TYPE_OBJECTBOUNDINGBOX) { + return GetBoundingBoxRelativeRect(aXYWH, aBBox); + } + nsIContent* content = aFrame->GetContent(); + if (content->IsSVG()) { + nsSVGElement* svgElement = static_cast(content); + return GetRelativeRect(aUnits, aXYWH, aBBox, SVGElementMetrics(svgElement)); + } + return GetRelativeRect(aUnits, aXYWH, aBBox, NonSVGFrameUserSpaceMetrics(aFrame)); } bool diff --git a/layout/svg/nsSVGUtils.h b/layout/svg/nsSVGUtils.h index 8b9214a665c8..05ff202624bf 100644 --- a/layout/svg/nsSVGUtils.h +++ b/layout/svg/nsSVGUtils.h @@ -58,6 +58,7 @@ class SVGAnimatedPreserveAspectRatio; class SVGPreserveAspectRatio; namespace dom { class Element; +class UserSpaceMetrics; } // namespace dom namespace gfx { class SourceSurface; @@ -274,12 +275,8 @@ public: Input: length - length to be converted */ static float UserSpace(nsSVGElement *aSVGElement, const nsSVGLength2 *aLength); - - /* Computes the input length in terms of user space coordinates. - Input: aFrame - object to be used for determining user space - length - length to be converted - */ static float UserSpace(nsIFrame *aFrame, const nsSVGLength2 *aLength); + static float UserSpace(const mozilla::dom::UserSpaceMetrics& aMetrics, const nsSVGLength2 *aLength); /* Find the outermost SVG frame of the passed frame */ static nsSVGOuterSVGFrame * @@ -454,7 +451,12 @@ public: */ static gfxRect GetRelativeRect(uint16_t aUnits, const nsSVGLength2 *aXYWH, - const gfxRect &aBBox, nsIFrame *aFrame); + const gfxRect& aBBox, nsIFrame *aFrame); + + static gfxRect + GetRelativeRect(uint16_t aUnits, const nsSVGLength2 *aXYWH, + const gfxRect& aBBox, + const mozilla::dom::UserSpaceMetrics& aMetrics); /** * Find the first frame, starting with aStartFrame and going up its From 4d8ac4a8d7ae6e2dcc74c834a71397e660750bb1 Mon Sep 17 00:00:00 2001 From: Markus Stange Date: Mon, 15 Sep 2014 12:12:50 +0200 Subject: [PATCH 06/53] Bug 1066270 - Resolve SVG lengths in nsSVGFilterInstance using the UserSpaceMetrics supplied in the nsFilterInstance constructor. r=roc --- layout/svg/nsFilterInstance.cpp | 30 +++++++++++++++++++++++++----- layout/svg/nsFilterInstance.h | 14 ++++++++++++++ layout/svg/nsSVGFilterInstance.cpp | 22 +++++++++++----------- layout/svg/nsSVGFilterInstance.h | 15 +++++++++++---- 4 files changed, 61 insertions(+), 20 deletions(-) diff --git a/layout/svg/nsFilterInstance.cpp b/layout/svg/nsFilterInstance.cpp index cce14c752eac..258fc083e1ae 100644 --- a/layout/svg/nsFilterInstance.cpp +++ b/layout/svg/nsFilterInstance.cpp @@ -6,6 +6,9 @@ // Main header first: #include "nsFilterInstance.h" +// MFBT headers next: +#include "mozilla/UniquePtr.h" + // Keep others in (case-insensitive) order: #include "gfxPlatform.h" #include "gfxUtils.h" @@ -24,6 +27,16 @@ using namespace mozilla; using namespace mozilla::dom; using namespace mozilla::gfx; +static UniquePtr +UserSpaceMetricsForFrame(nsIFrame* aFrame) +{ + if (aFrame->GetContent()->IsSVG()) { + nsSVGElement* element = static_cast(aFrame->GetContent()); + return MakeUnique(element); + } + return MakeUnique(aFrame); +} + nsresult nsFilterInstance::PaintFilteredFrame(nsIFrame *aFilteredFrame, nsRenderingContext *aContext, @@ -32,7 +45,8 @@ nsFilterInstance::PaintFilteredFrame(nsIFrame *aFilteredFrame, const nsRegion *aDirtyArea) { auto& filterChain = aFilteredFrame->StyleSVGReset()->mFilters; - nsFilterInstance instance(aFilteredFrame, filterChain, aPaintCallback, aTransform, + UniquePtr metrics = UserSpaceMetricsForFrame(aFilteredFrame); + nsFilterInstance instance(aFilteredFrame, *metrics, filterChain, aPaintCallback, aTransform, aDirtyArea, nullptr, nullptr, nullptr); if (!instance.IsInitialized()) { return NS_OK; @@ -50,7 +64,8 @@ nsFilterInstance::GetPostFilterDirtyArea(nsIFrame *aFilteredFrame, gfxMatrix unused; // aPaintTransform arg not used since we're not painting auto& filterChain = aFilteredFrame->StyleSVGReset()->mFilters; - nsFilterInstance instance(aFilteredFrame, filterChain, nullptr, unused, nullptr, + UniquePtr metrics = UserSpaceMetricsForFrame(aFilteredFrame); + nsFilterInstance instance(aFilteredFrame, *metrics, filterChain, nullptr, unused, nullptr, &aPreFilterDirtyRegion); if (!instance.IsInitialized()) { return nsRegion(); @@ -68,7 +83,8 @@ nsFilterInstance::GetPreFilterNeededArea(nsIFrame *aFilteredFrame, { gfxMatrix unused; // aPaintTransform arg not used since we're not painting auto& filterChain = aFilteredFrame->StyleSVGReset()->mFilters; - nsFilterInstance instance(aFilteredFrame, filterChain, nullptr, unused, + UniquePtr metrics = UserSpaceMetricsForFrame(aFilteredFrame); + nsFilterInstance instance(aFilteredFrame, *metrics, filterChain, nullptr, unused, &aPostFilterDirtyRegion); if (!instance.IsInitialized()) { return nsRect(); @@ -97,7 +113,8 @@ nsFilterInstance::GetPostFilterBounds(nsIFrame *aFilteredFrame, gfxMatrix unused; // aPaintTransform arg not used since we're not painting auto& filterChain = aFilteredFrame->StyleSVGReset()->mFilters; - nsFilterInstance instance(aFilteredFrame, filterChain, nullptr, unused, nullptr, + UniquePtr metrics = UserSpaceMetricsForFrame(aFilteredFrame); + nsFilterInstance instance(aFilteredFrame, *metrics, filterChain, nullptr, unused, nullptr, preFilterRegionPtr, aPreFilterBounds, aOverrideBBox); if (!instance.IsInitialized()) { @@ -108,6 +125,7 @@ nsFilterInstance::GetPostFilterBounds(nsIFrame *aFilteredFrame, } nsFilterInstance::nsFilterInstance(nsIFrame *aTargetFrame, + const UserSpaceMetrics& aMetrics, const nsTArray& aFilterChain, nsSVGFilterPaintCallback *aPaintCallback, const gfxMatrix& aPaintTransform, @@ -116,6 +134,7 @@ nsFilterInstance::nsFilterInstance(nsIFrame *aTargetFrame, const nsRect *aPreFilterVisualOverflowRectOverride, const gfxRect *aOverrideBBox) : mTargetFrame(aTargetFrame) + , mMetrics(aMetrics) , mPaintCallback(aPaintCallback) , mPaintTransform(aPaintTransform) , mInitialized(false) @@ -246,7 +265,8 @@ nsFilterInstance::BuildPrimitivesForFilter(const nsStyleFilter& aFilter) if (aFilter.GetType() == NS_STYLE_FILTER_URL) { // Build primitives for an SVG filter. - nsSVGFilterInstance svgFilterInstance(aFilter, mTargetFrame, mTargetBBox, + nsSVGFilterInstance svgFilterInstance(aFilter, mTargetFrame->GetContent(), + mMetrics, mTargetBBox, mUserSpaceToFilterSpaceScale, mFilterSpaceToUserSpaceScale); if (!svgFilterInstance.IsInitialized()) { diff --git a/layout/svg/nsFilterInstance.h b/layout/svg/nsFilterInstance.h index 053ca603b8b1..1094ddd184ed 100644 --- a/layout/svg/nsFilterInstance.h +++ b/layout/svg/nsFilterInstance.h @@ -25,6 +25,12 @@ class gfxASurface; class nsIFrame; class nsSVGFilterPaintCallback; +namespace mozilla { +namespace dom { +class UserSpaceMetrics; +} +} + /** * This class performs all filter processing. * @@ -48,6 +54,7 @@ class nsFilterInstance typedef mozilla::gfx::DrawTarget DrawTarget; typedef mozilla::gfx::FilterPrimitiveDescription FilterPrimitiveDescription; typedef mozilla::gfx::FilterDescription FilterDescription; + typedef mozilla::dom::UserSpaceMetrics UserSpaceMetrics; public: /** @@ -94,6 +101,7 @@ public: /** * @param aTargetFrame The frame of the filtered element under consideration. + * @param aMetrics The metrics to resolve SVG lengths against. * @param aFilterChain The list of filters to apply. * @param aPaintCallback [optional] The callback that Render() should use to * paint. Only required if you will call Render(). @@ -111,6 +119,7 @@ public: * element. */ nsFilterInstance(nsIFrame *aTargetFrame, + const UserSpaceMetrics& aMetrics, const nsTArray& aFilterChain, nsSVGFilterPaintCallback *aPaintCallback, const gfxMatrix& aPaintTransform, @@ -269,6 +278,11 @@ private: */ nsIFrame* mTargetFrame; + /** + * The user space metrics of the filtered frame. + */ + const UserSpaceMetrics& mMetrics; + nsSVGFilterPaintCallback* mPaintCallback; /** diff --git a/layout/svg/nsSVGFilterInstance.cpp b/layout/svg/nsSVGFilterInstance.cpp index 6b3655c4bd87..234a571d34b2 100644 --- a/layout/svg/nsSVGFilterInstance.cpp +++ b/layout/svg/nsSVGFilterInstance.cpp @@ -24,12 +24,14 @@ using namespace mozilla::dom; using namespace mozilla::gfx; nsSVGFilterInstance::nsSVGFilterInstance(const nsStyleFilter& aFilter, - nsIFrame *aTargetFrame, + nsIContent* aTargetContent, + const UserSpaceMetrics& aMetrics, const gfxRect& aTargetBBox, const gfxSize& aUserSpaceToFilterSpaceScale, const gfxSize& aFilterSpaceToUserSpaceScale) : mFilter(aFilter), - mTargetFrame(aTargetFrame), + mTargetContent(aTargetContent), + mMetrics(aMetrics), mTargetBBox(aTargetBBox), mUserSpaceToFilterSpaceScale(aUserSpaceToFilterSpaceScale), mFilterSpaceToUserSpaceScale(aFilterSpaceToUserSpaceScale), @@ -86,7 +88,7 @@ nsSVGFilterInstance::ComputeBounds() uint16_t filterUnits = mFilterFrame->GetEnumValue(SVGFilterElement::FILTERUNITS); gfxRect userSpaceBounds = nsSVGUtils::GetRelativeRect(filterUnits, - XYWH, mTargetBBox, mTargetFrame); + XYWH, mTargetBBox, mMetrics); // Transform the user space bounds to filter space, so we // can align them with the pixel boundries of the offscreen surface. @@ -126,16 +128,14 @@ nsSVGFilterInstance::GetFilterFrame() // Get the target element to use as a point of reference for looking up the // filter element. - nsIContent* targetElement = mTargetFrame->GetContent(); - if (!targetElement) { - // There is no element associated with the target frame. + if (!mTargetContent) { return nullptr; } // Look up the filter element by URL. nsReferencedElement filterElement; bool watch = false; - filterElement.Reset(targetElement, url, watch); + filterElement.Reset(mTargetContent, url, watch); Element* element = filterElement.get(); if (!element) { // The URL points to no element. @@ -163,7 +163,7 @@ nsSVGFilterInstance::GetPrimitiveNumber(uint8_t aCtxType, float aValue) const if (mPrimitiveUnits == SVG_UNIT_TYPE_OBJECTBOUNDINGBOX) { value = nsSVGUtils::ObjectSpace(mTargetBBox, &val); } else { - value = nsSVGUtils::UserSpace(mTargetFrame, &val); + value = nsSVGUtils::UserSpace(mMetrics, &val); } switch (aCtxType) { @@ -194,7 +194,7 @@ nsSVGFilterInstance::ConvertLocation(const Point3D& aPoint) const nsIDOMSVGLength::SVG_LENGTHTYPE_NUMBER); gfxRect feArea = nsSVGUtils::GetRelativeRect(mPrimitiveUnits, - val, mTargetBBox, mTargetFrame); + val, mTargetBBox, mMetrics); gfxRect r = UserSpaceToFilterSpace(feArea); return Point3D(r.x, r.y, GetPrimitiveNumber(SVGContentUtils::XY, aPoint.z)); } @@ -240,7 +240,7 @@ nsSVGFilterInstance::ComputeFilterPrimitiveSubregion(nsSVGFE* aFilterElement, } gfxRect feArea = nsSVGUtils::GetRelativeRect(mPrimitiveUnits, - &fE->mLengthAttributes[nsSVGFE::ATTR_X], mTargetBBox, mTargetFrame); + &fE->mLengthAttributes[nsSVGFE::ATTR_X], mTargetBBox, mMetrics); Rect region = ToRect(UserSpaceToFilterSpace(feArea)); if (!fE->mLengthAttributes[nsSVGFE::ATTR_X].IsExplicitlySet()) @@ -387,7 +387,7 @@ nsSVGFilterInstance::BuildPrimitives(nsTArray& aPrim nsDataHashtable imageTable(8); // The principal that we check principals of any loaded images against. - nsCOMPtr principal = mTargetFrame->GetContent()->NodePrincipal(); + nsCOMPtr principal = mTargetContent->NodePrincipal(); for (uint32_t primitiveElementIndex = 0; primitiveElementIndex < primitives.Length(); diff --git a/layout/svg/nsSVGFilterInstance.h b/layout/svg/nsSVGFilterInstance.h index f5264ef9573e..0e0394d71e59 100644 --- a/layout/svg/nsSVGFilterInstance.h +++ b/layout/svg/nsSVGFilterInstance.h @@ -70,18 +70,20 @@ class nsSVGFilterInstance typedef mozilla::gfx::IntRect IntRect; typedef mozilla::gfx::SourceSurface SourceSurface; typedef mozilla::gfx::FilterPrimitiveDescription FilterPrimitiveDescription; + typedef mozilla::dom::UserSpaceMetrics UserSpaceMetrics; public: /** * @param aFilter The SVG filter reference from the style system. This class * stores aFilter by reference, so callers should avoid modifying or * deleting aFilter during the lifetime of nsSVGFilterInstance. - * @param aTargetFrame The frame of the filtered element under consideration. + * @param aTargetContent The filtered element. * @param aTargetBBox The SVG bbox to use for the target frame, computed by * the caller. The caller may decide to override the actual SVG bbox. */ nsSVGFilterInstance(const nsStyleFilter& aFilter, - nsIFrame *aTargetFrame, + nsIContent* aTargetContent, + const UserSpaceMetrics& aMetrics, const gfxRect& aTargetBBox, const gfxSize& aUserSpaceToFilterSpaceScale, const gfxSize& aFilterSpaceToUserSpaceScale); @@ -208,9 +210,14 @@ private: const nsStyleFilter& mFilter; /** - * The frame for the element that is currently being filtered. + * The filtered element. */ - nsIFrame* mTargetFrame; + nsIContent* mTargetContent; + + /** + * The SVG user space metrics that SVG lengths are resolved against. + */ + const UserSpaceMetrics& mMetrics; /** * The filter element referenced by mTargetFrame's element. From e1860516a0679ad8eaa1f80e53462f6481ecd9c3 Mon Sep 17 00:00:00 2001 From: Markus Stange Date: Mon, 15 Sep 2014 12:12:51 +0200 Subject: [PATCH 07/53] Bug 1066270 - Add an nsIContent* parameter to the nsFilterInstance constructor. r=roc --- layout/svg/nsFilterInstance.cpp | 25 +++++++++++++++++-------- layout/svg/nsFilterInstance.h | 7 +++++++ 2 files changed, 24 insertions(+), 8 deletions(-) diff --git a/layout/svg/nsFilterInstance.cpp b/layout/svg/nsFilterInstance.cpp index 258fc083e1ae..e6edf0d07d2d 100644 --- a/layout/svg/nsFilterInstance.cpp +++ b/layout/svg/nsFilterInstance.cpp @@ -46,7 +46,8 @@ nsFilterInstance::PaintFilteredFrame(nsIFrame *aFilteredFrame, { auto& filterChain = aFilteredFrame->StyleSVGReset()->mFilters; UniquePtr metrics = UserSpaceMetricsForFrame(aFilteredFrame); - nsFilterInstance instance(aFilteredFrame, *metrics, filterChain, aPaintCallback, aTransform, + nsFilterInstance instance(aFilteredFrame, aFilteredFrame->GetContent(), *metrics, + filterChain, aPaintCallback, aTransform, aDirtyArea, nullptr, nullptr, nullptr); if (!instance.IsInitialized()) { return NS_OK; @@ -65,7 +66,8 @@ nsFilterInstance::GetPostFilterDirtyArea(nsIFrame *aFilteredFrame, gfxMatrix unused; // aPaintTransform arg not used since we're not painting auto& filterChain = aFilteredFrame->StyleSVGReset()->mFilters; UniquePtr metrics = UserSpaceMetricsForFrame(aFilteredFrame); - nsFilterInstance instance(aFilteredFrame, *metrics, filterChain, nullptr, unused, nullptr, + nsFilterInstance instance(aFilteredFrame, aFilteredFrame->GetContent(), *metrics, + filterChain, nullptr, unused, nullptr, &aPreFilterDirtyRegion); if (!instance.IsInitialized()) { return nsRegion(); @@ -84,7 +86,8 @@ nsFilterInstance::GetPreFilterNeededArea(nsIFrame *aFilteredFrame, gfxMatrix unused; // aPaintTransform arg not used since we're not painting auto& filterChain = aFilteredFrame->StyleSVGReset()->mFilters; UniquePtr metrics = UserSpaceMetricsForFrame(aFilteredFrame); - nsFilterInstance instance(aFilteredFrame, *metrics, filterChain, nullptr, unused, + nsFilterInstance instance(aFilteredFrame, aFilteredFrame->GetContent(), *metrics, + filterChain, nullptr, unused, &aPostFilterDirtyRegion); if (!instance.IsInitialized()) { return nsRect(); @@ -114,7 +117,8 @@ nsFilterInstance::GetPostFilterBounds(nsIFrame *aFilteredFrame, gfxMatrix unused; // aPaintTransform arg not used since we're not painting auto& filterChain = aFilteredFrame->StyleSVGReset()->mFilters; UniquePtr metrics = UserSpaceMetricsForFrame(aFilteredFrame); - nsFilterInstance instance(aFilteredFrame, *metrics, filterChain, nullptr, unused, nullptr, + nsFilterInstance instance(aFilteredFrame, aFilteredFrame->GetContent(), *metrics, + filterChain, nullptr, unused, nullptr, preFilterRegionPtr, aPreFilterBounds, aOverrideBBox); if (!instance.IsInitialized()) { @@ -125,6 +129,7 @@ nsFilterInstance::GetPostFilterBounds(nsIFrame *aFilteredFrame, } nsFilterInstance::nsFilterInstance(nsIFrame *aTargetFrame, + nsIContent* aTargetContent, const UserSpaceMetrics& aMetrics, const nsTArray& aFilterChain, nsSVGFilterPaintCallback *aPaintCallback, @@ -134,14 +139,18 @@ nsFilterInstance::nsFilterInstance(nsIFrame *aTargetFrame, const nsRect *aPreFilterVisualOverflowRectOverride, const gfxRect *aOverrideBBox) : mTargetFrame(aTargetFrame) + , mTargetContent(aTargetContent) , mMetrics(aMetrics) , mPaintCallback(aPaintCallback) , mPaintTransform(aPaintTransform) , mInitialized(false) { - - mTargetBBox = aOverrideBBox ? - *aOverrideBBox : nsSVGUtils::GetBBox(mTargetFrame); + if (aOverrideBBox) { + mTargetBBox = *aOverrideBBox; + } else { + MOZ_ASSERT(mTargetFrame, "Need to supply a frame when there's no aOverrideBBox"); + mTargetBBox = nsSVGUtils::GetBBox(mTargetFrame); + } // Compute user space to filter space transforms. nsresult rv = ComputeUserSpaceToFilterSpaceScale(); @@ -265,7 +274,7 @@ nsFilterInstance::BuildPrimitivesForFilter(const nsStyleFilter& aFilter) if (aFilter.GetType() == NS_STYLE_FILTER_URL) { // Build primitives for an SVG filter. - nsSVGFilterInstance svgFilterInstance(aFilter, mTargetFrame->GetContent(), + nsSVGFilterInstance svgFilterInstance(aFilter, mTargetContent, mMetrics, mTargetBBox, mUserSpaceToFilterSpaceScale, mFilterSpaceToUserSpaceScale); diff --git a/layout/svg/nsFilterInstance.h b/layout/svg/nsFilterInstance.h index 1094ddd184ed..1b14ee62a7da 100644 --- a/layout/svg/nsFilterInstance.h +++ b/layout/svg/nsFilterInstance.h @@ -101,6 +101,7 @@ public: /** * @param aTargetFrame The frame of the filtered element under consideration. + * @param aTargetContent The filtered element itself. * @param aMetrics The metrics to resolve SVG lengths against. * @param aFilterChain The list of filters to apply. * @param aPaintCallback [optional] The callback that Render() should use to @@ -119,6 +120,7 @@ public: * element. */ nsFilterInstance(nsIFrame *aTargetFrame, + nsIContent* aTargetContent, const UserSpaceMetrics& aMetrics, const nsTArray& aFilterChain, nsSVGFilterPaintCallback *aPaintCallback, @@ -278,6 +280,11 @@ private: */ nsIFrame* mTargetFrame; + /** + * The filtered element. + */ + nsIContent* mTargetContent; + /** * The user space metrics of the filtered frame. */ From 9b0707d88608e0b87794877c2bb81f0c89f0244c Mon Sep 17 00:00:00 2001 From: Markus Stange Date: Mon, 15 Sep 2014 12:12:51 +0200 Subject: [PATCH 08/53] Bug 1066270 - Replace the nsIFrame* argument to nsCSSFilterInstance with a shadowFallbackColor argument. r=roc --- layout/svg/nsCSSFilterInstance.cpp | 7 +++---- layout/svg/nsCSSFilterInstance.h | 13 ++++++++----- layout/svg/nsFilterInstance.cpp | 8 +++++++- 3 files changed, 18 insertions(+), 10 deletions(-) diff --git a/layout/svg/nsCSSFilterInstance.cpp b/layout/svg/nsCSSFilterInstance.cpp index 48074fd0f4b1..8d541c4112d6 100644 --- a/layout/svg/nsCSSFilterInstance.cpp +++ b/layout/svg/nsCSSFilterInstance.cpp @@ -29,11 +29,11 @@ static float ClampFactor(float aFactor) } nsCSSFilterInstance::nsCSSFilterInstance(const nsStyleFilter& aFilter, - nsIFrame *aTargetFrame, + nscolor aShadowFallbackColor, const nsIntRect& aTargetBBoxInFilterSpace, const gfxMatrix& aFrameSpaceInCSSPxToFilterSpaceTransform) : mFilter(aFilter) - , mTargetFrame(aTargetFrame) + , mShadowFallbackColor(aShadowFallbackColor) , mTargetBBoxInFilterSpace(aTargetBBoxInFilterSpace) , mFrameSpaceInCSSPxToFilterSpaceTransform(aFrameSpaceInCSSPxToFilterSpaceTransform) { @@ -201,8 +201,7 @@ nsCSSFilterInstance::SetAttributesForDropShadow(FilterPrimitiveDescription& aDes aDescr.Attributes().Set(eDropShadowOffset, offsetInFilterSpace); // Set color. If unspecified, use the CSS color property. - nscolor shadowColor = shadow->mHasColor ? - shadow->mColor : mTargetFrame->StyleColor()->mColor; + nscolor shadowColor = shadow->mHasColor ? shadow->mColor : mShadowFallbackColor; aDescr.Attributes().Set(eDropShadowColor, ToAttributeColor(shadowColor)); return NS_OK; diff --git a/layout/svg/nsCSSFilterInstance.h b/layout/svg/nsCSSFilterInstance.h index 47823d528408..16ae11598482 100644 --- a/layout/svg/nsCSSFilterInstance.h +++ b/layout/svg/nsCSSFilterInstance.h @@ -35,14 +35,16 @@ public: * @param aFilter The CSS filter from the style system. This class stores * aFilter by reference, so callers should avoid modifying or deleting * aFilter during the lifetime of nsCSSFilterInstance. - * @param mTargetBBoxInFilterSpace The frame of element being filtered, in + * @param aShadowFallbackColor The color that should be used for + * drop-shadow() filters that don't specify a shadow color. + * @param aTargetBBoxInFilterSpace The frame of element being filtered, in * filter space. * @param aFrameSpaceInCSSPxToFilterSpaceTransform The transformation from * the filtered element's frame space in CSS pixels to filter space. */ nsCSSFilterInstance(const nsStyleFilter& aFilter, - nsIFrame *aTargetFrame, - const nsIntRect& mTargetBBoxInFilterSpace, + nscolor aShadowFallbackColor, + const nsIntRect& aTargetBBoxInFilterSpace, const gfxMatrix& aFrameSpaceInCSSPxToFilterSpaceTransform); /** @@ -112,9 +114,10 @@ private: const nsStyleFilter& mFilter; /** - * The frame for the element that is currently being filtered. + * The color that should be used for drop-shadow() filters that don't + * specify a shadow color. */ - nsIFrame* mTargetFrame; + nscolor mShadowFallbackColor; /** * The bounding box of the element being filtered, in filter space. Used for diff --git a/layout/svg/nsFilterInstance.cpp b/layout/svg/nsFilterInstance.cpp index e6edf0d07d2d..c9231550bd6f 100644 --- a/layout/svg/nsFilterInstance.cpp +++ b/layout/svg/nsFilterInstance.cpp @@ -286,7 +286,13 @@ nsFilterInstance::BuildPrimitivesForFilter(const nsStyleFilter& aFilter) } // Build primitives for a CSS filter. - nsCSSFilterInstance cssFilterInstance(aFilter, mTargetFrame, + + // If we don't have a frame, use opaque black for shadows with unspecified + // shadow colors. + nscolor shadowFallbackColor = + mTargetFrame ? mTargetFrame->StyleColor()->mColor : NS_RGB(0,0,0); + + nsCSSFilterInstance cssFilterInstance(aFilter, shadowFallbackColor, mTargetBBoxInFilterSpace, mFrameSpaceInCSSPxToFilterSpaceTransform); return cssFilterInstance.BuildPrimitives(mPrimitiveDescriptions); From d3ab6f184c194cb58351b64b6cd968f8c2cc256a Mon Sep 17 00:00:00 2001 From: Markus Stange Date: Mon, 15 Sep 2014 12:12:51 +0200 Subject: [PATCH 09/53] Bug 1066270 - Allow aTargetFrame to be null in nsFilterInstance. r=roc --- layout/svg/nsFilterInstance.cpp | 21 ++++++++++++++++----- layout/svg/nsFilterInstance.h | 5 +++-- 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/layout/svg/nsFilterInstance.cpp b/layout/svg/nsFilterInstance.cpp index c9231550bd6f..e004ae61d80a 100644 --- a/layout/svg/nsFilterInstance.cpp +++ b/layout/svg/nsFilterInstance.cpp @@ -200,7 +200,7 @@ nsFilterInstance::nsFilterInstance(nsIFrame *aTargetFrame, if (aPreFilterVisualOverflowRectOverride) { mTargetBounds = FrameSpaceToFilterSpace(aPreFilterVisualOverflowRectOverride); - } else { + } else if (mTargetFrame) { nsRect preFilterVOR = mTargetFrame->GetPreEffectsVisualOverflowRect(); mTargetBounds = FrameSpaceToFilterSpace(&preFilterVOR); } @@ -211,10 +211,13 @@ nsFilterInstance::nsFilterInstance(nsIFrame *aTargetFrame, nsresult nsFilterInstance::ComputeUserSpaceToFilterSpaceScale() { - gfxMatrix canvasTransform = nsSVGUtils::GetCanvasTM(mTargetFrame); - if (canvasTransform.IsSingular()) { - // Nothing should be rendered. - return NS_ERROR_FAILURE; + gfxMatrix canvasTransform; + if (mTargetFrame) { + canvasTransform = nsSVGUtils::GetCanvasTM(mTargetFrame); + if (canvasTransform.IsSingular()) { + // Nothing should be rendered. + return NS_ERROR_FAILURE; + } } mUserSpaceToFilterSpaceScale = canvasTransform.ScaleFactors(true); @@ -326,6 +329,7 @@ nsresult nsFilterInstance::BuildSourcePaint(SourceInfo *aSource, DrawTarget* aTargetDT) { + MOZ_ASSERT(mTargetFrame); nsIntRect neededRect = aSource->mNeededBounds; RefPtr offscreenDT = @@ -383,6 +387,8 @@ nsFilterInstance::BuildSourcePaints(DrawTarget* aTargetDT) nsresult nsFilterInstance::BuildSourceImage(DrawTarget* aTargetDT) { + MOZ_ASSERT(mTargetFrame); + nsIntRect neededRect = mSourceGraphic.mNeededBounds; if (neededRect.IsEmpty()) { return NS_OK; @@ -434,6 +440,8 @@ nsFilterInstance::BuildSourceImage(DrawTarget* aTargetDT) nsresult nsFilterInstance::Render(gfxContext* aContext) { + MOZ_ASSERT(mTargetFrame, "Need a frame for rendering"); + nsIntRect filterRect = mPostFilterDirtyRegion.GetBounds().Intersect(OutputFilterSpaceBounds()); gfxMatrix ctm = GetFilterSpaceToDeviceSpaceTransform(); @@ -576,5 +584,8 @@ nsFilterInstance::FilterSpaceToFrameSpace(const nsIntRegion& aRegion) const gfxMatrix nsFilterInstance::GetUserSpaceToFrameSpaceInCSSPxTransform() const { + if (!mTargetFrame) { + return gfxMatrix(); + } return gfxMatrix::Translation(-nsSVGUtils::FrameSpaceInCSSPxToUserSpaceOffset(mTargetFrame)); } diff --git a/layout/svg/nsFilterInstance.h b/layout/svg/nsFilterInstance.h index 1b14ee62a7da..f72965a0507c 100644 --- a/layout/svg/nsFilterInstance.h +++ b/layout/svg/nsFilterInstance.h @@ -100,7 +100,8 @@ public: const nsRect *aPreFilterBounds = nullptr); /** - * @param aTargetFrame The frame of the filtered element under consideration. + * @param aTargetFrame The frame of the filtered element under consideration, + * may be null. * @param aTargetContent The filtered element itself. * @param aMetrics The metrics to resolve SVG lengths against. * @param aFilterChain The list of filters to apply. @@ -117,7 +118,7 @@ public: * @param aOverridePreFilterVisualOverflowRect [optional] Use a different * visual overflow rect for the target element. * @param aOverrideBBox [optional] Use a different SVG bbox for the target - * element. + * element. Must be non-null if aTargetFrame is null. */ nsFilterInstance(nsIFrame *aTargetFrame, nsIContent* aTargetContent, From 3c38e1c4b8cefef60cb89ded11cd4b43041d178c Mon Sep 17 00:00:00 2001 From: Markus Stange Date: Mon, 15 Sep 2014 12:12:52 +0200 Subject: [PATCH 10/53] Bug 1066270 - Add nsFilterInstance::GetFilterDescription. r=roc --- layout/svg/nsFilterInstance.cpp | 17 +++++++++++++++++ layout/svg/nsFilterInstance.h | 19 +++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/layout/svg/nsFilterInstance.cpp b/layout/svg/nsFilterInstance.cpp index e004ae61d80a..b2baef53054a 100644 --- a/layout/svg/nsFilterInstance.cpp +++ b/layout/svg/nsFilterInstance.cpp @@ -27,6 +27,23 @@ using namespace mozilla; using namespace mozilla::dom; using namespace mozilla::gfx; +FilterDescription +nsFilterInstance::GetFilterDescription(nsIContent* aFilteredElement, + const nsTArray& aFilterChain, + const UserSpaceMetrics& aMetrics, + const gfxRect& aBBox, + nsTArray>& aOutAdditionalImages) +{ + gfxMatrix unused; // aPaintTransform arg not used since we're not painting + nsFilterInstance instance(nullptr, aFilteredElement, aMetrics, + aFilterChain, nullptr, unused, + nullptr, nullptr, nullptr, &aBBox); + if (!instance.IsInitialized()) { + return FilterDescription(); + } + return instance.ExtractDescriptionAndAdditionalImages(aOutAdditionalImages); +} + static UniquePtr UserSpaceMetricsForFrame(nsIFrame* aFrame) { diff --git a/layout/svg/nsFilterInstance.h b/layout/svg/nsFilterInstance.h index f72965a0507c..68ccfac22a62 100644 --- a/layout/svg/nsFilterInstance.h +++ b/layout/svg/nsFilterInstance.h @@ -57,6 +57,19 @@ class nsFilterInstance typedef mozilla::dom::UserSpaceMetrics UserSpaceMetrics; public: + /** + * Create a FilterDescription for the supplied filter. All coordinates in + * the description are in filter space. + * @param aOutAdditionalImages Will contain additional images needed to + * render the filter (from feImage primitives). + * @return A FilterDescription describing the filter. + */ + static FilterDescription GetFilterDescription(nsIContent* aFilteredElement, + const nsTArray& aFilterChain, + const UserSpaceMetrics& aMetrics, + const gfxRect& aBBox, + nsTArray>& aOutAdditionalImages); + /** * Paint the given filtered frame. * @param aDirtyArea The area than needs to be painted, in aFilteredFrame's @@ -144,6 +157,12 @@ public: */ nsresult Render(gfxContext* aContext); + const FilterDescription& ExtractDescriptionAndAdditionalImages(nsTArray>& aOutAdditionalImages) + { + mInputImages.SwapElements(aOutAdditionalImages); + return mFilterDescription; + } + /** * Sets the aPostFilterDirtyRegion outparam to the post-filter area in frame * space that would be dirtied by mTargetFrame when a given From 27c391194ae5814c7d79e08c39f68bb3b77d335b Mon Sep 17 00:00:00 2001 From: Markus Stange Date: Mon, 15 Sep 2014 12:12:52 +0200 Subject: [PATCH 11/53] Bug 1066270 - Don't crash when attempting to resolve a filter from an external resource document that hasn't undergone frame construction yet. r=roc --- layout/svg/nsSVGFilterInstance.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/layout/svg/nsSVGFilterInstance.cpp b/layout/svg/nsSVGFilterInstance.cpp index 234a571d34b2..39d1f10a4e4e 100644 --- a/layout/svg/nsSVGFilterInstance.cpp +++ b/layout/svg/nsSVGFilterInstance.cpp @@ -144,8 +144,9 @@ nsSVGFilterInstance::GetFilterFrame() // Get the frame of the filter element. nsIFrame* frame = element->GetPrimaryFrame(); - if (frame->GetType() != nsGkAtoms::svgFilterFrame) { - // The URL points to an element that's not an SVG filter element. + if (!frame || frame->GetType() != nsGkAtoms::svgFilterFrame) { + // The URL points to an element that's not an SVG filter element, or to an + // element that hasn't had its frame constructed yet. return nullptr; } From 99314bc653e781cb67ad40539f3f2c3f905304a9 Mon Sep 17 00:00:00 2001 From: Markus Stange Date: Mon, 15 Sep 2014 12:12:52 +0200 Subject: [PATCH 12/53] Bug 1066270 - Simplify mTargetBounds usage. r=roc --- layout/svg/nsFilterInstance.cpp | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/layout/svg/nsFilterInstance.cpp b/layout/svg/nsFilterInstance.cpp index b2baef53054a..8248110d38f2 100644 --- a/layout/svg/nsFilterInstance.cpp +++ b/layout/svg/nsFilterInstance.cpp @@ -214,13 +214,16 @@ nsFilterInstance::nsFilterInstance(nsIFrame *aTargetFrame, // Convert the passed in rects from frame space to filter space: mPostFilterDirtyRegion = FrameSpaceToFilterSpace(aPostFilterDirtyRegion); mPreFilterDirtyRegion = FrameSpaceToFilterSpace(aPreFilterDirtyRegion); + + nsIntRect targetBounds; if (aPreFilterVisualOverflowRectOverride) { - mTargetBounds = + targetBounds = FrameSpaceToFilterSpace(aPreFilterVisualOverflowRectOverride); } else if (mTargetFrame) { nsRect preFilterVOR = mTargetFrame->GetPreEffectsVisualOverflowRect(); - mTargetBounds = FrameSpaceToFilterSpace(&preFilterVOR); + targetBounds = FrameSpaceToFilterSpace(&preFilterVOR); } + mTargetBounds.UnionRect(mTargetBBoxInFilterSpace, targetBounds); mInitialized = true; } @@ -332,10 +335,7 @@ nsFilterInstance::ComputeNeededBoxes() mFilterDescription, mPostFilterDirtyRegion, sourceGraphicNeededRegion, fillPaintNeededRegion, strokePaintNeededRegion); - nsIntRect sourceBounds; - sourceBounds.UnionRect(mTargetBBoxInFilterSpace, mTargetBounds); - - sourceGraphicNeededRegion.And(sourceGraphicNeededRegion, sourceBounds); + sourceGraphicNeededRegion.And(sourceGraphicNeededRegion, mTargetBounds); mSourceGraphic.mNeededBounds = sourceGraphicNeededRegion.GetBounds(); mFillPaint.mNeededBounds = fillPaintNeededRegion.GetBounds(); @@ -507,11 +507,8 @@ nsFilterInstance::ComputePostFilterDirtyRegion() nsRect nsFilterInstance::ComputePostFilterExtents() { - nsIntRect sourceBounds; - sourceBounds.UnionRect(mTargetBBoxInFilterSpace, mTargetBounds); - nsIntRegion postFilterExtents = - FilterSupport::ComputePostFilterExtents(mFilterDescription, sourceBounds); + FilterSupport::ComputePostFilterExtents(mFilterDescription, mTargetBounds); return FilterSpaceToFrameSpace(postFilterExtents.GetBounds()); } From 61985df23984abece77b74aa1d1fa8b03672f7e4 Mon Sep 17 00:00:00 2001 From: Matthew Gregan Date: Mon, 15 Sep 2014 16:16:54 +1200 Subject: [PATCH 13/53] Bug 1064826 - Fix random test failures: don't start test seek sequence until appends have been processed. Test only. DONTBUILD --- content/media/mediasource/test/mochitest.ini | 1 - content/media/mediasource/test/test_FrameSelection.html | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/content/media/mediasource/test/mochitest.ini b/content/media/mediasource/test/mochitest.ini index f42e292f37d1..58a4cdf9053c 100644 --- a/content/media/mediasource/test/mochitest.ini +++ b/content/media/mediasource/test/mochitest.ini @@ -7,7 +7,6 @@ support-files = [test_BufferedSeek.html] [test_FrameSelection.html] -skip-if = os == "mac" [test_MediaSource.html] [test_SplitAppendDelay.html] [test_SplitAppend.html] diff --git a/content/media/mediasource/test/test_FrameSelection.html b/content/media/mediasource/test/test_FrameSelection.html index c69626d19cdb..d441a044973a 100644 --- a/content/media/mediasource/test/test_FrameSelection.html +++ b/content/media/mediasource/test/test_FrameSelection.html @@ -49,10 +49,10 @@ runWithMSE(function () { first = false; } else { ms.endOfStream(); + target = targets.shift(); + v.currentTime = target.currentTime; } }); - target = targets.shift(); - v.currentTime = target.currentTime; }); }); From 904d9ad030d03c1d93291da09965f3092dcc8e77 Mon Sep 17 00:00:00 2001 From: Jonathan Watt Date: Mon, 15 Sep 2014 12:10:30 +0100 Subject: [PATCH 14/53] Bug 1067093 - Get rid of gfxContext::AntialiasMode in favor of Moz2D AntialiasMode. r=Bas --- gfx/thebes/gfxContext.cpp | 13 +++---------- gfx/thebes/gfxContext.h | 13 ++----------- gfx/thebes/gfxDrawable.cpp | 10 ++++------ layout/base/nsCSSRendering.cpp | 9 +++++---- layout/base/nsCSSRenderingBorders.cpp | 2 +- layout/svg/SVGTextFrame.cpp | 4 ++-- layout/svg/nsSVGPathGeometryFrame.cpp | 4 ++-- 7 files changed, 19 insertions(+), 36 deletions(-) diff --git a/gfx/thebes/gfxContext.cpp b/gfx/thebes/gfxContext.cpp index 8663382ce323..7e2708a45952 100644 --- a/gfx/thebes/gfxContext.cpp +++ b/gfx/thebes/gfxContext.cpp @@ -586,20 +586,13 @@ gfxContext::PixelSnappedRectangleAndSetPattern(const gfxRect& rect, void gfxContext::SetAntialiasMode(AntialiasMode mode) { - if (mode == MODE_ALIASED) { - CurrentState().aaMode = gfx::AntialiasMode::NONE; - } else if (mode == MODE_COVERAGE) { - CurrentState().aaMode = gfx::AntialiasMode::SUBPIXEL; - } + CurrentState().aaMode = mode; } -gfxContext::AntialiasMode +AntialiasMode gfxContext::CurrentAntialiasMode() const { - if (CurrentState().aaMode == gfx::AntialiasMode::NONE) { - return MODE_ALIASED; - } - return MODE_COVERAGE; + return CurrentState().aaMode; } void diff --git a/gfx/thebes/gfxContext.h b/gfx/thebes/gfxContext.h index 7cb503e798c7..1695e30e454b 100644 --- a/gfx/thebes/gfxContext.h +++ b/gfx/thebes/gfxContext.h @@ -529,17 +529,8 @@ public: void SetOperator(GraphicsOperator op); GraphicsOperator CurrentOperator() const; - /** - * MODE_ALIASED means that only pixels whose centers are in the drawn area - * should be modified, and they should be modified to take the value drawn - * at the pixel center. - */ - enum AntialiasMode { - MODE_ALIASED, - MODE_COVERAGE - }; - void SetAntialiasMode(AntialiasMode mode); - AntialiasMode CurrentAntialiasMode() const; + void SetAntialiasMode(mozilla::gfx::AntialiasMode mode); + mozilla::gfx::AntialiasMode CurrentAntialiasMode() const; /** ** Clipping diff --git a/gfx/thebes/gfxDrawable.cpp b/gfx/thebes/gfxDrawable.cpp index 3c638daca0cc..6488265785ec 100644 --- a/gfx/thebes/gfxDrawable.cpp +++ b/gfx/thebes/gfxDrawable.cpp @@ -93,12 +93,10 @@ gfxSurfaceDrawable::DrawInternal(gfxContext* aContext, dt->ClearRect(fillRect); dt->FillRect(fillRect, pattern); } else { - CompositionOp op = CompositionOpForOp(aContext->CurrentOperator()); - AntialiasMode aaMode = - aContext->CurrentAntialiasMode() == gfxContext::MODE_ALIASED ? - AntialiasMode::NONE : - AntialiasMode::SUBPIXEL; - dt->FillRect(fillRect, pattern, DrawOptions(aOpacity, op, aaMode)); + dt->FillRect(fillRect, pattern, + DrawOptions(aOpacity, + CompositionOpForOp(aContext->CurrentOperator()), + aContext->CurrentAntialiasMode())); } } diff --git a/layout/base/nsCSSRendering.cpp b/layout/base/nsCSSRendering.cpp index 2f78e7064e4e..43f08f094cbc 100644 --- a/layout/base/nsCSSRendering.cpp +++ b/layout/base/nsCSSRendering.cpp @@ -9,6 +9,7 @@ #include #include "mozilla/DebugOnly.h" +#include "mozilla/gfx/2D.h" #include "mozilla/HashFunctions.h" #include "mozilla/MathAlgorithms.h" @@ -3598,8 +3599,8 @@ nsCSSRendering::DrawTableBorderSegment(nsRenderingContext& aContext, } gfxContext *ctx = aContext.ThebesContext(); - gfxContext::AntialiasMode oldMode = ctx->CurrentAntialiasMode(); - ctx->SetAntialiasMode(gfxContext::MODE_ALIASED); + AntialiasMode oldMode = ctx->CurrentAntialiasMode(); + ctx->SetAntialiasMode(AntialiasMode::NONE); switch (aBorderStyle) { case NS_STYLE_BORDER_STYLE_NONE: @@ -3932,12 +3933,12 @@ nsCSSRendering::PaintDecorationLine(nsIFrame* aFrame, contextIsSaved = true; aGfxContext->Clip(rect); if (lineHeight > 2.0) { - aGfxContext->SetAntialiasMode(gfxContext::MODE_COVERAGE); + aGfxContext->SetAntialiasMode(AntialiasMode::SUBPIXEL); } else { // Don't use anti-aliasing here. Because looks like lighter color wavy // line at this case. And probably, users don't think the // non-anti-aliased wavy line is not pretty. - aGfxContext->SetAntialiasMode(gfxContext::MODE_ALIASED); + aGfxContext->SetAntialiasMode(AntialiasMode::NONE); } break; default: diff --git a/layout/base/nsCSSRenderingBorders.cpp b/layout/base/nsCSSRenderingBorders.cpp index 0f5b0ddba3ae..642c1759551d 100644 --- a/layout/base/nsCSSRenderingBorders.cpp +++ b/layout/base/nsCSSRenderingBorders.cpp @@ -1494,7 +1494,7 @@ nsCSSBorderRenderer::DrawBorders() gfxFloat dash = mBorderWidths[0]; mContext->SetDash(&dash, 1, 0.5); - mContext->SetAntialiasMode(gfxContext::MODE_ALIASED); + mContext->SetAntialiasMode(AntialiasMode::NONE); gfxRect rect = mOuterRect; rect.Deflate(mBorderWidths[0] / 2.0); mContext->NewPath(); diff --git a/layout/svg/SVGTextFrame.cpp b/layout/svg/SVGTextFrame.cpp index 5a236cb80834..aef962a31bdb 100644 --- a/layout/svg/SVGTextFrame.cpp +++ b/layout/svg/SVGTextFrame.cpp @@ -2888,10 +2888,10 @@ SVGTextDrawPathCallbacks::SetupContext() // or make SetAntialiasMode set cairo text antialiasing too. switch (mFrame->StyleSVG()->mTextRendering) { case NS_STYLE_TEXT_RENDERING_OPTIMIZESPEED: - gfx->SetAntialiasMode(gfxContext::MODE_ALIASED); + gfx->SetAntialiasMode(AntialiasMode::NONE); break; default: - gfx->SetAntialiasMode(gfxContext::MODE_COVERAGE); + gfx->SetAntialiasMode(AntialiasMode::SUBPIXEL); break; } } diff --git a/layout/svg/nsSVGPathGeometryFrame.cpp b/layout/svg/nsSVGPathGeometryFrame.cpp index 915edfae2eb8..5e27ccdd9dd5 100644 --- a/layout/svg/nsSVGPathGeometryFrame.cpp +++ b/layout/svg/nsSVGPathGeometryFrame.cpp @@ -620,10 +620,10 @@ nsSVGPathGeometryFrame::Render(nsRenderingContext *aContext, switch (StyleSVG()->mShapeRendering) { case NS_STYLE_SHAPE_RENDERING_OPTIMIZESPEED: case NS_STYLE_SHAPE_RENDERING_CRISPEDGES: - gfx->SetAntialiasMode(gfxContext::MODE_ALIASED); + gfx->SetAntialiasMode(AntialiasMode::NONE); break; default: - gfx->SetAntialiasMode(gfxContext::MODE_COVERAGE); + gfx->SetAntialiasMode(AntialiasMode::SUBPIXEL); break; } From b581a410e1a527e693bea6672d6777a358d20131 Mon Sep 17 00:00:00 2001 From: Henri Sivonen Date: Mon, 15 Sep 2014 14:50:12 +0300 Subject: [PATCH 15/53] Bug 616421 preparation - Make bogus tree op enum crashes distinct from bogus pointers in append tree op. r=smaug. --- parser/html/nsHtml5TreeOperation.cpp | 4 +--- parser/html/nsHtml5TreeOperation.h | 2 -- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/parser/html/nsHtml5TreeOperation.cpp b/parser/html/nsHtml5TreeOperation.cpp index b75c2bb13cea..bcdccc6231e0 100644 --- a/parser/html/nsHtml5TreeOperation.cpp +++ b/parser/html/nsHtml5TreeOperation.cpp @@ -75,9 +75,7 @@ class MOZ_STACK_CLASS nsHtml5OtherDocUpdate { }; nsHtml5TreeOperation::nsHtml5TreeOperation() -#ifdef DEBUG : mOpCode(eTreeOpUninitialized) -#endif { MOZ_COUNT_CTOR(nsHtml5TreeOperation); } @@ -960,7 +958,7 @@ nsHtml5TreeOperation::Perform(nsHtml5TreeOpExecutor* aBuilder, return rv; } default: { - NS_NOTREACHED("Bogus tree op"); + MOZ_CRASH("Bogus tree op"); } } return NS_OK; // keep compiler happy diff --git a/parser/html/nsHtml5TreeOperation.h b/parser/html/nsHtml5TreeOperation.h index f5e4e7f142b2..2c2db0713742 100644 --- a/parser/html/nsHtml5TreeOperation.h +++ b/parser/html/nsHtml5TreeOperation.h @@ -16,9 +16,7 @@ class nsHtml5StateSnapshot; class nsHtml5DocumentBuilder; enum eHtml5TreeOperation { -#ifdef DEBUG eTreeOpUninitialized, -#endif // main HTML5 ops eTreeOpAppend, eTreeOpDetach, From d7458ed3dbccc943e7ef1e6403eb7bddb3fc1d63 Mon Sep 17 00:00:00 2001 From: Bobby Holley Date: Mon, 15 Sep 2014 14:12:12 +0200 Subject: [PATCH 16/53] Bug 1065452 - Add an API to access the associated window of addon scopes. r=billm --- js/src/jsfriendapi.cpp | 8 ++++++++ js/src/jsfriendapi.h | 3 +++ js/xpconnect/src/XPCJSRuntime.cpp | 19 +++++++++++++++++++ js/xpconnect/src/xpcpublic.h | 8 ++++++++ 4 files changed, 38 insertions(+) diff --git a/js/src/jsfriendapi.cpp b/js/src/jsfriendapi.cpp index 3e6017797ee2..3f54d5cd08e5 100644 --- a/js/src/jsfriendapi.cpp +++ b/js/src/jsfriendapi.cpp @@ -395,6 +395,14 @@ js::GetGlobalForObjectCrossCompartment(JSObject *obj) return &obj->global(); } +JS_FRIEND_API(JSObject *) +js::GetPrototypeNoProxy(JSObject *obj) +{ + JS_ASSERT(!obj->is()); + JS_ASSERT(!obj->getTaggedProto().isLazy()); + return obj->getTaggedProto().toObjectOrNull(); +} + JS_FRIEND_API(void) js::SetPendingExceptionCrossContext(JSContext *cx, JS::HandleValue v) { diff --git a/js/src/jsfriendapi.h b/js/src/jsfriendapi.h index 84c1d13c67c8..951edd1bfda6 100644 --- a/js/src/jsfriendapi.h +++ b/js/src/jsfriendapi.h @@ -706,6 +706,9 @@ GetObjectParentMaybeScope(JSObject *obj); JS_FRIEND_API(JSObject *) GetGlobalForObjectCrossCompartment(JSObject *obj); +JS_FRIEND_API(JSObject *) +GetPrototypeNoProxy(JSObject *obj); + // Sidestep the activeContext checking implicitly performed in // JS_SetPendingException. JS_FRIEND_API(void) diff --git a/js/xpconnect/src/XPCJSRuntime.cpp b/js/xpconnect/src/XPCJSRuntime.cpp index a339c5f834f8..e2a71c760cf4 100644 --- a/js/xpconnect/src/XPCJSRuntime.cpp +++ b/js/xpconnect/src/XPCJSRuntime.cpp @@ -575,6 +575,25 @@ WindowGlobalOrNull(JSObject *aObj) return WindowOrNull(glob); } +nsGlobalWindow* +AddonWindowOrNull(JSObject *aObj) +{ + if (!IsInAddonScope(aObj)) + return nullptr; + + JSObject *global = js::GetGlobalForObjectCrossCompartment(aObj); + JSObject *proto = js::GetPrototypeNoProxy(global); + + // Addons could theoretically change the prototype of the addon scope, but + // we pretty much just want to crash if that happens so that we find out + // about it and get them to change their code. + MOZ_RELEASE_ASSERT(js::IsCrossCompartmentWrapper(proto)); + JSObject *mainGlobal = js::UncheckedUnwrap(proto, /* stopAtOuter = */ false); + MOZ_RELEASE_ASSERT(JS_IsGlobalObject(mainGlobal)); + + return WindowOrNull(mainGlobal); +} + } static void diff --git a/js/xpconnect/src/xpcpublic.h b/js/xpconnect/src/xpcpublic.h index 297d323137a4..932e11e51bdb 100644 --- a/js/xpconnect/src/xpcpublic.h +++ b/js/xpconnect/src/xpcpublic.h @@ -472,6 +472,14 @@ WindowOrNull(JSObject *aObj); nsGlobalWindow* WindowGlobalOrNull(JSObject *aObj); +/** + * If |aObj| is in an addon scope and that addon scope is associated with a + * live DOM Window, returns the associated nsGlobalWindow. Otherwise, returns + * null. + */ +nsGlobalWindow* +AddonWindowOrNull(JSObject *aObj); + // Error reporter used when there is no associated DOM window on to which to // report errors and warnings. // From 04cf67421e8c0c2c91d3dff6df14d946600b020c Mon Sep 17 00:00:00 2001 From: Bobby Holley Date: Mon, 15 Sep 2014 14:12:13 +0200 Subject: [PATCH 17/53] Bug 1065452 - Re-route exceptions directed at addon globals to their associated DOMWindow. r=bz --- dom/base/nsJSEnvironment.cpp | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/dom/base/nsJSEnvironment.cpp b/dom/base/nsJSEnvironment.cpp index d7e4da988312..3e26b9efb2aa 100644 --- a/dom/base/nsJSEnvironment.cpp +++ b/dom/base/nsJSEnvironment.cpp @@ -468,7 +468,22 @@ SystemErrorReporter(JSContext *cx, const char *message, JSErrorReport *report) if (outer) { globalObject = static_cast(outer->GetCurrentInnerWindow()); } - } else { + } + + // We run addons in a separate privileged compartment, but they still expect + // to trigger the onerror handler of their associated DOMWindow. + // + // Note that the way we do this right now is sloppy. Error reporters can + // theoretically be triggered at arbitrary times (not just immediately before + // an AutoJSAPI comes off the stack), so we don't really have a way of knowing + // that the global of the current compartment is the correct global with which + // to report the error. But in practice this is probably fine for the time + // being, and will get cleaned up soon when we fix bug 981187. + if (!globalObject && JS::CurrentGlobalOrNull(cx)) { + globalObject = xpc::AddonWindowOrNull(JS::CurrentGlobalOrNull(cx)); + } + + if (!globalObject) { globalObject = xpc::GetNativeForGlobal(xpc::PrivilegedJunkScope()); } From 3090e7865ad88447669bef54dfb9bb7da7be09ca Mon Sep 17 00:00:00 2001 From: Bobby Holley Date: Mon, 15 Sep 2014 14:13:02 +0200 Subject: [PATCH 18/53] Bug 1060521 - Remove infrastructure for Xrayed NewResolve, GetProperty, and SetProperty on XPCWrappedNatives. r=peterv --- dom/base/nsDOMClassInfo.h | 4 +- js/xpconnect/src/Sandbox.cpp | 18 +- js/xpconnect/wrappers/AccessCheck.cpp | 2 +- js/xpconnect/wrappers/FilteringWrapper.cpp | 21 -- js/xpconnect/wrappers/WrapperFactory.cpp | 7 - js/xpconnect/wrappers/WrapperFactory.h | 3 - js/xpconnect/wrappers/XrayWrapper.cpp | 314 +-------------------- js/xpconnect/wrappers/XrayWrapper.h | 63 ----- 8 files changed, 19 insertions(+), 413 deletions(-) diff --git a/dom/base/nsDOMClassInfo.h b/dom/base/nsDOMClassInfo.h index bada4260535a..664b14022646 100644 --- a/dom/base/nsDOMClassInfo.h +++ b/dom/base/nsDOMClassInfo.h @@ -117,9 +117,7 @@ public: * transparent one. * * Note: So ObjectIsNativeWrapper(cx, obj) check usually means "through xray - * wrapper this part is not visible" while combined with - * || xpc::WrapperFactory::XrayWrapperNotShadowing(obj) it means "through - * xray wrapper it is visible only if it does not hide any native property." + * wrapper this part is not visible". */ static bool ObjectIsNativeWrapper(JSContext* cx, JSObject* obj); diff --git a/js/xpconnect/src/Sandbox.cpp b/js/xpconnect/src/Sandbox.cpp index 85b076cebdf7..eada0fb3940f 100644 --- a/js/xpconnect/src/Sandbox.cpp +++ b/js/xpconnect/src/Sandbox.cpp @@ -637,22 +637,14 @@ xpc::SandboxProxyHandler::getPropertyDescriptor(JSContext *cx, if (!desc.object()) return true; // No property, nothing to do - // Now fix up the getter/setter/value as needed to be bound to desc->obj - // Don't mess with holder_get and holder_set, though, because those rely on - // the "vp is prefilled with the value in the slot" behavior that property - // ops can in theory rely on, but our property op forwarder doesn't know how - // to make that happen. Since we really only need to rebind the DOM methods - // here, not rebindings holder_get and holder_set is OK. + // Now fix up the getter/setter/value as needed to be bound to desc->obj. // - // Similarly, don't mess with XPC_WN_Helper_GetProperty and - // XPC_WN_Helper_SetProperty, for the same reasons: that could confuse our - // access to expandos when we're not doing Xrays. - if (desc.getter() != xpc::holder_get && - desc.getter() != XPC_WN_Helper_GetProperty && + // Don't mess with XPC_WN_Helper_GetProperty and XPC_WN_Helper_SetProperty, + // because that could confuse our access to expandos. + if (desc.getter() != XPC_WN_Helper_GetProperty && !BindPropertyOp(cx, desc.getter(), desc.address(), id, JSPROP_GETTER, proxy)) return false; - if (desc.setter() != xpc::holder_set && - desc.setter() != XPC_WN_Helper_SetProperty && + if (desc.setter() != XPC_WN_Helper_SetProperty && !BindPropertyOp(cx, desc.setter(), desc.address(), id, JSPROP_SETTER, proxy)) return false; if (desc.value().isObject()) { diff --git a/js/xpconnect/wrappers/AccessCheck.cpp b/js/xpconnect/wrappers/AccessCheck.cpp index 2c4b77b1c50f..b238dd217f6a 100644 --- a/js/xpconnect/wrappers/AccessCheck.cpp +++ b/js/xpconnect/wrappers/AccessCheck.cpp @@ -185,7 +185,7 @@ AccessCheck::isCrossOriginAccessPermitted(JSContext *cx, HandleObject wrapper, H // Check for frame IDs. If we're resolving named frames, make sure to only // resolve ones that don't shadow native properties. See bug 860494. if (IsWindow(name)) { - if (JSID_IS_STRING(id) && !XrayUtils::IsXrayResolving(cx, wrapper, id)) { + if (JSID_IS_STRING(id)) { bool wouldShadow = false; if (!XrayUtils::HasNativeProperty(cx, wrapper, id, &wouldShadow) || wouldShadow) diff --git a/js/xpconnect/wrappers/FilteringWrapper.cpp b/js/xpconnect/wrappers/FilteringWrapper.cpp index 55f0ccc312bb..edd10ee4e75a 100644 --- a/js/xpconnect/wrappers/FilteringWrapper.cpp +++ b/js/xpconnect/wrappers/FilteringWrapper.cpp @@ -156,22 +156,6 @@ bool FilteringWrapper::enter(JSContext *cx, HandleObject wrapper, HandleId id, Wrapper::Action act, bool *bp) const { - // This is a super ugly hacky to get around Xray Resolve wonkiness. - // - // Basically, XPCWN Xrays sometimes call into the Resolve hook of the - // scriptable helper, and pass the wrapper itself as the object upon which - // the resolve is happening. Then, special handling happens in - // XrayWrapper::defineProperty to detect the resolve and redefine the - // property on the holder. Really, we should just pass the holder itself to - // NewResolve, but there's too much code in nsDOMClassInfo that assumes this - // isn't the case (in particular, code expects to be able to look up - // properties on the object, which doesn't work for the holder). Given that - // these hooks are going away eventually with the new DOM bindings, let's - // just hack around this for now. - if (XrayUtils::IsXrayResolving(cx, wrapper, id)) { - *bp = true; - return true; - } if (!Policy::check(cx, wrapper, id, act)) { *bp = JS_IsExceptionPending(cx) ? false : Policy::deny(act, id); return false; @@ -240,11 +224,6 @@ CrossOriginXrayWrapper::defineProperty(JSContext *cx, JS::Handle wrap JS::Handle id, JS::MutableHandle desc) const { - // Until XPCWN Xrays go away, we'll have native resolves looping back - // through here. - if (XrayUtils::IsXrayResolving(cx, wrapper, id)) - return SecurityXrayDOM::defineProperty(cx, wrapper, id, desc); - JS_ReportError(cx, "Permission denied to define property on cross-origin object"); return false; } diff --git a/js/xpconnect/wrappers/WrapperFactory.cpp b/js/xpconnect/wrappers/WrapperFactory.cpp index d3472ac6fbf2..4b45981c3a36 100644 --- a/js/xpconnect/wrappers/WrapperFactory.cpp +++ b/js/xpconnect/wrappers/WrapperFactory.cpp @@ -596,13 +596,6 @@ WrapperFactory::WaiveXrayAndWrap(JSContext *cx, MutableHandleObject argObj) return true; } -bool -WrapperFactory::XrayWrapperNotShadowing(JSObject *wrapper, jsid id) -{ - ResolvingId *rid = ResolvingId::getResolvingIdFromWrapper(wrapper); - return rid->isXrayShadowing(id); -} - /* * Calls to JS_TransplantObject* should go through these helpers here so that * waivers get fixed up properly. diff --git a/js/xpconnect/wrappers/WrapperFactory.h b/js/xpconnect/wrappers/WrapperFactory.h index 5cf24e8a3bb7..1d988766862d 100644 --- a/js/xpconnect/wrappers/WrapperFactory.h +++ b/js/xpconnect/wrappers/WrapperFactory.h @@ -52,9 +52,6 @@ class WrapperFactory { // Wrap wrapped object into a waiver wrapper and then re-wrap it. static bool WaiveXrayAndWrap(JSContext *cx, JS::MutableHandleValue vp); static bool WaiveXrayAndWrap(JSContext *cx, JS::MutableHandleObject object); - - // Returns true if the wrapper is in not shadowing mode for the id. - static bool XrayWrapperNotShadowing(JSObject *wrapper, jsid id); }; extern const js::Wrapper XrayWaiver; diff --git a/js/xpconnect/wrappers/XrayWrapper.cpp b/js/xpconnect/wrappers/XrayWrapper.cpp index 8393a5e2d0d4..caa7e8d01eb7 100644 --- a/js/xpconnect/wrappers/XrayWrapper.cpp +++ b/js/xpconnect/wrappers/XrayWrapper.cpp @@ -126,62 +126,6 @@ XrayAwareCalleeGlobal(JSObject *fun) return js::GetGlobalForObjectCrossCompartment(scope); } -const uint32_t JSSLOT_RESOLVING = 0; -ResolvingId::ResolvingId(JSContext *cx, HandleObject wrapper, HandleId id) - : mId(id), - mHolder(cx, getHolderObject(wrapper)), - mPrev(getResolvingId(mHolder)), - mXrayShadowing(false) -{ - js::SetReservedSlot(mHolder, JSSLOT_RESOLVING, js::PrivateValue(this)); -} - -ResolvingId::~ResolvingId() -{ - MOZ_ASSERT(getResolvingId(mHolder) == this, "unbalanced ResolvingIds"); - js::SetReservedSlot(mHolder, JSSLOT_RESOLVING, js::PrivateValue(mPrev)); -} - -bool -ResolvingId::isXrayShadowing(jsid id) -{ - if (!mXrayShadowing) - return false; - - return mId == id; -} - -bool -ResolvingId::isResolving(jsid id) -{ - for (ResolvingId *cur = this; cur; cur = cur->mPrev) { - if (cur->mId == id) - return true; - } - - return false; -} - -ResolvingId * -ResolvingId::getResolvingId(JSObject *holder) -{ - MOZ_ASSERT(strcmp(JS_GetClass(holder)->name, "NativePropertyHolder") == 0); - return (ResolvingId *)js::GetReservedSlot(holder, JSSLOT_RESOLVING).toPrivate(); -} - -JSObject * -ResolvingId::getHolderObject(JSObject *wrapper) -{ - return &js::GetProxyExtra(wrapper, 0).toObject(); -} - -ResolvingId * -ResolvingId::getResolvingIdFromWrapper(JSObject *wrapper) -{ - return getResolvingId(getHolderObject(wrapper)); -} - - JSObject * XrayTraits::getExpandoChain(HandleObject obj) { @@ -203,8 +147,9 @@ XPCWrappedNativeXrayTraits::getWN(JSObject *wrapper) const JSClass XPCWrappedNativeXrayTraits::HolderClass = { "NativePropertyHolder", JSCLASS_HAS_RESERVED_SLOTS(2), - JS_PropertyStub, JS_DeletePropertyStub, holder_get, holder_set, - JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub + JS_PropertyStub, JS_DeletePropertyStub, JS_PropertyStub, + JS_StrictPropertyStub, JS_EnumerateStub, JS_ResolveStub, + JS_ConvertStub }; @@ -1087,16 +1032,6 @@ XrayTraits::ensureHolder(JSContext *cx, HandleObject wrapper) return holder; } -bool -XPCWrappedNativeXrayTraits::isResolving(JSContext *cx, JSObject *holder, - jsid id) -{ - ResolvingId *cur = ResolvingId::getResolvingId(holder); - if (!cur) - return false; - return cur->isResolving(id); -} - namespace XrayUtils { bool @@ -1107,135 +1042,6 @@ IsXPCWNHolderClass(const JSClass *clasp) } - -// Some DOM objects have shared properties that don't have an explicit -// getter/setter and rely on the class getter/setter. We install a -// class getter/setter on the holder object to trigger them. -bool -holder_get(JSContext *cx, HandleObject wrapper, HandleId id, MutableHandleValue vp) -{ - // JSClass::getProperty is wacky enough that it's hard to be sure someone - // can't inherit this getter by prototyping a random object to an - // XrayWrapper. Be safe. - NS_ENSURE_TRUE(WrapperFactory::IsXrayWrapper(wrapper), true); - JSObject *holder = GetHolder(wrapper); - - XPCWrappedNative *wn = XPCWrappedNativeXrayTraits::getWN(wrapper); - if (NATIVE_HAS_FLAG(wn, WantGetProperty)) { - JSAutoCompartment ac(cx, holder); - bool retval = true; - nsresult rv = wn->GetScriptableCallback()->GetProperty(wn, cx, wrapper, - id, vp.address(), &retval); - if (NS_FAILED(rv) || !retval) { - if (retval) - XPCThrower::Throw(rv, cx); - return false; - } - } - return true; -} - -bool -holder_set(JSContext *cx, HandleObject wrapper, HandleId id, bool strict, MutableHandleValue vp) -{ - // JSClass::setProperty is wacky enough that it's hard to be sure someone - // can't inherit this getter by prototyping a random object to an - // XrayWrapper. Be safe. - NS_ENSURE_TRUE(WrapperFactory::IsXrayWrapper(wrapper), true); - JSObject *holder = GetHolder(wrapper); - if (XPCWrappedNativeXrayTraits::isResolving(cx, holder, id)) { - return true; - } - - XPCWrappedNative *wn = XPCWrappedNativeXrayTraits::getWN(wrapper); - if (NATIVE_HAS_FLAG(wn, WantSetProperty)) { - JSAutoCompartment ac(cx, holder); - bool retval = true; - nsresult rv = wn->GetScriptableCallback()->SetProperty(wn, cx, wrapper, - id, vp.address(), &retval); - if (NS_FAILED(rv) || !retval) { - if (retval) - XPCThrower::Throw(rv, cx); - return false; - } - } - return true; -} - -class AutoSetWrapperNotShadowing -{ -public: - explicit AutoSetWrapperNotShadowing(ResolvingId *resolvingId MOZ_GUARD_OBJECT_NOTIFIER_PARAM) - { - MOZ_GUARD_OBJECT_NOTIFIER_INIT; - MOZ_ASSERT(resolvingId); - mResolvingId = resolvingId; - mResolvingId->mXrayShadowing = true; - } - - ~AutoSetWrapperNotShadowing() - { - mResolvingId->mXrayShadowing = false; - } - -private: - MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER - ResolvingId *mResolvingId; -}; - -// This is called after the resolveNativeProperty could not find any property -// with the given id. At this point we can check for DOM specific collections -// like document["formName"] because we already know that it is not shadowing -// any native property. -bool -XPCWrappedNativeXrayTraits::resolveDOMCollectionProperty(JSContext *cx, HandleObject wrapper, - HandleObject holder, HandleId id, - MutableHandle desc) -{ - // If we are not currently resolving this id and resolveNative is called - // we don't do anything. (see defineProperty in case of shadowing is forbidden). - ResolvingId *rid = ResolvingId::getResolvingId(holder); - if (!rid || rid->mId != id) - return true; - - XPCWrappedNative *wn = getWN(wrapper); - if (!wn) { - // This should NEVER happen, but let's be extra careful here - // because of the reported crashes (Bug 832091). - XPCThrower::Throw(NS_ERROR_UNEXPECTED, cx); - return false; - } - if (!NATIVE_HAS_FLAG(wn, WantNewResolve)) - return true; - - ResolvingId *resolvingId = ResolvingId::getResolvingIdFromWrapper(wrapper); - if (!resolvingId) { - // This should NEVER happen, but let's be extra careful here - // becaue of the reported crashes (Bug 832091). - XPCThrower::Throw(NS_ERROR_UNEXPECTED, cx); - return false; - } - - // Setting the current ResolvingId in non-shadowing mode. So for this id - // Xray won't ignore DOM specific collection properties temporarily. - AutoSetWrapperNotShadowing asw(resolvingId); - - bool retval = true; - RootedObject pobj(cx); - nsresult rv = wn->GetScriptableInfo()->GetCallback()->NewResolve(wn, cx, wrapper, id, - pobj.address(), &retval); - if (NS_FAILED(rv)) { - if (retval) - XPCThrower::Throw(rv, cx); - return false; - } - - if (pobj && !JS_GetPropertyDescriptorById(cx, holder, id, desc)) - return false; - - return true; -} - static nsGlobalWindow* AsWindow(JSContext *cx, JSObject *wrapper) { @@ -1285,14 +1091,9 @@ XPCWrappedNativeXrayTraits::resolveNativeProperty(JSContext *cx, HandleObject wr XPCCallContext ccx(JS_CALLER, cx, target, NullPtr(), id); // There are no native numeric (or symbol-keyed) properties, so we can - // shortcut here. We will not find the property. However we want to support - // non shadowing dom specific collection properties like window.frames, so - // we still have to check for those. - if (!JSID_IS_STRING(id)) { - /* Not found */ - return resolveDOMCollectionProperty(cx, wrapper, holder, id, desc); - } - + // shortcut here. We will not find the property. + if (!JSID_IS_STRING(id)) + return true; // The |controllers| property is accessible as a [ChromeOnly] property on // Window.WebIDL, and [noscript] in XPIDL. Chrome needs to see this over @@ -1346,15 +1147,12 @@ XPCWrappedNativeXrayTraits::resolveNativeProperty(JSContext *cx, HandleObject wr XPCWrappedNative *wn = getWN(wrapper); if (ccx.GetWrapper() != wn || !wn->IsValid()) { - // Something is wrong. If the wrapper is not even valid let's not risk - // calling resolveDOMCollectionProperty. return true; - } else if (!(iface = ccx.GetInterface()) || - !(member = ccx.GetMember())) { - /* Not found */ - return resolveDOMCollectionProperty(cx, wrapper, holder, id, desc); } + if (!(iface = ccx.GetInterface()) || !(member = ccx.GetMember())) + return true; + desc.object().set(holder); desc.setAttributes(JSPROP_ENUMERATE); desc.setGetter(nullptr); @@ -1541,45 +1339,6 @@ XPCWrappedNativeXrayTraits::resolveOwnProperty(JSContext *cx, const Wrapper &jsW // in the wrapper's compartment here, not the wrappee. MOZ_ASSERT(js::IsObjectInContextCompartment(wrapper, cx)); - bool hasProp; - if (!JS_HasPropertyById(cx, holder, id, &hasProp)) { - return false; - } - if (!hasProp) { - XPCWrappedNative *wn = getWN(wrapper); - - // Run the resolve hook of the wrapped native. - if (!NATIVE_HAS_FLAG(wn, WantNewResolve)) { - return true; - } - - bool retval = true; - RootedObject pobj(cx); - nsIXPCScriptable *callback = wn->GetScriptableInfo()->GetCallback(); - nsresult rv = callback->NewResolve(wn, cx, wrapper, id, pobj.address(), - &retval); - if (NS_FAILED(rv)) { - if (retval) - XPCThrower::Throw(rv, cx); - return false; - } - - MOZ_ASSERT(!pobj || (JS_HasPropertyById(cx, holder, id, &hasProp) && - hasProp), "id got defined somewhere else?"); - } - - // resolveOwnProperty must return a non-empty |desc| if and only if an |own| - // property was found on the object. However, given how the NewResolve setup - // works, we can't run the resolve hook if the holder already has a property - // of the same name. So if there was a pre-existing property on the holder, - // we have to use it. But we have no way of knowing if it corresponded to an - // |own| or non-|own| property, since both get cached on the holder and the - // |own|-ness information is lost. - // - // So we just over-zealously call things |own| here. This can cause us to - // return non-|own| properties from Object.getOwnPropertyDescriptor if - // lookups are performed in a certain order, but we can probably live with - // that until XPCWN Xrays go away with the new DOM bindings. return JS_GetPropertyDescriptorById(cx, holder, id, desc); } @@ -1590,18 +1349,6 @@ XPCWrappedNativeXrayTraits::defineProperty(JSContext *cx, HandleObject wrapper, { *defined = false; RootedObject holder(cx, singleton.ensureHolder(cx, wrapper)); - if (isResolving(cx, holder, id)) { - if (!desc.hasAttributes(JSPROP_GETTER | JSPROP_SETTER)) { - if (!desc.getter()) - desc.setGetter(holder_get); - if (!desc.setter()) - desc.setSetter(holder_set); - } - - *defined = true; - return JS_DefinePropertyById(cx, holder, id, desc.value(), desc.attributes(), - desc.getter(), desc.setter()); - } // Check for an indexed property on a Window. If that's happening, do // nothing but claim we defined it so it won't get added as an expando. @@ -1647,13 +1394,7 @@ JSObject * XPCWrappedNativeXrayTraits::createHolder(JSContext *cx, JSObject *wrapper) { RootedObject global(cx, JS_GetGlobalForObject(cx, wrapper)); - JSObject *holder = JS_NewObjectWithGivenProto(cx, &HolderClass, JS::NullPtr(), - global); - if (!holder) - return nullptr; - - js::SetReservedSlot(holder, JSSLOT_RESOLVING, PrivateValue(nullptr)); - return holder; + return JS_NewObjectWithGivenProto(cx, &HolderClass, JS::NullPtr(), global); } bool @@ -1661,7 +1402,7 @@ XPCWrappedNativeXrayTraits::call(JSContext *cx, HandleObject wrapper, const JS::CallArgs &args, const js::Wrapper& baseInstance) { - // Run the resolve hook of the wrapped native. + // Run the call hook of the wrapped native. XPCWrappedNative *wn = getWN(wrapper); if (NATIVE_HAS_FLAG(wn, WantCall)) { XPCCallContext ccx(JS_CALLER, cx, wrapper, NullPtr(), JSID_VOIDHANDLE, args.length(), @@ -1687,7 +1428,7 @@ XPCWrappedNativeXrayTraits::construct(JSContext *cx, HandleObject wrapper, const JS::CallArgs &args, const js::Wrapper& baseInstance) { - // Run the resolve hook of the wrapped native. + // Run the construct hook of the wrapped native. XPCWrappedNative *wn = getWN(wrapper); if (NATIVE_HAS_FLAG(wn, WantConstruct)) { XPCCallContext ccx(JS_CALLER, cx, wrapper, NullPtr(), JSID_VOIDHANDLE, args.length(), @@ -1910,19 +1651,6 @@ GetNativePropertiesObject(JSContext *cx, JSObject *wrapper) return holder; } -bool -IsXrayResolving(JSContext *cx, HandleObject wrapper, HandleId id) -{ - if (!WrapperFactory::IsXrayWrapper(wrapper) || - GetXrayType(wrapper) != XrayForWrappedNative) - { - return false; - } - JSObject *holder = - XPCWrappedNativeXrayTraits::singleton.ensureHolder(cx, wrapper); - return XPCWrappedNativeXrayTraits::isResolving(cx, holder, id); -} - bool HasNativeProperty(JSContext *cx, HandleObject wrapper, HandleId id, bool *hasProp) { @@ -1936,9 +1664,6 @@ HasNativeProperty(JSContext *cx, HandleObject wrapper, HandleId id, bool *hasPro const Wrapper *handler = Wrapper::wrapperHandler(wrapper); // Try resolveOwnProperty. - Maybe resolvingId; - if (traits == &XPCWrappedNativeXrayTraits::singleton) - resolvingId.emplace(cx, wrapper, id); if (!traits->resolveOwnProperty(cx, *handler, wrapper, holder, id, &desc)) return false; if (desc.object()) { @@ -2085,12 +1810,6 @@ XrayWrapper::getPropertyDescriptor(JSContext *cx, HandleObject wra assertEnteredPolicy(cx, wrapper, id, BaseProxyHandler::GET | BaseProxyHandler::SET | BaseProxyHandler::GET_PROPERTY_DESCRIPTOR); RootedObject holder(cx, Traits::singleton.ensureHolder(cx, wrapper)); - if (Traits::isResolving(cx, holder, id)) { - desc.object().set(nullptr); - return true; - } - - typename Traits::ResolvingIdImpl resolving(cx, wrapper, id); if (!holder) return false; @@ -2218,15 +1937,6 @@ XrayWrapper::getOwnPropertyDescriptor(JSContext *cx, HandleObject assertEnteredPolicy(cx, wrapper, id, BaseProxyHandler::GET | BaseProxyHandler::SET | BaseProxyHandler::GET_PROPERTY_DESCRIPTOR); RootedObject holder(cx, Traits::singleton.ensureHolder(cx, wrapper)); - if (Traits::isResolving(cx, holder, id)) { - desc.object().set(nullptr); - return true; - } - - typename Traits::ResolvingIdImpl resolving(cx, wrapper, id); - - // NB: Nothing we do here acts on the wrapped native itself, so we don't - // enter our policy. if (!Traits::singleton.resolveOwnProperty(cx, *this, wrapper, holder, id, desc)) return false; diff --git a/js/xpconnect/wrappers/XrayWrapper.h b/js/xpconnect/wrappers/XrayWrapper.h index 9515841a6d73..8a2dc9d3cd04 100644 --- a/js/xpconnect/wrappers/XrayWrapper.h +++ b/js/xpconnect/wrappers/XrayWrapper.h @@ -24,12 +24,6 @@ class XPCWrappedNative; namespace xpc { -bool -holder_get(JSContext *cx, JS::HandleObject holder, JS::HandleId id, JS::MutableHandleValue vp); -bool -holder_set(JSContext *cx, JS::HandleObject holder, JS::HandleId id, bool strict, - JS::MutableHandleValue vp); - namespace XrayUtils { bool IsXPCWNHolderClass(const JSClass *clasp); @@ -42,9 +36,6 @@ IsTransparent(JSContext *cx, JS::HandleObject wrapper, JS::HandleId id); JSObject * GetNativePropertiesObject(JSContext *cx, JSObject *wrapper); -bool -IsXrayResolving(JSContext *cx, JS::HandleObject wrapper, JS::HandleId id); - bool HasNativeProperty(JSContext *cx, JS::HandleObject wrapper, JS::HandleId id, bool *hasProp); @@ -58,35 +49,6 @@ enum XrayType { NotXray }; -class MOZ_STACK_CLASS ResolvingId { -public: - ResolvingId(JSContext *cx, JS::HandleObject wrapper, JS::HandleId id); - ~ResolvingId(); - - bool isXrayShadowing(jsid id); - bool isResolving(jsid id); - static ResolvingId* getResolvingId(JSObject *holder); - static JSObject* getHolderObject(JSObject *wrapper); - static ResolvingId *getResolvingIdFromWrapper(JSObject *wrapper); - -private: - friend class AutoSetWrapperNotShadowing; - friend class XPCWrappedNativeXrayTraits; - - JS::HandleId mId; - JS::RootedObject mHolder; - ResolvingId *mPrev; - bool mXrayShadowing; -}; - -class MOZ_STACK_CLASS ResolvingIdDummy -{ -public: - ResolvingIdDummy(JSContext *cx, JS::HandleObject wrapper, JS::HandleId id) - { - } -}; - class XrayTraits { public: @@ -174,8 +136,6 @@ public: static bool construct(JSContext *cx, JS::HandleObject wrapper, const JS::CallArgs &args, const js::Wrapper& baseInstance); - static bool isResolving(JSContext *cx, JSObject *holder, jsid id); - static bool resolveDOMCollectionProperty(JSContext *cx, JS::HandleObject wrapper, JS::HandleObject holder, JS::HandleId id, JS::MutableHandle desc); @@ -184,8 +144,6 @@ public: virtual void preserveWrapper(JSObject *target) MOZ_OVERRIDE; - typedef ResolvingId ResolvingIdImpl; - virtual JSObject* createHolder(JSContext *cx, JSObject *wrapper) MOZ_OVERRIDE; static const JSClass HolderClass; @@ -219,13 +177,6 @@ public: static bool construct(JSContext *cx, JS::HandleObject wrapper, const JS::CallArgs &args, const js::Wrapper& baseInstance); - static bool isResolving(JSContext *cx, JSObject *holder, jsid id) - { - return false; - } - - typedef ResolvingIdDummy ResolvingIdImpl; - virtual void preserveWrapper(JSObject *target) MOZ_OVERRIDE; virtual JSObject* createHolder(JSContext *cx, JSObject *wrapper) MOZ_OVERRIDE; @@ -287,13 +238,6 @@ public: return false; } - static bool isResolving(JSContext *cx, JSObject *holder, jsid id) - { - return false; - } - - typedef ResolvingIdDummy ResolvingIdImpl; - bool getPrototypeOf(JSContext *cx, JS::HandleObject wrapper, JS::HandleObject target, JS::MutableHandleObject protop) @@ -408,13 +352,6 @@ public: return false; } - static bool isResolving(JSContext *cx, JSObject *holder, jsid id) - { - return false; - } - - typedef ResolvingIdDummy ResolvingIdImpl; - bool getPrototypeOf(JSContext *cx, JS::HandleObject wrapper, JS::HandleObject target, JS::MutableHandleObject protop) From bca5ea6dd23fe0ba70364059bffdc61a3e3761f8 Mon Sep 17 00:00:00 2001 From: Bobby Holley Date: Mon, 15 Sep 2014 14:17:32 +0200 Subject: [PATCH 19/53] Bug 1066340 - Handle null/undefined alternativeURI.host. r=Gijs Without this, we fail in [1] and friends when we pass the host value to asyncResolve. [1] browser/base/content/test/general/browser_keywordSearch.js --- browser/base/content/browser.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/browser/base/content/browser.js b/browser/base/content/browser.js index 12eee24de19c..c954df312272 100644 --- a/browser/base/content/browser.js +++ b/browser/base/content/browser.js @@ -682,7 +682,7 @@ function gKeywordURIFixup({ target: browser, data: fixupInfo }) { // whether the original input would be vaguely interpretable as a URL, // so figure that out first. let alternativeURI = deserializeURI(fixupInfo.fixedURI); - if (!fixupInfo.fixupUsedKeyword || !alternativeURI) { + if (!fixupInfo.fixupUsedKeyword || !alternativeURI || !alternativeURI.host) { return; } From bc6cdbde352654cb214bc134c9d7a7ce54d703d6 Mon Sep 17 00:00:00 2001 From: Bobby Holley Date: Mon, 15 Sep 2014 14:17:32 +0200 Subject: [PATCH 20/53] Bug 1066340 - Use an AutoEntryScript in nsFrameMessageManager::ReceiveMessage. r=smaug --- content/base/src/nsFrameMessageManager.cpp | 19 +++++++++++++++---- content/base/test/chrome/cpows_child.js | 5 +++++ content/base/test/chrome/cpows_parent.xul | 12 ++++++++++++ 3 files changed, 32 insertions(+), 4 deletions(-) diff --git a/content/base/src/nsFrameMessageManager.cpp b/content/base/src/nsFrameMessageManager.cpp index 0b97e31f0469..b09e14743dc1 100644 --- a/content/base/src/nsFrameMessageManager.cpp +++ b/content/base/src/nsFrameMessageManager.cpp @@ -925,7 +925,6 @@ nsFrameMessageManager::ReceiveMessage(nsISupports* aTarget, nsIPrincipal* aPrincipal, InfallibleTArray* aJSONRetVal) { - AutoSafeJSContext cx; nsAutoTObserverArray* listeners = mListeners.Get(aMessage); if (listeners) { @@ -956,11 +955,23 @@ nsFrameMessageManager::ReceiveMessage(nsISupports* aTarget, if (!wrappedJS) { continue; } - JS::Rooted object(cx, wrappedJS->GetJSObject()); - if (!object) { + + if (!wrappedJS->GetJSObject()) { continue; } - JSAutoCompartment ac(cx, object); + + // Note - The ergonomics here will get a lot better with bug 971673: + // + // AutoEntryScript aes; + // if (!aes.Init(wrappedJS->GetJSObject())) { + // continue; + // } + // JSContext* cx = aes.cx(); + nsIGlobalObject* nativeGlobal = + xpc::GetNativeForGlobal(js::GetGlobalForObjectCrossCompartment(wrappedJS->GetJSObject())); + AutoEntryScript aes(nativeGlobal); + JSContext* cx = aes.cx(); + JS::Rooted object(cx, wrappedJS->GetJSObject()); // The parameter for the listener function. JS::Rooted param(cx, diff --git a/content/base/test/chrome/cpows_child.js b/content/base/test/chrome/cpows_child.js index 2b4ee595bc64..fffbe2b7d664 100644 --- a/content/base/test/chrome/cpows_child.js +++ b/content/base/test/chrome/cpows_child.js @@ -9,6 +9,7 @@ var is_remote; (function start() { [is_remote] = sendSyncMessage("cpows:is_remote"); parent_test(); + error_reporting_test(); dom_test(); xray_test(); compartment_test(); @@ -89,6 +90,10 @@ function parent_test() sendSyncMessage("cpows:parent_test", {}, {func: f}); } +function error_reporting_test() { + sendSyncMessage("cpows:error_reporting_test", {}, {}); +} + function dom_test() { let element = content.document.createElement("div"); diff --git a/content/base/test/chrome/cpows_parent.xul b/content/base/test/chrome/cpows_parent.xul index 6852276c9b8d..87c37ce78b92 100644 --- a/content/base/test/chrome/cpows_parent.xul +++ b/content/base/test/chrome/cpows_parent.xul @@ -33,7 +33,12 @@ } // Make sure that an error in this file actually causes the test to fail. + var gReceivedErrorProbe = false; window.onerror = function (msg, url, line) { + if (/Test Error Probe/.test(msg)) { + gReceivedErrorProbe = true; + return; + } ok(false, "Error while executing: \n" + msg + "\n" + url + ":" + line); }; @@ -175,6 +180,11 @@ savedMM.sendAsyncMessage("cpows:from_parent", {}, {obj: obj}); } + // Make sure errors in this file actually hit window.onerror. + function recvErrorReportingTest(message) { + throw "Test Error Probe"; + } + let savedElement = null; function recvDomTest(message) { savedElement = message.objects.element; @@ -271,6 +281,7 @@ mm.addMessageListener("cpows:done", recvDoneMessage); mm.addMessageListener("cpows:fail", recvFailMessage); mm.addMessageListener("cpows:parent_test", recvParentTest); + mm.addMessageListener("cpows:error_reporting_test", recvErrorReportingTest); mm.addMessageListener("cpows:dom_test", recvDomTest); mm.addMessageListener("cpows:dom_test_after_gc", recvDomTestAfterGC); mm.addMessageListener("cpows:xray_test", recvXrayTest); @@ -285,6 +296,7 @@ } function finish() { + ok(gReceivedErrorProbe, "Should have reported error probe"); opener.setTimeout("done()", 0); window.close(); } From 50e2d796ac2fb838868ed8a713dc7130dd2585df Mon Sep 17 00:00:00 2001 From: Benjamin Bouvier Date: Mon, 15 Sep 2014 14:46:27 +0200 Subject: [PATCH 21/53] Bug 1062217: Rename simdSplat into splatSimd and de-templatize it; r=luke --- js/src/asmjs/AsmJSValidate.cpp | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/js/src/asmjs/AsmJSValidate.cpp b/js/src/asmjs/AsmJSValidate.cpp index ca96a73795ce..df6a5abd0dca 100644 --- a/js/src/asmjs/AsmJSValidate.cpp +++ b/js/src/asmjs/AsmJSValidate.cpp @@ -2444,6 +2444,17 @@ class FunctionCompiler return ins; } + MDefinition *splatSimd(MDefinition *v, MIRType type) + { + if (inDeadCode()) + return nullptr; + + JS_ASSERT(IsSimdType(type)); + MSimdSplatX4 *ins = MSimdSplatX4::New(alloc(), type, v); + curBlock_->add(ins); + return ins; + } + MDefinition *minMax(MDefinition *lhs, MDefinition *rhs, MIRType type, bool isMax) { if (inDeadCode()) return nullptr; @@ -2620,18 +2631,6 @@ class FunctionCompiler return ins; } - template - MDefinition *simdSplat(MDefinition *v, MIRType type) - { - if (inDeadCode()) - return nullptr; - - JS_ASSERT(IsSimdType(type)); - T *ins = T::New(alloc(), type, v); - curBlock_->add(ins); - return ins; - } - /***************************************************************** Calls */ // The IonMonkey backend maintains a single stack offset (from the stack @@ -4724,7 +4723,7 @@ CheckUnarySimd(FunctionCompiler &f, ParseNode *call, const ModuleCompiler::Globa } *type = global->simdOperationType(); - *def = f.simdSplat(argDef, type->toMIRType()); + *def = f.splatSimd(argDef, type->toMIRType()); return true; } @@ -4929,7 +4928,7 @@ CheckSimdCtorCall(FunctionCompiler &f, ParseNode *call, const ModuleCompiler::Gl *type = simdType; if (defs[1] == defs[0] && defs[2] == defs[0] && defs[3] == defs[0]) - *def = f.simdSplat(defs[0], type->toMIRType()); + *def = f.splatSimd(defs[0], type->toMIRType()); else *def = f.constructSimd(defs[0], defs[1], defs[2], defs[3], type->toMIRType()); return true; From e34bfcab70e7ab2ff3af12b0f90fa48d30318a1e Mon Sep 17 00:00:00 2001 From: Benjamin Bouvier Date: Mon, 15 Sep 2014 14:46:32 +0200 Subject: [PATCH 22/53] Bug 1062217: Add operator<= for Type; r=luke --- js/src/asmjs/AsmJSValidate.cpp | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/js/src/asmjs/AsmJSValidate.cpp b/js/src/asmjs/AsmJSValidate.cpp index df6a5abd0dca..c33dcdfba4db 100644 --- a/js/src/asmjs/AsmJSValidate.cpp +++ b/js/src/asmjs/AsmJSValidate.cpp @@ -426,6 +426,29 @@ class Type bool operator==(Type rhs) const { return which_ == rhs.which_; } bool operator!=(Type rhs) const { return which_ != rhs.which_; } + inline bool operator<=(Type rhs) const { + switch (rhs.which_) { + case Type::Signed: return isSigned(); + case Type::Unsigned: return isUnsigned(); + case Type::Double: return isDouble(); + case Type::Float: return isFloat(); + case Type::Int32x4: return isInt32x4(); + case Type::Float32x4: return isFloat32x4(); + case Type::MaybeDouble: return isMaybeDouble(); + case Type::MaybeFloat: return isMaybeFloat(); + case Type::Floatish: return isFloatish(); + case Type::Int: return isInt(); + case Type::Intish: return isIntish(); + case Type::Fixnum: return isFixnum(); + case Type::Void: return isVoid(); + } + MOZ_MAKE_COMPILER_ASSUME_IS_UNREACHABLE("unexpected this type"); + } + + bool isFixnum() const { + return which_ == Fixnum; + } + bool isSigned() const { return which_ == Signed || which_ == Fixnum; } From 61109135a9c9bf9e47475282e6b20a6d679b6f8b Mon Sep 17 00:00:00 2001 From: Benjamin Bouvier Date: Mon, 15 Sep 2014 14:46:35 +0200 Subject: [PATCH 23/53] Bug 1062217: Generalize SIMD operation and ctor validation; r=luke --- js/src/asmjs/AsmJSValidate.cpp | 350 ++++++++++++++++----------------- 1 file changed, 175 insertions(+), 175 deletions(-) diff --git a/js/src/asmjs/AsmJSValidate.cpp b/js/src/asmjs/AsmJSValidate.cpp index c33dcdfba4db..70daa31832da 100644 --- a/js/src/asmjs/AsmJSValidate.cpp +++ b/js/src/asmjs/AsmJSValidate.cpp @@ -558,6 +558,30 @@ class Type MOZ_MAKE_COMPILER_ASSUME_IS_UNREACHABLE("Invalid SIMD Type"); } + Type simdToCoercedScalarType() const { + JS_ASSERT(isSimd()); + switch (which_) { + case Int32x4: + return Intish; + case Float32x4: + return Floatish; + // Scalar types + case Double: + case MaybeDouble: + case Float: + case MaybeFloat: + case Floatish: + case Fixnum: + case Int: + case Signed: + case Unsigned: + case Intish: + case Void: + break; + } + MOZ_MAKE_COMPILER_ASSUME_IS_UNREACHABLE("Invalid SIMD Type"); + } + AsmJSSimdType simdToSimdType() const { JS_ASSERT(isSimd()); switch (which_) { @@ -4718,161 +4742,127 @@ CheckMathBuiltinCall(FunctionCompiler &f, ParseNode *callNode, AsmJSMathBuiltinF return true; } +typedef Vector DefinitionVector; + +template static bool -CheckUnarySimd(FunctionCompiler &f, ParseNode *call, const ModuleCompiler::Global *global, - MDefinition **def, Type *type) +CheckSimdCallArgs(FunctionCompiler &f, ParseNode *call, unsigned expectedArity, + const CheckArgOp &checkArg, DefinitionVector *defs) { unsigned numArgs = CallArgListLength(call); - if (numArgs != 1) - return f.failf(call, "expected 1 argument to unary arithmetic SIMD operation, got %u", numArgs); + if (numArgs != expectedArity) + return f.failf(call, "expected %u arguments to SIMD call, got %u", expectedArity, numArgs); + + DefinitionVector &argDefs = *defs; + if (!argDefs.resize(numArgs)) + return false; ParseNode *arg = CallArgList(call); - MDefinition *argDef; - Type argType; - if (!CheckExpr(f, arg, &argDef, &argType)) - return false; + for (size_t i = 0; i < numArgs; i++, arg = NextNode(arg)) { + MOZ_ASSERT(!!arg); - // For now, the only unary SIMD operation is splat(scalar). - MOZ_ASSERT(global->simdOperation() == AsmJSSimdOperation_splat); - switch (global->simdOperationType()) { - case AsmJSSimdType_int32x4: - if (!argType.isIntish()) - return f.failf(arg, "%s is not a subtype of intish", argType.toChars()); - break; - case AsmJSSimdType_float32x4: - if (!CheckFloatCoercionArg(f, arg, argType, argDef, &argDef)) - return false; - break; - } - - *type = global->simdOperationType(); - *def = f.splatSimd(argDef, type->toMIRType()); - return true; -} - -static bool -CheckBinarySimd(FunctionCompiler &f, ParseNode *call, const ModuleCompiler::Global *global, - MDefinition **def, Type *type) -{ - unsigned numArgs = CallArgListLength(call); - if (numArgs != 2) - return f.failf(call, "expected 2 arguments to binary arithmetic SIMD operation, got %u", numArgs); - - ParseNode *lhs = CallArgList(call); - ParseNode *rhs = NextNode(lhs); - - MDefinition *lhsDef, *rhsDef; - Type lhsType, rhsType; - if (!CheckExpr(f, lhs, &lhsDef, &lhsType)) - return false; - if (!CheckExpr(f, rhs, &rhsDef, &rhsType)) - return false; - - Type retType = global->simdOperationType(); - if (lhsType != retType || rhsType != retType) - return f.failf(lhs, "arguments to SIMD binary op should both be %s", retType.toChars()); - - MIRType opType = retType.toMIRType(); - switch (global->simdOperation()) { - case AsmJSSimdOperation_add: - *def = f.binarySimd(lhsDef, rhsDef, MSimdBinaryArith::Add, opType); - *type = retType; - break; - case AsmJSSimdOperation_sub: - *def = f.binarySimd(lhsDef, rhsDef, MSimdBinaryArith::Sub, opType); - *type = retType; - break; - case AsmJSSimdOperation_mul: - JS_ASSERT(!retType.isInt32x4()); - *def = f.binarySimd(lhsDef, rhsDef, MSimdBinaryArith::Mul, opType); - *type = retType; - break; - case AsmJSSimdOperation_div: - JS_ASSERT(!retType.isInt32x4()); - *def = f.binarySimd(lhsDef, rhsDef, MSimdBinaryArith::Div, opType); - *type = retType; - break; - case AsmJSSimdOperation_lessThan: - *def = f.binarySimd(lhsDef, rhsDef, MSimdBinaryComp::lessThan); - *type = Type::Int32x4; - break; - case AsmJSSimdOperation_lessThanOrEqual: - JS_ASSERT(!retType.isInt32x4()); - *def = f.binarySimd(lhsDef, rhsDef, MSimdBinaryComp::lessThanOrEqual); - *type = Type::Int32x4; - break; - case AsmJSSimdOperation_equal: - *def = f.binarySimd(lhsDef, rhsDef, MSimdBinaryComp::equal); - *type = Type::Int32x4; - break; - case AsmJSSimdOperation_notEqual: - JS_ASSERT(!retType.isInt32x4()); - *def = f.binarySimd(lhsDef, rhsDef, MSimdBinaryComp::notEqual); - *type = Type::Int32x4; - break; - case AsmJSSimdOperation_greaterThan: - *def = f.binarySimd(lhsDef, rhsDef, MSimdBinaryComp::greaterThan); - *type = Type::Int32x4; - break; - case AsmJSSimdOperation_greaterThanOrEqual: - JS_ASSERT(!retType.isInt32x4()); - *def = f.binarySimd(lhsDef, rhsDef, MSimdBinaryComp::greaterThanOrEqual); - *type = Type::Int32x4; - break; - case AsmJSSimdOperation_and: - *def = f.binarySimd(lhsDef, rhsDef, MSimdBinaryBitwise::and_, opType); - *type = retType; - break; - case AsmJSSimdOperation_or: - *def = f.binarySimd(lhsDef, rhsDef, MSimdBinaryBitwise::or_, opType); - *type = retType; - break; - case AsmJSSimdOperation_xor: - *def = f.binarySimd(lhsDef, rhsDef, MSimdBinaryBitwise::xor_, opType); - *type = retType; - break; - case AsmJSSimdOperation_splat: - case AsmJSSimdOperation_select: - MOZ_CRASH("unexpected SIMD binary operation"); + Type argType; + if (!CheckExpr(f, arg, &argDefs[i], &argType)) + return false; + if (!checkArg(f, arg, i, argType, &argDefs[i])) + return false; } return true; } -static bool -CheckSimdSelect(FunctionCompiler &f, ParseNode *call, const ModuleCompiler::Global *global, - MDefinition **def, Type *type) +namespace { + +class CheckSimdScalarArgs { - MOZ_ASSERT(global->simdOperation() == AsmJSSimdOperation_select); + Type formalType_; - unsigned numArgs = CallArgListLength(call); - if (numArgs != 3) - return f.failf(call, "expected 3 arguments to ternary SIMD operation, got %u", numArgs); + public: + explicit CheckSimdScalarArgs(Type t) : formalType_(t.simdToCoercedScalarType()) {} - ParseNode *mask = CallArgList(call); - ParseNode *lhs = NextNode(mask); - ParseNode *rhs = NextNode(lhs); + bool operator()(FunctionCompiler &f, ParseNode *arg, unsigned argIndex, Type actualType, + MDefinition **argDef) const + { + if (formalType_ == Type::Floatish) + return CheckFloatCoercionArg(f, arg, actualType, *argDef, argDef); - MDefinition *maskDef; - Type maskType; - if (!CheckExpr(f, mask, &maskDef, &maskType)) + if (!(actualType <= formalType_)) { + return f.failf(arg, "%s is not a subtype of %s", actualType.toChars(), + formalType_.toChars()); + } + return true; + } +}; + +class CheckSimdVectorArgs +{ + Type formalType_; + + public: + explicit CheckSimdVectorArgs(Type t) : formalType_(t) {} + + bool operator()(FunctionCompiler &f, ParseNode *arg, unsigned argIndex, Type actualType, + MDefinition **argDef) const + { + if (!(actualType <= formalType_)) { + return f.failf(arg, "%s is not a subtype of %s", actualType.toChars(), + formalType_.toChars()); + } + return true; + } +}; + +class CheckSimdSelectArgs +{ + Type formalType_; + + public: + explicit CheckSimdSelectArgs(Type t) : formalType_(t) {} + + bool operator()(FunctionCompiler &f, ParseNode *arg, unsigned argIndex, Type actualType, + MDefinition **argDef) const + { + if (argIndex == 0) { + // First argument of select is an int32x4 mask. + if (!(actualType <= Type::Int32x4)) + return f.failf(arg, "%s is not a subtype of Int32x4", actualType.toChars()); + return true; + } + + if (!(actualType <= formalType_)) { + return f.failf(arg, "%s is not a subtype of %s", actualType.toChars(), + formalType_.toChars()); + } + return true; + } +}; + +} // anonymous namespace + +template +static inline bool +CheckSimdBinary(FunctionCompiler &f, ParseNode *call, Type retType, OpEnum op, MDefinition **def, + Type *type) +{ + DefinitionVector argDefs; + if (!CheckSimdCallArgs(f, call, 2, CheckSimdVectorArgs(retType), &argDefs)) return false; - if (maskType != Type::Int32x4) - return f.failf(mask, "%s is not a subtype of int32x4", maskType.toChars()); - - MDefinition *lhsDef, *rhsDef; - Type lhsType, rhsType; - if (!CheckExpr(f, lhs, &lhsDef, &lhsType)) - return false; - if (!CheckExpr(f, rhs, &rhsDef, &rhsType)) - return false; - - Type retType = global->simdOperationType(); - if (lhsType != retType || rhsType != retType) - return f.failf(mask, "last two arguments to SIMD ternary op should both be %s", retType.toChars()); - + *def = f.binarySimd(argDefs[0], argDefs[1], op, retType.toMIRType()); *type = retType; - *def = f.ternarySimd(maskDef, lhsDef, rhsDef, MSimdTernaryBitwise::select, retType.toMIRType()); + return true; +} + +template<> +inline bool +CheckSimdBinary(FunctionCompiler &f, ParseNode *call, Type retType, + MSimdBinaryComp::Operation op, MDefinition **def, + Type *type) +{ + DefinitionVector argDefs; + if (!CheckSimdCallArgs(f, call, 2, CheckSimdVectorArgs(retType), &argDefs)) + return false; + *def = f.binarySimd(argDefs[0], argDefs[1], op); + *type = Type::Int32x4; return true; } @@ -4880,26 +4870,58 @@ static bool CheckSimdOperationCall(FunctionCompiler &f, ParseNode *call, const ModuleCompiler::Global *global, MDefinition **def, Type *type) { - JS_ASSERT(global->isSimdOperation()); + MOZ_ASSERT(global->isSimdOperation()); + + Type retType = global->simdOperationType(); + switch (global->simdOperation()) { - case AsmJSSimdOperation_splat: - return CheckUnarySimd(f, call, global, def, type); case AsmJSSimdOperation_add: + return CheckSimdBinary(f, call, retType, MSimdBinaryArith::Add, def, type); case AsmJSSimdOperation_sub: + return CheckSimdBinary(f, call, retType, MSimdBinaryArith::Sub, def, type); case AsmJSSimdOperation_mul: + return CheckSimdBinary(f, call, retType, MSimdBinaryArith::Mul, def, type); case AsmJSSimdOperation_div: + return CheckSimdBinary(f, call, retType, MSimdBinaryArith::Div, def, type); + case AsmJSSimdOperation_lessThan: + return CheckSimdBinary(f, call, retType, MSimdBinaryComp::lessThan, def, type); case AsmJSSimdOperation_lessThanOrEqual: + return CheckSimdBinary(f, call, retType, MSimdBinaryComp::lessThanOrEqual, def, type); case AsmJSSimdOperation_equal: + return CheckSimdBinary(f, call, retType, MSimdBinaryComp::equal, def, type); case AsmJSSimdOperation_notEqual: + return CheckSimdBinary(f, call, retType, MSimdBinaryComp::notEqual, def, type); case AsmJSSimdOperation_greaterThan: + return CheckSimdBinary(f, call, retType, MSimdBinaryComp::greaterThan, def, type); case AsmJSSimdOperation_greaterThanOrEqual: + return CheckSimdBinary(f, call, retType, MSimdBinaryComp::greaterThanOrEqual, def, type); + case AsmJSSimdOperation_and: + return CheckSimdBinary(f, call, retType, MSimdBinaryBitwise::and_, def, type); case AsmJSSimdOperation_or: + return CheckSimdBinary(f, call, retType, MSimdBinaryBitwise::or_, def, type); case AsmJSSimdOperation_xor: - return CheckBinarySimd(f, call, global, def, type); - case AsmJSSimdOperation_select: - return CheckSimdSelect(f, call, global, def, type); + return CheckSimdBinary(f, call, retType, MSimdBinaryBitwise::xor_, def, type); + + case AsmJSSimdOperation_splat: { + DefinitionVector defs; + if (!CheckSimdCallArgs(f, call, 1, CheckSimdScalarArgs(retType), &defs)) + return false; + *def = f.splatSimd(defs[0], retType.toMIRType()); + *type = retType; + return true; + } + + case AsmJSSimdOperation_select: { + DefinitionVector defs; + if (!CheckSimdCallArgs(f, call, 3, CheckSimdSelectArgs(retType), &defs)) + return false; + *def = f.ternarySimd(defs[0], defs[1], defs[2], MSimdTernaryBitwise::select, + retType.toMIRType()); + *type = retType; + return true; + } } MOZ_CRASH("unexpected simd operation in CheckSimdOperationCall"); } @@ -4916,44 +4938,22 @@ CheckSimdCtorCall(FunctionCompiler &f, ParseNode *call, const ModuleCompiler::Gl return CheckCoercionArg(f, argNode, coercion, def, type); AsmJSSimdType simdType = global->simdCtorType(); - unsigned numArgs = CallArgListLength(call); unsigned length = SimdTypeToLength(simdType); - if (numArgs != length) - return f.failName(call, "invalid number of arguments in call to '%s'", CallCallee(call)->name()); + Type retType = simdType; - Vector defs; - if (!defs.resize(length)) + DefinitionVector defs; + if (!CheckSimdCallArgs(f, call, length, CheckSimdScalarArgs(retType), &defs)) return false; - argNode = CallArgList(call); - size_t i = 0; - for (; argNode; argNode = NextNode(argNode), ++i) - { - JS_ASSERT(i < length); - - Type argType; - if (!CheckExpr(f, argNode, &defs[i], &argType)) - return false; - - switch (simdType) { - case AsmJSSimdType_int32x4: - if (!argType.isIntish()) - return f.failf(argNode, "argument %d of Int32x4 ctor isn't a subtype of intish", i); - break; - case AsmJSSimdType_float32x4: - if (!CheckFloatCoercionArg(f, argNode, argType, defs[i], &defs[i])) - return false; - break; - } - } - JS_ASSERT(i == length); - - *type = simdType; + // This code will need to be generalized when we handle float64x2 + MOZ_ASSERT(length == 4); + MIRType opType = retType.toMIRType(); if (defs[1] == defs[0] && defs[2] == defs[0] && defs[3] == defs[0]) - *def = f.splatSimd(defs[0], type->toMIRType()); + *def = f.splatSimd(defs[0], opType); else - *def = f.constructSimd(defs[0], defs[1], defs[2], defs[3], type->toMIRType()); + *def = f.constructSimd(defs[0], defs[1], defs[2], defs[3], opType); + *type = retType; return true; } From 4482068d51804f3ae487f05f0d41ad0e8b17b8c7 Mon Sep 17 00:00:00 2001 From: Benjamin Bouvier Date: Mon, 15 Sep 2014 15:13:05 +0200 Subject: [PATCH 24/53] Bug 1066020: Add JSConstIntegerSpec to jsapi; r=till --- js/src/jsapi.cpp | 29 ++++++++++++++++++++++++++--- js/src/jsapi.h | 11 +++++++++-- js/src/jsnum.cpp | 8 ++++---- js/src/jspubtd.h | 5 ++++- 4 files changed, 43 insertions(+), 10 deletions(-) diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp index 701088f0a429..6ac4985f5a05 100644 --- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -3218,8 +3218,20 @@ JS_DefineObject(JSContext *cx, HandleObject obj, const char *name, const JSClass return nobj; } -JS_PUBLIC_API(bool) -JS_DefineConstDoubles(JSContext *cx, HandleObject obj, const JSConstDoubleSpec *cds) +static inline Value +ValueFromScalar(double x) +{ + return DoubleValue(x); +} +static inline Value +ValueFromScalar(int32_t x) +{ + return Int32Value(x); +} + +template +static bool +DefineConstScalar(JSContext *cx, HandleObject obj, const JSConstScalarSpec *cds) { bool ok; unsigned attrs; @@ -3229,7 +3241,7 @@ JS_DefineConstDoubles(JSContext *cx, HandleObject obj, const JSConstDoubleSpec * JSPropertyOpWrapper noget = GetterWrapper(nullptr); JSStrictPropertyOpWrapper noset = SetterWrapper(nullptr); for (ok = true; cds->name; cds++) { - RootedValue value(cx, DoubleValue(cds->dval)); + RootedValue value(cx, ValueFromScalar(cds->val)); attrs = cds->flags; if (!attrs) attrs = JSPROP_READONLY | JSPROP_PERMANENT; @@ -3240,6 +3252,17 @@ JS_DefineConstDoubles(JSContext *cx, HandleObject obj, const JSConstDoubleSpec * return ok; } +JS_PUBLIC_API(bool) +JS_DefineConstDoubles(JSContext *cx, HandleObject obj, const JSConstDoubleSpec *cds) +{ + return DefineConstScalar(cx, obj, cds); +} +JS_PUBLIC_API(bool) +JS_DefineConstIntegers(JSContext *cx, HandleObject obj, const JSConstIntegerSpec *cis) +{ + return DefineConstScalar(cx, obj, cis); +} + JS_PUBLIC_API(bool) JS_DefineProperties(JSContext *cx, HandleObject obj, const JSPropertySpec *ps) { diff --git a/js/src/jsapi.h b/js/src/jsapi.h index 13cb40a8fc69..8fb00a02314a 100644 --- a/js/src/jsapi.h +++ b/js/src/jsapi.h @@ -2303,13 +2303,17 @@ extern JS_PUBLIC_API(bool) JS_ConvertStub(JSContext *cx, JS::HandleObject obj, JSType type, JS::MutableHandleValue vp); -struct JSConstDoubleSpec { - double dval; +template +struct JSConstScalarSpec { + T val; const char *name; uint8_t flags; uint8_t spare[3]; }; +typedef JSConstScalarSpec JSConstDoubleSpec; +typedef JSConstScalarSpec JSConstIntegerSpec; + struct JSJitInfo; /* @@ -2766,6 +2770,9 @@ JS_DefineObject(JSContext *cx, JS::HandleObject obj, const char *name, extern JS_PUBLIC_API(bool) JS_DefineConstDoubles(JSContext *cx, JS::HandleObject obj, const JSConstDoubleSpec *cds); +extern JS_PUBLIC_API(bool) +JS_DefineConstIntegers(JSContext *cx, JS::HandleObject obj, const JSConstIntegerSpec *cis); + extern JS_PUBLIC_API(bool) JS_DefineProperties(JSContext *cx, JS::HandleObject obj, const JSPropertySpec *ps); diff --git a/js/src/jsnum.cpp b/js/src/jsnum.cpp index 5f29e51c59cf..84fbc2cafbe5 100644 --- a/js/src/jsnum.cpp +++ b/js/src/jsnum.cpp @@ -1101,12 +1101,12 @@ js::InitRuntimeNumberState(JSRuntime *rt) * Our NaN must be one particular canonical value, because we rely on NaN * encoding for our value representation. See Value.h. */ - number_constants[NC_NaN].dval = GenericNaN(); + number_constants[NC_NaN].val = GenericNaN(); - number_constants[NC_POSITIVE_INFINITY].dval = mozilla::PositiveInfinity(); - number_constants[NC_NEGATIVE_INFINITY].dval = mozilla::NegativeInfinity(); + number_constants[NC_POSITIVE_INFINITY].val = mozilla::PositiveInfinity(); + number_constants[NC_NEGATIVE_INFINITY].val = mozilla::NegativeInfinity(); - number_constants[NC_MIN_VALUE].dval = MinNumberValue(); + number_constants[NC_MIN_VALUE].val = MinNumberValue(); // XXX If EXPOSE_INTL_API becomes true all the time at some point, // js::InitRuntimeNumberState is no longer fallible, and we should diff --git a/js/src/jspubtd.h b/js/src/jspubtd.h index 55517eec4bbd..e84baa98013e 100644 --- a/js/src/jspubtd.h +++ b/js/src/jspubtd.h @@ -124,7 +124,6 @@ enum JSGCTraceKind { /* Struct forward declarations. */ struct JSClass; struct JSCompartment; -struct JSConstDoubleSpec; struct JSCrossCompartmentCall; struct JSErrorReport; struct JSExceptionState; @@ -148,6 +147,10 @@ class JSFlatString; typedef struct PRCallOnceType JSCallOnceType; typedef bool (*JSInitCallback)(void); +template struct JSConstScalarSpec; +typedef JSConstScalarSpec JSConstDoubleSpec; +typedef JSConstScalarSpec JSConstIntegerSpec; + /* * Generic trace operation that calls JS_CallTracer on each traceable thing * stored in data. From dd59d590622d51ae112e15a5d01ddec0422d5a0d Mon Sep 17 00:00:00 2001 From: Benjamin Bouvier Date: Mon, 15 Sep 2014 15:13:08 +0200 Subject: [PATCH 25/53] Bug 1066020: Remove fields in JSConstScalarSpec and invert fields order; r=till --- js/src/jsapi.cpp | 16 +++++----------- js/src/jsapi.h | 4 +--- js/src/jsmath.cpp | 18 +++++++++--------- js/src/jsnum.cpp | 18 +++++++++--------- 4 files changed, 24 insertions(+), 32 deletions(-) diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp index 6ac4985f5a05..fa0fabc18b97 100644 --- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -3233,23 +3233,17 @@ template static bool DefineConstScalar(JSContext *cx, HandleObject obj, const JSConstScalarSpec *cds) { - bool ok; - unsigned attrs; - AssertHeapIsIdle(cx); CHECK_REQUEST(cx); JSPropertyOpWrapper noget = GetterWrapper(nullptr); JSStrictPropertyOpWrapper noset = SetterWrapper(nullptr); - for (ok = true; cds->name; cds++) { + unsigned attrs = JSPROP_READONLY | JSPROP_PERMANENT; + for (; cds->name; cds++) { RootedValue value(cx, ValueFromScalar(cds->val)); - attrs = cds->flags; - if (!attrs) - attrs = JSPROP_READONLY | JSPROP_PERMANENT; - ok = DefineProperty(cx, obj, cds->name, value, noget, noset, attrs, 0); - if (!ok) - break; + if (!DefineProperty(cx, obj, cds->name, value, noget, noset, attrs, 0)) + return false; } - return ok; + return true; } JS_PUBLIC_API(bool) diff --git a/js/src/jsapi.h b/js/src/jsapi.h index 8fb00a02314a..33d32320d675 100644 --- a/js/src/jsapi.h +++ b/js/src/jsapi.h @@ -2305,10 +2305,8 @@ JS_ConvertStub(JSContext *cx, JS::HandleObject obj, JSType type, template struct JSConstScalarSpec { + const char *name; T val; - const char *name; - uint8_t flags; - uint8_t spare[3]; }; typedef JSConstScalarSpec JSConstDoubleSpec; diff --git a/js/src/jsmath.cpp b/js/src/jsmath.cpp index 237d8d7882fb..ca851089e4c1 100644 --- a/js/src/jsmath.cpp +++ b/js/src/jsmath.cpp @@ -50,15 +50,15 @@ using JS::ToNumber; using JS::GenericNaN; static const JSConstDoubleSpec math_constants[] = { - {M_E, "E", 0, {0,0,0}}, - {M_LOG2E, "LOG2E", 0, {0,0,0}}, - {M_LOG10E, "LOG10E", 0, {0,0,0}}, - {M_LN2, "LN2", 0, {0,0,0}}, - {M_LN10, "LN10", 0, {0,0,0}}, - {M_PI, "PI", 0, {0,0,0}}, - {M_SQRT2, "SQRT2", 0, {0,0,0}}, - {M_SQRT1_2, "SQRT1_2", 0, {0,0,0}}, - {0,0,0,{0,0,0}} + {"E" , M_E }, + {"LOG2E" , M_LOG2E }, + {"LOG10E" , M_LOG10E }, + {"LN2" , M_LN2 }, + {"LN10" , M_LN10 }, + {"PI" , M_PI }, + {"SQRT2" , M_SQRT2 }, + {"SQRT1_2", M_SQRT1_2 }, + {0,0} }; MathCache::MathCache() { diff --git a/js/src/jsnum.cpp b/js/src/jsnum.cpp index 84fbc2cafbe5..614fd5451a24 100644 --- a/js/src/jsnum.cpp +++ b/js/src/jsnum.cpp @@ -1061,18 +1061,18 @@ enum nc_slot { * using union jsdpun. */ static JSConstDoubleSpec number_constants[] = { - {0, "NaN", 0,{0,0,0}}, - {0, "POSITIVE_INFINITY", 0,{0,0,0}}, - {0, "NEGATIVE_INFINITY", 0,{0,0,0}}, - {1.7976931348623157E+308, "MAX_VALUE", 0,{0,0,0}}, - {0, "MIN_VALUE", 0,{0,0,0}}, + {"NaN", 0 }, + {"POSITIVE_INFINITY", 0 }, + {"NEGATIVE_INFINITY", 0 }, + {"MAX_VALUE", 1.7976931348623157E+308 }, + {"MIN_VALUE", 0 }, /* ES6 (April 2014 draft) 20.1.2.6 */ - {9007199254740991, "MAX_SAFE_INTEGER", 0,{0,0,0}}, + {"MAX_SAFE_INTEGER", 9007199254740991 }, /* ES6 (April 2014 draft) 20.1.2.10 */ - {-9007199254740991, "MIN_SAFE_INTEGER", 0,{0,0,0}}, + {"MIN_SAFE_INTEGER", -9007199254740991, }, /* ES6 (May 2013 draft) 15.7.3.7 */ - {2.2204460492503130808472633361816e-16, "EPSILON", 0,{0,0,0}}, - {0,0,0,{0,0,0}} + {"EPSILON", 2.2204460492503130808472633361816e-16}, + {0,0} }; /* From 44d5f7d5f2f928b2cfb073670c1f58934952c55c Mon Sep 17 00:00:00 2001 From: Benjamin Bouvier Date: Mon, 15 Sep 2014 15:13:13 +0200 Subject: [PATCH 26/53] Bug 1066020: Use JSConstIntegerSpec for defining SIMD shuffle masks in the interpreter; r=till --- js/src/builtin/SIMD.cpp | 268 +++++++++++++++++++- js/src/builtin/SIMDShuffleMaskConstants.h | 284 ---------------------- js/src/vm/CommonPropertyNames.h | 2 - 3 files changed, 266 insertions(+), 288 deletions(-) delete mode 100644 js/src/builtin/SIMDShuffleMaskConstants.h diff --git a/js/src/builtin/SIMD.cpp b/js/src/builtin/SIMD.cpp index ec49706df328..88d295c324d4 100644 --- a/js/src/builtin/SIMD.cpp +++ b/js/src/builtin/SIMD.cpp @@ -16,7 +16,6 @@ #include "jsapi.h" #include "jsfriendapi.h" -#include "builtin/SIMDShuffleMaskConstants.h" #include "builtin/TypedObject.h" #include "js/Value.h" @@ -372,6 +371,270 @@ const Class SIMDObject::class_ = { nullptr }; +static JSConstIntegerSpec SHUFFLE_MASKS[] = { + {"XXXX", 0x0}, + {"XXXY", 0x40}, + {"XXXZ", 0x80}, + {"XXXW", 0xC0}, + {"XXYX", 0x10}, + {"XXYY", 0x50}, + {"XXYZ", 0x90}, + {"XXYW", 0xD0}, + {"XXZX", 0x20}, + {"XXZY", 0x60}, + {"XXZZ", 0xA0}, + {"XXZW", 0xE0}, + {"XXWX", 0x30}, + {"XXWY", 0x70}, + {"XXWZ", 0xB0}, + {"XXWW", 0xF0}, + {"XYXX", 0x4}, + {"XYXY", 0x44}, + {"XYXZ", 0x84}, + {"XYXW", 0xC4}, + {"XYYX", 0x14}, + {"XYYY", 0x54}, + {"XYYZ", 0x94}, + {"XYYW", 0xD4}, + {"XYZX", 0x24}, + {"XYZY", 0x64}, + {"XYZZ", 0xA4}, + {"XYZW", 0xE4}, + {"XYWX", 0x34}, + {"XYWY", 0x74}, + {"XYWZ", 0xB4}, + {"XYWW", 0xF4}, + {"XZXX", 0x8}, + {"XZXY", 0x48}, + {"XZXZ", 0x88}, + {"XZXW", 0xC8}, + {"XZYX", 0x18}, + {"XZYY", 0x58}, + {"XZYZ", 0x98}, + {"XZYW", 0xD8}, + {"XZZX", 0x28}, + {"XZZY", 0x68}, + {"XZZZ", 0xA8}, + {"XZZW", 0xE8}, + {"XZWX", 0x38}, + {"XZWY", 0x78}, + {"XZWZ", 0xB8}, + {"XZWW", 0xF8}, + {"XWXX", 0xC}, + {"XWXY", 0x4C}, + {"XWXZ", 0x8C}, + {"XWXW", 0xCC}, + {"XWYX", 0x1C}, + {"XWYY", 0x5C}, + {"XWYZ", 0x9C}, + {"XWYW", 0xDC}, + {"XWZX", 0x2C}, + {"XWZY", 0x6C}, + {"XWZZ", 0xAC}, + {"XWZW", 0xEC}, + {"XWWX", 0x3C}, + {"XWWY", 0x7C}, + {"XWWZ", 0xBC}, + {"XWWW", 0xFC}, + {"YXXX", 0x1}, + {"YXXY", 0x41}, + {"YXXZ", 0x81}, + {"YXXW", 0xC1}, + {"YXYX", 0x11}, + {"YXYY", 0x51}, + {"YXYZ", 0x91}, + {"YXYW", 0xD1}, + {"YXZX", 0x21}, + {"YXZY", 0x61}, + {"YXZZ", 0xA1}, + {"YXZW", 0xE1}, + {"YXWX", 0x31}, + {"YXWY", 0x71}, + {"YXWZ", 0xB1}, + {"YXWW", 0xF1}, + {"YYXX", 0x5}, + {"YYXY", 0x45}, + {"YYXZ", 0x85}, + {"YYXW", 0xC5}, + {"YYYX", 0x15}, + {"YYYY", 0x55}, + {"YYYZ", 0x95}, + {"YYYW", 0xD5}, + {"YYZX", 0x25}, + {"YYZY", 0x65}, + {"YYZZ", 0xA5}, + {"YYZW", 0xE5}, + {"YYWX", 0x35}, + {"YYWY", 0x75}, + {"YYWZ", 0xB5}, + {"YYWW", 0xF5}, + {"YZXX", 0x9}, + {"YZXY", 0x49}, + {"YZXZ", 0x89}, + {"YZXW", 0xC9}, + {"YZYX", 0x19}, + {"YZYY", 0x59}, + {"YZYZ", 0x99}, + {"YZYW", 0xD9}, + {"YZZX", 0x29}, + {"YZZY", 0x69}, + {"YZZZ", 0xA9}, + {"YZZW", 0xE9}, + {"YZWX", 0x39}, + {"YZWY", 0x79}, + {"YZWZ", 0xB9}, + {"YZWW", 0xF9}, + {"YWXX", 0xD}, + {"YWXY", 0x4D}, + {"YWXZ", 0x8D}, + {"YWXW", 0xCD}, + {"YWYX", 0x1D}, + {"YWYY", 0x5D}, + {"YWYZ", 0x9D}, + {"YWYW", 0xDD}, + {"YWZX", 0x2D}, + {"YWZY", 0x6D}, + {"YWZZ", 0xAD}, + {"YWZW", 0xED}, + {"YWWX", 0x3D}, + {"YWWY", 0x7D}, + {"YWWZ", 0xBD}, + {"YWWW", 0xFD}, + {"ZXXX", 0x2}, + {"ZXXY", 0x42}, + {"ZXXZ", 0x82}, + {"ZXXW", 0xC2}, + {"ZXYX", 0x12}, + {"ZXYY", 0x52}, + {"ZXYZ", 0x92}, + {"ZXYW", 0xD2}, + {"ZXZX", 0x22}, + {"ZXZY", 0x62}, + {"ZXZZ", 0xA2}, + {"ZXZW", 0xE2}, + {"ZXWX", 0x32}, + {"ZXWY", 0x72}, + {"ZXWZ", 0xB2}, + {"ZXWW", 0xF2}, + {"ZYXX", 0x6}, + {"ZYXY", 0x46}, + {"ZYXZ", 0x86}, + {"ZYXW", 0xC6}, + {"ZYYX", 0x16}, + {"ZYYY", 0x56}, + {"ZYYZ", 0x96}, + {"ZYYW", 0xD6}, + {"ZYZX", 0x26}, + {"ZYZY", 0x66}, + {"ZYZZ", 0xA6}, + {"ZYZW", 0xE6}, + {"ZYWX", 0x36}, + {"ZYWY", 0x76}, + {"ZYWZ", 0xB6}, + {"ZYWW", 0xF6}, + {"ZZXX", 0xA}, + {"ZZXY", 0x4A}, + {"ZZXZ", 0x8A}, + {"ZZXW", 0xCA}, + {"ZZYX", 0x1A}, + {"ZZYY", 0x5A}, + {"ZZYZ", 0x9A}, + {"ZZYW", 0xDA}, + {"ZZZX", 0x2A}, + {"ZZZY", 0x6A}, + {"ZZZZ", 0xAA}, + {"ZZZW", 0xEA}, + {"ZZWX", 0x3A}, + {"ZZWY", 0x7A}, + {"ZZWZ", 0xBA}, + {"ZZWW", 0xFA}, + {"ZWXX", 0xE}, + {"ZWXY", 0x4E}, + {"ZWXZ", 0x8E}, + {"ZWXW", 0xCE}, + {"ZWYX", 0x1E}, + {"ZWYY", 0x5E}, + {"ZWYZ", 0x9E}, + {"ZWYW", 0xDE}, + {"ZWZX", 0x2E}, + {"ZWZY", 0x6E}, + {"ZWZZ", 0xAE}, + {"ZWZW", 0xEE}, + {"ZWWX", 0x3E}, + {"ZWWY", 0x7E}, + {"ZWWZ", 0xBE}, + {"ZWWW", 0xFE}, + {"WXXX", 0x3}, + {"WXXY", 0x43}, + {"WXXZ", 0x83}, + {"WXXW", 0xC3}, + {"WXYX", 0x13}, + {"WXYY", 0x53}, + {"WXYZ", 0x93}, + {"WXYW", 0xD3}, + {"WXZX", 0x23}, + {"WXZY", 0x63}, + {"WXZZ", 0xA3}, + {"WXZW", 0xE3}, + {"WXWX", 0x33}, + {"WXWY", 0x73}, + {"WXWZ", 0xB3}, + {"WXWW", 0xF3}, + {"WYXX", 0x7}, + {"WYXY", 0x47}, + {"WYXZ", 0x87}, + {"WYXW", 0xC7}, + {"WYYX", 0x17}, + {"WYYY", 0x57}, + {"WYYZ", 0x97}, + {"WYYW", 0xD7}, + {"WYZX", 0x27}, + {"WYZY", 0x67}, + {"WYZZ", 0xA7}, + {"WYZW", 0xE7}, + {"WYWX", 0x37}, + {"WYWY", 0x77}, + {"WYWZ", 0xB7}, + {"WYWW", 0xF7}, + {"WZXX", 0xB}, + {"WZXY", 0x4B}, + {"WZXZ", 0x8B}, + {"WZXW", 0xCB}, + {"WZYX", 0x1B}, + {"WZYY", 0x5B}, + {"WZYZ", 0x9B}, + {"WZYW", 0xDB}, + {"WZZX", 0x2B}, + {"WZZY", 0x6B}, + {"WZZZ", 0xAB}, + {"WZZW", 0xEB}, + {"WZWX", 0x3B}, + {"WZWY", 0x7B}, + {"WZWZ", 0xBB}, + {"WZWW", 0xFB}, + {"WWXX", 0xF}, + {"WWXY", 0x4F}, + {"WWXZ", 0x8F}, + {"WWXW", 0xCF}, + {"WWYX", 0x1F}, + {"WWYY", 0x5F}, + {"WWYZ", 0x9F}, + {"WWYW", 0xDF}, + {"WWZX", 0x2F}, + {"WWZY", 0x6F}, + {"WWZZ", 0xAF}, + {"WWZW", 0xEF}, + {"WWWX", 0x3F}, + {"WWWY", 0x7F}, + {"WWWZ", 0xBF}, + {"WWWW", 0xFF}, + {"XX", 0x0}, + {"XY", 0x2}, + {"YX", 0x1}, + {"YY", 0x3}, + {0,0} +}; + JSObject * SIMDObject::initClass(JSContext *cx, Handle global) { @@ -392,7 +655,8 @@ SIMDObject::initClass(JSContext *cx, Handle global) if (!SIMD) return nullptr; - SET_ALL_SHUFFLE_MASKS; + if (!JS_DefineConstIntegers(cx, SIMD, SHUFFLE_MASKS)) + return nullptr; // float32x4 RootedObject float32x4Object(cx); diff --git a/js/src/builtin/SIMDShuffleMaskConstants.h b/js/src/builtin/SIMDShuffleMaskConstants.h deleted file mode 100644 index 3e7e51f74c57..000000000000 --- a/js/src/builtin/SIMDShuffleMaskConstants.h +++ /dev/null @@ -1,284 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * vim: set ts=8 sts=4 et sw=4 tw=99: - * 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/. */ - -#ifndef builtin_SIMDShuffleMaskConstants_h -#define builtin_SIMDShuffleMaskConstants_h - -#define COMMON_PROPERTY_NAMES_MACRO(macro, mask, maskStr, value) macro(mask, mask, maskStr) - -#define SET_SHUFFLE_MASK(macro, maskId, maskStr, value) \ - { \ - RootedValue mask##maskId(cx, JS::Int32Value(value)); \ - JSObject::defineProperty(cx, SIMD, cx->names().maskId, \ - mask##maskId, nullptr, nullptr, \ - JSPROP_READONLY | JSPROP_PERMANENT); \ - } - -#define SET_ALL_SHUFFLE_MASKS FOR_EACH_SIMD_SHUFFLE_MASK(SET_SHUFFLE_MASK, 0) - -#define FOR_EACH_SIMD_SHUFFLE_MASK(macro, innerMacro) \ - macro(innerMacro, XXXX, "XXXX", 0x0) \ - macro(innerMacro, XXXY, "XXXY", 0x40) \ - macro(innerMacro, XXXZ, "XXXZ", 0x80) \ - macro(innerMacro, XXXW, "XXXW", 0xC0) \ - macro(innerMacro, XXYX, "XXYX", 0x10) \ - macro(innerMacro, XXYY, "XXYY", 0x50) \ - macro(innerMacro, XXYZ, "XXYZ", 0x90) \ - macro(innerMacro, XXYW, "XXYW", 0xD0) \ - macro(innerMacro, XXZX, "XXZX", 0x20) \ - macro(innerMacro, XXZY, "XXZY", 0x60) \ - macro(innerMacro, XXZZ, "XXZZ", 0xA0) \ - macro(innerMacro, XXZW, "XXZW", 0xE0) \ - macro(innerMacro, XXWX, "XXWX", 0x30) \ - macro(innerMacro, XXWY, "XXWY", 0x70) \ - macro(innerMacro, XXWZ, "XXWZ", 0xB0) \ - macro(innerMacro, XXWW, "XXWW", 0xF0) \ - macro(innerMacro, XYXX, "XYXX", 0x4) \ - macro(innerMacro, XYXY, "XYXY", 0x44) \ - macro(innerMacro, XYXZ, "XYXZ", 0x84) \ - macro(innerMacro, XYXW, "XYXW", 0xC4) \ - macro(innerMacro, XYYX, "XYYX", 0x14) \ - macro(innerMacro, XYYY, "XYYY", 0x54) \ - macro(innerMacro, XYYZ, "XYYZ", 0x94) \ - macro(innerMacro, XYYW, "XYYW", 0xD4) \ - macro(innerMacro, XYZX, "XYZX", 0x24) \ - macro(innerMacro, XYZY, "XYZY", 0x64) \ - macro(innerMacro, XYZZ, "XYZZ", 0xA4) \ - macro(innerMacro, XYZW, "XYZW", 0xE4) \ - macro(innerMacro, XYWX, "XYWX", 0x34) \ - macro(innerMacro, XYWY, "XYWY", 0x74) \ - macro(innerMacro, XYWZ, "XYWZ", 0xB4) \ - macro(innerMacro, XYWW, "XYWW", 0xF4) \ - macro(innerMacro, XZXX, "XZXX", 0x8) \ - macro(innerMacro, XZXY, "XZXY", 0x48) \ - macro(innerMacro, XZXZ, "XZXZ", 0x88) \ - macro(innerMacro, XZXW, "XZXW", 0xC8) \ - macro(innerMacro, XZYX, "XZYX", 0x18) \ - macro(innerMacro, XZYY, "XZYY", 0x58) \ - macro(innerMacro, XZYZ, "XZYZ", 0x98) \ - macro(innerMacro, XZYW, "XZYW", 0xD8) \ - macro(innerMacro, XZZX, "XZZX", 0x28) \ - macro(innerMacro, XZZY, "XZZY", 0x68) \ - macro(innerMacro, XZZZ, "XZZZ", 0xA8) \ - macro(innerMacro, XZZW, "XZZW", 0xE8) \ - macro(innerMacro, XZWX, "XZWX", 0x38) \ - macro(innerMacro, XZWY, "XZWY", 0x78) \ - macro(innerMacro, XZWZ, "XZWZ", 0xB8) \ - macro(innerMacro, XZWW, "XZWW", 0xF8) \ - macro(innerMacro, XWXX, "XWXX", 0xC) \ - macro(innerMacro, XWXY, "XWXY", 0x4C) \ - macro(innerMacro, XWXZ, "XWXZ", 0x8C) \ - macro(innerMacro, XWXW, "XWXW", 0xCC) \ - macro(innerMacro, XWYX, "XWYX", 0x1C) \ - macro(innerMacro, XWYY, "XWYY", 0x5C) \ - macro(innerMacro, XWYZ, "XWYZ", 0x9C) \ - macro(innerMacro, XWYW, "XWYW", 0xDC) \ - macro(innerMacro, XWZX, "XWZX", 0x2C) \ - macro(innerMacro, XWZY, "XWZY", 0x6C) \ - macro(innerMacro, XWZZ, "XWZZ", 0xAC) \ - macro(innerMacro, XWZW, "XWZW", 0xEC) \ - macro(innerMacro, XWWX, "XWWX", 0x3C) \ - macro(innerMacro, XWWY, "XWWY", 0x7C) \ - macro(innerMacro, XWWZ, "XWWZ", 0xBC) \ - macro(innerMacro, XWWW, "XWWW", 0xFC) \ - macro(innerMacro, YXXX, "YXXX", 0x1) \ - macro(innerMacro, YXXY, "YXXY", 0x41) \ - macro(innerMacro, YXXZ, "YXXZ", 0x81) \ - macro(innerMacro, YXXW, "YXXW", 0xC1) \ - macro(innerMacro, YXYX, "YXYX", 0x11) \ - macro(innerMacro, YXYY, "YXYY", 0x51) \ - macro(innerMacro, YXYZ, "YXYZ", 0x91) \ - macro(innerMacro, YXYW, "YXYW", 0xD1) \ - macro(innerMacro, YXZX, "YXZX", 0x21) \ - macro(innerMacro, YXZY, "YXZY", 0x61) \ - macro(innerMacro, YXZZ, "YXZZ", 0xA1) \ - macro(innerMacro, YXZW, "YXZW", 0xE1) \ - macro(innerMacro, YXWX, "YXWX", 0x31) \ - macro(innerMacro, YXWY, "YXWY", 0x71) \ - macro(innerMacro, YXWZ, "YXWZ", 0xB1) \ - macro(innerMacro, YXWW, "YXWW", 0xF1) \ - macro(innerMacro, YYXX, "YYXX", 0x5) \ - macro(innerMacro, YYXY, "YYXY", 0x45) \ - macro(innerMacro, YYXZ, "YYXZ", 0x85) \ - macro(innerMacro, YYXW, "YYXW", 0xC5) \ - macro(innerMacro, YYYX, "YYYX", 0x15) \ - macro(innerMacro, YYYY, "YYYY", 0x55) \ - macro(innerMacro, YYYZ, "YYYZ", 0x95) \ - macro(innerMacro, YYYW, "YYYW", 0xD5) \ - macro(innerMacro, YYZX, "YYZX", 0x25) \ - macro(innerMacro, YYZY, "YYZY", 0x65) \ - macro(innerMacro, YYZZ, "YYZZ", 0xA5) \ - macro(innerMacro, YYZW, "YYZW", 0xE5) \ - macro(innerMacro, YYWX, "YYWX", 0x35) \ - macro(innerMacro, YYWY, "YYWY", 0x75) \ - macro(innerMacro, YYWZ, "YYWZ", 0xB5) \ - macro(innerMacro, YYWW, "YYWW", 0xF5) \ - macro(innerMacro, YZXX, "YZXX", 0x9) \ - macro(innerMacro, YZXY, "YZXY", 0x49) \ - macro(innerMacro, YZXZ, "YZXZ", 0x89) \ - macro(innerMacro, YZXW, "YZXW", 0xC9) \ - macro(innerMacro, YZYX, "YZYX", 0x19) \ - macro(innerMacro, YZYY, "YZYY", 0x59) \ - macro(innerMacro, YZYZ, "YZYZ", 0x99) \ - macro(innerMacro, YZYW, "YZYW", 0xD9) \ - macro(innerMacro, YZZX, "YZZX", 0x29) \ - macro(innerMacro, YZZY, "YZZY", 0x69) \ - macro(innerMacro, YZZZ, "YZZZ", 0xA9) \ - macro(innerMacro, YZZW, "YZZW", 0xE9) \ - macro(innerMacro, YZWX, "YZWX", 0x39) \ - macro(innerMacro, YZWY, "YZWY", 0x79) \ - macro(innerMacro, YZWZ, "YZWZ", 0xB9) \ - macro(innerMacro, YZWW, "YZWW", 0xF9) \ - macro(innerMacro, YWXX, "YWXX", 0xD) \ - macro(innerMacro, YWXY, "YWXY", 0x4D) \ - macro(innerMacro, YWXZ, "YWXZ", 0x8D) \ - macro(innerMacro, YWXW, "YWXW", 0xCD) \ - macro(innerMacro, YWYX, "YWYX", 0x1D) \ - macro(innerMacro, YWYY, "YWYY", 0x5D) \ - macro(innerMacro, YWYZ, "YWYZ", 0x9D) \ - macro(innerMacro, YWYW, "YWYW", 0xDD) \ - macro(innerMacro, YWZX, "YWZX", 0x2D) \ - macro(innerMacro, YWZY, "YWZY", 0x6D) \ - macro(innerMacro, YWZZ, "YWZZ", 0xAD) \ - macro(innerMacro, YWZW, "YWZW", 0xED) \ - macro(innerMacro, YWWX, "YWWX", 0x3D) \ - macro(innerMacro, YWWY, "YWWY", 0x7D) \ - macro(innerMacro, YWWZ, "YWWZ", 0xBD) \ - macro(innerMacro, YWWW, "YWWW", 0xFD) \ - macro(innerMacro, ZXXX, "ZXXX", 0x2) \ - macro(innerMacro, ZXXY, "ZXXY", 0x42) \ - macro(innerMacro, ZXXZ, "ZXXZ", 0x82) \ - macro(innerMacro, ZXXW, "ZXXW", 0xC2) \ - macro(innerMacro, ZXYX, "ZXYX", 0x12) \ - macro(innerMacro, ZXYY, "ZXYY", 0x52) \ - macro(innerMacro, ZXYZ, "ZXYZ", 0x92) \ - macro(innerMacro, ZXYW, "ZXYW", 0xD2) \ - macro(innerMacro, ZXZX, "ZXZX", 0x22) \ - macro(innerMacro, ZXZY, "ZXZY", 0x62) \ - macro(innerMacro, ZXZZ, "ZXZZ", 0xA2) \ - macro(innerMacro, ZXZW, "ZXZW", 0xE2) \ - macro(innerMacro, ZXWX, "ZXWX", 0x32) \ - macro(innerMacro, ZXWY, "ZXWY", 0x72) \ - macro(innerMacro, ZXWZ, "ZXWZ", 0xB2) \ - macro(innerMacro, ZXWW, "ZXWW", 0xF2) \ - macro(innerMacro, ZYXX, "ZYXX", 0x6) \ - macro(innerMacro, ZYXY, "ZYXY", 0x46) \ - macro(innerMacro, ZYXZ, "ZYXZ", 0x86) \ - macro(innerMacro, ZYXW, "ZYXW", 0xC6) \ - macro(innerMacro, ZYYX, "ZYYX", 0x16) \ - macro(innerMacro, ZYYY, "ZYYY", 0x56) \ - macro(innerMacro, ZYYZ, "ZYYZ", 0x96) \ - macro(innerMacro, ZYYW, "ZYYW", 0xD6) \ - macro(innerMacro, ZYZX, "ZYZX", 0x26) \ - macro(innerMacro, ZYZY, "ZYZY", 0x66) \ - macro(innerMacro, ZYZZ, "ZYZZ", 0xA6) \ - macro(innerMacro, ZYZW, "ZYZW", 0xE6) \ - macro(innerMacro, ZYWX, "ZYWX", 0x36) \ - macro(innerMacro, ZYWY, "ZYWY", 0x76) \ - macro(innerMacro, ZYWZ, "ZYWZ", 0xB6) \ - macro(innerMacro, ZYWW, "ZYWW", 0xF6) \ - macro(innerMacro, ZZXX, "ZZXX", 0xA) \ - macro(innerMacro, ZZXY, "ZZXY", 0x4A) \ - macro(innerMacro, ZZXZ, "ZZXZ", 0x8A) \ - macro(innerMacro, ZZXW, "ZZXW", 0xCA) \ - macro(innerMacro, ZZYX, "ZZYX", 0x1A) \ - macro(innerMacro, ZZYY, "ZZYY", 0x5A) \ - macro(innerMacro, ZZYZ, "ZZYZ", 0x9A) \ - macro(innerMacro, ZZYW, "ZZYW", 0xDA) \ - macro(innerMacro, ZZZX, "ZZZX", 0x2A) \ - macro(innerMacro, ZZZY, "ZZZY", 0x6A) \ - macro(innerMacro, ZZZZ, "ZZZZ", 0xAA) \ - macro(innerMacro, ZZZW, "ZZZW", 0xEA) \ - macro(innerMacro, ZZWX, "ZZWX", 0x3A) \ - macro(innerMacro, ZZWY, "ZZWY", 0x7A) \ - macro(innerMacro, ZZWZ, "ZZWZ", 0xBA) \ - macro(innerMacro, ZZWW, "ZZWW", 0xFA) \ - macro(innerMacro, ZWXX, "ZWXX", 0xE) \ - macro(innerMacro, ZWXY, "ZWXY", 0x4E) \ - macro(innerMacro, ZWXZ, "ZWXZ", 0x8E) \ - macro(innerMacro, ZWXW, "ZWXW", 0xCE) \ - macro(innerMacro, ZWYX, "ZWYX", 0x1E) \ - macro(innerMacro, ZWYY, "ZWYY", 0x5E) \ - macro(innerMacro, ZWYZ, "ZWYZ", 0x9E) \ - macro(innerMacro, ZWYW, "ZWYW", 0xDE) \ - macro(innerMacro, ZWZX, "ZWZX", 0x2E) \ - macro(innerMacro, ZWZY, "ZWZY", 0x6E) \ - macro(innerMacro, ZWZZ, "ZWZZ", 0xAE) \ - macro(innerMacro, ZWZW, "ZWZW", 0xEE) \ - macro(innerMacro, ZWWX, "ZWWX", 0x3E) \ - macro(innerMacro, ZWWY, "ZWWY", 0x7E) \ - macro(innerMacro, ZWWZ, "ZWWZ", 0xBE) \ - macro(innerMacro, ZWWW, "ZWWW", 0xFE) \ - macro(innerMacro, WXXX, "WXXX", 0x3) \ - macro(innerMacro, WXXY, "WXXY", 0x43) \ - macro(innerMacro, WXXZ, "WXXZ", 0x83) \ - macro(innerMacro, WXXW, "WXXW", 0xC3) \ - macro(innerMacro, WXYX, "WXYX", 0x13) \ - macro(innerMacro, WXYY, "WXYY", 0x53) \ - macro(innerMacro, WXYZ, "WXYZ", 0x93) \ - macro(innerMacro, WXYW, "WXYW", 0xD3) \ - macro(innerMacro, WXZX, "WXZX", 0x23) \ - macro(innerMacro, WXZY, "WXZY", 0x63) \ - macro(innerMacro, WXZZ, "WXZZ", 0xA3) \ - macro(innerMacro, WXZW, "WXZW", 0xE3) \ - macro(innerMacro, WXWX, "WXWX", 0x33) \ - macro(innerMacro, WXWY, "WXWY", 0x73) \ - macro(innerMacro, WXWZ, "WXWZ", 0xB3) \ - macro(innerMacro, WXWW, "WXWW", 0xF3) \ - macro(innerMacro, WYXX, "WYXX", 0x7) \ - macro(innerMacro, WYXY, "WYXY", 0x47) \ - macro(innerMacro, WYXZ, "WYXZ", 0x87) \ - macro(innerMacro, WYXW, "WYXW", 0xC7) \ - macro(innerMacro, WYYX, "WYYX", 0x17) \ - macro(innerMacro, WYYY, "WYYY", 0x57) \ - macro(innerMacro, WYYZ, "WYYZ", 0x97) \ - macro(innerMacro, WYYW, "WYYW", 0xD7) \ - macro(innerMacro, WYZX, "WYZX", 0x27) \ - macro(innerMacro, WYZY, "WYZY", 0x67) \ - macro(innerMacro, WYZZ, "WYZZ", 0xA7) \ - macro(innerMacro, WYZW, "WYZW", 0xE7) \ - macro(innerMacro, WYWX, "WYWX", 0x37) \ - macro(innerMacro, WYWY, "WYWY", 0x77) \ - macro(innerMacro, WYWZ, "WYWZ", 0xB7) \ - macro(innerMacro, WYWW, "WYWW", 0xF7) \ - macro(innerMacro, WZXX, "WZXX", 0xB) \ - macro(innerMacro, WZXY, "WZXY", 0x4B) \ - macro(innerMacro, WZXZ, "WZXZ", 0x8B) \ - macro(innerMacro, WZXW, "WZXW", 0xCB) \ - macro(innerMacro, WZYX, "WZYX", 0x1B) \ - macro(innerMacro, WZYY, "WZYY", 0x5B) \ - macro(innerMacro, WZYZ, "WZYZ", 0x9B) \ - macro(innerMacro, WZYW, "WZYW", 0xDB) \ - macro(innerMacro, WZZX, "WZZX", 0x2B) \ - macro(innerMacro, WZZY, "WZZY", 0x6B) \ - macro(innerMacro, WZZZ, "WZZZ", 0xAB) \ - macro(innerMacro, WZZW, "WZZW", 0xEB) \ - macro(innerMacro, WZWX, "WZWX", 0x3B) \ - macro(innerMacro, WZWY, "WZWY", 0x7B) \ - macro(innerMacro, WZWZ, "WZWZ", 0xBB) \ - macro(innerMacro, WZWW, "WZWW", 0xFB) \ - macro(innerMacro, WWXX, "WWXX", 0xF) \ - macro(innerMacro, WWXY, "WWXY", 0x4F) \ - macro(innerMacro, WWXZ, "WWXZ", 0x8F) \ - macro(innerMacro, WWXW, "WWXW", 0xCF) \ - macro(innerMacro, WWYX, "WWYX", 0x1F) \ - macro(innerMacro, WWYY, "WWYY", 0x5F) \ - macro(innerMacro, WWYZ, "WWYZ", 0x9F) \ - macro(innerMacro, WWYW, "WWYW", 0xDF) \ - macro(innerMacro, WWZX, "WWZX", 0x2F) \ - macro(innerMacro, WWZY, "WWZY", 0x6F) \ - macro(innerMacro, WWZZ, "WWZZ", 0xAF) \ - macro(innerMacro, WWZW, "WWZW", 0xEF) \ - macro(innerMacro, WWWX, "WWWX", 0x3F) \ - macro(innerMacro, WWWY, "WWWY", 0x7F) \ - macro(innerMacro, WWWZ, "WWWZ", 0xBF) \ - macro(innerMacro, WWWW, "WWWW", 0xFF) \ - macro(innerMacro, XX, "XX", 0x0) \ - macro(innerMacro, XY, "XY", 0x2) \ - macro(innerMacro, YX, "YX", 0x1) \ - macro(innerMacro, YY, "YY", 0x3) - -#endif diff --git a/js/src/vm/CommonPropertyNames.h b/js/src/vm/CommonPropertyNames.h index 43ed32b8a3ee..a59ac6f9c2d0 100644 --- a/js/src/vm/CommonPropertyNames.h +++ b/js/src/vm/CommonPropertyNames.h @@ -10,7 +10,6 @@ #define vm_CommonPropertyNames_h #include "jsprototypes.h" -#include "builtin/SIMDShuffleMaskConstants.h" #define FOR_EACH_COMMON_PROPERTYNAME(macro) \ macro(anonymous, anonymous, "anonymous") \ @@ -232,6 +231,5 @@ macro(Symbol_toPrimitive, Symbol_toPrimitive, "Symbol.toPrimitive") \ macro(Symbol_toStringTag, Symbol_toStringTag, "Symbol.toStringTag") \ macro(Symbol_unscopables, Symbol_unscopables, "Symbol.unscopables") \ - FOR_EACH_SIMD_SHUFFLE_MASK(COMMON_PROPERTY_NAMES_MACRO, macro) #endif /* vm_CommonPropertyNames_h */ From 23bbee84bdf5ade0baabcf188b8a60ba96819fb7 Mon Sep 17 00:00:00 2001 From: Ethan Hugg Date: Thu, 4 Sep 2014 13:13:25 -0700 Subject: [PATCH 27/53] Bug 1049087 - pre-populate the whitelist for screensharing in Fx33 r=jesup --- modules/libpref/init/all.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/libpref/init/all.js b/modules/libpref/init/all.js index eec3e56aba18..1785c70f4032 100644 --- a/modules/libpref/init/all.js +++ b/modules/libpref/init/all.js @@ -383,10 +383,10 @@ pref("media.getusermedia.screensharing.enabled", true); #endif #ifdef RELEASE_BUILD -pref("media.getusermedia.screensharing.allowed_domains", ""); +pref("media.getusermedia.screensharing.allowed_domains", "webex.com,*.webex.com,collaborate.com,*.collaborate.com"); #else // temporary value, not intended for release - bug 1049087 -pref("media.getusermedia.screensharing.allowed_domains", "mozilla.github.io"); +pref("media.getusermedia.screensharing.allowed_domains", "mozilla.github.io,webex.com,*.webex.com,collaborate.com,*.collaborate.com"); #endif // OS/X 10.6 and XP have screen/window sharing off by default due to various issues - Caveat emptor pref("media.getusermedia.screensharing.allow_on_old_platforms", false); From f9d2a7e73a2d0addffd430d18a6bc78cec87537c Mon Sep 17 00:00:00 2001 From: Georg Fritzsche Date: Mon, 15 Sep 2014 15:28:33 +0200 Subject: [PATCH 28/53] Bug 1064470 - Increase the experiments forensic log buffer size again. r=bsmedberg --- browser/experiments/Experiments.jsm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/browser/experiments/Experiments.jsm b/browser/experiments/Experiments.jsm index fb011952bcc1..b2412f094543 100644 --- a/browser/experiments/Experiments.jsm +++ b/browser/experiments/Experiments.jsm @@ -368,7 +368,7 @@ Experiments.Experiments = function (policy=new Experiments.Policy()) { // crashes. For forensics purposes, keep the last few log // messages in memory and upload them in case of crash. this._forensicsLogs = []; - this._forensicsLogs.length = 10; + this._forensicsLogs.length = 20; this._log = Object.create(log); this._log.log = (level, string, params) => { this._forensicsLogs.shift(); From 318164d65c0b0838dccac5b433c25d7363083f8c Mon Sep 17 00:00:00 2001 From: Tim Taubert Date: Sun, 14 Sep 2014 16:54:41 +0200 Subject: [PATCH 29/53] Bug 1067117 - Typo in Sqlite.jsm: REASON_CANCELLED should be REASON_CANCELED r=mak --- toolkit/modules/Sqlite.jsm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/toolkit/modules/Sqlite.jsm b/toolkit/modules/Sqlite.jsm index 8177522b56e2..6a2ec123e654 100644 --- a/toolkit/modules/Sqlite.jsm +++ b/toolkit/modules/Sqlite.jsm @@ -602,7 +602,7 @@ ConnectionData.prototype = Object.freeze({ deferred.resolve(result); break; - case Ci.mozIStorageStatementCallback.REASON_CANCELLED: + case Ci.mozIStorageStatementCallback.REASON_CANCELED: // It is not an error if the user explicitly requested cancel via // the onRow handler. if (userCancelled) { From 75753e84c33f4214b213e996a3265c53216bd408 Mon Sep 17 00:00:00 2001 From: Tim Taubert Date: Mon, 8 Sep 2014 11:54:00 +0200 Subject: [PATCH 30/53] Bug 1047469 - Implement search terms hilighting r=dao --- .../test/general/browser_urlHighlight.js | 8 +++- browser/base/content/urlbarBindings.xml | 38 +++++++++++++++---- 2 files changed, 36 insertions(+), 10 deletions(-) diff --git a/browser/base/content/test/general/browser_urlHighlight.js b/browser/base/content/test/general/browser_urlHighlight.js index 3ab312738417..4308ec15de8d 100644 --- a/browser/base/content/test/general/browser_urlHighlight.js +++ b/browser/base/content/test/general/browser_urlHighlight.js @@ -19,7 +19,11 @@ function testVal(aExpected) { is(result, aExpected); } -function test() { +add_task(function* () { + return new Promise(resolve => Services.search.init(resolve)); +}); + +add_task(function* () { const prefname = "browser.urlbar.formatting.enabled"; registerCleanupFunction(function () { @@ -109,4 +113,4 @@ function test() { Services.prefs.setBoolPref(prefname, false); testVal("https://mozilla.org"); -} +}); diff --git a/browser/base/content/urlbarBindings.xml b/browser/base/content/urlbarBindings.xml index 755bd9dc054b..aaead336356a 100644 --- a/browser/base/content/urlbarBindings.xml +++ b/browser/base/content/urlbarBindings.xml @@ -174,11 +174,23 @@ true + false { + this._searchServiceInitialized = true; + this.formatValue(); + }); + + return; + } + let controller = this.editor.selectionController; let selection = controller.getSelection(controller.SELECTION_URLSECONDARY); selection.removeAllRanges(); @@ -213,20 +225,29 @@ subDomain = domain.slice(0, -baseDomain.length); } - let rangeLength = preDomain.length + subDomain.length; - if (rangeLength) { + function addSelectionRange(start, end) { let range = document.createRange(); - range.setStart(textNode, 0); - range.setEnd(textNode, rangeLength); + range.setStart(textNode, start); + range.setEnd(textNode, end); selection.addRange(range); } + let rangeLength = preDomain.length + subDomain.length; + if (rangeLength) { + addSelectionRange(0, rangeLength); + } + + let result = Services.search.parseSubmissionURL(value); let startRest = preDomain.length + domain.length; + + // Format search terms in the URL, if any. + if (result.termsOffset > -1 && result.termsLength) { + addSelectionRange(startRest, result.termsOffset); + startRest = result.termsOffset + result.termsLength; + } + if (startRest < value.length) { - let range = document.createRange(); - range.setStart(textNode, startRest); - range.setEnd(textNode, value.length); - selection.addRange(range); + addSelectionRange(startRest, value.length); } ]]> @@ -606,6 +627,7 @@ this.timeout = this._prefs.getIntPref(aData); break; case "formatting.enabled": + this._clearFormatting(); this._formattingEnabled = this._prefs.getBoolPref(aData); break; case "trimURLs": From ef31fc9a53e41f89b60994272305fc6dfa1eae80 Mon Sep 17 00:00:00 2001 From: Sotaro Ikeda Date: Mon, 15 Sep 2014 06:30:40 -0700 Subject: [PATCH 31/53] Bug 1065492 - Fix a stride when using android::ColorConverter r=nical --- gfx/layers/GrallocImages.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/gfx/layers/GrallocImages.cpp b/gfx/layers/GrallocImages.cpp index ff1375a231f4..a27fff35c4ea 100644 --- a/gfx/layers/GrallocImages.cpp +++ b/gfx/layers/GrallocImages.cpp @@ -351,9 +351,10 @@ ConvertOmxYUVFormatToRGB565(android::sp& aBuffer, return BAD_VALUE; } + uint32_t pixelStride = aMappedSurface->mStride/gfx::BytesPerPixel(gfx::SurfaceFormat::R5G6B5); rv = colorConverter.convert(buffer, width, height, 0, 0, width - 1, height - 1 /* source crop */, - aMappedSurface->mData, width, height, + aMappedSurface->mData, pixelStride, height, 0, 0, width - 1, height - 1 /* dest crop */); if (rv) { NS_WARNING("OMX color conversion failed"); From 7d25ea7c8e4b0e10cb6e175881e0e5ba8f7ff7cb Mon Sep 17 00:00:00 2001 From: Benjamin Bouvier Date: Mon, 15 Sep 2014 15:36:55 +0200 Subject: [PATCH 32/53] Bug 1062217: Try fixing winxp build; r=bustage --- js/src/asmjs/AsmJSValidate.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/js/src/asmjs/AsmJSValidate.cpp b/js/src/asmjs/AsmJSValidate.cpp index 70daa31832da..55d7734e2573 100644 --- a/js/src/asmjs/AsmJSValidate.cpp +++ b/js/src/asmjs/AsmJSValidate.cpp @@ -4744,6 +4744,8 @@ CheckMathBuiltinCall(FunctionCompiler &f, ParseNode *callNode, AsmJSMathBuiltinF typedef Vector DefinitionVector; +namespace { + template static bool CheckSimdCallArgs(FunctionCompiler &f, ParseNode *call, unsigned expectedArity, @@ -4771,8 +4773,6 @@ CheckSimdCallArgs(FunctionCompiler &f, ParseNode *call, unsigned expectedArity, return true; } -namespace { - class CheckSimdScalarArgs { Type formalType_; From db2139cc10c183b3580f82b53c2b427d00e6124b Mon Sep 17 00:00:00 2001 From: James Graham Date: Mon, 15 Sep 2014 15:13:18 +0100 Subject: [PATCH 33/53] Bug 1055533 - Fix web-platform-tests metadata for addition of Element.closest, r=bz --- testing/web-platform/meta/dom/interfaces.html.ini | 12 ------------ .../web-platform/meta/html/dom/interfaces.html.ini | 6 ------ 2 files changed, 18 deletions(-) diff --git a/testing/web-platform/meta/dom/interfaces.html.ini b/testing/web-platform/meta/dom/interfaces.html.ini index dd0a916cce9f..1936e3de709d 100644 --- a/testing/web-platform/meta/dom/interfaces.html.ini +++ b/testing/web-platform/meta/dom/interfaces.html.ini @@ -147,9 +147,6 @@ [Element interface: attribute localName] expected: FAIL - [Element interface: operation closest(DOMString)] - expected: FAIL - [Element interface: operation prepend([object Object\],[object Object\])] expected: FAIL @@ -171,12 +168,6 @@ [Element interface: operation replace([object Object\],[object Object\])] expected: FAIL - [Element interface: element must inherit property "closest" with the proper type (16)] - expected: FAIL - - [Element interface: calling closest(DOMString) on element with too few arguments must throw TypeError] - expected: FAIL - [Element interface: element must inherit property "prepend" with the proper type (25)] expected: FAIL @@ -339,9 +330,6 @@ [Element interface: operation hasAttributes()] expected: FAIL - [Element interface: element must inherit property "closest" with the proper type (22)] - expected: FAIL - [Element interface: element must inherit property "prepend" with the proper type (31)] expected: FAIL diff --git a/testing/web-platform/meta/html/dom/interfaces.html.ini b/testing/web-platform/meta/html/dom/interfaces.html.ini index b7b2567819bd..768d5c15f05d 100644 --- a/testing/web-platform/meta/html/dom/interfaces.html.ini +++ b/testing/web-platform/meta/html/dom/interfaces.html.ini @@ -714,12 +714,6 @@ [HTMLElement interface: document.createElement("noscript") must inherit property "ontoggle" with the proper type (92)] expected: FAIL - [Element interface: document.createElement("noscript") must inherit property "closest" with the proper type (22)] - expected: FAIL - - [Element interface: calling closest(DOMString) on document.createElement("noscript") with too few arguments must throw TypeError] - expected: FAIL - [Element interface: document.createElement("noscript") must inherit property "prepend" with the proper type (31)] expected: FAIL From 188b3e07cbaff6fb6167bcad9722abedc192ee40 Mon Sep 17 00:00:00 2001 From: Boris Zbarsky Date: Mon, 15 Sep 2014 11:00:25 -0400 Subject: [PATCH 34/53] Update some documentation to make it clearer. No bug, DONTBUILD --- dom/bindings/BindingUtils.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/dom/bindings/BindingUtils.h b/dom/bindings/BindingUtils.h index 7b990d8a5099..5a8a2d7e4fb8 100644 --- a/dom/bindings/BindingUtils.h +++ b/dom/bindings/BindingUtils.h @@ -842,6 +842,10 @@ MaybeWrapValue(JSContext* cx, JS::MutableHandle rval) // GetWrapperPreserveColor() which can return its existing wrapper, if any, and // a WrapObject() which will try to create a wrapper. Typically, this is done by // having "value" inherit from nsWrapperCache. +// +// The value stored in rval will be ready to be exposed to whatever JS +// is running on cx right now. In particular, it will be in the +// compartment of cx, and outerized as needed. template MOZ_ALWAYS_INLINE bool WrapNewBindingObject(JSContext* cx, T* value, JS::MutableHandle rval) From e558587ded1213e2f65a363c1b1091340427792b Mon Sep 17 00:00:00 2001 From: Ehsan Akhgari Date: Mon, 15 Sep 2014 11:03:14 -0400 Subject: [PATCH 35/53] Bug 1067404 - Do not expect a copysign function to be defined in with clang-cl; r=upstream clang-cl defines __cplusplus to 201103L, but it uses the runtime library provided by MSVC, so the copysign function will not be available there. Review URL: https://codereview.chromium.org/526813002 --- gfx/skia/trunk/include/core/SkFloatingPoint.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gfx/skia/trunk/include/core/SkFloatingPoint.h b/gfx/skia/trunk/include/core/SkFloatingPoint.h index 6e372d9519e0..6c480c3b076a 100644 --- a/gfx/skia/trunk/include/core/SkFloatingPoint.h +++ b/gfx/skia/trunk/include/core/SkFloatingPoint.h @@ -31,7 +31,7 @@ static inline float sk_float_pow(float base, float exp) { static inline float sk_float_copysign(float x, float y) { // c++11 contains a 'float copysign(float, float)' function in . -#if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1800) +#if (!defined(_MSC_VER) && __cplusplus >= 201103L) || (defined(_MSC_VER) && _MSC_VER >= 1800) return copysign(x, y); // Posix has demanded 'float copysignf(float, float)' (from C99) since Issue 6. From c6416e4f55ffac6c5f264182c9551c4b5e02ad57 Mon Sep 17 00:00:00 2001 From: Jonathan Watt Date: Mon, 15 Sep 2014 16:24:03 +0100 Subject: [PATCH 36/53] Bug 1067222 - Make the gfxPattern code much easier to understand (by giving variables meaningful names, adding comments, and integrating the mysterious AdjustTransformForPattern into gfxPattern::GetPattern). r=Bas --- gfx/thebes/gfxPattern.cpp | 81 ++++++++++++++++----------------------- gfx/thebes/gfxPattern.h | 21 ++-------- 2 files changed, 36 insertions(+), 66 deletions(-) diff --git a/gfx/thebes/gfxPattern.cpp b/gfx/thebes/gfxPattern.cpp index ba2d42afc29b..774d14e4fde0 100644 --- a/gfx/thebes/gfxPattern.cpp +++ b/gfx/thebes/gfxPattern.cpp @@ -47,12 +47,12 @@ gfxPattern::gfxPattern(gfxFloat cx0, gfxFloat cy0, gfxFloat radius0, } // Azure -gfxPattern::gfxPattern(SourceSurface *aSurface, const Matrix &aTransform) - : mTransform(aTransform) +gfxPattern::gfxPattern(SourceSurface *aSurface, const Matrix &aPatternToUserSpace) + : mPatternToUserSpace(aPatternToUserSpace) , mExtend(EXTEND_NONE) { mGfxPattern = new (mSurfacePattern.addr()) - SurfacePattern(aSurface, ToExtendMode(mExtend), aTransform, + SurfacePattern(aSurface, ToExtendMode(mExtend), Matrix(), // matrix is overridden in GetPattern() mozilla::gfx::Filter::GOOD); } @@ -100,13 +100,13 @@ gfxPattern::CacheColorStops(DrawTarget *aDT) } void -gfxPattern::SetMatrix(const gfxMatrix& matrix) +gfxPattern::SetMatrix(const gfxMatrix& aPatternToUserSpace) { - mTransform = ToMatrix(matrix); + mPatternToUserSpace = ToMatrix(aPatternToUserSpace); // Cairo-pattern matrices specify the conversion from DrawTarget to pattern // space. Azure pattern matrices specify the conversion from pattern to // DrawTarget space. - mTransform.Invert(); + mPatternToUserSpace.Invert(); } gfxMatrix @@ -114,7 +114,7 @@ gfxPattern::GetMatrix() const { // invert at the higher precision of gfxMatrix // cause we need to convert at some point anyways - gfxMatrix mat = ThebesMatrix(mTransform); + gfxMatrix mat = ThebesMatrix(mPatternToUserSpace); mat.Invert(); return mat; } @@ -122,12 +122,33 @@ gfxPattern::GetMatrix() const gfxMatrix gfxPattern::GetInverseMatrix() const { - return ThebesMatrix(mTransform); + return ThebesMatrix(mPatternToUserSpace); } Pattern* -gfxPattern::GetPattern(DrawTarget *aTarget, Matrix *aPatternTransform) +gfxPattern::GetPattern(DrawTarget *aTarget, + Matrix *aOriginalUserToDevice) { + Matrix patternToUser = mPatternToUserSpace; + + if (aOriginalUserToDevice && + *aOriginalUserToDevice != aTarget->GetTransform()) { + // mPatternToUserSpace maps from pattern space to the original user space, + // but aTarget now has a transform to a different user space. In order for + // the Pattern* that we return to be usable in aTarget's new user space we + // need the Pattern's mMatrix to be the transform from pattern space to + // aTarget's -new- user space. That transform is equivalent to the + // transform from pattern space to original user space (patternToUser), + // multiplied by the transform from original user space to device space, + // multiplied by the transform from device space to current user space. + + Matrix deviceToCurrentUser = aTarget->GetTransform(); + deviceToCurrentUser.Invert(); + + patternToUser = patternToUser * *aOriginalUserToDevice * deviceToCurrentUser; + } + patternToUser.NudgeToIntegers(); + if (!mStops && !mStopsList.IsEmpty()) { mStops = aTarget->CreateGradientStops(mStopsList.Elements(), @@ -135,18 +156,17 @@ gfxPattern::GetPattern(DrawTarget *aTarget, Matrix *aPatternTransform) ToExtendMode(mExtend)); } - Matrix* matrix = nullptr; switch (mGfxPattern->GetType()) { case PatternType::SURFACE: - matrix = &mSurfacePattern.addr()->mMatrix; + mSurfacePattern.addr()->mMatrix = patternToUser; mSurfacePattern.addr()->mExtendMode = ToExtendMode(mExtend); break; case PatternType::LINEAR_GRADIENT: - matrix = &mLinearGradientPattern.addr()->mMatrix; + mLinearGradientPattern.addr()->mMatrix = patternToUser; mLinearGradientPattern.addr()->mStops = mStops; break; case PatternType::RADIAL_GRADIENT: - matrix = &mRadialGradientPattern.addr()->mMatrix; + mRadialGradientPattern.addr()->mMatrix = patternToUser; mRadialGradientPattern.addr()->mStops = mStops; break; default: @@ -154,15 +174,6 @@ gfxPattern::GetPattern(DrawTarget *aTarget, Matrix *aPatternTransform) break; } - if (matrix) { - *matrix = mTransform; - if (aPatternTransform) { - AdjustTransformForPattern(*matrix, - aTarget->GetTransform(), - aPatternTransform); - } - } - return mGfxPattern; } @@ -233,29 +244,3 @@ gfxPattern::CairoStatus() { return CAIRO_STATUS_SUCCESS; } - -void -gfxPattern::AdjustTransformForPattern(Matrix &aPatternTransform, - const Matrix &aCurrentTransform, - const Matrix *aOriginalTransform) -{ - aPatternTransform.Invert(); - if (!aOriginalTransform) { - // User space is unchanged, so to get from pattern space to user space, - // just invert the cairo matrix. - aPatternTransform.NudgeToIntegers(); - return; - } - // aPatternTransform now maps from pattern space to the user space defined - // by *aOriginalTransform. - - Matrix mat = aCurrentTransform; - mat.Invert(); - // mat maps from device space to current user space - - // First, transform from pattern space to original user space. Then transform - // from original user space to device space. Then transform from - // device space to current user space. - aPatternTransform = aPatternTransform * *aOriginalTransform * mat; - aPatternTransform.NudgeToIntegers(); -} diff --git a/gfx/thebes/gfxPattern.h b/gfx/thebes/gfxPattern.h index af46c25fcf37..0670b4497975 100644 --- a/gfx/thebes/gfxPattern.h +++ b/gfx/thebes/gfxPattern.h @@ -32,7 +32,7 @@ public: gfxPattern(gfxFloat cx0, gfxFloat cy0, gfxFloat radius0, gfxFloat cx1, gfxFloat cy1, gfxFloat radius1); // radial gfxPattern(mozilla::gfx::SourceSurface *aSurface, - const mozilla::gfx::Matrix &aTransform); // Azure + const mozilla::gfx::Matrix &aPatternToUserSpace); void AddColorStop(gfxFloat offset, const gfxRGBA& c); void SetColorStops(mozilla::gfx::GradientStops* aStops); @@ -52,7 +52,7 @@ public: * to the current transform. */ mozilla::gfx::Pattern *GetPattern(mozilla::gfx::DrawTarget *aTarget, - mozilla::gfx::Matrix *aPatternTransform = nullptr); + mozilla::gfx::Matrix *aOriginalUserToDevice = nullptr); bool IsOpaque(); enum GraphicsExtend { @@ -97,21 +97,6 @@ private: // Private destructor, to discourage deletion outside of Release(): ~gfxPattern(); - /** - * aPatternTransform is the cairo pattern transform --- from user space at - * the time the pattern was set, to pattern space. - * aCurrentTransform is the DrawTarget's CTM --- from user space to device - * space. - * aOriginalTransform, if non-null, is the DrawTarget's TM when - * aPatternTransform was set --- user space to device space. If null, then - * the DrawTarget's CTM is the same as the TM when aPatternTransfrom was set. - * This function sets aPatternTransform to the Azure pattern transform --- - * from pattern space to current DrawTarget user space. - */ - void AdjustTransformForPattern(mozilla::gfx::Matrix &aPatternTransform, - const mozilla::gfx::Matrix &aCurrentTransform, - const mozilla::gfx::Matrix *aOriginalTransform); - union { mozilla::AlignedStorage2 mColorPattern; mozilla::AlignedStorage2 mLinearGradientPattern; @@ -122,7 +107,7 @@ private: mozilla::gfx::Pattern *mGfxPattern; mozilla::RefPtr mSourceSurface; - mozilla::gfx::Matrix mTransform; + mozilla::gfx::Matrix mPatternToUserSpace; mozilla::RefPtr mStops; nsTArray mStopsList; GraphicsExtend mExtend; From 93fa9ca8db5ad0a97467c37d52d296b1f6dd601f Mon Sep 17 00:00:00 2001 From: Jon Coppeard Date: Mon, 15 Sep 2014 16:49:11 +0100 Subject: [PATCH 37/53] Bug 1045945 - Initialize the destroy principals callback for workers r=bent --- dom/workers/Principal.cpp | 22 ++++++++++++++++++---- dom/workers/Principal.h | 3 +++ dom/workers/RuntimeService.cpp | 2 ++ js/public/Principals.h | 2 ++ 4 files changed, 25 insertions(+), 4 deletions(-) diff --git a/dom/workers/Principal.cpp b/dom/workers/Principal.cpp index dd80f9e8dd16..21b99e552ed6 100644 --- a/dom/workers/Principal.cpp +++ b/dom/workers/Principal.cpp @@ -6,23 +6,37 @@ #include "Principal.h" #include "jsapi.h" +#include "mozilla/Assertions.h" BEGIN_WORKERS_NAMESPACE JSPrincipals* GetWorkerPrincipal() { - static Atomic sInitialized(false); static JSPrincipals sPrincipal; - bool isInitialized = sInitialized.exchange(true); - if (!isInitialized) { - sPrincipal.refcount = 1; + /* + * To make sure the the principals refcount is initialized to one, atomically + * increment it on every pass though this function. If we discover this wasn't + * the first time, decrement it again. This avoids the need for + * synchronization. + */ + int32_t prevRefcount = sPrincipal.refcount++; + if (prevRefcount > 0) { + --sPrincipal.refcount; + } else { #ifdef DEBUG sPrincipal.debugToken = kJSPrincipalsDebugToken; #endif } + return &sPrincipal; } +void +DestroyWorkerPrincipals(JSPrincipals* aPrincipals) +{ + MOZ_ASSERT_UNREACHABLE("Worker principals refcount should never fall below one"); +} + END_WORKERS_NAMESPACE diff --git a/dom/workers/Principal.h b/dom/workers/Principal.h index 76e32f208f26..c5d6ca561648 100644 --- a/dom/workers/Principal.h +++ b/dom/workers/Principal.h @@ -13,6 +13,9 @@ BEGIN_WORKERS_NAMESPACE JSPrincipals* GetWorkerPrincipal(); +void +DestroyWorkerPrincipals(JSPrincipals* aPrincipals); + END_WORKERS_NAMESPACE #endif /* mozilla_dom_workers_principal_h__ */ diff --git a/dom/workers/RuntimeService.cpp b/dom/workers/RuntimeService.cpp index e2eabc7c53ee..28db57e643d0 100644 --- a/dom/workers/RuntimeService.cpp +++ b/dom/workers/RuntimeService.cpp @@ -61,6 +61,7 @@ #include "nsThreadManager.h" #endif +#include "Principal.h" #include "ServiceWorker.h" #include "SharedWorker.h" #include "WorkerPrivate.h" @@ -852,6 +853,7 @@ public: WORKER_DEFAULT_NURSERY_SIZE), mWorkerPrivate(aWorkerPrivate) { + JS_InitDestroyPrincipalsCallback(Runtime(), DestroyWorkerPrincipals); } ~WorkerJSRuntime() diff --git a/js/public/Principals.h b/js/public/Principals.h index a2baa8970089..ad7a6262dd7c 100644 --- a/js/public/Principals.h +++ b/js/public/Principals.h @@ -24,6 +24,8 @@ struct JSPrincipals { uint32_t debugToken; #endif + JSPrincipals() : refcount(0) {} + void setDebugToken(uint32_t token) { # ifdef JS_DEBUG debugToken = token; From 63feeb0f58c219cad91df514ac265751363794f5 Mon Sep 17 00:00:00 2001 From: Jon Coppeard Date: Mon, 15 Sep 2014 16:49:37 +0100 Subject: [PATCH 38/53] Bug 1063468 - Remove unnecessary use of address() r=sfink --- js/src/ctypes/CTypes.cpp | 78 ++++++++++++++++++++-------------------- js/src/jsapi.cpp | 10 +++--- js/src/jsapi.h | 2 +- js/src/jsdate.cpp | 47 +++++++++++++----------- js/src/vm/DateObject.h | 3 +- 5 files changed, 73 insertions(+), 67 deletions(-) diff --git a/js/src/ctypes/CTypes.cpp b/js/src/ctypes/CTypes.cpp index 65f1621f9b0f..9a0d0060b8dc 100644 --- a/js/src/ctypes/CTypes.cpp +++ b/js/src/ctypes/CTypes.cpp @@ -459,7 +459,7 @@ namespace CDataFinalizer { * * Note that the jsval is actually not recorded, but converted back from C. */ - static bool GetValue(JSContext *cx, JSObject *obj, jsval *result); + static bool GetValue(JSContext *cx, JSObject *obj, MutableHandleValue result); static JSObject* GetCData(JSContext *cx, JSObject *obj); } @@ -1717,7 +1717,7 @@ jsvalToInteger(JSContext* cx, jsval val, IntegerType* result) if (CDataFinalizer::IsCDataFinalizer(obj)) { RootedValue innerData(cx); - if (!CDataFinalizer::GetValue(cx, obj, innerData.address())) { + if (!CDataFinalizer::GetValue(cx, obj, &innerData)) { return false; // Nothing to convert } return jsvalToInteger(cx, innerData, result); @@ -1908,7 +1908,7 @@ jsvalToBigInteger(JSContext* cx, if (CDataFinalizer::IsCDataFinalizer(obj)) { RootedValue innerData(cx); - if (!CDataFinalizer::GetValue(cx, obj, innerData.address())) { + if (!CDataFinalizer::GetValue(cx, obj, &innerData)) { return false; // Nothing to convert } return jsvalToBigInteger(cx, innerData, allowString, result); @@ -1973,14 +1973,14 @@ jsidToSize(JSContext* cx, jsid val, bool allowString, size_t* result) // Implicitly convert a size value to a jsval, ensuring that the size_t value // fits in a double. static bool -SizeTojsval(JSContext* cx, size_t size, jsval* result) +SizeTojsval(JSContext* cx, size_t size, MutableHandleValue result) { if (Convert(double(size)) != size) { JS_ReportError(cx, "size overflow"); return false; } - *result = JS_NumberValue(double(size)); + result.setNumber(double(size)); return true; } @@ -2125,7 +2125,7 @@ ConvertToJS(JSContext* cx, void* data, bool wantPrimitive, bool ownResult, - jsval* result) + MutableHandleValue result) { JS_ASSERT(!parentObj || CData::IsCData(parentObj)); JS_ASSERT(!parentObj || !ownResult); @@ -2135,18 +2135,18 @@ ConvertToJS(JSContext* cx, switch (typeCode) { case TYPE_void_t: - *result = JSVAL_VOID; + result.setUndefined(); break; case TYPE_bool: - *result = *static_cast(data) ? JSVAL_TRUE : JSVAL_FALSE; + result.setBoolean(*static_cast(data)); break; #define DEFINE_INT_TYPE(name, type, ffiType) \ case TYPE_##name: { \ type value = *static_cast(data); \ if (sizeof(type) < 4) \ - *result = INT_TO_JSVAL(int32_t(value)); \ + result.setInt32(int32_t(value)); \ else \ - *result = JS_NumberValue(double(value)); \ + result.setDouble(double(value)); \ break; \ } #define DEFINE_WRAPPED_INT_TYPE(name, type, ffiType) \ @@ -2172,20 +2172,20 @@ ConvertToJS(JSContext* cx, !NumericLimits::is_signed); \ if (!obj) \ return false; \ - *result = OBJECT_TO_JSVAL(obj); \ + result.setObject(*obj); \ break; \ } #define DEFINE_FLOAT_TYPE(name, type, ffiType) \ case TYPE_##name: { \ type value = *static_cast(data); \ - *result = JS_NumberValue(double(value)); \ + result.setDouble(double(value)); \ break; \ } #define DEFINE_CHAR_TYPE(name, type, ffiType) \ case TYPE_##name: \ /* Convert to an integer. We have no idea what character encoding to */ \ /* use, if any. */ \ - *result = INT_TO_JSVAL(*static_cast(data)); \ + result.setInt32(*static_cast(data)); \ break; #include "ctypes/typedefs.h" case TYPE_char16_t: { @@ -2194,7 +2194,7 @@ ConvertToJS(JSContext* cx, if (!str) return false; - *result = STRING_TO_JSVAL(str); + result.setString(str); break; } case TYPE_pointer: @@ -2211,7 +2211,7 @@ ConvertToJS(JSContext* cx, if (!obj) return false; - *result = OBJECT_TO_JSVAL(obj); + result.setObject(*obj); break; } case TYPE_function: @@ -2627,7 +2627,7 @@ ImplicitConvert(JSContext* cx, RootedId id(cx); size_t i = 0; while (1) { - if (!JS_NextProperty(cx, iter, id.address())) + if (!JS_NextProperty(cx, iter, &id)) return false; if (JSID_IS_VOID(id)) break; @@ -4194,7 +4194,7 @@ PointerType::ContentsGetter(JSContext* cx, JS::CallArgs args) } RootedValue result(cx); - if (!ConvertToJS(cx, baseType, NullPtr(), data, false, false, result.address())) + if (!ConvertToJS(cx, baseType, NullPtr(), data, false, false, &result)) return false; args.rval().set(result); @@ -4290,8 +4290,8 @@ ArrayType::CreateInternal(JSContext* cx, JS_ReportError(cx, "size overflow"); return nullptr; } - if (!SizeTojsval(cx, size, sizeVal.address()) || - !SizeTojsval(cx, length, lengthVal.address())) + if (!SizeTojsval(cx, size, &sizeVal) || + !SizeTojsval(cx, length, &lengthVal)) return nullptr; } @@ -4589,7 +4589,7 @@ ArrayType::Getter(JSContext* cx, HandleObject obj, HandleId idval, MutableHandle RootedObject baseType(cx, GetBaseType(typeObj)); size_t elementSize = CType::GetSize(baseType); char* data = static_cast(CData::GetData(obj)) + elementSize * index; - return ConvertToJS(cx, baseType, obj, data, false, false, vp.address()); + return ConvertToJS(cx, baseType, obj, data, false, false, vp); } bool @@ -4686,7 +4686,7 @@ ArrayType::AddressOfElement(JSContext* cx, unsigned argc, jsval* vp) // For a struct field descriptor 'val' of the form { name : type }, extract // 'name' and 'type'. static JSFlatString* -ExtractStructField(JSContext* cx, jsval val, JSObject** typeObj) +ExtractStructField(JSContext* cx, jsval val, MutableHandleObject typeObj) { if (val.isPrimitive()) { JS_ReportError(cx, "struct field descriptors require a valid name and type"); @@ -4699,7 +4699,7 @@ ExtractStructField(JSContext* cx, jsval val, JSObject** typeObj) return nullptr; RootedId nameid(cx); - if (!JS_NextProperty(cx, iter, nameid.address())) + if (!JS_NextProperty(cx, iter, &nameid)) return nullptr; if (JSID_IS_VOID(nameid)) { JS_ReportError(cx, "struct field descriptors require a valid name and type"); @@ -4712,7 +4712,7 @@ ExtractStructField(JSContext* cx, jsval val, JSObject** typeObj) } // make sure we have one, and only one, property - jsid id; + RootedId id(cx); if (!JS_NextProperty(cx, iter, &id)) return nullptr; if (!JSID_IS_VOID(id)) { @@ -4732,9 +4732,9 @@ ExtractStructField(JSContext* cx, jsval val, JSObject** typeObj) // Undefined size or zero size struct members are illegal. // (Zero-size arrays are legal as struct members in C++, but libffi will // choke on a zero-size struct, so we disallow them.) - *typeObj = &propVal.toObject(); + typeObj.set(&propVal.toObject()); size_t size; - if (!CType::GetSafeSize(*typeObj, &size) || size == 0) { + if (!CType::GetSafeSize(typeObj, &size) || size == 0) { JS_ReportError(cx, "struct field types must have defined and nonzero size"); return nullptr; } @@ -4746,7 +4746,7 @@ ExtractStructField(JSContext* cx, jsval val, JSObject** typeObj) // { name : type }. static bool AddFieldToArray(JSContext* cx, - jsval* element, + MutableHandleValue element, JSFlatString* name_, JSObject* typeObj_) { @@ -4756,7 +4756,7 @@ AddFieldToArray(JSContext* cx, if (!fieldObj) return false; - *element = OBJECT_TO_JSVAL(fieldObj); + element.setObject(*fieldObj); AutoStableStringChars nameChars(cx); if (!nameChars.initTwoByte(cx, name)) @@ -4882,7 +4882,7 @@ StructType::DefineInternal(JSContext* cx, JSObject* typeObj_, JSObject* fieldsOb return false; RootedObject fieldType(cx, nullptr); - Rooted name(cx, ExtractStructField(cx, item, fieldType.address())); + Rooted name(cx, ExtractStructField(cx, item, &fieldType)); if (!name) return false; fieldRoots[i].setObject(*fieldType); @@ -4948,7 +4948,7 @@ StructType::DefineInternal(JSContext* cx, JSObject* typeObj_, JSObject* fieldsOb } RootedValue sizeVal(cx); - if (!SizeTojsval(cx, structSize, sizeVal.address())) + if (!SizeTojsval(cx, structSize, &sizeVal)) return false; JS_SetReservedSlot(typeObj, SLOT_FIELDINFO, PRIVATE_TO_JSVAL(fields.forget())); @@ -5197,7 +5197,7 @@ StructType::BuildFieldsArray(JSContext* cx, JSObject* obj) for (FieldInfoHash::Range r = fields->all(); !r.empty(); r.popFront()) { const FieldInfoHash::Entry& entry = r.front(); // Add the field descriptor to the array. - if (!AddFieldToArray(cx, fieldsVec[entry.value().mIndex].address(), + if (!AddFieldToArray(cx, fieldsVec[entry.value().mIndex], entry.key(), entry.value().mType)) return nullptr; } @@ -5269,7 +5269,7 @@ StructType::FieldGetter(JSContext* cx, HandleObject obj, HandleId idval, Mutable char* data = static_cast(CData::GetData(obj)) + field->mOffset; RootedObject fieldType(cx, field->mType); - return ConvertToJS(cx, fieldType, obj, data, false, false, vp.address()); + return ConvertToJS(cx, fieldType, obj, data, false, false, vp); } bool @@ -5962,7 +5962,7 @@ FunctionType::Call(JSContext* cx, // prepare a JS object from the result RootedObject returnType(cx, fninfo->mReturnType); - return ConvertToJS(cx, returnType, NullPtr(), returnValue.mData, false, true, vp); + return ConvertToJS(cx, returnType, NullPtr(), returnValue.mData, false, true, args.rval()); } FunctionInfo* @@ -6242,7 +6242,7 @@ CClosure::ClosureStub(ffi_cif* cif, void* result, void** args, void* userData) // Convert each argument, and have any CData objects created depend on // the existing buffers. RootedObject argType(cx, fninfo->mArgTypes[i]); - if (!ConvertToJS(cx, argType, NullPtr(), args[i], false, false, argv[i].address())) + if (!ConvertToJS(cx, argType, NullPtr(), args[i], false, false, argv[i])) return; } @@ -6478,7 +6478,7 @@ CData::ValueGetter(JSContext* cx, JS::CallArgs args) // Convert the value to a primitive; do not create a new CData object. RootedObject ctype(cx, GetCType(obj)); - return ConvertToJS(cx, ctype, NullPtr(), GetData(obj), true, false, args.rval().address()); + return ConvertToJS(cx, ctype, NullPtr(), GetData(obj), true, false, args.rval()); } bool @@ -6844,7 +6844,7 @@ CDataFinalizer::Methods::ToString(JSContext *cx, unsigned argc, jsval *vp) if (!strMessage) { return false; } - } else if (!CDataFinalizer::GetValue(cx, objThis, value.address())) { + } else if (!CDataFinalizer::GetValue(cx, objThis, &value)) { MOZ_CRASH("Could not convert an empty CDataFinalizer"); } else { strMessage = ToString(cx, value); @@ -6892,7 +6892,7 @@ CDataFinalizer::GetCData(JSContext *cx, JSObject *obj) return nullptr; } RootedValue val(cx); - if (!CDataFinalizer::GetValue(cx, obj, val.address()) || val.isPrimitive()) { + if (!CDataFinalizer::GetValue(cx, obj, &val) || val.isPrimitive()) { JS_ReportError(cx, "Empty CDataFinalizer"); return nullptr; } @@ -6900,7 +6900,7 @@ CDataFinalizer::GetCData(JSContext *cx, JSObject *obj) } bool -CDataFinalizer::GetValue(JSContext *cx, JSObject *obj, jsval *aResult) +CDataFinalizer::GetValue(JSContext *cx, JSObject *obj, MutableHandleValue aResult) { MOZ_ASSERT(IsCDataFinalizer(obj)); @@ -7184,7 +7184,7 @@ CDataFinalizer::Methods::Forget(JSContext* cx, unsigned argc, jsval *vp) RootedValue valJSData(cx); RootedObject ctype(cx, GetCType(cx, obj)); - if (!ConvertToJS(cx, ctype, NullPtr(), p->cargs, false, true, valJSData.address())) { + if (!ConvertToJS(cx, ctype, NullPtr(), p->cargs, false, true, &valJSData)) { JS_ReportError(cx, "CDataFinalizer value cannot be represented"); return false; } @@ -7261,7 +7261,7 @@ CDataFinalizer::Methods::Dispose(JSContext* cx, unsigned argc, jsval *vp) JS_SetReservedSlot(objCTypes, SLOT_LASTERROR, INT_TO_JSVAL(lastErrorStatus)); #endif // defined(XP_WIN) - if (ConvertToJS(cx, resultType, NullPtr(), p->rvalue, false, true, result.address())) { + if (ConvertToJS(cx, resultType, NullPtr(), p->rvalue, false, true, &result)) { CDataFinalizer::Cleanup(p, obj); args.rval().set(result); return true; diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp index fa0fabc18b97..f394e73cf049 100644 --- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -3724,7 +3724,7 @@ JS_NewPropertyIterator(JSContext *cx, HandleObject obj) } JS_PUBLIC_API(bool) -JS_NextProperty(JSContext *cx, HandleObject iterobj, jsid *idp) +JS_NextProperty(JSContext *cx, HandleObject iterobj, MutableHandleId idp) { AssertHeapIsIdle(cx); CHECK_REQUEST(cx); @@ -3740,10 +3740,10 @@ JS_NextProperty(JSContext *cx, HandleObject iterobj, jsid *idp) if (!shape->previous()) { JS_ASSERT(shape->isEmptyShape()); - *idp = JSID_VOID; + idp.set(JSID_VOID); } else { iterobj->setPrivateGCThing(const_cast(shape->previous().get())); - *idp = shape->propid(); + idp.set(shape->propid()); } } else { /* Non-native case: use the ida enumerated when iterobj was created. */ @@ -3751,9 +3751,9 @@ JS_NextProperty(JSContext *cx, HandleObject iterobj, jsid *idp) JS_ASSERT(i <= ida->length); STATIC_ASSUME(i <= ida->length); if (i == 0) { - *idp = JSID_VOID; + idp.set(JSID_VOID); } else { - *idp = ida->vector[--i]; + idp.set(ida->vector[--i]); iterobj->setSlot(JSSLOT_ITER_INDEX, Int32Value(i)); } } diff --git a/js/src/jsapi.h b/js/src/jsapi.h index 33d32320d675..1d845c945c81 100644 --- a/js/src/jsapi.h +++ b/js/src/jsapi.h @@ -3291,7 +3291,7 @@ JS_NewPropertyIterator(JSContext *cx, JS::Handle obj); * left to visit. Return false on error. */ extern JS_PUBLIC_API(bool) -JS_NextProperty(JSContext *cx, JS::Handle iterobj, jsid *idp); +JS_NextProperty(JSContext *cx, JS::HandleObject iterobj, JS::MutableHandleId idp); extern JS_PUBLIC_API(jsval) JS_GetReservedSlot(JSObject *obj, uint32_t index); diff --git a/js/src/jsdate.cpp b/js/src/jsdate.cpp index b5accdf4c69b..cddc4a33df1c 100644 --- a/js/src/jsdate.cpp +++ b/js/src/jsdate.cpp @@ -1204,14 +1204,19 @@ date_now(JSContext *cx, unsigned argc, Value *vp) } void -DateObject::setUTCTime(double t, Value *vp) +DateObject::setUTCTime(double t) { for (size_t ind = COMPONENTS_START_SLOT; ind < RESERVED_SLOTS; ind++) setReservedSlot(ind, UndefinedValue()); setFixedSlot(UTC_TIME_SLOT, DoubleValue(t)); - if (vp) - vp->setDouble(t); +} + +void +DateObject::setUTCTime(double t, MutableHandleValue vp) +{ + setUTCTime(t); + vp.setDouble(t); } void @@ -1674,7 +1679,7 @@ date_setTime_impl(JSContext *cx, CallArgs args) { Rooted dateObj(cx, &args.thisv().toObject().as()); if (args.length() == 0) { - dateObj->setUTCTime(GenericNaN(), args.rval().address()); + dateObj->setUTCTime(GenericNaN(), args.rval()); return true; } @@ -1682,7 +1687,7 @@ date_setTime_impl(JSContext *cx, CallArgs args) if (!ToNumber(cx, args[0], &result)) return false; - dateObj->setUTCTime(TimeClip(result), args.rval().address()); + dateObj->setUTCTime(TimeClip(result), args.rval()); return true; } @@ -1742,7 +1747,7 @@ date_setMilliseconds_impl(JSContext *cx, CallArgs args) double u = TimeClip(UTC(MakeDate(Day(t), time), &cx->runtime()->dateTimeInfo)); /* Steps 4-5. */ - dateObj->setUTCTime(u, args.rval().address()); + dateObj->setUTCTime(u, args.rval()); return true; } @@ -1772,7 +1777,7 @@ date_setUTCMilliseconds_impl(JSContext *cx, CallArgs args) double v = TimeClip(MakeDate(Day(t), time)); /* Steps 4-5. */ - dateObj->setUTCTime(v, args.rval().address()); + dateObj->setUTCTime(v, args.rval()); return true; } @@ -1809,7 +1814,7 @@ date_setSeconds_impl(JSContext *cx, CallArgs args) double u = TimeClip(UTC(date, &cx->runtime()->dateTimeInfo)); /* Steps 6-7. */ - dateObj->setUTCTime(u, args.rval().address()); + dateObj->setUTCTime(u, args.rval()); return true; } @@ -1846,7 +1851,7 @@ date_setUTCSeconds_impl(JSContext *cx, CallArgs args) double v = TimeClip(date); /* Steps 6-7. */ - dateObj->setUTCTime(v, args.rval().address()); + dateObj->setUTCTime(v, args.rval()); return true; } @@ -1888,7 +1893,7 @@ date_setMinutes_impl(JSContext *cx, CallArgs args) double u = TimeClip(UTC(date, &cx->runtime()->dateTimeInfo)); /* Steps 7-8. */ - dateObj->setUTCTime(u, args.rval().address()); + dateObj->setUTCTime(u, args.rval()); return true; } @@ -1930,7 +1935,7 @@ date_setUTCMinutes_impl(JSContext *cx, CallArgs args) double v = TimeClip(date); /* Steps 7-8. */ - dateObj->setUTCTime(v, args.rval().address()); + dateObj->setUTCTime(v, args.rval()); return true; } @@ -1977,7 +1982,7 @@ date_setHours_impl(JSContext *cx, CallArgs args) double u = TimeClip(UTC(date, &cx->runtime()->dateTimeInfo)); /* Steps 7-8. */ - dateObj->setUTCTime(u, args.rval().address()); + dateObj->setUTCTime(u, args.rval()); return true; } @@ -2024,7 +2029,7 @@ date_setUTCHours_impl(JSContext *cx, CallArgs args) double v = TimeClip(newDate); /* Steps 8-9. */ - dateObj->setUTCTime(v, args.rval().address()); + dateObj->setUTCTime(v, args.rval()); return true; } @@ -2056,7 +2061,7 @@ date_setDate_impl(JSContext *cx, CallArgs args) double u = TimeClip(UTC(newDate, &cx->runtime()->dateTimeInfo)); /* Steps 5-6. */ - dateObj->setUTCTime(u, args.rval().address()); + dateObj->setUTCTime(u, args.rval()); return true; } @@ -2088,7 +2093,7 @@ date_setUTCDate_impl(JSContext *cx, CallArgs args) double v = TimeClip(newDate); /* Steps 5-6. */ - dateObj->setUTCTime(v, args.rval().address()); + dateObj->setUTCTime(v, args.rval()); return true; } @@ -2145,7 +2150,7 @@ date_setMonth_impl(JSContext *cx, CallArgs args) double u = TimeClip(UTC(newDate, &cx->runtime()->dateTimeInfo)); /* Steps 6-7. */ - dateObj->setUTCTime(u, args.rval().address()); + dateObj->setUTCTime(u, args.rval()); return true; } @@ -2182,7 +2187,7 @@ date_setUTCMonth_impl(JSContext *cx, CallArgs args) double v = TimeClip(newDate); /* Steps 6-7. */ - dateObj->setUTCTime(v, args.rval().address()); + dateObj->setUTCTime(v, args.rval()); return true; } @@ -2240,7 +2245,7 @@ date_setFullYear_impl(JSContext *cx, CallArgs args) double u = TimeClip(UTC(newDate, &cx->runtime()->dateTimeInfo)); /* Steps 7-8. */ - dateObj->setUTCTime(u, args.rval().address()); + dateObj->setUTCTime(u, args.rval()); return true; } @@ -2282,7 +2287,7 @@ date_setUTCFullYear_impl(JSContext *cx, CallArgs args) double v = TimeClip(newDate); /* Steps 7-8. */ - dateObj->setUTCTime(v, args.rval().address()); + dateObj->setUTCTime(v, args.rval()); return true; } @@ -2309,7 +2314,7 @@ date_setYear_impl(JSContext *cx, CallArgs args) /* Step 3. */ if (IsNaN(y)) { - dateObj->setUTCTime(GenericNaN(), args.rval().address()); + dateObj->setUTCTime(GenericNaN(), args.rval()); return true; } @@ -2325,7 +2330,7 @@ date_setYear_impl(JSContext *cx, CallArgs args) double u = UTC(MakeDate(day, TimeWithinDay(t)), &cx->runtime()->dateTimeInfo); /* Steps 7-8. */ - dateObj->setUTCTime(TimeClip(u), args.rval().address()); + dateObj->setUTCTime(TimeClip(u), args.rval()); return true; } diff --git a/js/src/vm/DateObject.h b/js/src/vm/DateObject.h index ae2db617e0eb..a9d5cadb669c 100644 --- a/js/src/vm/DateObject.h +++ b/js/src/vm/DateObject.h @@ -46,7 +46,8 @@ class DateObject : public JSObject } // Set UTC time to a given time and invalidate cached local time. - void setUTCTime(double t, Value *vp = nullptr); + void setUTCTime(double t); + void setUTCTime(double t, MutableHandleValue vp); inline double cachedLocalTime(DateTimeInfo *dtInfo); From 7b32611a01b96f8d9a775290c5ff66108177e692 Mon Sep 17 00:00:00 2001 From: Jonathan Kew Date: Mon, 15 Sep 2014 17:19:24 +0100 Subject: [PATCH 39/53] Bug 1066756 - Include characters with Unicode category Sk (modifier symbol) in double-click word selection. r=mats --- intl/unicharutil/util/nsUnicodeProperties.cpp | 2 +- layout/generic/nsTextFrame.cpp | 24 +++++++++++-- .../generic/test/test_movement_by_words.html | 34 +++++++++++++++++-- 3 files changed, 54 insertions(+), 6 deletions(-) diff --git a/intl/unicharutil/util/nsUnicodeProperties.cpp b/intl/unicharutil/util/nsUnicodeProperties.cpp index e8d5d1b80290..39c12221410b 100644 --- a/intl/unicharutil/util/nsUnicodeProperties.cpp +++ b/intl/unicharutil/util/nsUnicodeProperties.cpp @@ -90,7 +90,7 @@ of values. nsIUGenCategory::nsUGenCategory sDetailedToGeneralCategory[] = { /* * The order here corresponds to the HB_UNICODE_GENERAL_CATEGORY_* constants - * of the hb_unicode_general_category_t enum in gfx/harfbuzz/src/hb-common.h. + * of the hb_unicode_general_category_t enum in gfx/harfbuzz/src/hb-unicode.h. */ /* CONTROL */ nsIUGenCategory::kOther, /* FORMAT */ nsIUGenCategory::kOther, diff --git a/layout/generic/nsTextFrame.cpp b/layout/generic/nsTextFrame.cpp index 9e8e2f89aeb3..8577c5b4fee9 100644 --- a/layout/generic/nsTextFrame.cpp +++ b/layout/generic/nsTextFrame.cpp @@ -6726,9 +6726,27 @@ bool ClusterIterator::IsPunctuation() { NS_ASSERTION(mCharIndex >= 0, "No cluster selected"); - nsIUGenCategory::nsUGenCategory c = - mozilla::unicode::GetGenCategory(mFrag->CharAt(mCharIndex)); - return c == nsIUGenCategory::kPunctuation || c == nsIUGenCategory::kSymbol; + // Return true for all Punctuation categories (Unicode general category P?), + // and also for Symbol categories (S?) except for Modifier Symbol, which is + // kept together with any adjacent letter/number. (Bug 1066756) + uint8_t cat = unicode::GetGeneralCategory(mFrag->CharAt(mCharIndex)); + switch (cat) { + case HB_UNICODE_GENERAL_CATEGORY_CONNECT_PUNCTUATION: /* Pc */ + case HB_UNICODE_GENERAL_CATEGORY_DASH_PUNCTUATION: /* Pd */ + case HB_UNICODE_GENERAL_CATEGORY_CLOSE_PUNCTUATION: /* Pe */ + case HB_UNICODE_GENERAL_CATEGORY_FINAL_PUNCTUATION: /* Pf */ + case HB_UNICODE_GENERAL_CATEGORY_INITIAL_PUNCTUATION: /* Pi */ + case HB_UNICODE_GENERAL_CATEGORY_OTHER_PUNCTUATION: /* Po */ + case HB_UNICODE_GENERAL_CATEGORY_OPEN_PUNCTUATION: /* Ps */ + case HB_UNICODE_GENERAL_CATEGORY_CURRENCY_SYMBOL: /* Sc */ + // Deliberately omitted: + // case HB_UNICODE_GENERAL_CATEGORY_MODIFIER_SYMBOL: /* Sk */ + case HB_UNICODE_GENERAL_CATEGORY_MATH_SYMBOL: /* Sm */ + case HB_UNICODE_GENERAL_CATEGORY_OTHER_SYMBOL: /* So */ + return true; + default: + return false; + } } int32_t diff --git a/layout/generic/test/test_movement_by_words.html b/layout/generic/test/test_movement_by_words.html index 8f5402b5d501..fae98e5678c2 100644 --- a/layout/generic/test/test_movement_by_words.html +++ b/layout/generic/test/test_movement_by_words.html @@ -14,7 +14,7 @@

Catch-all