Merge mozilla-central to mozilla-inbound. r=merge a=merge CLOSED TREE

This commit is contained in:
Attila Craciun 2017-10-26 12:34:39 +03:00
commit 4d25367716
411 changed files with 5019 additions and 3050 deletions

View File

@ -179,7 +179,7 @@ public:
* Return node type information of DOM node associated with the accessible.
*/
bool IsContent() const
{ return GetNode() && GetNode()->IsNodeOfType(nsINode::eCONTENT); }
{ return GetNode() && GetNode()->IsContent(); }
/**
* Return the unique identifier of the accessible.

View File

@ -106,8 +106,9 @@ sdnAccessible::get_nodeInfo(BSTR __RPC_FAR* aNodeName,
DOMNode->GetNodeValue(nodeValue);
*aNodeValue = ::SysAllocString(nodeValue.get());
*aNameSpaceID = mNode->IsNodeOfType(nsINode::eCONTENT) ?
static_cast<short>(mNode->AsContent()->GetNameSpaceID()) : 0;
*aNameSpaceID = mNode->IsContent()
? static_cast<short>(mNode->AsContent()->GetNameSpaceID())
: 0;
// This is a unique ID for every content node. The 3rd party accessibility
// application can compare this to the childID we return for events such as

View File

@ -26,9 +26,7 @@ include $(topsrcdir)/config/config.mk
# If we are trying to show an error dialog about the lack of SSE2 support,
# make sure that code itself doesn't use SSE2.
ifdef MOZ_LINUX_32_SSE2_STARTUP_ERROR
CXXFLAGS := $(filter-out -march=% -msse -msse2 -mfpmath=sse,$(CXXFLAGS))
CXX := $(filter-out -march=% -msse -msse2 -mfpmath=sse,$(CXX))
CXXFLAGS += -mno-sse -mno-sse2 -mfpmath=387
CXX += -march=pentiumpro
endif

View File

@ -117,6 +117,12 @@ if CONFIG['MOZ_GPSD']:
if CONFIG['MOZ_LINUX_32_SSE2_STARTUP_ERROR']:
DEFINES['MOZ_LINUX_32_SSE2_STARTUP_ERROR'] = True
COMPILE_FLAGS['OS_CXXFLAGS'] = [
f for f in COMPILE_FLAGS.get('OS_CXXFLAGS', [])
if not f.startswith('-march=') and f not in ('-msse', '-msse2', '-mfpmath=sse')
] + [
'-mno-sse', '-mno-sse2', '-mfpmath=387',
]
for icon in ('firefox', 'document', 'newwindow', 'newtab', 'pbmode'):
DEFINES[icon.upper() + '_ICO'] = '"%s/%s/%s.ico"' % (

View File

@ -1407,6 +1407,9 @@ pref("identity.fxaccounts.remote.force_auth.uri", "https://accounts.firefox.com/
// The remote content URL shown for signin in. Must use HTTPS.
pref("identity.fxaccounts.remote.signin.uri", "https://accounts.firefox.com/signin?service=sync&context=fx_desktop_v3");
// The remote content URL shown for the email (FxA determines if we show sign-in or sign-up) endpoint. Must use HTTPS.
pref("identity.fxaccounts.remote.email.uri", "https://accounts.firefox.com/?service=sync&context=fx_desktop_v3&action=email");
// The remote content URL where FxAccountsWebChannel messages originate.
pref("identity.fxaccounts.remote.webchannel.uri", "https://accounts.firefox.com/");

View File

@ -150,6 +150,17 @@ function init() {
});
}
break;
case "email":
if (user) {
// asking to sign-in/up when already signed in just shows manage.
show("stage", "manage");
} else {
return fxAccounts.promiseAccountsEmailURI().then(url => {
show("remote");
wrapper.init(url, urlParams);
});
}
break;
case "signup":
if (user) {
// asking to sign-up when already signed in just shows manage.

View File

@ -4,15 +4,7 @@
// The test runs from a container ID 2.
// Output: we have no referrer.
function getReferrerTest(aTestNumber) {
let testCase = _referrerTests[aTestNumber];
if (testCase) {
// We want all the referrer tests to fail!
testCase.result = "";
}
return testCase;
}
getReferrerTest = getRemovedReferrerTest;
function startNewTabTestCase(aTestNumber) {
info("browser_referrer_open_link_in_container_tab: " +

View File

@ -1,6 +1,11 @@
// Tests referrer on context menu navigation - open link in new private window.
// Selects "open link in new private window" from the context menu.
// The test runs from a regular browsing window.
// Output: we have no referrer.
getReferrerTest = getRemovedReferrerTest;
function startNewPrivateWindowTestCase(aTestNumber) {
info("browser_referrer_open_link_in_private: " +
getReferrerTestDescription(aTestNumber));

View File

@ -77,6 +77,23 @@ function getReferrerTest(aTestNumber) {
return _referrerTests[aTestNumber];
}
/**
* Returns shimmed test object for a given test number.
*
* @param aTestNumber The test number - 0, 1, 2, ...
* @return The test object with result hard-coded to "",
* or undefined if the number is out of range.
*/
function getRemovedReferrerTest(aTestNumber) {
let testCase = _referrerTests[aTestNumber];
if (testCase) {
// We want all the referrer tests to fail!
testCase.result = "";
}
return testCase;
}
/**
* Returns a brief summary of the test, for logging.
* @param aTestNumber The test number - 0, 1, 2...

View File

@ -130,7 +130,10 @@ var gTests = [
},
{
desc: "Test action=signup - user logged in",
teardown: () => gBrowser.removeCurrentTab(),
async teardown() {
gBrowser.removeCurrentTab();
await signOut();
},
async run() {
const expected_url = "https://example.com/?is_sign_up";
setPref("identity.fxaccounts.remote.signup.uri", expected_url);
@ -147,6 +150,43 @@ var gTests = [
});
},
},
{
desc: "Test action=email - no user logged in",
teardown: () => gBrowser.removeCurrentTab(),
async run() {
const expected_url = "https://example.com/?is_email";
setPref("identity.fxaccounts.remote.email.uri", expected_url);
let [tab, url] = await promiseNewTabWithIframeLoadEvent("about:accounts?action=email");
is(url, expected_url, "action=email got the expected URL");
// we expect the remote iframe to be shown.
await checkVisibilities(tab, {
stage: false, // parent of 'manage' and 'intro'
manage: false,
intro: false, // this is "get started"
remote: true,
networkError: false
});
},
},
{
desc: "Test action=email - user logged in",
teardown: () => gBrowser.removeCurrentTab(),
async run() {
const expected_url = "https://example.com/?is_email";
setPref("identity.fxaccounts.remote.email.uri", expected_url);
await setSignedInUser();
let tab = await promiseNewTabLoadEvent("about:accounts?action=email");
await fxAccounts.getSignedInUser();
// we expect "manage" to be shown.
await checkVisibilities(tab, {
stage: true, // parent of 'manage' and 'intro'
manage: true,
intro: false, // this is "get started"
remote: false,
networkError: false
});
},
},
{
desc: "Test action=reauth",
async teardown() {

View File

@ -105,3 +105,17 @@ add_task(async function test_customizationui_panel_touch() {
CustomizableUI.reset();
});
// Test the overflow menu panel.
add_task(async function test_overflow_panel_touch() {
// Move something in the overflow menu to make the button appear.
CustomizableUI.addWidgetToArea("library-button", CustomizableUI.AREA_FIXED_OVERFLOW_PANEL);
await BrowserTestUtils.waitForCondition(() =>
CustomizableUI.getPlacementOfWidget("library-button").area == CustomizableUI.AREA_FIXED_OVERFLOW_PANEL);
let overflowPanel = document.getElementById("widget-overflow");
let target = document.getElementById("nav-bar-overflow-button");
await openAndCheckMenu(overflowPanel, target);
CustomizableUI.reset();
});

View File

@ -288,6 +288,14 @@ function openLinkIn(url, where, params) {
aTriggeringPrincipal = useOAForPrincipal(aTriggeringPrincipal);
if (!w || where == "window") {
let features = "chrome,dialog=no,all";
if (aIsPrivate) {
features += ",private";
// To prevent regular browsing data from leaking to private browsing sites,
// strip the referrer when opening a new private window. (See Bug: 1409226)
aNoReferrer = true;
}
// This propagates to window.arguments.
var sa = Cc["@mozilla.org/array;1"].
createInstance(Ci.nsIMutableArray);
@ -332,11 +340,6 @@ function openLinkIn(url, where, params) {
sa.appendElement(aPrincipal);
sa.appendElement(aTriggeringPrincipal);
let features = "chrome,dialog=no,all";
if (aIsPrivate) {
features += ",private";
}
const sourceWindow = (w || window);
let win;
if (params.frameOuterWindowID != undefined && sourceWindow) {

View File

@ -4312,7 +4312,7 @@ OverflowableToolbar.prototype = {
}
},
show() {
show(aEvent) {
if (this._panel.state == "open") {
return Promise.resolve();
}
@ -4333,10 +4333,10 @@ OverflowableToolbar.prototype = {
// Ensure we update the gEditUIVisible flag when opening the popup, in
// case the edit controls are in it.
this._panel.addEventListener("popupshowing", () => doc.defaultView.updateEditUIVisibility(), {once: true});
this._panel.openPopup(anchor || this._chevron);
this._panel.openPopup(anchor || this._chevron, { triggerEvent: aEvent });
this._chevron.open = true;
this._panel.addEventListener("popupshown", aEvent => {
this._panel.addEventListener("popupshown", () => {
this._panel.addEventListener("dragover", this);
this._panel.addEventListener("dragend", this);
resolve();
@ -4349,7 +4349,7 @@ OverflowableToolbar.prototype = {
this._panel.hidePopup();
this._chevron.open = false;
} else if (this._panel.state != "hiding" && !this._chevron.disabled) {
this.show();
this.show(aEvent);
}
},

View File

@ -542,8 +542,10 @@
<toolbarseparator/>
<toolbaritem id="appMenu-zoom-controls" class="toolbaritem-combined-buttons" closemenu="none">
<!-- Use a spacer, because panel sizing code gets confused when using CSS methods. -->
<spacer/>
<spacer class="before-label"/>
<label value="&fullZoom.label;"/>
<!-- This spacer keeps the scrollbar from overlapping the view. -->
<spacer class="after-label"/>
<toolbarbutton id="appMenu-zoomReduce-button"
class="subviewbutton subviewbutton-iconic"
command="cmd_fullZoomReduce"
@ -568,8 +570,10 @@
<toolbarseparator/>
<toolbaritem id="appMenu-edit-controls" class="toolbaritem-combined-buttons" closemenu="none">
<!-- Use a spacer, because panel sizing code gets confused when using CSS methods. -->
<spacer/>
<spacer class="before-label"/>
<label value="&editMenu.label;"/>
<!-- This spacer keeps the scrollbar from overlapping the view. -->
<spacer class="after-label"/>
<toolbarbutton id="appMenu-cut-button"
class="subviewbutton subviewbutton-iconic"
command="cmd_cut"

View File

@ -206,7 +206,6 @@
closemenu="single"
selection="link|host"
selectiontype="single"
hideifprivatebrowsing="true"
forcehideselection="bookmark"/>
<menuseparator id="placesContext_deleteSeparator"/>
<menuitem id="placesContext_sortBy:name"

View File

@ -2617,20 +2617,26 @@ function getControllingExtensionEl(settingName) {
async function handleControllingExtension(type, settingName) {
let controllingExtensionId = await getControllingExtensionId(type, settingName);
let addon = controllingExtensionId
&& await AddonManager.getAddonByID(controllingExtensionId);
if (controllingExtensionId) {
showControllingExtension(settingName, controllingExtensionId);
// Sometimes the ExtensionSettingsStore gets in a bad state where it thinks
// an extension is controlling a setting but the extension has been uninstalled
// outside of the regular lifecycle. If the extension isn't currently installed
// then we should treat the setting as not being controlled.
// See https://bugzilla.mozilla.org/show_bug.cgi?id=1411046 for an example.
if (addon) {
showControllingExtension(settingName, addon);
} else {
hideControllingExtension(settingName);
}
return !!controllingExtensionId;
return !!addon;
}
async function showControllingExtension(settingName, extensionId) {
let extensionControlledContent = getControllingExtensionEl(settingName);
async function showControllingExtension(settingName, addon) {
// Tell the user what extension is controlling the setting.
let addon = await AddonManager.getAddonByID(extensionId);
let extensionControlledContent = getControllingExtensionEl(settingName);
const defaultIcon = "chrome://mozapps/skin/extensions/extensionGeneric.svg";
let stringParts = document
.getElementById("bundlePreferences")

View File

@ -1,3 +1,5 @@
XPCOMUtils.defineLazyModuleGetter(this, "ExtensionSettingsStore",
"resource://gre/modules/ExtensionSettingsStore.jsm");
XPCOMUtils.defineLazyServiceGetter(this, "aboutNewTabService",
"@mozilla.org/browser/aboutnewtab-service;1",
"nsIAboutNewTabService");
@ -274,3 +276,66 @@ add_task(async function testExtensionControlledNewTab() {
await BrowserTestUtils.removeTab(gBrowser.selectedTab);
});
add_task(async function testExtensionControlledHomepageUninstalledAddon() {
async function checkHomepageEnabled() {
await openPreferencesViaOpenPreferencesAPI("paneGeneral", {leaveOpen: true});
let doc = gBrowser.contentDocument;
is(gBrowser.currentURI.spec, "about:preferences#general",
"#general should be in the URI for about:preferences");
let controlledContent = doc.getElementById("browserHomePageExtensionContent");
// The homepage is enabled.
let homepageInut = doc.getElementById("browserHomePage");
is(homepageInut.disabled, false, "The homepage input is enabled");
is(homepageInut.value, "", "The homepage input is empty");
is(controlledContent.hidden, true, "The extension controlled row is hidden");
await BrowserTestUtils.removeTab(gBrowser.selectedTab);
}
await ExtensionSettingsStore.initialize();
// Verify the setting isn't reported as controlled and the inputs are enabled.
is(ExtensionSettingsStore.getSetting("prefs", "homepage_override"), null,
"The homepage_override is not set");
await checkHomepageEnabled();
// Write out a bad store file.
let storeData = {
prefs: {
homepage_override: {
initialValue: "",
precedenceList: [{
id: "bad@mochi.test",
installDate: 1508802672,
value: "https://developer.mozilla.org",
enabled: true,
}],
},
},
};
let jsonFileName = "extension-settings.json";
let storePath = OS.Path.join(OS.Constants.Path.profileDir, jsonFileName);
await OS.File.writeAtomic(storePath, JSON.stringify(storeData));
// Reload the ExtensionSettingsStore so it will read the file on disk. Don't
// finalize the current store since it will overwrite our file.
await ExtensionSettingsStore._reloadFile(false);
// Verify that the setting is reported as set, but the homepage is still enabled
// since there is no matching installed extension.
is(ExtensionSettingsStore.getSetting("prefs", "homepage_override").value,
"https://developer.mozilla.org",
"The homepage_override appears to be set");
await checkHomepageEnabled();
// Remove the bad store file that we used.
await OS.File.remove(storePath)
// Reload the ExtensionSettingsStore again so it clears the data we added.
// Don't finalize the current store since it will write out the bad data.
await ExtensionSettingsStore._reloadFile(false);
is(ExtensionSettingsStore.getSetting("prefs", "homepage_override"), null,
"The ExtensionSettingsStore is left empty.");
});

View File

@ -504,7 +504,7 @@ var FormAutofillContent = {
if (!formHandler) {
let formLike = FormLikeFactory.createFromField(element);
formHandler = new FormAutofillHandler(formLike);
} else if (!formHandler.isFormChangedSinceLastCollection) {
} else if (!formHandler.updateFormIfNeeded(element)) {
this.log.debug("No control is removed or inserted since last collection.");
return;
}

View File

@ -19,6 +19,8 @@ Cu.import("resource://formautofill/FormAutofillUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "FormAutofillHeuristics",
"resource://formautofill/FormAutofillHeuristics.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "FormLikeFactory",
"resource://gre/modules/FormLikeFactory.jsm");
this.log = null;
FormAutofillUtils.defineLazyLogGetter(this, this.EXPORTED_SYMBOLS[0]);
@ -28,8 +30,7 @@ FormAutofillUtils.defineLazyLogGetter(this, this.EXPORTED_SYMBOLS[0]);
* @param {FormLike} form Form that need to be auto filled
*/
function FormAutofillHandler(form) {
this.form = form;
this.fieldDetails = [];
this._updateForm(form);
this.winUtils = this.form.rootElement.ownerGlobal.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindowUtils);
@ -68,8 +69,6 @@ FormAutofillHandler.prototype = {
*/
form: null,
_formFieldCount: 0,
/**
* Array of collected data about relevant form fields. Each item is an object
* storing the identifying details of the field and a reference to the
@ -112,19 +111,71 @@ FormAutofillHandler.prototype = {
PREVIEW: "-moz-autofill-preview",
},
get isFormChangedSinceLastCollection() {
// When the number of form controls is the same with last collection, it
// can be recognized as there is no element changed. However, we should
// improve the function to detect the element changes. e.g. a tel field
// is changed from type="hidden" to type="tel".
return this._formFieldCount != this.form.elements.length;
},
/**
* Time in milliseconds since epoch when a user started filling in the form.
*/
timeStartedFillingMS: null,
/**
* Check the form is necessary to be updated. This function should be able to
* detect any changes including all control elements in the form.
* @param {HTMLElement} element The element supposed to be in the form.
* @returns {boolean} FormAutofillHandler.form is updated or not.
*/
updateFormIfNeeded(element) {
// When the following condition happens, FormAutofillHandler.form should be
// updated:
// * The count of form controls is changed.
// * When the element can not be found in the current form.
//
// However, we should improve the function to detect the element changes.
// e.g. a tel field is changed from type="hidden" to type="tel".
let _formLike;
let getFormLike = () => {
if (!_formLike) {
_formLike = FormLikeFactory.createFromField(element);
}
return _formLike;
};
let currentForm = element.form;
if (!currentForm) {
currentForm = getFormLike();
}
if (currentForm.elements.length != this.form.elements.length) {
log.debug("The count of form elements is changed.");
this._updateForm(getFormLike());
return true;
}
if (this.form.elements.indexOf(element) === -1) {
log.debug("The element can not be found in the current form.");
this._updateForm(getFormLike());
return true;
}
return false;
},
/**
* Update the form with a new FormLike, and the related fields should be
* updated or clear to ensure the data consistency.
* @param {FormLike} form a new FormLike to replace the original one.
*/
_updateForm(form) {
this.form = form;
this.fieldDetails = [];
if (this.address) {
this.address.fieldDetails = [];
}
if (this.creditCard) {
this.creditCard.fieldDetails = [];
}
},
/**
* Set fieldDetails from the form about fields that can be autofilled.
*
@ -135,7 +186,6 @@ FormAutofillHandler.prototype = {
*/
collectFormFields(allowDuplicates = false) {
this._cacheValue.allFieldNames = null;
this._formFieldCount = this.form.elements.length;
let fieldDetails = FormAutofillHeuristics.getFormInfo(this.form, allowDuplicates);
this.fieldDetails = fieldDetails ? fieldDetails : [];
log.debug("Collected details on", this.fieldDetails.length, "fields");
@ -403,14 +453,15 @@ FormAutofillHandler.prototype = {
*
* @param {Object} profile
* A profile to be filled in.
* @param {Object} focusedInput
* @param {HTMLElement} focusedInput
* A focused input element needed to determine the address or credit
* card field.
*/
async autofillFormFields(profile, focusedInput) {
let focusedDetail = this.fieldDetails.find(
detail => detail.elementWeakRef.get() == focusedInput
);
let focusedDetail = this.getFieldDetailByElement(focusedInput);
if (!focusedDetail) {
throw new Error("No fieldDetail for the focused input.");
}
let targetSet;
if (FormAutofillUtils.isCreditCardField(focusedDetail.fieldName)) {
// When Master Password is enabled by users, the decryption process
@ -522,7 +573,7 @@ FormAutofillHandler.prototype = {
*
* @param {Object} profile
* A profile to be previewed with
* @param {Object} focusedInput
* @param {HTMLElement} focusedInput
* A focused input element for determining credit card or address fields.
*/
previewFormFields(profile, focusedInput) {
@ -568,7 +619,7 @@ FormAutofillHandler.prototype = {
/**
* Clear preview text and background highlight of all fields.
*
* @param {Object} focusedInput
* @param {HTMLElement} focusedInput
* A focused input element for determining credit card or address fields.
*/
clearPreviewedFormFields(focusedInput) {

View File

@ -565,6 +565,69 @@ this.FormAutofillHeuristics = {
return fieldScanner.trimmedFieldDetail;
},
_regExpTableHashValue(...signBits) {
return signBits.reduce((p, c, i) => p | !!c << i, 0);
},
_setRegExpListCache(regexps, b0, b1, b2) {
if (!this._regexpList) {
this._regexpList = [];
}
this._regexpList[this._regExpTableHashValue(b0, b1, b2)] = regexps;
},
_getRegExpListCache(b0, b1, b2) {
if (!this._regexpList) {
return null;
}
return this._regexpList[this._regExpTableHashValue(b0, b1, b2)];
},
_getRegExpList(isAutoCompleteOff, elementTagName) {
let isSelectElem = elementTagName == "SELECT";
let regExpListCache = this._getRegExpListCache(
isAutoCompleteOff,
FormAutofillUtils.isAutofillCreditCardsAvailable,
isSelectElem
);
if (regExpListCache) {
return regExpListCache;
}
const FIELDNAMES_IGNORING_AUTOCOMPLETE_OFF = [
"cc-name",
"cc-number",
"cc-exp-month",
"cc-exp-year",
"cc-exp",
];
let regexps = isAutoCompleteOff ? FIELDNAMES_IGNORING_AUTOCOMPLETE_OFF : Object.keys(this.RULES);
if (!FormAutofillUtils.isAutofillCreditCardsAvailable) {
regexps = regexps.filter(name => !FormAutofillUtils.isCreditCardField(name));
}
if (isSelectElem) {
const FIELDNAMES_FOR_SELECT_ELEMENT = [
"address-level1",
"address-level2",
"country",
"cc-exp-month",
"cc-exp-year",
"cc-exp",
];
regexps = regexps.filter(name => FIELDNAMES_FOR_SELECT_ELEMENT.includes(name));
}
this._setRegExpListCache(
regexps,
isAutoCompleteOff,
FormAutofillUtils.isAutofillCreditCardsAvailable,
isSelectElem
);
return regexps;
},
getInfo(element) {
if (!FormAutofillUtils.isFieldEligibleForAutofill(element)) {
return null;
@ -598,28 +661,7 @@ this.FormAutofillHeuristics = {
};
}
const FIELDNAMES_IGNORING_AUTOCOMPLETE_OFF = [
"cc-name",
"cc-number",
"cc-exp-month",
"cc-exp-year",
"cc-exp",
];
let regexps = isAutoCompleteOff ? FIELDNAMES_IGNORING_AUTOCOMPLETE_OFF : Object.keys(this.RULES);
if (!FormAutofillUtils.isAutofillCreditCardsAvailable) {
if (isAutoCompleteOff) {
if (!this._regexpListOf_CcUnavailable_AcOff) {
this._regexpListOf_CcUnavailable_AcOff = regexps.filter(name => !FormAutofillUtils.isCreditCardField(name));
}
regexps = this._regexpListOf_CcUnavailable_AcOff;
} else {
if (!this._regexpListOf_CcUnavailable_AcOn) {
this._regexpListOf_CcUnavailable_AcOn = regexps.filter(name => !FormAutofillUtils.isCreditCardField(name));
}
regexps = this._regexpListOf_CcUnavailable_AcOn;
}
}
let regexps = this._getRegExpList(isAutoCompleteOff, element.tagName);
if (regexps.length == 0) {
return null;
}

View File

@ -14,12 +14,18 @@ async function sleep(ms = 500, reason = "Intentionally wait for UI ready") {
await new Promise(resolve => setTimeout(resolve, ms));
}
async function focusAndWaitForFieldsIdentified(input) {
async function focusAndWaitForFieldsIdentified(input, mustBeIdentified = false) {
if (typeof input === "string") {
input = document.querySelector(input);
}
const rootElement = input.form || input.ownerDocument.documentElement;
const previouslyFocused = input != document.activeElement;
input.focus();
if (mustBeIdentified) {
rootElement.removeAttribute("test-formautofill-identified");
}
if (rootElement.hasAttribute("test-formautofill-identified")) {
return;
}

View File

@ -13,6 +13,7 @@ support-files =
scheme=https
[test_creditcard_autocomplete_off.html]
scheme=https
[test_form_changes.html]
[test_formautofill_preview_highlight.html]
[test_multiple_forms.html]
[test_on_address_submission.html]

View File

@ -0,0 +1,107 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>Test basic autofill</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SpawnTask.js"></script>
<script type="text/javascript" src="formautofill_common.js"></script>
<script type="text/javascript" src="satchel_common.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
Form autofill test: autocomplete on an autofocus form
<script>
/* import-globals-from ../../../../../testing/mochitest/tests/SimpleTest/SpawnTask.js */
/* import-globals-from ../../../../../toolkit/components/satchel/test/satchel_common.js */
/* import-globals-from formautofill_common.js */
"use strict";
let MOCK_STORAGE = [{
name: "John Doe",
organization: "Sesame Street",
"address-level2": "Austin",
tel: "+13453453456",
}, {
name: "Foo Bar",
organization: "Mozilla",
"address-level2": "San Francisco",
tel: "+16509030800",
}];
initPopupListener();
async function setupAddressStorage() {
await addAddress(MOCK_STORAGE[0]);
await addAddress(MOCK_STORAGE[1]);
}
function addInputField(form, className) {
let newElem = document.createElement("input");
newElem.name = className;
newElem.autocomplete = className;
newElem.type = "text";
form.appendChild(newElem);
}
async function checkFormChangeHappened(formId) {
await focusAndWaitForFieldsIdentified(`#${formId} input[name=tel]`);
doKey("down");
await expectPopup();
checkMenuEntries(MOCK_STORAGE.map(address =>
JSON.stringify({primary: address.tel, secondary: address.name})
));
// This is for checking the changes of element count.
addInputField(document.querySelector(`#${formId}`), "address-level2");
await focusAndWaitForFieldsIdentified(`#${formId} input[name=name]`);
doKey("down");
await expectPopup();
checkMenuEntries(MOCK_STORAGE.map(address =>
JSON.stringify({primary: address.name, secondary: address["address-level2"]})
));
// This is for checking the changes of element removed and added then.
document.querySelector(`#${formId} input[name=address-level2]`).remove();
addInputField(document.querySelector(`#${formId}`), "address-level2");
await focusAndWaitForFieldsIdentified(`#${formId} input[name=address-level2]`, true);
doKey("down");
await expectPopup();
checkMenuEntries(MOCK_STORAGE.map(address =>
JSON.stringify({primary: address["address-level2"], secondary: address.name})
));
}
add_task(async function init_storage() {
await setupAddressStorage();
});
add_task(async function check_change_happened_in_form() {
await checkFormChangeHappened("form1");
});
add_task(async function check_change_happened_in_body() {
await checkFormChangeHappened("form2");
});
</script>
<p id="display"></p>
<div id="content">
<form id="form1">
<p><label>organization: <input name="organization" autocomplete="organization" type="text"></label></p>
<p><label>tel: <input name="tel" autocomplete="tel" type="text"></label></p>
<p><label>name: <input name="name" autocomplete="name" type="text"></label></p>
</form>
<div id="form2">
<p><label>organization: <input name="organization" autocomplete="organization" type="text"></label></p>
<p><label>tel: <input name="tel" autocomplete="tel" type="text"></label></p>
<p><label>name: <input name="name" autocomplete="name" type="text"></label></p>
</div>
</div>
<pre id="test"></pre>
</body>
</html>

View File

@ -255,3 +255,53 @@ TESTCASES.forEach(testcase => {
LabelUtils.clearLabelMap();
});
});
add_task(async function test_regexp_list() {
do_print("Verify the fieldName support for select element.");
let SUPPORT_LIST = {
"email": null, // email
"tel-extension": null, // tel-extension
"phone": null, // tel
"organization": null, // organization
"street-address": null, // street-address
"address1": null, // address-line1
"address2": null, // address-line2
"address3": null, // address-line3
"city": "address-level2",
"region": "address-level1",
"postal-code": null, // postal-code
"country": "country",
"fullname": null, // name
"fname": null, // given-name
"mname": null, // additional-name
"lname": null, // family-name
"cardholder": null, // cc-name
"cc-number": null, // cc-number
"addmonth": "cc-exp-month",
"addyear": "cc-exp-year",
};
for (let label of Object.keys(SUPPORT_LIST)) {
let testcase = {
description: `A select element supports ${label} or not`,
document: `<select id="${label}"></select>`,
elementId: label,
expectedReturnValue: (SUPPORT_LIST[label] ? {
fieldName: SUPPORT_LIST[label],
section: "",
addressType: "",
contactType: "",
} : null),
};
do_print(testcase.description);
do_print(testcase.document);
let doc = MockDocument.createTestDocument(
"http://localhost:8080/test/", testcase.document);
let element = doc.getElementById(testcase.elementId);
let value = FormAutofillHeuristics.getInfo(element);
Assert.deepEqual(value, testcase.expectedReturnValue, label);
}
LabelUtils.clearLabelMap();
});

View File

@ -1510,8 +1510,8 @@ Function SetAsDefaultAppUserHKCU
StrCpy $R9 "${AppRegName}-$AppUserModelID"
${EndIf}
; Only set as the user's StartMenuInternet browser if the StartMenuInternet
; registry keys are for this install.
; Set ourselves as the user's selected StartMenuInternet browser, but only
; if we have StartMenuInternet registry keys that are for this install.
ClearErrors
ReadRegStr $0 HKCU "Software\Clients\StartMenuInternet\$R9\DefaultIcon" ""
${If} ${Errors}
@ -1520,29 +1520,30 @@ Function SetAsDefaultAppUserHKCU
ReadRegStr $0 HKLM "Software\Clients\StartMenuInternet\$R9\DefaultIcon" ""
${EndIf}
${Unless} ${Errors}
WriteRegStr HKCU "Software\Clients\StartMenuInternet" "" "$R9"
${Else}
ClearErrors
ReadRegStr $0 HKCU "Software\Clients\StartMenuInternet\$R9\DefaultIcon" ""
${If} ${Errors}
${OrIf} ${AtMostWin2008R2}
ClearErrors
ReadRegStr $0 HKLM "Software\Clients\StartMenuInternet\$R9\DefaultIcon" ""
${EndIf}
${Unless} ${Errors}
${GetPathFromString} "$0" $0
${GetParent} "$0" $0
${If} ${FileExists} "$0"
${GetLongPath} "$0" $0
${If} "$0" == "$INSTDIR"
${GetPathFromString} "$0" $0
${GetParent} "$0" $0
${If} ${FileExists} "$0"
${GetLongPath} "$0" $0
${If} "$0" == "$INSTDIR"
; On Windows >= 8, this function cannot do anything to actually set
; the default browser, it can only set up the registry entries to
; allow the user to do so. Getting here means that those entries already
; exist for this installation, we just found them, so there is nothing
; more to be done.
${If} ${AtLeastWin8}
Return
${Else}
WriteRegStr HKCU "Software\Clients\StartMenuInternet" "" "$R9"
${EndIf}
${EndIf}
${EndUnless}
${EndIf}
${EndUnless}
SetShellVarContext current ; Set SHCTX to the current user (e.g. HKCU)
; It's unlikely that we didn't find a StartMenuInternet key above, but it is
; possible; it likely would mean this copy of the application was extracted
; directly from a ZIP file and the installer was never run.
${If} ${AtLeastWin8}
${SetStartMenuInternet} "HKCU"
${FixShellIconHandler} "HKCU"

View File

@ -466,7 +466,7 @@ photonpanelmultiview panelview {
#appMenu-popup panelview,
#customizationui-widget-multiview panelview:not([extension]) {
min-width: @menuPanelWidth@;
max-width: 30em;
max-width: 35em;
}
#customizationui-widget-multiview #appMenu-libraryView,
@ -1444,10 +1444,15 @@ photonpanelmultiview .toolbaritem-combined-buttons > label {
margin: 0;
}
photonpanelmultiview .toolbaritem-combined-buttons > spacer {
photonpanelmultiview .toolbaritem-combined-buttons > spacer.before-label {
width: 36px; /* 12px toolbarbutton padding + 16px icon + 8px label padding start */
}
photonpanelmultiview .toolbaritem-combined-buttons > spacer.after-label {
-moz-box-flex: 1;
width: 20px; /* a little bigger than the width of the scrollbar */
}
photonpanelmultiview .PanelUI-subView .toolbaritem-combined-buttons > .subviewbutton {
-moz-box-flex: 0;
height: auto;

View File

@ -2,6 +2,6 @@
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
<path fill="context-fill" d="M12 0H4a2 2 0 0 0-2 2v2a1 1 0 0 0 1 1 1 1 0 0 0 1-1V2.5a.5.5 0 0 1 .5-.5h7a.5.5 0 0 1 .5.5v10a.5.5 0 0 1-.5.5h-7a.5.5 0 0 1-.5-.5V11a1 1 0 0 0-1-1 1 1 0 0 0-1 1v3a2 2 0 0 0 2 2h8a2 2 0 0 0 2-2V2a2 2 0 0 0-2-2zM9 15H7v-1h2z"/>
<path fill="context-fill" d="M5.146 10.146a.5.5 0 1 0 .707.707l3-3a.5.5 0 0 0 0-.708l-3-3a.5.5 0 0 0-.707.707L7.293 7H.5a.5.5 0 0 0 0 1h6.793z"/>
<path fill="context-fill" fill-opacity="context-fill-opacity" d="M12 0H4a2 2 0 0 0-2 2v2a1 1 0 0 0 1 1 1 1 0 0 0 1-1V2.5a.5.5 0 0 1 .5-.5h7a.5.5 0 0 1 .5.5v10a.5.5 0 0 1-.5.5h-7a.5.5 0 0 1-.5-.5V11a1 1 0 0 0-1-1 1 1 0 0 0-1 1v3a2 2 0 0 0 2 2h8a2 2 0 0 0 2-2V2a2 2 0 0 0-2-2zM9 15H7v-1h2z"/>
<path fill="context-fill" fill-opacity="context-fill-opacity" d="M5.146 10.146a.5.5 0 1 0 .707.707l3-3a.5.5 0 0 0 0-.708l-3-3a.5.5 0 0 0-.707.707L7.293 7H.5a.5.5 0 0 0 0 1h6.793z"/>
</svg>

Before

Width:  |  Height:  |  Size: 708 B

After

Width:  |  Height:  |  Size: 780 B

View File

@ -1118,6 +1118,7 @@ notification[value="translation"] {
%include ../shared/contextmenu.inc.css
/* Make menu items larger when opened through touch. */
#widget-overflow[touchmode] .toolbarbutton-1,
panel[touchmode] .PanelUI-subView .subviewbutton,
menupopup[touchmode] menu,
menupopup[touchmode] menuitem {

View File

@ -4,10 +4,6 @@ dnl file, You can obtain one at http://mozilla.org/MPL/2.0/.
AC_DEFUN([MOZ_CONFIG_CLANG_PLUGIN], [
MOZ_ARG_ENABLE_BOOL(clang-plugin,
[ --enable-clang-plugin Enable building with the mozilla clang plugin ],
ENABLE_CLANG_PLUGIN=1,
ENABLE_CLANG_PLUGIN= )
if test -n "$ENABLE_CLANG_PLUGIN"; then
if test -z "${CLANG_CC}${CLANG_CL}"; then
AC_MSG_ERROR([Can't use clang plugin without clang.])
@ -155,10 +151,13 @@ if test -n "$ENABLE_CLANG_PLUGIN"; then
LLVM_CXXFLAGS="$LLVM_CXXFLAGS -DHAS_ACCEPTS_IGNORINGPARENIMPCASTS"
fi
CLANG_PLUGIN_FLAGS="-Xclang -load -Xclang $CLANG_PLUGIN -Xclang -add-plugin -Xclang moz-check"
AC_DEFINE(MOZ_CLANG_PLUGIN)
fi
AC_SUBST(LLVM_CXXFLAGS)
AC_SUBST_LIST(CLANG_PLUGIN_FLAGS)
AC_SUBST_LIST(LLVM_CXXFLAGS)
AC_SUBST(LLVM_LDFLAGS)
AC_SUBST(CLANG_LDFLAGS)

View File

@ -28,7 +28,7 @@ define([AC_SUBST_SET],
[ifdef([AC_SUBST_SET_$1], ,
[define([AC_SUBST_SET_$1], )dnl
AC_DIVERT_PUSH(MOZ_DIVERSION_SUBST)dnl
(''' $1 ''', unique_list(r''' [$]$1 '''.split()))
(''' $1 ''', unique_list(split(r''' [$]$1 ''')))
AC_DIVERT_POP()dnl
])])])])
@ -41,7 +41,7 @@ define([AC_SUBST_LIST],
[ifdef([AC_SUBST_LIST_$1], ,
[define([AC_SUBST_LIST_$1], )dnl
AC_DIVERT_PUSH(MOZ_DIVERSION_SUBST)dnl
(''' $1 ''', list(r''' [$]$1 '''.split()))
(''' $1 ''', list(split(r''' [$]$1 ''')))
AC_DIVERT_POP()dnl
])])])])
@ -106,12 +106,6 @@ changequote(<<<, >>>)dnl
echo creating $CONFIG_STATUS
cat > $CONFIG_STATUS <<EOF
def unique_list(l):
result = []
for i in l:
if l not in result:
result.append(i)
return result
dnl All defines and substs are stored with an additional space at the beginning
dnl and at the end of the string, to avoid any problem with values starting or

View File

@ -9,13 +9,9 @@ include $(topsrcdir)/config/config.mk
# In the current moz.build world, we need to override essentially every
# variable to limit ourselves to what we need to build the clang plugin.
ifeq ($(HOST_OS_ARCH),WINNT)
OS_CXXFLAGS := $(LLVM_CXXFLAGS) -GR- -EHsc
else
OS_CXXFLAGS := $(LLVM_CXXFLAGS) -fno-rtti -fno-exceptions
ifneq ($(HOST_OS_ARCH),WINNT)
DSO_LDOPTS := -shared
endif
OS_COMPILE_CXXFLAGS :=
OS_LDFLAGS := $(LLVM_LDFLAGS) $(CLANG_LDFLAGS)
ifeq ($(HOST_OS_ARCH)_$(OS_ARCH),Linux_Darwin)

View File

@ -59,3 +59,19 @@ if CONFIG['HOST_OS_ARCH'] == 'Darwin':
DIRS += [
'tests',
]
# In the current moz.build world, we need to override essentially every
# variable to limit ourselves to what we need to build the clang plugin.
if CONFIG['HOST_OS_ARCH'] == 'WINNT':
extra_cxxflags = ['-GR-', '-EHsc']
else:
extra_cxxflags = ['-fno-rtti', '-fno-exceptions']
if CONFIG['LLVM_CXXFLAGS']:
COMPILE_FLAGS['OS_CXXFLAGS'] = CONFIG['LLVM_CXXFLAGS'] + extra_cxxflags
COMPILE_FLAGS['CLANG_PLUGIN'] = []
COMPILE_FLAGS['OPTIMIZE'] = []
COMPILE_FLAGS['DEBUG'] = []
COMPILE_FLAGS['OS_COMPILE_CXXFLAGS'] = []

View File

@ -2,11 +2,6 @@
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
# Build without any warning flags, and with clang verify flag for a
# syntax-only build (no codegen), without a limit on the number of errors.
OS_CFLAGS := $(filter-out -W%,$(OS_CFLAGS)) -fsyntax-only -Xclang -verify -ferror-limit=0 -std=c11 -Wno-invalid-noreturn
OS_CXXFLAGS := $(filter-out -W%,$(OS_CXXFLAGS)) -fsyntax-only -Xclang -verify -ferror-limit=0 -Wno-invalid-noreturn
include $(topsrcdir)/config/rules.mk
target:: $(OBJS)

View File

@ -47,3 +47,15 @@ SOURCES += [
DisableStlWrapping()
NoVisibilityFlags()
# Build without any warning flags, and with clang verify flag for a
# syntax-only build (no codegen), without a limit on the number of errors.
COMPILE_FLAGS['OS_CXXFLAGS'] = (
[f for f in COMPILE_FLAGS.get('OS_CXXFLAGS', []) if not f.startswith('-W')] +
['-fsyntax-only', '-Xclang', '-verify', '-ferror-limit=0', '-Wno-invalid-noreturn']
)
COMPILE_FLAGS['OS_CFLAGS'] = (
[f for f in COMPILE_FLAGS.get('OS_CFLAGS', []) if not f.startswith('-W')] +
['-fsyntax-only', '-Xclang', '-verify', '-ferror-limit=0', '-std=c11',
'-Wno-invalid-noreturn']
)

View File

@ -66,6 +66,7 @@ set_config('AUTOCONF', autoconf)
old_configure_assignments, build_project)
@imports(_from='__builtin__', _import='open')
@imports(_from='__builtin__', _import='print')
@imports(_from='__builtin__', _import='sorted')
@imports('glob')
@imports('itertools')
@imports('subprocess')
@ -126,13 +127,21 @@ def prepare_configure(old_configure, mozconfig, autoconf, build_env, shell,
log.debug('| %s', command)
if mozconfig['path']:
inject('# start of mozconfig values')
items = {}
for key, value in mozconfig['vars']['added'].items():
inject("%s=%s" % (key, quote(value)))
items[key] = (value, 'added')
for key, (old, value) in mozconfig['vars']['modified'].items():
inject("%s=%s" % (key, quote(value)))
items[key] = (value, 'modified')
for key, (value, action) in sorted(items.items()):
inject("%s=%s # %s" % (key, quote(value), action))
for t in ('env', 'vars'):
for key in mozconfig[t]['removed'].keys():
inject("unset %s" % key)
for key in sorted(mozconfig[t]['removed'].keys()):
inject("unset %s # from %s" % (key, t))
inject('# end of mozconfig values')
# Autoconf is special, because it might be passed from
# mozconfig['make_extra'], which we don't pass automatically above.
@ -164,7 +173,6 @@ def old_configure_options(*options):
'--enable-address-sanitizer',
'--enable-alsa',
'--enable-bundled-fonts',
'--enable-clang-plugin',
'--enable-content-sandbox',
'--enable-cookies',
'--enable-cpp-rtti',
@ -200,7 +208,6 @@ def old_configure_options(*options):
'--enable-nspr-build',
'--enable-official-branding',
'--enable-oom-breakpoint',
'--enable-optimize',
'--enable-parental-controls',
'--enable-pie',
'--enable-posix-nspr-emulation',
@ -298,6 +305,7 @@ def old_configure_options(*options):
@imports('subprocess')
@imports('sys')
@imports(_from='mozbuild.shellutil', _import='quote')
@imports(_from='mozbuild.shellutil', _import='split')
def old_configure(prepare_configure, extra_old_configure_args, all_options,
*options):
cmd = prepare_configure
@ -358,7 +366,10 @@ def old_configure(prepare_configure, extra_old_configure_args, all_options,
log.error('old-configure failed')
sys.exit(ret)
raw_config = {}
raw_config = {
'split': split,
'unique_list': unique_list,
}
with encoded_open('config.data', 'r') as fh:
code = compile(fh.read(), 'config.data', 'exec')
# Every variation of the exec() function I tried led to:

View File

@ -11,6 +11,37 @@ option(env='MOZ_PGO', help='Build with profile guided optimizations')
set_config('MOZ_PGO', depends('MOZ_PGO')(lambda x: bool(x)))
add_old_configure_assignment('MOZ_PGO', depends('MOZ_PGO')(lambda x: bool(x)))
# Code optimization
# ==============================================================
js_option('--enable-optimize',
nargs='?',
default=True,
help='Enable optimizations via compiler flags')
@depends('--enable-optimize')
def moz_optimize(option):
flags = None
if len(option):
val = '2'
flags = option[0]
elif option:
val = '1'
else:
val = None
return namespace(
optimize=val,
flags=flags,
)
set_config('MOZ_OPTIMIZE', moz_optimize.optimize)
add_old_configure_assignment('MOZ_OPTIMIZE', moz_optimize.optimize)
add_old_configure_assignment('MOZ_CONFIGURE_OPTIMIZE_FLAGS', moz_optimize.flags)
# yasm detection
# ==============================================================
yasm = check_prog('YASM', ['yasm'], allow_missing=True)
@ -1269,6 +1300,67 @@ def developer_options(value):
add_old_configure_assignment('DEVELOPER_OPTIONS', developer_options)
set_config('DEVELOPER_OPTIONS', developer_options)
# Rust compiler flags
# ==============================================================
js_option(env='RUSTC_OPT_LEVEL',
nargs=1,
help='Rust compiler optimization level (-C opt-level=%s)')
# --enable-release kicks in full optimizations.
imply_option('RUSTC_OPT_LEVEL', '2', when='--enable-release')
@depends('RUSTC_OPT_LEVEL', debug_rust, '--enable-debug-symbols',
moz_optimize)
def rust_compiler_flags(opt_level_option, debug_rust, debug_symbols,
moz_optimize):
optimize = moz_optimize.optimize
# Cargo currently supports only two interesting profiles for building:
# development and release. Those map (roughly) to --enable-debug and
# --disable-debug in Gecko, respectively.
#
# But we'd also like to support an additional axis of control for
# optimization level. Since Cargo only supports 2 profiles, we're in
# a bit of a bind.
#
# Code here derives various compiler options given other configure options.
# The options defined here effectively override defaults specified in
# Cargo.toml files.
opt_level = None
debug_assertions = None
debug_info = None
if opt_level_option.origin != 'default':
opt_level = opt_level_option[0]
else:
opt_level = '1' if optimize else '0'
# opt-level=0 implies -C debug-assertions, which may not be desired
# unless Rust debugging is enabled.
if opt_level == '0' and not debug_rust:
debug_assertions = False
if debug_symbols:
debug_info = '2'
flags = []
if opt_level is not None:
flags.append('-Copt-level=%s' % opt_level)
if debug_assertions is not None:
flags.append('-Cdebug-assertions=%s' %
('yes' if debug_assertions else 'no'))
if debug_info is not None:
flags.append('-Cdebuginfo=%s' % debug_info)
return flags
set_config('MOZ_RUST_DEFAULT_FLAGS', rust_compiler_flags)
# Linker detection
# ==============================================================
@ -1393,6 +1485,13 @@ set_config('LD_IS_BFD', depends(select_linker.KIND)
(lambda x: x == 'bfd' or None))
set_config('LINKER_LDFLAGS', select_linker.LINKER_FLAG)
js_option('--enable-clang-plugin', env='ENABLE_CLANG_PLUGIN',
help="Enable building with the mozilla clang plugin")
add_old_configure_assignment('ENABLE_CLANG_PLUGIN',
depends_if('--enable-clang-plugin')(lambda _: True))
# Code Coverage
# ==============================================================

View File

@ -156,6 +156,9 @@ def DisableStlWrapping():
def NoVisibilityFlags():
COMPILE_FLAGS['VISIBILITY'] = []
@template
def AllowCompilerWarnings():
COMPILE_FLAGS['WARNINGS_AS_ERRORS'] = []
@template
def RustTest(name, features=None):

View File

@ -3,8 +3,6 @@
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
OS_CXXFLAGS := $(filter-out -fno-exceptions,$(OS_CXXFLAGS)) -fexceptions
include $(topsrcdir)/config/rules.mk
test-array$(DLL_SUFFIX) test-ctors$(DLL_SUFFIX): %$(DLL_SUFFIX): %.$(OBJ_SUFFIX) elfhack

View File

@ -9,5 +9,3 @@ $(CSRCS): %.c: ../inject.c
cp $< $@
GARBAGE += $(CSRCS)
CFLAGS := -O2 -fno-stack-protector $(filter -m% -I% -idirafter%,$(subst -idirafter ,-idirafter,$(CFLAGS)))

View File

@ -23,4 +23,19 @@ SOURCES += [
NO_PGO = True
for v in ('OS_CPPFLAGS', 'OS_CFLAGS', 'DEBUG', 'CLANG_PLUGIN', 'OPTIMIZE',
'FRAMEPTR'):
flags = []
idx = 0
for flag in COMPILE_FLAGS[v]:
if flag == '-idirafter':
flags.append(''.join(COMPILE_FLAGS[v][idx:idx + 2]))
elif flag.startswith(('-m', '-I', '-idirafter')):
flags.append(flag)
idx += 1
COMPILE_FLAGS[v] = flags
COMPILE_FLAGS['OS_CFLAGS'] += ['-O2', '-fno-stack-protector']
AllowCompilerWarnings()
NoVisibilityFlags()

View File

@ -26,3 +26,8 @@ HOST_SOURCES += [
HostProgram('elfhack')
NO_PGO = True
COMPILE_FLAGS['OS_CXXFLAGS'] = [
f for f in COMPILE_FLAGS['OS_CXXFLAGS'] if f != '-fno-exceptions'
] + ['-fexceptions']

View File

@ -1,7 +0,0 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this file,
# You can obtain one at http://mozilla.org/MPL/2.0/.
ENABLE_CLANG_PLUGIN :=
include $(topsrcdir)/config/rules.mk

View File

@ -19,6 +19,7 @@ FORCE_STATIC_LIB = True
NO_PGO = True
DisableStlWrapping()
COMPILE_FLAGS['CLANG_PLUGIN'] = []
DEFINES['MOZ_LIBSTDCXX_VERSION'] = CONFIG['MOZ_LIBSTDCXX_TARGET_VERSION']
HOST_DEFINES['MOZ_LIBSTDCXX_VERSION'] = CONFIG['MOZ_LIBSTDCXX_HOST_VERSION']

View File

@ -134,7 +134,6 @@ PYTHON_PATH = $(PYTHON) $(topsrcdir)/config/pythonpath.py
# determine debug-related options
_DEBUG_ASFLAGS :=
_DEBUG_CFLAGS :=
_DEBUG_LDFLAGS :=
ifneq (,$(MOZ_DEBUG)$(MOZ_DEBUG_SYMBOLS))
@ -149,13 +148,10 @@ ifneq (,$(MOZ_DEBUG)$(MOZ_DEBUG_SYMBOLS))
else
_DEBUG_ASFLAGS += $(MOZ_DEBUG_FLAGS)
endif
_DEBUG_CFLAGS += $(MOZ_DEBUG_FLAGS)
_DEBUG_LDFLAGS += $(MOZ_DEBUG_LDFLAGS)
endif
ASFLAGS += $(_DEBUG_ASFLAGS)
OS_CFLAGS += $(_DEBUG_CFLAGS)
OS_CXXFLAGS += $(_DEBUG_CFLAGS)
OS_LDFLAGS += $(_DEBUG_LDFLAGS)
# XXX: What does this? Bug 482434 filed for better explanation.
@ -203,8 +199,7 @@ endif
# Enable profile-based feedback
ifneq (1,$(NO_PROFILE_GUIDED_OPTIMIZE))
ifdef MOZ_PROFILE_GENERATE
OS_CFLAGS += $(if $(filter $(notdir $<),$(notdir $(NO_PROFILE_GUIDED_OPTIMIZE))),,$(PROFILE_GEN_CFLAGS))
OS_CXXFLAGS += $(if $(filter $(notdir $<),$(notdir $(NO_PROFILE_GUIDED_OPTIMIZE))),,$(PROFILE_GEN_CFLAGS))
PGO_CFLAGS += $(if $(filter $(notdir $<),$(notdir $(NO_PROFILE_GUIDED_OPTIMIZE))),,$(PROFILE_GEN_CFLAGS))
OS_LDFLAGS += $(PROFILE_GEN_LDFLAGS)
ifeq (WINNT,$(OS_ARCH))
AR_FLAGS += -LTCG
@ -212,8 +207,7 @@ endif
endif # MOZ_PROFILE_GENERATE
ifdef MOZ_PROFILE_USE
OS_CFLAGS += $(if $(filter $(notdir $<),$(notdir $(NO_PROFILE_GUIDED_OPTIMIZE))),,$(PROFILE_USE_CFLAGS))
OS_CXXFLAGS += $(if $(filter $(notdir $<),$(notdir $(NO_PROFILE_GUIDED_OPTIMIZE))),,$(PROFILE_USE_CFLAGS))
PGO_CFLAGS += $(if $(filter $(notdir $<),$(notdir $(NO_PROFILE_GUIDED_OPTIMIZE))),,$(PROFILE_USE_CFLAGS))
OS_LDFLAGS += $(PROFILE_USE_LDFLAGS)
ifeq (WINNT,$(OS_ARCH))
AR_FLAGS += -LTCG
@ -255,23 +249,9 @@ INCLUDES = \
include $(MOZILLA_DIR)/config/static-checking-config.mk
CFLAGS = $(OS_CPPFLAGS) $(OS_CFLAGS)
CXXFLAGS = $(OS_CPPFLAGS) $(OS_CXXFLAGS)
LDFLAGS = $(OS_LDFLAGS) $(MOZBUILD_LDFLAGS) $(MOZ_FIX_LINK_PATHS)
ifdef MOZ_OPTIMIZE
ifeq (1,$(MOZ_OPTIMIZE))
ifneq (,$(if $(MOZ_PROFILE_GENERATE)$(MOZ_PROFILE_USE),$(MOZ_PGO_OPTIMIZE_FLAGS)))
CFLAGS += $(MOZ_PGO_OPTIMIZE_FLAGS)
CXXFLAGS += $(MOZ_PGO_OPTIMIZE_FLAGS)
else
CFLAGS += $(MOZ_OPTIMIZE_FLAGS)
CXXFLAGS += $(MOZ_OPTIMIZE_FLAGS)
endif # neq (,$(MOZ_PROFILE_GENERATE)$(MOZ_PROFILE_USE))
else
CFLAGS += $(MOZ_OPTIMIZE_FLAGS)
CXXFLAGS += $(MOZ_OPTIMIZE_FLAGS)
endif # MOZ_OPTIMIZE == 1
LDFLAGS += $(MOZ_OPTIMIZE_LDFLAGS)
endif # MOZ_OPTIMIZE
@ -287,33 +267,8 @@ HOST_CXXFLAGS += $(MOZ_OPTIMIZE_FLAGS)
endif # MOZ_OPTIMIZE
endif # CROSS_COMPILE
CFLAGS += $(MOZ_FRAMEPTR_FLAGS)
CXXFLAGS += $(MOZ_FRAMEPTR_FLAGS)
# Check for ALLOW_COMPILER_WARNINGS (shorthand for Makefiles to request that we
# *don't* use the warnings-as-errors compile flags)
# Don't use warnings-as-errors in Windows PGO builds because it is suspected of
# causing problems in that situation. (See bug 437002.)
ifeq (WINNT_1,$(OS_ARCH)_$(MOZ_PROFILE_GENERATE)$(MOZ_PROFILE_USE))
ALLOW_COMPILER_WARNINGS=1
endif # WINNT && (MOS_PROFILE_GENERATE ^ MOZ_PROFILE_USE)
# Don't use warnings-as-errors in clang-cl because it warns about many more
# things than MSVC does.
ifdef CLANG_CL
ALLOW_COMPILER_WARNINGS=1
endif # CLANG_CL
# Use warnings-as-errors if ALLOW_COMPILER_WARNINGS is not set to 1 (which
# includes the case where it's undefined).
ifneq (1,$(ALLOW_COMPILER_WARNINGS))
CXXFLAGS += $(WARNINGS_AS_ERRORS)
CFLAGS += $(WARNINGS_AS_ERRORS)
endif # ALLOW_COMPILER_WARNINGS
COMPILE_CFLAGS = $(COMPUTED_CFLAGS) $(DSO_CFLAGS) $(DSO_PIC_CFLAGS) $(RTL_FLAGS) $(OS_COMPILE_CFLAGS) $(_DEPEND_CFLAGS) $(CFLAGS) $(MOZBUILD_CFLAGS) $(MK_COMPILE_DEFINES)
COMPILE_CXXFLAGS = $(COMPUTED_CXXFLAGS) $(DSO_CFLAGS) $(DSO_PIC_CFLAGS) $(RTL_FLAGS) $(OS_COMPILE_CXXFLAGS) $(_DEPEND_CFLAGS) $(CXXFLAGS) $(MOZBUILD_CXXFLAGS) $(MK_COMPILE_DEFINES)
COMPILE_CFLAGS = $(COMPUTED_CFLAGS) $(PGO_CFLAGS) $(MOZBUILD_CFLAGS) $(_DEPEND_CFLAGS) $(MK_COMPILE_DEFINES)
COMPILE_CXXFLAGS = $(COMPUTED_CXXFLAGS) $(PGO_CFLAGS) $(MOZBUILD_CXXFLAGS) $(_DEPEND_CFLAGS) $(MK_COMPILE_DEFINES)
COMPILE_CMFLAGS = $(OS_COMPILE_CMFLAGS) $(MOZBUILD_CMFLAGS)
COMPILE_CMMFLAGS = $(OS_COMPILE_CMMFLAGS) $(MOZBUILD_CMMFLAGS)
ASFLAGS += $(MOZBUILD_ASFLAGS)

View File

@ -9,7 +9,7 @@ FINAL_LIBRARY = 'js'
if CONFIG['MOZ_SYSTEM_FFI']:
OS_LIBS += CONFIG['MOZ_FFI_LIBS']
else:
ALLOW_COMPILER_WARNINGS = True
AllowCompilerWarnings()
NoVisibilityFlags()
CONFIGURE_DEFINE_FILES += [

View File

@ -33,7 +33,7 @@ elif CONFIG['OS_TARGET'] == 'WINNT':
CXXFLAGS += ['-GR']
DisableStlWrapping()
ALLOW_COMPILER_WARNINGS = True
AllowCompilerWarnings()
# We allow compiler warnings, but we can at least cut down on spammy
# warnings that get triggered for every file.

View File

@ -13,7 +13,7 @@ else:
# We allow warnings for third-party code that can be updated from upstream.
# TODO: fix NSPR warnings and remove this
ALLOW_COMPILER_WARNINGS = True
AllowCompilerWarnings()
DEFINES['_NSPR_BUILD_'] = True

View File

@ -13,7 +13,7 @@ else:
# We allow warnings for third-party code that can be updated from upstream.
# TODO: fix NSPR warnings and remove this
ALLOW_COMPILER_WARNINGS = True
AllowCompilerWarnings()
DEFINES['_NSPR_BUILD_'] = True

View File

@ -11,7 +11,7 @@ else:
# We allow warnings for third-party code that can be updated from upstream.
# TODO: fix NSPR warnings and remove this
ALLOW_COMPILER_WARNINGS = True
AllowCompilerWarnings()
DEFINES['_NSPR_BUILD_'] = True
if CONFIG['OS_ARCH'] == 'Linux':

View File

@ -598,7 +598,7 @@ ifdef MOZ_PROFILE_GENERATE
touch -t `date +%Y%m%d%H%M.%S -d 'now+5seconds'` pgo.relink
endif
else # !WINNT || GNU_CC
$(call EXPAND_CC_OR_CXX,$@) -o $@ $(CXXFLAGS) $(PROGOBJS) $(RESFILE) $(WIN32_EXE_LDFLAGS) $(LDFLAGS) $(WRAP_LDFLAGS) $(STATIC_LIBS) $(MOZ_PROGRAM_LDFLAGS) $(SHARED_LIBS) $(EXTRA_LIBS) $(OS_LIBS) $(BIN_FLAGS) $(EXE_DEF_FILE)
$(call EXPAND_CC_OR_CXX,$@) -o $@ $(COMPUTED_CXX_LDFLAGS) $(PGO_CFLAGS) $(PROGOBJS) $(RESFILE) $(WIN32_EXE_LDFLAGS) $(LDFLAGS) $(WRAP_LDFLAGS) $(STATIC_LIBS) $(MOZ_PROGRAM_LDFLAGS) $(SHARED_LIBS) $(EXTRA_LIBS) $(OS_LIBS) $(BIN_FLAGS) $(EXE_DEF_FILE)
$(call CHECK_BINARY,$@)
endif # WINNT && !GNU_CC
@ -657,7 +657,7 @@ ifdef MSMANIFEST_TOOL
fi
endif # MSVC with manifest tool
else
$(call EXPAND_CC_OR_CXX,$@) $(CXXFLAGS) -o $@ $< $(WIN32_EXE_LDFLAGS) $(LDFLAGS) $(WRAP_LDFLAGS) $(STATIC_LIBS) $(MOZ_PROGRAM_LDFLAGS) $(SHARED_LIBS) $(EXTRA_LIBS) $(OS_LIBS) $(BIN_FLAGS)
$(call EXPAND_CC_OR_CXX,$@) $(COMPUTED_CXX_LDFLAGS) $(PGO_CFLAGS) -o $@ $< $(WIN32_EXE_LDFLAGS) $(LDFLAGS) $(WRAP_LDFLAGS) $(STATIC_LIBS) $(MOZ_PROGRAM_LDFLAGS) $(SHARED_LIBS) $(EXTRA_LIBS) $(OS_LIBS) $(BIN_FLAGS)
$(call CHECK_BINARY,$@)
endif # WINNT && !GNU_CC
@ -875,24 +875,7 @@ cargo_rustc_flags += -C lto
endif
endif
# Cargo currently supports only two interesting profiles for building:
# development and release. Those map (roughly) to --enable-debug and
# --disable-debug in Gecko, respectively, but there's another axis that we'd
# like to support: --{disable,enable}-optimize. Since that would be four
# choices, and Cargo only supports two, we choose to enable various
# optimization levels in our Cargo.toml files all the time, and override the
# optimization level here, if necessary. (The Cargo.toml files already
# specify debug-assertions appropriately for --{disable,enable}-debug.)
default_rustflags =
ifndef MOZ_OPTIMIZE
default_rustflags = -C opt-level=0
# Unfortunately, -C opt-level=0 implies -C debug-assertions, so we need
# to explicitly disable them when MOZ_DEBUG_RUST is not set.
ifndef MOZ_DEBUG_RUST
default_rustflags += -C debug-assertions=no
endif
endif
rustflags_override = RUSTFLAGS='$(default_rustflags) $(RUSTFLAGS)'
rustflags_override = RUSTFLAGS='$(MOZ_RUST_DEFAULT_FLAGS) $(RUSTFLAGS)'
ifdef MOZ_MSVCBITS
# If we are building a MozillaBuild shell, we want to clear out the
@ -919,10 +902,6 @@ ifdef MOZ_USING_SCCACHE
sccache_wrap := RUSTC_WRAPPER='$(CCACHE)'
endif
ifdef MOZ_DEBUG_SYMBOLS
default_rustflags += -C debuginfo=2
endif
# We use the + prefix to pass down the jobserver fds to cargo, but we
# don't use the prefix when make -n is used, so that cargo doesn't run
# in that case)

View File

@ -13,8 +13,4 @@ ifeq ($(OS_ARCH),WINNT)
CC := $(subst clang-cl.exe,clang.exe --driver-mode=cl,$(CC:.EXE=.exe))
CXX := $(subst clang-cl.exe,clang.exe --driver-mode=cl,$(CXX:.EXE=.exe))
endif
CLANG_PLUGIN := $(topobjdir)/build/clang-plugin/$(DLL_PREFIX)clang-plugin$(DLL_SUFFIX)
OS_CXXFLAGS += -Xclang -load -Xclang $(CLANG_PLUGIN) -Xclang -add-plugin -Xclang moz-check
OS_CFLAGS += -Xclang -load -Xclang $(CLANG_PLUGIN) -Xclang -add-plugin -Xclang moz-check
endif

View File

@ -10,7 +10,7 @@ EXPORTS += [
]
# We allow warnings for third-party code that can be updated from upstream.
ALLOW_COMPILER_WARNINGS = True
AllowCompilerWarnings()
if CONFIG['MOZ_FOLD_LIBS']:
# When folding libraries, sqlite is actually in the nss library.

View File

@ -5,7 +5,7 @@
"use strict";
const {
createClass,
Component,
createFactory,
DOM,
PropTypes,
@ -49,21 +49,28 @@ const SUMMARY_VERSION = L10N.getStr("netmonitor.summary.version");
* Headers panel component
* Lists basic information about the request
*/
const HeadersPanel = createClass({
displayName: "HeadersPanel",
propTypes: {
cloneSelectedRequest: PropTypes.func.isRequired,
request: PropTypes.object.isRequired,
renderValue: PropTypes.func,
openLink: PropTypes.func,
},
getInitialState() {
class HeadersPanel extends Component {
static get propTypes() {
return {
cloneSelectedRequest: PropTypes.func.isRequired,
request: PropTypes.object.isRequired,
renderValue: PropTypes.func,
openLink: PropTypes.func,
};
}
constructor(props) {
super(props);
this.state = {
rawHeadersOpened: false,
};
},
this.getProperties = this.getProperties.bind(this);
this.toggleRawHeaders = this.toggleRawHeaders.bind(this);
this.renderSummary = this.renderSummary.bind(this);
this.renderValue = this.renderValue.bind(this);
}
getProperties(headers, title) {
if (headers && headers.headers.length) {
@ -80,13 +87,13 @@ const HeadersPanel = createClass({
}
return null;
},
}
toggleRawHeaders() {
this.setState({
rawHeadersOpened: !this.state.rawHeadersOpened,
});
},
}
renderSummary(label, value) {
return (
@ -101,7 +108,7 @@ const HeadersPanel = createClass({
}),
)
);
},
}
renderValue(props) {
const member = props.member;
@ -127,7 +134,7 @@ const HeadersPanel = createClass({
}) : null
)
);
},
}
render() {
const {
@ -273,6 +280,6 @@ const HeadersPanel = createClass({
)
);
}
});
}
module.exports = HeadersPanel;

View File

@ -6,7 +6,7 @@
const Services = require("Services");
const {
createClass,
Component,
createFactory,
DOM,
PropTypes,
@ -29,33 +29,37 @@ const MediaQueryList = window.matchMedia("(min-width: 700px)");
* Monitor panel component
* The main panel for displaying various network request information
*/
const MonitorPanel = createClass({
displayName: "MonitorPanel",
propTypes: {
connector: PropTypes.object.isRequired,
isEmpty: PropTypes.bool.isRequired,
networkDetailsOpen: PropTypes.bool.isRequired,
openNetworkDetails: PropTypes.func.isRequired,
request: PropTypes.object,
sourceMapService: PropTypes.object,
openLink: PropTypes.func,
updateRequest: PropTypes.func.isRequired,
},
getInitialState() {
class MonitorPanel extends Component {
static get propTypes() {
return {
connector: PropTypes.object.isRequired,
isEmpty: PropTypes.bool.isRequired,
networkDetailsOpen: PropTypes.bool.isRequired,
openNetworkDetails: PropTypes.func.isRequired,
request: PropTypes.object,
sourceMapService: PropTypes.object,
openLink: PropTypes.func,
updateRequest: PropTypes.func.isRequired,
};
}
constructor(props) {
super(props);
this.state = {
isVerticalSpliter: MediaQueryList.matches,
};
},
this.onLayoutChange = this.onLayoutChange.bind(this);
}
componentDidMount() {
MediaQueryList.addListener(this.onLayoutChange);
},
}
componentWillReceiveProps(nextProps) {
updateFormDataSections(nextProps);
},
}
componentWillUnmount() {
MediaQueryList.removeListener(this.onLayoutChange);
@ -70,13 +74,13 @@ const MonitorPanel = createClass({
Services.prefs.setIntPref(
"devtools.netmonitor.panes-network-details-height", clientHeight);
}
},
}
onLayoutChange() {
this.setState({
isVerticalSpliter: MediaQueryList.matches,
});
},
}
render() {
let {
@ -116,7 +120,7 @@ const MonitorPanel = createClass({
)
);
}
});
}
module.exports = connect(
(state) => ({

View File

@ -5,7 +5,7 @@
"use strict";
const {
createClass,
Component,
createFactory,
DOM,
PropTypes,
@ -39,23 +39,23 @@ const SECTION_NAMES = [
* Params panel component
* Displays the GET parameters and POST data of a request
*/
const ParamsPanel = createClass({
displayName: "ParamsPanel",
propTypes: {
connector: PropTypes.object.isRequired,
openLink: PropTypes.func,
request: PropTypes.object.isRequired,
updateRequest: PropTypes.func.isRequired,
},
class ParamsPanel extends Component {
static get propTypes() {
return {
connector: PropTypes.object.isRequired,
openLink: PropTypes.func,
request: PropTypes.object.isRequired,
updateRequest: PropTypes.func.isRequired,
};
}
componentDidMount() {
updateFormDataSections(this.props);
},
}
componentWillReceiveProps(nextProps) {
updateFormDataSections(nextProps);
},
}
render() {
let {
@ -124,7 +124,7 @@ const ParamsPanel = createClass({
)
);
}
});
}
/**
* Mapping array to dict for TreeView usage.

View File

@ -7,7 +7,7 @@
"use strict";
const {
createClass,
Component,
createFactory,
DOM,
PropTypes,
@ -40,20 +40,20 @@ const EDITOR_CONFIG_ID = "EDITOR_CONFIG";
* Source editor - Enable by specifying object level 1 property name to EDITOR_CONFIG_ID.
* Rep - Default enabled.
*/
const PropertiesView = createClass({
displayName: "PropertiesView",
class PropertiesView extends Component {
static get propTypes() {
return {
object: PropTypes.object,
enableInput: PropTypes.bool,
expandableStrings: PropTypes.bool,
filterPlaceHolder: PropTypes.string,
sectionNames: PropTypes.array,
openLink: PropTypes.func,
cropLimit: PropTypes.number
};
}
propTypes: {
object: PropTypes.object,
enableInput: PropTypes.bool,
expandableStrings: PropTypes.bool,
filterPlaceHolder: PropTypes.string,
sectionNames: PropTypes.array,
openLink: PropTypes.func,
cropLimit: PropTypes.number
},
getDefaultProps() {
static get defaultProps() {
return {
enableInput: true,
enableFilter: true,
@ -62,17 +62,26 @@ const PropertiesView = createClass({
sectionNames: [],
cropLimit: 1024
};
},
}
getInitialState() {
return {
constructor(props) {
super(props);
this.state = {
filterText: "",
};
},
this.getRowClass = this.getRowClass.bind(this);
this.onFilter = this.onFilter.bind(this);
this.renderRowWithEditor = this.renderRowWithEditor.bind(this);
this.renderValueWithRep = this.renderValueWithRep.bind(this);
this.shouldRenderSearchBox = this.shouldRenderSearchBox.bind(this);
this.updateFilterText = this.updateFilterText.bind(this);
}
getRowClass(object, sectionNames) {
return sectionNames.includes(object.name) ? "tree-section" : "";
},
}
onFilter(object, whiteList) {
let { name, value } = object;
@ -84,7 +93,7 @@ const PropertiesView = createClass({
let jsonString = JSON.stringify({ [name]: value }).toLowerCase();
return jsonString.includes(filterText.toLowerCase());
},
}
renderRowWithEditor(props) {
const { level, name, value, path } = props.member;
@ -106,7 +115,7 @@ const PropertiesView = createClass({
}
return TreeRow(props);
},
}
renderValueWithRep(props) {
const { member } = props;
@ -128,18 +137,18 @@ const PropertiesView = createClass({
mode: MODE.TINY,
cropLimit: this.props.cropLimit,
}));
},
}
shouldRenderSearchBox(object) {
return this.props.enableFilter && object && Object.keys(object)
.filter((section) => !object[section][EDITOR_CONFIG_ID]).length > 0;
},
}
updateFilterText(filterText) {
this.setState({
filterText,
});
},
}
render() {
const {
@ -191,6 +200,6 @@ const PropertiesView = createClass({
)
);
}
});
}
module.exports = PropertiesView;

View File

@ -5,24 +5,24 @@
"use strict";
const {
createClass,
Component,
DOM,
PropTypes,
} = require("devtools/client/shared/vendor/react");
const { div } = DOM;
const RequestListColumnCause = createClass({
displayName: "RequestListColumnCause",
propTypes: {
item: PropTypes.object.isRequired,
onCauseBadgeMouseDown: PropTypes.func.isRequired,
},
class RequestListColumnCause extends Component {
static get propTypes() {
return {
item: PropTypes.object.isRequired,
onCauseBadgeMouseDown: PropTypes.func.isRequired,
};
}
shouldComponentUpdate(nextProps) {
return this.props.item.cause !== nextProps.item.cause;
},
}
render() {
let {
@ -49,6 +49,6 @@ const RequestListColumnCause = createClass({
)
);
}
});
}
module.exports = RequestListColumnCause;

View File

@ -5,7 +5,7 @@
"use strict";
const {
createClass,
Component,
DOM,
PropTypes,
} = require("devtools/client/shared/vendor/react");
@ -13,16 +13,16 @@ const { getFormattedSize } = require("../utils/format-utils");
const { div } = DOM;
const RequestListColumnContentSize = createClass({
displayName: "RequestListColumnContentSize",
propTypes: {
item: PropTypes.object.isRequired,
},
class RequestListColumnContentSize extends Component {
static get propTypes() {
return {
item: PropTypes.object.isRequired,
};
}
shouldComponentUpdate(nextProps) {
return this.props.item.contentSize !== nextProps.item.contentSize;
},
}
render() {
let { contentSize } = this.props.item;
@ -31,6 +31,6 @@ const RequestListColumnContentSize = createClass({
div({ className: "requests-list-column requests-list-size", title: size }, size)
);
}
});
}
module.exports = RequestListColumnContentSize;

View File

@ -5,19 +5,19 @@
"use strict";
const {
createClass,
Component,
DOM,
PropTypes,
} = require("devtools/client/shared/vendor/react");
const { div } = DOM;
const RequestListColumnCookies = createClass({
displayName: "RequestListColumnCookies",
propTypes: {
item: PropTypes.object.isRequired,
},
class RequestListColumnCookies extends Component {
static get propTypes() {
return {
item: PropTypes.object.isRequired,
};
}
shouldComponentUpdate(nextProps) {
let { requestCookies: currRequestCookies = { cookies: [] } } = this.props.item;
@ -25,7 +25,7 @@ const RequestListColumnCookies = createClass({
currRequestCookies = currRequestCookies.cookies || currRequestCookies;
nextRequestCookies = nextRequestCookies.cookies || nextRequestCookies;
return currRequestCookies !== nextRequestCookies;
},
}
render() {
let { requestCookies = { cookies: [] } } = this.props.item;
@ -38,6 +38,6 @@ const RequestListColumnCookies = createClass({
}, requestCookiesLength)
);
}
});
}
module.exports = RequestListColumnCookies;

View File

@ -5,7 +5,7 @@
"use strict";
const {
createClass,
Component,
DOM,
PropTypes,
} = require("devtools/client/shared/vendor/react");
@ -21,17 +21,17 @@ const UPDATED_DOMAIN_PROPS = [
"urlDetails",
];
const RequestListColumnDomain = createClass({
displayName: "RequestListColumnDomain",
propTypes: {
item: PropTypes.object.isRequired,
onSecurityIconMouseDown: PropTypes.func.isRequired,
},
class RequestListColumnDomain extends Component {
static get propTypes() {
return {
item: PropTypes.object.isRequired,
onSecurityIconMouseDown: PropTypes.func.isRequired,
};
}
shouldComponentUpdate(nextProps) {
return !propertiesEqual(UPDATED_DOMAIN_PROPS, this.props.item, nextProps.item);
},
}
render() {
let { item, onSecurityIconMouseDown } = this.props;
@ -61,6 +61,6 @@ const RequestListColumnDomain = createClass({
)
);
}
});
}
module.exports = RequestListColumnDomain;

View File

@ -5,7 +5,7 @@
"use strict";
const {
createClass,
Component,
DOM,
PropTypes,
} = require("devtools/client/shared/vendor/react");
@ -13,16 +13,16 @@ const { getFormattedTime } = require("../utils/format-utils");
const { div } = DOM;
const RequestListColumnDuration = createClass({
displayName: "RequestListColumnDuration",
propTypes: {
item: PropTypes.object.isRequired,
},
class RequestListColumnDuration extends Component {
static get propTypes() {
return {
item: PropTypes.object.isRequired,
};
}
shouldComponentUpdate(nextProps) {
return this.props.item.totalTime !== nextProps.item.totalTime;
},
}
render() {
let { totalTime } = this.props.item;
@ -36,6 +36,6 @@ const RequestListColumnDuration = createClass({
)
);
}
});
}
module.exports = RequestListColumnDuration;

View File

@ -5,7 +5,7 @@
"use strict";
const {
createClass,
Component,
DOM,
PropTypes,
} = require("devtools/client/shared/vendor/react");
@ -14,17 +14,17 @@ const { getEndTime } = require("../utils/request-utils");
const { div } = DOM;
const RequestListColumnEndTime = createClass({
displayName: "RequestListColumnEndTime",
propTypes: {
firstRequestStartedMillis: PropTypes.number.isRequired,
item: PropTypes.object.isRequired,
},
class RequestListColumnEndTime extends Component {
static get propTypes() {
return {
firstRequestStartedMillis: PropTypes.number.isRequired,
item: PropTypes.object.isRequired,
};
}
shouldComponentUpdate(nextProps) {
return getEndTime(this.props.item) !== getEndTime(nextProps.item);
},
}
render() {
let { firstRequestStartedMillis, item } = this.props;
@ -39,6 +39,6 @@ const RequestListColumnEndTime = createClass({
)
);
}
});
}
module.exports = RequestListColumnEndTime;

View File

@ -5,7 +5,7 @@
"use strict";
const {
createClass,
Component,
DOM,
PropTypes,
} = require("devtools/client/shared/vendor/react");
@ -18,17 +18,17 @@ const UPDATED_FILE_PROPS = [
"urlDetails",
];
const RequestListColumnFile = createClass({
displayName: "RequestListColumnFile",
propTypes: {
item: PropTypes.object.isRequired,
onThumbnailMouseDown: PropTypes.func.isRequired,
},
class RequestListColumnFile extends Component {
static get propTypes() {
return {
item: PropTypes.object.isRequired,
onThumbnailMouseDown: PropTypes.func.isRequired,
};
}
shouldComponentUpdate(nextProps) {
return !propertiesEqual(UPDATED_FILE_PROPS, this.props.item, nextProps.item);
},
}
render() {
let {
@ -50,6 +50,6 @@ const RequestListColumnFile = createClass({
)
);
}
});
}
module.exports = RequestListColumnFile;

View File

@ -5,7 +5,7 @@
"use strict";
const {
createClass,
Component,
DOM,
PropTypes,
} = require("devtools/client/shared/vendor/react");
@ -13,18 +13,18 @@ const { getFormattedTime } = require("../utils/format-utils");
const { div } = DOM;
const RequestListColumnLatency = createClass({
displayName: "RequestListColumnLatency",
propTypes: {
item: PropTypes.object.isRequired,
},
class RequestListColumnLatency extends Component {
static get propTypes() {
return {
item: PropTypes.object.isRequired,
};
}
shouldComponentUpdate(nextProps) {
let { eventTimings: currEventTimings = { timings: {} } } = this.props.item;
let { eventTimings: nextEventTimings = { timings: {} } } = nextProps.item;
return currEventTimings.timings.wait !== nextEventTimings.timings.wait;
},
}
render() {
let { eventTimings = { timings: {} } } = this.props.item;
@ -39,6 +39,6 @@ const RequestListColumnLatency = createClass({
)
);
}
});
}
module.exports = RequestListColumnLatency;

View File

@ -5,28 +5,28 @@
"use strict";
const {
createClass,
Component,
DOM,
PropTypes,
} = require("devtools/client/shared/vendor/react");
const { div } = DOM;
const RequestListColumnMethod = createClass({
displayName: "RequestListColumnMethod",
propTypes: {
item: PropTypes.object.isRequired,
},
class RequestListColumnMethod extends Component {
static get propTypes() {
return {
item: PropTypes.object.isRequired,
};
}
shouldComponentUpdate(nextProps) {
return this.props.item.method !== nextProps.item.method;
},
}
render() {
let { method } = this.props.item;
return div({ className: "requests-list-column requests-list-method" }, method);
}
});
}
module.exports = RequestListColumnMethod;

View File

@ -5,7 +5,7 @@
"use strict";
const {
createClass,
Component,
DOM,
PropTypes,
} = require("devtools/client/shared/vendor/react");
@ -13,17 +13,17 @@ const { getFormattedProtocol } = require("../utils/request-utils");
const { div } = DOM;
const RequestListColumnProtocol = createClass({
displayName: "RequestListColumnProtocol",
propTypes: {
item: PropTypes.object.isRequired,
},
class RequestListColumnProtocol extends Component {
static get propTypes() {
return {
item: PropTypes.object.isRequired,
};
}
shouldComponentUpdate(nextProps) {
return getFormattedProtocol(this.props.item) !==
getFormattedProtocol(nextProps.item);
},
}
render() {
let protocol = getFormattedProtocol(this.props.item);
@ -37,6 +37,6 @@ const RequestListColumnProtocol = createClass({
)
);
}
});
}
module.exports = RequestListColumnProtocol;

View File

@ -5,7 +5,7 @@
"use strict";
const {
createClass,
Component,
DOM,
PropTypes,
} = require("devtools/client/shared/vendor/react");
@ -13,16 +13,16 @@ const { getFormattedIPAndPort } = require("../utils/format-utils");
const { div } = DOM;
const RequestListColumnRemoteIP = createClass({
displayName: "RequestListColumnRemoteIP",
propTypes: {
item: PropTypes.object.isRequired,
},
class RequestListColumnRemoteIP extends Component {
static get propTypes() {
return {
item: PropTypes.object.isRequired,
};
}
shouldComponentUpdate(nextProps) {
return this.props.item.remoteAddress !== nextProps.item.remoteAddress;
},
}
render() {
let { remoteAddress, remotePort } = this.props.item;
@ -35,6 +35,6 @@ const RequestListColumnRemoteIP = createClass({
)
);
}
});
}
module.exports = RequestListColumnRemoteIP;

View File

@ -5,7 +5,7 @@
"use strict";
const {
createClass,
Component,
DOM,
PropTypes,
} = require("devtools/client/shared/vendor/react");
@ -17,19 +17,19 @@ const { div } = DOM;
* Renders a response header column in the requests list. The actual
* header to show is passed as a prop.
*/
const RequestListColumnResponseHeader = createClass({
displayName: "RequestListColumnResponseHeader",
propTypes: {
item: PropTypes.object.isRequired,
header: PropTypes.string.isRequired,
},
class RequestListColumnResponseHeader extends Component {
static get propTypes() {
return {
item: PropTypes.object.isRequired,
header: PropTypes.string.isRequired,
};
}
shouldComponentUpdate(nextProps) {
const currHeader = getResponseHeader(this.props.item, this.props.header);
const nextHeader = getResponseHeader(nextProps.item, nextProps.header);
return currHeader !== nextHeader;
},
}
render() {
let header = getResponseHeader(this.props.item, this.props.header);
@ -42,6 +42,6 @@ const RequestListColumnResponseHeader = createClass({
)
);
}
});
}
module.exports = RequestListColumnResponseHeader;

View File

@ -5,7 +5,7 @@
"use strict";
const {
createClass,
Component,
DOM,
PropTypes,
} = require("devtools/client/shared/vendor/react");
@ -14,17 +14,17 @@ const { getResponseTime } = require("../utils/request-utils");
const { div } = DOM;
const RequestListColumnResponseTime = createClass({
displayName: "RequestListColumnResponseTime",
propTypes: {
firstRequestStartedMillis: PropTypes.number.isRequired,
item: PropTypes.object.isRequired,
},
class RequestListColumnResponseTime extends Component {
static get propTypes() {
return {
firstRequestStartedMillis: PropTypes.number.isRequired,
item: PropTypes.object.isRequired,
};
}
shouldComponentUpdate(nextProps) {
return getResponseTime(this.props.item) !== getResponseTime(nextProps.item);
},
}
render() {
let { firstRequestStartedMillis, item } = this.props;
@ -40,6 +40,6 @@ const RequestListColumnResponseTime = createClass({
)
);
}
});
}
module.exports = RequestListColumnResponseTime;

View File

@ -5,23 +5,23 @@
"use strict";
const {
createClass,
Component,
DOM,
PropTypes,
} = require("devtools/client/shared/vendor/react");
const { div } = DOM;
const RequestListColumnScheme = createClass({
displayName: "RequestListColumnScheme",
propTypes: {
item: PropTypes.object.isRequired,
},
class RequestListColumnScheme extends Component {
static get propTypes() {
return {
item: PropTypes.object.isRequired,
};
}
shouldComponentUpdate(nextProps) {
return this.props.item.urlDetails.scheme !== nextProps.item.urlDetails.scheme;
},
}
render() {
const { urlDetails } = this.props.item;
@ -34,6 +34,6 @@ const RequestListColumnScheme = createClass({
)
);
}
});
}
module.exports = RequestListColumnScheme;

View File

@ -5,19 +5,19 @@
"use strict";
const {
createClass,
Component,
DOM,
PropTypes,
} = require("devtools/client/shared/vendor/react");
const { div } = DOM;
const RequestListColumnSetCookies = createClass({
displayName: "RequestListColumnSetCookies",
propTypes: {
item: PropTypes.object.isRequired,
},
class RequestListColumnSetCookies extends Component {
static get propTypes() {
return {
item: PropTypes.object.isRequired,
};
}
shouldComponentUpdate(nextProps) {
let { responseCookies: currResponseCookies = { cookies: [] } } = this.props.item;
@ -25,7 +25,7 @@ const RequestListColumnSetCookies = createClass({
currResponseCookies = currResponseCookies.cookies || currResponseCookies;
nextResponseCookies = nextResponseCookies.cookies || nextResponseCookies;
return currResponseCookies !== nextResponseCookies;
},
}
render() {
let { responseCookies = { cookies: [] } } = this.props.item;
@ -38,6 +38,6 @@ const RequestListColumnSetCookies = createClass({
}, responseCookiesLength)
);
}
});
}
module.exports = RequestListColumnSetCookies;

View File

@ -5,7 +5,7 @@
"use strict";
const {
createClass,
Component,
DOM,
PropTypes,
} = require("devtools/client/shared/vendor/react");
@ -14,18 +14,18 @@ const { getStartTime } = require("../utils/request-utils");
const { div } = DOM;
const RequestListColumnStartTime = createClass({
displayName: "RequestListColumnStartTime",
propTypes: {
firstRequestStartedMillis: PropTypes.number.isRequired,
item: PropTypes.object.isRequired,
},
class RequestListColumnStartTime extends Component {
static get propTypes() {
return {
firstRequestStartedMillis: PropTypes.number.isRequired,
item: PropTypes.object.isRequired,
};
}
shouldComponentUpdate(nextProps) {
return getStartTime(this.props.item, this.props.firstRequestStartedMillis)
!== getStartTime(nextProps.item, nextProps.firstRequestStartedMillis);
},
}
render() {
let { firstRequestStartedMillis, item } = this.props;
@ -40,6 +40,6 @@ const RequestListColumnStartTime = createClass({
)
);
}
});
}
module.exports = RequestListColumnStartTime;

View File

@ -5,7 +5,7 @@
"use strict";
const {
createClass,
Component,
DOM,
PropTypes,
} = require("devtools/client/shared/vendor/react");
@ -21,16 +21,16 @@ const UPDATED_STATUS_PROPS = [
"statusText",
];
const RequestListColumnStatus = createClass({
displayName: "RequestListColumnStatus",
propTypes: {
item: PropTypes.object.isRequired,
},
class RequestListColumnStatus extends Component {
static get propTypes() {
return {
item: PropTypes.object.isRequired,
};
}
shouldComponentUpdate(nextProps) {
return !propertiesEqual(UPDATED_STATUS_PROPS, this.props.item, nextProps.item);
},
}
render() {
let { fromCache, fromServiceWorker, status, statusText } = this.props.item;
@ -69,6 +69,6 @@ const RequestListColumnStatus = createClass({
)
);
}
});
}
module.exports = RequestListColumnStatus;

View File

@ -5,7 +5,7 @@
"use strict";
const {
createClass,
Component,
DOM,
PropTypes,
} = require("devtools/client/shared/vendor/react");
@ -21,16 +21,16 @@ const UPDATED_TRANSFERRED_PROPS = [
"fromServiceWorker",
];
const RequestListColumnTransferredSize = createClass({
displayName: "RequestListColumnTransferredSize",
propTypes: {
item: PropTypes.object.isRequired,
},
class RequestListColumnTransferredSize extends Component {
static get propTypes() {
return {
item: PropTypes.object.isRequired,
};
}
shouldComponentUpdate(nextProps) {
return !propertiesEqual(UPDATED_TRANSFERRED_PROPS, this.props.item, nextProps.item);
},
}
render() {
let { fromCache, fromServiceWorker, status, transferredSize } = this.props.item;
@ -52,6 +52,6 @@ const RequestListColumnTransferredSize = createClass({
)
);
}
});
}
module.exports = RequestListColumnTransferredSize;

View File

@ -5,7 +5,7 @@
"use strict";
const {
createClass,
Component,
DOM,
PropTypes,
} = require("devtools/client/shared/vendor/react");
@ -13,16 +13,16 @@ const { getAbbreviatedMimeType } = require("../utils/request-utils");
const { div } = DOM;
const RequestListColumnType = createClass({
displayName: "RequestListColumnType",
propTypes: {
item: PropTypes.object.isRequired,
},
class RequestListColumnType extends Component {
static get propTypes() {
return {
item: PropTypes.object.isRequired,
};
}
shouldComponentUpdate(nextProps) {
return this.props.item.mimeType !== nextProps.item.mimeType;
},
}
render() {
let { mimeType } = this.props.item;
@ -41,6 +41,6 @@ const RequestListColumnType = createClass({
)
);
}
});
}
module.exports = RequestListColumnType;

View File

@ -5,7 +5,7 @@
"use strict";
const {
createClass,
Component,
DOM,
PropTypes,
} = require("devtools/client/shared/vendor/react");
@ -23,19 +23,19 @@ const UPDATED_WATERFALL_PROPS = [
// List of properties of the timing info we want to create boxes for
const TIMING_KEYS = ["blocked", "dns", "connect", "ssl", "send", "wait", "receive"];
const RequestListColumnWaterfall = createClass({
displayName: "RequestListColumnWaterfall",
propTypes: {
firstRequestStartedMillis: PropTypes.number.isRequired,
item: PropTypes.object.isRequired,
onWaterfallMouseDown: PropTypes.func.isRequired,
},
class RequestListColumnWaterfall extends Component {
static get propTypes() {
return {
firstRequestStartedMillis: PropTypes.number.isRequired,
item: PropTypes.object.isRequired,
onWaterfallMouseDown: PropTypes.func.isRequired,
};
}
shouldComponentUpdate(nextProps) {
return !propertiesEqual(UPDATED_WATERFALL_PROPS, this.props.item, nextProps.item) ||
this.props.firstRequestStartedMillis !== nextProps.firstRequestStartedMillis;
},
}
render() {
let { firstRequestStartedMillis, item, onWaterfallMouseDown } = this.props;
@ -62,7 +62,7 @@ const RequestListColumnWaterfall = createClass({
)
);
}
});
}
function timingTooltip(item) {
let { eventTimings, fromCache, fromServiceWorker, totalTime } = item;

View File

@ -5,7 +5,7 @@
"use strict";
const {
createClass,
Component,
createFactory,
DOM,
PropTypes,
@ -31,25 +31,36 @@ const REQUESTS_TOOLTIP_TOGGLE_DELAY = 500;
/**
* Renders the actual contents of the request list.
*/
const RequestListContent = createClass({
displayName: "RequestListContent",
class RequestListContent extends Component {
static get propTypes() {
return {
connector: PropTypes.object.isRequired,
columns: PropTypes.object.isRequired,
dispatch: PropTypes.func.isRequired,
displayedRequests: PropTypes.object.isRequired,
firstRequestStartedMillis: PropTypes.number.isRequired,
fromCache: PropTypes.bool,
onCauseBadgeMouseDown: PropTypes.func.isRequired,
onItemMouseDown: PropTypes.func.isRequired,
onSecurityIconMouseDown: PropTypes.func.isRequired,
onSelectDelta: PropTypes.func.isRequired,
onThumbnailMouseDown: PropTypes.func.isRequired,
onWaterfallMouseDown: PropTypes.func.isRequired,
scale: PropTypes.number,
selectedRequestId: PropTypes.string,
};
}
propTypes: {
connector: PropTypes.object.isRequired,
columns: PropTypes.object.isRequired,
dispatch: PropTypes.func.isRequired,
displayedRequests: PropTypes.object.isRequired,
firstRequestStartedMillis: PropTypes.number.isRequired,
fromCache: PropTypes.bool,
onCauseBadgeMouseDown: PropTypes.func.isRequired,
onItemMouseDown: PropTypes.func.isRequired,
onSecurityIconMouseDown: PropTypes.func.isRequired,
onSelectDelta: PropTypes.func.isRequired,
onThumbnailMouseDown: PropTypes.func.isRequired,
onWaterfallMouseDown: PropTypes.func.isRequired,
scale: PropTypes.number,
selectedRequestId: PropTypes.string,
},
constructor(props) {
super(props);
this.setScalingStyles = this.setScalingStyles.bind(this);
this.isScrolledToBottom = this.isScrolledToBottom.bind(this);
this.onHover = this.onHover.bind(this);
this.onScroll = this.onScroll.bind(this);
this.onKeyDown = this.onKeyDown.bind(this);
this.onContextMenu = this.onContextMenu.bind(this);
this.onFocusedNodeChange = this.onFocusedNodeChange.bind(this);
}
componentWillMount() {
const { dispatch, connector } = this.props;
@ -60,7 +71,7 @@ const RequestListContent = createClass({
openStatistics: (open) => dispatch(Actions.openStatistics(connector, open)),
});
this.tooltip = new HTMLTooltip(window.parent.document, { type: "arrow" });
},
}
componentDidMount() {
// Set the CSS variables for waterfall scaling
@ -74,14 +85,14 @@ const RequestListContent = createClass({
// Install event handler to hide the tooltip on scroll
this.refs.contentEl.addEventListener("scroll", this.onScroll, true);
},
}
componentWillUpdate(nextProps) {
// Check if the list is scrolled to bottom before the UI update.
// The scroll is ever needed only if new rows are added to the list.
const delta = nextProps.displayedRequests.size - this.props.displayedRequests.size;
this.shouldScrollBottom = delta > 0 && this.isScrolledToBottom();
},
}
componentDidUpdate(prevProps) {
// Update the CSS variables for waterfall scaling after props change
@ -92,14 +103,14 @@ const RequestListContent = createClass({
let node = this.refs.contentEl;
node.scrollTop = node.scrollHeight;
}
},
}
componentWillUnmount() {
this.refs.contentEl.removeEventListener("scroll", this.onScroll, true);
// Uninstall the tooltip event handler
this.tooltip.stopTogglingOnHover();
},
}
/**
* Set the CSS variables for waterfall scaling. If React supported setting CSS
@ -119,7 +130,7 @@ const RequestListContent = createClass({
style.removeProperty("--timings-rev-scale");
style.setProperty("--timings-scale", scale);
style.setProperty("--timings-rev-scale", 1 / scale);
},
}
isScrolledToBottom() {
const { contentEl } = this.refs;
@ -133,7 +144,7 @@ const RequestListContent = createClass({
let contentRect = contentEl.getBoundingClientRect();
return (lastChildRect.height + lastChildRect.top) <= contentRect.bottom;
},
}
/**
* The predicate used when deciding whether a popup should be shown
@ -165,14 +176,14 @@ const RequestListContent = createClass({
}
return false;
},
}
/**
* Scroll listener for the requests menu view.
*/
onScroll() {
this.tooltip.hide();
},
}
/**
* Handler for keyboard events. For arrow up/down, page up/down, home/end,
@ -210,12 +221,12 @@ const RequestListContent = createClass({
evt.stopPropagation();
this.props.onSelectDelta(delta);
}
},
}
onContextMenu(evt) {
evt.preventDefault();
this.contextMenu.open(evt);
},
}
/**
* If selection has just changed (by keyboard navigation), don't keep the list
@ -223,7 +234,7 @@ const RequestListContent = createClass({
*/
onFocusedNodeChange() {
this.shouldScrollBottom = false;
},
}
render() {
const {
@ -267,8 +278,8 @@ const RequestListContent = createClass({
)
)
);
},
});
}
}
module.exports = connect(
(state) => ({

View File

@ -5,7 +5,7 @@
"use strict";
const {
createClass,
Component,
createFactory,
DOM,
PropTypes,
@ -32,14 +32,14 @@ const PERFORMANCE_NOTICE_3 = L10N.getStr("netmonitor.perfNotice3");
* UI displayed when the request list is empty. Contains instructions on reloading
* the page and on triggering performance analysis of the page.
*/
const RequestListEmptyNotice = createClass({
displayName: "RequestListEmptyNotice",
propTypes: {
connector: PropTypes.object.isRequired,
onReloadClick: PropTypes.func.isRequired,
onPerfClick: PropTypes.func.isRequired,
},
class RequestListEmptyNotice extends Component {
static get propTypes() {
return {
connector: PropTypes.object.isRequired,
onReloadClick: PropTypes.func.isRequired,
onPerfClick: PropTypes.func.isRequired,
};
}
render() {
return div(
@ -71,7 +71,7 @@ const RequestListEmptyNotice = createClass({
)
);
}
});
}
module.exports = connect(
undefined,

View File

@ -5,7 +5,7 @@
"use strict";
const {
createClass,
Component,
PropTypes,
DOM,
} = require("devtools/client/shared/vendor/react");
@ -27,19 +27,26 @@ const { div, button } = DOM;
* Displays tick marks in the waterfall column header.
* Also draws the waterfall background canvas and updates it when needed.
*/
const RequestListHeader = createClass({
displayName: "RequestListHeader",
class RequestListHeader extends Component {
static get propTypes() {
return {
columns: PropTypes.object.isRequired,
resetColumns: PropTypes.func.isRequired,
resizeWaterfall: PropTypes.func.isRequired,
scale: PropTypes.number,
sort: PropTypes.object,
sortBy: PropTypes.func.isRequired,
toggleColumn: PropTypes.func.isRequired,
waterfallWidth: PropTypes.number,
};
}
propTypes: {
columns: PropTypes.object.isRequired,
resetColumns: PropTypes.func.isRequired,
resizeWaterfall: PropTypes.func.isRequired,
scale: PropTypes.number,
sort: PropTypes.object,
sortBy: PropTypes.func.isRequired,
toggleColumn: PropTypes.func.isRequired,
waterfallWidth: PropTypes.number,
},
constructor(props) {
super(props);
this.onContextMenu = this.onContextMenu.bind(this);
this.drawBackground = this.drawBackground.bind(this);
this.resizeWaterfall = this.resizeWaterfall.bind(this);
}
componentWillMount() {
const { resetColumns, toggleColumn } = this.props;
@ -47,7 +54,7 @@ const RequestListHeader = createClass({
resetColumns,
toggleColumn,
});
},
}
componentDidMount() {
// Create the object that takes care of drawing the waterfall canvas background
@ -56,23 +63,23 @@ const RequestListHeader = createClass({
this.resizeWaterfall();
window.addEventListener("resize", this.resizeWaterfall);
addThemeObserver(this.drawBackground);
},
}
componentDidUpdate() {
this.drawBackground();
},
}
componentWillUnmount() {
this.background.destroy();
this.background = null;
window.removeEventListener("resize", this.resizeWaterfall);
removeThemeObserver(this.drawBackground);
},
}
onContextMenu(evt) {
evt.preventDefault();
this.contextMenu.open(evt);
},
}
drawBackground() {
// The background component is theme dependent, so add the current theme to the props.
@ -80,7 +87,7 @@ const RequestListHeader = createClass({
theme: getTheme()
});
this.background.draw(props);
},
}
resizeWaterfall() {
let waterfallHeader = this.refs.waterfallHeader;
@ -91,7 +98,7 @@ const RequestListHeader = createClass({
this._resizeTimerId = window.requestIdleCallback(() =>
this.props.resizeWaterfall(waterfallHeader.getBoundingClientRect().width));
}
},
}
render() {
let { columns, scale, sort, sortBy, waterfallWidth } = this.props;
@ -141,7 +148,7 @@ const RequestListHeader = createClass({
)
);
}
});
}
/**
* Build the waterfall header - timing tick marks with the right spacing

View File

@ -5,7 +5,7 @@
"use strict";
const {
createClass,
Component,
createFactory,
DOM,
PropTypes,
@ -73,37 +73,37 @@ const UPDATED_REQ_PROPS = [
/**
* Render one row in the request list.
*/
const RequestListItem = createClass({
displayName: "RequestListItem",
propTypes: {
columns: PropTypes.object.isRequired,
item: PropTypes.object.isRequired,
index: PropTypes.number.isRequired,
isSelected: PropTypes.bool.isRequired,
firstRequestStartedMillis: PropTypes.number.isRequired,
fromCache: PropTypes.bool,
onCauseBadgeMouseDown: PropTypes.func.isRequired,
onContextMenu: PropTypes.func.isRequired,
onFocusedNodeChange: PropTypes.func,
onMouseDown: PropTypes.func.isRequired,
onSecurityIconMouseDown: PropTypes.func.isRequired,
onThumbnailMouseDown: PropTypes.func.isRequired,
onWaterfallMouseDown: PropTypes.func.isRequired,
waterfallWidth: PropTypes.number,
},
class RequestListItem extends Component {
static get propTypes() {
return {
columns: PropTypes.object.isRequired,
item: PropTypes.object.isRequired,
index: PropTypes.number.isRequired,
isSelected: PropTypes.bool.isRequired,
firstRequestStartedMillis: PropTypes.number.isRequired,
fromCache: PropTypes.bool,
onCauseBadgeMouseDown: PropTypes.func.isRequired,
onContextMenu: PropTypes.func.isRequired,
onFocusedNodeChange: PropTypes.func,
onMouseDown: PropTypes.func.isRequired,
onSecurityIconMouseDown: PropTypes.func.isRequired,
onThumbnailMouseDown: PropTypes.func.isRequired,
onWaterfallMouseDown: PropTypes.func.isRequired,
waterfallWidth: PropTypes.number,
};
}
componentDidMount() {
if (this.props.isSelected) {
this.refs.listItem.focus();
}
},
}
shouldComponentUpdate(nextProps) {
return !propertiesEqual(UPDATED_REQ_ITEM_PROPS, this.props.item, nextProps.item) ||
!propertiesEqual(UPDATED_REQ_PROPS, this.props, nextProps) ||
!I.is(this.props.columns, nextProps.columns);
},
}
componentDidUpdate(prevProps) {
if (!prevProps.isSelected && this.props.isSelected) {
@ -112,7 +112,7 @@ const RequestListItem = createClass({
this.props.onFocusedNodeChange();
}
}
},
}
render() {
let {
@ -174,6 +174,6 @@ const RequestListItem = createClass({
)
);
}
});
}
module.exports = RequestListItem;

View File

@ -5,7 +5,7 @@
"use strict";
const {
createClass,
Component,
createFactory,
DOM,
PropTypes,
@ -34,22 +34,27 @@ const JSON_VIEW_MIME_TYPE = "application/vnd.mozilla.json.view";
* Response panel component
* Displays the GET parameters and POST data of a request
*/
const ResponsePanel = createClass({
displayName: "ResponsePanel",
propTypes: {
request: PropTypes.object.isRequired,
openLink: PropTypes.func,
},
getInitialState() {
class ResponsePanel extends Component {
static get propTypes() {
return {
request: PropTypes.object.isRequired,
openLink: PropTypes.func,
};
}
constructor(props) {
super(props);
this.state = {
imageDimensions: {
width: 0,
height: 0,
},
};
},
this.updateImageDimemsions = this.updateImageDimemsions.bind(this);
this.isJSON = this.isJSON.bind(this);
}
updateImageDimemsions({ target }) {
this.setState({
@ -58,7 +63,7 @@ const ResponsePanel = createClass({
height: target.naturalHeight,
},
});
},
}
// Handle json, which we tentatively identify by checking the MIME type
// for "json" after any word boundary. This works for the standard
@ -114,7 +119,7 @@ const ResponsePanel = createClass({
}
return null;
},
}
render() {
let { openLink, request } = this.props;
@ -193,6 +198,6 @@ const ResponsePanel = createClass({
)
);
}
});
}
module.exports = ResponsePanel;

View File

@ -5,7 +5,7 @@
"use strict";
const {
createClass,
Component,
DOM,
PropTypes,
} = require("devtools/client/shared/vendor/react");
@ -17,15 +17,15 @@ const { div } = DOM;
/**
* CodeMirror editor as a React component
*/
const SourceEditor = createClass({
displayName: "SourceEditor",
propTypes: {
// Source editor syntax hightligh mode, which is a mime type defined in CodeMirror
mode: PropTypes.string,
// Source editor content
text: PropTypes.string,
},
class SourceEditor extends Component {
static get propTypes() {
return {
// Source editor syntax hightligh mode, which is a mime type defined in CodeMirror
mode: PropTypes.string,
// Source editor content
text: PropTypes.string,
};
}
componentDidMount() {
const { mode, text } = this.props;
@ -43,7 +43,7 @@ const SourceEditor = createClass({
this.editorTimeout = setTimeout(() => {
this.editor.appendToLocalElement(this.refs.editorElement);
});
},
}
componentDidUpdate(prevProps) {
const { mode, text } = this.props;
@ -56,12 +56,12 @@ const SourceEditor = createClass({
if (prevProps.text !== text) {
this.editor.setText(text);
}
},
}
componentWillUnmount() {
clearTimeout(this.editorTimeout);
this.editor.destroy();
},
}
render() {
return (
@ -71,6 +71,6 @@ const SourceEditor = createClass({
})
);
}
});
}
module.exports = SourceEditor;

View File

@ -7,7 +7,7 @@
const ReactDOM = require("devtools/client/shared/vendor/react-dom");
const { FILTER_TAGS } = require("../constants");
const {
createClass,
Component,
createFactory,
DOM,
PropTypes,
@ -40,25 +40,34 @@ const CHARTS_CACHE_DISABLED = L10N.getStr("charts.cacheDisabled");
* Performance analysis tool which shows you how long the browser takes to
* download the different parts of your site.
*/
const StatisticsPanel = createClass({
displayName: "StatisticsPanel",
propTypes: {
connector: PropTypes.object.isRequired,
closeStatistics: PropTypes.func.isRequired,
enableRequestFilterTypeOnly: PropTypes.func.isRequired,
requests: PropTypes.object,
},
getInitialState() {
class StatisticsPanel extends Component {
static get propTypes() {
return {
connector: PropTypes.object.isRequired,
closeStatistics: PropTypes.func.isRequired,
enableRequestFilterTypeOnly: PropTypes.func.isRequired,
requests: PropTypes.object,
};
}
constructor(props) {
super(props);
this.state = {
isVerticalSpliter: MediaQueryList.matches,
};
},
this.createMDNLink = this.createMDNLink.bind(this);
this.unmountMDNLinkContainers = this.unmountMDNLinkContainers.bind(this);
this.createChart = this.createChart.bind(this);
this.sanitizeChartDataSource = this.sanitizeChartDataSource.bind(this);
this.responseIsFresh = this.responseIsFresh.bind(this);
this.onLayoutChange = this.onLayoutChange.bind(this);
}
componentWillMount() {
this.mdnLinkContainerNodes = new Map();
},
}
componentDidUpdate(prevProps) {
MediaQueryList.addListener(this.onLayoutChange);
@ -83,12 +92,12 @@ const StatisticsPanel = createClass({
this.createMDNLink("primedCacheChart", getPerformanceAnalysisURL());
this.createMDNLink("emptyCacheChart", getPerformanceAnalysisURL());
},
}
componentWillUnmount() {
MediaQueryList.removeListener(this.onLayoutChange);
this.unmountMDNLinkContainers();
},
}
createMDNLink(chartId, url) {
if (this.mdnLinkContainerNodes.has(chartId)) {
@ -103,13 +112,13 @@ const StatisticsPanel = createClass({
title.appendChild(containerNode);
ReactDOM.render(MDNLink({ url }), containerNode);
this.mdnLinkContainerNodes.set(chartId, containerNode);
},
}
unmountMDNLinkContainers() {
for (let [, node] of this.mdnLinkContainerNodes) {
ReactDOM.unmountComponentAtNode(node);
}
},
}
createChart({ id, title, data }) {
// Create a new chart.
@ -166,7 +175,7 @@ const StatisticsPanel = createClass({
}
container.appendChild(chart.node);
},
}
sanitizeChartDataSource(requests, emptyCache) {
const data = FILTER_TAGS.map((type) => ({
@ -225,7 +234,7 @@ const StatisticsPanel = createClass({
}
return data.filter(e => e.count > 0);
},
}
/**
* Checks if the "Expiration Calculations" defined in section 13.2.4 of the
@ -263,13 +272,13 @@ const StatisticsPanel = createClass({
}
return false;
},
}
onLayoutChange() {
this.setState({
isVerticalSpliter: MediaQueryList.matches,
});
},
}
render() {
const { closeStatistics } = this.props;
@ -297,7 +306,7 @@ const StatisticsPanel = createClass({
)
);
}
});
}
module.exports = connect(
(state) => ({

View File

@ -6,7 +6,7 @@
const Services = require("Services");
const {
createClass,
Component,
createFactory,
DOM,
PropTypes,
@ -56,58 +56,65 @@ const DISABLE_CACHE_LABEL = L10N.getStr("netmonitor.toolbar.disableCache.label")
* Toolbar contains a set of useful tools to control network requests
* as well as set of filters for filtering the content.
*/
const Toolbar = createClass({
displayName: "Toolbar",
class Toolbar extends Component {
static get propTypes() {
return {
toggleRecording: PropTypes.func.isRequired,
recording: PropTypes.bool.isRequired,
clearRequests: PropTypes.func.isRequired,
requestFilterTypes: PropTypes.array.isRequired,
setRequestFilterText: PropTypes.func.isRequired,
networkDetailsToggleDisabled: PropTypes.bool.isRequired,
networkDetailsOpen: PropTypes.bool.isRequired,
toggleNetworkDetails: PropTypes.func.isRequired,
enablePersistentLogs: PropTypes.func.isRequired,
togglePersistentLogs: PropTypes.func.isRequired,
persistentLogsEnabled: PropTypes.bool.isRequired,
disableBrowserCache: PropTypes.func.isRequired,
toggleBrowserCache: PropTypes.func.isRequired,
browserCacheDisabled: PropTypes.bool.isRequired,
toggleRequestFilterType: PropTypes.func.isRequired,
filteredRequests: PropTypes.object.isRequired,
};
}
propTypes: {
toggleRecording: PropTypes.func.isRequired,
recording: PropTypes.bool.isRequired,
clearRequests: PropTypes.func.isRequired,
requestFilterTypes: PropTypes.array.isRequired,
setRequestFilterText: PropTypes.func.isRequired,
networkDetailsToggleDisabled: PropTypes.bool.isRequired,
networkDetailsOpen: PropTypes.bool.isRequired,
toggleNetworkDetails: PropTypes.func.isRequired,
enablePersistentLogs: PropTypes.func.isRequired,
togglePersistentLogs: PropTypes.func.isRequired,
persistentLogsEnabled: PropTypes.bool.isRequired,
disableBrowserCache: PropTypes.func.isRequired,
toggleBrowserCache: PropTypes.func.isRequired,
browserCacheDisabled: PropTypes.bool.isRequired,
toggleRequestFilterType: PropTypes.func.isRequired,
filteredRequests: PropTypes.object.isRequired,
},
constructor(props) {
super(props);
this.toggleRequestFilterType = this.toggleRequestFilterType.bind(this);
this.updatePersistentLogsEnabled = this.updatePersistentLogsEnabled.bind(this);
this.updateBrowserCacheDisabled = this.updateBrowserCacheDisabled.bind(this);
}
componentDidMount() {
Services.prefs.addObserver(DEVTOOLS_ENABLE_PERSISTENT_LOG_PREF,
this.updatePersistentLogsEnabled);
Services.prefs.addObserver(DEVTOOLS_DISABLE_CACHE_PREF,
this.updateBrowserCacheDisabled);
},
}
componentWillUnmount() {
Services.prefs.removeObserver(DEVTOOLS_ENABLE_PERSISTENT_LOG_PREF,
this.updatePersistentLogsEnabled);
Services.prefs.removeObserver(DEVTOOLS_DISABLE_CACHE_PREF,
this.updateBrowserCacheDisabled);
},
}
toggleRequestFilterType(evt) {
if (evt.type === "keydown" && (evt.key !== "" || evt.key !== "Enter")) {
return;
}
this.props.toggleRequestFilterType(evt.target.dataset.key);
},
}
updatePersistentLogsEnabled() {
this.props.enablePersistentLogs(
Services.prefs.getBoolPref(DEVTOOLS_ENABLE_PERSISTENT_LOG_PREF));
},
}
updateBrowserCacheDisabled() {
this.props.disableBrowserCache(
Services.prefs.getBoolPref(DEVTOOLS_DISABLE_CACHE_PREF));
},
}
render() {
let {
@ -226,8 +233,8 @@ const Toolbar = createClass({
)
)
);
},
});
}
}
module.exports = connect(
(state) => ({

View File

@ -3,28 +3,25 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const React = require("devtools/client/shared/vendor/react");
const NetInfoGroupList = React.createFactory(require("./net-info-group-list"));
const Spinner = React.createFactory(require("./spinner"));
// Shortcuts
const DOM = React.DOM;
const PropTypes = React.PropTypes;
const { Component, createFactory, DOM, PropTypes } =
require("devtools/client/shared/vendor/react");
const NetInfoGroupList = createFactory(require("./net-info-group-list"));
const Spinner = createFactory(require("./spinner"));
/**
* This template represents 'Cookies' tab displayed when the user
* expands network log in the Console panel. It's responsible for rendering
* sent and received cookies.
*/
var CookiesTab = React.createClass({
propTypes: {
actions: PropTypes.shape({
requestData: PropTypes.func.isRequired
}),
data: PropTypes.object.isRequired,
},
displayName: "CookiesTab",
class CookiesTab extends Component {
static get propTypes() {
return {
actions: PropTypes.shape({
requestData: PropTypes.func.isRequired
}),
data: PropTypes.object.isRequired,
};
}
componentDidMount() {
let { actions, data } = this.props;
@ -39,7 +36,7 @@ var CookiesTab = React.createClass({
if (!responseCookies || !responseCookies.length) {
actions.requestData("responseCookies");
}
},
}
render() {
let { actions, data: file } = this.props;
@ -69,7 +66,7 @@ var CookiesTab = React.createClass({
)
);
}
});
}
// Exports from this module
module.exports = CookiesTab;

View File

@ -3,28 +3,25 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const React = require("devtools/client/shared/vendor/react");
const NetInfoGroupList = React.createFactory(require("./net-info-group-list"));
const Spinner = React.createFactory(require("./spinner"));
// Shortcuts
const DOM = React.DOM;
const PropTypes = React.PropTypes;
const { Component, createFactory, DOM, PropTypes } =
require("devtools/client/shared/vendor/react");
const NetInfoGroupList = createFactory(require("./net-info-group-list"));
const Spinner = createFactory(require("./spinner"));
/**
* This template represents 'Headers' tab displayed when the user
* expands network log in the Console panel. It's responsible for rendering
* request and response HTTP headers.
*/
var HeadersTab = React.createClass({
propTypes: {
actions: PropTypes.shape({
requestData: PropTypes.func.isRequired
}),
data: PropTypes.object.isRequired,
},
displayName: "HeadersTab",
class HeadersTab extends Component {
static get propTypes() {
return {
actions: PropTypes.shape({
requestData: PropTypes.func.isRequired
}),
data: PropTypes.object.isRequired,
};
}
componentDidMount() {
let { actions, data } = this.props;
@ -40,7 +37,7 @@ var HeadersTab = React.createClass({
if (!responseHeaders) {
actions.requestData("responseHeaders");
}
},
}
render() {
let { data } = this.props;
@ -73,7 +70,7 @@ var HeadersTab = React.createClass({
)
);
}
});
}
// Exports from this module
module.exports = HeadersTab;

View File

@ -3,21 +3,20 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const React = require("devtools/client/shared/vendor/react");
const { Component, createFactory, PropTypes } =
require("devtools/client/shared/vendor/react");
const { createFactories } = require("devtools/client/shared/react-utils");
const { Tabs, TabPanel } = createFactories(require("devtools/client/shared/components/tabs/Tabs"));
// Network
const HeadersTab = React.createFactory(require("./headers-tab"));
const ResponseTab = React.createFactory(require("./response-tab"));
const ParamsTab = React.createFactory(require("./params-tab"));
const CookiesTab = React.createFactory(require("./cookies-tab"));
const PostTab = React.createFactory(require("./post-tab"));
const StackTraceTab = React.createFactory(require("./stacktrace-tab"));
const HeadersTab = createFactory(require("./headers-tab"));
const ResponseTab = createFactory(require("./response-tab"));
const ParamsTab = createFactory(require("./params-tab"));
const CookiesTab = createFactory(require("./cookies-tab"));
const PostTab = createFactory(require("./post-tab"));
const StackTraceTab = createFactory(require("./stacktrace-tab"));
const NetUtils = require("../utils/net");
// Shortcuts
const PropTypes = React.PropTypes;
/**
* This template renders the basic Network log info body. It's not
@ -31,51 +30,58 @@ const PropTypes = React.PropTypes;
* 4) Cookies - request and response cookies
* 5) Post - posted data
*/
var NetInfoBody = React.createClass({
propTypes: {
tabActive: PropTypes.number.isRequired,
actions: PropTypes.object.isRequired,
data: PropTypes.shape({
request: PropTypes.object.isRequired,
response: PropTypes.object.isRequired
}),
// Service to enable the source map feature.
sourceMapService: PropTypes.object,
},
class NetInfoBody extends Component {
static get propTypes() {
return {
tabActive: PropTypes.number.isRequired,
actions: PropTypes.object.isRequired,
data: PropTypes.shape({
request: PropTypes.object.isRequired,
response: PropTypes.object.isRequired
}),
// Service to enable the source map feature.
sourceMapService: PropTypes.object,
};
}
displayName: "NetInfoBody",
getDefaultProps() {
static get defaultProps() {
return {
tabActive: 0
};
},
}
getInitialState() {
return {
constructor(props) {
super(props);
this.state = {
data: {
request: {},
response: {}
},
tabActive: this.props.tabActive,
tabActive: props.tabActive,
};
},
this.onTabChanged = this.onTabChanged.bind(this);
this.hasCookies = this.hasCookies.bind(this);
this.hasStackTrace = this.hasStackTrace.bind(this);
this.getTabPanels = this.getTabPanels.bind(this);
}
onTabChanged(index) {
this.setState({tabActive: index});
},
}
hasCookies() {
let {request, response} = this.state.data;
return this.state.hasCookies ||
NetUtils.getHeaderValue(request.headers, "Cookie") ||
NetUtils.getHeaderValue(response.headers, "Set-Cookie");
},
}
hasStackTrace() {
let {cause} = this.state.data;
return cause && cause.stacktrace && cause.stacktrace.length > 0;
},
}
getTabPanels() {
let { actions, sourceMapService } = this.props;
@ -163,7 +169,7 @@ var NetInfoBody = React.createClass({
}
return panels;
},
}
render() {
let tabActive = this.state.tabActive;
@ -176,7 +182,7 @@ var NetInfoBody = React.createClass({
)
);
}
});
}
// Exports from this module
module.exports = NetInfoBody;

View File

@ -3,23 +3,20 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const React = require("devtools/client/shared/vendor/react");
const NetInfoGroup = React.createFactory(require("./net-info-group"));
// Shortcuts
const DOM = React.DOM;
const PropTypes = React.PropTypes;
const { Component, createFactory, DOM, PropTypes } =
require("devtools/client/shared/vendor/react");
const NetInfoGroup = createFactory(require("./net-info-group"));
/**
* This template is responsible for rendering sections/groups inside tabs.
* It's used e.g to display Response and Request headers as separate groups.
*/
var NetInfoGroupList = React.createClass({
propTypes: {
groups: PropTypes.array.isRequired,
},
displayName: "NetInfoGroupList",
class NetInfoGroupList extends Component {
static get propTypes() {
return {
groups: PropTypes.array.isRequired,
};
}
render() {
let groups = this.props.groups;
@ -41,7 +38,7 @@ var NetInfoGroupList = React.createClass({
)
);
}
});
}
// Exports from this module
module.exports = NetInfoGroupList;

View File

@ -3,46 +3,47 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const React = require("devtools/client/shared/vendor/react");
const NetInfoParams = React.createFactory(require("./net-info-params"));
// Shortcuts
const DOM = React.DOM;
const PropTypes = React.PropTypes;
const { Component, createFactory, DOM, PropTypes } =
require("devtools/client/shared/vendor/react");
const NetInfoParams = createFactory(require("./net-info-params"));
/**
* This template represents a group of data within a tab. For example,
* Headers tab has two groups 'Request Headers' and 'Response Headers'
* The Response tab can also have two groups 'Raw Data' and 'JSON'
*/
var NetInfoGroup = React.createClass({
propTypes: {
type: PropTypes.string.isRequired,
name: PropTypes.string.isRequired,
params: PropTypes.array,
content: PropTypes.element,
open: PropTypes.bool
},
class NetInfoGroup extends Component {
static get propTypes() {
return {
type: PropTypes.string.isRequired,
name: PropTypes.string.isRequired,
params: PropTypes.array,
content: PropTypes.element,
open: PropTypes.bool
};
}
displayName: "NetInfoGroup",
getDefaultProps() {
static get defaultProps() {
return {
open: true,
};
},
}
getInitialState() {
return {
open: this.props.open,
constructor(props) {
super(props);
this.state = {
open: props.open,
};
},
this.onToggle = this.onToggle.bind(this);
}
onToggle(event) {
this.setState({
open: !this.state.open
});
},
}
render() {
let content = this.props.content;
@ -74,7 +75,7 @@ var NetInfoGroup = React.createClass({
)
);
}
});
}
// Exports from this module
module.exports = NetInfoGroup;

View File

@ -3,25 +3,22 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const React = require("devtools/client/shared/vendor/react");
// Shortcuts
const DOM = React.DOM;
const PropTypes = React.PropTypes;
const { Component, DOM, PropTypes } =
require("devtools/client/shared/vendor/react");
/**
* This template renders list of parameters within a group.
* It's essentially a list of name + value pairs.
*/
var NetInfoParams = React.createClass({
displayName: "NetInfoParams",
propTypes: {
params: PropTypes.arrayOf(PropTypes.shape({
name: PropTypes.string.isRequired,
value: PropTypes.string.isRequired
})).isRequired,
},
class NetInfoParams extends Component {
static get propTypes() {
return {
params: PropTypes.arrayOf(PropTypes.shape({
name: PropTypes.string.isRequired,
value: PropTypes.string.isRequired
})).isRequired,
};
}
render() {
let params = this.props.params || [];
@ -52,7 +49,7 @@ var NetInfoParams = React.createClass({
)
);
}
});
}
// Exports from this module
module.exports = NetInfoParams;

View File

@ -3,26 +3,23 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const React = require("devtools/client/shared/vendor/react");
const NetInfoParams = React.createFactory(require("./net-info-params"));
// Shortcuts
const DOM = React.DOM;
const PropTypes = React.PropTypes;
const { Component, createFactory, DOM, PropTypes } =
require("devtools/client/shared/vendor/react");
const NetInfoParams = createFactory(require("./net-info-params"));
/**
* This template represents 'Params' tab displayed when the user
* expands network log in the Console panel. It's responsible for
* displaying URL parameters (query string).
*/
var ParamsTab = React.createClass({
propTypes: {
data: PropTypes.shape({
request: PropTypes.object.isRequired
})
},
displayName: "ParamsTab",
class ParamsTab extends Component {
static get propTypes() {
return {
data: PropTypes.shape({
request: PropTypes.object.isRequired
})
};
}
render() {
let data = this.props.data;
@ -35,7 +32,7 @@ var ParamsTab = React.createClass({
)
);
}
});
}
// Exports from this module
module.exports = ParamsTab;

View File

@ -3,45 +3,57 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const React = require("devtools/client/shared/vendor/react");
const { Component, createFactory, DOM, PropTypes } =
require("devtools/client/shared/vendor/react");
const TreeView = React.createFactory(require("devtools/client/shared/components/tree/TreeView"));
const TreeView =
createFactory(require("devtools/client/shared/components/tree/TreeView"));
const { REPS, MODE, parseURLEncodedText } = require("devtools/client/shared/components/reps/reps");
const { REPS, MODE, parseURLEncodedText } =
require("devtools/client/shared/components/reps/reps");
const { Rep } = REPS;
// Network
const NetInfoParams = React.createFactory(require("./net-info-params"));
const NetInfoGroupList = React.createFactory(require("./net-info-group-list"));
const Spinner = React.createFactory(require("./spinner"));
const SizeLimit = React.createFactory(require("./size-limit"));
const NetInfoParams = createFactory(require("./net-info-params"));
const NetInfoGroupList = createFactory(require("./net-info-group-list"));
const Spinner = createFactory(require("./spinner"));
const SizeLimit = createFactory(require("./size-limit"));
const NetUtils = require("../utils/net");
const Json = require("../utils/json");
// Shortcuts
const DOM = React.DOM;
const PropTypes = React.PropTypes;
/**
* This template represents 'Post' tab displayed when the user
* expands network log in the Console panel. It's responsible for
* displaying posted data (HTTP post body).
*/
var PostTab = React.createClass({
propTypes: {
data: PropTypes.shape({
request: PropTypes.object.isRequired
}),
actions: PropTypes.object.isRequired
},
class PostTab extends Component {
static get propTypes() {
return {
data: PropTypes.shape({
request: PropTypes.object.isRequired
}),
actions: PropTypes.object.isRequired
};
}
displayName: "PostTab",
constructor(props) {
super(props);
this.isJson = this.isJson.bind(this);
this.parseJson = this.parseJson.bind(this);
this.renderJson = this.renderJson.bind(this);
this.parseXml = this.parseXml.bind(this);
this.isXml = this.isXml.bind(this);
this.renderXml = this.renderXml.bind(this);
this.renderMultiPart = this.renderMultiPart.bind(this);
this.renderUrlEncoded = this.renderUrlEncoded.bind(this);
this.renderRawData = this.renderRawData.bind(this);
}
isJson(file) {
let text = file.request.postData.text;
let value = NetUtils.getHeaderValue(file.request.headers, "content-type");
return Json.isJSON(value, text);
},
}
parseJson(file) {
let postData = file.request.postData;
@ -51,7 +63,7 @@ var PostTab = React.createClass({
let jsonString = new String(postData.text);
return Json.parseJSONString(jsonString);
},
}
/**
* Render JSON post data as an expandable tree.
@ -83,7 +95,7 @@ var PostTab = React.createClass({
}),
name: Locale.$STR("jsonScopeName")
};
},
}
parseXml(file) {
let text = file.request.postData.text;
@ -95,7 +107,7 @@ var PostTab = React.createClass({
mimeType: NetUtils.getHeaderValue(file.request.headers, "content-type"),
text: text,
});
},
}
isXml(file) {
if (isLongString(file.request.postData.text)) {
@ -108,7 +120,7 @@ var PostTab = React.createClass({
}
return NetUtils.isHTML(value);
},
}
renderXml(file) {
let text = file.request.postData.text;
@ -127,7 +139,7 @@ var PostTab = React.createClass({
// Proper component for rendering XML should be used (see bug 1247392)
return null;
},
}
/**
* Multipart post data are parsed and nicely rendered
@ -144,7 +156,7 @@ var PostTab = React.createClass({
}
return;
},
}
/**
* URL encoded post data are nicely rendered as a list
@ -168,7 +180,7 @@ var PostTab = React.createClass({
content: NetInfoParams({params: params}),
name: Locale.$STR("netRequest.params")
};
},
}
renderRawData(file) {
let text = file.request.postData.text;
@ -202,7 +214,7 @@ var PostTab = React.createClass({
}
return group;
},
}
componentDidMount() {
let { actions, data: file } = this.props;
@ -211,7 +223,7 @@ var PostTab = React.createClass({
// TODO: use async action objects as soon as Redux is in place
actions.requestData("requestPostData");
}
},
}
render() {
let { actions, data: file } = this.props;
@ -257,7 +269,7 @@ var PostTab = React.createClass({
)
);
}
});
}
// Helpers

View File

@ -3,24 +3,21 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const React = require("devtools/client/shared/vendor/react");
const { Component, createFactory, DOM, PropTypes } =
require("devtools/client/shared/vendor/react");
// Reps
const TreeView = React.createFactory(require("devtools/client/shared/components/tree/TreeView"));
const TreeView = createFactory(require("devtools/client/shared/components/tree/TreeView"));
const { REPS, MODE } = require("devtools/client/shared/components/reps/reps");
const { Rep } = REPS;
// Network
const SizeLimit = React.createFactory(require("./size-limit"));
const NetInfoGroupList = React.createFactory(require("./net-info-group-list"));
const Spinner = React.createFactory(require("./spinner"));
const SizeLimit = createFactory(require("./size-limit"));
const NetInfoGroupList = createFactory(require("./net-info-group-list"));
const Spinner = createFactory(require("./spinner"));
const Json = require("../utils/json");
const NetUtils = require("../utils/net");
// Shortcuts
const DOM = React.DOM;
const PropTypes = React.PropTypes;
/**
* This template represents 'Response' tab displayed when the user
* expands network log in the Console panel. It's responsible for
@ -30,16 +27,30 @@ const PropTypes = React.PropTypes;
* text/xml, etc.), the response is parsed using appropriate parser
* and rendered accordingly.
*/
var ResponseTab = React.createClass({
propTypes: {
data: PropTypes.shape({
request: PropTypes.object.isRequired,
response: PropTypes.object.isRequired
}),
actions: PropTypes.object.isRequired
},
class ResponseTab extends Component {
static get propTypes() {
return {
data: PropTypes.shape({
request: PropTypes.object.isRequired,
response: PropTypes.object.isRequired
}),
actions: PropTypes.object.isRequired
};
}
displayName: "ResponseTab",
constructor(props) {
super(props);
this.isJson = this.isJson.bind(this);
this.parseJson = this.parseJson.bind(this);
this.isImage = this.isImage.bind(this);
this.isXml = this.isXml.bind(this);
this.parseXml = this.parseXml.bind(this);
this.renderJson = this.renderJson.bind(this);
this.renderImage = this.renderImage.bind(this);
this.renderXml = this.renderXml.bind(this);
this.renderFormattedResponse = this.renderFormattedResponse.bind(this);
this.renderRawResponse = this.renderRawResponse.bind(this);
}
// Response Types
@ -49,7 +60,7 @@ var ResponseTab = React.createClass({
}
return Json.isJSON(content.mimeType, content.text);
},
}
parseJson(file) {
let content = file.response.content;
@ -59,7 +70,7 @@ var ResponseTab = React.createClass({
let jsonString = new String(content.text);
return Json.parseJSONString(jsonString);
},
}
isImage(content) {
if (isLongString(content.text)) {
@ -67,7 +78,7 @@ var ResponseTab = React.createClass({
}
return NetUtils.isImage(content.mimeType);
},
}
isXml(content) {
if (isLongString(content.text)) {
@ -75,7 +86,7 @@ var ResponseTab = React.createClass({
}
return NetUtils.isHTML(content.mimeType);
},
}
parseXml(file) {
let content = file.response.content;
@ -84,7 +95,7 @@ var ResponseTab = React.createClass({
}
return NetUtils.parseXml(content);
},
}
// Rendering
@ -111,7 +122,7 @@ var ResponseTab = React.createClass({
}),
name: Locale.$STR("jsonScopeName")
};
},
}
renderImage(file) {
let content = file.response.content;
@ -125,7 +136,7 @@ var ResponseTab = React.createClass({
content: DOM.img({src: dataUri}),
name: Locale.$STR("netRequest.image")
};
},
}
renderXml(file) {
let content = file.response.content;
@ -140,7 +151,7 @@ var ResponseTab = React.createClass({
// Proper component for rendering XML should be used (see bug 1247392)
return null;
},
}
/**
* If full response text is available, let's try to parse and
@ -166,7 +177,7 @@ var ResponseTab = React.createClass({
if (group) {
return group;
}
},
}
renderRawResponse(file) {
let group;
@ -199,7 +210,7 @@ var ResponseTab = React.createClass({
}
return group;
},
}
componentDidMount() {
let { actions, data: file } = this.props;
@ -209,7 +220,7 @@ var ResponseTab = React.createClass({
// TODO: use async action objects as soon as Redux is in place
actions.requestData("responseContent");
}
},
}
/**
* The response panel displays two groups:
@ -265,7 +276,7 @@ var ResponseTab = React.createClass({
)
);
}
});
}
// Helpers

View File

@ -3,11 +3,8 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const React = require("devtools/client/shared/vendor/react");
// Shortcuts
const DOM = React.DOM;
const PropTypes = React.PropTypes;
const { Component, DOM, PropTypes } =
require("devtools/client/shared/vendor/react");
/**
* This template represents a size limit notification message
@ -15,17 +12,22 @@ const PropTypes = React.PropTypes;
* size limit. The message contains a link allowing the user
* to fetch the rest of the data from the backend (debugger server).
*/
var SizeLimit = React.createClass({
propTypes: {
data: PropTypes.object.isRequired,
message: PropTypes.string.isRequired,
link: PropTypes.string.isRequired,
actions: PropTypes.shape({
resolveString: PropTypes.func.isRequired
}),
},
class SizeLimit extends Component {
static get propTypes() {
return {
data: PropTypes.object.isRequired,
message: PropTypes.string.isRequired,
link: PropTypes.string.isRequired,
actions: PropTypes.shape({
resolveString: PropTypes.func.isRequired
}),
};
}
displayName: "SizeLimit",
constructor(props) {
super(props);
this.onClickLimit = this.onClickLimit.bind(this);
}
// Event Handlers
@ -34,7 +36,7 @@ var SizeLimit = React.createClass({
let content = this.props.data;
actions.resolveString(content, "text");
},
}
// Rendering
@ -56,7 +58,7 @@ var SizeLimit = React.createClass({
)
);
}
});
}
// Exports from this module
module.exports = SizeLimit;

View File

@ -3,24 +3,19 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const React = require("devtools/client/shared/vendor/react");
// Shortcuts
const DOM = React.DOM;
const { Component, DOM } = require("devtools/client/shared/vendor/react");
/**
* This template represents a throbber displayed when the UI
* is waiting for data coming from the backend (debugging server).
*/
var Spinner = React.createClass({
displayName: "Spinner",
class Spinner extends Component {
render() {
return (
DOM.div({className: "devtools-throbber"})
);
}
});
}
// Exports from this module
module.exports = Spinner;

View File

@ -3,20 +3,22 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const { PropTypes, createClass, createFactory } = require("devtools/client/shared/vendor/react");
const StackTrace = createFactory(require("devtools/client/shared/components/StackTrace"));
const { PropTypes, Component, createFactory } =
require("devtools/client/shared/vendor/react");
const StackTrace =
createFactory(require("devtools/client/shared/components/StackTrace"));
const StackTraceTab = createClass({
displayName: "StackTraceTab",
propTypes: {
data: PropTypes.object.isRequired,
actions: PropTypes.shape({
onViewSourceInDebugger: PropTypes.func.isRequired
}),
// Service to enable the source map feature.
sourceMapService: PropTypes.object,
},
class StackTraceTab extends Component {
static get propTypes() {
return {
data: PropTypes.object.isRequired,
actions: PropTypes.shape({
onViewSourceInDebugger: PropTypes.func.isRequired
}),
// Service to enable the source map feature.
sourceMapService: PropTypes.object,
};
}
render() {
let { stacktrace } = this.props.data.cause;
@ -25,7 +27,7 @@ const StackTraceTab = createClass({
return StackTrace({ stacktrace, onViewSourceInDebugger, sourceMapService });
}
});
}
// Exports from this module
module.exports = StackTraceTab;

View File

@ -4,7 +4,7 @@
"use strict";
const {
createClass,
Component,
createFactory,
DOM: dom,
PropTypes
@ -24,26 +24,30 @@ const {
MESSAGE_TYPE,
} = require("devtools/client/webconsole/new-console-output/constants");
const ConsoleOutput = createClass({
class ConsoleOutput extends Component {
static get propTypes() {
return {
messages: PropTypes.object.isRequired,
messagesUi: PropTypes.object.isRequired,
serviceContainer: PropTypes.shape({
attachRefToHud: PropTypes.func.isRequired,
openContextMenu: PropTypes.func.isRequired,
sourceMapService: PropTypes.object,
}),
dispatch: PropTypes.func.isRequired,
timestampsVisible: PropTypes.bool,
messagesTableData: PropTypes.object.isRequired,
messagesRepeat: PropTypes.object.isRequired,
networkMessagesUpdate: PropTypes.object.isRequired,
visibleMessages: PropTypes.array.isRequired,
networkMessageActiveTabId: PropTypes.string.isRequired,
};
}
displayName: "ConsoleOutput",
propTypes: {
messages: PropTypes.object.isRequired,
messagesUi: PropTypes.object.isRequired,
serviceContainer: PropTypes.shape({
attachRefToHud: PropTypes.func.isRequired,
openContextMenu: PropTypes.func.isRequired,
sourceMapService: PropTypes.object,
}),
dispatch: PropTypes.func.isRequired,
timestampsVisible: PropTypes.bool,
messagesTableData: PropTypes.object.isRequired,
messagesRepeat: PropTypes.object.isRequired,
networkMessagesUpdate: PropTypes.object.isRequired,
visibleMessages: PropTypes.array.isRequired,
networkMessageActiveTabId: PropTypes.string.isRequired,
},
constructor(props) {
super(props);
this.onContextMenu = this.onContextMenu.bind(this);
}
componentDidMount() {
// Do the scrolling in the nextTick since this could hit console startup performances.
@ -52,7 +56,7 @@ const ConsoleOutput = createClass({
scrollToBottom(this.outputNode);
}, 0);
this.props.serviceContainer.attachRefToHud("outputScroller", this.outputNode);
},
}
componentWillUpdate(nextProps, nextState) {
const outputNode = this.outputNode;
@ -78,19 +82,19 @@ const ConsoleOutput = createClass({
this.shouldScrollBottom =
(messagesDelta > 0 && nextProps.messages.last().type === MESSAGE_TYPE.RESULT) ||
(visibleMessagesDelta > 0 && isScrolledToBottom(lastChild, outputNode));
},
}
componentDidUpdate() {
if (this.shouldScrollBottom) {
scrollToBottom(this.outputNode);
}
},
}
onContextMenu(e) {
this.props.serviceContainer.openContextMenu(e);
e.stopPropagation();
e.preventDefault();
},
}
render() {
let {
@ -131,7 +135,7 @@ const ConsoleOutput = createClass({
)
);
}
});
}
function scrollToBottom(node) {
node.scrollTop = node.scrollHeight;

View File

@ -4,7 +4,7 @@
"use strict";
const {
createClass,
Component,
createFactory,
DOM: dom,
PropTypes
@ -18,21 +18,26 @@ const GripMessageBody = createFactory(require("devtools/client/webconsole/new-co
const TABLE_ROW_MAX_ITEMS = 1000;
const TABLE_COLUMN_MAX_ITEMS = 10;
const ConsoleTable = createClass({
class ConsoleTable extends Component {
static get propTypes() {
return {
dispatch: PropTypes.func.isRequired,
parameters: PropTypes.array.isRequired,
serviceContainer: PropTypes.shape({
hudProxy: PropTypes.object.isRequired,
}),
id: PropTypes.string.isRequired,
tableData: PropTypes.object,
};
}
displayName: "ConsoleTable",
constructor(props) {
super(props);
this.getHeaders = this.getHeaders.bind(this);
this.getRows = this.getRows.bind(this);
}
propTypes: {
dispatch: PropTypes.func.isRequired,
parameters: PropTypes.array.isRequired,
serviceContainer: PropTypes.shape({
hudProxy: PropTypes.object.isRequired,
}),
id: PropTypes.string.isRequired,
tableData: PropTypes.object,
},
componentWillMount: function () {
componentWillMount() {
const {id, dispatch, serviceContainer, parameters} = this.props;
if (!Array.isArray(parameters) || parameters.length === 0) {
@ -44,15 +49,15 @@ const ConsoleTable = createClass({
// Get all the object properties.
dispatch(actions.messageTableDataGet(id, client, dataType));
},
}
getHeaders: function (columns) {
getHeaders(columns) {
let headerItems = [];
columns.forEach((value, key) => headerItems.push(dom.th({}, value)));
return headerItems;
},
}
getRows: function (columns, items) {
getRows(columns, items) {
const {
dispatch,
serviceContainer,
@ -76,9 +81,9 @@ const ConsoleTable = createClass({
});
return dom.tr({}, cells);
});
},
}
render: function () {
render() {
const {parameters, tableData} = this.props;
const headersGrip = parameters[1];
const headers = headersGrip && headersGrip.preview ? headersGrip.preview.items : null;
@ -101,7 +106,7 @@ const ConsoleTable = createClass({
)
);
}
});
}
function getParametersDataType(parameters = null) {
if (!Array.isArray(parameters) || parameters.length === 0) {

View File

@ -4,7 +4,7 @@
"use strict";
const {
createClass,
Component,
DOM: dom,
PropTypes
} = require("devtools/client/shared/vendor/react");
@ -23,20 +23,38 @@ const {
const FilterButton = require("devtools/client/webconsole/new-console-output/components/FilterButton");
const FilterCheckbox = require("devtools/client/webconsole/new-console-output/components/FilterCheckbox");
const FilterBar = createClass({
class FilterBar extends Component {
static get propTypes() {
return {
dispatch: PropTypes.func.isRequired,
filter: PropTypes.object.isRequired,
serviceContainer: PropTypes.shape({
attachRefToHud: PropTypes.func.isRequired,
}).isRequired,
filterBarVisible: PropTypes.bool.isRequired,
persistLogs: PropTypes.bool.isRequired,
filteredMessagesCount: PropTypes.object.isRequired,
};
}
displayName: "FilterBar",
constructor(props) {
super(props);
this.onClickMessagesClear = this.onClickMessagesClear.bind(this);
this.onClickFilterBarToggle = this.onClickFilterBarToggle.bind(this);
this.onClickRemoveAllFilters = this.onClickRemoveAllFilters.bind(this);
this.onClickRemoveTextFilter = this.onClickRemoveTextFilter.bind(this);
this.onSearchInput = this.onSearchInput.bind(this);
this.onChangePersistToggle = this.onChangePersistToggle.bind(this);
this.renderFiltersConfigBar = this.renderFiltersConfigBar.bind(this);
this.renderFilteredMessagesBar = this.renderFilteredMessagesBar.bind(this);
}
propTypes: {
dispatch: PropTypes.func.isRequired,
filter: PropTypes.object.isRequired,
serviceContainer: PropTypes.shape({
attachRefToHud: PropTypes.func.isRequired,
}).isRequired,
filterBarVisible: PropTypes.bool.isRequired,
persistLogs: PropTypes.bool.isRequired,
filteredMessagesCount: PropTypes.object.isRequired,
},
componentDidMount() {
this.props.serviceContainer.attachRefToHud(
"filterBox",
this.wrapperNode.querySelector(".text-filter")
);
}
shouldComponentUpdate(nextProps, nextState) {
if (nextProps.filter !== this.props.filter) {
@ -59,36 +77,31 @@ const FilterBar = createClass({
}
return false;
},
}
componentDidMount() {
this.props.serviceContainer.attachRefToHud("filterBox",
this.wrapperNode.querySelector(".text-filter"));
},
onClickMessagesClear: function () {
onClickMessagesClear() {
this.props.dispatch(actions.messagesClear());
},
}
onClickFilterBarToggle: function () {
onClickFilterBarToggle() {
this.props.dispatch(actions.filterBarToggle());
},
}
onClickRemoveAllFilters: function () {
onClickRemoveAllFilters() {
this.props.dispatch(actions.defaultFiltersReset());
},
}
onClickRemoveTextFilter: function () {
onClickRemoveTextFilter() {
this.props.dispatch(actions.filterTextSet(""));
},
}
onSearchInput: function (e) {
onSearchInput(e) {
this.props.dispatch(actions.filterTextSet(e.target.value));
},
}
onChangePersistToggle: function () {
onChangePersistToggle() {
this.props.dispatch(actions.persistToggle());
},
}
renderFiltersConfigBar() {
const {
@ -167,7 +180,7 @@ const FilterBar = createClass({
dispatch
}),
);
},
}
renderFilteredMessagesBar() {
const {
@ -201,7 +214,7 @@ const FilterBar = createClass({
onClick: this.onClickRemoveAllFilters
}, l10n.getStr("webconsole.resetFiltersButton.label"))
);
},
}
render() {
const {
@ -264,7 +277,7 @@ const FilterBar = createClass({
)
);
}
});
}
function mapStateToProps(state) {
let uiState = getAllUi(state);

View File

@ -8,7 +8,7 @@
// React & Redux
const {
createClass,
Component,
createFactory,
DOM: dom,
PropTypes
@ -23,51 +23,57 @@ const MessageRepeat = require("devtools/client/webconsole/new-console-output/com
const FrameView = createFactory(require("devtools/client/shared/components/Frame"));
const StackTrace = createFactory(require("devtools/client/shared/components/StackTrace"));
const Message = createClass({
displayName: "Message",
propTypes: {
open: PropTypes.bool,
collapsible: PropTypes.bool,
collapseTitle: PropTypes.string,
source: PropTypes.string.isRequired,
type: PropTypes.string.isRequired,
level: PropTypes.string.isRequired,
indent: PropTypes.number.isRequired,
topLevelClasses: PropTypes.array.isRequired,
messageBody: PropTypes.any.isRequired,
repeat: PropTypes.any,
frame: PropTypes.any,
attachment: PropTypes.any,
stacktrace: PropTypes.any,
messageId: PropTypes.string,
scrollToMessage: PropTypes.bool,
exceptionDocURL: PropTypes.string,
parameters: PropTypes.object,
request: PropTypes.object,
dispatch: PropTypes.func,
timeStamp: PropTypes.number,
timestampsVisible: PropTypes.bool.isRequired,
serviceContainer: PropTypes.shape({
emitNewMessage: PropTypes.func.isRequired,
onViewSourceInDebugger: PropTypes.func,
onViewSourceInScratchpad: PropTypes.func,
onViewSourceInStyleEditor: PropTypes.func,
openContextMenu: PropTypes.func.isRequired,
openLink: PropTypes.func.isRequired,
sourceMapService: PropTypes.any,
}),
notes: PropTypes.arrayOf(PropTypes.shape({
messageBody: PropTypes.string.isRequired,
class Message extends Component {
static get propTypes() {
return {
open: PropTypes.bool,
collapsible: PropTypes.bool,
collapseTitle: PropTypes.string,
source: PropTypes.string.isRequired,
type: PropTypes.string.isRequired,
level: PropTypes.string.isRequired,
indent: PropTypes.number.isRequired,
topLevelClasses: PropTypes.array.isRequired,
messageBody: PropTypes.any.isRequired,
repeat: PropTypes.any,
frame: PropTypes.any,
})),
},
attachment: PropTypes.any,
stacktrace: PropTypes.any,
messageId: PropTypes.string,
scrollToMessage: PropTypes.bool,
exceptionDocURL: PropTypes.string,
parameters: PropTypes.object,
request: PropTypes.object,
dispatch: PropTypes.func,
timeStamp: PropTypes.number,
timestampsVisible: PropTypes.bool.isRequired,
serviceContainer: PropTypes.shape({
emitNewMessage: PropTypes.func.isRequired,
onViewSourceInDebugger: PropTypes.func,
onViewSourceInScratchpad: PropTypes.func,
onViewSourceInStyleEditor: PropTypes.func,
openContextMenu: PropTypes.func.isRequired,
openLink: PropTypes.func.isRequired,
sourceMapService: PropTypes.any,
}),
notes: PropTypes.arrayOf(PropTypes.shape({
messageBody: PropTypes.string.isRequired,
frame: PropTypes.any,
})),
};
}
getDefaultProps: function () {
static get defaultProps() {
return {
indent: 0
};
},
}
constructor(props) {
super(props);
this.onLearnMoreClick = this.onLearnMoreClick.bind(this);
this.onContextMenu = this.onContextMenu.bind(this);
}
componentDidMount() {
if (this.messageNode) {
@ -81,12 +87,12 @@ const Message = createClass({
this.messageNode, this.props.messageId, this.props.timeStamp);
}
}
},
}
onLearnMoreClick: function () {
onLearnMoreClick() {
let {exceptionDocURL} = this.props;
this.props.serviceContainer.openLink(exceptionDocURL);
},
}
onContextMenu(e) {
let { serviceContainer, source, request, messageId } = this.props;
@ -98,7 +104,7 @@ const Message = createClass({
serviceContainer.openContextMenu(e, messageInfo);
e.stopPropagation();
e.preventDefault();
},
}
render() {
const {
@ -261,6 +267,6 @@ const Message = createClass({
)
);
}
});
}
module.exports = Message;

Some files were not shown because too many files have changed in this diff Show More