Merge mozilla-central and inbound

This commit is contained in:
Ed Morley 2014-08-07 14:40:43 +01:00
commit 0c010bd02f
54 changed files with 1026 additions and 97 deletions

View File

@ -44,15 +44,19 @@ var checkTestResults = function() {
SimpleTest.finish();
}
function loadElements() {
// save this for last so that our listeners are registered.
// ... this loads the testbed of good and bad requests.
document.getElementById('cspframe').src = 'file_CSP_evalscript_main_getCRMFRequest.html';
document.getElementById('cspframe2').src = 'file_CSP_evalscript_main_allowed_getCRMFRequest.html';
document.getElementById('cspframe3').src = 'file_CSP_evalscript_no_CSP_at_all.html';
}
//////////////////////////////////////////////////////////////////////
// set up and go
SimpleTest.waitForExplicitFinish();
// save this for last so that our listeners are registered.
// ... this loads the testbed of good and bad requests.
document.getElementById('cspframe').src = 'file_CSP_evalscript_main_getCRMFRequest.html';
document.getElementById('cspframe2').src = 'file_CSP_evalscript_main_allowed_getCRMFRequest.html';
document.getElementById('cspframe3').src = 'file_CSP_evalscript_no_CSP_at_all.html';
SpecialPowers.pushPrefEnv({"set": [["dom.unsafe_legacy_crypto.enabled", true]]},
loadElements);
</script>
</pre>
</body>

View File

@ -0,0 +1,41 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=1017086
-->
<head>
<meta charset="utf-8">
<title>Test for Bug 1017086</title>
<meta name="author" content="Maksim Lebedev" />
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script type="application/javascript">
/** Test for Bug 1017086 **/
var testelem = undefined;
var pointer_events = ["onpointerover", "onpointerenter",
"onpointermove",
"onpointerdown", "onpointerup",
"onpointerout", "onpointerleave",
"onpointercancel"];
function check(expected_value, event_name, container, container_name) {
var text = event_name + " in " + container_name + " should be " + expected_value;
parent.is(event_name in container, expected_value, text);
}
function runTest() {
testelem = document.getElementById("test");
is(!!testelem, true, "Document should have element with id 'test'");
parent.turnOnOffPointerEvents( function() {
parent.part_of_checks(pointer_events, check, window, document, testelem);
});
}
</script>
</head>
<body onload="runTest();">
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1017086">Mozilla Bug 1017086</a>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
</pre>
</body>
</html>

View File

@ -126,11 +126,17 @@ skip-if = toolkit == 'android'
[test_bug864040.html]
skip-if = buildapp == 'b2g' # b2g(failing when the test gets moved around, and on debug) b2g-debug(failing when the test gets moved around, and on debug) b2g-desktop(failing when the test gets moved around, and on debug)
[test_bug930374-content.html]
[test_bug944011.html]
[test_bug944847.html]
[test_bug946632.html]
[test_bug967796.html]
skip-if = toolkit == "gonk" || e10s
[test_bug944011.html]
[test_bug946632.html]
[test_bug985988.html]
[test_bug998809.html]
[test_bug1017086_disable.html]
support-files = bug1017086_inner.html
[test_bug1017086_enable.html]
support-files = bug1017086_inner.html
[test_clickevent_on_input.html]
skip-if = toolkit == 'android' #CRASH_DUMP, RANDOM
[test_continuous_wheel_events.html]
@ -140,6 +146,7 @@ skip-if = buildapp == 'b2g' || e10s # b2g(5535 passed, 108 failed - more tests r
skip-if = toolkit == 'android' #CRASH_DUMP, RANDOM
[test_dom_mouse_event.html]
skip-if = toolkit == 'android' #CRASH_DUMP, RANDOM
[test_dom_storage_event.html]
[test_dom_wheel_event.html]
skip-if = buildapp == 'b2g' || e10s # b2g(456 failed out of 19873, mousewheel test) b2g-debug(456 failed out of 19873, mousewheel test) b2g-desktop(456 failed out of 19873, mousewheel test)
[test_draggableprop.html]
@ -159,6 +166,3 @@ skip-if = buildapp == 'mulet'
[test_onerror_handler_args.html]
[test_wheel_default_action.html]
skip-if = buildapp == 'mulet' || buildapp == 'b2g' || e10s
[test_bug985988.html]
[test_dom_storage_event.html]
[test_bug998809.html]

View File

@ -0,0 +1,41 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=1017086
-->
<head>
<meta charset="utf-8">
<title>Test for Bug 1017086</title>
<meta name="author" content="Maksim Lebedev" />
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script type="text/javascript">
/** Test for Bug 1017086 **/
var pointer_events_enabled = false;
function prepareTest() {
SimpleTest.waitForExplicitFinish();
turnOnOffPointerEvents(startTest);
}
function turnOnOffPointerEvents(callback) {
SpecialPowers.pushPrefEnv({
"set": [
["dom.w3c_pointer_events.enabled", pointer_events_enabled]
]
}, callback);
}
function startTest() {
var iframe = document.getElementById("testFrame");
iframe.src = "bug1017086_inner.html";
}
function part_of_checks(pointer_events, check, window, document, testelem) {
for(item in pointer_events) { check(false, pointer_events[item], window, "window"); }
for(item in pointer_events) { check(false, pointer_events[item], document, "document"); }
for(item in pointer_events) { check(false, pointer_events[item], testelem, "element"); }
SimpleTest.finish();
}
</script>
</head>
<body onload="prepareTest()">
<iframe id="testFrame" height="700" width="700"></iframe>
</body>
</html>

View File

@ -0,0 +1,43 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=1017086
-->
<head>
<meta charset="utf-8">
<title>Test for Bug 1017086</title>
<meta name="author" content="Maksim Lebedev" />
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script type="text/javascript">
/** Test for Bug 1017086 **/
var pointer_events_enabled = true;
function prepareTest() {
SimpleTest.waitForExplicitFinish();
turnOnOffPointerEvents(startTest);
}
function turnOnOffPointerEvents(callback) {
SpecialPowers.pushPrefEnv({
"set": [
["dom.w3c_pointer_events.enabled", pointer_events_enabled]
]
}, callback);
}
function startTest() {
var iframe = document.getElementById("testFrame");
iframe.src = "bug1017086_inner.html";
}
function part_of_checks(pointer_events, check, window, document, testelem) {
for(item in pointer_events) { check(true, pointer_events[item], window, "window"); }
/** TODO
for(item in pointer_events) { check(false, pointer_events[item], document, "document"); }
**/
for(item in pointer_events) { check(true, pointer_events[item], testelem, "element"); }
SimpleTest.finish();
}
</script>
</head>
<body onload="prepareTest()">
<iframe id="testFrame" height="700" width="700"></iframe>
</body>
</html>

View File

@ -1650,8 +1650,8 @@ ContentChild::RecvActivateA11y()
#ifdef ACCESSIBILITY
// Start accessibility in content process if it's running in chrome
// process.
nsCOMPtr<nsIAccessibilityService> accService =
do_GetService("@mozilla.org/accessibilityService;1");
nsCOMPtr<nsIAccessibilityService> accService =
services::GetAccessibilityService();
#endif
return true;
}

View File

@ -1,2 +0,0 @@
[test_no_legacy.html]
skip-if = e10s

View File

@ -2,3 +2,4 @@
skip-if = e10s
[test_getRandomValues.html]
[test_no_legacy.html]

View File

