Merge mozilla-central and inbound

This commit is contained in:
Ed Morley 2013-06-26 15:13:20 +01:00
Родитель 61b84edea9 f5ddb637cd
Коммит 5a944e0ca0
63 изменённых файлов: 850 добавлений и 282 удалений

Просмотреть файл

@ -355,6 +355,9 @@ DocManager::RemoveListeners(nsIDocument* aDocument)
return;
EventTarget* target = window->GetChromeEventHandler();
if (!target)
return;
nsEventListenerManager* elm = target->GetListenerManager(true);
elm->RemoveEventListenerByType(this, NS_LITERAL_STRING("pagehide"),
dom::TrustedEventsAtCapture());

Просмотреть файл

@ -3,15 +3,15 @@
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
const kPrefNotifyMissingFlash = "plugins.notifyMissingFlash";
const kPrefSessionPersistMinutes = "plugin.sessionPermissionNow.intervalInMinutes";
const kPrefPersistentDays = "plugin.persistentPermissionAlways.intervalInDays";
var gPluginHandler = {
PLUGIN_SCRIPTED_STATE_NONE: 0,
PLUGIN_SCRIPTED_STATE_FIRED: 1,
PLUGIN_SCRIPTED_STATE_DONE: 2,
PREF_NOTIFY_MISSING_FLASH: "plugins.notifyMissingFlash",
PREF_SESSION_PERSIST_MINUTES: "plugin.sessionPermissionNow.intervalInMinutes",
PREF_PERSISTENT_DAYS: "plugin.persistentPermissionAlways.intervalInDays",
getPluginUI: function (plugin, className) {
return plugin.ownerDocument.
getAnonymousElementByAttribute(plugin, "class", className);
@ -468,13 +468,14 @@ var gPluginHandler = {
let secondaryActions = null;
let options = { dismissed: true };
let showForFlash = Services.prefs.getBoolPref(kPrefNotifyMissingFlash);
let showForFlash = Services.prefs.getBoolPref(this.PREF_NOTIFY_MISSING_FLASH);
if (pluginIdentifier == "flash" && showForFlash) {
let prefNotifyMissingFlash = this.PREF_NOTIFY_MISSING_FLASH;
secondaryActions = [{
label: gNavigatorBundle.getString("installPlugin.ignoreButton.label"),
accessKey: gNavigatorBundle.getString("installPlugin.ignoreButton.accesskey"),
callback: function () {
Services.prefs.setBoolPref(kPrefNotifyMissingFlash, false);
Services.prefs.setBoolPref(prefNotifyMissingFlash, false);
}
}];
options.dismissed = false;
@ -690,7 +691,7 @@ var gPluginHandler = {
}
permission = Ci.nsIPermissionManager.ALLOW_ACTION;
expireType = Ci.nsIPermissionManager.EXPIRE_SESSION;
expireTime = Date.now() + Services.prefs.getIntPref(kPrefSessionPersistMinutes) * 60 * 1000;
expireTime = Date.now() + Services.prefs.getIntPref(this.PREF_SESSION_PERSIST_MINUTES) * 60 * 1000;
break;
case "allowalways":
@ -700,7 +701,7 @@ var gPluginHandler = {
permission = Ci.nsIPermissionManager.ALLOW_ACTION;
expireType = Ci.nsIPermissionManager.EXPIRE_TIME;
expireTime = Date.now() +
Services.prefs.getIntPref(kPrefPersistentDays) * 24 * 60 * 60 * 1000;
Services.prefs.getIntPref(this.PREF_PERSISTENT_DAYS) * 24 * 60 * 60 * 1000;
break;
case "block":

Просмотреть файл

@ -1522,7 +1522,7 @@
class="click-to-play-plugins-notification-button-container"
pack="center" align="center">
<xul:button anonid="primarybutton"
class="click-to-play-popup-button primary-button"
class="click-to-play-popup-button"
oncommand="document.getBindingParent(this)._onButton(this)"
flex="1"/>
<xul:button anonid="secondarybutton"

Просмотреть файл

@ -1189,7 +1189,7 @@ FilterView.prototype = {
_doSearch: function(aOperator = "") {
this._searchbox.focus();
this._searchbox.value = ""; // Need to clear value beforehand. Bug 779738.
this._searchbox.value = aOperator;
this._searchbox.value = aOperator + DebuggerView.getEditorSelectionText();
},
/**

Просмотреть файл

@ -16,7 +16,7 @@ var gSearchBox = null;
function test()
{
requestLongerTimeout(2);
requestLongerTimeout(3);
debug_tab_pane(STACK_URL, function(aTab, aDebuggee, aPane) {
gTab = aTab;
@ -269,6 +269,12 @@ function testScriptSearching() {
isnot(gSources.widget.getAttribute("label"), noMatchingSources,
"The scripts container should not display a notice that matches are found.");
gEditor.setSelection(1, 5);
EventUtils.synthesizeKey("F", { accelKey:true });
is(gSearchBox.value, "#" + gEditor.getSelectedText(),
"The search field has the right initial value.");
closeDebuggerAndFinish();
}}, 0);
}

Просмотреть файл

@ -409,7 +409,9 @@ gTests.push({
////////////////////////////////////////////////////////////
// Context menu options
/*
XXX disabled temporarily due to bug 880739
// image01 - 1x1x100x100
let promise = waitForEvent(document, "popupshown");
sendContextMenuClickToWindow(win, 10, 10);
@ -456,7 +458,7 @@ gTests.push({
purgeEventQueue();
ok(saveLocationPath.exists(), "image saved");
*/
////////////////////////////////////////////////////////////
// Copy image
@ -465,10 +467,10 @@ gTests.push({
yield promise;
ok(ContextMenuUI._menuPopup._visible, "is visible");
menuItem = document.getElementById("context-copy-image");
let menuItem = document.getElementById("context-copy-image");
ok(menuItem, "menu item exists");
ok(!menuItem.hidden, "menu item visible");
popupPromise = waitForEvent(document, "popuphidden");
let popupPromise = waitForEvent(document, "popuphidden");
EventUtils.synthesizeMouse(menuItem, 10, 10, {}, win);
yield popupPromise;

Просмотреть файл

@ -17,6 +17,9 @@ endif
_MOZBUILD_EXTERNAL_VARIABLES := \
DIRS \
EXTRA_PP_COMPONENTS \
GTEST_CMMSRCS \
GTEST_CPPSRCS \
GTEST_CSRCS \
HOST_CSRCS \
HOST_LIBRARY_NAME \
MODULE \

Просмотреть файл

@ -45,6 +45,7 @@ MOCHITEST_FILES = \
test_hasFeature.xhtml \
$(filter disabled-for-intermittent-failures--bug-701060, test_lang.xhtml) \
test_nonAnimStrings.xhtml \
test_non-scaling-stroke.html \
test_pathAnimInterpolation.xhtml \
test_pathSeg.xhtml \
test_pointAtLength.xhtml \

Просмотреть файл

@ -0,0 +1,53 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=829085
-->
<head>
<title>Test for Bug 829085 - non-scaling-stroke hit testing</title>
<meta charset="utf-8"></meta>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=829085">Mozilla Bug 829085 - non-scaling-stroke hit testing</a>
<p id="display"></p>
<div id="content">
<svg id="svg" xmlns="http://www.w3.org/2000/svg" width="300" height="250">
<rect width="100%" height="100%" fill="none" stroke-width="4" stroke="blue"/>
<style>
line:hover { stroke: lime; }
</style>
<g transform="scale(1.3) translate(100, -80) rotate(45)">
<line id="line" stroke="teal" stroke-width="120px"
x1="50" y1="130" x2="200" y2="130"
vector-effect="non-scaling-stroke"></line>
</g>
</svg>
</div>
<pre id="test">
<script type="application/javascript">
function startTest() {
SimpleTest.waitForFocus(function() {
disableNonTestMouseEvents(true);
var line = document.getElementById('line');
// Send a click
synthesizeMouseExpectEvent($("svg"), 170, 100, { },
$("line"), "click",
"Testing mouse event on non-scaling-stroke");
disableNonTestMouseEvents(false);
SimpleTest.finish();
});
}
SimpleTest.waitForExplicitFinish();
addLoadEvent(startTest);
</script>
</pre>
</body>
</html>

Просмотреть файл

@ -61,8 +61,6 @@ function run_test()
// Needed to properly setup and shutdown the profile.
do_get_profile();
Services.prefs.setBoolPref("places.history.enabled", true);
for (var i = 0; i < tests.length; i++)
tests[i]();

Просмотреть файл

@ -108,6 +108,17 @@ Future::PrefEnabled()
return Preferences::GetBool("dom.future.enabled", false);
}
static void
EnterCompartment(Maybe<JSAutoCompartment>& aAc, JSContext* aCx,
const Optional<JS::Handle<JS::Value> >& aValue)
{
// FIXME Bug 878849
if (aValue.WasPassed() && aValue.Value().isObject()) {
JS::Rooted<JSObject*> rooted(aCx, &aValue.Value().toObject());
aAc.construct(aCx, rooted);
}
}
/* static */ already_AddRefed<Future>
Future::Constructor(const GlobalObject& aGlobal, JSContext* aCx,
FutureInit& aInit, ErrorResult& aRv)
@ -129,6 +140,9 @@ Future::Constructor(const GlobalObject& aGlobal, JSContext* aCx,
if (aRv.IsJSException()) {
Optional<JS::Handle<JS::Value> > value(aCx);
aRv.StealJSException(aCx, &value.Value());
Maybe<JSAutoCompartment> ac;
EnterCompartment(ac, aCx, value);
future->mResolver->Reject(aCx, value);
}

Просмотреть файл

@ -34,6 +34,17 @@ FutureCallback::~FutureCallback()
MOZ_COUNT_DTOR(FutureCallback);
}
static void
EnterCompartment(Maybe<JSAutoCompartment>& aAc, JSContext* aCx,
const Optional<JS::Handle<JS::Value> >& aValue)
{
// FIXME Bug 878849
if (aValue.WasPassed() && aValue.Value().isObject()) {
JS::Rooted<JSObject*> rooted(aCx, &aValue.Value().toObject());
aAc.construct(aCx, rooted);
}
}
// ResolveFutureCallback
NS_IMPL_CYCLE_COLLECTION_INHERITED_1(ResolveFutureCallback,
@ -63,12 +74,8 @@ ResolveFutureCallback::Call(const Optional<JS::Handle<JS::Value> >& aValue)
{
// Run resolver's algorithm with value and the synchronous flag set.
AutoJSContext cx;
// FIXME Bug 878849
Maybe<JSAutoCompartment> ac;
if (aValue.WasPassed() && aValue.Value().isObject()) {
JS::Rooted<JSObject*> rooted(cx, &aValue.Value().toObject());
ac.construct(cx, rooted);
}
EnterCompartment(ac, cx, aValue);
mResolver->ResolveInternal(cx, aValue, FutureResolver::SyncTask);
}
@ -102,12 +109,8 @@ RejectFutureCallback::Call(const Optional<JS::Handle<JS::Value> >& aValue)
{
// Run resolver's algorithm with value and the synchronous flag set.
AutoJSContext cx;
// FIXME Bug 878849
Maybe<JSAutoCompartment> ac;
if (aValue.WasPassed() && aValue.Value().isObject()) {
JS::Rooted<JSObject*> rooted(cx, &aValue.Value().toObject());
ac.construct(cx, rooted);
}
EnterCompartment(ac, cx, aValue);
mResolver->RejectInternal(cx, aValue, FutureResolver::SyncTask);
}
@ -142,12 +145,8 @@ void
WrapperFutureCallback::Call(const Optional<JS::Handle<JS::Value> >& aValue)
{
AutoJSContext cx;
// FIXME Bug 878849
Maybe<JSAutoCompartment> ac;
if (aValue.WasPassed() && aValue.Value().isObject()) {
JS::Rooted<JSObject*> rooted(cx, &aValue.Value().toObject());
ac.construct(cx, rooted);
}
EnterCompartment(ac, cx, aValue);
ErrorResult rv;
@ -162,12 +161,17 @@ WrapperFutureCallback::Call(const Optional<JS::Handle<JS::Value> >& aValue)
if (rv.Failed() && rv.IsJSException()) {
Optional<JS::Handle<JS::Value> > value(cx);
rv.StealJSException(cx, &value.Value());
Maybe<JSAutoCompartment> ac2;
EnterCompartment(ac2, cx, value);
mNextResolver->RejectInternal(cx, value, FutureResolver::SyncTask);
return;
}
// Otherwise, run resolver's resolve with value and the synchronous flag
// set.
Maybe<JSAutoCompartment> ac2;
EnterCompartment(ac2, cx, value);
mNextResolver->ResolveInternal(cx, value, FutureResolver::SyncTask);
}

Просмотреть файл

@ -14,6 +14,7 @@ include $(DEPTH)/config/autoconf.mk
MOCHITEST_FILES = \
test_future.html \
test_resolve.html \
test_bug883683.html \
$(NULL)
include $(topsrcdir)/config/rules.mk

Просмотреть файл

@ -0,0 +1,41 @@
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/
-->
<html>
<head>
<title>Future - bug 883683</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
<script type="application/javascript"><!--
function runTest() {
[{}, {}, {}, {}, {}].reduce(Future.reject);
ok(true, "No leaks with reject?");
[{}, {}, {}, {}, {}].reduce(Future.resolve);
ok(true, "No leaks with resolve?");
[{}, {}, {}, {}, {}].reduce(function(a, b, c, d) { return new Future(function(r) { throw a; }); });
ok(true, "No leaks with exception?");
[{}, {}, {}, {}, {}].reduce(function(a, b, c, d) { return new Future(function(r) { }); });
ok(true, "No leaks with empty future?");
SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPrefEnv({"set": [["dom.future.enabled", true]]}, runTest);
// -->
</script>
</pre>
</body>
</html>

Просмотреть файл

@ -350,8 +350,7 @@ TabChild::Observe(nsISupports *aSubject,
mLastMetrics.mZoom = ScreenToScreenScale(1.0);
mLastMetrics.mViewport = CSSRect(CSSPoint(), kDefaultViewportSize);
mLastMetrics.mCompositionBounds = ScreenIntRect(ScreenIntPoint(), mInnerSize);
CSSToScreenScale resolution =
AsyncPanZoomController::CalculateResolution(mLastMetrics);
CSSToScreenScale resolution = mLastMetrics.CalculateResolution();
// We use ScreenToLayerScale(1) below in order to ask gecko to render
// what's currently visible on the screen. This is effectively turning
// the async zoom amount into the gecko zoom amount.
@ -602,8 +601,7 @@ TabChild::HandlePossibleViewportChange()
nsresult rv = utils->GetIsFirstPaint(&isFirstPaint);
MOZ_ASSERT(NS_SUCCEEDED(rv));
if (NS_FAILED(rv) || isFirstPaint) {
CSSToScreenScale intrinsicScale =
AsyncPanZoomController::CalculateIntrinsicScale(metrics);
CSSToScreenScale intrinsicScale = metrics.CalculateIntrinsicScale();
// FIXME/bug 799585(?): GetViewportInfo() returns a defaultZoom of
// 0.0 to mean "did not calculate a zoom". In that case, we default
// it to the intrinsic scale.
@ -624,7 +622,7 @@ TabChild::HandlePossibleViewportChange()
// new CSS viewport, so we know that there's no velocity, acceleration, and
// we have no idea how long painting will take.
metrics, gfx::Point(0.0f, 0.0f), gfx::Point(0.0f, 0.0f), 0.0);
CSSToScreenScale resolution = AsyncPanZoomController::CalculateResolution(metrics);
CSSToScreenScale resolution = metrics.CalculateResolution();
metrics.mResolution = resolution / metrics.mDevPixelsPerCSSPixel * ScreenToLayerScale(1);
utils->SetResolution(metrics.mResolution.scale, metrics.mResolution.scale);
@ -1491,8 +1489,7 @@ TabChild::ProcessUpdateFrame(const FrameMetrics& aFrameMetrics)
return true;
}
CSSRect cssCompositedRect =
AsyncPanZoomController::CalculateCompositedRectInCssPixels(aFrameMetrics);
CSSRect cssCompositedRect = aFrameMetrics.CalculateCompositedRectInCssPixels();
// The BrowserElementScrolling helper must know about these updated metrics
// for other functions it performs, such as double tap handling.
nsCString data;
@ -1534,8 +1531,7 @@ TabChild::ProcessUpdateFrame(const FrameMetrics& aFrameMetrics)
utils->SetScrollPositionClampingScrollPortSize(
cssCompositedRect.width, cssCompositedRect.height);
ScrollWindowTo(window, aFrameMetrics.mScrollOffset);
CSSToScreenScale resolution = AsyncPanZoomController::CalculateResolution(
aFrameMetrics);
CSSToScreenScale resolution = aFrameMetrics.CalculateResolution();
utils->SetResolution(resolution.scale, resolution.scale);
nsCOMPtr<nsIDOMDocument> domDoc;

Просмотреть файл

@ -1387,7 +1387,7 @@ DONE_CREATING_PIXMAP:
display,
glxpixmap,
cfgs[chosenIndex],
false,
true,
libToUse,
xsurface);
}

Просмотреть файл

@ -94,6 +94,31 @@ public:
return mScrollOffset * LayersPixelsPerCSSPixel();
}
/**
* Return the scale factor needed to fit the viewport
* into its composition bounds.
*/
CSSToScreenScale CalculateIntrinsicScale() const
{
return CSSToScreenScale(float(mCompositionBounds.width) / float(mViewport.width));
}
/**
* Return the resolution that content should be rendered at given
* the configuration in this metrics object: viewport dimensions,
* zoom factor, etc. (The mResolution member of this metrics is
* ignored.)
*/
CSSToScreenScale CalculateResolution() const
{
return CalculateIntrinsicScale() * mZoom;
}
CSSRect CalculateCompositedRectInCssPixels() const
{
return CSSRect(gfx::RoundedIn(mCompositionBounds / CalculateResolution()));
}
// ---------------------------------------------------------------------------
// The following metrics are all in widget space/device pixels.
//

Просмотреть файл

@ -245,7 +245,7 @@ AsyncPanZoomController::ReceiveInputEvent(const nsInputEvent& aEvent,
CSSToScreenScale currentResolution;
{
MonitorAutoLock monitor(mMonitor);
currentResolution = CalculateResolution(mFrameMetrics);
currentResolution = mFrameMetrics.CalculateResolution();
}
nsEventStatus status;
@ -559,7 +559,7 @@ nsEventStatus AsyncPanZoomController::OnScale(const PinchGestureInput& aEvent) {
{
MonitorAutoLock monitor(mMonitor);
CSSToScreenScale resolution = CalculateResolution(mFrameMetrics);
CSSToScreenScale resolution = mFrameMetrics.CalculateResolution();
gfxFloat userZoom = mFrameMetrics.mZoom.scale;
ScreenPoint focusPoint = aEvent.mFocusPoint;
@ -579,8 +579,8 @@ nsEventStatus AsyncPanZoomController::OnScale(const PinchGestureInput& aEvent) {
// either axis such that we don't overscroll the boundaries when zooming.
gfx::Point neededDisplacement;
float maxZoom = mMaxZoom / CalculateIntrinsicScale(mFrameMetrics).scale;
float minZoom = mMinZoom / CalculateIntrinsicScale(mFrameMetrics).scale;
float maxZoom = mMaxZoom / mFrameMetrics.CalculateIntrinsicScale().scale;
float minZoom = mMinZoom / mFrameMetrics.CalculateIntrinsicScale().scale;
bool doScale = (spanRatio > 1.0 && userZoom < maxZoom) ||
(spanRatio < 1.0 && userZoom > minZoom);
@ -660,7 +660,7 @@ nsEventStatus AsyncPanZoomController::OnLongPress(const TapGestureInput& aEvent)
if (mGeckoContentController) {
MonitorAutoLock monitor(mMonitor);
CSSToScreenScale resolution = CalculateResolution(mFrameMetrics);
CSSToScreenScale resolution = mFrameMetrics.CalculateResolution();
CSSPoint point = WidgetSpaceToCompensatedViewportSpace(
ScreenPoint::FromUnknownPoint(gfx::Point(
aEvent.mPoint.x, aEvent.mPoint.y)),
@ -679,7 +679,7 @@ nsEventStatus AsyncPanZoomController::OnSingleTapConfirmed(const TapGestureInput
if (mGeckoContentController) {
MonitorAutoLock monitor(mMonitor);
CSSToScreenScale resolution = CalculateResolution(mFrameMetrics);
CSSToScreenScale resolution = mFrameMetrics.CalculateResolution();
CSSPoint point = WidgetSpaceToCompensatedViewportSpace(
ScreenPoint::FromUnknownPoint(gfx::Point(
aEvent.mPoint.x, aEvent.mPoint.y)),
@ -695,7 +695,7 @@ nsEventStatus AsyncPanZoomController::OnDoubleTap(const TapGestureInput& aEvent)
MonitorAutoLock monitor(mMonitor);
if (mAllowZoom) {
CSSToScreenScale resolution = CalculateResolution(mFrameMetrics);
CSSToScreenScale resolution = mFrameMetrics.CalculateResolution();
CSSPoint point = WidgetSpaceToCompensatedViewportSpace(
ScreenPoint::FromUnknownPoint(gfx::Point(
aEvent.mPoint.x, aEvent.mPoint.y)),
@ -765,7 +765,7 @@ void AsyncPanZoomController::TrackTouch(const MultiTouchInput& aEvent) {
// We want to inversely scale it because when you're zoomed further in, a
// larger swipe should move you a shorter distance.
ScreenToCSSScale inverseResolution = CalculateResolution(mFrameMetrics).Inverse();
ScreenToCSSScale inverseResolution = mFrameMetrics.CalculateResolution().Inverse();
gfx::Point displacement(mX.GetDisplacementForDuration(inverseResolution.scale,
timeDelta),
@ -809,7 +809,7 @@ bool AsyncPanZoomController::DoFling(const TimeDuration& aDelta) {
// We want to inversely scale it because when you're zoomed further in, a
// larger swipe should move you a shorter distance.
ScreenToCSSScale inverseResolution = CalculateResolution(mFrameMetrics).Inverse();
ScreenToCSSScale inverseResolution = mFrameMetrics.CalculateResolution().Inverse();
ScrollBy(CSSPoint::FromUnknownPoint(gfx::Point(
mX.GetDisplacementForDuration(inverseResolution.scale, aDelta),
@ -838,7 +838,7 @@ void AsyncPanZoomController::ScrollBy(const CSSPoint& aOffset) {
void AsyncPanZoomController::ScaleWithFocus(float aZoom,
const ScreenPoint& aFocus) {
float zoomFactor = aZoom / mFrameMetrics.mZoom.scale;
CSSToScreenScale resolution = CalculateResolution(mFrameMetrics);
CSSToScreenScale resolution = mFrameMetrics.CalculateResolution();
SetZoomAndResolution(ScreenToScreenScale(aZoom));
@ -900,7 +900,7 @@ const CSSRect AsyncPanZoomController::CalculatePendingDisplayPort(
double estimatedPaintDuration =
aEstimatedPaintDuration > EPSILON ? aEstimatedPaintDuration : 1.0;
CSSToScreenScale resolution = CalculateResolution(aFrameMetrics);
CSSToScreenScale resolution = aFrameMetrics.CalculateResolution();
CSSIntRect compositionBounds = gfx::RoundedIn(aFrameMetrics.mCompositionBounds / resolution);
CSSRect scrollableRect = aFrameMetrics.mScrollableRect;
@ -970,27 +970,6 @@ const CSSRect AsyncPanZoomController::CalculatePendingDisplayPort(
return scrollableRect.ClampRect(shiftedDisplayPort) - scrollOffset;
}
/*static*/ CSSToScreenScale
AsyncPanZoomController::CalculateIntrinsicScale(const FrameMetrics& aMetrics)
{
return CSSToScreenScale(gfxFloat(aMetrics.mCompositionBounds.width) /
gfxFloat(aMetrics.mViewport.width));
}
/*static*/ CSSToScreenScale
AsyncPanZoomController::CalculateResolution(const FrameMetrics& aMetrics)
{
return CalculateIntrinsicScale(aMetrics) * aMetrics.mZoom;
}
/*static*/ CSSRect
AsyncPanZoomController::CalculateCompositedRectInCssPixels(const FrameMetrics& aMetrics)
{
CSSToScreenScale resolution = CalculateResolution(aMetrics);
CSSIntRect rect = gfx::RoundedIn(aMetrics.mCompositionBounds / resolution);
return CSSRect(rect);
}
void AsyncPanZoomController::SetDPI(int aDPI) {
mDPI = aDPI;
}
@ -1146,7 +1125,7 @@ bool AsyncPanZoomController::SampleContentTransformForFrame(const TimeStamp& aSa
// what PZC has transformed due to touches like panning or
// pinching. Eventually, the root layer transform will become this
// during runtime, but we must wait for Gecko to repaint.
localScale = CalculateResolution(mFrameMetrics);
localScale = mFrameMetrics.CalculateResolution();
if (frame.IsScrollable()) {
metricsScrollOffset = frame.GetScrollOffsetInLayerPixels();
@ -1238,9 +1217,9 @@ void AsyncPanZoomController::NotifyLayersUpdated(const FrameMetrics& aViewportFr
aViewportFrame.mCompositionBounds.height == mFrameMetrics.mCompositionBounds.height) {
// Remote content has sync'd up to the composition geometry
// change, so we can accept the viewport it's calculated.
CSSToScreenScale previousResolution = CalculateResolution(mFrameMetrics);
CSSToScreenScale previousResolution = mFrameMetrics.CalculateResolution();
mFrameMetrics.mViewport = aViewportFrame.mViewport;
CSSToScreenScale newResolution = CalculateResolution(mFrameMetrics);
CSSToScreenScale newResolution = mFrameMetrics.CalculateResolution();
needContentRepaint |= (previousResolution != newResolution);
}
@ -1310,7 +1289,7 @@ void AsyncPanZoomController::ZoomToRect(const gfxRect& aRect) {
CSSPoint scrollOffset = mFrameMetrics.mScrollOffset;
float currentZoom = mFrameMetrics.mZoom.scale;
float targetZoom;
float intrinsicScale = CalculateIntrinsicScale(mFrameMetrics).scale;
float intrinsicScale = mFrameMetrics.CalculateIntrinsicScale().scale;
// The minimum zoom to prevent over-zoom-out.
// If the zoom factor is lower than this (i.e. we are zoomed more into the page),
@ -1338,7 +1317,7 @@ void AsyncPanZoomController::ZoomToRect(const gfxRect& aRect) {
if (zoomToRect.IsEmpty() ||
(currentZoom == localMaxZoom && targetZoom >= localMaxZoom) ||
(currentZoom == localMinZoom && targetZoom <= localMinZoom)) {
CSSRect compositedRect = CalculateCompositedRectInCssPixels(mFrameMetrics);
CSSRect compositedRect = mFrameMetrics.CalculateCompositedRectInCssPixels();
float y = scrollOffset.y;
float newHeight =
cssPageRect.width * (compositedRect.height / compositedRect.width);
@ -1361,8 +1340,7 @@ void AsyncPanZoomController::ZoomToRect(const gfxRect& aRect) {
// Adjust the zoomToRect to a sensible position to prevent overscrolling.
FrameMetrics metricsAfterZoom = mFrameMetrics;
metricsAfterZoom.mZoom = mEndZoomToMetrics.mZoom;
CSSRect rectAfterZoom
= CalculateCompositedRectInCssPixels(metricsAfterZoom);
CSSRect rectAfterZoom = metricsAfterZoom.CalculateCompositedRectInCssPixels();
// If either of these conditions are met, the page will be
// overscrolled after zoomed
@ -1442,7 +1420,7 @@ void AsyncPanZoomController::TimeoutTouchListeners() {
void AsyncPanZoomController::SetZoomAndResolution(const ScreenToScreenScale& aZoom) {
mMonitor.AssertCurrentThreadOwns();
mFrameMetrics.mZoom = aZoom;
CSSToScreenScale resolution = CalculateResolution(mFrameMetrics);
CSSToScreenScale resolution = mFrameMetrics.CalculateResolution();
// We use ScreenToLayerScale(1) below in order to ask gecko to render
// what's currently visible on the screen. This is effectively turning
// the async zoom amount into the gecko zoom amount.
@ -1474,7 +1452,7 @@ void AsyncPanZoomController::SendAsyncScrollEvent() {
CSSSize scrollableSize;
{
scrollableSize = mFrameMetrics.mScrollableRect.Size();
contentRect = AsyncPanZoomController::CalculateCompositedRectInCssPixels(mFrameMetrics);
contentRect = mFrameMetrics.CalculateCompositedRectInCssPixels();
contentRect.MoveTo(mCurrentAsyncScrollOffset);
}

Просмотреть файл

@ -223,22 +223,6 @@ public:
const gfx::Point& aAcceleration,
double aEstimatedPaintDuration);
/**
* Return the scale factor needed to fit the viewport in |aMetrics|
* into its composition bounds.
*/
static CSSToScreenScale CalculateIntrinsicScale(const FrameMetrics& aMetrics);
/**
* Return the resolution that content should be rendered at given
* the configuration in aFrameMetrics: viewport dimensions, zoom
* factor, etc. (The mResolution member of aFrameMetrics is
* ignored.)
*/
static CSSToScreenScale CalculateResolution(const FrameMetrics& aMetrics);
static CSSRect CalculateCompositedRectInCssPixels(const FrameMetrics& aMetrics);
/**
* Send an mozbrowserasyncscroll event.
* *** The monitor must be held while calling this.

Просмотреть файл

@ -298,8 +298,7 @@ float Axis::GetOrigin() {
float Axis::GetCompositionLength() {
const FrameMetrics& metrics = mAsyncPanZoomController->GetFrameMetrics();
CSSRect cssCompositedRect =
AsyncPanZoomController::CalculateCompositedRectInCssPixels(metrics);
CSSRect cssCompositedRect = metrics.CalculateCompositedRectInCssPixels();
return GetRectLength(cssCompositedRect);
}

Просмотреть файл

@ -23,23 +23,6 @@ LOCAL_INCLUDES = \
-I$(topsrcdir)/gfx/2d/unittest \
$(NULL)
GTEST_CPPSRCS = \
TestLayers.cpp \
TestTiledLayerBuffer.cpp \
TestAsyncPanZoomController.cpp \
$(NULL)
# Because of gkmedia on windows we wont find these
# symbols in xul.dll.
ifneq ($(MOZ_WIDGET_TOOLKIT),windows)
GTEST_CPPSRCS += \
TestMoz2D.cpp \
TestBase.cpp \
TestPoint.cpp \
TestScaling.cpp \
$(NULL)
endif
include $(topsrcdir)/config/rules.mk
include $(topsrcdir)/ipc/chromium/chromium-config.mk

Просмотреть файл

@ -8,3 +8,18 @@ MODULE = 'gfxtest'
LIBRARY_NAME = 'gfxtest'
GTEST_CPP_SOURCES += [
'TestAsyncPanZoomController.cpp',
'TestLayers.cpp',
'TestTiledLayerBuffer.cpp',
]
# Because of gkmedia on windows we wont find these
# symbols in xul.dll.
if CONFIG['MOZ_WIDGET_TOOLKIT'] != 'windows':
GTEST_CPP_SOURCES += [
'TestBase.cpp'
'TestMoz2D.cpp'
'TestPoint.cpp'
'TestScaling.cpp'
]

Просмотреть файл

@ -17,6 +17,9 @@ endif
_MOZBUILD_EXTERNAL_VARIABLES := \
DIRS \
EXTRA_PP_COMPONENTS \
GTEST_CMMSRCS \
GTEST_CPPSRCS \
GTEST_CSRCS \
HOST_CSRCS \
HOST_LIBRARY_NAME \
MODULE \

Просмотреть файл

@ -5476,7 +5476,6 @@ EmitArray(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
* JSOP_SETELEM/JSOP_SETPROP would do.
*/
#if JS_HAS_GENERATORS
if (pn->isKind(PNK_ARRAYCOMP)) {
if (!EmitNewInit(cx, bce, JSProto_Array, pn))
return false;
@ -5496,7 +5495,6 @@ EmitArray(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
/* Emit the usual op needed for decompilation. */
return Emit1(cx, bce, JSOP_ENDINIT) >= 0;
}
#endif /* JS_HAS_GENERATORS */
if (!(pn->pn_xflags & PNX_NONCONST) && pn->pn_head && bce->checkSingletonContext())
return EmitSingletonInitialiser(cx, bce, pn);
@ -5782,7 +5780,6 @@ frontend::EmitTree(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
ok = EmitReturn(cx, bce, pn);
break;
#if JS_HAS_GENERATORS
case PNK_YIELD:
JS_ASSERT(bce->sc->isFunctionBox());
if (pn->pn_kid) {
@ -5797,7 +5794,6 @@ frontend::EmitTree(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
if (Emit1(cx, bce, JSOP_YIELD) < 0)
return false;
break;
#endif
case PNK_STATEMENTLIST:
ok = EmitStatementList(cx, bce, pn, top);
@ -5943,7 +5939,6 @@ frontend::EmitTree(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
: EmitVariables(cx, bce, pn, InitializeVars);
break;
#endif /* JS_HAS_BLOCK_SCOPE */
#if JS_HAS_GENERATORS
case PNK_ARRAYPUSH: {
int slot;
@ -5962,12 +5957,9 @@ frontend::EmitTree(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
return false;
break;
}
#endif
case PNK_ARRAY:
#if JS_HAS_GENERATORS
case PNK_ARRAYCOMP:
#endif
ok = EmitArray(cx, bce, pn);
break;

Просмотреть файл

@ -3692,12 +3692,9 @@ Parser<ParseHandler>::matchInOrOf(bool *isForOfp)
*isForOfp = false;
return true;
}
if (tokenStream.matchToken(TOK_NAME)) {
if (tokenStream.currentToken().name() == context->names().of) {
*isForOfp = true;
return true;
}
tokenStream.ungetToken();
if (tokenStream.matchContextualKeyword(context->names().of)) {
*isForOfp = true;
return true;
}
return false;
}
@ -3764,13 +3761,9 @@ Parser<FullParseHandler>::forStatement()
bool isForEach = false;
unsigned iflags = 0;
if (allowsForEachIn() && tokenStream.matchToken(TOK_NAME)) {
if (tokenStream.currentToken().name() == context->names().each) {
iflags = JSITER_FOREACH;
isForEach = true;
} else {
tokenStream.ungetToken();
}
if (allowsForEachIn() && tokenStream.matchContextualKeyword(context->names().each)) {
iflags = JSITER_FOREACH;
isForEach = true;
}
MUST_MATCH_TOKEN(TOK_LP, JSMSG_PAREN_AFTER_FOR);
@ -4394,7 +4387,6 @@ Parser<ParseHandler>::returnStatementOrYieldExpression()
}
if (isYield) {
JS_ASSERT(JS_HAS_GENERATORS);
if (!abortIfSyntaxParser())
return null();
@ -4883,13 +4875,11 @@ Parser<FullParseHandler>::expr()
pn2->initList(pn);
pn = pn2;
do {
#if JS_HAS_GENERATORS
pn2 = pn->last();
if (pn2->isKind(PNK_YIELD) && !pn2->isInParens()) {
report(ParseError, false, pn2, JSMSG_BAD_GENERATOR_SYNTAX, js_yield_str);
return null();
}
#endif
pn2 = assignExpr();
if (!pn2)
return null();
@ -5158,12 +5148,10 @@ Parser<ParseHandler>::assignExpr()
{
JS_CHECK_RECURSION(context, return null());
#if JS_HAS_GENERATORS
if (tokenStream.matchToken(TOK_YIELD, TSF_OPERAND))
return returnStatementOrYieldExpression();
if (tokenStream.hadError())
return null();
#endif
// Save the tokenizer state in case we find an arrow function and have to
// rewind.
@ -5369,8 +5357,6 @@ Parser<ParseHandler>::unaryExpr()
return pn;
}
#if JS_HAS_GENERATORS
/*
* A dedicated helper for transplanting the comprehension expression E in
*
@ -5807,12 +5793,8 @@ Parser<FullParseHandler>::comprehensionTail(ParseNode *kid, unsigned blockid, bo
pn2->setOp(JSOP_ITER);
pn2->pn_iflags = JSITER_ENUMERATE;
if (allowsForEachIn() && tokenStream.matchToken(TOK_NAME)) {
if (tokenStream.currentToken().name() == context->names().each)
pn2->pn_iflags |= JSITER_FOREACH;
else
tokenStream.ungetToken();
}
if (allowsForEachIn() && tokenStream.matchContextualKeyword(context->names().each))
pn2->pn_iflags |= JSITER_FOREACH;
MUST_MATCH_TOKEN(TOK_LP, JSMSG_PAREN_AFTER_FOR);
GenexpGuard<FullParseHandler> guard(this);
@ -6104,22 +6086,17 @@ Parser<SyntaxParseHandler>::generatorExpr(Node kid)
static const char js_generator_str[] = "generator";
#endif /* JS_HAS_GENERATOR_EXPRS */
#endif /* JS_HAS_GENERATORS */
template <typename ParseHandler>
typename ParseHandler::Node
Parser<ParseHandler>::assignExprWithoutYield(unsigned msg)
{
#ifdef JS_HAS_GENERATORS
GenexpGuard<ParseHandler> yieldGuard(this);
#endif
Node res = assignExpr();
yieldGuard.endBody();
if (res) {
#ifdef JS_HAS_GENERATORS
if (!yieldGuard.checkValidBody(res, msg))
return null();
#endif
}
return res;
}
@ -6141,13 +6118,11 @@ Parser<ParseHandler>::argumentList(Node listNode)
if (arg0)
guard.endBody();
#if JS_HAS_GENERATORS
if (handler.isOperationWithoutParens(argNode, PNK_YIELD) &&
tokenStream.peekToken() == TOK_COMMA) {
report(ParseError, false, argNode, JSMSG_BAD_GENERATOR_SYNTAX, js_yield_str);
return false;
}
#endif
#if JS_HAS_GENERATOR_EXPRS
if (tokenStream.matchToken(TOK_FOR)) {
if (!guard.checkValidBody(argNode))
@ -6375,9 +6350,7 @@ Parser<ParseHandler>::primaryExpr(TokenKind tt)
pn = handler.newList(PNK_ARRAY, null(), JSOP_NEWINIT);
if (!pn)
return null();
#if JS_HAS_GENERATORS
handler.setBlockId(pn, pc->blockidGen);
#endif
if (tokenStream.matchToken(TOK_RB, TSF_OPERAND)) {
/*
@ -6437,7 +6410,6 @@ Parser<ParseHandler>::primaryExpr(TokenKind tt)
}
}
#if JS_HAS_GENERATORS
/*
* At this point, (index == 0 && missingTrailingComma) implies one
* element initialiser was parsed.
@ -6483,7 +6455,6 @@ Parser<ParseHandler>::primaryExpr(TokenKind tt)
if (!arrayInitializerComprehensionTail(pn))
return null();
}
#endif /* JS_HAS_GENERATORS */
MUST_MATCH_TOKEN(TOK_RB, JSMSG_BRACKET_AFTER_LIST);
}

Просмотреть файл

@ -631,6 +631,13 @@ class MOZ_STACK_CLASS TokenStream
JS_ALWAYS_TRUE(matchToken(tt));
}
bool matchContextualKeyword(PropertyName* keyword) {
if (getToken() == TOK_NAME && currentToken().name() == keyword)
return true;
ungetToken();
return false;
}
class MOZ_STACK_CLASS Position {
public:
/*

Просмотреть файл

@ -0,0 +1,6 @@
// |jit-test| error: can't convert
Error.prototype.toString = Function;
evaluate("n f", {
noScriptRval: true,
saveFrameChain: true
});

Просмотреть файл

@ -0,0 +1,9 @@
gczeal(4,1);
var iterable = {persistedProp: 17};
iterable.__iterator__ = function() {
yield ["foo", 2];
yield ["bar", 3];
};
var it = Iterator(iterable);
assertEq(it.next().toString(), "foo,2");
assertEq(it.next().toString(), "bar,3");

Просмотреть файл

@ -1813,9 +1813,7 @@ static const JSStdName standard_class_atoms[] = {
{js_InitStringClass, EAGER_ATOM_AND_OCLASP(String)},
{js_InitExceptionClasses, EAGER_ATOM_AND_OCLASP(Error)},
{js_InitRegExpClass, EAGER_ATOM_AND_OCLASP(RegExp)},
#if JS_HAS_GENERATORS
{js_InitIteratorClasses, EAGER_ATOM_AND_OCLASP(StopIteration)},
#endif
{js_InitJSONClass, EAGER_ATOM_AND_CLASP(JSON)},
{js_InitTypedArrayClasses, EAGER_CLASS_ATOM(ArrayBuffer), &js::ArrayBufferObject::protoClass},
{js_InitWeakMapClass, EAGER_ATOM_AND_OCLASP(WeakMap)},

Просмотреть файл

@ -65,6 +65,7 @@ const char js_break_str[] = "break";
const char js_case_str[] = "case";
const char js_catch_str[] = "catch";
const char js_class_str[] = "class";
const char js_close_str[] = "close";
const char js_const_str[] = "const";
const char js_continue_str[] = "continue";
const char js_debugger_str[] = "debugger";
@ -89,6 +90,7 @@ const char js_package_str[] = "package";
const char js_private_str[] = "private";
const char js_protected_str[] = "protected";
const char js_public_str[] = "public";
const char js_send_str[] = "send";
const char js_setter_str[] = "setter";
const char js_static_str[] = "static";
const char js_super_str[] = "super";
@ -100,10 +102,6 @@ const char js_void_str[] = "void";
const char js_while_str[] = "while";
const char js_with_str[] = "with";
const char js_yield_str[] = "yield";
#if JS_HAS_GENERATORS
const char js_close_str[] = "close";
const char js_send_str[] = "send";
#endif
/*
* For a browser build from 2007-08-09 after the browser starts up there are

Просмотреть файл

@ -135,6 +135,7 @@ extern const char js_break_str[];
extern const char js_case_str[];
extern const char js_catch_str[];
extern const char js_class_str[];
extern const char js_close_str[];
extern const char js_const_str[];
extern const char js_continue_str[];
extern const char js_debugger_str[];
@ -159,6 +160,7 @@ extern const char js_package_str[];
extern const char js_private_str[];
extern const char js_protected_str[];
extern const char js_public_str[];
extern const char js_send_str[];
extern const char js_setter_str[];
extern const char js_static_str[];
extern const char js_super_str[];
@ -170,10 +172,6 @@ extern const char js_void_str[];
extern const char js_while_str[];
extern const char js_with_str[];
extern const char js_yield_str[];
#if JS_HAS_GENERATORS
extern const char js_close_str[];
extern const char js_send_str[];
#endif
namespace js {

Просмотреть файл

@ -1206,7 +1206,6 @@ js::CallOrConstructBoundFunction(JSContext *cx, unsigned argc, Value *vp)
return true;
}
#if JS_HAS_GENERATORS
static JSBool
fun_isGenerator(JSContext *cx, unsigned argc, Value *vp)
{
@ -1226,7 +1225,6 @@ fun_isGenerator(JSContext *cx, unsigned argc, Value *vp)
JS_SET_RVAL(cx, vp, BooleanValue(result));
return true;
}
#endif
/* ES5 15.3.4.5. */
static JSBool
@ -1317,9 +1315,7 @@ const JSFunctionSpec js::function_methods[] = {
JS_FN(js_apply_str, js_fun_apply, 2,0),
JS_FN(js_call_str, js_fun_call, 1,0),
JS_FN("bind", fun_bind, 1,0),
#if JS_HAS_GENERATORS
JS_FN("isGenerator", fun_isGenerator,0,0),
#endif
JS_FS_END
};
@ -1351,6 +1347,7 @@ js::Function(JSContext *cx, unsigned argc, Value *vp)
options.setPrincipals(principals)
.setOriginPrincipals(originPrincipals)
.setFileAndLine(filename, lineno)
.setNoScriptRval(false)
.setCompileAndGo(true);
unsigned n = args.length() ? args.length() - 1 : 0;

Просмотреть файл

@ -959,10 +959,8 @@ const JSFunctionSpec ElementIteratorObject::methods[] = {
JS_FS_END
};
#if JS_HAS_GENERATORS
static JSBool
CloseGenerator(JSContext *cx, HandleObject genobj);
#endif
bool
js::ValueToIterator(JSContext *cx, unsigned flags, MutableHandleValue vp)
@ -1024,12 +1022,9 @@ js::CloseIterator(JSContext *cx, HandleObject obj)
*/
ni->props_cursor = ni->props_array;
}
}
#if JS_HAS_GENERATORS
else if (obj->is<GeneratorObject>()) {
} else if (obj->is<GeneratorObject>()) {
return CloseGenerator(cx, obj);
}
#endif
return true;
}
@ -1320,8 +1315,6 @@ Class StopIterationObject::class_ = {
/*** Generators **********************************************************************************/
#if JS_HAS_GENERATORS
static void
generator_finalize(FreeOp *fop, JSObject *obj)
{
@ -1418,11 +1411,6 @@ GeneratorState::pushInterpreterFrame(JSContext *cx, FrameGuard *)
* or else some kind of epoch scheme would have to be used.
*/
GeneratorWriteBarrierPre(cx, gen_);
/*
* Don't change the state until after the frame is successfully pushed
* or else we might fail to scan some generator values.
*/
gen_->state = futureState_;
gen_->fp->clearSuspended();
@ -1561,9 +1549,12 @@ SendToGenerator(JSContext *cx, JSGeneratorOp op, HandleObject obj,
if (gen->state == JSGEN_OPEN) {
/*
* Store the argument to send as the result of the yield
* expression.
* expression. The generator stack is not barriered, so we need
* write barriers here.
*/
HeapValue::writeBarrierPre(gen->regs.sp[-1]);
gen->regs.sp[-1] = arg;
HeapValue::writeBarrierPost(cx->runtime(), gen->regs.sp[-1], &gen->regs.sp[-1]);
}
futureState = JSGEN_RUNNING;
break;
@ -1777,8 +1768,6 @@ static const JSFunctionSpec generator_methods[] = {
JS_FS_END
};
#endif /* JS_HAS_GENERATORS */
/* static */ bool
GlobalObject::initIteratorClasses(JSContext *cx, Handle<GlobalObject *> global)
{
@ -1820,14 +1809,12 @@ GlobalObject::initIteratorClasses(JSContext *cx, Handle<GlobalObject *> global)
global->setReservedSlot(ELEMENT_ITERATOR_PROTO, ObjectValue(*proto));
}
#if JS_HAS_GENERATORS
if (global->getSlot(GENERATOR_PROTO).isUndefined()) {
proto = global->createBlankPrototype(cx, &GeneratorObject::class_);
if (!proto || !DefinePropertiesAndBrand(cx, proto, NULL, generator_methods))
return false;
global->setReservedSlot(GENERATOR_PROTO, ObjectValue(*proto));
}
#endif
if (global->getPrototype(JSProto_StopIteration).isUndefined()) {
proto = global->createBlankPrototype(cx, &StopIterationObject::class_);

Просмотреть файл

@ -324,8 +324,6 @@ class ForOfIterator
} /* namespace js */
#if JS_HAS_GENERATORS
/*
* Generator state codes.
*/
@ -357,7 +355,6 @@ bool
GeneratorHasMarkableFrame(JSGenerator *gen);
} /* namespace js */
#endif
extern JSObject *
js_InitIteratorClasses(JSContext *cx, js::HandleObject obj);

Просмотреть файл

@ -2786,12 +2786,7 @@ ASTSerializer::function(ParseNode *pn, ASTType type, MutableHandleValue dst)
{
RootedFunction func(cx, pn->pn_funbox->function());
bool isGenerator =
#if JS_HAS_GENERATORS
pn->pn_funbox->isGenerator();
#else
false;
#endif
bool isGenerator = pn->pn_funbox->isGenerator();
bool isExpression =
#if JS_HAS_EXPR_CLOSURES

Просмотреть файл

@ -1195,7 +1195,6 @@ Interpret(JSContext *cx, RunState &state)
RootedScript rootScript0(cx);
DebugOnly<uint32_t> blockDepth;
#if JS_HAS_GENERATORS
if (JS_UNLIKELY(regs.fp()->isGeneratorFrame())) {
JS_ASSERT(size_t(regs.pc - script->code) <= script->length);
JS_ASSERT(regs.stackDepth() <= script->nslots);
@ -1209,7 +1208,6 @@ Interpret(JSContext *cx, RunState &state)
goto error;
}
}
#endif
/* State communicated between non-local jumps: */
bool interpReturnOK;
@ -3050,7 +3048,6 @@ BEGIN_CASE(JSOP_LEAVEBLOCKEXPR)
}
END_CASE(JSOP_LEAVEBLOCK)
#if JS_HAS_GENERATORS
BEGIN_CASE(JSOP_GENERATOR)
{
JS_ASSERT(!cx->isExceptionPending());
@ -3094,7 +3091,6 @@ BEGIN_CASE(JSOP_ARRAYPUSH)
regs.sp--;
}
END_CASE(JSOP_ARRAYPUSH)
#endif /* JS_HAS_GENERATORS */
default:
{
@ -3149,11 +3145,9 @@ END_CASE(JSOP_ARRAYPUSH)
case JSTRY_CATCH:
JS_ASSERT(*regs.pc == JSOP_ENTERBLOCK);
#if JS_HAS_GENERATORS
/* Catch cannot intercept the closing of a generator. */
if (JS_UNLIKELY(cx->getPendingException().isMagic(JS_GENERATOR_CLOSING)))
break;
#endif
/*
* Don't clear exceptions to save cx->exception from GC
@ -3196,14 +3190,12 @@ END_CASE(JSOP_ARRAYPUSH)
* is an asynchronous return from a generator.
*/
interpReturnOK = false;
#if JS_HAS_GENERATORS
if (JS_UNLIKELY(cx->isExceptionPending() &&
cx->getPendingException().isMagic(JS_GENERATOR_CLOSING))) {
cx->clearPendingException();
interpReturnOK = true;
regs.fp()->clearReturnValue();
}
#endif
} else {
UnwindForUncatchableException(cx, regs);
interpReturnOK = false;

Просмотреть файл

@ -25,13 +25,6 @@
# define FOR_LET_KEYWORD(macro) \
macro(let, let, TOK_STRICT_RESERVED, JSOP_NOP, JSVERSION_1_7)
#endif
#if JS_HAS_GENERATORS
# define FOR_YIELD_KEYWORD(macro) \
macro(yield, yield, TOK_YIELD, JSOP_NOP, JSVERSION_1_7)
#else
# define FOR_YIELD_KEYWORD(macro) \
macro(yield, yield, TOK_STRICT_RESERVED, JSOP_NOP, JSVERSION_1_7)
#endif
#define FOR_EACH_JAVASCRIPT_KEYWORD(macro) \
macro(false, false_, TOK_FALSE, JSOP_FALSE, JSVERSION_DEFAULT) \
@ -79,9 +72,10 @@
macro(protected, protected_, TOK_STRICT_RESERVED, JSOP_NOP, JSVERSION_DEFAULT) \
macro(public, public_, TOK_STRICT_RESERVED, JSOP_NOP, JSVERSION_DEFAULT) \
macro(static, static_, TOK_STRICT_RESERVED, JSOP_NOP, JSVERSION_DEFAULT) \
/* ES5 future reserved keyword in strict mode, keyword in JS1.7 even when not strict. */ \
macro(yield, yield, TOK_YIELD, JSOP_NOP, JSVERSION_1_7) \
/* Various conditional keywords. */ \
FOR_CONST_KEYWORD(macro) \
FOR_LET_KEYWORD(macro) \
FOR_YIELD_KEYWORD(macro)
FOR_LET_KEYWORD(macro)
#endif /* vm_Keywords_h */

Просмотреть файл

@ -244,6 +244,11 @@ nsSVGPathGeometryFrame::GetFrameForPoint(const nsPoint &aPoint)
isHit = tmpCtx->PointInFill(userSpacePoint);
if (!isHit && (hitTestFlags & SVG_HIT_TEST_STROKE)) {
nsSVGUtils::SetupCairoStrokeGeometry(this, tmpCtx);
// tmpCtx's matrix may have transformed by SetupCairoStrokeGeometry
// if there is a non-scaling stroke. We need to transform userSpacePoint
// so that everything is using the same co-ordinate system.
userSpacePoint =
nsSVGUtils::GetStrokeTransform(this).Invert().Transform(userSpacePoint);
isHit = tmpCtx->PointInStroke(userSpacePoint);
}

Просмотреть файл

@ -456,7 +456,7 @@ pref("breakpad.reportURL", "https://crash-stats.mozilla.com/report/index/");
pref("app.support.baseURL", "http://support.mozilla.org/1/mobile/%VERSION%/%OS%/%LOCALE%/");
// Used to submit data to input from about:feedback
pref("app.feedback.postURL", "https://input.mozilla.org/%LOCALE%/feedback");
pref("app.privacyURL", "http://www.mozilla.org/%LOCALE%/privacy/");
pref("app.privacyURL", "https://www.mozilla.org/legal/privacy/firefox.html");
pref("app.creditsURL", "http://www.mozilla.org/credits/");
pref("app.channelURL", "http://www.mozilla.org/%LOCALE%/firefox/channel/");
#if MOZ_UPDATE_CHANNEL == aurora

Просмотреть файл

@ -87,6 +87,9 @@ class TreeMetadataEmitter(object):
EXTRA_COMPONENTS='EXTRA_COMPONENTS',
EXTRA_JS_MODULES='EXTRA_JS_MODULES',
EXTRA_PP_COMPONENTS='EXTRA_PP_COMPONENTS',
GTEST_CMMSRCS='GTEST_CMM_SOURCES',
GTEST_CPPSRCS='GTEST_CPP_SOURCES',
GTEST_CSRCS='GTEST_C_SOURCES',
HOST_CSRCS='HOST_CSRCS',
HOST_LIBRARY_NAME='HOST_LIBRARY_NAME',
JS_MODULES_PATH='JS_MODULES_PATH',

Просмотреть файл

@ -118,6 +118,27 @@ VARIABLES = {
files will be installed in the /components directory of the distribution.
"""),
'GTEST_C_SOURCES': (StrictOrderingOnAppendList, list, [],
"""C code source files for GTest unit tests.
This variable contains a list of C GTEST unit test source files to
compile.
"""),
'GTEST_CMM_SOURCES': (StrictOrderingOnAppendList, list, [],
"""Sources for GTest unit tests to compile with the Objective C/C++ compiler.
This variable contains a list of objective-C++ GTest unit test sources
to compile.
"""),
'GTEST_CPP_SOURCES': (list, list, [],
"""C++ source files for GTest unit tests.
This is a list of C++ GTest unit test sources. Entries must be files
that exist. These generally have .cpp, .cc, or .cxx extensions.
"""),
'HOST_CSRCS': (StrictOrderingOnAppendList, list, [],
"""C source files to compile with the host compiler.

Просмотреть файл

@ -13,6 +13,10 @@ DEFINES = ['-Dbar', '-Dfoo']
EXTRA_COMPONENTS = ['bar.js', 'foo.js']
EXTRA_PP_COMPONENTS = ['bar.pp.js', 'foo.pp.js']
GTEST_C_SOURCES = ['test1.c', 'test2.c']
GTEST_CMM_SOURCES = ['test1.mm', 'test2.mm']
GTEST_CPP_SOURCES = ['test1.cpp', 'test2.cpp']
HOST_CSRCS = ['bar.c', 'foo.c']
HOST_LIBRARY_NAME = 'host_bar'

Просмотреть файл

@ -162,6 +162,18 @@ class TestRecursiveMakeBackend(BackendTester):
'EXTRA_PP_COMPONENTS += bar.pp.js',
'EXTRA_PP_COMPONENTS += foo.pp.js',
],
'GTEST_CMMSRCS': [
'GTEST_CMMSRCS += test1.mm',
'GTEST_CMMSRCS += test2.mm',
],
'GTEST_CPPSRCS': [
'GTEST_CPPSRCS += test1.cpp',
'GTEST_CPPSRCS += test2.cpp',
],
'GTEST_CSRCS': [
'GTEST_CSRCS += test1.c',
'GTEST_CSRCS += test2.c',
],
'HOST_CSRCS': [
'HOST_CSRCS += bar.c',
'HOST_CSRCS += foo.c',

Просмотреть файл

@ -13,6 +13,10 @@ DEFINES=['-Dfans', '-Dtans']
EXTRA_COMPONENTS=['fans.js', 'tans.js']
EXTRA_PP_COMPONENTS=['fans.pp.js', 'tans.pp.js']
GTEST_C_SOURCES = ['test1.c', 'test2.c']
GTEST_CMM_SOURCES = ['test1.mm', 'test2.mm']
GTEST_CPP_SOURCES = ['test1.cpp', 'test2.cpp']
HOST_CSRCS += ['fans.c', 'tans.c']
HOST_LIBRARY_NAME = 'host_fans'

Просмотреть файл

@ -131,6 +131,9 @@ class TestEmitterBasic(unittest.TestCase):
DEFINES=['-Dfans', '-Dtans'],
EXTRA_COMPONENTS=['fans.js', 'tans.js'],
EXTRA_PP_COMPONENTS=['fans.pp.js', 'tans.pp.js'],
GTEST_CSRCS=['test1.c', 'test2.c'],
GTEST_CMMSRCS=['test1.mm', 'test2.mm'],
GTEST_CPPSRCS=['test1.cpp', 'test2.cpp'],
HOST_CSRCS=['fans.c', 'tans.c'],
HOST_LIBRARY_NAME='host_fans',
LIBRARY_NAME='lib_name',

Просмотреть файл

@ -22,10 +22,6 @@ EXPORT_LIBRARY = 1
LIBXUL_LIBRARY = 1
IS_COMPONENT = 1
GTEST_CPPSRCS = \
SanityTest.cpp \
$(NULL)
LOCAL_INCLUDES += \
-I$(srcdir)/gtest \
-I$(srcdir)/gtest/include \

Просмотреть файл

@ -61,3 +61,7 @@ CPP_SOURCES += [
LIBRARY_NAME = 'gtest'
GTEST_CPP_SOURCES += [
'SanityTest.cpp',
]

Просмотреть файл

@ -45,6 +45,17 @@ try {
}
catch (e) { }
// Only if building of places is enabled.
if (runningInParent &&
"mozIAsyncHistory" in Components.interfaces) {
// Ensure places history is enabled for xpcshell-tests as some non-FF
// apps disable it.
let (prefs = Components.classes["@mozilla.org/preferences-service;1"]
.getService(Components.interfaces.nsIPrefBranch)) {
prefs.setBoolPref("places.history.enabled", true);
};
}
try {
if (runningInParent) {
let prefs = Components.classes["@mozilla.org/preferences-service;1"]

Просмотреть файл

@ -36,9 +36,6 @@ add_task(function test_execute()
if (!("@mozilla.org/browser/nav-history-service;1" in Cc))
return;
// Ensure places is enabled.
Services.prefs.setBoolPref("places.history.enabled", true);
let dm = Cc["@mozilla.org/download-manager;1"].
getService(Ci.nsIDownloadManager);
let db = dm.DBConnection;

Просмотреть файл

@ -440,6 +440,23 @@ DownloadSource.prototype = {
* should be sent or the download source is not HTTP.
*/
referrer: null,
/**
* Returns a static representation of the current object state.
*
* @return A JavaScript object that can be serialized to JSON.
*/
serialize: function DS_serialize()
{
let serialized = { uri: this.uri.spec };
if (this.isPrivate) {
serialized.isPrivate = true;
}
if (this.referrer) {
serialized.referrer = this.referrer.spec;
}
return serialized;
},
};
////////////////////////////////////////////////////////////////////////////////
@ -456,6 +473,16 @@ DownloadTarget.prototype = {
* The nsIFile for the download target.
*/
file: null,
/**
* Returns a static representation of the current object state.
*
* @return A JavaScript object that can be serialized to JSON.
*/
serialize: function DT_serialize()
{
return { file: this.file.path };
},
};
////////////////////////////////////////////////////////////////////////////////
@ -555,6 +582,16 @@ DownloadSaver.prototype = {
{
throw new Error("Not implemented.");
},
/**
* Returns a static representation of the current object state.
*
* @return A JavaScript object that can be serialized to JSON.
*/
serialize: function DS_serialize()
{
throw new Error("Not implemented.");
},
};
////////////////////////////////////////////////////////////////////////////////
@ -686,6 +723,14 @@ DownloadCopySaver.prototype = {
this._backgroundFileSaver = null;
}
},
/**
* Implements "DownloadSaver.serialize".
*/
serialize: function DCS_serialize()
{
return { type: "copy" };
},
};
////////////////////////////////////////////////////////////////////////////////

Просмотреть файл

@ -25,14 +25,16 @@ const Cr = Components.results;
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "DownloadStore",
"resource://gre/modules/DownloadStore.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "FileUtils",
"resource://gre/modules/FileUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "OS",
"resource://gre/modules/osfile.jsm")
XPCOMUtils.defineLazyModuleGetter(this, "Services",
"resource://gre/modules/Services.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "Task",
"resource://gre/modules/Task.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "OS",
"resource://gre/modules/osfile.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "FileUtils",
"resource://gre/modules/FileUtils.jsm");
XPCOMUtils.defineLazyServiceGetter(this, "env",
"@mozilla.org/process/environment;1",
"nsIEnvironment");
@ -51,6 +53,44 @@ XPCOMUtils.defineLazyGetter(this, "gStringBundle", function() {
this.DownloadIntegration = {
// For testing only
testMode: false,
dontLoad: false,
/**
* Main DownloadStore object for loading and saving the list of persistent
* downloads, or null if the download list was never requested and thus it
* doesn't need to be persisted.
*/
_store: null,
/**
* Performs initialization of the list of persistent downloads, before its
* first use by the host application. This function may be called only once
* during the entire lifetime of the application.
*
* @param aList
* DownloadList object to be populated with the download objects
* serialized from the previous session. This list will be persisted
* to disk during the session lifetime or when the session terminates.
*
* @return {Promise}
* @resolves When the list has been populated.
* @rejects JavaScript exception.
*/
loadPersistent: function DI_loadPersistent(aList)
{
if (this.dontLoad) {
return Promise.resolve();
}
if (this._store) {
throw new Error("loadPersistent may be called only once.");
}
this._store = new DownloadStore(aList, OS.Path.join(
OS.Constants.Path.profileDir,
"downloads.json"));
return this._store.load();
},
/**
* Returns the system downloads directory asynchronously.

Просмотреть файл

@ -25,14 +25,144 @@ const Cr = Components.results;
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "Downloads",
"resource://gre/modules/Downloads.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "NetUtil",
"resource://gre/modules/NetUtil.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "OS",
"resource://gre/modules/osfile.jsm")
XPCOMUtils.defineLazyModuleGetter(this, "Task",
"resource://gre/modules/Task.jsm");
const LocalFile = Components.Constructor("@mozilla.org/file/local;1",
"nsIFile", "initWithPath");
XPCOMUtils.defineLazyGetter(this, "gTextDecoder", function () {
return new TextDecoder();
});
XPCOMUtils.defineLazyGetter(this, "gTextEncoder", function () {
return new TextEncoder();
});
////////////////////////////////////////////////////////////////////////////////
//// DownloadStore
/**
* Handles serialization of Download objects and persistence into a file, so
* that the state of downloads can be restored across sessions.
*
* @param aList
* DownloadList object to be populated or serialized.
* @param aPath
* String containing the file path where data should be saved.
*/
function DownloadStore() { }
function DownloadStore(aList, aPath)
{
this.list = aList;
this.path = aPath;
}
DownloadStore.prototype = {
/**
* DownloadList object to be populated or serialized.
*/
list: null,
/**
* String containing the file path where data should be saved.
*/
path: "",
/**
* Loads persistent downloads from the file to the list.
*
* @return {Promise}
* @resolves When the operation finished successfully.
* @rejects JavaScript exception.
*/
load: function DS_load()
{
return Task.spawn(function task_DS_load() {
let bytes;
try {
bytes = yield OS.File.read(this.path);
} catch (ex if ex instanceof OS.File.Error && ex.becauseNoSuchFile) {
// If the file does not exist, there are no downloads to load.
return;
}
let storeData = JSON.parse(gTextDecoder.decode(bytes));
// Create live downloads based on the static snapshot.
for (let downloadData of storeData) {
try {
let source = { uri: NetUtil.newURI(downloadData.source.uri) };
if ("referrer" in downloadData.source) {
source.referrer = NetUtil.newURI(downloadData.source.referrer);
}
let download = yield Downloads.createDownload({
source: source,
target: { file: new LocalFile(downloadData.target.file) },
saver: downloadData.saver,
});
this.list.add(download);
} catch (ex) {
// If an item is unrecognized, don't prevent others from being loaded.
Cu.reportError(ex);
}
}
}.bind(this));
},
/**
* Saves persistent downloads from the list to the file.
*
* If an error occurs, the previous file is not deleted.
*
* @return {Promise}
* @resolves When the operation finished successfully.
* @rejects JavaScript exception.
*/
save: function DS_save()
{
return Task.spawn(function task_DS_save() {
let downloads = yield this.list.getAll();
// Take a static snapshot of the current state of all the downloads.
let storeData = [];
let atLeastOneDownload = false;
for (let download of downloads) {
try {
storeData.push({
source: download.source.serialize(),
target: download.target.serialize(),
saver: download.saver.serialize(),
});
atLeastOneDownload = true;
} catch (ex) {
// If an item cannot be serialized, don't prevent others from being
// saved.
Cu.reportError(ex);
}
}
if (atLeastOneDownload) {
// Create or overwrite the file if there are downloads to save.
let bytes = gTextEncoder.encode(JSON.stringify(storeData));
yield OS.File.writeAtomic(this.path, bytes,
{ tmpPath: this.path + ".tmp" });
} else {
// Remove the file if there are no downloads to save at all.
try {
yield OS.File.remove(this.path);
} catch (ex if ex instanceof OS.File.Error &&
(ex.becauseNoSuchFile || ex.becauseAccessDenied)) {
// On Windows, we may get an access denied error instead of a no such
// file error if the file existed before, and was recently deleted.
}
}
}.bind(this));
},
};

Просмотреть файл

@ -29,8 +29,6 @@ XPCOMUtils.defineLazyModuleGetter(this, "DownloadIntegration",
"resource://gre/modules/DownloadIntegration.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "DownloadList",
"resource://gre/modules/DownloadList.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "DownloadStore",
"resource://gre/modules/DownloadStore.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "DownloadUIHelper",
"resource://gre/modules/DownloadUIHelper.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "FileUtils",
@ -173,12 +171,27 @@ this.Downloads = {
*/
getPublicDownloadList: function D_getPublicDownloadList()
{
if (!this._publicDownloadList) {
this._publicDownloadList = new DownloadList(true);
if (!this._promisePublicDownloadList) {
this._promisePublicDownloadList = Task.spawn(
function task_D_getPublicDownloadList() {
let list = new DownloadList(true);
try {
yield DownloadIntegration.loadPersistent(list);
} catch (ex) {
Cu.reportError(ex);
}
throw new Task.Result(list);
});
}
return Promise.resolve(this._publicDownloadList);
return this._promisePublicDownloadList;
},
_publicDownloadList: null,
/**
* This promise is resolved with a reference to a DownloadList object that
* represents persistent downloads. This property is null before the list of
* downloads is requested for the first time.
*/
_promisePublicDownloadList: null,
/**
* Retrieves the DownloadList object for downloads that were started from

Просмотреть файл

@ -75,6 +75,8 @@ const TEST_INTERRUPTIBLE_GZIP_URI = NetUtil.newURI(HTTP_BASE +
TEST_INTERRUPTIBLE_GZIP_PATH);
const TEST_TARGET_FILE_NAME = "test-download.txt";
const TEST_STORE_FILE_NAME = "test-downloads.json";
const TEST_DATA_SHORT = "This test string is downloaded.";
// Generate using gzipCompressString in TelemetryPing.js.
const TEST_DATA_SHORT_GZIP_ENCODED_FIRST = [
@ -184,6 +186,32 @@ function promiseSimpleDownload(aSourceURI) {
});
}
/**
* Returns a new public DownloadList object.
*
* @return {Promise}
* @resolves The newly created DownloadList object.
* @rejects JavaScript exception.
*/
function promiseNewDownloadList() {
// Force the creation of a new public download list.
Downloads._promisePublicDownloadList = null;
return Downloads.getPublicDownloadList();
}
/**
* Returns a new private DownloadList object.
*
* @return {Promise}
* @resolves The newly created DownloadList object.
* @rejects JavaScript exception.
*/
function promiseNewPrivateDownloadList() {
// Force the creation of a new public download list.
Downloads._privateDownloadList = null;
return Downloads.getPrivateDownloadList();
}
/**
* Ensures that the given file contents are equal to the given string.
*
@ -420,4 +448,7 @@ add_task(function test_common_initialize()
bos.writeByteArray(TEST_DATA_SHORT_GZIP_ENCODED_SECOND,
TEST_DATA_SHORT_GZIP_ENCODED_SECOND.length);
});
// Disable integration with the host application requiring profile access.
DownloadIntegration.dontLoad = true;
});

Просмотреть файл

@ -9,35 +9,6 @@
"use strict";
////////////////////////////////////////////////////////////////////////////////
//// Globals
/**
* Returns a new DownloadList object.
*
* @return {Promise}
* @resolves The newly created DownloadList object.
* @rejects JavaScript exception.
*/
function promiseNewDownloadList() {
// Force the creation of a new public download list.
Downloads._publicDownloadList = null;
return Downloads.getPublicDownloadList();
}
/**
* Returns a new private DownloadList object.
*
* @return {Promise}
* @resolves The newly created DownloadList object.
* @rejects JavaScript exception.
*/
function promiseNewPrivateDownloadList() {
// Force the creation of a new public download list.
Downloads._privateDownloadList = null;
return Downloads.getPrivateDownloadList();
}
////////////////////////////////////////////////////////////////////////////////
//// Tests

Просмотреть файл

@ -0,0 +1,219 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Tests the DownloadStore object.
*/
"use strict";
////////////////////////////////////////////////////////////////////////////////
//// Globals
XPCOMUtils.defineLazyModuleGetter(this, "DownloadStore",
"resource://gre/modules/DownloadStore.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "OS",
"resource://gre/modules/osfile.jsm")
/**
* Returns a new DownloadList object with an associated DownloadStore.
*
* @param aStorePath
* String pointing to the file to be associated with the DownloadStore,
* or undefined to use a non-existing temporary file. In this case, the
* temporary file is deleted when the test file execution finishes.
*
* @return {Promise}
* @resolves Array [ Newly created DownloadList , associated DownloadStore ].
* @rejects JavaScript exception.
*/
function promiseNewListAndStore(aStorePath) {
return promiseNewDownloadList().then(function (aList) {
let path = aStorePath || getTempFile(TEST_STORE_FILE_NAME).path;
let store = new DownloadStore(aList, path);
return [aList, store];
});
}
////////////////////////////////////////////////////////////////////////////////
//// Tests
/**
* Saves downloads to a file, then reloads them.
*/
add_task(function test_save_reload()
{
let [listForSave, storeForSave] = yield promiseNewListAndStore();
let [listForLoad, storeForLoad] = yield promiseNewListAndStore(
storeForSave.path);
listForSave.add(yield promiseSimpleDownload(TEST_SOURCE_URI));
listForSave.add(yield Downloads.createDownload({
source: { uri: TEST_EMPTY_URI,
referrer: TEST_REFERRER_URI },
target: { file: getTempFile(TEST_TARGET_FILE_NAME) },
saver: { type: "copy" },
}));
yield storeForSave.save();
yield storeForLoad.load();
let itemsForSave = yield listForSave.getAll();
let itemsForLoad = yield listForLoad.getAll();
do_check_eq(itemsForSave.length, itemsForLoad.length);
// Downloads should be reloaded in the same order.
for (let i = 0; i < itemsForSave.length; i++) {
// The reloaded downloads are different objects.
do_check_neq(itemsForSave[i], itemsForLoad[i]);
// The reloaded downloads have the same properties.
do_check_true(itemsForSave[i].source.uri.equals(
itemsForLoad[i].source.uri));
if (itemsForSave[i].source.referrer) {
do_check_true(itemsForSave[i].source.referrer.equals(
itemsForLoad[i].source.referrer));
} else {
do_check_true(itemsForLoad[i].source.referrer === null);
}
do_check_true(itemsForSave[i].target.file.equals(
itemsForLoad[i].target.file));
do_check_eq(itemsForSave[i].saver.type,
itemsForLoad[i].saver.type);
}
});
/**
* Checks that saving an empty list deletes any existing file.
*/
add_task(function test_save_empty()
{
let [list, store] = yield promiseNewListAndStore();
let createdFile = yield OS.File.open(store.path, { create: true });
yield createdFile.close();
yield store.save();
do_check_false(yield OS.File.exists(store.path));
// If the file does not exist, saving should not generate exceptions.
yield store.save();
});
/**
* Checks that loading from a missing file results in an empty list.
*/
add_task(function test_load_empty()
{
let [list, store] = yield promiseNewListAndStore();
do_check_false(yield OS.File.exists(store.path));
yield store.load();
let items = yield list.getAll();
do_check_eq(items.length, 0);
});
/**
* Loads downloads from a string in a predefined format. The purpose of this
* test is to verify that the JSON format used in previous versions can be
* loaded, assuming the file is reloaded on the same platform.
*/
add_task(function test_load_string_predefined()
{
let [list, store] = yield promiseNewListAndStore();
// The platform-dependent file name should be generated dynamically.
let targetFile = getTempFile(TEST_TARGET_FILE_NAME);
let filePathLiteral = JSON.stringify(targetFile.path);
let sourceUriLiteral = JSON.stringify(TEST_SOURCE_URI.spec);
let emptyUriLiteral = JSON.stringify(TEST_EMPTY_URI.spec);
let referrerUriLiteral = JSON.stringify(TEST_REFERRER_URI.spec);
let string = "[{\"source\":{\"uri\":" + sourceUriLiteral + "}," +
"\"target\":{\"file\":" + filePathLiteral + "}," +
"\"saver\":{\"type\":\"copy\"}}," +
"{\"source\":{\"uri\":" + emptyUriLiteral + "," +
"\"referrer\":" + referrerUriLiteral + "}," +
"\"target\":{\"file\":" + filePathLiteral + "}," +
"\"saver\":{\"type\":\"copy\"}}]";
yield OS.File.writeAtomic(store.path,
new TextEncoder().encode(string),
{ tmpPath: store.path + ".tmp" });
yield store.load();
let items = yield list.getAll();
do_check_eq(items.length, 2);
do_check_true(items[0].source.uri.equals(TEST_SOURCE_URI));
do_check_true(items[0].target.file.equals(targetFile));
do_check_true(items[1].source.uri.equals(TEST_EMPTY_URI));
do_check_true(items[1].source.referrer.equals(TEST_REFERRER_URI));
do_check_true(items[1].target.file.equals(targetFile));
});
/**
* Loads downloads from a well-formed JSON string containing unrecognized data.
*/
add_task(function test_load_string_unrecognized()
{
let [list, store] = yield promiseNewListAndStore();
// The platform-dependent file name should be generated dynamically.
let targetFile = getTempFile(TEST_TARGET_FILE_NAME);
let filePathLiteral = JSON.stringify(targetFile.path);
let sourceUriLiteral = JSON.stringify(TEST_SOURCE_URI.spec);
let string = "[{\"source\":null," +
"\"target\":null}," +
"{\"source\":{\"uri\":" + sourceUriLiteral + "}," +
"\"target\":{\"file\":" + filePathLiteral + "}," +
"\"saver\":{\"type\":\"copy\"}}]";
yield OS.File.writeAtomic(store.path,
new TextEncoder().encode(string),
{ tmpPath: store.path + ".tmp" });
yield store.load();
let items = yield list.getAll();
do_check_eq(items.length, 1);
do_check_true(items[0].source.uri.equals(TEST_SOURCE_URI));
do_check_true(items[0].target.file.equals(targetFile));
});
/**
* Loads downloads from a malformed JSON string.
*/
add_task(function test_load_string_malformed()
{
let [list, store] = yield promiseNewListAndStore();
let string = "[{\"source\":null,\"target\":null}," +
"{\"source\":{\"uri\":\"about:blank\"}}";
yield OS.File.writeAtomic(store.path, new TextEncoder().encode(string),
{ tmpPath: store.path + ".tmp" });
try {
yield store.load();
do_throw("Exception expected when JSON data is malformed.");
} catch (ex if ex.name == "SyntaxError") {
do_print("The expected SyntaxError exception was thrown.");
}
let items = yield list.getAll();
do_check_eq(items.length, 0);
});

Просмотреть файл

@ -3,8 +3,8 @@ head = head.js
tail = tail.js
[test_DownloadCore.js]
[test_DownloadIntegration.js]
[test_DownloadLegacy.js]
[test_DownloadList.js]
[test_Downloads.js]
[test_DownloadIntegration.js]
[test_DownloadStore.js]

Просмотреть файл

@ -138,6 +138,15 @@ if (typeof Components != "undefined") {
return this.unixErrno == OS.Constants.libc.EBADF;
}
});
/**
* |true| if the error was raised because permission is denied to
* access a file or directory, |false| otherwise.
*/
Object.defineProperty(OSError.prototype, "becauseAccessDenied", {
get: function becauseAccessDenied() {
return this.unixErrno == OS.Constants.libc.EACCES;
}
});
/**
* Serialize an instance of OSError to something that can be

Просмотреть файл

@ -151,6 +151,15 @@ if (typeof Components != "undefined") {
return this.winLastError == exports.OS.Constants.Win.ERROR_INVALID_HANDLE;
}
});
/**
* |true| if the error was raised because permission is denied to
* access a file or directory, |false| otherwise.
*/
Object.defineProperty(OSError.prototype, "becauseAccessDenied", {
get: function becauseAccessDenied() {
return this.winLastError == exports.OS.Constants.Win.ERROR_ACCESS_DENIED;
}
});
/**
* Serialize an instance of OSError to something that can be

Просмотреть файл

@ -55,9 +55,6 @@ function LOG(aMsg) {
let gTestDir = do_get_cwd();
// Ensure history is enabled.
Services.prefs.setBoolPref("places.history.enabled", true);
// Initialize profile.
let gProfD = do_get_profile();

Просмотреть файл

@ -6,9 +6,6 @@ const { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
// Ensure history is enabled.
Services.prefs.setBoolPref("places.history.enabled", true);
XPCOMUtils.defineLazyModuleGetter(this, "Promise",
"resource://gre/modules/commonjs/sdk/core/promise.js");
XPCOMUtils.defineLazyModuleGetter(this, "PlacesUtils",

Просмотреть файл

@ -733,8 +733,6 @@ let tests = [
function run_test()
{
Services.prefs.setBoolPref("places.history.enabled", true);
for (let i = 0; i < tests.length; i++)
add_task(tests[i]);

Просмотреть файл

@ -6,7 +6,6 @@
#include "mozilla/Util.h"
#include "mozilla/layers/CompositorChild.h"
#include "mozilla/layers/CompositorParent.h"
#include "mozilla/layers/AsyncPanZoomController.h"
#include <android/log.h>
#include <dlfcn.h>
@ -2784,8 +2783,7 @@ AndroidBridge::RequestContentRepaint(const mozilla::layers::FrameMetrics& aFrame
return;
}
CSSToScreenScale resolution =
mozilla::layers::AsyncPanZoomController::CalculateResolution(aFrameMetrics);
CSSToScreenScale resolution = aFrameMetrics.CalculateResolution();
ScreenRect dp = (aFrameMetrics.mDisplayPort + aFrameMetrics.mScrollOffset) * resolution;
AutoLocalJNIFrame jniFrame(env, 0);