Merge autoland to central, a=merge

MozReview-Commit-ID: AFEWjI3UWey
This commit is contained in:
Wes Kocher 2017-02-01 16:07:09 -08:00
Родитель 13f287296e 5b55368eda
Коммит 0af59511ea
86 изменённых файлов: 953 добавлений и 205 удалений

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

@ -6,6 +6,7 @@ module.exports = {
],
"rules": {
"no-shadow": "error"
"no-shadow": "error",
"no-undef": "off"
}
};

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

@ -351,6 +351,9 @@
function initPageCertError() {
document.body.className = "certerror";
document.title = document.getElementById("certErrorPageTitle").textContent;
for (let host of document.querySelectorAll(".hostname")) {
host.textContent = document.location.hostname;
}
setupAdvancedButton(true);

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

@ -175,7 +175,9 @@ var StarUI = {
}
clearTimeout(this._autoCloseTimer);
this._autoCloseTimer = setTimeout(() => {
this.panel.hidePopup();
if (!this.panel.mozMatchesSelector(":hover")) {
this.panel.hidePopup();
}
}, delay);
}
break;

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

@ -217,7 +217,7 @@ add_task(function* checkWrongSystemTimeWarning() {
});
add_task(function* checkAdvancedDetails() {
info("Loading a bad cert page and verifying the advanced details section");
info("Loading a bad cert page and verifying the main error and advanced details section");
let browser;
let certErrorLoaded;
yield BrowserTestUtils.openNewForegroundTab(gBrowser, () => {
@ -231,6 +231,11 @@ add_task(function* checkAdvancedDetails() {
let message = yield ContentTask.spawn(browser, null, function* () {
let doc = content.document;
let shortDescText = doc.getElementById("errorShortDescText");
info("Main error text: " + shortDescText.textContent);
ok(shortDescText.textContent.includes("expired.example.com"),
"Should list hostname in error message.");
let advancedButton = doc.getElementById("advancedButton");
advancedButton.click();
let el = doc.getElementById("errorCode");

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

@ -11,6 +11,7 @@
let bookmarkPanel = document.getElementById("editBookmarkPanel");
let bookmarkStar = document.getElementById("bookmarks-menu-button");
let bookmarkPanelTitle = document.getElementById("editBookmarkPanelTitle");
let editBookmarkPanelRemoveButtonRect;
StarUI._closePanelQuickForTesting = true;
@ -34,6 +35,9 @@ function* test_bookmarks_popup({isNewBookmark, popupShowFn, popupEditFn,
yield shownPromise;
is(bookmarkPanel.state, "open", "Panel should be 'open' after shownPromise is resolved");
editBookmarkPanelRemoveButtonRect =
document.getElementById("editBookmarkPanelRemoveButton").getBoundingClientRect();
if (popupEditFn) {
yield popupEditFn();
}
@ -363,6 +367,32 @@ add_task(function* enter_on_remove_bookmark_should_remove_bookmark() {
});
});
add_task(function* mouse_hovering_panel_should_prevent_autoclose() {
if (AppConstants.platform != "win") {
// This test requires synthesizing native mouse movement which is
// best supported on Windows.
return;
}
yield test_bookmarks_popup({
isNewBookmark: true,
*popupShowFn(browser) {
yield new Promise(resolve => {
EventUtils.synthesizeNativeMouseMove(
document.documentElement,
editBookmarkPanelRemoveButtonRect.left,
editBookmarkPanelRemoveButtonRect.top,
resolve);
});
EventUtils.synthesizeKey("D", {accelKey: true}, window);
},
shouldAutoClose: false,
popupHideFn() {
document.getElementById("editBookmarkPanelRemoveButton").click();
},
isBookmarkRemoved: true,
});
});
registerCleanupFunction(function() {
delete StarUI._closePanelQuickForTesting;
})

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

@ -48,6 +48,14 @@ let whitelist = [
isFromDevTools: false},
];
if (!Services.prefs.getBoolPref("full-screen-api.unprefix.enabled")) {
whitelist.push({
sourceName: /res\/(ua|html)\.css$/i,
errorMessage: /Unknown pseudo-class .*\bfullscreen\b/i,
isFromDevTools: false
});
}
// Platform can be "linux", "macosx" or "win". If omitted, the exception applies to all platforms.
let allowedImageReferences = [
// Bug 1302691

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

@ -3,5 +3,4 @@ support-files =
head.js
[browser_identityBlock_focus.js]
skip-if = os == 'mac' # Bug 1334418 (try only)
support-files = ../general/permissions.html

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

@ -14,6 +14,7 @@ function synthesizeKeyAndWaitForFocus(element, keyCode, options) {
// Checks that the identity block is the next element after the urlbar
// to be focused if there are no active notification anchors.
add_task(function* testWithoutNotifications() {
yield SpecialPowers.pushPrefEnv({"set": [["accessibility.tabfocus", 7]]});
yield BrowserTestUtils.withNewTab("https://example.com", function*() {
yield synthesizeKeyAndWaitForFocus(gURLBar, "l", {accelKey: true})
is(document.activeElement, gURLBar.inputField, "urlbar should be focused");
@ -26,7 +27,7 @@ add_task(function* testWithoutNotifications() {
// Checks that when there is a notification anchor, it will receive
// focus before the identity block.
add_task(function* testWithoutNotifications() {
yield SpecialPowers.pushPrefEnv({"set": [["accessibility.tabfocus", 7]]});
yield BrowserTestUtils.withNewTab(PERMISSIONS_PAGE, function*(browser) {
let popupshown = BrowserTestUtils.waitForEvent(PopupNotifications.panel, "popupshown");
// Request a permission;
@ -46,6 +47,7 @@ add_task(function* testWithoutNotifications() {
// Checks that with invalid pageproxystate the identity block is ignored.
add_task(function* testInvalidPageProxyState() {
yield SpecialPowers.pushPrefEnv({"set": [["accessibility.tabfocus", 7]]});
yield BrowserTestUtils.withNewTab("about:blank", function*(browser) {
// Loading about:blank will automatically focus the urlbar, which, however, can
// race with the test code. So we only send the shortcut if the urlbar isn't focused yet.

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

@ -2124,7 +2124,7 @@
<handler event="mousedown"><![CDATA[
let target = event.originalTarget;
if (!target.classList.contains("searchbar-engine-one-off-item")) {
if (target.getAttribute("anonid") == "addengine-menu-button") {
return;
}
// Required to receive click events from the buttons on Linux.

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

@ -343,6 +343,7 @@ this.ExtensionsUI = {
let options = {
hideClose: true,
timeout: Date.now() + 30000,
popupIconURL: addon.iconURL || DEFAULT_EXTENSION_ICON,
eventCallback(topic) {
if (topic == "showing") {

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

@ -14,6 +14,8 @@ const {gDevTools} = require("devtools/client/framework/devtools");
const {LocalizationHelper} = require("devtools/shared/l10n");
const L10N = new LocalizationHelper("devtools/client/locales/toolbox.properties");
loader.lazyRequireGetter(this, "system", "devtools/shared/system");
exports.OptionsPanel = OptionsPanel;
function GetPref(name) {
@ -91,6 +93,7 @@ OptionsPanel.prototype = {
this.setupToolsList();
this.setupToolbarButtonsList();
this.setupThemeList();
this.setupNightlyOptions();
yield this.populatePreferences();
this.isReady = true;
this.emit("ready");
@ -302,6 +305,55 @@ OptionsPanel.prototype = {
this.updateCurrentTheme();
},
/**
* Add common preferences enabled only on Nightly.
*/
setupNightlyOptions: function () {
let isNightly = system.constants.NIGHTLY_BUILD;
if (!isNightly) {
return;
}
// Labels for these new buttons are nightly only and mostly intended for working on
// devtools. They should not be localized.
let prefDefinitions = [{
pref: "devtools.webconsole.new-frontend-enabled",
label: "Enable new console frontend",
id: "devtools-new-webconsole",
parentId: "webconsole-options"
}, {
pref: "devtools.debugger.new-debugger-frontend",
label: "Enable new debugger frontend",
id: "devtools-new-debugger",
parentId: "debugger-options"
}];
let createPreferenceOption = ({pref, label, id}) => {
let inputLabel = this.panelDoc.createElement("label");
let checkbox = this.panelDoc.createElement("input");
checkbox.setAttribute("type", "checkbox");
if (GetPref(pref)) {
checkbox.setAttribute("checked", "checked");
}
checkbox.setAttribute("id", id);
checkbox.addEventListener("change", e => {
SetPref(pref, e.target.checked);
});
let inputSpanLabel = this.panelDoc.createElement("span");
inputSpanLabel.textContent = label;
inputLabel.appendChild(checkbox);
inputLabel.appendChild(inputSpanLabel);
return inputLabel;
};
for (let prefDefinition of prefDefinitions) {
let parent = this.panelDoc.getElementById(prefDefinition.parentId);
parent.appendChild(createPreferenceOption(prefDefinition));
}
},
populatePreferences: function () {
let prefCheckboxes = this.panelDoc.querySelectorAll(
"input[type=checkbox][data-pref]");

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

@ -2023,6 +2023,12 @@ Element::GetInlineStyleDeclaration() const
return nullptr;
}
const nsMappedAttributes*
Element::GetMappedAttributes() const
{
return mAttrsAndChildren.GetMapped();
}
nsresult
Element::SetInlineStyleDeclaration(DeclarationBlock* aDeclaration,
const nsAString* aSerialized,

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

@ -281,6 +281,11 @@ public:
*/
DeclarationBlock* GetInlineStyleDeclaration() const;
/**
* Get the mapped attributes, if any, for this element.
*/
const nsMappedAttributes* GetMappedAttributes() const;
/**
* Set the inline style declaration for this element. This will send
* an appropriate AttributeChanged notification if aNotify is true.

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

@ -772,6 +772,11 @@ nsAttrAndChildArray::MakeMappedUnique(nsMappedAttributes* aAttributes)
return NS_OK;
}
const nsMappedAttributes*
nsAttrAndChildArray::GetMapped() const
{
return mImpl ? mImpl->mMappedAttrs : nullptr;
}
bool
nsAttrAndChildArray::GrowBy(uint32_t aGrowSize)

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

@ -134,6 +134,7 @@ public:
{
return MappedAttrCount();
}
const nsMappedAttributes* GetMapped() const;
private:
nsAttrAndChildArray(const nsAttrAndChildArray& aOther) = delete;

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

@ -12,8 +12,10 @@
#include "nsMappedAttributes.h"
#include "nsHTMLStyleSheet.h"
#include "nsRuleWalker.h"
#include "nsRuleData.h"
#include "mozilla/HashFunctions.h"
#include "mozilla/MemoryReporting.h"
#include "mozilla/ServoDeclarationBlock.h"
using namespace mozilla;
@ -21,14 +23,18 @@ nsMappedAttributes::nsMappedAttributes(nsHTMLStyleSheet* aSheet,
nsMapRuleToAttributesFunc aMapRuleFunc)
: mAttrCount(0),
mSheet(aSheet),
mRuleMapper(aMapRuleFunc)
mRuleMapper(aMapRuleFunc),
mServoStyle(nullptr)
{
}
nsMappedAttributes::nsMappedAttributes(const nsMappedAttributes& aCopy)
: mAttrCount(aCopy.mAttrCount),
mSheet(aCopy.mSheet),
mRuleMapper(aCopy.mRuleMapper)
mRuleMapper(aCopy.mRuleMapper),
// This is only called by ::Clone, which is used to create independent
// nsMappedAttributes objects which should not share a ServoDeclarationBlock
mServoStyle(nullptr)
{
NS_ASSERTION(mBufferSize >= aCopy.mAttrCount, "can't fit attributes");
@ -281,3 +287,20 @@ nsMappedAttributes::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
return n;
}
void
nsMappedAttributes::LazilyResolveServoDeclaration(nsRuleData* aRuleData,
nsCSSPropertyID* aIndexToIdMapping,
size_t aRuleDataSize)
{
MapRuleInfoInto(aRuleData);
MOZ_ASSERT(!mServoStyle,
"LazilyResolveServoDeclaration should not be called if mServoStyle is already set");
mServoStyle = Servo_DeclarationBlock_CreateEmpty().Consume();
for (size_t i = 0; i < aRuleDataSize; i++) {
nsCSSValue& val = aRuleData->mValueStorage[i];
if (val.GetUnit() != eCSSUnit_Null) {
Servo_DeclarationBlock_AddPresValue(mServoStyle.get(), aIndexToIdMapping[i], &val);
}
}
}

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

@ -16,6 +16,7 @@
#include "nsMappedAttributeElement.h"
#include "nsIStyleRule.h"
#include "mozilla/Attributes.h"
#include "mozilla/ServoBindings.h"
#include "mozilla/MemoryReporting.h"
class nsIAtom;
@ -70,9 +71,27 @@ public:
void RemoveAttrAt(uint32_t aPos, nsAttrValue& aValue);
const nsAttrName* GetExistingAttrNameFromQName(const nsAString& aName) const;
int32_t IndexOfAttr(nsIAtom* aLocalName) const;
// nsIStyleRule
// Apply the contained mapper to an empty nsRuleData object
// that is able to contain all properties. Set contained servo declaration block
// to result of this computation.
// aIndexToIdMapping is
// a table that maps from an index in the rule data to the corresponding
// property ID. aRuleDataSize is the length of the backing storage
// of the rule data.
void LazilyResolveServoDeclaration(nsRuleData* aRuleData,
nsCSSPropertyID* aIndexToIdMapping,
size_t aRuleDataSize);
// Obtain the contained servo declaration block
// May return null if called before the inner block
// has been (lazily) resolved
const RefPtr<RawServoDeclarationBlock>& GetServoStyle() const
{
return mServoStyle;
}
// nsIStyleRule
virtual void MapRuleInfoInto(nsRuleData* aRuleData) override;
virtual bool MightMapInheritedStyleData() override;
virtual bool GetDiscretelyAnimatedCSSValue(nsCSSPropertyID aProperty,
@ -115,6 +134,7 @@ private:
#endif
nsHTMLStyleSheet* mSheet; //weak
nsMapRuleToAttributesFunc mRuleMapper;
RefPtr<RawServoDeclarationBlock> mServoStyle;
void* mAttrs[1];
};

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

@ -120,19 +120,6 @@ IsWebkitPrefixSupportEnabled()
return sIsWebkitPrefixSupportEnabled;
}
static bool
IsPrefixedPointerLockEnabled()
{
static bool sIsPrefixedPointerLockEnabled;
static bool sIsPrefCached = false;
if (!sIsPrefCached) {
sIsPrefCached = true;
Preferences::AddBoolVarCache(&sIsPrefixedPointerLockEnabled,
"pointer-lock-api.prefixed.enabled");
}
return sIsPrefixedPointerLockEnabled;
}
EventListenerManagerBase::EventListenerManagerBase()
: mNoListenerForEvent(eVoidEvent)
, mMayHavePaintEventListener(false)
@ -1164,14 +1151,6 @@ EventListenerManager::GetLegacyEventMessage(EventMessage aEventMessage) const
return eWebkitAnimationIteration;
}
}
if (IsPrefixedPointerLockEnabled()) {
if (aEventMessage == ePointerLockChange) {
return eMozPointerLockChange;
}
if (aEventMessage == ePointerLockError) {
return eMozPointerLockError;
}
}
}
switch (aEventMessage) {

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

@ -791,7 +791,7 @@ MediaFormatReader::MediaFormatReader(AbstractMediaDecoder* aDecoder,
Preferences::GetUint("media.audio-max-decode-error", 3))
, mVideo(this, MediaData::VIDEO_DATA,
Preferences::GetUint("media.video-max-decode-error", 2))
, mDemuxer(new DemuxerProxy(aDemuxer, aDecoder->AbstractMainThread()))
, mDemuxer(nullptr)
, mDemuxerInitDone(false)
, mLastReportedNumDecodedFrames(0)
, mPreviousDecodedKeyframeTime_us(sNoPreviousDecodedKeyframe)
@ -804,10 +804,15 @@ MediaFormatReader::MediaFormatReader(AbstractMediaDecoder* aDecoder,
MOZ_ASSERT(aDemuxer);
MOZ_COUNT_CTOR(MediaFormatReader);
if (aDecoder && aDecoder->CompositorUpdatedEvent()) {
mCompositorUpdatedListener =
aDecoder->CompositorUpdatedEvent()->Connect(
mTaskQueue, this, &MediaFormatReader::NotifyCompositorUpdated);
if (aDecoder) {
mDemuxer = MakeUnique<DemuxerProxy>(aDemuxer,
aDecoder->AbstractMainThread());
if (aDecoder->CompositorUpdatedEvent()) {
mCompositorUpdatedListener =
aDecoder->CompositorUpdatedEvent()->Connect(
mTaskQueue, this, &MediaFormatReader::NotifyCompositorUpdated);
}
}
}

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

@ -152,6 +152,13 @@ RemoteDecoderModule::SupportsMimeType(const nsACString& aMimeType,
return mWrapped->SupportsMimeType(aMimeType, aDiagnostics);
}
bool
RemoteDecoderModule::Supports(const TrackInfo& aTrackInfo,
DecoderDoctorDiagnostics* aDiagnostics) const
{
return mWrapped->Supports(aTrackInfo, aDiagnostics);
}
PlatformDecoderModule::ConversionRequired
RemoteDecoderModule::DecoderNeedsConversion(const TrackInfo& aConfig) const
{

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

@ -67,6 +67,8 @@ public:
bool SupportsMimeType(const nsACString& aMimeType,
DecoderDoctorDiagnostics* aDiagnostics) const override;
bool Supports(const TrackInfo& aTrackInfo,
DecoderDoctorDiagnostics* aDiagnostics) const override;
ConversionRequired DecoderNeedsConversion(
const TrackInfo& aConfig) const override;

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

@ -254,11 +254,7 @@ partial interface Document {
// https://w3c.github.io/pointerlock/#extensions-to-the-documentorshadowroot-mixin
partial interface Document {
readonly attribute Element? pointerLockElement;
[BinaryName="pointerLockElement", Pref="pointer-lock-api.prefixed.enabled"]
readonly attribute Element? mozPointerLockElement;
void exitPointerLock();
[BinaryName="exitPointerLock", Pref="pointer-lock-api.prefixed.enabled"]
void mozExitPointerLock();
// Event handlers
attribute EventHandler onpointerlockchange;

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

@ -260,6 +260,4 @@ partial interface Element {
partial interface Element {
[UnsafeInPrerendering, NeedsCallerType]
void requestPointerLock();
[UnsafeInPrerendering, BinaryName="requestPointerLock", Pref="pointer-lock-api.prefixed.enabled", NeedsCallerType]
void mozRequestPointerLock();
};

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

@ -120,10 +120,6 @@ interface GlobalEventHandlers {
// Document rather than here.
attribute EventHandler onmozfullscreenchange;
attribute EventHandler onmozfullscreenerror;
[Pref="pointer-lock-api.prefixed.enabled"]
attribute EventHandler onmozpointerlockchange;
[Pref="pointer-lock-api.prefixed.enabled"]
attribute EventHandler onmozpointerlockerror;
// CSS-Animation and CSS-Transition handlers.
attribute EventHandler onanimationend;

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

@ -77,11 +77,6 @@ dictionary MouseEventInit : EventModifierInit {
// Mozilla extensions
partial interface MouseEvent
{
[BinaryName="movementX", Pref="pointer-lock-api.prefixed.enabled"]
readonly attribute long mozMovementX;
[BinaryName="movementY", Pref="pointer-lock-api.prefixed.enabled"]
readonly attribute long mozMovementY;
// Finger or touch pressure event value
// ranges between 0.0 and 1.0
readonly attribute float mozPressure;

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

@ -57,6 +57,8 @@ for (let descriptor of WebAssembly.Module.imports(module)) {
var instance = new WebAssembly.Instance(module, imports);
`);
var wasmScript = dbg.findScripts().filter(s => s.format == 'wasm')[0];
assertEq(wasmScript.startLine, 1);
assertEq(wasmScript.lineCount > 0, true);
var lines = wasmScript.source.text.split('\n');
var offsetsFound = 0;
lines.forEach(function (l, n) {
@ -102,6 +104,8 @@ function getWasmScriptAfterDebuggerAttached(wast) {
var wasmScript1 = getWasmScriptAfterDebuggerAttached('(module (func (nop)))');
var wasmLines1 = wasmScript1.source.text.split('\n');
assertEq(wasmScript1.startLine, 1);
assertEq(wasmScript1.lineCount, 0);
assertEq(wasmLines1.every((l, n) => wasmScript1.getLineOffsets(n + 1).length == 0), true);
// Checking that we must not resolve any location for any offset in a wasm

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

@ -0,0 +1,35 @@
// |jit-test| test-also-wasm-baseline
// Tests debugEnabled state of wasm when allowUnobservedAsmJS == true.
load(libdir + "asserts.js");
if (!wasmIsSupported())
quit();
// Checking that there are no offsets are present in a wasm instance script for
// which debug mode was not enabled.
function getWasmScriptWithoutAllowUnobservedAsmJS(wast) {
var sandbox = newGlobal('');
var dbg = new Debugger();
dbg.allowUnobservedAsmJS = true;
dbg.addDebuggee(sandbox);
sandbox.eval(`
var wasm = wasmTextToBinary('${wast}');
var m = new WebAssembly.Instance(new WebAssembly.Module(wasm));
`);
// Attaching after wasm instance is created.
var wasmScript = dbg.findScripts().filter(s => s.format == 'wasm')[0];
return wasmScript;
}
var wasmScript1 = getWasmScriptWithoutAllowUnobservedAsmJS('(module (func (nop)))');
var wasmLines1 = wasmScript1.source.text.split('\n');
assertEq(wasmScript1.startLine, 1);
assertEq(wasmScript1.lineCount, 0);
assertEq(wasmLines1.every((l, n) => wasmScript1.getLineOffsets(n + 1).length == 0), true);
// Checking that we must not resolve any location for any offset in a wasm
// instance which debug mode was not enabled.
var wasmScript2 = getWasmScriptWithoutAllowUnobservedAsmJS('(module (func (nop)))');
for (var i = wasmTextToBinary('(module (func (nop)))').length - 1; i >= 0; i--)
assertThrowsInstanceOf(() => wasmScript2.getOffsetLocation(i), Error);

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

@ -5677,7 +5677,7 @@ struct DebuggerScriptGetLineCountMatcher
}
ReturnType match(Handle<WasmInstanceObject*> wasmInstance) {
uint32_t result;
if (wasmInstance->instance().code().totalSourceLines(cx_, &result))
if (!wasmInstance->instance().code().totalSourceLines(cx_, &result))
return false;
totalLines = double(result);
return true;

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

@ -864,12 +864,14 @@ Code::getOffsetLocation(JSContext* cx, uint32_t offset, bool* found, size_t* lin
bool
Code::totalSourceLines(JSContext* cx, uint32_t* count)
{
*count = 0;
if (!metadata_->debugEnabled)
return true;
if (!ensureSourceMap(cx))
return false;
if (!maybeSourceMap_)
*count = 0;
else
if (maybeSourceMap_)
*count = maybeSourceMap_->totalLines() + experimentalWarningLinesCount;
return true;
}

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

@ -172,6 +172,10 @@ SERVO_BINDING_FUNC(Servo_DeclarationBlock_RemoveProperty, void,
SERVO_BINDING_FUNC(Servo_DeclarationBlock_RemovePropertyById, void,
RawServoDeclarationBlockBorrowed declarations,
nsCSSPropertyID property)
SERVO_BINDING_FUNC(Servo_DeclarationBlock_AddPresValue, void,
RawServoDeclarationBlockBorrowed declarations,
nsCSSPropertyID property,
nsCSSValueBorrowedMut css_value)
// CSS supports()
SERVO_BINDING_FUNC(Servo_CSSSupports2, bool,
@ -222,6 +226,8 @@ SERVO_BINDING_FUNC(Servo_ResolveStyleLazily, ServoComputedValuesStrong,
RawServoStyleSetBorrowed set)
// Restyle the given subtree.
// Use ServoStyleSet::PrepareAndTraverseSubtree instead of calling this
// directly
SERVO_BINDING_FUNC(Servo_TraverseSubtree, void,
RawGeckoElementBorrowed root, RawServoStyleSetBorrowed set,
mozilla::TraversalRootBehavior root_behavior)

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

@ -68,6 +68,7 @@ typedef nsTArray<const RawServoAnimationValue*> RawServoAnimationValueBorrowedLi
#define SERVO_ARC_TYPE(name_, type_) \
DECL_NULLABLE_BORROWED_REF_TYPE_FOR(type_) \
DECL_BORROWED_REF_TYPE_FOR(type_) \
DECL_BORROWED_MUT_REF_TYPE_FOR(type_) \
struct MOZ_MUST_USE_TYPE type_##Strong \
{ \
type_* mPtr; \

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

@ -21,6 +21,7 @@
#include "nsIFrame.h"
#include "nsINode.h"
#include "nsIPrincipal.h"
#include "nsMappedAttributes.h"
#include "nsMediaFeatures.h"
#include "nsNameSpaceManager.h"
#include "nsNetUtil.h"
@ -312,7 +313,7 @@ Gecko_DropElementSnapshot(ServoElementSnapshotOwned aSnapshot)
}
RawServoDeclarationBlockStrongBorrowedOrNull
Gecko_GetServoDeclarationBlock(RawGeckoElementBorrowed aElement)
Gecko_GetStyleAttrDeclarationBlock(RawGeckoElementBorrowed aElement)
{
DeclarationBlock* decl = aElement->GetInlineStyleDeclaration();
if (!decl) {
@ -328,6 +329,21 @@ Gecko_GetServoDeclarationBlock(RawGeckoElementBorrowed aElement)
(decl->AsServo()->RefRaw());
}
RawServoDeclarationBlockStrongBorrowedOrNull
Gecko_GetHTMLPresentationAttrDeclarationBlock(RawGeckoElementBorrowed aElement)
{
static_assert(sizeof(RefPtr<RawServoDeclarationBlock>) ==
sizeof(RawServoDeclarationBlockStrong),
"RefPtr should just be a pointer");
const nsMappedAttributes* attrs = aElement->GetMappedAttributes();
if (!attrs) {
return nullptr;
}
const RefPtr<RawServoDeclarationBlock>& servo = attrs->GetServoStyle();
return reinterpret_cast<const RawServoDeclarationBlockStrong*>(&servo);
}
RawServoDeclarationBlockStrong
Gecko_GetAnimationRule(RawGeckoElementBorrowed aElement,
nsIAtom* aPseudoTag,

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

@ -158,7 +158,9 @@ SERVO_DECLARE_ELEMENT_ATTR_MATCHING_FUNCTIONS(Gecko_Snapshot,
// Style attributes.
RawServoDeclarationBlockStrongBorrowedOrNull
Gecko_GetServoDeclarationBlock(RawGeckoElementBorrowed element);
Gecko_GetStyleAttrDeclarationBlock(RawGeckoElementBorrowed element);
RawServoDeclarationBlockStrongBorrowedOrNull
Gecko_GetHTMLPresentationAttrDeclarationBlock(RawGeckoElementBorrowed element);
// Animations
RawServoDeclarationBlockStrong

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

@ -14,6 +14,7 @@
#include "nsAnimationManager.h"
#include "nsCSSAnonBoxes.h"
#include "nsCSSPseudoElements.h"
#include "nsHTMLStyleSheet.h"
#include "nsIDocumentInlines.h"
#include "nsPrintfCString.h"
#include "nsStyleContext.h"
@ -127,6 +128,8 @@ ServoStyleSet::GetContext(nsIContent* aContent,
MOZ_ASSERT(aContent->IsElement());
Element* element = aContent->AsElement();
ResolveMappedAttrDeclarationBlocks();
RefPtr<ServoComputedValues> computedValues;
if (aMayCompute == LazyComputeBehavior::Allow) {
computedValues =
@ -176,6 +179,21 @@ ServoStyleSet::GetContext(already_AddRefed<ServoComputedValues> aComputedValues,
return result.forget();
}
void
ServoStyleSet::ResolveMappedAttrDeclarationBlocks()
{
if (nsHTMLStyleSheet* sheet = mPresContext->Document()->GetAttributeStyleSheet()) {
sheet->CalculateMappedServoDeclarations();
}
}
void
ServoStyleSet::PrepareAndTraverseSubtree(RawGeckoElementBorrowed aRoot,
mozilla::TraversalRootBehavior aRootBehavior) {
ResolveMappedAttrDeclarationBlocks();
Servo_TraverseSubtree(aRoot, mRawSet.get(), aRootBehavior);
}
already_AddRefed<nsStyleContext>
ServoStyleSet::ResolveStyleFor(Element* aElement,
nsStyleContext* aParentContext,
@ -541,7 +559,7 @@ ServoStyleSet::StyleDocument()
DocumentStyleRootIterator iter(mPresContext->Document());
while (Element* root = iter.GetNextStyleRoot()) {
if (root->ShouldTraverseForServo()) {
Servo_TraverseSubtree(root, mRawSet.get(), TraversalRootBehavior::Normal);
PrepareAndTraverseSubtree(root, TraversalRootBehavior::Normal);
}
}
}
@ -550,14 +568,13 @@ void
ServoStyleSet::StyleNewSubtree(Element* aRoot)
{
MOZ_ASSERT(!aRoot->HasServoData());
Servo_TraverseSubtree(aRoot, mRawSet.get(), TraversalRootBehavior::Normal);
PrepareAndTraverseSubtree(aRoot, TraversalRootBehavior::Normal);
}
void
ServoStyleSet::StyleNewChildren(Element* aParent)
{
Servo_TraverseSubtree(aParent, mRawSet.get(),
TraversalRootBehavior::UnstyledChildrenOnly);
PrepareAndTraverseSubtree(aParent, TraversalRootBehavior::UnstyledChildrenOnly);
}
void

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

@ -199,6 +199,20 @@ private:
CSSPseudoElementType aPseudoType,
LazyComputeBehavior aMayCompute);
/**
* Resolve all ServoDeclarationBlocks attached to mapped
* presentation attributes cached on the document.
* Call this before jumping into Servo's style system.
*/
void ResolveMappedAttrDeclarationBlocks();
/**
* Perform all lazy operations required before traversing
* a subtree.
*/
void PrepareAndTraverseSubtree(RawGeckoElementBorrowed aRoot,
mozilla::TraversalRootBehavior aRootBehavior);
nsPresContext* mPresContext;
UniquePtr<RawServoStyleSet> mRawSet;
EnumeratedArray<SheetType, SheetType::Count,

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

@ -289,6 +289,7 @@ nsHTMLStyleSheet::nsHTMLStyleSheet(nsIDocument* aDocument)
, mTableQuirkColorRule(new TableQuirkColorRule())
, mTableTHRule(new TableTHRule())
, mMappedAttrTable(&MappedAttrTable_Ops, sizeof(MappedAttrTableEntry))
, mMappedAttrsDirty(false)
, mLangRuleTable(&LangRuleTable_Ops, sizeof(LangRuleTableEntry))
{
MOZ_ASSERT(aDocument);
@ -478,6 +479,7 @@ nsHTMLStyleSheet::Reset()
mLangRuleTable.Clear();
mMappedAttrTable.Clear();
mMappedAttrsDirty = false;
}
nsresult
@ -526,6 +528,7 @@ nsHTMLStyleSheet::SetVisitedLinkColor(nscolor aColor)
already_AddRefed<nsMappedAttributes>
nsHTMLStyleSheet::UniqueMappedAttributes(nsMappedAttributes* aMapped)
{
mMappedAttrsDirty = true;
auto entry = static_cast<MappedAttrTableEntry*>
(mMappedAttrTable.Add(aMapped, fallible));
if (!entry)
@ -542,7 +545,6 @@ void
nsHTMLStyleSheet::DropMappedAttributes(nsMappedAttributes* aMapped)
{
NS_ENSURE_TRUE_VOID(aMapped);
#ifdef DEBUG
uint32_t entryCount = mMappedAttrTable.EntryCount() - 1;
#endif
@ -552,6 +554,97 @@ nsHTMLStyleSheet::DropMappedAttributes(nsMappedAttributes* aMapped)
NS_ASSERTION(entryCount == mMappedAttrTable.EntryCount(), "not removed");
}
namespace {
// Struct containing once-initialized information about
// our synthesized rule data
struct StaticRuleDataInfo
{
// the bitmask used.
uint64_t mMask;
// the number of properties contained
size_t mPropCount;
// offset of given style struct in array
size_t mOffsets[nsStyleStructID_Length];
// location of property in given array
nsCSSPropertyID* mIndexToPropertyMapping;
};
}
static void
CalculateIndexArray(StaticRuleDataInfo* aInfo)
{
// this will leak at shutdown, but it's not much and this code is temporary
// anyway.
aInfo->mIndexToPropertyMapping = new nsCSSPropertyID[aInfo->mPropCount];
size_t structOffset;
size_t propertyIndex;
#define CSS_PROP_LIST_EXCLUDE_LOGICAL
#define CSS_PROP(name_, id_, method_, flags_, pref_, parsevariant_, \
kwtable_, stylestruct_, stylestructoffset_, animtype_) \
structOffset = aInfo->mOffsets[eStyleStruct_##stylestruct_]; \
propertyIndex = nsCSSProps::PropertyIndexInStruct(eCSSProperty_##id_); \
aInfo->mIndexToPropertyMapping[structOffset + propertyIndex] = eCSSProperty_##id_;
#include "nsCSSPropList.h"
#undef CSS_PROP
#undef CSS_PROP_LIST_EXCLUDE_LOGICAL
}
static StaticRuleDataInfo
CalculateRuleDataInfo()
{
StaticRuleDataInfo sizes;
sizes.mMask = 0;
sizes.mPropCount = 0;
#define STYLE_STRUCT(name, checkdata_cb) \
sizes.mMask |= NS_STYLE_INHERIT_BIT(name); \
sizes.mOffsets[eStyleStruct_##name] = sizes.mPropCount; \
sizes.mPropCount += nsCSSProps::PropertyCountInStruct(eStyleStruct_##name);
#include "nsStyleStructList.h"
#undef STYLE_STRUCT
CalculateIndexArray(&sizes);
return sizes;
}
void
nsHTMLStyleSheet::CalculateMappedServoDeclarations()
{
// avoid recalculating or reallocating
static StaticRuleDataInfo sizes = CalculateRuleDataInfo();
if (!mMappedAttrsDirty) {
return;
}
mMappedAttrsDirty = false;
void* dataStorage = alloca(sizes.mPropCount * sizeof(nsCSSValue));
for (auto iter = mMappedAttrTable.Iter(); !iter.Done(); iter.Next()) {
MappedAttrTableEntry* attr = static_cast<MappedAttrTableEntry*>(iter.Get());
if (attr->mAttributes->GetServoStyle()) {
// Only handle cases which haven't been filled in already
continue;
}
// Construction cleans up any values we may have set
AutoCSSValueArray dataArray(dataStorage, sizes.mPropCount);
// synthesized ruleData
// we pass null for the style context because the code we call into
// doesn't deal with the style context. This is temporary.
nsRuleData ruleData(sizes.mMask, dataArray.get(),
mDocument->GetShell()->GetPresContext(), nullptr);
// Copy the offsets; ruleData won't know where to find properties otherwise
mozilla::PodCopy(ruleData.mValueOffsets,
sizes.mOffsets,
nsStyleStructID_Length);
attr->mAttributes->LazilyResolveServoDeclaration(&ruleData,
sizes.mIndexToPropertyMapping,
sizes.mPropCount);
}
}
nsIStyleRule*
nsHTMLStyleSheet::LangRuleFor(const nsString& aLanguage)
{

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

@ -62,6 +62,10 @@ public:
already_AddRefed<nsMappedAttributes>
UniqueMappedAttributes(nsMappedAttributes* aMapped);
void DropMappedAttributes(nsMappedAttributes* aMapped);
// For each mapped presentation attribute in the cache, resolve
// the attached ServoDeclarationBlock by running the mapping
// and converting the ruledata to Servo specified values.
void CalculateMappedServoDeclarations();
nsIStyleRule* LangRuleFor(const nsString& aLanguage);
@ -175,6 +179,10 @@ private:
RefPtr<TableTHRule> mTableTHRule;
PLDHashTable mMappedAttrTable;
// Whether or not the mapped attributes table
// has been changed since the last call to
// CalculateMappedServoDeclarations()
bool mMappedAttrsDirty;
PLDHashTable mLangRuleTable;
};

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

@ -2354,44 +2354,25 @@ UnsetPropertiesWithoutFlags(const nsStyleStructID aSID,
}
}
/**
* We allocate arrays of CSS values with alloca. (These arrays are a
* fixed size per style struct, but we don't want to waste the
* allocation and construction/destruction costs of the big structs when
* we're handling much smaller ones.) Since the lifetime of an alloca
* allocation is the life of the calling function, the caller must call
* alloca. However, to ensure that constructors and destructors are
* balanced, we do the constructor and destructor calling from this RAII
* class, AutoCSSValueArray.
*/
struct AutoCSSValueArray {
/**
* aStorage must be the result of alloca(aCount * sizeof(nsCSSValue))
*/
AutoCSSValueArray(void* aStorage, size_t aCount) {
MOZ_ASSERT(size_t(aStorage) % NS_ALIGNMENT_OF(nsCSSValue) == 0,
"bad alignment from alloca");
mCount = aCount;
// Don't use placement new[], since it might store extra data
// for the count (on Windows!).
mArray = static_cast<nsCSSValue*>(aStorage);
for (size_t i = 0; i < mCount; ++i) {
new (KnownNotNull, mArray + i) nsCSSValue();
}
AutoCSSValueArray::AutoCSSValueArray(void* aStorage, size_t aCount)
{
MOZ_ASSERT(size_t(aStorage) % NS_ALIGNMENT_OF(nsCSSValue) == 0,
"bad alignment from alloca");
mCount = aCount;
// Don't use placement new[], since it might store extra data
// for the count (on Windows!).
mArray = static_cast<nsCSSValue*>(aStorage);
for (size_t i = 0; i < mCount; ++i) {
new (KnownNotNull, mArray + i) nsCSSValue();
}
}
~AutoCSSValueArray() {
for (size_t i = 0; i < mCount; ++i) {
mArray[i].~nsCSSValue();
}
AutoCSSValueArray::~AutoCSSValueArray()
{
for (size_t i = 0; i < mCount; ++i) {
mArray[i].~nsCSSValue();
}
nsCSSValue* get() { return mArray; }
private:
nsCSSValue *mArray;
size_t mCount;
};
}
/* static */ bool
nsRuleNode::ResolveVariableReferences(const nsStyleStructID aSID,

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

@ -1085,4 +1085,30 @@ private:
void* aStruct);
};
/**
* We allocate arrays of CSS values with alloca. (These arrays are a
* fixed size per style struct, but we don't want to waste the
* allocation and construction/destruction costs of the big structs when
* we're handling much smaller ones.) Since the lifetime of an alloca
* allocation is the life of the calling function, the caller must call
* alloca. However, to ensure that constructors and destructors are
* balanced, we do the constructor and destructor calling from this RAII
* class, AutoCSSValueArray.
*/
struct AutoCSSValueArray
{
/**
* aStorage must be the result of alloca(aCount * sizeof(nsCSSValue))
*/
AutoCSSValueArray(void* aStorage, size_t aCount);
~AutoCSSValueArray();
nsCSSValue* get() { return mArray; }
private:
nsCSSValue *mArray;
size_t mCount;
};
#endif

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

@ -88,5 +88,6 @@ class ReftestCommands(object):
description='Run the reftest harness.',
parser=setup_argument_parser)
def reftest(self, **kwargs):
self.context.activate_mozharness_venv()
kwargs['suite'] = 'reftest'
return run_reftest(self.context, **kwargs)

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

@ -45,11 +45,15 @@ AnnexB::ConvertSampleToAnnexB(mozilla::MediaRawData* aSample, bool aAddSPS)
uint32_t nalLen = reader.ReadU32();
const uint8_t* p = reader.Read(nalLen);
writer.Write(kAnnexBDelimiter, ArrayLength(kAnnexBDelimiter));
if (!writer.Write(kAnnexBDelimiter, ArrayLength(kAnnexBDelimiter))) {
return false;
}
if (!p) {
break;
}
writer.Write(p, nalLen);
if (!writer.Write(p, nalLen)) {
return false;
}
}
nsAutoPtr<MediaRawDataWriter> samplewriter(aSample->CreateWriter());
@ -188,7 +192,7 @@ FindStartCode(ByteReader& aBr, size_t& aStartSize)
return true;
}
static void
static bool
ParseNALUnits(ByteWriter& aBw, ByteReader& aBr)
{
size_t startSize;
@ -200,17 +204,22 @@ ParseNALUnits(ByteWriter& aBw, ByteReader& aBr)
size_t offset = aBr.Offset();
size_t sizeNAL = offset - startOffset - startSize;
aBr.Seek(startOffset);
aBw.WriteU32(sizeNAL);
aBw.Write(aBr.Read(sizeNAL), sizeNAL);
if (!aBw.WriteU32(sizeNAL)
|| !aBw.Write(aBr.Read(sizeNAL), sizeNAL)) {
return false;
}
aBr.Read(startSize);
startOffset = offset;
}
}
size_t sizeNAL = aBr.Remaining();
if (sizeNAL) {
aBw.WriteU32(sizeNAL);
aBw.Write(aBr.Read(sizeNAL), sizeNAL);
if (!aBw.WriteU32(sizeNAL)
|| !aBw.Write(aBr.Read(sizeNAL), sizeNAL)) {
return false;
}
}
return true;
}
bool
@ -228,7 +237,9 @@ AnnexB::ConvertSampleToAVCC(mozilla::MediaRawData* aSample)
ByteWriter writer(nalu);
ByteReader reader(aSample->Data(), aSample->Size());
ParseNALUnits(writer, reader);
if (!ParseNALUnits(writer, reader)) {
return false;
}
nsAutoPtr<MediaRawDataWriter> samplewriter(aSample->CreateWriter());
return samplewriter->Replace(nalu.begin(), nalu.length());
}
@ -284,12 +295,16 @@ AnnexB::ExtractExtraData(const mozilla::MediaRawData* aSample)
if (nalType == 0x7) { /* SPS */
numSps++;
spsw.WriteU16(nalLen);
spsw.Write(p, nalLen);
if (!spsw.WriteU16(nalLen)
|| !spsw.Write(p, nalLen)) {
return extradata.forget();
}
} else if (nalType == 0x8) { /* PPS */
numPps++;
ppsw.WriteU16(nalLen);
ppsw.Write(p, nalLen);
if (!ppsw.WriteU16(nalLen)
|| !ppsw.Write(p, nalLen)) {
return extradata.forget();
}
}
}
@ -399,8 +414,10 @@ AnnexB::ConvertSampleTo4BytesAVCC(mozilla::MediaRawData* aSample)
if (!p) {
return true;
}
writer.WriteU32(nalLen);
writer.Write(p, nalLen);
if (!writer.WriteU32(nalLen)
|| !writer.Write(p, nalLen)) {
return false;
}
}
nsAutoPtr<MediaRawDataWriter> samplewriter(aSample->CreateWriter());
return samplewriter->Replace(dest.begin(), dest.length());

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

@ -22,49 +22,49 @@ public:
{
}
void WriteU8(uint8_t aByte)
MOZ_MUST_USE bool WriteU8(uint8_t aByte)
{
Write(&aByte, 1);
return Write(&aByte, 1);
}
void WriteU16(uint16_t aShort)
MOZ_MUST_USE bool WriteU16(uint16_t aShort)
{
uint8_t c[2];
mozilla::BigEndian::writeUint16(&c[0], aShort);
Write(&c[0], 2);
return Write(&c[0], 2);
}
void WriteU32(uint32_t aLong)
MOZ_MUST_USE bool WriteU32(uint32_t aLong)
{
uint8_t c[4];
mozilla::BigEndian::writeUint32(&c[0], aLong);
Write(&c[0], 4);
return Write(&c[0], 4);
}
void Write32(int32_t aLong)
MOZ_MUST_USE bool Write32(int32_t aLong)
{
uint8_t c[4];
mozilla::BigEndian::writeInt32(&c[0], aLong);
Write(&c[0], 4);
return Write(&c[0], 4);
}
void WriteU64(uint64_t aLongLong)
MOZ_MUST_USE bool WriteU64(uint64_t aLongLong)
{
uint8_t c[8];
mozilla::BigEndian::writeUint64(&c[0], aLongLong);
Write(&c[0], 8);
return Write(&c[0], 8);
}
void Write64(int64_t aLongLong)
MOZ_MUST_USE bool Write64(int64_t aLongLong)
{
uint8_t c[8];
mozilla::BigEndian::writeInt64(&c[0], aLongLong);
Write(&c[0], 8);
return Write(&c[0], 8);
}
void Write(const uint8_t* aSrc, size_t aCount)
MOZ_MUST_USE bool Write(const uint8_t* aSrc, size_t aCount)
{
MOZ_RELEASE_ASSERT(mPtr.append(aSrc, aCount));
return mPtr.append(aSrc, aCount);
}
private:

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

@ -37,6 +37,7 @@ import android.content.pm.PackageManager.NameNotFoundException;
import android.os.Build;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.text.TextUtils;
import android.util.Log;
@ -199,16 +200,22 @@ public class SwitchBoard {
return experiment;
}
private static boolean isMatch(Context c, @Nullable JSONObject matchKeys) {
/**
* Return false if the match object contains any non-matching patterns. Otherwise returns true.
*/
private static boolean isMatch(Context context, @Nullable JSONObject matchKeys) {
// If no match keys are specified, default to enabling the experiment.
if (matchKeys == null) {
return true;
}
if (matchKeys.has(KEY_APP_ID)) {
final String packageName = c.getPackageName();
try {
if (!packageName.matches(matchKeys.getString(KEY_APP_ID))) {
final String packageName = context.getPackageName();
final String expectedAppIdPattern = matchKeys.getString(KEY_APP_ID);
if (!TextUtils.isEmpty(expectedAppIdPattern)
&& !packageName.matches(expectedAppIdPattern)) {
return false;
}
} catch (JSONException e) {
@ -219,7 +226,10 @@ public class SwitchBoard {
if (matchKeys.has(KEY_COUNTRY)) {
try {
final String country = Locale.getDefault().getISO3Country();
if (!country.matches(matchKeys.getString(KEY_COUNTRY))) {
final String expectedCountryPattern = matchKeys.getString(KEY_COUNTRY);
if (!TextUtils.isEmpty(expectedCountryPattern)
&& !country.matches(expectedCountryPattern)) {
return false;
}
} catch (MissingResourceException | JSONException e) {
@ -228,30 +238,40 @@ public class SwitchBoard {
}
if (matchKeys.has(KEY_DEVICE)) {
final String device = Build.DEVICE;
try {
if (!device.matches(matchKeys.getString(KEY_DEVICE))) {
final String device = Build.DEVICE;
final String expectedDevicePattern = matchKeys.getString(KEY_DEVICE);
if (!TextUtils.isEmpty(expectedDevicePattern)
&& !device.matches(expectedDevicePattern)) {
return false;
}
} catch (JSONException e) {
Log.e(TAG, "Exception matching device", e);
}
}
if (matchKeys.has(KEY_LANG)) {
try {
final String lang = Locale.getDefault().getISO3Language();
if (!lang.matches(matchKeys.getString(KEY_LANG))) {
final String expectedLanguagePattern = matchKeys.getString(KEY_LANG);
if (!TextUtils.isEmpty(expectedLanguagePattern)
&& !lang.matches(expectedLanguagePattern)) {
return false;
}
} catch (MissingResourceException | JSONException e) {
Log.e(TAG, "Exception matching lang", e);
}
}
if (matchKeys.has(KEY_MANUFACTURER)) {
final String manufacturer = Build.MANUFACTURER;
try {
if (!manufacturer.matches(matchKeys.getString(KEY_MANUFACTURER))) {
final String manufacturer = Build.MANUFACTURER;
final String expectedManufacturerPattern = matchKeys.getString(KEY_MANUFACTURER);
if (!TextUtils.isEmpty(expectedManufacturerPattern)
&& !manufacturer.matches(expectedManufacturerPattern)) {
return false;
}
} catch (JSONException e) {
@ -261,8 +281,11 @@ public class SwitchBoard {
if (matchKeys.has(KEY_VERSION)) {
try {
final String version = c.getPackageManager().getPackageInfo(c.getPackageName(), 0).versionName;
if (!version.matches(matchKeys.getString(KEY_VERSION))) {
final String version = context.getPackageManager().getPackageInfo(context.getPackageName(), 0).versionName;
final String expectedVersionPattern = matchKeys.getString(KEY_VERSION);
if (!TextUtils.isEmpty(expectedVersionPattern)
&& !version.matches(expectedVersionPattern)) {
return false;
}
} catch (NameNotFoundException | JSONException e) {

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

@ -4818,7 +4818,6 @@ pref("full-screen-api.warning.timeout", 3000);
pref("full-screen-api.warning.delay", 500);
// DOM pointerlock API
pref("pointer-lock-api.prefixed.enabled", false);
// time for the warning box stays on the screen before sliding out, unit: ms
pref("pointer-lock-api.warning.timeout", 3000);

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

@ -19,11 +19,13 @@ linux32/debug:
build-platform: linux/debug
test-sets:
- linux32-tests
- external-media-tests
linux32/opt:
build-platform: linux/opt
test-sets:
- linux32-tests
- linux32-opt-tests
- external-media-tests
linux64/debug:
build-platform: linux64/debug
@ -84,10 +86,12 @@ windows7-32-vm/debug:
build-platform: win32/debug
test-sets:
- windows-vm-tests
- external-media-tests
windows7-32-vm/opt:
build-platform: win32/opt
test-sets:
- windows-vm-tests
- external-media-tests
# win32 gpu
#windows7-32/debug:
@ -104,10 +108,12 @@ windows10-64-vm/debug:
build-platform: win64/debug
test-sets:
- windows-vm-tests
- external-media-tests
windows10-64-vm/opt:
build-platform: win64/opt
test-sets:
- windows-vm-tests
- external-media-tests
# win64 gpu
#windows10-64/debug:

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

@ -44,7 +44,9 @@ web-platform-tests:
- web-platform-tests-wdspec
external-media-tests:
- external-media-tests
- external-media-tests-base
- external-media-tests-youtube
- external-media-tests-twitch
opt-only-tests:
- mochitest-valgrind
@ -88,7 +90,6 @@ jsdcov-code-coverage-tests:
windows-vm-tests:
- cppunit
#- crashtest
- external-media-tests
#- gtest
#- jittest
- jsreftest
@ -147,7 +148,6 @@ macosx64-tests-talos:
linux32-tests:
- cppunit
- crashtest
- external-media-tests
- firefox-ui-functional-local
- firefox-ui-functional-remote
- gtest

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

@ -89,7 +89,7 @@ crashtest:
extra-options:
- --reftest-suite=crashtest
external-media-tests:
external-media-tests-base:
description: "External Media Test run"
suite: external-media-tests
treeherder-symbol: tc-VP(b-m)
@ -111,6 +111,54 @@ external-media-tests:
- mediatests/taskcluster_posix_config.py
- remove_executables.py
external-media-tests-twitch:
description: "External Media Test Twitch run"
suite: external-media-tests/twitch
treeherder-symbol: tc-VP(b-t)
e10s: false
tier: 2
max-run-time: 5400
docker-image: {"in-tree": "desktop1604-test"}
run-on-projects:
by-test-platform:
windows.*: ['mozilla-central', 'try']
default: ['all']
mozharness:
script: firefox_media_tests_taskcluster.py
config:
by-test-platform:
windows.*:
- mediatests/taskcluster_windows_config.py
default:
- mediatests/taskcluster_posix_config.py
- remove_executables.py
extra-options:
- "--suite=media-twitch-tests"
external-media-tests-youtube:
description: "External Media Test Youtube run"
suite: external-media-tests/youtube
treeherder-symbol: tc-VP(b-y)
e10s: false
tier: 2
max-run-time: 5400
docker-image: {"in-tree": "desktop1604-test"}
run-on-projects:
by-test-platform:
windows.*: ['mozilla-central', 'try']
default: ['all']
mozharness:
script: firefox_media_tests_taskcluster.py
config:
by-test-platform:
windows.*:
- mediatests/taskcluster_windows_config.py
default:
- mediatests/taskcluster_posix_config.py
- remove_executables.py
extra-options:
- "--suite=media-youtube-tests"
firefox-ui-functional-local:
description: "Firefox-ui-tests functional run"
suite: "firefox-ui/functional local"

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

@ -58,13 +58,6 @@ def setup():
os.remove(mach_dest)
os.symlink(mach_src, mach_dest)
activate = os.path.join(build_dir, 'venv', 'bin', 'activate')
if os.path.isfile(activate):
# TODO Support other shells
bashrc = os.path.expanduser(os.path.join('~', '.bashrc'))
with open(bashrc, 'ab') as f:
f.write(". {}".format(activate))
print("""
Mozharness has finished downloading the build and tests to:
{}

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

@ -68,7 +68,7 @@ def target_tasks_default(full_task_graph, parameters):
"""Target the tasks which have indicated they should be run on this project
via the `run_on_projects` attributes."""
def filter(task):
run_on_projects = set(t.attributes.get('run_on_projects', []))
run_on_projects = set(task.attributes.get('run_on_projects', []))
if 'all' in run_on_projects:
return True
project = parameters['project']

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

@ -425,7 +425,7 @@ action.InputState = {};
/**
* Input state associated with a keyboard-type device.
*/
action.InputState.Key = class extends InputState {
action.InputState.Key = class Key extends InputState {
constructor() {
super();
this.pressed = new Set();
@ -498,7 +498,7 @@ action.InputState.Key = class extends InputState {
/**
* Input state not associated with a specific physical device.
*/
action.InputState.Null = class extends InputState {
action.InputState.Null = class Null extends InputState {
constructor() {
super();
this.type = "none";
@ -513,7 +513,7 @@ action.InputState.Null = class extends InputState {
* @param {boolean} primary
* Whether the pointing device is primary.
*/
action.InputState.Pointer = class extends InputState {
action.InputState.Pointer = class Pointer extends InputState {
constructor(subtype, primary) {
super();
this.pressed = new Set();

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

@ -64,4 +64,5 @@ class MachCommands(object):
'using marionette).',
parser=setup_marionette_argument_parser)
def run_marionette_test(self, **kwargs):
self.context.activate_mozharness_venv()
return run_marionette(self.context, **kwargs)

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

@ -15,7 +15,7 @@ action.inputStateMap = new Map();
add_test(function test_createAction() {
Assert.throws(() => new action.Action(), InvalidArgumentError,
"Missing Action constructor args");
Assert.throws(() => new action.Action(1,2), InvalidArgumentError,
Assert.throws(() => new action.Action(1, 2), InvalidArgumentError,
"Missing Action constructor args");
Assert.throws(
() => new action.Action(1, 2, "sometype"), /Expected string/, "Non-string arguments.");
@ -157,7 +157,7 @@ add_test(function test_processPointerAction() {
pointerType: "touch",
primary: false,
},
}
};
let actionItems = [
{
duration: 2000,
@ -364,7 +364,7 @@ add_test(function test_processPointerActionInputStateMap() {
let parameters = {pointerType: "mouse", primary: false};
let a = new action.Action(id, "pointer", actionItem.type);
let wrongInputState = new action.InputState.Pointer("pause", true);
action.inputStateMap.set(id, wrongInputState)
action.inputStateMap.set(id, wrongInputState);
checkErrors(
/to be mapped to InputState whose subtype is/, action.processPointerAction,
[id, parameters, a],
@ -378,9 +378,22 @@ add_test(function test_processPointerActionInputStateMap() {
run_next_test();
});
add_test(function test_createInputState() {
for (let kind in action.InputState) {
let state = new action.InputState[kind]();
ok(state);
if (kind === "Null") {
equal(state.type, "none");
} else {
equal(state.type, kind.toLowerCase());
}
}
run_next_test();
});
add_test(function test_extractActionChainValidation() {
for (let actions of [-1, "a", undefined, null]) {
let message = `actions: ${getTypeString(actions)}`
let message = `actions: ${getTypeString(actions)}`;
Assert.throws(() => action.Chain.fromJson(actions),
InvalidArgumentError, message);
Assert.throws(() => action.Chain.fromJson(actions),

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

@ -38,6 +38,7 @@ module.exports = {
"is": false,
"isnot": false,
"ok": false,
"PromiseDebugging": false,
"privateNoteIntentionalCrash": false,
"registerCleanupFunction": false,
"requestLongerTimeout": false,

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

@ -93,4 +93,5 @@ class MochitestCommands(object):
description='Run the mochitest harness.',
parser=setup_argument_parser)
def mochitest(self, **kwargs):
self.context.activate_mozharness_venv()
return run_mochitest(self.context, **kwargs)

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

@ -76,6 +76,9 @@ CATEGORIES = {
}
IS_WIN = sys.platform in ('win32', 'cygwin')
def ancestors(path, depth=0):
"""Emit the parent directories of a path."""
count = 1
@ -88,6 +91,32 @@ def ancestors(path, depth=0):
count += 1
def activate_mozharness_venv(context):
"""Activate the mozharness virtualenv in-process."""
venv = os.path.join(context.mozharness_workdir,
context.mozharness_config.get('virtualenv_path', 'venv'))
if not os.path.isdir(venv):
print("No mozharness virtualenv detected at '{}'.".format(venv))
return 1
venv_bin = os.path.join(venv, 'Scripts' if IS_WIN else 'bin')
activate_path = os.path.join(venv_bin, 'activate_this.py')
execfile(activate_path, dict(__file__=activate_path))
if isinstance(os.environ['PATH'], unicode):
os.environ['PATH'] = os.environ['PATH'].encode('utf-8')
# sys.executable is used by mochitest-media to start the websocketprocessbridge,
# for some reason it doesn't get set when calling `activate_this.py` so set it
# here instead.
binary = 'python'
if IS_WIN:
binary += '.exe'
sys.executable = os.path.join(venv_bin, binary)
def find_firefox(context):
"""Try to automagically find the firefox binary."""
import mozinstall
@ -176,6 +205,9 @@ def bootstrap(test_package_root):
if config:
return os.path.join(config['base_work_dir'], config['work_dir'])
if key == 'activate_mozharness_venv':
return types.MethodType(activate_mozharness_venv, context)
mach = mach.main.Mach(os.getcwd())
mach.populate_context_handler = populate_context

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

@ -61,4 +61,5 @@ class MochitestCommands(object):
description='Run the xpcshell harness.',
parser=parser_desktop)
def xpcshell(self, **kwargs):
self.context.activate_mozharness_venv()
return run_xpcshell(self.context, **kwargs)

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

@ -52,6 +52,7 @@ module.exports = {
"notEqual": false,
"notStrictEqual": false,
"ok": false,
"PromiseDebugging": false,
"runningInParent": false,
"run_next_test": false,
"run_test": false,

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

@ -169,7 +169,7 @@ module.exports = {
"no-trailing-spaces": "error",
// No using undeclared variables
// "no-undef": "error",
"no-undef": "error",
// Error on newline where a semicolon is needed
"no-unexpected-multiline": "error",

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

@ -2,5 +2,6 @@
module.exports = {
"rules": {
"no-undef": "off"
}
};

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

@ -901,6 +901,43 @@ var insertSyncLivemark = Task.async(function* (insertInfo) {
return insertBookmarkMetadata(livemarkItem, insertInfo);
});
// Keywords are a 1 to 1 mapping between strings and pairs of (URL, postData).
// (the postData is not synced, so we ignore it). Sync associates keywords with
// bookmarks, which is not really accurate. -- We might already have a keyword
// with that name, or we might already have another bookmark with that URL with
// a different keyword, etc.
//
// If we don't handle those cases by removing the conflicting keywords first,
// the insertion will fail, and the keywords will either be wrong, or missing.
// This function handles those cases.
var removeConflictingKeywords = Task.async(function* (bookmarkURL, newKeyword) {
let entryForURL = yield PlacesUtils.keywords.fetch({
url: bookmarkURL
});
if (entryForURL && entryForURL.keyword !== newKeyword) {
yield PlacesUtils.keywords.remove({
keyword: entryForURL.keyword,
source: SOURCE_SYNC,
});
// This will cause us to reupload this record for this sync, but without it,
// we will risk data corruption.
yield BookmarkSyncUtils.addSyncChangesForBookmarksWithURL(entryForURL.url.href);
}
if (!newKeyword) {
return;
}
let entryForNewKeyword = yield PlacesUtils.keywords.fetch({
keyword: newKeyword
});
if (entryForNewKeyword) {
yield PlacesUtils.keywords.remove({
keyword: entryForNewKeyword.keyword,
source: SOURCE_SYNC,
});
yield BookmarkSyncUtils.addSyncChangesForBookmarksWithURL(entryForNewKeyword.url.href);
}
});
// Sets annotations, keywords, and tags on a new bookmark. Returns a Sync
// bookmark object.
var insertBookmarkMetadata = Task.async(function* (bookmarkItem, insertInfo) {
@ -923,6 +960,7 @@ var insertBookmarkMetadata = Task.async(function* (bookmarkItem, insertInfo) {
}
if (insertInfo.keyword) {
yield removeConflictingKeywords(bookmarkItem.url.href, insertInfo.keyword);
yield PlacesUtils.keywords.insert({
keyword: insertInfo.keyword,
url: bookmarkItem.url.href,
@ -1136,15 +1174,7 @@ var updateBookmarkMetadata = Task.async(function* (oldBookmarkItem,
if (updateInfo.hasOwnProperty("keyword")) {
// Unconditionally remove the old keyword.
let entry = yield PlacesUtils.keywords.fetch({
url: oldBookmarkItem.url.href,
});
if (entry) {
yield PlacesUtils.keywords.remove({
keyword: entry.keyword,
source: SOURCE_SYNC,
});
}
yield removeConflictingKeywords(oldBookmarkItem.url.href, updateInfo.keyword);
if (updateInfo.keyword) {
yield PlacesUtils.keywords.insert({
keyword: updateInfo.keyword,

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

@ -619,6 +619,98 @@ add_task(function* test_update_keyword() {
"Removing keyword for URL without existing keyword should succeed");
}
let item2;
do_print("Insert removes other item's keyword if they are the same");
{
let updatedItem = yield PlacesSyncUtils.bookmarks.update({
syncId: item.syncId,
keyword: "test",
});
equal(updatedItem.keyword, "test", "Initial update succeeds");
item2 = yield PlacesSyncUtils.bookmarks.insert({
kind: "bookmark",
parentSyncId: "menu",
url: "https://mozilla.org/1",
syncId: makeGuid(),
keyword: "test",
});
equal(item2.keyword, "test", "insert with existing should succeed");
updatedItem = yield PlacesSyncUtils.bookmarks.fetch(item.syncId);
ok(!updatedItem.keyword, "initial item no longer has keyword");
let entry = yield PlacesUtils.keywords.fetch({
url: "https://mozilla.org",
});
ok(!entry, "Direct check for original url keyword gives nothing");
let newEntry = yield PlacesUtils.keywords.fetch("test");
ok(newEntry, "Keyword should exist for new item");
equal(newEntry.url.href, "https://mozilla.org/1", "Keyword should point to new url");
}
do_print("Insert updates other item's keyword if they are the same url");
{
let updatedItem = yield PlacesSyncUtils.bookmarks.update({
syncId: item.syncId,
keyword: "test2",
});
equal(updatedItem.keyword, "test2", "Initial update succeeds");
let newItem = yield PlacesSyncUtils.bookmarks.insert({
kind: "bookmark",
parentSyncId: "menu",
url: "https://mozilla.org",
syncId: makeGuid(),
keyword: "test3",
});
equal(newItem.keyword, "test3", "insert with existing should succeed");
updatedItem = yield PlacesSyncUtils.bookmarks.fetch(item.syncId);
equal(updatedItem.keyword, "test3", "initial item has new keyword");
}
do_print("Update removes other item's keyword if they are the same");
{
let updatedItem = yield PlacesSyncUtils.bookmarks.update({
syncId: item.syncId,
keyword: "test4",
});
equal(updatedItem.keyword, "test4", "Initial update succeeds");
let updatedItem2 = yield PlacesSyncUtils.bookmarks.update({
syncId: item2.syncId,
keyword: "test4",
});
equal(updatedItem2.keyword, "test4", "New update succeeds");
updatedItem = yield PlacesSyncUtils.bookmarks.fetch(item.syncId);
ok(!updatedItem.keyword, "initial item no longer has keyword");
let entry = yield PlacesUtils.keywords.fetch({
url: "https://mozilla.org",
});
ok(!entry, "Direct check for original url keyword gives nothing");
let newEntry = yield PlacesUtils.keywords.fetch("test4");
ok(newEntry, "Keyword should exist for new item");
equal(newEntry.url.href, "https://mozilla.org/1", "Keyword should point to new url");
}
do_print("Update url updates it's keyword if url already has keyword");
{
let updatedItem = yield PlacesSyncUtils.bookmarks.update({
syncId: item.syncId,
keyword: "test4",
});
equal(updatedItem.keyword, "test4", "Initial update succeeds");
let updatedItem2 = yield PlacesSyncUtils.bookmarks.update({
syncId: item2.syncId,
keyword: "test5",
});
equal(updatedItem2.keyword, "test5", "New update succeeds");
yield PlacesSyncUtils.bookmarks.update({
syncId: item2.syncId,
url: item.url.href,
});
updatedItem2 = yield PlacesSyncUtils.bookmarks.fetch(item2.syncId);
equal(updatedItem2.keyword, "test4", "Item keyword has been updated");
updatedItem = yield PlacesSyncUtils.bookmarks.fetch(item.syncId);
equal(updatedItem.keyword, "test4", "Initial item still has keyword");
}
yield PlacesUtils.bookmarks.eraseEverything();
yield PlacesSyncUtils.bookmarks.reset();
});

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

@ -631,8 +631,11 @@ nsUrlClassifierDBServiceWorker::FinishUpdate()
mUpdateStatus : NS_ERROR_UC_UPDATE_UNKNOWN;
}
Telemetry::Accumulate(Telemetry::URLCLASSIFIER_UPDATE_ERROR, provider,
NS_ERROR_GET_CODE(updateStatus));
// Do not record telemetry for testing tables.
if (!provider.Equals(TESTING_TABLE_PROVIDER_NAME)) {
Telemetry::Accumulate(Telemetry::URLCLASSIFIER_UPDATE_ERROR, provider,
NS_ERROR_GET_CODE(updateStatus));
}
mMissCache.Clear();
@ -989,7 +992,7 @@ nsUrlClassifierLookupCallback::LookupComplete(nsTArray<LookupResult>* results)
// has registered the table. In the second case we should not call
// complete.
if ((!gethashUrl.IsEmpty() ||
StringBeginsWith(result.mTableName, NS_LITERAL_CSTRING("test-"))) &&
StringBeginsWith(result.mTableName, NS_LITERAL_CSTRING("test"))) &&
mDBService->GetCompleter(result.mTableName,
getter_AddRefs(completer))) {

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

@ -24,6 +24,7 @@
#include "mozilla/Telemetry.h"
#include "nsContentUtils.h"
#include "nsIURLFormatter.h"
#include "Classifier.h"
static const char* gQuitApplicationMessage = "quit-application";
@ -97,6 +98,7 @@ nsUrlClassifierStreamUpdater::DownloadDone()
mSuccessCallback = nullptr;
mUpdateErrorCallback = nullptr;
mDownloadErrorCallback = nullptr;
mTelemetryProvider.Truncate();
}
///////////////////////////////////////////////////////////////////////////////
@ -283,6 +285,14 @@ nsUrlClassifierStreamUpdater::DownloadUpdates(
return rv;
}
nsCOMPtr<nsIUrlClassifierUtils> urlUtil =
do_GetService(NS_URLCLASSIFIERUTILS_CONTRACTID);
nsTArray<nsCString> tables;
mozilla::safebrowsing::Classifier::SplitTables(aRequestTables, tables);
urlUtil->GetTelemetryProvider(tables.SafeElementAt(0, EmptyCString()),
mTelemetryProvider);
mSuccessCallback = aSuccessCallback;
mUpdateErrorCallback = aUpdateErrorCallback;
mDownloadErrorCallback = aDownloadErrorCallback;
@ -635,17 +645,11 @@ nsUrlClassifierStreamUpdater::OnStartRequest(nsIRequest *request,
spec.get(), this));
}
nsCOMPtr<nsIUrlClassifierUtils> urlUtil =
do_GetService(NS_URLCLASSIFIERUTILS_CONTRACTID);
nsCString provider;
urlUtil->GetTelemetryProvider(mStreamTable, provider);
if (NS_FAILED(status)) {
// Assume we're overloading the server and trigger backoff.
downloadError = true;
mozilla::Telemetry::Accumulate(mozilla::Telemetry::URLCLASSIFIER_UPDATE_REMOTE_STATUS2,
provider, 15 /* unknown response code */);
mTelemetryProvider, 15 /* unknown response code */);
} else {
bool succeeded = false;
@ -656,7 +660,7 @@ nsUrlClassifierStreamUpdater::OnStartRequest(nsIRequest *request,
rv = httpChannel->GetResponseStatus(&requestStatus);
NS_ENSURE_SUCCESS(rv, rv);
mozilla::Telemetry::Accumulate(mozilla::Telemetry::URLCLASSIFIER_UPDATE_REMOTE_STATUS2,
provider, HTTPStatusToBucket(requestStatus));
mTelemetryProvider, HTTPStatusToBucket(requestStatus));
LOG(("nsUrlClassifierStreamUpdater::OnStartRequest %s (%d)", succeeded ?
"succeeded" : "failed", requestStatus));
if (!succeeded) {

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

@ -73,7 +73,10 @@ private:
bool mInitialized;
bool mDownloadError;
bool mBeganStream;
// Note that mStreamTable is only used by v2, it is empty for v4 update.
nsCString mStreamTable;
nsCOMPtr<nsIChannel> mChannel;
nsCOMPtr<nsIUrlClassifierDBService> mDBService;
nsCOMPtr<nsITimer> mTimer;
@ -98,6 +101,10 @@ private:
nsCOMPtr<nsIUrlClassifierCallback> mSuccessCallback;
nsCOMPtr<nsIUrlClassifierCallback> mUpdateErrorCallback;
nsCOMPtr<nsIUrlClassifierCallback> mDownloadErrorCallback;
// The provider for current update request and should be only used by telemetry
// since it would show up as "other" for any other providers.
nsCString mTelemetryProvider;
};
#endif // nsUrlClassifierStreamUpdater_h_

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

@ -279,7 +279,9 @@ nsUrlClassifierUtils::GetProvider(const nsACString& aTableName,
{
MutexAutoLock lock(mProviderDictLock);
nsCString* provider = nullptr;
if (mProviderDict.Get(aTableName, &provider)) {
if (StringBeginsWith(aTableName, NS_LITERAL_CSTRING("test"))) {
aProvider = NS_LITERAL_CSTRING(TESTING_TABLE_PROVIDER_NAME);
} else if (mProviderDict.Get(aTableName, &provider)) {
aProvider = provider ? *provider : EmptyCString();
} else {
aProvider = EmptyCString();
@ -296,7 +298,8 @@ nsUrlClassifierUtils::GetTelemetryProvider(const nsACString& aTableName,
// Empty provider is filtered as "other"
if (!NS_LITERAL_CSTRING("mozilla").Equals(aProvider) &&
!NS_LITERAL_CSTRING("google").Equals(aProvider) &&
!NS_LITERAL_CSTRING("google4").Equals(aProvider)) {
!NS_LITERAL_CSTRING("google4").Equals(aProvider) &&
!NS_LITERAL_CSTRING(TESTING_TABLE_PROVIDER_NAME).Equals(aProvider)) {
aProvider.Assign(NS_LITERAL_CSTRING("other"));
}

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

@ -10,6 +10,8 @@
#include "nsClassHashtable.h"
#include "nsIObserver.h"
#define TESTING_TABLE_PROVIDER_NAME "test"
class nsUrlClassifierUtils final : public nsIUrlClassifierUtils,
public nsIObserver
{

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

@ -0,0 +1,7 @@
"use strict";
module.exports = {
"rules": {
"no-undef": "off"
}
};

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

@ -1,3 +1,5 @@
/* import-globals-from crasher_subprocess_head.js */
// Let the event loop process a bit before crashing.
if (shouldDelay) {
let shouldCrashNow = false;

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

@ -1,11 +1,11 @@
function run_test() {
do_crash(function() {
appAddr = CrashTestUtils.saveAppMemory();
crashReporter.registerAppMemory(appAddr, 32);
},
function(mdump, extra) {
do_check_true(mdump.exists());
do_check_true(mdump.fileSize > 0);
do_check_true(CrashTestUtils.dumpCheckMemory(mdump.path));
});
let appAddr = CrashTestUtils.saveAppMemory();
crashReporter.registerAppMemory(appAddr, 32);
},
function(mdump, extra) {
do_check_true(mdump.exists());
do_check_true(mdump.fileSize > 0);
do_check_true(CrashTestUtils.dumpCheckMemory(mdump.path));
});
}

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

@ -138,6 +138,7 @@ GMPInstallManager.prototype = {
*/
installAddon(gmpAddon) {
if (this._deferred) {
let log = getScopedLogger("GMPInstallManager.installAddon");
log.error("previous error encountered");
return Promise.reject({type: "previouserrorencountered"});
}

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

@ -20,6 +20,8 @@ Cu.import("resource://gre/modules/XPCOMUtils.jsm", this);
XPCOMUtils.defineLazyModuleGetter(this, "Promise",
"resource://gre/modules/Promise.jsm");
var pSlice = Array.prototype.slice;
this.ObjectUtils = {
/**
* This tests objects & values for deep equality.

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

@ -39,6 +39,11 @@
// that Components is not defined in worker threads, so no instance of Cu can
// be obtained.
// As this can be loaded in several ways, allow require and module to be defined.
/* global module:false require:false */
// This is allowed in workers.
/* global setImmediate:false */
var Cu = this.require ? require("chrome").Cu : Components.utils;
var Cc = this.require ? require("chrome").Cc : Components.classes;
var Ci = this.require ? require("chrome").Ci : Components.interfaces;

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

@ -57,13 +57,13 @@ function saveStreamAsync(aPath, aStream, aFile) {
try {
aStream.close();
} catch (e) {
logger.error("Failed to close JAR stream for " + aPath);
Cu.reportError("Failed to close JAR stream for " + aPath);
}
aFile.close().then(function() {
deferred.reject(error);
}, function(e) {
logger.error("Failed to close file for " + aPath);
Cu.reportError("Failed to close file for " + aPath);
deferred.reject(error);
});
}

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

@ -10,8 +10,8 @@ MOCHITEST_MANIFESTS += ['tests/mochitest/mochitest.ini']
MOCHITEST_CHROME_MANIFESTS += ['tests/chrome/chrome.ini']
TESTING_JS_MODULES += [
'tests/MockDocument.jsm',
'tests/PromiseTestUtils.jsm',
'tests/modules/MockDocument.jsm',
'tests/modules/PromiseTestUtils.jsm',
'tests/xpcshell/TestIntegration.jsm',
]

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

@ -1,7 +1,9 @@
var InlineSpellChecker;
function test() {
let tempScope = {};
Components.utils.import("resource://gre/modules/InlineSpellChecker.jsm", tempScope);
let InlineSpellChecker = tempScope.InlineSpellChecker;
InlineSpellChecker = tempScope.InlineSpellChecker;
ok(InlineSpellChecker, "InlineSpellChecker class exists");
for (var fname in tests) {

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

@ -3,6 +3,8 @@
<html>
<head>
<script type="text/javascript">
/* global addMessageListener, sendAsyncMessage, removeMessageListener */
addMessageListener("Ping", function(message) {
sendAsyncMessage("Pong", {
str: message.data.str,

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

@ -0,0 +1,7 @@
"use strict";
module.exports = {
"extends": [
"../../../../testing/xpcshell/xpcshell.eslintrc.js"
]
};

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

@ -6,6 +6,9 @@
* will fail tests in this case, unless the test whitelists itself.
*/
// For this test we allow the global Assert to be modified.
/* global Assert:true */
"use strict";
this.EXPORTED_SYMBOLS = [

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

@ -101,4 +101,13 @@ add_task(function* test_deepEqual() {
} catch (e) {
Assert.ok(true, "Didn't recurse infinitely.");
}
let e = {a: 3, b: 4};
let f = {b: 4, a: 3};
function checkEquiv() {
return arguments;
}
Assert.ok(deepEqual(checkEquiv(e, f), checkEquiv(f, e)));
});

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

@ -850,7 +850,6 @@ add_task(function* test_direct() {
print("Error when executing SQL (" + error.result + "): " +
error.message);
print("Original error: " + error.error);
errors.push(error);
deferred.reject();
},

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

@ -12,6 +12,9 @@
* are identical to their original files.
*/
// Available to the js shell.
/* global snarf, scriptArgs, quit */
"use strict";
function ast(filename) {

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

@ -65,15 +65,33 @@ const globalCache = new Map();
* parents parameter which is a list of the parent nodes of the current node.
* Each returns an array of globals found.
*
* @param {String} path
* @param {String} filePath
* The absolute path of the file being parsed.
*/
function GlobalsForNode(path) {
this.path = path;
this.root = helpers.getRootDir(path);
function GlobalsForNode(filePath) {
this.path = filePath;
this.dirname = path.dirname(this.path)
this.root = helpers.getRootDir(this.path);
this.isWorker = helpers.getIsWorker(this.path);
}
GlobalsForNode.prototype = {
Program(node) {
if (!this.isWorker) {
return [];
}
return [
{name: "importScripts", writable: false},
// Only available to workers.
{name: "FileReaderSync", writable: false},
{name: "onmessage", writable: true},
// Only available to chrome workers, but since we don't know which is which,
// we make it available anyway.
{name: "ctypes", writable: false}
];
},
BlockComment(node, parents) {
let value = node.value.trim();
let match = /^import-globals-from\s+(.+)$/.exec(value);
@ -84,8 +102,7 @@ GlobalsForNode.prototype = {
let filePath = match[1].trim();
if (!path.isAbsolute(filePath)) {
let dirName = path.dirname(this.path);
filePath = path.resolve(dirName, filePath);
filePath = path.resolve(this.dirname, filePath);
}
return module.exports.getGlobalsForFile(filePath);
@ -93,8 +110,19 @@ GlobalsForNode.prototype = {
ExpressionStatement(node, parents) {
let isGlobal = helpers.getIsGlobalScope(parents);
let names = helpers.convertExpressionToGlobals(node, isGlobal, this.root);
return names.map(name => { return { name, writable: true }});
let globals = helpers.convertExpressionToGlobals(node, isGlobal, this.root);
// Map these globals now, as getGlobalsForFile is pre-mapped.
globals = globals.map(name => { return { name, writable: true }});
if (this.isWorker) {
let workerDetails = helpers.convertWorkerExpressionToGlobals(node,
isGlobal, this.root, this.dirname);
globals = globals.concat(workerDetails.map(name => {
return { name, writable: true };
}));
}
return globals;
},
};
@ -106,6 +134,12 @@ module.exports = {
*
* @param {String} path
* The absolute path of the file to be parsed.
* @return {Array}
* An array of objects that contain details about the globals:
* - {String} name
* The name of the global.
* - {Boolean} writable
* If the global is writeable or not.
*/
getGlobalsForFile(path) {
if (globalCache.has(path)) {
@ -179,6 +213,9 @@ module.exports = {
for (let type of Object.keys(GlobalsForNode.prototype)) {
parser[type] = function(node) {
if (type === "Program") {
globalScope = context.getScope();
}
let globals = handler[type](node, context.getAncestors());
helpers.addGlobals(globals, globalScope);
}

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

@ -38,6 +38,8 @@ var imports = [
/^(?:Cu|Components\.utils)\.import\(".*\/((.*?)\.jsm?)"(?:, this)?\)/,
];
var workerImportFilenameMatch = /(.*\/)*(.*?\.jsm?)/;
module.exports = {
/**
* Gets the abstract syntax tree (AST) of the JavaScript source code contained
@ -168,8 +170,40 @@ module.exports = {
* The root of the repository.
*
* @return {Array}
* An array of variable names defined.
* An array of global variable names defined.
*/
convertWorkerExpressionToGlobals: function(node, isGlobal, repository, dirname) {
var getGlobalsForFile = require("./globals").getGlobalsForFile;
if (!modules) {
modules = require(path.join(repository, "tools", "lint", "eslint", "modules.json"));
}
let results = [];
let expr = node.expression;
if (node.expression.type === "CallExpression" &&
expr.callee &&
expr.callee.type === "Identifier" &&
expr.callee.name === "importScripts") {
for (var arg of expr.arguments) {
var match = arg.value.match(workerImportFilenameMatch);
if (match) {
if (!match[1]) {
let filePath = path.resolve(dirname, match[2]);
if (fs.existsSync(filePath)) {
let additionalGlobals = getGlobalsForFile(filePath);
results = results.concat(additionalGlobals);
}
} else if (match[2] in modules) {
results.push(modules[match[2]]);
}
}
}
}
return results;
},
convertExpressionToGlobals: function(node, isGlobal, repository) {
if (!modules) {
modules = require(path.join(repository, "tools", "lint", "eslint", "modules.json"));
@ -460,6 +494,12 @@ module.exports = {
return null;
},
getIsWorker: function(filePath) {
let filename = path.basename(this.cleanUpPath(filePath)).toLowerCase();
return filename.includes("worker");
},
/**
* Gets the root directory of the repository by walking up directories until
* a .eslintignore file is found.

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

@ -1,6 +1,6 @@
{
"name": "eslint-plugin-mozilla",
"version": "0.2.16",
"version": "0.2.17",
"description": "A collection of rules that help enforce JavaScript coding standard in the Mozilla project.",
"keywords": [
"eslint",

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

@ -70,6 +70,7 @@
"EventUtils.js": ["disableNonTestMouseEvents", "sendMouseEvent", "sendChar", "sendString", "sendKey", "synthesizeMouse", "synthesizeTouch", "synthesizeMouseAtPoint", "synthesizeTouchAtPoint", "synthesizeMouseAtCenter", "synthesizeTouchAtCenter", "synthesizeWheel", "synthesizeKey", "synthesizeMouseExpectEvent", "synthesizeKeyExpectEvent", "synthesizeText", "synthesizeComposition", "synthesizeQuerySelectedText"],
"Extension.jsm": ["Extension", "ExtensionData"],
"ExtensionAPI.jsm": ["ExtensionAPI", "ExtensionAPIs"],
"ExtensionsUI.jsm": ["ExtensionsUI"],
"extension-storage.js": ["ExtensionStorageEngine", "EncryptionRemoteTransformer", "KeyRingEncryptionRemoteTransformer"],
"ExtensionXPCShellUtils.jsm": ["ExtensionTestUtils"],
"fakeservices.js": ["FakeCryptoService", "FakeFilesystemService", "FakeGUIDService", "fakeSHA256HMAC"],
@ -110,6 +111,7 @@
"import_sub_module.jsm": ["SUBMODULE_IMPORTED", "test_obj"],
"InlineSpellChecker.jsm": ["InlineSpellChecker", "SpellCheckHelper"],
"JNI.jsm": ["JNI", "android_log"],
"JSDOMParser.js": ["JSDOMParser"],
"Jsbeautify.jsm": ["jsBeautify"],
"jsdebugger.jsm": ["addDebuggerToGlobal"],
"json2.js": ["JSON"],
@ -149,7 +151,7 @@
"offlineAppCache.jsm": ["OfflineAppCacheHelper"],
"OrientationChangeHandler.jsm": [],
"os.js": ["listDirectory", "getFileForPath", "abspath", "getPlatform"],
"osfile.jsm": ["OS"],
"osfile.jsm": ["OS", "require"],
"osfile_async_front.jsm": ["OS"],
"osfile_native.jsm": ["read"],
"osfile_shared_allthreads.jsm": ["LOG", "clone", "Config", "Constants", "Type", "HollowStructure", "OSError", "Library", "declareFFI", "declareLazy", "declareLazyFFI", "normalizeBufferArgs", "projectValue", "isArrayBuffer", "isTypedArray", "defineLazyGetter", "OS"],
@ -176,6 +178,7 @@
"PromiseWorker.jsm": ["BasePromiseWorker"],
"PushCrypto.jsm": ["PushCrypto", "concatArray"],
"quit.js": ["goQuitApplication"],
"Readability.js": ["Readability"],
"record.js": ["WBORecord", "RecordManager", "CryptoWrapper", "CollectionKeyManager", "Collection"],
"recursive_importA.jsm": ["foo", "bar"],
"recursive_importB.jsm": ["baz", "qux"],
@ -187,6 +190,7 @@
"responsivedesign.jsm": ["ResponsiveUIManager"],
"rest.js": ["RESTRequest", "RESTResponse", "TokenAuthenticatedRESTRequest", "SyncStorageRequest"],
"rotaryengine.js": ["RotaryEngine", "RotaryRecord", "RotaryStore", "RotaryTracker"],
"require.js": ["require"],
"RTCStatsReport.jsm": ["convertToRTCStatsReport"],
"scratchpad-manager.jsm": ["ScratchpadManager"],
"server.js": ["MarionetteServer"],