@ -2,50 +2,59 @@
<html>
<head>
<title>Test presence of legacy window.crypto features when
MOZ_DISABLE_CRYPTOLEGACY is NOT set.</title>
MOZ_DISABLE_CRYPTOLEGACY is NOT set and dom.unsafe_legacy_crypto.enabled is true</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<script class="testbody" type="text/javascript">
ok("crypto" in window, "crypto in window");
ok("version" in window.crypto, "version in window.crypto");
ok("enableSmartCardEvents" in window.crypto,
"enableSmartCardEvents in window.crypto");
ok("generateCRMFRequest" in window.crypto,
"generateCRMFRequest in window.crypto");
ok("importUserCertificates" in window.crypto,
"importUserCertificates in window.crypto");
ok("signText" in window.crypto, "signText in window.crypto");
function test_unsafe_legacy_crypto_enabled() {
ok("crypto" in window, "crypto in window");
ok("version" in window.crypto, "version in window.crypto");
ok("enableSmartCardEvents" in window.crypto,
"enableSmartCardEvents in window.crypto");
ok("generateCRMFRequest" in window.crypto,
"generateCRMFRequest in window.crypto");
ok("importUserCertificates" in window.crypto,
"importUserCertificates in window.crypto");
ok("signText" in window.crypto, "signText in window.crypto");
function jsCallback () {
function jsCallback () {
}
try {
window.crypto.generateCRMFRequest(null, null, null, null, jsCallback.toString());
ok(false, "window.crypto.generateCRMFRequest failed, should throw error");
} catch (e) {
ok(e.toString().search(/Failure/) > -1,
"Expected error: ReqDN cannot be null");
}
try {
window.crypto.generateCRMFRequest(document.documentElement, null, null, null,
null);
ok(false, "window.crypto.generateCRMFRequest failed, should throw error");
} catch (e) {
ok(e.toString().search(/Failure/) > -1,
"Expected error: jsCallback cannot be null");
}
try {
window.crypto.generateCRMFRequest(document.documentElement, null, null, null,
jsCallback.toString(), 1024);
ok(false, "window.crypto.generateCRMFRequest failed, should throw error");
} catch (e) {
ok(e.toString().search(/TypeError/) > -1,
"Expected error: Not enough arguments");
}
SimpleTest.finish();
}
try {
window.crypto.generateCRMFRequest(null, null, null, null, jsCallback.toString());
ok(false, "window.crypto.generateCRMFRequest failed, should throw error");
} catch (e) {
ok(e.toString().search(/Failure/) > -1,
"Expected error: ReqDN cannot be null");
}
SpecialPowers.pushPrefEnv({"set": [["dom.unsafe_legacy_crypto.enabled", true]]},
test_unsafe_legacy_crypto_enabled);
SimpleTest.waitForExplicitFinish();
try {
window.crypto.generateCRMFRequest(document.documentElement, null, null, null,
null);
ok(false, "window.crypto.generateCRMFRequest failed, should throw error");
} catch (e) {
ok(e.toString().search(/Failure/) > -1,
"Expected error: jsCallback cannot be null");
}
try {
window.crypto.generateCRMFRequest(document.documentElement, null, null, null,
jsCallback.toString(), 1024);
ok(false, "window.crypto.generateCRMFRequest failed, should throw error");
} catch (e) {
ok(e.toString().search(/TypeError/) > -1,
"Expected error: Not enough arguments");
}
</script>
</body></html>

View File

@ -2,7 +2,7 @@
<html>
<head>
<title>Test lack of legacy window.crypto features when
MOZ_DISABLE_CRYPTOLEGACY is set</title>
MOZ_DISABLE_CRYPTOLEGACY is set or dom.unsafe_legacy_crypto.enabled is false</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>

View File

@ -48,11 +48,7 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] != 'gtk2':
'mochitest/pointerlock/mochitest.ini',
]
if CONFIG['MOZ_DISABLE_CRYPTOLEGACY']:
MOCHITEST_MANIFESTS += [
'mochitest/crypto/mochitest-no-legacy.ini',
]
else:
if not CONFIG['MOZ_DISABLE_CRYPTOLEGACY']:
MOCHITEST_MANIFESTS += [
'mochitest/crypto/mochitest-legacy.ini',
]

View File

@ -23,12 +23,13 @@ interface Crypto {
#ifndef MOZ_DISABLE_CRYPTOLEGACY
[NoInterfaceObject]
interface CryptoLegacy {
[Pref="dom.unsafe_legacy_crypto.enabled"]
readonly attribute DOMString version;
[SetterThrows]
[SetterThrows,Pref="dom.unsafe_legacy_crypto.enabled"]
attribute boolean enableSmartCardEvents;
[Throws,NewObject]
[Throws,NewObject,Pref="dom.unsafe_legacy_crypto.enabled"]
CRMFObject? generateCRMFRequest(ByteString? reqDN,
ByteString? regToken,
ByteString? authenticator,
@ -36,16 +37,17 @@ interface CryptoLegacy {
ByteString? jsCallback,
any... args);
[Throws]
[Throws,Pref="dom.unsafe_legacy_crypto.enabled"]
DOMString importUserCertificates(DOMString nickname,
DOMString cmmfResponse,
boolean doForcedBackup);
[Pref="dom.unsafe_legacy_crypto.enabled"]
DOMString signText(DOMString stringToSign,
DOMString caOption,
ByteString... args);
[Throws]
[Throws,Pref="dom.unsafe_legacy_crypto.enabled"]
void logout();
};

View File

@ -653,7 +653,9 @@ DrawGradient(CGColorSpaceRef aColorSpace,
if (aPattern.GetType() == PatternType::LINEAR_GRADIENT) {
const LinearGradientPattern& pat = static_cast<const LinearGradientPattern&>(aPattern);
GradientStopsCG *stops = static_cast<GradientStopsCG*>(pat.mStops.get());
CGContextConcatCTM(cg, GfxMatrixToCGAffineTransform(pat.mMatrix));
CGAffineTransform patternMatrix = GfxMatrixToCGAffineTransform(pat.mMatrix);
CGContextConcatCTM(cg, patternMatrix);
CGRect extents = CGRectApplyAffineTransform(aExtents, CGAffineTransformInvert(patternMatrix));
if (stops->mExtend == ExtendMode::CLAMP) {
// XXX: we should take the m out of the properties of LinearGradientPatterns
@ -667,11 +669,13 @@ DrawGradient(CGColorSpaceRef aColorSpace,
CGContextDrawLinearGradient(cg, stops->mGradient, startPoint, endPoint,
kCGGradientDrawsBeforeStartLocation | kCGGradientDrawsAfterEndLocation);
} else if (stops->mExtend == ExtendMode::REPEAT || stops->mExtend == ExtendMode::REFLECT) {
DrawLinearRepeatingGradient(aColorSpace, cg, pat, aExtents, stops->mExtend == ExtendMode::REFLECT);
DrawLinearRepeatingGradient(aColorSpace, cg, pat, extents, stops->mExtend == ExtendMode::REFLECT);
}
} else if (aPattern.GetType() == PatternType::RADIAL_GRADIENT) {
const RadialGradientPattern& pat = static_cast<const RadialGradientPattern&>(aPattern);
CGContextConcatCTM(cg, GfxMatrixToCGAffineTransform(pat.mMatrix));
CGAffineTransform patternMatrix = GfxMatrixToCGAffineTransform(pat.mMatrix);
CGContextConcatCTM(cg, patternMatrix);
CGRect extents = CGRectApplyAffineTransform(aExtents, CGAffineTransformInvert(patternMatrix));
GradientStopsCG *stops = static_cast<GradientStopsCG*>(pat.mStops.get());
if (stops->mExtend == ExtendMode::CLAMP) {
@ -685,7 +689,7 @@ DrawGradient(CGColorSpaceRef aColorSpace,
CGContextDrawRadialGradient(cg, stops->mGradient, startCenter, startRadius, endCenter, endRadius,
kCGGradientDrawsBeforeStartLocation | kCGGradientDrawsAfterEndLocation);
} else if (stops->mExtend == ExtendMode::REPEAT || stops->mExtend == ExtendMode::REFLECT) {
DrawRadialRepeatingGradient(aColorSpace, cg, pat, aExtents, stops->mExtend == ExtendMode::REFLECT);
DrawRadialRepeatingGradient(aColorSpace, cg, pat, extents, stops->mExtend == ExtendMode::REFLECT);
}
} else {
assert(0);

View File

@ -530,6 +530,10 @@ ContainerRender(ContainerT* aContainer,
LayerManagerComposite::AutoAddMaskEffect autoMaskEffect(aContainer->GetMaskLayer(),
effectChain,
!aContainer->GetTransform().CanDraw2D());
if (autoMaskEffect.Failed()) {
NS_WARNING("Failed to apply a mask effect.");
return;
}
aContainer->AddBlendModeEffect(effectChain);
effectChain.mPrimaryEffect = new EffectRenderTarget(surface);

View File

@ -828,7 +828,7 @@ LayerManagerComposite::CreateRefLayerComposite()
LayerManagerComposite::AutoAddMaskEffect::AutoAddMaskEffect(Layer* aMaskLayer,
EffectChain& aEffects,
bool aIs3D)
: mCompositable(nullptr)
: mCompositable(nullptr), mFailed(false)
{
if (!aMaskLayer) {
return;
@ -837,11 +837,13 @@ LayerManagerComposite::AutoAddMaskEffect::AutoAddMaskEffect(Layer* aMaskLayer,
mCompositable = ToLayerComposite(aMaskLayer)->GetCompositableHost();
if (!mCompositable) {
NS_WARNING("Mask layer with no compositable host");
mFailed = true;
return;
}
if (!mCompositable->AddMaskEffect(aEffects, aMaskLayer->GetEffectiveTransform(), aIs3D)) {
mCompositable = nullptr;
mFailed = true;
}
}

View File

@ -184,8 +184,10 @@ public:
bool aIs3D = false);
~AutoAddMaskEffect();
bool Failed() const { return mFailed; }
private:
CompositableHost* mCompositable;
bool mFailed;
};
/**

View File

@ -21,3 +21,20 @@ keeping them separate from other `Debugger` facilities.
You can retrieve the allocation site for a given object with the
[`Debugger.Object.prototype.allocationSite`][allocation-site] accessor
property.
`maxAllocationsLogLength`
: The maximum number of allocation sites to accumulate in the allocations log
at a time. Its default value is `5000`.
## Function Properties of the `Debugger.Memory.prototype` Object
`drainAllocationsLog()`
: When `trackingAllocationSites` is `true`, this method returns an array of
allocation sites (as [captured stacks][saved-frame]) for recent `Object`
allocations within the set of debuggees. *Recent* is defined as the
`maxAllocationsLogLength` most recent `Object` allocations since the last
call to `drainAllocationsLog`. Therefore, calling this method effectively
clears the log.
When `trackingAllocationSites` is `false`, `drainAllocationsLog()` throws an
`Error`.

View File

@ -0,0 +1,31 @@
// Test basic usage of drainAllocationsLog()
const root = newGlobal();
const dbg = new Debugger();
const wrappedRoot = dbg.addDebuggee(root)
dbg.memory.trackingAllocationSites = true;
root.eval("(" + function immediate() {
this.tests = [
({}),
[],
/(two|2)\s*problems/,
new function Ctor(){},
new Object(),
new Array(),
new Date(),
];
} + "());");
const allocs = dbg.memory.drainAllocationsLog();
print(allocs.join("\n--------------------------------------------------------------------------\n"));
print("Total number of allocations logged: " + allocs.length);
let idx = -1;
for (let object of root.tests) {
let wrappedObject = wrappedRoot.makeDebuggeeValue(object);
let allocSite = wrappedObject.allocationSite;
let newIdx = allocs.indexOf(allocSite);
assertEq(newIdx > idx, true);
idx = newIdx;
}

View File

@ -0,0 +1,14 @@
// Test that drainAllocationsLog fails when we aren't trackingAllocationSites.
load(libdir + 'asserts.js');
const root = newGlobal();
const dbg = new Debugger();
dbg.memory.trackingAllocationSites = true;
root.eval("this.alloc1 = {}");
dbg.memory.trackingAllocationSites = false;
root.eval("this.alloc2 = {};");
assertThrowsInstanceOf(() => dbg.memory.drainAllocationsLog(),
Error);

View File

@ -0,0 +1,24 @@
// Test when there are more allocations than the maximum log length.
const root = newGlobal();
const dbg = new Debugger();
dbg.addDebuggee(root)
dbg.memory.maxAllocationsLogLength = 3;
dbg.memory.trackingAllocationSites = true;
root.eval([
"this.alloc1 = {};", // line 1
"this.alloc2 = {};", // line 2
"this.alloc3 = {};", // line 3
"this.alloc4 = {};", // line 4
].join("\n"));
const allocs = dbg.memory.drainAllocationsLog();
// Should have stayed at the maximum length.
assertEq(allocs.length, 3);
// Should have kept the most recent allocation.
assertEq(allocs[2].line, 4);
// Should have thrown away the oldest allocation.
assertEq(allocs.map(x => x.line).indexOf(1), -1);

View File

@ -0,0 +1,21 @@
// Test that when we shorten the maximum log length, we won't get a longer log
// than that new maximum afterwards.
const root = newGlobal();
const dbg = new Debugger();
dbg.addDebuggee(root)
dbg.memory.trackingAllocationSites = true;
root.eval([
"this.alloc1 = {};", // line 1
"this.alloc2 = {};", // line 2
"this.alloc3 = {};", // line 3
"this.alloc4 = {};", // line 4
].join("\n"));
dbg.memory.maxAllocationsLogLength = 1;
const allocs = dbg.memory.drainAllocationsLog();
// Should have trimmed down to the new maximum length.
assertEq(allocs.length, 1);

View File

@ -0,0 +1,9 @@
// Test an empty allocation log.
const root = newGlobal();
const dbg = new Debugger();
dbg.addDebuggee(root)
dbg.memory.trackingAllocationSites = true;
const allocs = dbg.memory.drainAllocationsLog();
assertEq(allocs.length, 0);

View File

@ -0,0 +1,23 @@
// Test doing a GC while we have a non-empty log.
const root = newGlobal();
const dbg = new Debugger();
dbg.addDebuggee(root)
dbg.memory.trackingAllocationSites = true;
root.eval("(" + function immediate() {
this.tests = [
({}),
[],
/(two|2)\s*problems/,
new function Ctor(){},
new Object(),
new Array(),
new Date(),
];
} + "());");
gc();
const allocs = dbg.memory.drainAllocationsLog();
assertEq(allocs.length >= root.tests.length, true);

View File

@ -0,0 +1,10 @@
// Test retrieving the log when allocation tracking hasn't ever been enabled.
load(libdir + 'asserts.js');
const root = newGlobal();
const dbg = new Debugger();
dbg.addDebuggee(root)
assertThrowsInstanceOf(() => dbg.memory.drainAllocationsLog(),
Error);

View File

@ -0,0 +1,30 @@
// Test retrieving the log multiple times.
const root = newGlobal();
const dbg = new Debugger();
dbg.addDebuggee(root)
root.eval([
"this.allocs = [];",
"this.doFirstAlloc = " + function () {
this.allocs.push({}); this.firstAllocLine = Error().lineNumber;
},
"this.doSecondAlloc = " + function () {
this.allocs.push(new Object()); this.secondAllocLine = Error().lineNumber;
}
].join("\n"));
dbg.memory.trackingAllocationSites = true;
root.doFirstAlloc();
let allocs1 = dbg.memory.drainAllocationsLog();
root.doSecondAlloc();
let allocs2 = dbg.memory.drainAllocationsLog();
let allocs1Lines = allocs1.map(x => x.line);
assertEq(allocs1Lines.indexOf(root.firstAllocLine) != -1, true);
assertEq(allocs1Lines.indexOf(root.secondAllocLine) == -1, true);
let allocs2Lines = allocs2.map(x => x.line);
assertEq(allocs2Lines.indexOf(root.secondAllocLine) != -1, true);
assertEq(allocs2Lines.indexOf(root.firstAllocLine) == -1, true);

View File

@ -0,0 +1,20 @@
// Test logs that contain allocations from many debuggee compartments.
const dbg = new Debugger();
const root1 = newGlobal();
const root2 = newGlobal();
const root3 = newGlobal();
dbg.addDebuggee(root1);
dbg.addDebuggee(root2);
dbg.addDebuggee(root3);
dbg.memory.trackingAllocationSites = true;
root1.eval("this.alloc = {}");
root2.eval("this.alloc = {}");
root3.eval("this.alloc = {}");
const allocs = dbg.memory.drainAllocationsLog();
assertEq(allocs.length >= 3, true);

View File

@ -0,0 +1,21 @@
// Test logs that contain allocations from debuggee compartments added as we are
// logging.
const dbg = new Debugger();
dbg.memory.trackingAllocationSites = true;
const root1 = newGlobal();
dbg.addDebuggee(root1);
root1.eval("this.alloc = {}");
const root2 = newGlobal();
dbg.addDebuggee(root2);
root2.eval("this.alloc = {}");
const root3 = newGlobal();
dbg.addDebuggee(root3);
root3.eval("this.alloc = {}");
const allocs = dbg.memory.drainAllocationsLog();
assertEq(allocs.length >= 3, true);

View File

@ -0,0 +1,25 @@
// Test logs that shouldn't contain allocations from debuggee compartments
// removed as we are logging.
const dbg = new Debugger();
const root1 = newGlobal();
dbg.addDebuggee(root1);
const root2 = newGlobal();
dbg.addDebuggee(root2);
const root3 = newGlobal();
dbg.addDebuggee(root3);
dbg.memory.trackingAllocationSites = true;
dbg.removeDebuggee(root1);
root1.eval("this.alloc = {}");
dbg.removeDebuggee(root2);
root2.eval("this.alloc = {}");
dbg.removeDebuggee(root3);
root3.eval("this.alloc = {}");
const allocs = dbg.memory.drainAllocationsLog();
assertEq(allocs.length, 0);

View File

@ -0,0 +1,17 @@
// Test that disabling the debugger disables allocation tracking.
load(libdir + "asserts.js");
const dbg = new Debugger();
const root = newGlobal();
dbg.addDebuggee(root);
dbg.memory.trackingAllocationSites = true;
dbg.enabled = false;
root.eval("this.alloc = {}");
// We shouldn't accumulate allocations in our log while the debugger is
// disabled.
let allocs = dbg.memory.drainAllocationsLog();
assertEq(allocs.length, 0);

View File

@ -0,0 +1,18 @@
// Test that we don't crash while logging allocations and there is
// off-main-thread compilation. OMT compilation will allocate functions and
// regexps, but we just punt on measuring that accurately.
if (helperThreadCount() === 0) {
quit(0);
}
const root = newGlobal();
root.eval("this.dbg = new Debugger()");
root.dbg.addDebuggee(this);
root.dbg.memory.trackingAllocationSites = true;
offThreadCompileScript(
"function foo() {\n" +
" print('hello world');\n" +
"}"
);

View File

@ -2971,6 +2971,28 @@ MLoadFixedSlot::mightAlias(const MDefinition *store) const
return true;
}
MDefinition *
MLoadFixedSlot::foldsTo(TempAllocator &alloc)
{
if (!dependency() || !dependency()->isStoreFixedSlot())
return this;
MStoreFixedSlot *store = dependency()->toStoreFixedSlot();
if (!store->block()->dominates(block()))
return this;
if (store->object() != object())
return this;
if (store->slot() != slot())
return this;
if (store->value()->type() != type())
return this;
return store->value();
}
bool
MAsmJSLoadHeap::mightAlias(const MDefinition *def) const
{
@ -3023,6 +3045,25 @@ MAsmJSLoadGlobalVar::congruentTo(const MDefinition *ins) const
return false;
}
MDefinition *
MAsmJSLoadGlobalVar::foldsTo(TempAllocator &alloc)
{
if (!dependency() || !dependency()->isAsmJSStoreGlobalVar())
return this;
MAsmJSStoreGlobalVar *store = dependency()->toAsmJSStoreGlobalVar();
if (!store->block()->dominates(block()))
return this;
if (store->globalDataOffset() != globalDataOffset())
return this;
if (store->value()->type() != type())
return this;
return store->value();
}
HashNumber
MAsmJSLoadFuncPtr::valueHash() const
{
@ -3075,6 +3116,47 @@ MLoadSlot::valueHash() const
return hash;
}
MDefinition *
MLoadSlot::foldsTo(TempAllocator &alloc)
{
if (!dependency() || !dependency()->isStoreSlot())
return this;
MStoreSlot *store = dependency()->toStoreSlot();
if (!store->block()->dominates(block()))
return this;
if (store->slots() != slots())
return this;
if (store->value()->type() != type())
return this;
return store->value();
}
MDefinition *
MLoadElement::foldsTo(TempAllocator &alloc)
{
if (!dependency() || !dependency()->isStoreElement())
return this;
MStoreElement *store = dependency()->toStoreElement();
if (!store->block()->dominates(block()))
return this;
if (store->elements() != elements())
return this;
if (store->index() != index())
return this;
if (store->value()->type() != type())
return this;
return store->value();
}
bool
MGuardShapePolymorphic::congruentTo(const MDefinition *ins) const
{

View File

@ -6625,6 +6625,7 @@ class MLoadElement
return false;
return congruentIfOperandsEqual(other);
}
MDefinition *foldsTo(TempAllocator &alloc);
AliasSet getAliasSet() const {
return AliasSet::Load(AliasSet::Element);
}
@ -7423,6 +7424,8 @@ class MLoadFixedSlot
return congruentIfOperandsEqual(ins);
}
MDefinition *foldsTo(TempAllocator &alloc);
AliasSet getAliasSet() const {
return AliasSet::Load(AliasSet::FixedSlot);
}
@ -8314,6 +8317,9 @@ class MLoadSlot
return false;
return congruentIfOperandsEqual(ins);
}
MDefinition *foldsTo(TempAllocator &alloc);
AliasSet getAliasSet() const {
JS_ASSERT(slots()->type() == MIRType_Slots);
return AliasSet::Load(AliasSet::DynamicSlot);
@ -10591,6 +10597,7 @@ class MAsmJSLoadGlobalVar : public MNullaryInstruction
HashNumber valueHash() const;
bool congruentTo(const MDefinition *ins) const;
MDefinition *foldsTo(TempAllocator &alloc);
AliasSet getAliasSet() const {
return isConstant_ ? AliasSet::None() : AliasSet::Load(AliasSet::AsmJSGlobalVar);

View File

@ -240,7 +240,7 @@ MSG_DEF(JSMSG_SYMBOL_TO_STRING, 186, 0, JSEXN_TYPEERR, "can't convert symb
MSG_DEF(JSMSG_OBJECT_METADATA_CALLBACK_ALREADY_SET, 187, 0, JSEXN_ERR, "Cannot track object allocation, because other tools are already doing so")
MSG_DEF(JSMSG_INCOMPATIBLE_METHOD, 188, 3, JSEXN_TYPEERR, "{0} {1} called on incompatible {2}")
MSG_DEF(JSMSG_SYMBOL_TO_PRIMITIVE, 189, 0, JSEXN_TYPEERR, "can't convert symbol object to primitive")
MSG_DEF(JSMSG_UNUSED190, 190, 0, JSEXN_NONE, "")
MSG_DEF(JSMSG_NOT_TRACKING_ALLOCATIONS, 190, 1, JSEXN_ERR, "Cannot call {0} without setting trackingAllocationSites to true")
MSG_DEF(JSMSG_BAD_INDEX, 191, 0, JSEXN_RANGEERR, "invalid or out-of-range index")
MSG_DEF(JSMSG_SELFHOSTED_TOP_LEVEL_LET,192,0, JSEXN_SYNTAXERR, "self-hosted code cannot contain top-level 'let' declarations")
MSG_DEF(JSMSG_BAD_FOR_EACH_LOOP, 193, 0, JSEXN_SYNTAXERR, "invalid for each loop")

View File

@ -6,6 +6,8 @@
#include "vm/Debugger-inl.h"
#include "mozilla/DebugOnly.h"
#include "jscntxt.h"
#include "jscompartment.h"
#include "jshashutil.h"
@ -338,6 +340,7 @@ Breakpoint::nextInSite()
Debugger::Debugger(JSContext *cx, JSObject *dbg)
: object(dbg), uncaughtExceptionHook(nullptr), enabled(true), trackingAllocationSites(false),
allocationsLogLength(0), maxAllocationsLogLength(DEFAULT_MAX_ALLOCATIONS_LOG_LENGTH),
frames(cx->runtime()), scripts(cx), sources(cx), objects(cx), environments(cx)
{
assertSameCompartment(cx, dbg);
@ -350,6 +353,7 @@ Debugger::Debugger(JSContext *cx, JSObject *dbg)
Debugger::~Debugger()
{
JS_ASSERT_IF(debuggees.initialized(), debuggees.empty());
emptyAllocationsLog();
/*
* Since the inactive state for this link is a singleton cycle, it's always
@ -392,6 +396,19 @@ Debugger::fromChildJSObject(JSObject *obj)
return fromJSObject(dbgobj);
}
bool
Debugger::hasMemory() const
{
return object->getReservedSlot(JSSLOT_DEBUG_MEMORY_INSTANCE).isObject();
}
DebuggerMemory &
Debugger::memory() const
{
JS_ASSERT(hasMemory());
return object->getReservedSlot(JSSLOT_DEBUG_MEMORY_INSTANCE).toObject().as<DebuggerMemory>();
}
bool
Debugger::getScriptFrameWithIter(JSContext *cx, AbstractFramePtr frame,
const ScriptFrameIter *maybeIter, MutableHandleValue vp)
@ -1439,6 +1456,61 @@ Debugger::slowPathOnNewGlobalObject(JSContext *cx, Handle<GlobalObject *> global
JS_ASSERT(!cx->isExceptionPending());
}
/* static */ bool
Debugger::slowPathOnLogAllocationSite(JSContext *cx, HandleSavedFrame frame,
GlobalObject::DebuggerVector &dbgs)
{
JS_ASSERT(!dbgs.empty());
mozilla::DebugOnly<Debugger **> begin = dbgs.begin();
for (Debugger **dbgp = dbgs.begin(); dbgp < dbgs.end(); dbgp++) {
// The set of debuggers had better not change while we're iterating,
// such that the vector gets reallocated.
JS_ASSERT(dbgs.begin() == begin);
if ((*dbgp)->trackingAllocationSites &&
(*dbgp)->enabled &&
!(*dbgp)->appendAllocationSite(cx, frame))
{
return false;
}
}
return true;
}
bool
Debugger::appendAllocationSite(JSContext *cx, HandleSavedFrame frame)
{
AutoCompartment ac(cx, object);
RootedObject wrapped(cx, frame);
if (!cx->compartment()->wrap(cx, &wrapped))
return false;
AllocationSite *allocSite = cx->new_<AllocationSite>(wrapped);
if (!allocSite)
return false;
allocationsLog.insertBack(allocSite);
if (allocationsLogLength >= maxAllocationsLogLength) {
js_delete(allocationsLog.getFirst());
} else {
allocationsLogLength++;
}
return true;
}
void
Debugger::emptyAllocationsLog()
{
while (!allocationsLog.isEmpty())
js_delete(allocationsLog.getFirst());
allocationsLogLength = 0;
}
/*** Debugger JSObjects **************************************************************************/
@ -1634,6 +1706,12 @@ Debugger::trace(JSTracer *trc)
MarkObject(trc, &frameobj, "live Debugger.Frame");
}
/*
* Mark every allocation site in our allocation log.
*/
for (AllocationSite *s = allocationsLog.getFirst(); s; s = s->getNext())
MarkObject(trc, &s->frame, "allocation log SavedFrame");
/* Trace the weak map from JSScript instances to Debugger.Script objects. */
scripts.trace(trc);

View File

@ -14,14 +14,17 @@
#include "jscntxt.h"
#include "jscompartment.h"
#include "jsweakmap.h"
#include "jswrapper.h"
#include "gc/Barrier.h"
#include "js/HashTable.h"
#include "vm/GlobalObject.h"
#include "vm/SavedStacks.h"
namespace js {
class Breakpoint;
class DebuggerMemory;
/*
* A weakmap that supports the keys being in different compartments to the
@ -161,6 +164,7 @@ class Debugger : private mozilla::LinkedListElement<Debugger>
friend class DebuggerMemory;
friend class mozilla::LinkedListElement<Debugger>;
friend bool (::JS_DefineDebuggerObject)(JSContext *cx, JS::HandleObject obj);
friend bool SavedStacksMetadataCallback(JSContext *cx, JSObject **pmetadata);
public:
enum Hook {
@ -190,9 +194,25 @@ class Debugger : private mozilla::LinkedListElement<Debugger>
GlobalObjectSet debuggees; /* Debuggee globals. Cross-compartment weak references. */
js::HeapPtrObject uncaughtExceptionHook; /* Strong reference. */
bool enabled;
bool trackingAllocationSites;
JSCList breakpoints; /* Circular list of all js::Breakpoints in this debugger */
struct AllocationSite : public mozilla::LinkedListElement<AllocationSite>
{
AllocationSite(HandleObject frame) : frame(frame) {
JS_ASSERT(UncheckedUnwrap(frame)->is<SavedFrame>());
};
RelocatablePtrObject frame;
};
typedef mozilla::LinkedList<AllocationSite> AllocationSiteList;
bool trackingAllocationSites;
AllocationSiteList allocationsLog;
size_t allocationsLogLength;
size_t maxAllocationsLogLength;
static const size_t DEFAULT_MAX_ALLOCATIONS_LOG_LENGTH = 5000;
bool appendAllocationSite(JSContext *cx, HandleSavedFrame frame);
void emptyAllocationsLog();
/*
* If this Debugger is enabled, and has a onNewGlobalObject handler, then
* this link is inserted into the circular list headed by
@ -359,6 +379,8 @@ class Debugger : private mozilla::LinkedListElement<Debugger>
static void slowPathOnNewScript(JSContext *cx, HandleScript script,
GlobalObject *compileAndGoGlobal);
static void slowPathOnNewGlobalObject(JSContext *cx, Handle<GlobalObject *> global);
static bool slowPathOnLogAllocationSite(JSContext *cx, HandleSavedFrame frame,
GlobalObject::DebuggerVector &dbgs);
static JSTrapStatus dispatchHook(JSContext *cx, MutableHandleValue vp, Hook which);
JSTrapStatus fireDebuggerStatement(JSContext *cx, MutableHandleValue vp);
@ -408,6 +430,9 @@ class Debugger : private mozilla::LinkedListElement<Debugger>
static inline Debugger *fromJSObject(JSObject *obj);
static Debugger *fromChildJSObject(JSObject *obj);
bool hasMemory() const;
DebuggerMemory &memory() const;
/*********************************** Methods for interaction with the GC. */
/*
@ -441,6 +466,7 @@ class Debugger : private mozilla::LinkedListElement<Debugger>
static inline void onNewScript(JSContext *cx, HandleScript script,
GlobalObject *compileAndGoGlobal);
static inline void onNewGlobalObject(JSContext *cx, Handle<GlobalObject *> global);
static inline bool onLogAllocationSite(JSContext *cx, HandleSavedFrame frame);
static JSTrapStatus onTrap(JSContext *cx, MutableHandleValue vp);
static JSTrapStatus onSingleStep(JSContext *cx, MutableHandleValue vp);
static bool handleBaselineOsr(JSContext *cx, InterpreterFrame *from, jit::BaselineFrame *to);
@ -758,6 +784,15 @@ Debugger::onNewGlobalObject(JSContext *cx, Handle<GlobalObject *> global)
Debugger::slowPathOnNewGlobalObject(cx, global);
}
bool
Debugger::onLogAllocationSite(JSContext *cx, HandleSavedFrame frame)
{
GlobalObject::DebuggerVector *dbgs = frame->global().getDebuggers();
if (!dbgs || dbgs->empty())
return true;
return Debugger::slowPathOnLogAllocationSite(cx, frame, *dbgs);
}
extern bool
EvaluateInEnv(JSContext *cx, Handle<Env*> env, HandleValue thisv, AbstractFramePtr frame,
mozilla::Range<const jschar> chars, const char *filename, unsigned lineno,

View File

@ -7,6 +7,7 @@
#include "vm/DebuggerMemory.h"
#include "jscompartment.h"
#include "gc/Marking.h"
#include "vm/Debugger.h"
#include "vm/GlobalObject.h"
#include "vm/SavedStacks.h"
@ -31,6 +32,13 @@ DebuggerMemory::create(JSContext *cx, Debugger *dbg)
return &memory->as<DebuggerMemory>();
}
Debugger *
DebuggerMemory::getDebugger()
{
const Value &dbgVal = getReservedSlot(JSSLOT_DEBUGGER);
return Debugger::fromJSObject(&dbgVal.toObject());
}
/* static */ bool
DebuggerMemory::construct(JSContext *cx, unsigned argc, Value *vp)
{
@ -51,12 +59,6 @@ DebuggerMemory::construct(JSContext *cx, unsigned argc, Value *vp)
JS_EnumerateStub, // enumerate
JS_ResolveStub, // resolve
JS_ConvertStub, // convert
nullptr, // finalize
nullptr, // call
nullptr, // hasInstance
nullptr, // construct
nullptr // trace
};
/* static */ DebuggerMemory *
@ -108,12 +110,6 @@ DebuggerMemory::checkThis(JSContext *cx, CallArgs &args, const char *fnName)
if (!memory) \
return false
Debugger *
DebuggerMemory::getDebugger()
{
return Debugger::fromJSObject(&getReservedSlot(JSSLOT_DEBUGGER).toObject());
}
/* static */ bool
DebuggerMemory::setTrackingAllocationSites(JSContext *cx, unsigned argc, Value *vp)
{
@ -149,6 +145,9 @@ DebuggerMemory::setTrackingAllocationSites(JSContext *cx, unsigned argc, Value *
}
}
if (!enabling)
dbg->emptyAllocationsLog();
dbg->trackingAllocationSites = enabling;
args.rval().setUndefined();
return true;
@ -162,11 +161,81 @@ DebuggerMemory::getTrackingAllocationSites(JSContext *cx, unsigned argc, Value *
return true;
}
/* static */ bool
DebuggerMemory::drainAllocationsLog(JSContext *cx, unsigned argc, Value *vp)
{
THIS_DEBUGGER_MEMORY(cx, argc, vp, "drainAllocationsLog", args, memory);
Debugger* dbg = memory->getDebugger();
if (!dbg->trackingAllocationSites) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_NOT_TRACKING_ALLOCATIONS,
"drainAllocationsLog");
return false;
}
size_t length = dbg->allocationsLogLength;
RootedObject result(cx, NewDenseAllocatedArray(cx, length));
if (!result)
return false;
result->ensureDenseInitializedLength(cx, 0, length);
for (size_t i = 0; i < length; i++) {
Debugger::AllocationSite *allocSite = dbg->allocationsLog.popFirst();
result->setDenseElement(i, ObjectValue(*allocSite->frame));
js_delete(allocSite);
}
dbg->allocationsLogLength = 0;
args.rval().setObject(*result);
return true;
}
/* static */ bool
DebuggerMemory::getMaxAllocationsLogLength(JSContext *cx, unsigned argc, Value *vp)
{
THIS_DEBUGGER_MEMORY(cx, argc, vp, "(get maxAllocationsLogLength)", args, memory);
args.rval().setInt32(memory->getDebugger()->maxAllocationsLogLength);
return true;
}
/* static */ bool
DebuggerMemory::setMaxAllocationsLogLength(JSContext *cx, unsigned argc, Value *vp)
{
THIS_DEBUGGER_MEMORY(cx, argc, vp, "(set maxAllocationsLogLength)", args, memory);
if (!args.requireAtLeast(cx, "(set maxAllocationsLogLength)", 1))
return false;
int32_t max;
if (!ToInt32(cx, args[0], &max))
return false;
if (max < 1) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_UNEXPECTED_TYPE,
"(set maxAllocationsLogLength)'s parameter",
"not a positive integer");
return false;
}
Debugger *dbg = memory->getDebugger();
dbg->maxAllocationsLogLength = max;
while (dbg->allocationsLogLength > dbg->maxAllocationsLogLength) {
js_delete(dbg->allocationsLog.getFirst());
dbg->allocationsLogLength--;
}
args.rval().setUndefined();
return true;
}
/* static */ const JSPropertySpec DebuggerMemory::properties[] = {
JS_PSGS("trackingAllocationSites", getTrackingAllocationSites, setTrackingAllocationSites, 0),
JS_PSGS("maxAllocationsLogLength", getMaxAllocationsLogLength, setMaxAllocationsLogLength, 0),
JS_PS_END
};
/* static */ const JSFunctionSpec DebuggerMemory::methods[] = {
JS_FN("drainAllocationsLog", DebuggerMemory::drainAllocationsLog, 0, 0),
JS_FS_END
};

View File

@ -37,6 +37,9 @@ class DebuggerMemory : public JSObject {
static bool setTrackingAllocationSites(JSContext *cx, unsigned argc, Value *vp);
static bool getTrackingAllocationSites(JSContext *cx, unsigned argc, Value *vp);
static bool drainAllocationsLog(JSContext *cx, unsigned argc, Value *vp);
static bool setMaxAllocationsLogLength(JSContext*cx, unsigned argc, Value *vp);
static bool getMaxAllocationsLogLength(JSContext*cx, unsigned argc, Value *vp);
};
} /* namespace js */

View File

@ -14,6 +14,7 @@
#include "gc/Marking.h"
#include "js/Vector.h"
#include "vm/Debugger.h"
#include "vm/GlobalObject.h"
#include "vm/StringBuffer.h"
@ -734,7 +735,8 @@ SavedStacksMetadataCallback(JSContext *cx, JSObject **pmetadata)
if (!cx->compartment()->savedStacks().saveCurrentStack(cx, &frame))
return false;
*pmetadata = frame;
return true;
return Debugger::onLogAllocationSite(cx, frame);
}
#ifdef JS_CRASH_DIAGNOSTICS

View File

@ -330,8 +330,8 @@ inDOMView::GetCellProperties(int32_t row, nsITreeColumn* col,
#ifdef ACCESSIBILITY
if (mShowAccessibleNodes) {
nsCOMPtr<nsIAccessibilityService> accService(
do_GetService("@mozilla.org/accessibilityService;1"));
nsCOMPtr<nsIAccessibilityService> accService =
services::GetAccessibilityService();
NS_ENSURE_TRUE(accService, NS_ERROR_FAILURE);
nsCOMPtr<nsIAccessible> accessible;

View File

@ -64,7 +64,7 @@ fuzzy(1,139) fuzzy-if(OSX,2,4478) == border-image-radial-gradient-slice-fill-2.h
fuzzy(1,9000) == border-image-radial-gradient-slice-width.html border-image-radial-gradient-slice-width-ref.html
# OS X failures tracked in bug 957025
fails-if(OSX) == border-image-repeating-linear-gradient.html border-image-repeating-linear-gradient-ref.html
== border-image-repeating-linear-gradient.html border-image-repeating-linear-gradient-ref.html
fuzzy(1,5608) fails-if(OSX) == border-image-repeating-linear-gradient-slice-fill-2.html border-image-repeating-linear-gradient-slice-fill-2-ref.html
fuzzy(1,19200) fails-if(OSX) == border-image-repeating-linear-gradient-repeat-round-2.html border-image-repeating-linear-gradient-repeat-round-2-ref.html
@ -75,7 +75,7 @@ fuzzy(1,1357) fails-if(OSX) == border-image-repeating-radial-gradient-slice-fill
fuzzy(1,1058) fails-if(OSX) == border-image-repeating-radial-gradient-slice-fill-2.html border-image-repeating-radial-gradient-slice-fill-2-ref.html
fuzzy(1,602) fails-if(OSX) == border-image-repeating-radial-gradient-width.html border-image-repeating-radial-gradient-width-ref.html
fuzzy(3,18000) fails-if(OSX) == border-image-repeating-radial-gradient-slice-width.html border-image-repeating-radial-gradient-slice-width-ref.html
fails-if(OSX) == border-image-repeating-radial-gradient-repeat-repeat-2.html border-image-repeating-radial-gradient-repeat-repeat-2-ref.html
== border-image-repeating-radial-gradient-repeat-repeat-2.html border-image-repeating-radial-gradient-repeat-repeat-2-ref.html
fuzzy(1,1054) fails-if(OSX) == border-image-repeating-radial-gradient-repeat-round-2.html border-image-repeating-radial-gradient-repeat-round-2-ref.html
# border-image-source (-moz-)element

View File

@ -0,0 +1,20 @@
<!DOCTYPE html>
<html lang="en">
<meta charset="utf-8">
<title>Choose the correct gradient repeat count even when there's a non-identity pattern matrix</title>
<style>
html {
overflow: hidden;
}
div {
width: 30px;
height: 40px;
background-image: repeating-linear-gradient(-36.8698976deg, blue, blue 5px, lime 5px, lime 10px);
}
</style>
<div></div>

View File

@ -0,0 +1,27 @@
<!DOCTYPE html>
<html lang="en">
<meta charset="utf-8">
<title>Choose the correct gradient repeat count even when there's a non-identity pattern matrix</title>
<style>
html {
overflow: hidden;
}
div {
box-sizing: border-box;
width: 240px;
height: 320px;
/* Scale a 240x320 gradient down by a factor of 8 into a 30x40 border image. */
/* 240x320 gives a diagonal of 400px, so we should get 5 repetitions of a 80px long gradient. */
/* tan(36.8698976deg) == 240 / 320 */
border-left: 30px solid;
border-top: 40px solid;
border-image: repeating-linear-gradient(-36.8698976deg, blue, blue 40px, lime 40px, lime 80px);
}
</style>
<div></div>

View File

@ -1820,3 +1820,4 @@ pref(browser.display.use_document_fonts,0) == 1022481-1.html 1022481-1-ref.html
== 1024473-1.html 1024473-1-ref.html
== 1042104-1.html 1042104-1-ref.html
== 1044198-1.html 1044198-1-ref.html
== 1049499-1.html 1049499-1-ref.html

View File

@ -64,6 +64,7 @@ nsSliderFrame::nsSliderFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
nsBoxFrame(aPresShell, aContext),
mCurPos(0),
mChange(0),
mDragFinished(true),
mUserChanged(false)
{
}
@ -417,6 +418,11 @@ nsSliderFrame::HandleEvent(nsPresContext* aPresContext,
return NS_OK;
}
if (!mDragFinished && !isDraggingThumb()) {
StopDrag();
return NS_OK;
}
nsIFrame* scrollbarBox = GetScrollbar();
nsCOMPtr<nsIContent> scrollbar;
scrollbar = GetContentOfBox(scrollbarBox);
@ -487,13 +493,7 @@ nsSliderFrame::HandleEvent(nsPresContext* aPresContext,
case NS_TOUCH_END:
case NS_MOUSE_BUTTON_UP:
if (ShouldScrollForEvent(aEvent)) {
// stop capturing
AddListener();
DragThumb(false);
if (mChange) {
StopRepeat();
mChange = 0;
}
StopDrag();
//we MUST call nsFrame HandleEvent for mouse ups to maintain the selection state and capture state.
return nsFrame::HandleEvent(aPresContext, aEvent, aEventStatus);
}
@ -876,9 +876,23 @@ nsSliderFrame::StartDrag(nsIDOMEvent* aEvent)
return NS_OK;
}
nsresult
nsSliderFrame::StopDrag()
{
AddListener();
DragThumb(false);
if (mChange) {
StopRepeat();
mChange = 0;
}
return NS_OK;
}
void
nsSliderFrame::DragThumb(bool aGrabMouseEvents)
{
mDragFinished = !aGrabMouseEvents;
// inform the parent <scale> that a drag is beginning or ending
nsIFrame* parent = GetParent();
if (parent) {

View File

@ -97,6 +97,7 @@ public:
nsIFrame* aOldFrame) MOZ_OVERRIDE;
nsresult StartDrag(nsIDOMEvent* aEvent);
nsresult StopDrag();
static int32_t GetCurrentPosition(nsIContent* content);
static int32_t GetMinPosition(nsIContent* content);
@ -173,6 +174,8 @@ private:
nscoord mChange;
bool mDragFinished;
// true if an attribute change has been caused by the user manipulating the
// slider. This allows notifications to tell how a slider's current position
// was changed.

View File

@ -515,7 +515,6 @@ main(int argc, char * argv[])
test_init_destroy_multiple_contexts();
test_init_destroy_stream();
test_init_destroy_multiple_streams();
test_init_destroy_multiple_contexts_and_streams();
test_basic_stream_operations();
test_stream_position();
@ -525,6 +524,8 @@ main(int argc, char * argv[])
* and is not documented as a possible return value for this call. Hence, we
* try to limit the number of streams we create in this test. */
if (!is_windows_7()) {
test_init_destroy_multiple_contexts_and_streams();
delay_callback = 0;
test_init_start_stop_destroy_multiple_streams(0, 0);
test_init_start_stop_destroy_multiple_streams(1, 0);

View File

@ -10,8 +10,12 @@
SimpleTest.waitForExplicitFinish();
function onWindowLoad()
{
function onWindowLoad() {
SpecialPowers.pushPrefEnv({"set": [["dom.unsafe_legacy_crypto.enabled", true]]},
runTest);
}
function runTest() {
// Does it work at all?
try {
var crmfObject = crypto.generateCRMFRequest("CN=undefined", "regToken",

View File

@ -83,6 +83,8 @@ skip-if = os == "win" # Intermittent failures, bug 919016
[test_bug585946.xul]
[test_bug624329.xul]
[test_bug792324.xul]
[test_bug1048178.xul]
skip-if = toolkit == "cocoa"
[test_button.xul]
[test_closemenu_attribute.xul]
[test_colorpicker_popup.xul]

View File

@ -0,0 +1,86 @@
<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" type="text/css"?>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=1048178
-->
<window title="Mozilla Bug 1048178"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"/>
<!-- test results are displayed in the html:body -->
<body xmlns="http://www.w3.org/1999/xhtml"/>
<a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1048178"
target="_blank">Mozilla Bug 1048178</a>
<hbox>
<scrollbar id="scroller"
orient="horizontal"
curpos="0"
maxpos="500"
pageincrement="500"
width="500"
style="margin:0"/>
</hbox>
<!-- test code goes here -->
<script type="application/javascript"><![CDATA[
/** Test for Bug 1048178 **/
var scrollbarTester = {
scrollbar: null,
startTest: function() {
this.scrollbar = $("scroller");
this.setScrollToClick(false);
this.testThumbDragging();
SimpleTest.finish();
},
testThumbDragging: function() {
var x = 400; // on the right half of the scroolbar
var y = 5;
this.mousedown(x, y, 0);
this.mousedown(x, y, 2);
this.mouseup(x, y, 2);
this.mouseup(x, y, 0);
var newPos = this.getPos(); // sould be '500'
this.mousedown(x, y, 0);
this.mousemove(x-1, y, 0);
this.mouseup(x-1, y, 0);
var newPos2 = this.getPos();
ok(newPos2 < newPos,
"Scrollbar thumb should follow the mouse when dragged.");
},
setScrollToClick: function(value) {
var prefService = Components.classes["@mozilla.org/preferences-service;1"]
.getService(Components.interfaces.nsIPrefService);
var uiBranch = prefService.getBranch("ui.");
uiBranch.setIntPref("scrollToClick", value ? 1 : 0);
},
getPos: function() {
return this.scrollbar.getAttribute("curpos");
},
mousedown: function(x, y, button) {
synthesizeMouse(this.scrollbar, x, y, { type: "mousedown", 'button': button });
},
mousemove: function(x, y, button) {
synthesizeMouse(this.scrollbar, x, y, { type: "mousemove", 'button': button });
},
mouseup: function(x, y, button) {
synthesizeMouse(this.scrollbar, x, y, { type: "mouseup", 'button': button });
}
}
function doTest() {
setTimeout(function() { scrollbarTester.startTest(); }, 0);
}
SimpleTest.waitForExplicitFinish();
addLoadEvent(doTest);
]]></script>
</window>

View File

@ -4,11 +4,12 @@
# 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/.
import sys, subprocess
import sys, subprocess, os
def NMSymbolicate(library, addresses):
target_tools_prefix = os.environ.get("TARGET_TOOLS_PREFIX", "")
args = [
"nm", "-D", "-S", library
target_tools_prefix + "nm", "-D", "-S", library
]
nm_lines = subprocess.check_output(args).split("\n")
symbol_table = []

View File

@ -47,6 +47,8 @@ nsSystemStatusBarCocoa::RemoveItem(nsIDOMElement* aDOMElement)
nsSystemStatusBarCocoa::StatusItem::StatusItem(nsStandaloneNativeMenu* aMenu)
: mMenu(aMenu)
{
MOZ_COUNT_CTOR(nsSystemStatusBarCocoa::StatusItem);
NSMenu* nativeMenu = nil;
mMenu->GetNativeMenu(reinterpret_cast<void**>(&nativeMenu));
@ -67,4 +69,6 @@ nsSystemStatusBarCocoa::StatusItem::~StatusItem()
[[NSStatusBar systemStatusBar] removeStatusItem:mStatusItem];
[mStatusItem release];
mStatusItem = nil;
MOZ_COUNT_DTOR(nsSystemStatusBarCocoa::StatusItem);
}

View File

@ -5882,7 +5882,7 @@ nsWindow::DispatchEventToRootAccessible(uint32_t aEventType)
}
nsCOMPtr<nsIAccessibilityService> accService =
do_GetService("@mozilla.org/accessibilityService;1");
services::GetAccessibilityService();
if (!accService) {
return;
}

View File

@ -67,6 +67,8 @@ skip-if = toolkit != "cocoa"
skip-if = toolkit != "cocoa"
[test_native_key_bindings_mac.html]
skip-if = toolkit != "cocoa"
[test_system_status_bar.xul]
skip-if = toolkit != "cocoa"
# Windows
# taskbar_previews.xul

View File

@ -0,0 +1,57 @@
<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
type="text/css"?>
<window title="Testing composition, text and query content events"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
<body xmlns="http://www.w3.org/1999/xhtml">
<div id="content" style="display: none">
</div>
<pre id="test">
</pre>
</body>
<menupopup id="menuContainer">
<menu id="menu1" image="data:image/svg+xml,&lt;svg%20xmlns=&quot;http://www.w3.org/2000/svg&quot;%20width=&quot;32&quot;%20height=&quot;32&quot;>&lt;circle%20cx=&quot;16&quot;%20cy=&quot;16&quot;%20r=&quot;16&quot;/>&lt;/svg>">
<menupopup>
<menuitem label="Item 1 in menu 1"/>
<menuitem label="Item 2 in menu 1"/>
</menupopup>
</menu>
<menu id="menu2" image="data:image/svg+xml,&lt;svg%20xmlns=&quot;http://www.w3.org/2000/svg&quot;%20width=&quot;32&quot;%20height=&quot;32&quot;>&lt;path%20d=&quot;M0 16 L 16 0 L 32 16 L 16 32 Z&quot;/>&lt;/svg>">
<menupopup>
<menuitem label="Item 1 in menu 2"/>
<menuitem label="Item 2 in menu 2"/>
</menupopup>
</menu>
</menupopup>
<script class="testbody" type="application/javascript">
<![CDATA[
let Cc = Components.classes;
let Ci = Components.interfaces;
let systemStatusBar = Cc["@mozilla.org/widget/macsystemstatusbar;1"].getService(Ci.nsISystemStatusBar);
ok(systemStatusBar, "should have got an nsISystemStatusBar instance");
let menu1 = document.getElementById("menu1");
let menu2 = document.getElementById("menu2");
// Add and remove the item, just to get basic leak testing coverage.
systemStatusBar.addItem(menu1);
systemStatusBar.removeItem(menu1);
// Make sure that calling addItem twice with the same element doesn't leak.
systemStatusBar.addItem(menu2);
systemStatusBar.addItem(menu2);
systemStatusBar.removeItem(menu2);
]]>
</script>
</window>