mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-07 18:04:46 +00:00
Merge m-c to inbound, a=merge
This commit is contained in:
commit
c84ec3b3f3
@ -419,11 +419,11 @@
|
||||
// display debug information about the cert error.
|
||||
var errorCode = document.getElementById("errorCode");
|
||||
if (errorCode) {
|
||||
errorCode.href = "#technicalInformation";
|
||||
errorCode.href = "javascript:void(0)";
|
||||
errorCode.addEventListener("click", () => {
|
||||
var div = document.getElementById("certificateErrorDebugInformation");
|
||||
if (toggleDisplay(div) == "block") {
|
||||
div.scrollIntoView({block: "start", behavior: "smooth"});
|
||||
let debugInfo = document.getElementById("certificateErrorDebugInformation");
|
||||
if (toggleDisplay(debugInfo) == "block") {
|
||||
debugInfo.scrollIntoView({block: "start", behavior: "smooth"});
|
||||
}
|
||||
}, false);
|
||||
}
|
||||
@ -646,7 +646,6 @@
|
||||
</div>
|
||||
|
||||
<div id="certificateErrorDebugInformation">
|
||||
<a name="technicalInformation"></a>
|
||||
<button id="copyToClipboard">&certerror.copyToClipboard.label;</button>
|
||||
<div id="certificateErrorText"/>
|
||||
<button id="copyToClipboard">&certerror.copyToClipboard.label;</button>
|
||||
|
@ -6798,7 +6798,6 @@ var gIdentityHandler = {
|
||||
|
||||
if (this._identityPopup.state == "open") {
|
||||
this.updateSitePermissions();
|
||||
this._identityPopupMultiView.setHeightToFit();
|
||||
}
|
||||
},
|
||||
|
||||
@ -7317,7 +7316,6 @@ var gIdentityHandler = {
|
||||
button.setAttribute("class", "identity-popup-permission-remove-button");
|
||||
button.addEventListener("command", () => {
|
||||
this._permissionList.removeChild(container);
|
||||
this._identityPopupMultiView.setHeightToFit();
|
||||
if (aPermission.inUse &&
|
||||
["camera", "microphone", "screen"].includes(aPermission.id)) {
|
||||
let windowId = this._sharingState.windowId;
|
||||
|
@ -16,7 +16,7 @@
|
||||
|
||||
<panelmultiview id="identity-popup-multiView"
|
||||
mainViewId="identity-popup-mainView">
|
||||
<panelview id="identity-popup-mainView" flex="1">
|
||||
<panelview id="identity-popup-mainView">
|
||||
|
||||
<!-- Security Section -->
|
||||
<hbox id="identity-popup-security" class="identity-popup-section">
|
||||
|
@ -318,7 +318,7 @@
|
||||
break;
|
||||
case "popuphidden":
|
||||
this.removeAttribute("panelopen");
|
||||
this._mainView.style.removeProperty("height");
|
||||
this._mainView.style.removeProperty("max-height");
|
||||
this.showMainView();
|
||||
this._mainViewObserver.disconnect();
|
||||
break;
|
||||
@ -346,7 +346,7 @@
|
||||
// Ignore the mutation that'll fire when we set the height of
|
||||
// the main view.
|
||||
this.ignoreMutations = true;
|
||||
this._mainView.style.height =
|
||||
this._mainView.style.maxHeight =
|
||||
this.getBoundingClientRect().height + "px";
|
||||
this.ignoreMutations = false;
|
||||
]]></body>
|
||||
|
@ -809,11 +809,11 @@ extensions.registerSchemaAPI("tabs", (extension, context) => {
|
||||
},
|
||||
|
||||
insertCSS: function(tabId, details) {
|
||||
return self.tabs._execute(tabId, details, "css", "insertCSS");
|
||||
return self.tabs._execute(tabId, details, "css", "insertCSS").then(() => {});
|
||||
},
|
||||
|
||||
removeCSS: function(tabId, details) {
|
||||
return self.tabs._execute(tabId, details, "css", "removeCSS");
|
||||
return self.tabs._execute(tabId, details, "css", "removeCSS").then(() => {});
|
||||
},
|
||||
|
||||
connect: function(tabId, connectInfo) {
|
||||
|
@ -70,9 +70,14 @@ add_task(function* testDefaultDetails() {
|
||||
"/foo/bar.png",
|
||||
{"19": "foo/bar.png"},
|
||||
{"38": "foo/bar.png"},
|
||||
{"19": "foo/bar.png", "38": "baz/quux.png"},
|
||||
];
|
||||
|
||||
if (window.devicePixelRatio > 1) {
|
||||
icons.push({"19": "baz/quux.png", "38": "foo/bar.png"});
|
||||
} else {
|
||||
icons.push({"19": "foo/bar.png", "38": "baz/quux@2x.png"});
|
||||
}
|
||||
|
||||
let expectedURL = new RegExp(String.raw`^moz-extension://[^/]+/foo/bar\.png$`);
|
||||
|
||||
for (let icon of icons) {
|
||||
@ -95,6 +100,7 @@ add_task(function* testDefaultDetails() {
|
||||
files: {
|
||||
"foo/bar.png": imageBuffer,
|
||||
"baz/quux.png": imageBuffer,
|
||||
"baz/quux@2x.png": imageBuffer,
|
||||
},
|
||||
});
|
||||
|
||||
|
@ -21,7 +21,8 @@ add_task(function* testExecuteScript() {
|
||||
browser.tabs.executeScript({
|
||||
code: "42",
|
||||
}).then(result => {
|
||||
browser.test.assertEq(42, result, "Expected callback result");
|
||||
browser.test.assertEq(1, result.length, "Expected one callback result");
|
||||
browser.test.assertEq(42, result[0], "Expected callback result");
|
||||
}),
|
||||
|
||||
browser.tabs.executeScript({
|
||||
@ -37,13 +38,15 @@ add_task(function* testExecuteScript() {
|
||||
browser.tabs.executeScript({
|
||||
file: "script.js",
|
||||
}).then(result => {
|
||||
browser.test.assertEq(undefined, result, "Expected callback result");
|
||||
browser.test.assertEq(1, result.length, "Expected one callback result");
|
||||
browser.test.assertEq(undefined, result[0], "Expected callback result");
|
||||
}),
|
||||
|
||||
browser.tabs.executeScript({
|
||||
file: "script2.js",
|
||||
}).then(result => {
|
||||
browser.test.assertEq(27, result, "Expected callback result");
|
||||
browser.test.assertEq(1, result.length, "Expected one callback result");
|
||||
browser.test.assertEq(27, result[0], "Expected callback result");
|
||||
}),
|
||||
|
||||
browser.tabs.executeScript({
|
||||
@ -62,9 +65,10 @@ add_task(function* testExecuteScript() {
|
||||
code: "location.href;",
|
||||
runAt: "document_end",
|
||||
}).then(result => {
|
||||
browser.test.assertTrue(typeof(result) == "string", "Result is a string");
|
||||
browser.test.assertEq(1, result.length, "Expected callback result");
|
||||
browser.test.assertEq("string", typeof result[0], "Result is a string");
|
||||
|
||||
browser.test.assertTrue(/\/file_iframe_document\.html$/.test(result), "Result is correct");
|
||||
browser.test.assertTrue(/\/file_iframe_document\.html$/.test(result[0]), "Result is correct");
|
||||
}),
|
||||
|
||||
browser.tabs.executeScript({
|
||||
@ -118,7 +122,7 @@ add_task(function* testExecuteScript() {
|
||||
browser.tabs.executeScript({
|
||||
code: "Promise.resolve(42)",
|
||||
}).then(result => {
|
||||
browser.test.assertEq(42, result, "Got expected promise resolution value as result");
|
||||
browser.test.assertEq(42, result[0], "Got expected promise resolution value as result");
|
||||
}),
|
||||
|
||||
browser.tabs.executeScript({
|
||||
@ -138,19 +142,21 @@ add_task(function* testExecuteScript() {
|
||||
code: "location.href;",
|
||||
frameId: frames[0].frameId,
|
||||
}).then(result => {
|
||||
browser.test.assertTrue(/\/file_iframe_document\.html$/.test(result), `Result for frameId[0] is correct: ${result}`);
|
||||
browser.test.assertEq(1, result.length, "Expected one result");
|
||||
browser.test.assertTrue(/\/file_iframe_document\.html$/.test(result[0]), `Result for frameId[0] is correct: ${result[0]}`);
|
||||
}),
|
||||
|
||||
browser.tabs.executeScript({
|
||||
code: "location.href;",
|
||||
frameId: frames[1].frameId,
|
||||
}).then(result => {
|
||||
browser.test.assertEq("http://mochi.test:8888/", result, "Result for frameId[1] is correct");
|
||||
browser.test.assertEq(1, result.length, "Expected one result");
|
||||
browser.test.assertEq("http://mochi.test:8888/", result[0], "Result for frameId[1] is correct");
|
||||
}),
|
||||
|
||||
browser.tabs.create({url: "http://example.com/"}).then(tab => {
|
||||
return browser.tabs.executeScript(tab.id, {code: "location.href"}).then(result => {
|
||||
browser.test.assertEq("http://example.com/", result, "Script executed correctly in new tab");
|
||||
browser.test.assertEq("http://example.com/", result[0], "Script executed correctly in new tab");
|
||||
|
||||
return browser.tabs.remove(tab.id);
|
||||
});
|
||||
|
@ -49,7 +49,7 @@ add_task(function* testExecuteScript() {
|
||||
return browser.tabs.executeScript({
|
||||
code: `(${checkCSS})()`,
|
||||
});
|
||||
}).then(result => {
|
||||
}).then(([result]) => {
|
||||
browser.test.assertEq(background, result[0], "Expected background color");
|
||||
browser.test.assertEq(foreground, result[1], "Expected foreground color");
|
||||
return next();
|
||||
|
@ -33,14 +33,14 @@ add_task(function* () {
|
||||
return awaitLoad(tabId);
|
||||
}).then(() => {
|
||||
return browser.tabs.executeScript(tabId, {code: "document.body.textContent"});
|
||||
}).then(textContent => {
|
||||
}).then(([textContent]) => {
|
||||
browser.test.assertEq("", textContent, "`textContent` should be empty when bypassCache=false");
|
||||
return browser.tabs.reload(tabId, {bypassCache: true});
|
||||
}).then(() => {
|
||||
return awaitLoad(tabId);
|
||||
}).then(() => {
|
||||
return browser.tabs.executeScript(tabId, {code: "document.body.textContent"});
|
||||
}).then(textContent => {
|
||||
}).then(([textContent]) => {
|
||||
let [pragma, cacheControl] = textContent.split(":");
|
||||
browser.test.assertEq("no-cache", pragma, "`pragma` should be set to `no-cache` when bypassCache is true");
|
||||
browser.test.assertEq("no-cache", cacheControl, "`cacheControl` should be set to `no-cache` when bypassCache is true");
|
||||
|
@ -66,7 +66,7 @@ add_task(function* testExecuteScript() {
|
||||
return browser.tabs.executeScript({
|
||||
code: `(${checkCSS})()`,
|
||||
});
|
||||
}).then(result => {
|
||||
}).then(([result]) => {
|
||||
browser.test.assertEq(background, result[0], "Expected background color");
|
||||
browser.test.assertEq(foreground, result[1], "Expected foreground color");
|
||||
return next();
|
||||
|
@ -188,17 +188,12 @@ add_task(function* back_navigation_on_browser_tab_should_close_dialog() {
|
||||
});
|
||||
|
||||
add_task(function* escape_should_close_dialog() {
|
||||
todo(false, "BrowserTestUtils.sendChar('VK_ESCAPE') triggers " +
|
||||
"'can't access dead object' on `navigator` in this test. " +
|
||||
"See bug 1238065.")
|
||||
return;
|
||||
|
||||
yield open_subdialog_and_test_generic_start_state(tab.linkedBrowser);
|
||||
|
||||
info("canceling the dialog");
|
||||
yield close_subdialog_and_test_generic_end_state(tab.linkedBrowser,
|
||||
function() { return BrowserTestUtils.sendChar("VK_ESCAPE", tab.linkedBrowser); },
|
||||
null, undefined, {runClosingFnOutsideOfContentTask: true});
|
||||
function() { return BrowserTestUtils.synthesizeKey("VK_ESCAPE", {}, tab.linkedBrowser); },
|
||||
"cancel", 0, {runClosingFnOutsideOfContentTask: true});
|
||||
});
|
||||
|
||||
add_task(function* correct_width_and_height_should_be_used_for_dialog() {
|
||||
|
@ -126,7 +126,7 @@
|
||||
border: 1px solid rgb(192,192,192);
|
||||
border-radius: 3px;
|
||||
margin: 5px;
|
||||
padding: 2px 12px;
|
||||
padding: 2px 10px;
|
||||
background-color: rgb(251,251,251);
|
||||
color: rgb(71,71,71);
|
||||
box-shadow: 0 1px rgba(255, 255, 255, 0.5),
|
||||
@ -134,6 +134,25 @@
|
||||
-moz-appearance: none;
|
||||
}
|
||||
|
||||
.customizationmode-button > .box-inherit {
|
||||
border-width: 0;
|
||||
padding-inline-start: 0;
|
||||
padding-inline-end: 0;
|
||||
}
|
||||
|
||||
.customizationmode-button > .button-icon {
|
||||
margin-inline-start: 0;
|
||||
}
|
||||
|
||||
.customizationmode-button:not([type=menu]) > .button-text {
|
||||
margin-inline-end: 0;
|
||||
}
|
||||
|
||||
.customizationmode-button > .button-menu-dropmarker {
|
||||
margin-inline-end: 0;
|
||||
padding-inline-end: 0;
|
||||
}
|
||||
|
||||
#customization-titlebar-visibility-button[checked],
|
||||
#customization-devedition-theme-button[checked] {
|
||||
background-color: rgb(218, 218, 218);
|
||||
@ -157,11 +176,6 @@
|
||||
-moz-image-region: rect(0, 24px, 24px, 0);
|
||||
}
|
||||
|
||||
#customization-lwtheme-button,
|
||||
#customization-titlebar-visibility-button {
|
||||
padding: 2px 7px;
|
||||
}
|
||||
|
||||
#customization-lwtheme-button > .box-inherit > .box-inherit > .button-text,
|
||||
#customization-titlebar-visibility-button > .button-box > .button-text {
|
||||
/* Sadly, button.css thinks its margins are perfect for everyone. */
|
||||
|
@ -155,6 +155,7 @@ def old_configure_options(*options):
|
||||
|
||||
@old_configure_options(
|
||||
'--cache-file',
|
||||
'--datadir',
|
||||
'--enable-accessibility',
|
||||
'--enable-address-sanitizer',
|
||||
'--enable-alsa',
|
||||
@ -249,6 +250,8 @@ def old_configure_options(*options):
|
||||
'--enable-webrtc',
|
||||
'--enable-xul',
|
||||
'--enable-zipwriter',
|
||||
'--includedir',
|
||||
'--libdir',
|
||||
'--no-create',
|
||||
'--prefix',
|
||||
'--with-android-cxx-stl',
|
||||
|
@ -62,6 +62,32 @@ def normsep(path):
|
||||
return mozpath.normsep(path)
|
||||
|
||||
|
||||
@imports('ctypes')
|
||||
@imports(_from='ctypes', _import='wintypes')
|
||||
@imports(_from='mozbuild.configure.constants', _import='WindowsBinaryType')
|
||||
def windows_binary_type(path):
|
||||
"""Obtain the type of a binary on Windows.
|
||||
|
||||
Returns WindowsBinaryType constant.
|
||||
"""
|
||||
GetBinaryTypeW = ctypes.windll.kernel32.GetBinaryTypeW
|
||||
GetBinaryTypeW.argtypes = [wintypes.LPWSTR, wintypes.POINTER(wintypes.DWORD)]
|
||||
GetBinaryTypeW.restype = wintypes.BOOL
|
||||
|
||||
bin_type = wintypes.DWORD()
|
||||
res = GetBinaryTypeW(path, ctypes.byref(bin_type))
|
||||
if not res:
|
||||
die('could not obtain binary type of %s' % path)
|
||||
|
||||
if bin_type.value == 0:
|
||||
return WindowsBinaryType('win32')
|
||||
elif bin_type.value == 6:
|
||||
return WindowsBinaryType('win64')
|
||||
# If we see another binary type, something is likely horribly wrong.
|
||||
else:
|
||||
die('unsupported binary type on %s: %s' % (path, bin_type))
|
||||
|
||||
|
||||
@imports('ctypes')
|
||||
@imports(_from='ctypes', _import='wintypes')
|
||||
def get_GetShortPathNameW():
|
||||
|
@ -119,6 +119,7 @@ support-files =
|
||||
doc_terminate-on-tab-close.html
|
||||
doc_watch-expressions.html
|
||||
doc_watch-expression-button.html
|
||||
doc_whitespace-property-names.html
|
||||
doc_with-frame.html
|
||||
doc_worker-source-map.html
|
||||
doc_WorkerActor.attach-tab1.html
|
||||
@ -521,6 +522,8 @@ skip-if = e10s && debug
|
||||
skip-if = e10s && debug
|
||||
[browser_dbg_variables-view-07.js]
|
||||
skip-if = e10s && debug
|
||||
[browser_dbg_variables-view-08.js]
|
||||
skip-if = e10s && debug
|
||||
[browser_dbg_variables-view-accessibility.js]
|
||||
subsuite = clipboard
|
||||
skip-if = e10s && debug
|
||||
|
@ -121,7 +121,5 @@ var test = Task.async(function* () {
|
||||
}
|
||||
}
|
||||
|
||||
debugger;
|
||||
|
||||
resumeDebuggerThenCloseAndFinish(panel);
|
||||
});
|
||||
|
@ -28,9 +28,11 @@ var test = Task.async(function* () {
|
||||
ok(scope, "Should get the current function's scope.");
|
||||
|
||||
let proxy;
|
||||
[...scope].forEach(function([name, value]) {
|
||||
if(name === "proxy") proxy = value;
|
||||
});
|
||||
for (let [name, value] of scope) {
|
||||
if (name === "proxy") {
|
||||
proxy = value;
|
||||
}
|
||||
}
|
||||
ok(proxy, "Should have found the proxy variable");
|
||||
|
||||
info("Expanding variable 'proxy'");
|
||||
@ -52,16 +54,16 @@ var test = Task.async(function* () {
|
||||
}
|
||||
} else {
|
||||
is(property, "<handler>", "There shouldn't be properties other than <target> and <handler>");
|
||||
for(let [subprop, subdata] of data) if(subprop === "name") {
|
||||
is(subdata.value, "handler", "The value of '<handler>' should be the [[ProxyHandler]]");
|
||||
foundHandler = true;
|
||||
for (let [subprop, subdata] of data) {
|
||||
if(subprop === "name") {
|
||||
is(subdata.value, "handler", "The value of '<handler>' should be the [[ProxyHandler]]");
|
||||
foundHandler = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ok(foundTarget, "Should have found the '<target>' property containing the [[ProxyTarget]]");
|
||||
ok(foundHandler, "Should have found the '<handler>' property containing the [[ProxyHandler]]");
|
||||
|
||||
debugger;
|
||||
|
||||
resumeDebuggerThenCloseAndFinish(panel);
|
||||
});
|
||||
|
@ -0,0 +1,61 @@
|
||||
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Test that property values are not missing when the property names only contain whitespace.
|
||||
*/
|
||||
|
||||
const TAB_URL = EXAMPLE_URL + "doc_whitespace-property-names.html";
|
||||
|
||||
var test = Task.async(function* () {
|
||||
let options = {
|
||||
source: TAB_URL,
|
||||
line: 1
|
||||
};
|
||||
var dbg = initDebugger(TAB_URL, options);
|
||||
const [tab,, panel] = yield dbg;
|
||||
const debuggerLineNumber = 24;
|
||||
const scopes = waitForCaretAndScopes(panel, debuggerLineNumber);
|
||||
callInTab(tab, "doPause");
|
||||
yield scopes;
|
||||
|
||||
const variables = panel.panelWin.DebuggerView.Variables;
|
||||
ok(variables, "Should get the variables view.");
|
||||
|
||||
const scope = [...variables][0];
|
||||
ok(scope, "Should get the current function's scope.");
|
||||
|
||||
let obj;
|
||||
for (let [name, value] of scope) {
|
||||
if (name === "obj") {
|
||||
obj = value;
|
||||
}
|
||||
}
|
||||
ok(obj, "Should have found the 'obj' variable");
|
||||
|
||||
info("Expanding variable 'obj'");
|
||||
let expanded = once(variables, "fetched");
|
||||
obj.expand();
|
||||
yield expanded;
|
||||
|
||||
let values = [" ", "\r", "\n", "\t", "\f", "\uFEFF", "\xA0"];
|
||||
let count = values.length;
|
||||
|
||||
for (let [property, value] of obj) {
|
||||
let index = values.indexOf(property);
|
||||
if (index >= 0) {
|
||||
--count;
|
||||
is(value._nameString, property,
|
||||
"The _nameString is different than the property name");
|
||||
is(value._valueString, index + "",
|
||||
"The _valueString is different than the stringified value");
|
||||
is(value._valueLabel.getAttribute("value"), index + "",
|
||||
"The _valueLabel value is different than the stringified value");
|
||||
}
|
||||
}
|
||||
is(count, 0, "There are " + count + " missing properties");
|
||||
|
||||
resumeDebuggerThenCloseAndFinish(panel);
|
||||
});
|
@ -0,0 +1,29 @@
|
||||
<!-- Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ -->
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<title>Debugger + Whitespace property name test page</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<script>
|
||||
window.obj = {
|
||||
" ": 0,
|
||||
"\r": 1,
|
||||
"\n": 2,
|
||||
"\t": 3,
|
||||
"\f": 4,
|
||||
"\uFEFF": 5,
|
||||
"\xA0": 6
|
||||
};
|
||||
window.doPause = function () {
|
||||
var obj = window.obj;
|
||||
debugger;
|
||||
};
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
@ -23,6 +23,9 @@ const SCROLL_REPEAT_MS = 100;
|
||||
const EventEmitter = require("devtools/shared/event-emitter");
|
||||
const {KeyShortcuts} = require("devtools/client/shared/key-shortcuts");
|
||||
|
||||
// Some margin may be required for visible element detection.
|
||||
const SCROLL_MARGIN = 1;
|
||||
|
||||
/**
|
||||
* Component to replicate functionality of XUL arrowscrollbox
|
||||
* for breadcrumbs
|
||||
@ -40,6 +43,9 @@ function ArrowScrollBox(win, container) {
|
||||
|
||||
ArrowScrollBox.prototype = {
|
||||
|
||||
// Scroll behavior, exposed for testing
|
||||
scrollBehavior: "smooth",
|
||||
|
||||
/**
|
||||
* Build the HTML, add to the DOM and start listening to
|
||||
* events
|
||||
@ -68,10 +74,26 @@ ArrowScrollBox.prototype = {
|
||||
this.inner.addEventListener("overflow", this.onOverflow, false);
|
||||
},
|
||||
|
||||
/**
|
||||
* Determine whether the current text directionality is RTL
|
||||
*/
|
||||
isRtl: function () {
|
||||
return this.win.getComputedStyle(this.container).direction === "rtl";
|
||||
},
|
||||
|
||||
/**
|
||||
* Scroll to the specified element using the current scroll behavior
|
||||
* @param {Element} element element to scroll
|
||||
* @param {String} block desired alignment of element after scrolling
|
||||
*/
|
||||
scrollToElement: function (element, block) {
|
||||
element.scrollIntoView({ block: block, behavior: this.scrollBehavior });
|
||||
},
|
||||
|
||||
/**
|
||||
* Call the given function once; then continuously
|
||||
* while the mouse button is held
|
||||
* @param {repeatFn} the function to repeat while the button is held
|
||||
* @param {Function} repeatFn the function to repeat while the button is held
|
||||
*/
|
||||
clickOrHold: function (repeatFn) {
|
||||
let timer;
|
||||
@ -109,7 +131,7 @@ ArrowScrollBox.prototype = {
|
||||
}
|
||||
|
||||
let element = this.inner.childNodes[0];
|
||||
element.scrollIntoView({ block: "start", behavior: "smooth" });
|
||||
this.scrollToElement(element, "start");
|
||||
},
|
||||
|
||||
/**
|
||||
@ -122,7 +144,7 @@ ArrowScrollBox.prototype = {
|
||||
}
|
||||
|
||||
let element = children[children.length - 1];
|
||||
element.scrollIntoView({ block: "start", behavior: "smooth" });
|
||||
this.scrollToElement(element, "start");
|
||||
},
|
||||
|
||||
/**
|
||||
@ -135,7 +157,8 @@ ArrowScrollBox.prototype = {
|
||||
return;
|
||||
}
|
||||
|
||||
element.scrollIntoView({ block: "start", behavior: "smooth" });
|
||||
let block = this.isRtl() ? "end" : "start";
|
||||
this.scrollToElement(element, block);
|
||||
};
|
||||
|
||||
this.clickOrHold(scrollToStart);
|
||||
@ -151,7 +174,8 @@ ArrowScrollBox.prototype = {
|
||||
return;
|
||||
}
|
||||
|
||||
element.scrollIntoView({ block: "end", behavior: "smooth" });
|
||||
let block = this.isRtl() ? "start" : "end";
|
||||
this.scrollToElement(element, block);
|
||||
};
|
||||
|
||||
this.clickOrHold(scrollToEnd);
|
||||
@ -195,47 +219,73 @@ ArrowScrollBox.prototype = {
|
||||
this.emit("overflow");
|
||||
},
|
||||
|
||||
/**
|
||||
* Check whether the element is to the left of its container but does
|
||||
* not also span the entire container.
|
||||
* @param {Number} left the left scroll point of the container
|
||||
* @param {Number} right the right edge of the container
|
||||
* @param {Number} elementLeft the left edge of the element
|
||||
* @param {Number} elementRight the right edge of the element
|
||||
*/
|
||||
elementLeftOfContainer: function (left, right, elementLeft, elementRight) {
|
||||
return elementLeft < (left - SCROLL_MARGIN)
|
||||
&& elementRight < (right - SCROLL_MARGIN);
|
||||
},
|
||||
|
||||
/**
|
||||
* Check whether the element is to the right of its container but does
|
||||
* not also span the entire container.
|
||||
* @param {Number} left the left scroll point of the container
|
||||
* @param {Number} right the right edge of the container
|
||||
* @param {Number} elementLeft the left edge of the element
|
||||
* @param {Number} elementRight the right edge of the element
|
||||
*/
|
||||
elementRightOfContainer: function (left, right, elementLeft, elementRight) {
|
||||
return elementLeft > (left + SCROLL_MARGIN)
|
||||
&& elementRight > (right + SCROLL_MARGIN);
|
||||
},
|
||||
|
||||
/**
|
||||
* Get the first (i.e. furthest left for LTR)
|
||||
* non visible element in the scroll box
|
||||
* non or partly visible element in the scroll box
|
||||
*/
|
||||
getFirstInvisibleElement: function () {
|
||||
let start = this.inner.scrollLeft;
|
||||
let end = this.inner.scrollLeft + this.inner.clientWidth;
|
||||
let crumbs = this.inner.childNodes;
|
||||
for (let i = crumbs.length - 1; i > -1; i--) {
|
||||
let element = crumbs[i];
|
||||
let elementRight = element.offsetLeft + element.offsetWidth;
|
||||
if (element.offsetLeft < start) {
|
||||
// edge case, check the element isn't already visible
|
||||
if (elementRight >= end) {
|
||||
continue;
|
||||
}
|
||||
return element;
|
||||
}
|
||||
}
|
||||
let elementsList = Array.from(this.inner.childNodes).reverse();
|
||||
|
||||
return null;
|
||||
let predicate = this.isRtl() ?
|
||||
this.elementRightOfContainer : this.elementLeftOfContainer;
|
||||
return this.findFirstWithBounds(elementsList, predicate);
|
||||
},
|
||||
|
||||
/**
|
||||
* Get the last (i.e. furthest right for LTR)
|
||||
* non-visible element in the scroll box
|
||||
* non or partly visible element in the scroll box
|
||||
*/
|
||||
getLastInvisibleElement: function () {
|
||||
let end = this.inner.scrollLeft + this.inner.clientWidth;
|
||||
let elementStart = 0;
|
||||
for (let element of this.inner.childNodes) {
|
||||
let elementEnd = elementStart + element.offsetWidth;
|
||||
if (elementEnd > end) {
|
||||
// Edge case: check the element isn't bigger than the
|
||||
// container and thus already in view
|
||||
if (elementStart > this.inner.scrollLeft) {
|
||||
return element;
|
||||
}
|
||||
}
|
||||
let predicate = this.isRtl() ?
|
||||
this.elementLeftOfContainer : this.elementRightOfContainer;
|
||||
return this.findFirstWithBounds(this.inner.childNodes, predicate);
|
||||
},
|
||||
|
||||
elementStart = elementEnd;
|
||||
/**
|
||||
* Find the first element that matches the given predicate, called with bounds
|
||||
* information
|
||||
* @param {Array} elements an ordered list of elements
|
||||
* @param {Function} predicate a function to be called with bounds
|
||||
* information
|
||||
*/
|
||||
findFirstWithBounds: function (elements, predicate) {
|
||||
let left = this.inner.scrollLeft;
|
||||
let right = left + this.inner.clientWidth;
|
||||
for (let element of elements) {
|
||||
let elementLeft = element.offsetLeft - element.parentElement.offsetLeft;
|
||||
let elementRight = elementLeft + element.offsetWidth;
|
||||
|
||||
// Check that the starting edge of the element is out of the visible area
|
||||
// and that the ending edge does not span the whole container
|
||||
if (predicate(left, right, elementLeft, elementRight)) {
|
||||
return element;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
@ -725,7 +775,7 @@ HTMLBreadcrumbs.prototype = {
|
||||
// FIXME bug 684352: make sure its immediate neighbors are visible too.
|
||||
if (!this.isDestroyed) {
|
||||
let element = this.nodeHierarchy[this.currentIndex].button;
|
||||
element.scrollIntoView({ block: "end", behavior: "smooth" });
|
||||
this.arrowScrollBox.scrollToElement(element, "end");
|
||||
}
|
||||
},
|
||||
|
||||
@ -815,6 +865,7 @@ HTMLBreadcrumbs.prototype = {
|
||||
}
|
||||
|
||||
// If this was an interesting deletion; then trim the breadcrumb trail
|
||||
let trimmed = false;
|
||||
if (reason === "markupmutation") {
|
||||
for (let {type, removed} of mutations) {
|
||||
if (type !== "childList") {
|
||||
@ -825,6 +876,7 @@ HTMLBreadcrumbs.prototype = {
|
||||
let removedIndex = this.indexOf(node);
|
||||
if (removedIndex > -1) {
|
||||
this.cutAfter(removedIndex - 1);
|
||||
trimmed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -833,6 +885,10 @@ HTMLBreadcrumbs.prototype = {
|
||||
if (!this.selection.isElementNode()) {
|
||||
// no selection
|
||||
this.setCursor(-1);
|
||||
if (trimmed) {
|
||||
// Since something changed, notify the interested parties.
|
||||
this.inspector.emit("breadcrumbs-updated", this.selection.nodeFront);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -483,6 +483,9 @@ CssComputedView.prototype = {
|
||||
onItem: (propView) => {
|
||||
propView.refresh();
|
||||
},
|
||||
onCancel: () => {
|
||||
deferred.reject("_refreshProcess of computed view cancelled");
|
||||
},
|
||||
onDone: () => {
|
||||
this._refreshProcess = null;
|
||||
this.noResults.hidden = this.numVisibleProperties > 0;
|
||||
|
@ -182,17 +182,21 @@ InspectorPanel.prototype = {
|
||||
this._supportsScrollIntoView = false;
|
||||
this._supportsResolveRelativeURL = false;
|
||||
|
||||
return promise.all([
|
||||
this._target.actorHasMethod("domwalker", "duplicateNode").then(value => {
|
||||
this._supportsDuplicateNode = value;
|
||||
}).catch(e => console.error(e)),
|
||||
this._target.actorHasMethod("domnode", "scrollIntoView").then(value => {
|
||||
this._supportsScrollIntoView = value;
|
||||
}).catch(e => console.error(e)),
|
||||
this._target.actorHasMethod("inspector", "resolveRelativeURL").then(value => {
|
||||
this._supportsResolveRelativeURL = value;
|
||||
}).catch(e => console.error(e)),
|
||||
]);
|
||||
// Use getActorDescription first so that all actorHasMethod calls use
|
||||
// a cached response from the server.
|
||||
return this._target.getActorDescription("domwalker").then(desc => {
|
||||
return promise.all([
|
||||
this._target.actorHasMethod("domwalker", "duplicateNode").then(value => {
|
||||
this._supportsDuplicateNode = value;
|
||||
}).catch(e => console.error(e)),
|
||||
this._target.actorHasMethod("domnode", "scrollIntoView").then(value => {
|
||||
this._supportsScrollIntoView = value;
|
||||
}).catch(e => console.error(e)),
|
||||
this._target.actorHasMethod("inspector", "resolveRelativeURL").then(value => {
|
||||
this._supportsResolveRelativeURL = value;
|
||||
}).catch(e => console.error(e)),
|
||||
]);
|
||||
});
|
||||
},
|
||||
|
||||
_deferredOpen: function (defaultSelection) {
|
||||
|
@ -132,6 +132,7 @@ InspectorSearch.prototype = {
|
||||
},
|
||||
|
||||
_onClearSearch: function () {
|
||||
this.searchBox.classList.remove("devtools-style-searchbox-no-match");
|
||||
this.searchBox.value = "";
|
||||
this.searchClearButton.hidden = true;
|
||||
}
|
||||
|
@ -23,9 +23,7 @@ support-files =
|
||||
[browser_layout_rotate-labels-on-sides.js]
|
||||
[browser_layout_sync.js]
|
||||
[browser_layout_tooltips.js]
|
||||
# [browser_layout_update-after-navigation.js]
|
||||
# Disabled for too many intermittent failures (bug 1288213)
|
||||
# [browser_layout_update-after-reload.js]
|
||||
# Disabled for too many intermittent failures (bug 1287745)
|
||||
[browser_layout_update-after-navigation.js]
|
||||
[browser_layout_update-after-reload.js]
|
||||
# [browser_layout_update-in-iframes.js]
|
||||
# Bug 1020038 layout-view updates for iframe elements changes
|
||||
|
@ -4,6 +4,7 @@ subsuite = devtools
|
||||
support-files =
|
||||
doc_inspector_add_node.html
|
||||
doc_inspector_breadcrumbs.html
|
||||
doc_inspector_breadcrumbs_visibility.html
|
||||
doc_inspector_delete-selected-node-01.html
|
||||
doc_inspector_delete-selected-node-02.html
|
||||
doc_inspector_embed.html
|
||||
@ -48,6 +49,7 @@ support-files =
|
||||
skip-if = os == "mac" # Full keyboard navigation on OSX only works if Full Keyboard Access setting is set to All Control in System Keyboard Preferences
|
||||
[browser_inspector_breadcrumbs_mutations.js]
|
||||
[browser_inspector_breadcrumbs_namespaced.js]
|
||||
[browser_inspector_breadcrumbs_visibility.js]
|
||||
[browser_inspector_delete-selected-node-01.js]
|
||||
[browser_inspector_delete-selected-node-02.js]
|
||||
[browser_inspector_delete-selected-node-03.js]
|
||||
|
@ -0,0 +1,106 @@
|
||||
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
"use strict";
|
||||
|
||||
// Test that the start and end buttons on the breadcrumb trail bring the right
|
||||
// crumbs into the visible area, for both LTR and RTL
|
||||
|
||||
let { Toolbox } = require("devtools/client/framework/toolbox");
|
||||
|
||||
const TEST_URI = URL_ROOT + "doc_inspector_breadcrumbs_visibility.html";
|
||||
const NODE_ONE = "div#aVeryLongIdToExceedTheBreadcrumbTruncationLimit";
|
||||
const NODE_TWO = "div#anotherVeryLongIdToExceedTheBreadcrumbTruncationLimit";
|
||||
const NODE_THREE = "div#aThirdVeryLongIdToExceedTheTruncationLimit";
|
||||
const NODE_FOUR = "div#aFourthOneToExceedTheTruncationLimit";
|
||||
const NODE_FIVE = "div#aFifthOneToExceedTheTruncationLimit";
|
||||
const NODE_SIX = "div#aSixthOneToExceedTheTruncationLimit";
|
||||
const NODE_SEVEN = "div#aSeventhOneToExceedTheTruncationLimit";
|
||||
|
||||
const NODES = [
|
||||
{ action: "start", title: NODE_SIX },
|
||||
{ action: "start", title: NODE_FIVE },
|
||||
{ action: "start", title: NODE_FOUR },
|
||||
{ action: "start", title: NODE_THREE },
|
||||
{ action: "start", title: NODE_TWO },
|
||||
{ action: "start", title: NODE_ONE },
|
||||
{ action: "end", title: NODE_TWO },
|
||||
{ action: "end", title: NODE_THREE },
|
||||
{ action: "end", title: NODE_FOUR },
|
||||
{ action: "end", title: NODE_FIVE },
|
||||
{ action: "end", title: NODE_SIX }
|
||||
];
|
||||
|
||||
add_task(function* () {
|
||||
let { inspector, toolbox } = yield openInspectorForURL(TEST_URI);
|
||||
|
||||
// No way to wait for scrolling to end (Bug 1172171)
|
||||
// Rather than wait a max time; limit test to instant scroll behavior
|
||||
inspector.breadcrumbs.arrowScrollBox.scrollBehavior = "instant";
|
||||
|
||||
yield toolbox.switchHost(Toolbox.HostType.WINDOW);
|
||||
let hostWindow = toolbox._host._window;
|
||||
let originalWidth = hostWindow.outerWidth;
|
||||
let originalHeight = hostWindow.outerHeight;
|
||||
hostWindow.resizeTo(640, 300);
|
||||
|
||||
info("Testing transitions ltr");
|
||||
yield pushPref("intl.uidirection.en-US", "ltr");
|
||||
yield testBreadcrumbTransitions(hostWindow, inspector);
|
||||
|
||||
info("Testing transitions rtl");
|
||||
yield pushPref("intl.uidirection.en-US", "rtl");
|
||||
yield testBreadcrumbTransitions(hostWindow, inspector);
|
||||
|
||||
hostWindow.resizeTo(originalWidth, originalHeight);
|
||||
});
|
||||
|
||||
function* testBreadcrumbTransitions(hostWindow, inspector) {
|
||||
let breadcrumbs = inspector.panelDoc.getElementById("inspector-breadcrumbs");
|
||||
let startBtn = breadcrumbs.querySelector(".scrollbutton-up");
|
||||
let endBtn = breadcrumbs.querySelector(".scrollbutton-down");
|
||||
let container = breadcrumbs.querySelector(".html-arrowscrollbox-inner");
|
||||
let breadcrumbsUpdated = inspector.once("breadcrumbs-updated");
|
||||
|
||||
info("Selecting initial node");
|
||||
yield selectNode(NODE_SEVEN, inspector);
|
||||
|
||||
// So just need to wait for a duration
|
||||
yield breadcrumbsUpdated;
|
||||
let initialCrumb = container.querySelector("button[checked]");
|
||||
is(isElementInViewport(hostWindow, initialCrumb), true,
|
||||
"initial element was visible");
|
||||
|
||||
for (let node of NODES) {
|
||||
info("Checking for visibility of crumb " + node.title);
|
||||
if (node.action === "end") {
|
||||
info("Simulating click of end button");
|
||||
EventUtils.synthesizeMouseAtCenter(endBtn, {}, inspector.panelWin);
|
||||
} else if (node.action === "start") {
|
||||
info("Simulating click of start button");
|
||||
EventUtils.synthesizeMouseAtCenter(startBtn, {}, inspector.panelWin);
|
||||
}
|
||||
|
||||
yield breadcrumbsUpdated;
|
||||
let selector = "button[title=\"" + node.title + "\"]";
|
||||
let relevantCrumb = container.querySelector(selector);
|
||||
is(isElementInViewport(hostWindow, relevantCrumb), true,
|
||||
node.title + " crumb is visible");
|
||||
}
|
||||
}
|
||||
|
||||
function isElementInViewport(window, el) {
|
||||
let rect = el.getBoundingClientRect();
|
||||
|
||||
return (
|
||||
rect.top >= 0 &&
|
||||
rect.left >= 0 &&
|
||||
rect.bottom <= window.innerHeight &&
|
||||
rect.right <= window.innerWidth
|
||||
);
|
||||
}
|
||||
|
||||
registerCleanupFunction(function () {
|
||||
// Restore the host type for other tests.
|
||||
Services.prefs.clearUserPref("devtools.toolbox.host");
|
||||
});
|
@ -93,6 +93,7 @@ add_task(function* () {
|
||||
|
||||
function* deleteNodeWithContextMenu(selector) {
|
||||
yield selectNode(selector, inspector);
|
||||
let nodeToBeDeleted = inspector.selection.nodeFront;
|
||||
|
||||
info("Getting the node container in the markup view.");
|
||||
let container = yield getContainerForSelector(selector, inspector);
|
||||
@ -111,6 +112,16 @@ add_task(function* () {
|
||||
|
||||
info("Waiting for inspector to update.");
|
||||
yield inspector.once("inspector-updated");
|
||||
|
||||
// Since the mutations are sent asynchronously from the server, the
|
||||
// inspector-updated event triggered by the deletion might happen before
|
||||
// the mutation is received and the element is removed from the
|
||||
// breadcrumbs. See bug 1284125.
|
||||
if (inspector.breadcrumbs.indexOf(nodeToBeDeleted) > -1) {
|
||||
info("Crumbs haven't seen deletion. Waiting for breadcrumbs-updated.");
|
||||
yield inspector.once("breadcrumbs-updated");
|
||||
}
|
||||
|
||||
return menuItem;
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,22 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="content-type" content="text/html; charset=windows-1252">
|
||||
</head>
|
||||
<body>
|
||||
<div id="aVeryLongIdToExceedTheBreadcrumbTruncationLimit">
|
||||
<div id="anotherVeryLongIdToExceedTheBreadcrumbTruncationLimit">
|
||||
<div id="aThirdVeryLongIdToExceedTheTruncationLimit">
|
||||
<div id="aFourthOneToExceedTheTruncationLimit">
|
||||
<div id="aFifthOneToExceedTheTruncationLimit">
|
||||
<div id="aSixthOneToExceedTheTruncationLimit">
|
||||
<div id="aSeventhOneToExceedTheTruncationLimit">
|
||||
A text node at the end
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
@ -165,6 +165,7 @@ HarBuilder.prototype = {
|
||||
request.httpVersion = file.httpVersion || "";
|
||||
|
||||
request.headers = this.buildHeaders(file.requestHeaders);
|
||||
request.headers = this.appendHeadersPostData(request.headers, file);
|
||||
request.cookies = this.buildCookies(file.requestCookies);
|
||||
|
||||
request.queryString = NetworkHelper.parseQueryString(
|
||||
@ -199,6 +200,33 @@ HarBuilder.prototype = {
|
||||
return this.buildNameValuePairs(input.headers);
|
||||
},
|
||||
|
||||
appendHeadersPostData: function (input = [], file) {
|
||||
if (!file.requestPostData) {
|
||||
return input;
|
||||
}
|
||||
|
||||
this.fetchData(file.requestPostData.postData.text).then(value => {
|
||||
let contentType = value.match(/Content-Type: ([^;\s]+)/);
|
||||
let contentLength = value.match(/Content-Length: (.+)/);
|
||||
|
||||
if (contentType && contentType.length > 1) {
|
||||
input.push({
|
||||
name: "Content-Type",
|
||||
value: contentType[1]
|
||||
});
|
||||
}
|
||||
|
||||
if (contentLength && contentLength.length > 1) {
|
||||
input.push({
|
||||
name: "Content-Length",
|
||||
value: contentLength[1]
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
return input;
|
||||
},
|
||||
|
||||
buildCookies: function (input) {
|
||||
if (!input) {
|
||||
return [];
|
||||
|
@ -12,8 +12,8 @@ const URL = EXAMPLE_URL.replace("http:", "https:");
|
||||
|
||||
const TEST_URL = URL + "service-workers/status-codes.html";
|
||||
|
||||
var test = Task.async(function* () {
|
||||
let [, debuggee, monitor] = yield initNetMonitor(TEST_URL, null, true);
|
||||
add_task(function* () {
|
||||
let [tab, , monitor] = yield initNetMonitor(TEST_URL, null, true);
|
||||
info("Starting test... ");
|
||||
|
||||
let { NetMonitorView } = monitor.panelWin;
|
||||
@ -35,11 +35,16 @@ var test = Task.async(function* () {
|
||||
];
|
||||
|
||||
info("Registering the service worker...");
|
||||
yield debuggee.registerServiceWorker();
|
||||
yield ContentTask.spawn(tab.linkedBrowser, {}, function* () {
|
||||
yield content.wrappedJSObject.registerServiceWorker();
|
||||
});
|
||||
|
||||
info("Performing requests...");
|
||||
debuggee.performRequests();
|
||||
yield waitForNetworkEvents(monitor, REQUEST_DATA.length);
|
||||
let wait = waitForNetworkEvents(monitor, REQUEST_DATA.length);
|
||||
yield ContentTask.spawn(tab.linkedBrowser, {}, function* () {
|
||||
content.wrappedJSObject.performRequests();
|
||||
});
|
||||
yield wait;
|
||||
|
||||
let index = 0;
|
||||
for (let request of REQUEST_DATA) {
|
||||
@ -64,8 +69,9 @@ var test = Task.async(function* () {
|
||||
}
|
||||
|
||||
info("Unregistering the service worker...");
|
||||
yield debuggee.unregisterServiceWorker();
|
||||
yield ContentTask.spawn(tab.linkedBrowser, {}, function* () {
|
||||
yield content.wrappedJSObject.unregisterServiceWorker();
|
||||
});
|
||||
|
||||
yield teardown(monitor);
|
||||
finish();
|
||||
});
|
||||
|
@ -37,24 +37,19 @@ define(function (require, exports, module) {
|
||||
|
||||
delim = (i == array.length - 1 ? "" : ", ");
|
||||
|
||||
if (value === array) {
|
||||
items.push(Reference({
|
||||
key: i,
|
||||
object: value,
|
||||
delim: delim
|
||||
}));
|
||||
} else {
|
||||
items.push(ItemRep({
|
||||
key: i,
|
||||
object: value,
|
||||
delim: delim
|
||||
}));
|
||||
}
|
||||
items.push(ItemRep({
|
||||
key: i,
|
||||
object: value,
|
||||
// Hardcode tiny mode to avoid recursive handling.
|
||||
mode: "tiny",
|
||||
delim: delim
|
||||
}));
|
||||
} catch (exc) {
|
||||
items.push(ItemRep({
|
||||
key: i,
|
||||
object: exc,
|
||||
delim: delim,
|
||||
key: i
|
||||
mode: "tiny",
|
||||
delim: delim
|
||||
}));
|
||||
}
|
||||
}
|
||||
@ -173,30 +168,16 @@ define(function (require, exports, module) {
|
||||
|
||||
let object = this.props.object;
|
||||
let delim = this.props.delim;
|
||||
let mode = this.props.mode;
|
||||
return (
|
||||
DOM.span({},
|
||||
Rep({object: object}),
|
||||
Rep({object: object, mode: mode}),
|
||||
delim
|
||||
)
|
||||
);
|
||||
}
|
||||
}));
|
||||
|
||||
/**
|
||||
* Renders cycle references in an array.
|
||||
*/
|
||||
let Reference = React.createFactory(React.createClass({
|
||||
displayName: "Reference",
|
||||
|
||||
render: function () {
|
||||
let tooltip = "Circular reference";
|
||||
return (
|
||||
DOM.span({title: tooltip},
|
||||
"[…]")
|
||||
);
|
||||
}
|
||||
}));
|
||||
|
||||
function supportsObject(object, type) {
|
||||
return Array.isArray(object) ||
|
||||
Object.prototype.toString.call(object) === "[object Arguments]";
|
||||
|
@ -11,10 +11,8 @@ define(function (require, exports, module) {
|
||||
const React = require("devtools/client/shared/vendor/react");
|
||||
|
||||
// Reps
|
||||
const { isGrip } = require("./rep-utils");
|
||||
|
||||
// Shortcuts
|
||||
const { span } = React.DOM;
|
||||
const { createFactories, isGrip } = require("./rep-utils");
|
||||
const { rep } = createFactories(require("./grip").Grip);
|
||||
|
||||
/**
|
||||
* Renders DOM event objects.
|
||||
@ -26,40 +24,18 @@ define(function (require, exports, module) {
|
||||
object: React.PropTypes.object.isRequired
|
||||
},
|
||||
|
||||
getTitle: function (grip) {
|
||||
if (this.props.objectLink) {
|
||||
return this.props.objectLink({
|
||||
object: grip
|
||||
}, grip.preview.type);
|
||||
}
|
||||
return grip.preview.type;
|
||||
},
|
||||
|
||||
summarizeEvent: function (grip) {
|
||||
let info = [];
|
||||
|
||||
let eventFamily = grip.class;
|
||||
let props = grip.preview.properties;
|
||||
|
||||
if (eventFamily == "MouseEvent") {
|
||||
info.push("clientX=", props.clientX, ", clientY=", props.clientY);
|
||||
} else if (eventFamily == "KeyboardEvent") {
|
||||
info.push("charCode=", props.charCode, ", keyCode=", props.keyCode);
|
||||
} else if (eventFamily == "MessageEvent") {
|
||||
info.push("origin=", props.origin, ", data=", props.data);
|
||||
}
|
||||
|
||||
return info.join("");
|
||||
},
|
||||
|
||||
render: function () {
|
||||
let grip = this.props.object;
|
||||
return (
|
||||
span({className: "objectBox objectBox-event"},
|
||||
this.getTitle(grip),
|
||||
this.summarizeEvent(grip)
|
||||
)
|
||||
);
|
||||
// Use `Object.assign` to keep `this.props` without changes becuase:
|
||||
// 1. JSON.stringify/JSON.parse is slow.
|
||||
// 2. Immutable.js is planned for the future.
|
||||
let props = Object.assign({}, this.props);
|
||||
props.object = Object.assign({}, this.props.object);
|
||||
props.object.preview = Object.assign({}, this.props.object.preview);
|
||||
props.object.preview.ownProperties = props.object.preview.properties;
|
||||
delete props.object.preview.properties;
|
||||
props.object.ownPropertyLength =
|
||||
Object.keys(props.object.preview.ownProperties).length;
|
||||
return rep(props);
|
||||
},
|
||||
});
|
||||
|
||||
|
@ -56,6 +56,10 @@ define(function (require, exports, module) {
|
||||
}
|
||||
|
||||
let delim;
|
||||
// number of grip.preview.items is limited to 10, but we may have more
|
||||
// items in grip-array
|
||||
let delimMax = grip.preview.length > array.length ?
|
||||
array.length : array.length - 1;
|
||||
let provider = this.props.provider;
|
||||
|
||||
for (let i = 0; i < array.length && i < max; i++) {
|
||||
@ -63,7 +67,7 @@ define(function (require, exports, module) {
|
||||
let itemGrip = array[i];
|
||||
let value = provider ? provider.getValue(itemGrip) : itemGrip;
|
||||
|
||||
delim = (i == array.length - 1 ? "" : ", ");
|
||||
delim = (i == delimMax ? "" : ", ");
|
||||
|
||||
if (value === array) {
|
||||
items.push(Reference({
|
||||
@ -86,14 +90,15 @@ define(function (require, exports, module) {
|
||||
)));
|
||||
}
|
||||
}
|
||||
|
||||
if (array.length > max) {
|
||||
if (array.length > max || grip.preview.length > array.length) {
|
||||
let objectLink = this.props.objectLink || span;
|
||||
let leftItemNum = grip.preview.length - max > 0 ?
|
||||
grip.preview.length - max : grip.preview.length - array.length;
|
||||
items.push(Caption({
|
||||
key: "more",
|
||||
object: objectLink({
|
||||
object: this.props.object
|
||||
}, (grip.preview.length - max) + " more…")
|
||||
}, leftItemNum + " more…")
|
||||
}));
|
||||
}
|
||||
|
||||
|
@ -110,7 +110,8 @@ define(function (require, exports, module) {
|
||||
|
||||
indexes.forEach((i) => {
|
||||
let name = Object.keys(ownProperties)[i];
|
||||
let value = ownProperties[name].value;
|
||||
let prop = ownProperties[name];
|
||||
let value = prop.value !== undefined ? prop.value : prop;
|
||||
props.push(PropRep(Object.assign({}, this.props, {
|
||||
key: name,
|
||||
mode: "tiny",
|
||||
@ -144,7 +145,7 @@ define(function (require, exports, module) {
|
||||
}
|
||||
|
||||
let prop = ownProperties[name];
|
||||
let value = prop.value;
|
||||
let value = prop.value !== undefined ? prop.value : prop;
|
||||
|
||||
// Type is specified in grip's "class" field and for primitive
|
||||
// values use typeof.
|
||||
|
@ -96,7 +96,8 @@ define(function (require, exports, module) {
|
||||
return props;
|
||||
}
|
||||
|
||||
let mode = this.props.mode;
|
||||
// Hardcode tiny mode to avoid recursive handling.
|
||||
let mode = "tiny";
|
||||
|
||||
try {
|
||||
for (let name in object) {
|
||||
|
@ -35,8 +35,11 @@ define(function (require, exports, module) {
|
||||
let croppedString = this.props.cropLimit ?
|
||||
cropMultipleLines(text, this.props.cropLimit) : cropMultipleLines(text);
|
||||
|
||||
let formattedString = this.props.omitQuotes ?
|
||||
croppedString : "\"" + croppedString + "\"";
|
||||
|
||||
return (
|
||||
span({className: "objectBox objectBox-string"}, "\"" + croppedString + "\""
|
||||
span({className: "objectBox objectBox-string"}, formattedString
|
||||
)
|
||||
);
|
||||
},
|
||||
|
@ -35,7 +35,6 @@
|
||||
height: calc(100% - 24px);
|
||||
}
|
||||
|
||||
.tabs .tab-panel-box,
|
||||
.tabs .tab-panel {
|
||||
height: 100%;
|
||||
}
|
||||
|
@ -161,7 +161,7 @@ window.onload = Task.async(function* () {
|
||||
function testRecursiveArray() {
|
||||
let stub = [1];
|
||||
stub.push(stub);
|
||||
const defaultOutput = `[ 1, […] ]`;
|
||||
const defaultOutput = `[ 1, [2] ]`;
|
||||
|
||||
const modeTests = [
|
||||
{
|
||||
@ -194,7 +194,7 @@ window.onload = Task.async(function* () {
|
||||
p4: "s4"
|
||||
}
|
||||
];
|
||||
const defaultOutput = `[ Object { p1: "s1", p3: "s3", p4: "s4", 1 more… } ]`;
|
||||
const defaultOutput = `[ Object ]`;
|
||||
|
||||
const modeTests = [
|
||||
{
|
||||
|
@ -35,22 +35,30 @@ window.onload = Task.async(function* () {
|
||||
|
||||
function testEvent() {
|
||||
const renderedComponent = renderComponent(Event.rep, { object: getGripStub("testEvent") });
|
||||
is(renderedComponent.textContent, "beforeprint", "Event rep has expected text content for an event");
|
||||
is(renderedComponent.textContent,
|
||||
"Event { isTrusted: true, eventPhase: 2, bubbles: false, 7 more… }",
|
||||
"Event rep has expected text content for an event");
|
||||
}
|
||||
|
||||
function testMouseEvent() {
|
||||
const renderedComponent = renderComponent(Event.rep, { object: getGripStub("testMouseEvent") });
|
||||
is(renderedComponent.textContent, "clickclientX=62, clientY=18", "Event rep has expected text content for a mouse event");
|
||||
is(renderedComponent.textContent,
|
||||
"MouseEvent { buttons: 0, clientX: 62, clientY: 18, 2 more… }",
|
||||
"Event rep has expected text content for a mouse event");
|
||||
}
|
||||
|
||||
function testKeyboardEvent() {
|
||||
const renderedComponent = renderComponent(Event.rep, { object: getGripStub("testKeyboardEvent") });
|
||||
is(renderedComponent.textContent, "keyupcharCode=0, keyCode=17", "Event rep has expected text content for a keyboard event");
|
||||
is(renderedComponent.textContent,
|
||||
"KeyboardEvent { key: \"Control\", charCode: 0, keyCode: 17 }",
|
||||
"Event rep has expected text content for a keyboard event");
|
||||
}
|
||||
|
||||
function testMessageEvent() {
|
||||
const renderedComponent = renderComponent(Event.rep, { object: getGripStub("testMessageEvent") });
|
||||
is(renderedComponent.textContent, "messageorigin=null, data=test data", "Event rep has expected text content for a message event");
|
||||
is(renderedComponent.textContent,
|
||||
"MessageEvent { isTrusted: false, data: \"test data\", origin: \"null\", 7 more… }",
|
||||
"Event rep has expected text content for a message event");
|
||||
}
|
||||
|
||||
function getGripStub(name) {
|
||||
|
@ -32,6 +32,7 @@ window.onload = Task.async(function* () {
|
||||
yield testMoreThanShortMaxProps();
|
||||
yield testMoreThanLongMaxProps();
|
||||
yield testRecursiveArray();
|
||||
yield testPreviewLimit();
|
||||
|
||||
yield testNamedNodeMap();
|
||||
} catch(e) {
|
||||
@ -190,6 +191,34 @@ window.onload = Task.async(function* () {
|
||||
testRepRenderModes(modeTests, testName, componentUnderTest, getGripStub(testName));
|
||||
}
|
||||
|
||||
function testPreviewLimit() {
|
||||
const testName = "testPreviewLimit";
|
||||
|
||||
const shortOutput = `Array[ 0, 1, 2, 8 more… ]`;
|
||||
const defaultOutput = `Array[ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 1 more… ]`;
|
||||
|
||||
const modeTests = [
|
||||
{
|
||||
mode: undefined,
|
||||
expectedOutput: shortOutput,
|
||||
},
|
||||
{
|
||||
mode: "tiny",
|
||||
expectedOutput: `[11]`,
|
||||
},
|
||||
{
|
||||
mode: "short",
|
||||
expectedOutput: shortOutput,
|
||||
},
|
||||
{
|
||||
mode: "long",
|
||||
expectedOutput: defaultOutput,
|
||||
}
|
||||
];
|
||||
|
||||
testRepRenderModes(modeTests, testName, componentUnderTest, getGripStub(testName));
|
||||
}
|
||||
|
||||
function testNamedNodeMap() {
|
||||
const testName = "testNamedNodeMap";
|
||||
|
||||
@ -311,6 +340,22 @@ window.onload = Task.async(function* () {
|
||||
|
||||
return longArrayGrip;
|
||||
|
||||
case "testPreviewLimit":
|
||||
return {
|
||||
"type": "object",
|
||||
"class": "Array",
|
||||
"actor": "server1.conn1.obj31",
|
||||
"extensible": true,
|
||||
"frozen": false,
|
||||
"sealed": false,
|
||||
"ownPropertyLength": 12,
|
||||
"preview": {
|
||||
"kind": "ArrayLike",
|
||||
"length": 11,
|
||||
"items": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
|
||||
}
|
||||
};
|
||||
|
||||
case "testRecursiveArray":
|
||||
return {
|
||||
"type": "object",
|
||||
|
@ -160,7 +160,7 @@ window.onload = Task.async(function* () {
|
||||
strProp: "test string",
|
||||
arrProp: [1]
|
||||
};
|
||||
const defaultOutput = `Object { strProp: "test string", objProp: Object { id: 1, arr: [ 2 ] }, arrProp: [ 1 ] }`;
|
||||
const defaultOutput = `Object { strProp: "test string", objProp: Object, arrProp: [1] }`;
|
||||
|
||||
const modeTests = [
|
||||
{
|
||||
|
@ -27,6 +27,7 @@ window.onload = Task.async(function* () {
|
||||
yield testMultiline();
|
||||
yield testMultilineOpen();
|
||||
yield testMultilineLimit();
|
||||
yield testOmitQuotes();
|
||||
} catch(e) {
|
||||
ok(false, "Got an error: " + DevToolsUtils.safeErrorString(e));
|
||||
} finally {
|
||||
@ -48,10 +49,18 @@ window.onload = Task.async(function* () {
|
||||
is(renderedComponent.textContent, "\"aaaaaaaaaaaaaaaaaaaaa\nbbbbbbbbbbbbbbbbbbb\ncccccccccccccccc\n\"", "String rep has expected text content for multiline string when open");
|
||||
}
|
||||
|
||||
function testOmitQuotes(){
|
||||
const renderedComponent = renderComponent(StringRep.rep, { object: getGripStub("testOmitQuotes"), omitQuotes: true });
|
||||
is(renderedComponent.textContent, "abc","String rep has expected to omit quotes");
|
||||
}
|
||||
|
||||
function getGripStub(name) {
|
||||
switch (name) {
|
||||
case "testMultiline":
|
||||
return "aaaaaaaaaaaaaaaaaaaaa\nbbbbbbbbbbbbbbbbbbb\ncccccccccccccccc\n";
|
||||
return "aaaaaaaaaaaaaaaaaaaaa\nbbbbbbbbbbbbbbbbbbb\ncccccccccccccccc\n";
|
||||
break;
|
||||
case "testOmitQuotes":
|
||||
return "abc";
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -1257,7 +1257,7 @@ function Scope(aView, aName, aFlags = {}) {
|
||||
this.contextMenuId = aView.contextMenuId;
|
||||
this.separatorStr = aView.separatorStr;
|
||||
|
||||
this._init(aName.trim(), aFlags);
|
||||
this._init(aName, aFlags);
|
||||
}
|
||||
|
||||
Scope.prototype = {
|
||||
@ -1822,7 +1822,7 @@ Scope.prototype = {
|
||||
|
||||
let name = this._name = document.createElement("label");
|
||||
name.className = "plain name";
|
||||
name.setAttribute("value", aName);
|
||||
name.setAttribute("value", aName.trim());
|
||||
name.setAttribute("crop", "end");
|
||||
|
||||
let title = this._title = document.createElement("hbox");
|
||||
|
@ -37,7 +37,6 @@
|
||||
/* TODO: bug 1265759: should apply to .devtools-searchinput once all searchbox
|
||||
is converted to html*/
|
||||
#inspector-searchbox {
|
||||
flex: 1;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
|
@ -462,7 +462,7 @@
|
||||
.devtools-searchinput-clear {
|
||||
position: absolute;
|
||||
top: 3.5px;
|
||||
right: 7px;
|
||||
offset-inline-end: 7px;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
width: 16px;
|
||||
|
@ -447,8 +447,6 @@ JSTerm.prototype = {
|
||||
const { ConsoleCommand } = require("devtools/client/webconsole/new-console-output/types");
|
||||
let message = new ConsoleCommand({
|
||||
messageText: executeString,
|
||||
source: "javascript",
|
||||
type: "command",
|
||||
// @TODO remove category and severity
|
||||
category: "input",
|
||||
severity: "log",
|
||||
|
@ -0,0 +1,39 @@
|
||||
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
||||
/* 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/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
const {
|
||||
FILTER_TEXT_SET,
|
||||
FILTER_TOGGLE,
|
||||
FILTERS_CLEAR
|
||||
} = require("../constants");
|
||||
|
||||
function filterTextSet(text) {
|
||||
return {
|
||||
type: FILTER_TEXT_SET,
|
||||
text
|
||||
};
|
||||
}
|
||||
|
||||
function filterToggle(filter) {
|
||||
return {
|
||||
type: FILTER_TOGGLE,
|
||||
filter,
|
||||
};
|
||||
}
|
||||
|
||||
function filtersClear() {
|
||||
return {
|
||||
type: FILTERS_CLEAR
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
filterTextSet,
|
||||
filterToggle,
|
||||
filtersClear
|
||||
};
|
@ -13,10 +13,7 @@ const { IdGenerator } = require("devtools/client/webconsole/new-console-output/u
|
||||
|
||||
const {
|
||||
MESSAGE_ADD,
|
||||
MESSAGES_CLEAR,
|
||||
SEVERITY_FILTER,
|
||||
MESSAGES_SEARCH,
|
||||
FILTERS_CLEAR,
|
||||
MESSAGES_CLEAR
|
||||
} = require("../constants");
|
||||
|
||||
const defaultIdGenerator = new IdGenerator();
|
||||
@ -39,29 +36,5 @@ function messagesClear() {
|
||||
};
|
||||
}
|
||||
|
||||
function severityFilter(filter, toggled) {
|
||||
return {
|
||||
type: SEVERITY_FILTER,
|
||||
filter,
|
||||
toggled
|
||||
};
|
||||
}
|
||||
|
||||
function filtersClear() {
|
||||
return {
|
||||
type: FILTERS_CLEAR
|
||||
};
|
||||
}
|
||||
|
||||
function messagesSearch(searchText) {
|
||||
return {
|
||||
type: MESSAGES_SEARCH,
|
||||
searchText
|
||||
};
|
||||
}
|
||||
|
||||
exports.messageAdd = messageAdd;
|
||||
exports.messagesClear = messagesClear;
|
||||
exports.severityFilter = severityFilter;
|
||||
exports.filtersClear = filtersClear;
|
||||
exports.messagesSearch = messagesSearch;
|
||||
|
@ -4,6 +4,7 @@
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
DevToolsModules(
|
||||
'filters.js',
|
||||
'messages.js',
|
||||
'ui.js',
|
||||
)
|
||||
|
@ -7,12 +7,12 @@
|
||||
"use strict";
|
||||
|
||||
const {
|
||||
FILTERBAR_TOGGLE,
|
||||
FILTER_BAR_TOGGLE,
|
||||
} = require("../constants");
|
||||
|
||||
function filterBarToggle(show) {
|
||||
return {
|
||||
type: FILTERBAR_TOGGLE
|
||||
type: FILTER_BAR_TOGGLE
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -12,12 +12,13 @@ const {
|
||||
const { connect } = require("devtools/client/shared/vendor/react-redux");
|
||||
const { getAllFilters } = require("devtools/client/webconsole/new-console-output/selectors/filters");
|
||||
const { getAllUi } = require("devtools/client/webconsole/new-console-output/selectors/ui");
|
||||
const messagesActions = require("devtools/client/webconsole/new-console-output/actions/messages");
|
||||
const { filterTextSet, filtersClear } = require("devtools/client/webconsole/new-console-output/actions/filters");
|
||||
const { messagesClear } = require("devtools/client/webconsole/new-console-output/actions/messages");
|
||||
const uiActions = require("devtools/client/webconsole/new-console-output/actions/ui");
|
||||
const {
|
||||
SEVERITY_FILTER
|
||||
MESSAGE_LEVEL
|
||||
} = require("../constants");
|
||||
const FilterToggleButton = createFactory(require("devtools/client/webconsole/new-console-output/components/filter-toggle-button").FilterToggleButton);
|
||||
const FilterButton = createFactory(require("devtools/client/webconsole/new-console-output/components/filter-button").FilterButton);
|
||||
|
||||
const FilterBar = createClass({
|
||||
|
||||
@ -28,77 +29,73 @@ const FilterBar = createClass({
|
||||
ui: PropTypes.object.isRequired
|
||||
},
|
||||
|
||||
onClearOutputButtonClick: function () {
|
||||
this.props.dispatch(messagesActions.messagesClear());
|
||||
onClickMessagesClear: function () {
|
||||
this.props.dispatch(messagesClear());
|
||||
},
|
||||
|
||||
onToggleFilterConfigBarButtonClick: function () {
|
||||
onClickFilterBarToggle: function () {
|
||||
this.props.dispatch(uiActions.filterBarToggle());
|
||||
},
|
||||
|
||||
onClearFiltersButtonClick: function () {
|
||||
this.props.dispatch(messagesActions.filtersClear());
|
||||
onClickFiltersClear: function () {
|
||||
this.props.dispatch(filtersClear());
|
||||
},
|
||||
|
||||
onSearchInput: function (e) {
|
||||
this.props.dispatch(messagesActions.messagesSearch(e.target.value));
|
||||
this.props.dispatch(filterTextSet(e.target.value));
|
||||
},
|
||||
|
||||
render() {
|
||||
const {dispatch, filter, ui} = this.props;
|
||||
let configFilterBarVisible = ui.configFilterBarVisible;
|
||||
let filterBarVisible = ui.filterBarVisible;
|
||||
let children = [];
|
||||
|
||||
children.push(dom.div({className: "devtools-toolbar webconsole-filterbar-primary"},
|
||||
dom.button({
|
||||
className: "devtools-button devtools-clear-icon",
|
||||
title: "Clear output",
|
||||
onClick: this.onClearOutputButtonClick
|
||||
onClick: this.onClickMessagesClear
|
||||
}),
|
||||
dom.button({
|
||||
className: "devtools-button devtools-filter-icon" + (
|
||||
configFilterBarVisible ? " checked" : ""),
|
||||
filterBarVisible ? " checked" : ""),
|
||||
title: "Toggle filter bar",
|
||||
onClick: this.onToggleFilterConfigBarButtonClick
|
||||
onClick: this.onClickFilterBarToggle
|
||||
}),
|
||||
dom.input({
|
||||
className: "devtools-plaininput",
|
||||
type: "search",
|
||||
value: filter.searchText,
|
||||
value: filter.text,
|
||||
placeholder: "Filter output",
|
||||
onInput: this.onSearchInput
|
||||
})
|
||||
));
|
||||
|
||||
if (configFilterBarVisible) {
|
||||
if (filterBarVisible) {
|
||||
children.push(
|
||||
dom.div({className: "devtools-toolbar"},
|
||||
FilterToggleButton({
|
||||
FilterButton({
|
||||
active: filter.error,
|
||||
label: "Errors",
|
||||
filterType: SEVERITY_FILTER,
|
||||
filterKey: "error",
|
||||
filterKey: MESSAGE_LEVEL.ERROR,
|
||||
dispatch
|
||||
}),
|
||||
FilterToggleButton({
|
||||
FilterButton({
|
||||
active: filter.warn,
|
||||
label: "Warnings",
|
||||
filterType: SEVERITY_FILTER,
|
||||
filterKey: "warn",
|
||||
filterKey: MESSAGE_LEVEL.WARN,
|
||||
dispatch
|
||||
}),
|
||||
FilterToggleButton({
|
||||
FilterButton({
|
||||
active: filter.log,
|
||||
label: "Logs",
|
||||
filterType: SEVERITY_FILTER,
|
||||
filterKey: "log",
|
||||
filterKey: MESSAGE_LEVEL.LOG,
|
||||
dispatch
|
||||
}),
|
||||
FilterToggleButton({
|
||||
FilterButton({
|
||||
active: filter.info,
|
||||
label: "Info",
|
||||
filterType: SEVERITY_FILTER,
|
||||
filterKey: "info",
|
||||
filterKey: MESSAGE_LEVEL.INFO,
|
||||
dispatch
|
||||
})
|
||||
)
|
||||
@ -116,7 +113,7 @@ const FilterBar = createClass({
|
||||
"."),
|
||||
dom.button({
|
||||
className: "menu-filter-button",
|
||||
onClick: this.onClearFiltersButtonClick
|
||||
onClick: this.onClickFiltersClear
|
||||
}, "Remove filters")
|
||||
)
|
||||
);
|
||||
|
@ -8,28 +8,21 @@ const {
|
||||
DOM: dom,
|
||||
PropTypes
|
||||
} = require("devtools/client/shared/vendor/react");
|
||||
const actions = require("devtools/client/webconsole/new-console-output/actions/messages");
|
||||
const {
|
||||
SEVERITY_FILTER
|
||||
} = require("../constants");
|
||||
const actions = require("devtools/client/webconsole/new-console-output/actions/filters");
|
||||
|
||||
const FilterToggleButton = createClass({
|
||||
const FilterButton = createClass({
|
||||
|
||||
displayName: "FilterToggleButton",
|
||||
displayName: "FilterButton",
|
||||
|
||||
propTypes: {
|
||||
label: PropTypes.string.isRequired,
|
||||
filterType: PropTypes.string.isRequired,
|
||||
filterKey: PropTypes.string.isRequired,
|
||||
active: PropTypes.bool.isRequired,
|
||||
dispatch: PropTypes.func.isRequired,
|
||||
},
|
||||
|
||||
onClick: function () {
|
||||
if (this.props.filterType === SEVERITY_FILTER) {
|
||||
this.props.dispatch(actions.severityFilter(
|
||||
this.props.filterKey, !this.props.active));
|
||||
}
|
||||
this.props.dispatch(actions.filterToggle(this.props.filterKey));
|
||||
},
|
||||
|
||||
render() {
|
||||
@ -47,4 +40,4 @@ const FilterToggleButton = createClass({
|
||||
}
|
||||
});
|
||||
|
||||
exports.FilterToggleButton = FilterToggleButton;
|
||||
exports.FilterButton = FilterButton;
|
@ -10,7 +10,7 @@ DIRS += [
|
||||
DevToolsModules(
|
||||
'console-output.js',
|
||||
'filter-bar.js',
|
||||
'filter-toggle-button.js',
|
||||
'filter-button.js',
|
||||
'grip-message-body.js',
|
||||
'message-container.js',
|
||||
'message-icon.js',
|
||||
|
@ -8,10 +8,10 @@
|
||||
const actionTypes = {
|
||||
MESSAGE_ADD: "MESSAGE_ADD",
|
||||
MESSAGES_CLEAR: "MESSAGES_CLEAR",
|
||||
SEVERITY_FILTER: "SEVERITY_FILTER",
|
||||
MESSAGES_SEARCH: "MESSAGES_SEARCH",
|
||||
FILTER_TOGGLE: "FILTER_TOGGLE",
|
||||
FILTER_TEXT_SET: "FILTER_TEXT_SET",
|
||||
FILTERS_CLEAR: "FILTERS_CLEAR",
|
||||
FILTERBAR_TOGGLE: "FILTERBAR_TOGGLE",
|
||||
FILTER_BAR_TOGGLE: "FILTER_BAR_TOGGLE",
|
||||
};
|
||||
|
||||
const categories = {
|
||||
@ -97,7 +97,7 @@ const chromeRDPEnums = {
|
||||
};
|
||||
|
||||
const filterTypes = {
|
||||
SEVERITY_FILTER: "SEVERITY_FILTER"
|
||||
FILTER_TOGGLE: "FILTER_TOGGLE"
|
||||
};
|
||||
|
||||
// Combine into a single constants object
|
||||
|
@ -13,19 +13,20 @@ const FilterState = Immutable.Record({
|
||||
warn: true,
|
||||
info: true,
|
||||
log: true,
|
||||
searchText: ""
|
||||
text: ""
|
||||
});
|
||||
|
||||
function filters(state = new FilterState(), action) {
|
||||
switch (action.type) {
|
||||
case constants.SEVERITY_FILTER:
|
||||
let {filter, toggled} = action;
|
||||
return state.set(filter, toggled);
|
||||
case constants.FILTER_TOGGLE:
|
||||
const {filter} = action;
|
||||
const active = !state.get(filter);
|
||||
return state.set(filter, active);
|
||||
case constants.FILTERS_CLEAR:
|
||||
return new FilterState();
|
||||
case constants.MESSAGES_SEARCH:
|
||||
let {searchText} = action;
|
||||
return state.set("searchText", searchText);
|
||||
case constants.FILTER_TEXT_SET:
|
||||
let {text} = action;
|
||||
return state.set("text", text);
|
||||
}
|
||||
|
||||
return state;
|
||||
|
@ -9,14 +9,14 @@ const constants = require("devtools/client/webconsole/new-console-output/constan
|
||||
const Immutable = require("devtools/client/shared/vendor/immutable");
|
||||
|
||||
const Ui = Immutable.Record({
|
||||
configFilterBarVisible: false,
|
||||
filterBarVisible: false,
|
||||
filteredMessageVisible: false
|
||||
});
|
||||
|
||||
function ui(state = new Ui(), action) {
|
||||
switch (action.type) {
|
||||
case constants.FILTERBAR_TOGGLE:
|
||||
return state.set("configFilterBarVisible", !state.configFilterBarVisible);
|
||||
case constants.FILTER_BAR_TOGGLE:
|
||||
return state.set("filterBarVisible", !state.filterBarVisible);
|
||||
}
|
||||
|
||||
return state;
|
||||
|
@ -16,18 +16,18 @@ function getAllMessages(state) {
|
||||
return prune(
|
||||
search(
|
||||
filterSeverity(messages, filters),
|
||||
filters.searchText
|
||||
filters.text
|
||||
),
|
||||
logLimit
|
||||
);
|
||||
}
|
||||
|
||||
function filterSeverity(messages, filters) {
|
||||
return messages.filter((message) => filters[message.severity] === true);
|
||||
return messages.filter((message) => filters[message.level] === true);
|
||||
}
|
||||
|
||||
function search(messages, searchText = "") {
|
||||
if (searchText === "") {
|
||||
function search(messages, text = "") {
|
||||
if (text === "") {
|
||||
return messages;
|
||||
}
|
||||
|
||||
@ -39,7 +39,7 @@ function search(messages, searchText = "") {
|
||||
return message
|
||||
.parameters.join("")
|
||||
.toLocaleLowerCase()
|
||||
.includes(searchText.toLocaleLowerCase());
|
||||
.includes(text.toLocaleLowerCase());
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -22,7 +22,6 @@ function configureStore(Services) {
|
||||
warn: Services.prefs.getBoolPref("devtools.webconsole.filter.warn"),
|
||||
info: Services.prefs.getBoolPref("devtools.webconsole.filter.info"),
|
||||
log: Services.prefs.getBoolPref("devtools.webconsole.filter.log"),
|
||||
searchText: ""
|
||||
})
|
||||
};
|
||||
|
||||
|
@ -0,0 +1,54 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
"use strict";
|
||||
|
||||
const actions = require("devtools/client/webconsole/new-console-output/actions/filters");
|
||||
const {
|
||||
FILTER_TEXT_SET,
|
||||
FILTER_TOGGLE,
|
||||
FILTERS_CLEAR,
|
||||
MESSAGE_LEVEL
|
||||
} = require("devtools/client/webconsole/new-console-output/constants");
|
||||
|
||||
const expect = require("expect");
|
||||
|
||||
describe("Filter actions:", () => {
|
||||
describe("filterTextSet", () => {
|
||||
it("creates expected action", () => {
|
||||
const action = actions.filterTextSet("test");
|
||||
const expected = {
|
||||
type: FILTER_TEXT_SET,
|
||||
text: "test"
|
||||
};
|
||||
|
||||
expect(action).toEqual(expected);
|
||||
});
|
||||
});
|
||||
|
||||
describe("filterToggle", () => {
|
||||
it("creates expected action", () => {
|
||||
const action = actions.filterToggle(MESSAGE_LEVEL.ERROR);
|
||||
const expected = {
|
||||
type: FILTER_TOGGLE,
|
||||
filter: "error"
|
||||
};
|
||||
|
||||
expect(action).toEqual(expected);
|
||||
});
|
||||
});
|
||||
|
||||
describe("filterTextApply", () => {
|
||||
|
||||
});
|
||||
|
||||
describe("filtersClear", () => {
|
||||
it("creates expected action", () => {
|
||||
const action = actions.filtersClear();
|
||||
const expected = {
|
||||
type: FILTERS_CLEAR
|
||||
};
|
||||
|
||||
expect(action).toEqual(expected);
|
||||
});
|
||||
});
|
||||
});
|
@ -0,0 +1,23 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
"use strict";
|
||||
|
||||
const actions = require("devtools/client/webconsole/new-console-output/actions/ui");
|
||||
const {
|
||||
FILTER_BAR_TOGGLE
|
||||
} = require("devtools/client/webconsole/new-console-output/constants");
|
||||
|
||||
const expect = require("expect");
|
||||
|
||||
describe("UI actions:", () => {
|
||||
describe("filterBarToggle", () => {
|
||||
it("creates expected action", () => {
|
||||
const action = actions.filterBarToggle();
|
||||
const expected = {
|
||||
type: FILTER_BAR_TOGGLE
|
||||
};
|
||||
|
||||
expect(action).toEqual(expected);
|
||||
});
|
||||
});
|
||||
});
|
@ -58,7 +58,7 @@ function timeit(cb) {
|
||||
|
||||
window.onload = Task.async(function* () {
|
||||
const { configureStore } = browserRequire("devtools/client/webconsole/new-console-output/store");
|
||||
const { messagesSearch, filtersClear } = browserRequire("devtools/client/webconsole/new-console-output/actions/messages");
|
||||
const { filterTextSet, filtersClear } = browserRequire("devtools/client/webconsole/new-console-output/actions/filters");
|
||||
const NewConsoleOutputWrapper = browserRequire("devtools/client/webconsole/new-console-output/new-console-output-wrapper");
|
||||
const wrapper = new NewConsoleOutputWrapper(document.querySelector("#output"), {});
|
||||
|
||||
@ -72,7 +72,7 @@ window.onload = Task.async(function* () {
|
||||
info("took " + time + " seconds to render messages");
|
||||
|
||||
time = yield timeit(() => {
|
||||
store.dispatch(messagesSearch("Odd text"));
|
||||
store.dispatch(filterTextSet("Odd text"));
|
||||
});
|
||||
info("took " + time + " seconds to search filter half the messages");
|
||||
|
||||
|
@ -4,7 +4,6 @@
|
||||
|
||||
const { stubConsoleMessages } = require("devtools/client/webconsole/new-console-output/test/fixtures/stubs");
|
||||
const { ConsoleApiCall } = require("devtools/client/webconsole/new-console-output/components/message-types/console-api-call");
|
||||
const jsdom = require("mocha-jsdom");
|
||||
const expect = require("expect");
|
||||
|
||||
const {
|
||||
@ -12,7 +11,6 @@ const {
|
||||
} = require("devtools/client/webconsole/new-console-output/test/helpers");
|
||||
|
||||
describe("ConsoleAPICall component:", () => {
|
||||
jsdom();
|
||||
describe("console.log", () => {
|
||||
it("renders string grips", () => {
|
||||
const message = stubConsoleMessages.get("console.log('foobar', 'test')");
|
||||
|
@ -5,7 +5,6 @@
|
||||
const { stubConsoleMessages } = require("devtools/client/webconsole/new-console-output/test/fixtures/stubs");
|
||||
const { EvaluationResult } = require("devtools/client/webconsole/new-console-output/components/message-types/evaluation-result");
|
||||
|
||||
const jsdom = require("mocha-jsdom");
|
||||
const expect = require("expect");
|
||||
|
||||
const {
|
||||
@ -13,7 +12,6 @@ const {
|
||||
} = require("devtools/client/webconsole/new-console-output/test/helpers");
|
||||
|
||||
describe("EvaluationResult component:", () => {
|
||||
jsdom();
|
||||
it("renders a grip result", () => {
|
||||
const message = stubConsoleMessages.get("new Date(0)");
|
||||
const props = {
|
||||
|
@ -0,0 +1,96 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
"use strict";
|
||||
|
||||
// Require helper is necessary to load certain modules.
|
||||
require("devtools/client/webconsole/new-console-output/test/requireHelper")();
|
||||
const { render, mount } = require("enzyme");
|
||||
|
||||
const { createFactory } = require("devtools/client/shared/vendor/react");
|
||||
const Provider = createFactory(require("react-redux").Provider);
|
||||
|
||||
const FilterButton = createFactory(require("devtools/client/webconsole/new-console-output/components/filter-button").FilterButton);
|
||||
const FilterBar = createFactory(require("devtools/client/webconsole/new-console-output/components/filter-bar"));
|
||||
const { getAllUi } = require("devtools/client/webconsole/new-console-output/selectors/ui");
|
||||
const {
|
||||
MESSAGES_CLEAR,
|
||||
MESSAGE_LEVEL
|
||||
} = require("devtools/client/webconsole/new-console-output/constants");
|
||||
|
||||
const { setupStore } = require("devtools/client/webconsole/new-console-output/test/helpers");
|
||||
|
||||
const expect = require("expect");
|
||||
const sinon = require("sinon");
|
||||
|
||||
describe("FilterBar component:", () => {
|
||||
it("initial render", () => {
|
||||
const store = setupStore([]);
|
||||
|
||||
const wrapper = render(Provider({store}, FilterBar({})));
|
||||
const toolbar = wrapper.find(
|
||||
".devtools-toolbar.webconsole-filterbar-primary"
|
||||
);
|
||||
|
||||
// Clear button
|
||||
expect(toolbar.children().eq(0).attr("class"))
|
||||
.toBe("devtools-button devtools-clear-icon");
|
||||
expect(toolbar.children().eq(0).attr("title")).toBe("Clear output");
|
||||
|
||||
// Filter bar toggle
|
||||
expect(toolbar.children().eq(1).attr("class"))
|
||||
.toBe("devtools-button devtools-filter-icon");
|
||||
expect(toolbar.children().eq(1).attr("title")).toBe("Toggle filter bar");
|
||||
|
||||
// Text filter
|
||||
expect(toolbar.children().eq(2).attr("class")).toBe("devtools-plaininput");
|
||||
expect(toolbar.children().eq(2).attr("placeholder")).toBe("Filter output");
|
||||
expect(toolbar.children().eq(2).attr("type")).toBe("search");
|
||||
expect(toolbar.children().eq(2).attr("value")).toBe("");
|
||||
});
|
||||
|
||||
it("displays filter bar when button is clicked", () => {
|
||||
const store = setupStore([]);
|
||||
|
||||
expect(getAllUi(store.getState()).filterBarVisible).toBe(false);
|
||||
|
||||
const wrapper = mount(Provider({store}, FilterBar({})));
|
||||
wrapper.find(".devtools-filter-icon").simulate("click");
|
||||
|
||||
expect(getAllUi(store.getState()).filterBarVisible).toBe(true);
|
||||
|
||||
// Buttons are displayed
|
||||
const buttonProps = {
|
||||
active: true,
|
||||
dispatch: store.dispatch
|
||||
};
|
||||
const logButton = FilterButton(Object.assign({}, buttonProps,
|
||||
{ label: "Logs", filterKey: MESSAGE_LEVEL.LOG }));
|
||||
const infoButton = FilterButton(Object.assign({}, buttonProps,
|
||||
{ label: "Info", filterKey: MESSAGE_LEVEL.INFO }));
|
||||
const warnButton = FilterButton(Object.assign({}, buttonProps,
|
||||
{ label: "Warnings", filterKey: MESSAGE_LEVEL.WARN }));
|
||||
const errorButton = FilterButton(Object.assign({}, buttonProps,
|
||||
{ label: "Errors", filterKey: MESSAGE_LEVEL.ERROR }));
|
||||
expect(wrapper.contains([errorButton, warnButton, logButton, infoButton])).toBe(true);
|
||||
});
|
||||
|
||||
it("fires MESSAGES_CLEAR action when clear button is clicked", () => {
|
||||
const store = setupStore([]);
|
||||
store.dispatch = sinon.spy();
|
||||
|
||||
const wrapper = mount(Provider({store}, FilterBar({})));
|
||||
wrapper.find(".devtools-clear-icon").simulate("click");
|
||||
const call = store.dispatch.getCall(0);
|
||||
expect(call.args[0]).toEqual({
|
||||
type: MESSAGES_CLEAR
|
||||
});
|
||||
});
|
||||
|
||||
it("sets filter text when text is typed", () => {
|
||||
const store = setupStore([]);
|
||||
|
||||
const wrapper = mount(Provider({store}, FilterBar({})));
|
||||
wrapper.find(".devtools-plaininput").simulate("input", { target: { value: "a" } });
|
||||
expect(store.getState().filters.text).toBe("a");
|
||||
});
|
||||
});
|
@ -0,0 +1,52 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
"use strict";
|
||||
|
||||
// Require helper is necessary to load certain modules.
|
||||
require("devtools/client/webconsole/new-console-output/test/requireHelper")();
|
||||
const { render, shallow } = require("enzyme");
|
||||
|
||||
const { createFactory } = require("devtools/client/shared/vendor/react");
|
||||
|
||||
const FilterButton = createFactory(require("devtools/client/webconsole/new-console-output/components/filter-button").FilterButton);
|
||||
const {
|
||||
FILTER_TOGGLE,
|
||||
MESSAGE_LEVEL
|
||||
} = require("devtools/client/webconsole/new-console-output/constants");
|
||||
|
||||
const expect = require("expect");
|
||||
const sinon = require("sinon");
|
||||
|
||||
describe("FilterButton component:", () => {
|
||||
const props = {
|
||||
active: true,
|
||||
label: "Error",
|
||||
filterKey: MESSAGE_LEVEL.ERROR,
|
||||
dispatch: sinon.spy()
|
||||
};
|
||||
|
||||
it("displays as active when turned on", () => {
|
||||
const wrapper = render(FilterButton(props));
|
||||
expect(wrapper.html()).toBe(
|
||||
"<button class=\"menu-filter-button checked\">Error</button>"
|
||||
);
|
||||
});
|
||||
|
||||
it("displays as inactive when turned off", () => {
|
||||
const inactiveProps = Object.assign({}, props, { active: false });
|
||||
const wrapper = render(FilterButton(inactiveProps));
|
||||
expect(wrapper.html()).toBe(
|
||||
"<button class=\"menu-filter-button\">Error</button>"
|
||||
);
|
||||
});
|
||||
|
||||
it("fires FILTER_TOGGLE action when clicked", () => {
|
||||
const wrapper = shallow(FilterButton(props));
|
||||
wrapper.find("button").simulate("click");
|
||||
const call = props.dispatch.getCall(0);
|
||||
expect(call.args[0]).toEqual({
|
||||
type: FILTER_TOGGLE,
|
||||
filter: MESSAGE_LEVEL.ERROR
|
||||
});
|
||||
});
|
||||
});
|
@ -9,7 +9,6 @@ const { ConsoleApiCall } = require("devtools/client/webconsole/new-console-outpu
|
||||
const { EvaluationResult } = require("devtools/client/webconsole/new-console-output/components/message-types/evaluation-result");
|
||||
const { PageError } = require("devtools/client/webconsole/new-console-output/components/message-types/page-error");
|
||||
|
||||
const jsdom = require("mocha-jsdom");
|
||||
const expect = require("expect");
|
||||
|
||||
const {
|
||||
@ -18,7 +17,6 @@ const {
|
||||
} = require("devtools/client/webconsole/new-console-output/test/helpers");
|
||||
|
||||
describe("MessageContainer component:", () => {
|
||||
jsdom();
|
||||
it("pipes data to children as expected", () => {
|
||||
const message = stubConsoleMessages.get("console.log('foobar', 'test')");
|
||||
const rendered = renderComponent(MessageContainer, {message});
|
||||
|
@ -7,7 +7,6 @@ const {
|
||||
} = require("devtools/client/webconsole/new-console-output/constants");
|
||||
const { MessageIcon } = require("devtools/client/webconsole/new-console-output/components/message-icon");
|
||||
|
||||
const jsdom = require("mocha-jsdom");
|
||||
const expect = require("expect");
|
||||
|
||||
const {
|
||||
@ -15,8 +14,6 @@ const {
|
||||
} = require("devtools/client/webconsole/new-console-output/test/helpers");
|
||||
|
||||
describe("MessageIcon component:", () => {
|
||||
jsdom();
|
||||
|
||||
it("renders icon based on severity", () => {
|
||||
const rendered = renderComponent(MessageIcon, { severity: SEVERITY_ERROR });
|
||||
|
||||
|
@ -6,7 +6,6 @@ const { stubConsoleMessages } = require("devtools/client/webconsole/new-console-
|
||||
|
||||
const { PageError } = require("devtools/client/webconsole/new-console-output/components/message-types/page-error");
|
||||
|
||||
const jsdom = require("mocha-jsdom");
|
||||
const expect = require("expect");
|
||||
|
||||
const {
|
||||
@ -14,7 +13,6 @@ const {
|
||||
} = require("devtools/client/webconsole/new-console-output/test/helpers");
|
||||
|
||||
describe("PageError component:", () => {
|
||||
jsdom();
|
||||
it("renders a page error", () => {
|
||||
const message = stubConsoleMessages.get("ReferenceError");
|
||||
const rendered = renderComponent(PageError, {message});
|
||||
|
@ -4,7 +4,6 @@
|
||||
|
||||
const { MessageRepeat } = require("devtools/client/webconsole/new-console-output/components/message-repeat");
|
||||
|
||||
const jsdom = require("mocha-jsdom");
|
||||
const expect = require("expect");
|
||||
|
||||
const {
|
||||
@ -12,8 +11,6 @@ const {
|
||||
} = require("devtools/client/webconsole/new-console-output/test/helpers");
|
||||
|
||||
describe("MessageRepeat component:", () => {
|
||||
jsdom();
|
||||
|
||||
it("renders repeated value correctly", () => {
|
||||
const rendered = renderComponent(MessageRepeat, { repeat: 99 });
|
||||
expect(rendered.classList.contains("message-repeats")).toBe(true);
|
||||
|
@ -3,6 +3,8 @@
|
||||
|
||||
"use strict";
|
||||
|
||||
require("devtools/client/webconsole/new-console-output/test/requireHelper")();
|
||||
|
||||
let ReactDOM = require("devtools/client/shared/vendor/react-dom");
|
||||
let React = require("devtools/client/shared/vendor/react");
|
||||
var TestUtils = React.addons.TestUtils;
|
||||
|
@ -0,0 +1,26 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
"use strict";
|
||||
|
||||
const requireHacker = require("require-hacker");
|
||||
|
||||
module.exports = () => {
|
||||
try {
|
||||
requireHacker.global_hook("default", path => {
|
||||
switch (path) {
|
||||
case "react-dom/server":
|
||||
return `const React = require('react-dev'); module.exports = React`;
|
||||
case "react-addons-test-utils":
|
||||
return `const React = require('react-dev'); module.exports = React.addons.TestUtils`;
|
||||
case "react":
|
||||
return `const React = require('react-dev'); module.exports = React`;
|
||||
case "devtools/client/shared/vendor/react":
|
||||
return `const React = require('react-dev'); module.exports = React`;
|
||||
case "devtools/client/shared/vendor/react.default":
|
||||
return `const React = require('react-dev'); module.exports = React`;
|
||||
}
|
||||
});
|
||||
} catch (e) {
|
||||
// Do nothing. This means the hook is already registered.
|
||||
}
|
||||
};
|
@ -5,20 +5,98 @@
|
||||
|
||||
const expect = require("expect");
|
||||
|
||||
const actions = require("devtools/client/webconsole/new-console-output/actions/messages");
|
||||
const actions = require("devtools/client/webconsole/new-console-output/actions/filters");
|
||||
const { messageAdd } = require("devtools/client/webconsole/new-console-output/actions/messages");
|
||||
const { ConsoleCommand } = require("devtools/client/webconsole/new-console-output/types");
|
||||
const { getAllMessages } = require("devtools/client/webconsole/new-console-output/selectors/messages");
|
||||
const { getAllFilters } = require("devtools/client/webconsole/new-console-output/selectors/filters");
|
||||
const { setupStore } = require("devtools/client/webconsole/new-console-output/test/helpers");
|
||||
const { MESSAGE_LEVEL } = require("devtools/client/webconsole/new-console-output/constants");
|
||||
|
||||
describe("Search", () => {
|
||||
it("matches on value grips", () => {
|
||||
const store = setupStore([
|
||||
"console.log('foobar', 'test')",
|
||||
"console.warn('danger, will robinson!')",
|
||||
"console.log(undefined)"
|
||||
]);
|
||||
store.dispatch(actions.messagesSearch("danger"));
|
||||
describe("Filtering", () => {
|
||||
const numMessages = 5;
|
||||
const store = setupStore([
|
||||
"console.log('foobar', 'test')",
|
||||
"console.warn('danger, will robinson!')",
|
||||
"console.log(undefined)",
|
||||
"ReferenceError"
|
||||
]);
|
||||
// Add a console command as well
|
||||
store.dispatch(messageAdd(new ConsoleCommand({ messageText: `console.warn("x")` })));
|
||||
|
||||
let messages = getAllMessages(store.getState());
|
||||
expect(messages.size).toEqual(1);
|
||||
beforeEach(() => {
|
||||
store.dispatch(actions.filtersClear());
|
||||
});
|
||||
|
||||
describe("Severity filter", () => {
|
||||
it("filters log messages", () => {
|
||||
store.dispatch(actions.filterToggle(MESSAGE_LEVEL.LOG));
|
||||
|
||||
let messages = getAllMessages(store.getState());
|
||||
// @TODO It currently filters console command. This should be -2, not -3.
|
||||
expect(messages.size).toEqual(numMessages - 3);
|
||||
});
|
||||
|
||||
// @TODO add info stub
|
||||
it("filters info messages");
|
||||
|
||||
it("filters warning messages", () => {
|
||||
store.dispatch(actions.filterToggle(MESSAGE_LEVEL.WARN));
|
||||
|
||||
let messages = getAllMessages(store.getState());
|
||||
expect(messages.size).toEqual(numMessages - 1);
|
||||
});
|
||||
|
||||
it("filters error messages", () => {
|
||||
store.dispatch(actions.filterToggle(MESSAGE_LEVEL.ERROR));
|
||||
|
||||
let messages = getAllMessages(store.getState());
|
||||
expect(messages.size).toEqual(numMessages - 1);
|
||||
});
|
||||
});
|
||||
|
||||
describe("Text filter", () => {
|
||||
it("matches on value grips", () => {
|
||||
store.dispatch(actions.filterTextSet("danger"));
|
||||
|
||||
let messages = getAllMessages(store.getState());
|
||||
// @TODO figure out what this should filter
|
||||
// This does not filter out PageErrors or console commands
|
||||
expect(messages.size).toEqual(3);
|
||||
});
|
||||
});
|
||||
|
||||
describe("Combined filters", () => {
|
||||
// @TODO add test
|
||||
it("filters");
|
||||
});
|
||||
});
|
||||
|
||||
describe("Clear filters", () => {
|
||||
it("clears all filters", () => {
|
||||
const store = setupStore([]);
|
||||
|
||||
// Setup test case
|
||||
store.dispatch(actions.filterToggle(MESSAGE_LEVEL.ERROR));
|
||||
store.dispatch(actions.filterTextSet("foobar"));
|
||||
let filters = getAllFilters(store.getState());
|
||||
expect(filters.toJS()).toEqual({
|
||||
"error": false,
|
||||
"info": true,
|
||||
"log": true,
|
||||
"warn": true,
|
||||
"text": "foobar"
|
||||
});
|
||||
|
||||
store.dispatch(actions.filtersClear());
|
||||
|
||||
filters = getAllFilters(store.getState());
|
||||
expect(filters.toJS()).toEqual({
|
||||
"error": true,
|
||||
"info": true,
|
||||
"log": true,
|
||||
"warn": true,
|
||||
"text": ""
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -7,14 +7,21 @@
|
||||
|
||||
const Immutable = require("devtools/client/shared/vendor/immutable");
|
||||
|
||||
const {
|
||||
MESSAGE_SOURCE,
|
||||
MESSAGE_TYPE,
|
||||
MESSAGE_LEVEL
|
||||
} = require("devtools/client/webconsole/new-console-output/constants");
|
||||
|
||||
exports.ConsoleCommand = Immutable.Record({
|
||||
id: null,
|
||||
allowRepeating: false,
|
||||
messageText: null,
|
||||
source: null,
|
||||
type: null,
|
||||
category: null,
|
||||
severity: null,
|
||||
source: MESSAGE_SOURCE.JAVASCRIPT,
|
||||
type: MESSAGE_TYPE.COMMAND,
|
||||
level: MESSAGE_LEVEL.LOG,
|
||||
category: "input",
|
||||
severity: MESSAGE_TYPE.LOG,
|
||||
});
|
||||
|
||||
exports.ConsoleMessage = Immutable.Record({
|
||||
|
@ -5,12 +5,15 @@
|
||||
"amd-loader": "0.0.5",
|
||||
"babel-preset-es2015": "^6.6.0",
|
||||
"babel-register": "^6.7.2",
|
||||
"enzyme": "^2.4.1",
|
||||
"expect": "^1.16.0",
|
||||
"jsdom": "^9.4.1",
|
||||
"jsdom-global": "^2.0.0",
|
||||
"mocha": "^2.5.3",
|
||||
"mocha-jsdom": "^1.1.0"
|
||||
"require-hacker": "^2.1.4",
|
||||
"sinon": "^1.17.5"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "NODE_PATH=`pwd`/../../../ mocha new-console-output/test/**/*.test.js --compilers js:babel-register"
|
||||
"test": "NODE_PATH=`pwd`/../../../:`pwd`/../../../devtools/client/shared/vendor/ mocha new-console-output/test/**/*.test.js --compilers js:babel-register -r jsdom-global/register"
|
||||
}
|
||||
}
|
||||
|
@ -567,125 +567,119 @@ exports.createEmptyNodeList = function(doc) {
|
||||
* See BUG 664991: GCLI's keyboard handling should be updated to use DOM-L3
|
||||
* https://bugzilla.mozilla.org/show_bug.cgi?id=664991
|
||||
*/
|
||||
if (typeof 'KeyEvent' === 'undefined') {
|
||||
/* jshint -W040 */
|
||||
exports.KeyEvent = this.KeyEvent;
|
||||
}
|
||||
else {
|
||||
exports.KeyEvent = {
|
||||
DOM_VK_CANCEL: 3,
|
||||
DOM_VK_HELP: 6,
|
||||
DOM_VK_BACK_SPACE: 8,
|
||||
DOM_VK_TAB: 9,
|
||||
DOM_VK_CLEAR: 12,
|
||||
DOM_VK_RETURN: 13,
|
||||
DOM_VK_SHIFT: 16,
|
||||
DOM_VK_CONTROL: 17,
|
||||
DOM_VK_ALT: 18,
|
||||
DOM_VK_PAUSE: 19,
|
||||
DOM_VK_CAPS_LOCK: 20,
|
||||
DOM_VK_ESCAPE: 27,
|
||||
DOM_VK_SPACE: 32,
|
||||
DOM_VK_PAGE_UP: 33,
|
||||
DOM_VK_PAGE_DOWN: 34,
|
||||
DOM_VK_END: 35,
|
||||
DOM_VK_HOME: 36,
|
||||
DOM_VK_LEFT: 37,
|
||||
DOM_VK_UP: 38,
|
||||
DOM_VK_RIGHT: 39,
|
||||
DOM_VK_DOWN: 40,
|
||||
DOM_VK_PRINTSCREEN: 44,
|
||||
DOM_VK_INSERT: 45,
|
||||
DOM_VK_DELETE: 46,
|
||||
DOM_VK_0: 48,
|
||||
DOM_VK_1: 49,
|
||||
DOM_VK_2: 50,
|
||||
DOM_VK_3: 51,
|
||||
DOM_VK_4: 52,
|
||||
DOM_VK_5: 53,
|
||||
DOM_VK_6: 54,
|
||||
DOM_VK_7: 55,
|
||||
DOM_VK_8: 56,
|
||||
DOM_VK_9: 57,
|
||||
DOM_VK_SEMICOLON: 59,
|
||||
DOM_VK_EQUALS: 61,
|
||||
DOM_VK_A: 65,
|
||||
DOM_VK_B: 66,
|
||||
DOM_VK_C: 67,
|
||||
DOM_VK_D: 68,
|
||||
DOM_VK_E: 69,
|
||||
DOM_VK_F: 70,
|
||||
DOM_VK_G: 71,
|
||||
DOM_VK_H: 72,
|
||||
DOM_VK_I: 73,
|
||||
DOM_VK_J: 74,
|
||||
DOM_VK_K: 75,
|
||||
DOM_VK_L: 76,
|
||||
DOM_VK_M: 77,
|
||||
DOM_VK_N: 78,
|
||||
DOM_VK_O: 79,
|
||||
DOM_VK_P: 80,
|
||||
DOM_VK_Q: 81,
|
||||
DOM_VK_R: 82,
|
||||
DOM_VK_S: 83,
|
||||
DOM_VK_T: 84,
|
||||
DOM_VK_U: 85,
|
||||
DOM_VK_V: 86,
|
||||
DOM_VK_W: 87,
|
||||
DOM_VK_X: 88,
|
||||
DOM_VK_Y: 89,
|
||||
DOM_VK_Z: 90,
|
||||
DOM_VK_CONTEXT_MENU: 93,
|
||||
DOM_VK_NUMPAD0: 96,
|
||||
DOM_VK_NUMPAD1: 97,
|
||||
DOM_VK_NUMPAD2: 98,
|
||||
DOM_VK_NUMPAD3: 99,
|
||||
DOM_VK_NUMPAD4: 100,
|
||||
DOM_VK_NUMPAD5: 101,
|
||||
DOM_VK_NUMPAD6: 102,
|
||||
DOM_VK_NUMPAD7: 103,
|
||||
DOM_VK_NUMPAD8: 104,
|
||||
DOM_VK_NUMPAD9: 105,
|
||||
DOM_VK_MULTIPLY: 106,
|
||||
DOM_VK_ADD: 107,
|
||||
DOM_VK_SEPARATOR: 108,
|
||||
DOM_VK_SUBTRACT: 109,
|
||||
DOM_VK_DECIMAL: 110,
|
||||
DOM_VK_DIVIDE: 111,
|
||||
DOM_VK_F1: 112,
|
||||
DOM_VK_F2: 113,
|
||||
DOM_VK_F3: 114,
|
||||
DOM_VK_F4: 115,
|
||||
DOM_VK_F5: 116,
|
||||
DOM_VK_F6: 117,
|
||||
DOM_VK_F7: 118,
|
||||
DOM_VK_F8: 119,
|
||||
DOM_VK_F9: 120,
|
||||
DOM_VK_F10: 121,
|
||||
DOM_VK_F11: 122,
|
||||
DOM_VK_F12: 123,
|
||||
DOM_VK_F13: 124,
|
||||
DOM_VK_F14: 125,
|
||||
DOM_VK_F15: 126,
|
||||
DOM_VK_F16: 127,
|
||||
DOM_VK_F17: 128,
|
||||
DOM_VK_F18: 129,
|
||||
DOM_VK_F19: 130,
|
||||
DOM_VK_F20: 131,
|
||||
DOM_VK_F21: 132,
|
||||
DOM_VK_F22: 133,
|
||||
DOM_VK_F23: 134,
|
||||
DOM_VK_F24: 135,
|
||||
DOM_VK_NUM_LOCK: 144,
|
||||
DOM_VK_SCROLL_LOCK: 145,
|
||||
DOM_VK_COMMA: 188,
|
||||
DOM_VK_PERIOD: 190,
|
||||
DOM_VK_SLASH: 191,
|
||||
DOM_VK_BACK_QUOTE: 192,
|
||||
DOM_VK_OPEN_BRACKET: 219,
|
||||
DOM_VK_BACK_SLASH: 220,
|
||||
DOM_VK_CLOSE_BRACKET: 221,
|
||||
DOM_VK_QUOTE: 222,
|
||||
DOM_VK_META: 224
|
||||
};
|
||||
}
|
||||
exports.KeyEvent = {
|
||||
DOM_VK_CANCEL: 3,
|
||||
DOM_VK_HELP: 6,
|
||||
DOM_VK_BACK_SPACE: 8,
|
||||
DOM_VK_TAB: 9,
|
||||
DOM_VK_CLEAR: 12,
|
||||
DOM_VK_RETURN: 13,
|
||||
DOM_VK_SHIFT: 16,
|
||||
DOM_VK_CONTROL: 17,
|
||||
DOM_VK_ALT: 18,
|
||||
DOM_VK_PAUSE: 19,
|
||||
DOM_VK_CAPS_LOCK: 20,
|
||||
DOM_VK_ESCAPE: 27,
|
||||
DOM_VK_SPACE: 32,
|
||||
DOM_VK_PAGE_UP: 33,
|
||||
DOM_VK_PAGE_DOWN: 34,
|
||||
DOM_VK_END: 35,
|
||||
DOM_VK_HOME: 36,
|
||||
DOM_VK_LEFT: 37,
|
||||
DOM_VK_UP: 38,
|
||||
DOM_VK_RIGHT: 39,
|
||||
DOM_VK_DOWN: 40,
|
||||
DOM_VK_PRINTSCREEN: 44,
|
||||
DOM_VK_INSERT: 45,
|
||||
DOM_VK_DELETE: 46,
|
||||
DOM_VK_0: 48,
|
||||
DOM_VK_1: 49,
|
||||
DOM_VK_2: 50,
|
||||
DOM_VK_3: 51,
|
||||
DOM_VK_4: 52,
|
||||
DOM_VK_5: 53,
|
||||
DOM_VK_6: 54,
|
||||
DOM_VK_7: 55,
|
||||
DOM_VK_8: 56,
|
||||
DOM_VK_9: 57,
|
||||
DOM_VK_SEMICOLON: 59,
|
||||
DOM_VK_EQUALS: 61,
|
||||
DOM_VK_A: 65,
|
||||
DOM_VK_B: 66,
|
||||
DOM_VK_C: 67,
|
||||
DOM_VK_D: 68,
|
||||
DOM_VK_E: 69,
|
||||
DOM_VK_F: 70,
|
||||
DOM_VK_G: 71,
|
||||
DOM_VK_H: 72,
|
||||
DOM_VK_I: 73,
|
||||
DOM_VK_J: 74,
|
||||
DOM_VK_K: 75,
|
||||
DOM_VK_L: 76,
|
||||
DOM_VK_M: 77,
|
||||
DOM_VK_N: 78,
|
||||
DOM_VK_O: 79,
|
||||
DOM_VK_P: 80,
|
||||
DOM_VK_Q: 81,
|
||||
DOM_VK_R: 82,
|
||||
DOM_VK_S: 83,
|
||||
DOM_VK_T: 84,
|
||||
DOM_VK_U: 85,
|
||||
DOM_VK_V: 86,
|
||||
DOM_VK_W: 87,
|
||||
DOM_VK_X: 88,
|
||||
DOM_VK_Y: 89,
|
||||
DOM_VK_Z: 90,
|
||||
DOM_VK_CONTEXT_MENU: 93,
|
||||
DOM_VK_NUMPAD0: 96,
|
||||
DOM_VK_NUMPAD1: 97,
|
||||
DOM_VK_NUMPAD2: 98,
|
||||
DOM_VK_NUMPAD3: 99,
|
||||
DOM_VK_NUMPAD4: 100,
|
||||
DOM_VK_NUMPAD5: 101,
|
||||
DOM_VK_NUMPAD6: 102,
|
||||
DOM_VK_NUMPAD7: 103,
|
||||
DOM_VK_NUMPAD8: 104,
|
||||
DOM_VK_NUMPAD9: 105,
|
||||
DOM_VK_MULTIPLY: 106,
|
||||
DOM_VK_ADD: 107,
|
||||
DOM_VK_SEPARATOR: 108,
|
||||
DOM_VK_SUBTRACT: 109,
|
||||
DOM_VK_DECIMAL: 110,
|
||||
DOM_VK_DIVIDE: 111,
|
||||
DOM_VK_F1: 112,
|
||||
DOM_VK_F2: 113,
|
||||
DOM_VK_F3: 114,
|
||||
DOM_VK_F4: 115,
|
||||
DOM_VK_F5: 116,
|
||||
DOM_VK_F6: 117,
|
||||
DOM_VK_F7: 118,
|
||||
DOM_VK_F8: 119,
|
||||
DOM_VK_F9: 120,
|
||||
DOM_VK_F10: 121,
|
||||
DOM_VK_F11: 122,
|
||||
DOM_VK_F12: 123,
|
||||
DOM_VK_F13: 124,
|
||||
DOM_VK_F14: 125,
|
||||
DOM_VK_F15: 126,
|
||||
DOM_VK_F16: 127,
|
||||
DOM_VK_F17: 128,
|
||||
DOM_VK_F18: 129,
|
||||
DOM_VK_F19: 130,
|
||||
DOM_VK_F20: 131,
|
||||
DOM_VK_F21: 132,
|
||||
DOM_VK_F22: 133,
|
||||
DOM_VK_F23: 134,
|
||||
DOM_VK_F24: 135,
|
||||
DOM_VK_NUM_LOCK: 144,
|
||||
DOM_VK_SCROLL_LOCK: 145,
|
||||
DOM_VK_COMMA: 188,
|
||||
DOM_VK_PERIOD: 190,
|
||||
DOM_VK_SLASH: 191,
|
||||
DOM_VK_BACK_QUOTE: 192,
|
||||
DOM_VK_OPEN_BRACKET: 219,
|
||||
DOM_VK_BACK_SLASH: 220,
|
||||
DOM_VK_CLOSE_BRACKET: 221,
|
||||
DOM_VK_QUOTE: 222,
|
||||
DOM_VK_META: 224
|
||||
};
|
||||
|
@ -56,6 +56,14 @@ AnimValuesStyleRule::MightMapInheritedStyleData()
|
||||
return mStyleBits & NS_STYLE_INHERITED_STRUCT_MASK;
|
||||
}
|
||||
|
||||
bool
|
||||
AnimValuesStyleRule::GetDiscretelyAnimatedCSSValue(nsCSSPropertyID aProperty,
|
||||
nsCSSValue* aValue)
|
||||
{
|
||||
MOZ_ASSERT(false, "GetDiscretelyAnimatedCSSValue is not implemented yet");
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
void
|
||||
AnimValuesStyleRule::List(FILE* out, int32_t aIndent) const
|
||||
|
@ -32,6 +32,8 @@ public:
|
||||
// nsIStyleRule implementation
|
||||
void MapRuleInfoInto(nsRuleData* aRuleData) override;
|
||||
bool MightMapInheritedStyleData() override;
|
||||
bool GetDiscretelyAnimatedCSSValue(nsCSSPropertyID aProperty,
|
||||
nsCSSValue* aValue) override;
|
||||
#ifdef DEBUG
|
||||
void List(FILE* out = stdout, int32_t aIndent = 0) const override;
|
||||
#endif
|
||||
|
@ -62,4 +62,19 @@ AnimationUtils::IsOffscreenThrottlingEnabled()
|
||||
return sOffscreenThrottlingEnabled;
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
AnimationUtils::IsCoreAPIEnabled()
|
||||
{
|
||||
static bool sCoreAPIEnabled;
|
||||
static bool sPrefCached = false;
|
||||
|
||||
if (!sPrefCached) {
|
||||
sPrefCached = true;
|
||||
Preferences::AddBoolVarCache(&sCoreAPIEnabled,
|
||||
"dom.animations-api.core.enabled");
|
||||
}
|
||||
|
||||
return sCoreAPIEnabled;
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
|
@ -60,6 +60,13 @@ public:
|
||||
*/
|
||||
static bool
|
||||
IsOffscreenThrottlingEnabled();
|
||||
|
||||
/**
|
||||
* Returns true if the preference to enable the core Web Animations API is
|
||||
* true.
|
||||
*/
|
||||
static bool
|
||||
IsCoreAPIEnabled();
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
@ -6,6 +6,7 @@
|
||||
|
||||
#include "mozilla/KeyframeEffectParams.h"
|
||||
|
||||
#include "mozilla/AnimationUtils.h"
|
||||
#include "mozilla/KeyframeUtils.h"
|
||||
#include "mozilla/RangedPtr.h"
|
||||
#include "nsReadableUtils.h"
|
||||
@ -111,6 +112,13 @@ KeyframeEffectParams::ParseSpacing(const nsAString& aSpacing,
|
||||
{
|
||||
aInvalidPacedProperty.Truncate();
|
||||
|
||||
// Ignore spacing if the core API is not enabled since it is not yet ready to
|
||||
// ship.
|
||||
if (!AnimationUtils::IsCoreAPIEnabled()) {
|
||||
aSpacingMode = SpacingMode::distribute;
|
||||
return;
|
||||
}
|
||||
|
||||
// Parse spacing.
|
||||
// distribute | paced({ident})
|
||||
// https://w3c.github.io/web-animations/#dom-keyframeeffectreadonly-spacing
|
||||
|
@ -42,6 +42,7 @@ support-files =
|
||||
mozilla/file_hide_and_show.html
|
||||
mozilla/file_partial_keyframes.html
|
||||
mozilla/file_transform_limits.html
|
||||
mozilla/file_underlying-discrete-value.html
|
||||
style/file_animation-seeking-with-current-time.html
|
||||
style/file_animation-seeking-with-start-time.html
|
||||
testcommon.js
|
||||
@ -91,5 +92,6 @@ skip-if = (toolkit == 'gonk' && debug)
|
||||
[mozilla/test_partial_keyframes.html]
|
||||
[mozilla/test_set-easing.html]
|
||||
[mozilla/test_transform_limits.html]
|
||||
[mozilla/test_underlying-discrete-value.html]
|
||||
[style/test_animation-seeking-with-current-time.html]
|
||||
[style/test_animation-seeking-with-start-time.html]
|
||||
|
192
dom/animation/test/mozilla/file_underlying-discrete-value.html
Normal file
192
dom/animation/test/mozilla/file_underlying-discrete-value.html
Normal file
@ -0,0 +1,192 @@
|
||||
<!doctype html>
|
||||
<meta charset=utf-8>
|
||||
<script src="../testcommon.js"></script>
|
||||
<body>
|
||||
<script>
|
||||
"use strict";
|
||||
|
||||
// Tests that we correctly extract the underlying value when the animation
|
||||
// type is 'discrete'.
|
||||
const discreteTests = [
|
||||
{
|
||||
stylesheet: {
|
||||
"@keyframes keyframes":
|
||||
"from { align-content: flex-start; } to { align-content: flex-end; } "
|
||||
},
|
||||
expectedKeyframes: [
|
||||
{ computedOffset: 0, alignContent: "flex-start" },
|
||||
{ computedOffset: 1, alignContent: "flex-end" }
|
||||
],
|
||||
explanation: "Test for fully-specified keyframes"
|
||||
},
|
||||
{
|
||||
stylesheet: {
|
||||
"@keyframes keyframes": "from { align-content: flex-start; }"
|
||||
},
|
||||
// The value of 100% should be 'stretch',
|
||||
// but we are not supporting underlying value.
|
||||
// https://bugzilla.mozilla.org/show_bug.cgi?id=1295401
|
||||
expectedKeyframes: [
|
||||
{ computedOffset: 0, alignContent: "flex-start" },
|
||||
{ computedOffset: 1, alignContent: "unset" }
|
||||
],
|
||||
explanation: "Test for 0% keyframe only"
|
||||
},
|
||||
{
|
||||
stylesheet: {
|
||||
"@keyframes keyframes": "to { align-content: flex-end; }"
|
||||
},
|
||||
// The value of 0% should be 'stretch',
|
||||
// but we are not supporting underlying value.
|
||||
// https://bugzilla.mozilla.org/show_bug.cgi?id=1295401
|
||||
expectedKeyframes: [
|
||||
{ computedOffset: 0, alignContent: "unset" },
|
||||
{ computedOffset: 1, alignContent: "flex-end" }
|
||||
],
|
||||
explanation: "Test for 100% keyframe only"
|
||||
},
|
||||
{
|
||||
stylesheet: {
|
||||
"@keyframes keyframes": "50% { align-content: center; }",
|
||||
"#target": "align-content: space-between;"
|
||||
},
|
||||
expectedKeyframes: [
|
||||
{ computedOffset: 0, alignContent: "space-between" },
|
||||
{ computedOffset: 0.5, alignContent: "center" },
|
||||
{ computedOffset: 1, alignContent: "space-between" }
|
||||
],
|
||||
explanation: "Test for no 0%/100% keyframes " +
|
||||
"and specified style on target element"
|
||||
},
|
||||
{
|
||||
stylesheet: {
|
||||
"@keyframes keyframes": "50% { align-content: center; }"
|
||||
},
|
||||
attributes: {
|
||||
style: "align-content: space-between"
|
||||
},
|
||||
expectedKeyframes: [
|
||||
{ computedOffset: 0, alignContent: "space-between" },
|
||||
{ computedOffset: 0.5, alignContent: "center" },
|
||||
{ computedOffset: 1, alignContent: "space-between" }
|
||||
],
|
||||
explanation: "Test for no 0%/100% keyframes " +
|
||||
"and specified style on target element using style attribute"
|
||||
},
|
||||
{
|
||||
stylesheet: {
|
||||
"@keyframes keyframes": "50% { align-content: center; }",
|
||||
"#target": "align-content: inherit;"
|
||||
},
|
||||
// The value of 0%/100% should be 'stretch',
|
||||
// but we are not supporting underlying value.
|
||||
// https://bugzilla.mozilla.org/show_bug.cgi?id=1295401
|
||||
expectedKeyframes: [
|
||||
{ computedOffset: 0, alignContent: "inherit" },
|
||||
{ computedOffset: 0.5, alignContent: "center" },
|
||||
{ computedOffset: 1, alignContent: "inherit" }
|
||||
],
|
||||
explanation: "Test for no 0%/100% keyframes " +
|
||||
"and 'inherit' specified on target element"
|
||||
},
|
||||
{
|
||||
stylesheet: {
|
||||
"@keyframes keyframes": "50% { align-content: center; }",
|
||||
".target": "align-content: space-between;"
|
||||
},
|
||||
attributes: {
|
||||
class: "target"
|
||||
},
|
||||
expectedKeyframes: [
|
||||
{ computedOffset: 0, alignContent: "space-between" },
|
||||
{ computedOffset: 0.5, alignContent: "center" },
|
||||
{ computedOffset: 1, alignContent: "space-between" }
|
||||
],
|
||||
explanation: "Test for no 0%/100% keyframes " +
|
||||
"and specified style on target element using class selector"
|
||||
},
|
||||
{
|
||||
stylesheet: {
|
||||
"@keyframes keyframes": "50% { align-content: center; }",
|
||||
"div": "align-content: space-between;"
|
||||
},
|
||||
expectedKeyframes: [
|
||||
{ computedOffset: 0, alignContent: "space-between" },
|
||||
{ computedOffset: 0.5, alignContent: "center" },
|
||||
{ computedOffset: 1, alignContent: "space-between" }
|
||||
],
|
||||
explanation: "Test for no 0%/100% keyframes " +
|
||||
"and specified style on target element using type selector"
|
||||
},
|
||||
{
|
||||
stylesheet: {
|
||||
"@keyframes keyframes": "50% { align-content: center; }",
|
||||
"div": "align-content: space-between;",
|
||||
".target": "align-content: flex-start;",
|
||||
"#target": "align-content: flex-end;"
|
||||
},
|
||||
attributes: {
|
||||
class: "target"
|
||||
},
|
||||
expectedKeyframes: [
|
||||
{ computedOffset: 0, alignContent: "flex-end" },
|
||||
{ computedOffset: 0.5, alignContent: "center" },
|
||||
{ computedOffset: 1, alignContent: "flex-end" }
|
||||
],
|
||||
explanation: "Test for no 0%/100% keyframes " +
|
||||
"and specified style on target element " +
|
||||
"using ID selector that overrides class selector"
|
||||
},
|
||||
{
|
||||
stylesheet: {
|
||||
"@keyframes keyframes": "50% { align-content: center; }",
|
||||
"div": "align-content: space-between !important;",
|
||||
".target": "align-content: flex-start;",
|
||||
"#target": "align-content: flex-end;"
|
||||
},
|
||||
attributes: {
|
||||
class: "target"
|
||||
},
|
||||
expectedKeyframes: [
|
||||
{ computedOffset: 0, alignContent: "space-between" },
|
||||
{ computedOffset: 0.5, alignContent: "center" },
|
||||
{ computedOffset: 1, alignContent: "space-between" }
|
||||
],
|
||||
explanation: "Test for no 0%/100% keyframes " +
|
||||
"and specified style on target element " +
|
||||
"using important type selector that overrides other rules"
|
||||
},
|
||||
];
|
||||
|
||||
discreteTests.forEach(testcase => {
|
||||
test(t => {
|
||||
addStyle(t, testcase.stylesheet);
|
||||
|
||||
const div = addDiv(t, { "id": "target" });
|
||||
if (testcase.attributes) {
|
||||
for (let attributeName in testcase.attributes) {
|
||||
div.setAttribute(attributeName, testcase.attributes[attributeName]);
|
||||
}
|
||||
}
|
||||
div.style.animation = "keyframes 100s";
|
||||
|
||||
const keyframes = div.getAnimations()[0].effect.getKeyframes();
|
||||
const expectedKeyframes = testcase.expectedKeyframes;
|
||||
assert_equals(keyframes.length, expectedKeyframes.length,
|
||||
`keyframes.length should be ${ expectedKeyframes.length }`);
|
||||
|
||||
keyframes.forEach((keyframe, index) => {
|
||||
const expectedKeyframe = expectedKeyframes[index];
|
||||
assert_equals(keyframe.computedOffset, expectedKeyframe.computedOffset,
|
||||
`computedOffset of keyframes[${ index }] should be ` +
|
||||
`${ expectedKeyframe.computedOffset }`);
|
||||
assert_equals(keyframe.alignContent, expectedKeyframe.alignContent,
|
||||
`alignContent of keyframes[${ index }] should be ` +
|
||||
`${ expectedKeyframe.alignContent }`);
|
||||
});
|
||||
}, testcase.explanation);
|
||||
});
|
||||
|
||||
done();
|
||||
</script>
|
||||
</body>
|
@ -0,0 +1,15 @@
|
||||
<!doctype html>
|
||||
<meta charset=utf-8>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<div id="log"></div>
|
||||
<script>
|
||||
'use strict';
|
||||
setup({explicit_done: true});
|
||||
SpecialPowers.pushPrefEnv(
|
||||
{ "set": [["dom.animations-api.core.enabled", true]]},
|
||||
function() {
|
||||
window.open("file_underlying-discrete-value.html");
|
||||
});
|
||||
</script>
|
||||
</html>
|
@ -192,6 +192,14 @@ nsMappedAttributes::MightMapInheritedStyleData()
|
||||
return true;
|
||||
}
|
||||
|
||||
/* virtual */ bool
|
||||
nsMappedAttributes::GetDiscretelyAnimatedCSSValue(nsCSSPropertyID aProperty,
|
||||
nsCSSValue* aValue)
|
||||
{
|
||||
MOZ_ASSERT(false, "GetDiscretelyAnimatedCSSValue is not implemented yet");
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
/* virtual */ void
|
||||
nsMappedAttributes::List(FILE* out, int32_t aIndent) const
|
||||
|
@ -75,6 +75,8 @@ public:
|
||||
// nsIStyleRule
|
||||
virtual void MapRuleInfoInto(nsRuleData* aRuleData) override;
|
||||
virtual bool MightMapInheritedStyleData() override;
|
||||
virtual bool GetDiscretelyAnimatedCSSValue(nsCSSPropertyID aProperty,
|
||||
nsCSSValue* aValue) override;
|
||||
#ifdef DEBUG
|
||||
virtual void List(FILE* out = stdout, int32_t aIndent = 0) const override;
|
||||
#endif
|
||||
|
@ -469,26 +469,22 @@ suite.test('bug-1054803', function() {
|
||||
ok(found == 1, "found size " + size.toSource() + " in pictureSizes");
|
||||
});
|
||||
|
||||
var sizeGenerator = Iterator(expSizes);
|
||||
var sizeIterator = expSizes.values();
|
||||
return new Promise(function(resolve, reject) {
|
||||
function nextSize() {
|
||||
try {
|
||||
var size = sizeGenerator.next()[1];
|
||||
var sync = suite.waitParameterPush();
|
||||
cam.setPictureSize(size);
|
||||
sync.then(function() {
|
||||
var got = cam.getPictureSize();
|
||||
ok(got.width == size.width && got.height == size.height,
|
||||
"Set size " + size.toSource() + ", got size " + got.toSource());
|
||||
nextSize();
|
||||
}, reject);
|
||||
} catch(e) {
|
||||
if (e instanceof StopIteration) {
|
||||
resolve();
|
||||
} else {
|
||||
reject(e);
|
||||
}
|
||||
var {value:size, done} = sizeIterator.next();
|
||||
if (done) {
|
||||
resolve();
|
||||
return;
|
||||
}
|
||||
var sync = suite.waitParameterPush();
|
||||
cam.setPictureSize(size);
|
||||
sync.then(function() {
|
||||
var got = cam.getPictureSize();
|
||||
ok(got.width == size.width && got.height == size.height,
|
||||
"Set size " + size.toSource() + ", got size " + got.toSource());
|
||||
nextSize();
|
||||
}, reject);
|
||||
}
|
||||
|
||||
nextSize();
|
||||
|
@ -174,6 +174,14 @@ BodyRule::MightMapInheritedStyleData()
|
||||
return false;
|
||||
}
|
||||
|
||||
/* virtual */ bool
|
||||
BodyRule::GetDiscretelyAnimatedCSSValue(nsCSSPropertyID aProperty,
|
||||
nsCSSValue* aValue)
|
||||
{
|
||||
MOZ_ASSERT(false, "GetDiscretelyAnimatedCSSValue is not implemented yet");
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
/* virtual */ void
|
||||
BodyRule::List(FILE* out, int32_t aIndent) const
|
||||
|
@ -29,6 +29,8 @@ public:
|
||||
// nsIStyleRule interface
|
||||
virtual void MapRuleInfoInto(nsRuleData* aRuleData) override;
|
||||
virtual bool MightMapInheritedStyleData() override;
|
||||
virtual bool GetDiscretelyAnimatedCSSValue(nsCSSPropertyID aProperty,
|
||||
nsCSSValue* aValue) override;
|
||||
#ifdef DEBUG
|
||||
virtual void List(FILE* out = stdout, int32_t aIndent = 0) const override;
|
||||
#endif
|
||||
|
@ -2617,20 +2617,6 @@ HTMLMediaElement::NotifyXPCOMShutdown()
|
||||
ShutdownDecoder();
|
||||
}
|
||||
|
||||
void
|
||||
HTMLMediaElement::ResetConnectionState()
|
||||
{
|
||||
SetCurrentTime(0);
|
||||
FireTimeUpdate(false);
|
||||
DispatchAsyncEvent(NS_LITERAL_STRING("ended"));
|
||||
ChangeNetworkState(nsIDOMHTMLMediaElement::NETWORK_EMPTY);
|
||||
ChangeDelayLoadStatus(false);
|
||||
ChangeReadyState(nsIDOMHTMLMediaElement::HAVE_NOTHING);
|
||||
if (mDecoder) {
|
||||
ShutdownDecoder();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
HTMLMediaElement::Play(ErrorResult& aRv)
|
||||
{
|
||||
@ -3378,19 +3364,7 @@ nsresult HTMLMediaElement::InitializeDecoderForChannel(nsIChannel* aChannel,
|
||||
mChannelLoader = nullptr;
|
||||
}
|
||||
|
||||
// We postpone the |FinishDecoderSetup| function call until we get
|
||||
// |OnConnected| signal from MediaStreamController which is held by
|
||||
// RtspMediaResource.
|
||||
if (DecoderTraits::DecoderWaitsForOnConnected(mimeType)) {
|
||||
decoder->SetResource(resource);
|
||||
SetDecoder(decoder);
|
||||
if (aListener) {
|
||||
*aListener = nullptr;
|
||||
}
|
||||
return NS_OK;
|
||||
} else {
|
||||
return FinishDecoderSetup(decoder, resource, aListener);
|
||||
}
|
||||
return FinishDecoderSetup(decoder, resource, aListener);
|
||||
}
|
||||
|
||||
nsresult HTMLMediaElement::FinishDecoderSetup(MediaDecoder* aDecoder,
|
||||
|
@ -439,10 +439,6 @@ public:
|
||||
return mNetworkState;
|
||||
}
|
||||
|
||||
// Called by the media decoder object, on the main thread,
|
||||
// when the connection between Rtsp server and client gets lost.
|
||||
virtual void ResetConnectionState() final override;
|
||||
|
||||
void NotifyXPCOMShutdown() final override;
|
||||
|
||||
// Called by media decoder when the audible state changed or when input is
|
||||
@ -719,13 +715,6 @@ public:
|
||||
// A method to check whether we are currently playing.
|
||||
bool IsCurrentlyPlaying() const;
|
||||
|
||||
/**
|
||||
* A public wrapper for FinishDecoderSetup()
|
||||
*/
|
||||
nsresult FinishDecoderSetup(MediaDecoder* aDecoder, MediaResource* aStream) {
|
||||
return FinishDecoderSetup(aDecoder, aStream, nullptr);
|
||||
}
|
||||
|
||||
// Returns true if the media element is being destroyed. Used in
|
||||
// dormancy checks to prevent dormant processing for an element
|
||||
// that will soon be gone.
|
||||
|
@ -561,7 +561,7 @@ TextTrackManager::TimeMarchesOn()
|
||||
mTimeMarchesOnDispatched = false;
|
||||
|
||||
// Early return if we don't have any TextTracks.
|
||||
if (mTextTracks->Length() == 0) {
|
||||
if (!mTextTracks || mTextTracks->Length() == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -922,11 +922,13 @@ ContentChild::InitXPCOM()
|
||||
ClipboardCapabilities clipboardCaps;
|
||||
DomainPolicyClone domainPolicy;
|
||||
StructuredCloneData initialData;
|
||||
OptionalURIParams userContentSheetURL;
|
||||
|
||||
SendGetXPCOMProcessAttributes(&isOffline, &isConnected,
|
||||
&isLangRTL, &haveBidiKeyboards,
|
||||
&mAvailableDictionaries,
|
||||
&clipboardCaps, &domainPolicy, &initialData);
|
||||
&clipboardCaps, &domainPolicy, &initialData,
|
||||
&userContentSheetURL);
|
||||
RecvSetOffline(isOffline);
|
||||
RecvSetConnectivity(isConnected);
|
||||
RecvBidiKeyboardNotify(isLangRTL, haveBidiKeyboards);
|
||||
@ -964,6 +966,10 @@ ContentChild::InitXPCOM()
|
||||
global->SetInitialProcessData(data);
|
||||
}
|
||||
|
||||
// The stylesheet cache is not ready yet. Store this URL for future use.
|
||||
nsCOMPtr<nsIURI> ucsURL = DeserializeURI(userContentSheetURL);
|
||||
nsLayoutStylesheetCache::SetUserContentCSSURL(ucsURL);
|
||||
|
||||
// This will register cross-process observer.
|
||||
mozilla::dom::time::InitializeDateCacheCleaner();
|
||||
}
|
||||
|
@ -195,6 +195,8 @@
|
||||
|
||||
#include "nsIBidiKeyboard.h"
|
||||
|
||||
#include "nsLayoutStylesheetCache.h"
|
||||
|
||||
#ifdef MOZ_WEBRTC
|
||||
#include "signaling/src/peerconnection/WebrtcGlobalParent.h"
|
||||
#endif
|
||||
@ -2975,7 +2977,8 @@ ContentParent::RecvGetXPCOMProcessAttributes(bool* aIsOffline,
|
||||
InfallibleTArray<nsString>* dictionaries,
|
||||
ClipboardCapabilities* clipboardCaps,
|
||||
DomainPolicyClone* domainPolicy,
|
||||
StructuredCloneData* aInitialData)
|
||||
StructuredCloneData* aInitialData,
|
||||
OptionalURIParams* aUserContentCSSURL)
|
||||
{
|
||||
nsCOMPtr<nsIIOService> io(do_GetIOService());
|
||||
MOZ_ASSERT(io, "No IO service?");
|
||||
@ -3032,6 +3035,16 @@ ContentParent::RecvGetXPCOMProcessAttributes(bool* aIsOffline,
|
||||
}
|
||||
}
|
||||
|
||||
// XXX bug 1046166
|
||||
// Content processes have no permission to read profile, so we send the
|
||||
// file URL instead.
|
||||
StyleSheetHandle::RefPtr ucs = nsLayoutStylesheetCache::For(StyleBackendType::Gecko)->UserContentSheet();
|
||||
if (ucs) {
|
||||
SerializeURI(ucs->GetSheetURI(), *aUserContentCSSURL);
|
||||
} else {
|
||||
SerializeURI(nullptr, *aUserContentCSSURL);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -732,7 +732,8 @@ private:
|
||||
InfallibleTArray<nsString>* dictionaries,
|
||||
ClipboardCapabilities* clipboardCaps,
|
||||
DomainPolicyClone* domainPolicy,
|
||||
StructuredCloneData* initialData) override;
|
||||
StructuredCloneData* initialData,
|
||||
OptionalURIParams* aUserContentSheetURL) override;
|
||||
|
||||
virtual bool
|
||||
DeallocPJavaScriptParent(mozilla::jsipc::PJavaScriptParent*) override;
|
||||
|
@ -722,7 +722,8 @@ parent:
|
||||
bool haveBidiKeyboards, nsString[] dictionaries,
|
||||
ClipboardCapabilities clipboardCaps,
|
||||
DomainPolicyClone domainPolicy,
|
||||
StructuredCloneData initialData);
|
||||
StructuredCloneData initialData,
|
||||
OptionalURIParams userContentSheetURL);
|
||||
|
||||
sync CreateChildProcess(IPCTabContext context,
|
||||
ProcessPriority priority,
|
||||
|
@ -33,10 +33,6 @@
|
||||
#include "nsIPrincipal.h"
|
||||
#include "mozilla/dom/HTMLMediaElement.h"
|
||||
#endif
|
||||
#ifdef NECKO_PROTOCOL_rtsp
|
||||
#include "RtspOmxDecoder.h"
|
||||
#include "RtspOmxReader.h"
|
||||
#endif
|
||||
#ifdef MOZ_DIRECTSHOW
|
||||
#include "DirectShowDecoder.h"
|
||||
#include "DirectShowReader.h"
|
||||
@ -273,29 +269,6 @@ static char const *const gOMXWebMCodecs[] = {
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef NECKO_PROTOCOL_rtsp
|
||||
static const char* const gRtspTypes[2] = {
|
||||
"RTSP",
|
||||
nullptr
|
||||
};
|
||||
|
||||
static bool
|
||||
IsRtspSupportedType(const nsACString& aMimeType)
|
||||
{
|
||||
return MediaDecoder::IsRtspEnabled() &&
|
||||
CodecListContains(gRtspTypes, aMimeType);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* static */
|
||||
bool DecoderTraits::DecoderWaitsForOnConnected(const nsACString& aMimeType) {
|
||||
#ifdef NECKO_PROTOCOL_rtsp
|
||||
return CodecListContains(gRtspTypes, aMimeType);
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef MOZ_ANDROID_OMX
|
||||
static bool
|
||||
IsAndroidMediaType(const nsACString& aType)
|
||||
@ -547,11 +520,6 @@ DecoderTraits::CanHandleMediaType(const char* aMIMEType,
|
||||
EnsureAndroidMediaPluginHost()->FindDecoder(nsDependentCString(aMIMEType), nullptr)) {
|
||||
return CANPLAY_MAYBE;
|
||||
}
|
||||
#endif
|
||||
#ifdef NECKO_PROTOCOL_rtsp
|
||||
if (IsRtspSupportedType(nsDependentCString(aMIMEType))) {
|
||||
return CANPLAY_MAYBE;
|
||||
}
|
||||
#endif
|
||||
return CANPLAY_NO;
|
||||
}
|
||||
@ -615,12 +583,6 @@ InstantiateDecoder(const nsACString& aType,
|
||||
return decoder.forget();
|
||||
}
|
||||
#endif
|
||||
#ifdef NECKO_PROTOCOL_rtsp
|
||||
if (IsRtspSupportedType(aType)) {
|
||||
decoder = new RtspOmxDecoder(aOwner);
|
||||
return decoder.forget();
|
||||
}
|
||||
#endif
|
||||
#ifdef MOZ_ANDROID_OMX
|
||||
if (MediaDecoder::IsAndroidMediaPluginEnabled() &&
|
||||
EnsureAndroidMediaPluginHost()->FindDecoder(aType, nullptr)) {
|
||||
@ -753,9 +715,6 @@ bool DecoderTraits::IsSupportedInVideoDocument(const nsACString& aType)
|
||||
IsAACSupportedType(aType) ||
|
||||
#ifdef MOZ_DIRECTSHOW
|
||||
IsDirectShowSupportedType(aType) ||
|
||||
#endif
|
||||
#ifdef NECKO_PROTOCOL_rtsp
|
||||
IsRtspSupportedType(aType) ||
|
||||
#endif
|
||||
false;
|
||||
}
|
||||
|
@ -71,10 +71,6 @@ public:
|
||||
// vice versa.
|
||||
static bool IsSupportedInVideoDocument(const nsACString& aType);
|
||||
|
||||
// Returns true if we should not start decoder until we receive
|
||||
// OnConnected signal. (currently RTSP only)
|
||||
static bool DecoderWaitsForOnConnected(const nsACString& aType);
|
||||
|
||||
static bool IsWebMTypeAndEnabled(const nsACString& aType);
|
||||
static bool IsWebMAudioType(const nsACString& aType);
|
||||
static bool IsMP4TypeAndEnabled(const nsACString& aType,
|
||||
|
@ -183,22 +183,6 @@ MediaDecoder::ResourceCallback::SetMediaSeekable(bool aMediaSeekable)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MediaDecoder::ResourceCallback::ResetConnectionState()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
if (mDecoder) {
|
||||
mDecoder->ResetConnectionState();
|
||||
}
|
||||
}
|
||||
|
||||
nsresult
|
||||
MediaDecoder::ResourceCallback::FinishDecoderSetup(MediaResource* aResource)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
return mDecoder ? mDecoder->FinishDecoderSetup(aResource) : NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
void
|
||||
MediaDecoder::ResourceCallback::NotifyNetworkError()
|
||||
{
|
||||
@ -499,6 +483,11 @@ MediaDecoder::IsInfinite() const
|
||||
return mInfiniteStream;
|
||||
}
|
||||
|
||||
#define INIT_MIRROR(name, val) \
|
||||
name(AbstractThread::MainThread(), val, "MediaDecoder::" #name " (Mirror)")
|
||||
#define INIT_CANONICAL(name, val) \
|
||||
name(AbstractThread::MainThread(), val, "MediaDecoder::" #name " (Canonical)")
|
||||
|
||||
MediaDecoder::MediaDecoder(MediaDecoderOwner* aOwner)
|
||||
: mWatchManager(this, AbstractThread::MainThread())
|
||||
, mDormantSupported(false)
|
||||
@ -526,53 +515,29 @@ MediaDecoder::MediaDecoder(MediaDecoderOwner* aOwner)
|
||||
Preferences::GetInt("media.decoder.heuristic.dormant.timeout",
|
||||
DEFAULT_HEURISTIC_DORMANT_TIMEOUT_MSECS))
|
||||
, mIsHeuristicDormant(false)
|
||||
, mStateMachineIsShutdown(AbstractThread::MainThread(), true,
|
||||
"MediaDecoder::mStateMachineIsShutdown (Mirror)")
|
||||
, mBuffered(AbstractThread::MainThread(), TimeIntervals(),
|
||||
"MediaDecoder::mBuffered (Mirror)")
|
||||
, mNextFrameStatus(AbstractThread::MainThread(),
|
||||
MediaDecoderOwner::NEXT_FRAME_UNINITIALIZED,
|
||||
"MediaDecoder::mNextFrameStatus (Mirror)")
|
||||
, mCurrentPosition(AbstractThread::MainThread(), 0,
|
||||
"MediaDecoder::mCurrentPosition (Mirror)")
|
||||
, mStateMachineDuration(AbstractThread::MainThread(), NullableTimeUnit(),
|
||||
"MediaDecoder::mStateMachineDuration (Mirror)")
|
||||
, mPlaybackPosition(AbstractThread::MainThread(), 0,
|
||||
"MediaDecoder::mPlaybackPosition (Mirror)")
|
||||
, mIsAudioDataAudible(AbstractThread::MainThread(), false,
|
||||
"MediaDecoder::mIsAudioDataAudible (Mirror)")
|
||||
, mVolume(AbstractThread::MainThread(), 0.0,
|
||||
"MediaDecoder::mVolume (Canonical)")
|
||||
, mPlaybackRate(AbstractThread::MainThread(), 1.0,
|
||||
"MediaDecoder::mPlaybackRate (Canonical)")
|
||||
, mPreservesPitch(AbstractThread::MainThread(), true,
|
||||
"MediaDecoder::mPreservesPitch (Canonical)")
|
||||
, mEstimatedDuration(AbstractThread::MainThread(), NullableTimeUnit(),
|
||||
"MediaDecoder::mEstimatedDuration (Canonical)")
|
||||
, mExplicitDuration(AbstractThread::MainThread(), Maybe<double>(),
|
||||
"MediaDecoder::mExplicitDuration (Canonical)")
|
||||
, mPlayState(AbstractThread::MainThread(), PLAY_STATE_LOADING,
|
||||
"MediaDecoder::mPlayState (Canonical)")
|
||||
, mNextState(AbstractThread::MainThread(), PLAY_STATE_PAUSED,
|
||||
"MediaDecoder::mNextState (Canonical)")
|
||||
, mLogicallySeeking(AbstractThread::MainThread(), false,
|
||||
"MediaDecoder::mLogicallySeeking (Canonical)")
|
||||
, mSameOriginMedia(AbstractThread::MainThread(), false,
|
||||
"MediaDecoder::mSameOriginMedia (Canonical)")
|
||||
, mMediaPrincipalHandle(AbstractThread::MainThread(), PRINCIPAL_HANDLE_NONE,
|
||||
"MediaDecoder::mMediaPrincipalHandle (Canonical)")
|
||||
, mPlaybackBytesPerSecond(AbstractThread::MainThread(), 0.0,
|
||||
"MediaDecoder::mPlaybackBytesPerSecond (Canonical)")
|
||||
, mPlaybackRateReliable(AbstractThread::MainThread(), true,
|
||||
"MediaDecoder::mPlaybackRateReliable (Canonical)")
|
||||
, mDecoderPosition(AbstractThread::MainThread(), 0,
|
||||
"MediaDecoder::mDecoderPosition (Canonical)")
|
||||
, mMediaSeekable(AbstractThread::MainThread(), true,
|
||||
"MediaDecoder::mMediaSeekable (Canonical)")
|
||||
, mMediaSeekableOnlyInBufferedRanges(AbstractThread::MainThread(), false,
|
||||
"MediaDecoder::mMediaSeekableOnlyInBufferedRanges (Canonical)")
|
||||
, mIsVisible(AbstractThread::MainThread(), !aOwner->IsHidden(),
|
||||
"MediaDecoder::mIsVisible (Canonical)")
|
||||
, INIT_MIRROR(mStateMachineIsShutdown, true)
|
||||
, INIT_MIRROR(mBuffered, TimeIntervals())
|
||||
, INIT_MIRROR(mNextFrameStatus, MediaDecoderOwner::NEXT_FRAME_UNINITIALIZED)
|
||||
, INIT_MIRROR(mCurrentPosition, 0)
|
||||
, INIT_MIRROR(mStateMachineDuration, NullableTimeUnit())
|
||||
, INIT_MIRROR(mPlaybackPosition, 0)
|
||||
, INIT_MIRROR(mIsAudioDataAudible, false)
|
||||
, INIT_CANONICAL(mVolume, 0.0)
|
||||
, INIT_CANONICAL(mPlaybackRate, 1.0)
|
||||
, INIT_CANONICAL(mPreservesPitch, true)
|
||||
, INIT_CANONICAL(mEstimatedDuration, NullableTimeUnit())
|
||||
, INIT_CANONICAL(mExplicitDuration, Maybe<double>())
|
||||
, INIT_CANONICAL(mPlayState, PLAY_STATE_LOADING)
|
||||
, INIT_CANONICAL(mNextState, PLAY_STATE_PAUSED)
|
||||
, INIT_CANONICAL(mLogicallySeeking, false)
|
||||
, INIT_CANONICAL(mSameOriginMedia, false)
|
||||
, INIT_CANONICAL(mMediaPrincipalHandle, PRINCIPAL_HANDLE_NONE)
|
||||
, INIT_CANONICAL(mPlaybackBytesPerSecond, 0.0)
|
||||
, INIT_CANONICAL(mPlaybackRateReliable, true)
|
||||
, INIT_CANONICAL(mDecoderPosition, 0)
|
||||
, INIT_CANONICAL(mMediaSeekable, true)
|
||||
, INIT_CANONICAL(mMediaSeekableOnlyInBufferedRanges, false)
|
||||
, INIT_CANONICAL(mIsVisible, !aOwner->IsHidden())
|
||||
, mTelemetryReported(false)
|
||||
{
|
||||
MOZ_COUNT_CTOR(MediaDecoder);
|
||||
@ -612,6 +577,9 @@ MediaDecoder::MediaDecoder(MediaDecoderOwner* aOwner)
|
||||
MediaShutdownManager::Instance().Register(this);
|
||||
}
|
||||
|
||||
#undef INIT_MIRROR
|
||||
#undef INIT_CANONICAL
|
||||
|
||||
void
|
||||
MediaDecoder::Shutdown()
|
||||
{
|
||||
@ -1026,26 +994,6 @@ MediaDecoder::FirstFrameLoaded(nsAutoPtr<MediaInfo> aInfo,
|
||||
NotifySuspendedStatusChanged();
|
||||
}
|
||||
|
||||
nsresult
|
||||
MediaDecoder::FinishDecoderSetup(MediaResource* aResource)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(!IsShutdown());
|
||||
HTMLMediaElement* element = mOwner->GetMediaElement();
|
||||
NS_ENSURE_TRUE(element, NS_ERROR_FAILURE);
|
||||
element->FinishDecoderSetup(this, aResource);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
MediaDecoder::ResetConnectionState()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(!IsShutdown());
|
||||
mOwner->ResetConnectionState();
|
||||
MOZ_ASSERT(IsShutdown());
|
||||
}
|
||||
|
||||
void
|
||||
MediaDecoder::NetworkError()
|
||||
{
|
||||
@ -1755,15 +1703,6 @@ MediaDecoder::IsWebMEnabled()
|
||||
return Preferences::GetBool("media.webm.enabled");
|
||||
}
|
||||
|
||||
#ifdef NECKO_PROTOCOL_rtsp
|
||||
bool
|
||||
MediaDecoder::IsRtspEnabled()
|
||||
{
|
||||
//Currently the Rtsp decoded by omx.
|
||||
return (Preferences::GetBool("media.rtsp.enabled", false) && IsOmxEnabled());
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_OMX_DECODER
|
||||
bool
|
||||
MediaDecoder::IsOmxEnabled()
|
||||
|
@ -85,8 +85,6 @@ public:
|
||||
MediaDecoderOwner* GetMediaOwner() const override;
|
||||
void SetInfinite(bool aInfinite) override;
|
||||
void SetMediaSeekable(bool aMediaSeekable) override;
|
||||
void ResetConnectionState() override;
|
||||
nsresult FinishDecoderSetup(MediaResource* aResource) override;
|
||||
void NotifyNetworkError() override;
|
||||
void NotifyDecodeError() override;
|
||||
void NotifyDataArrived() override;
|
||||
@ -462,10 +460,6 @@ private:
|
||||
static bool IsWaveEnabled();
|
||||
static bool IsWebMEnabled();
|
||||
|
||||
#ifdef NECKO_PROTOCOL_rtsp
|
||||
static bool IsRtspEnabled();
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_OMX_DECODER
|
||||
static bool IsOmxEnabled();
|
||||
#endif
|
||||
@ -887,12 +881,6 @@ private:
|
||||
// no longer considered to be infinite.
|
||||
void SetInfinite(bool aInfinite);
|
||||
|
||||
// Reset the decoder and notify the media element that
|
||||
// server connection is closed.
|
||||
void ResetConnectionState();
|
||||
|
||||
nsresult FinishDecoderSetup(MediaResource* aResource);
|
||||
|
||||
// Called by MediaResource when the principal of the resource has
|
||||
// changed. Called on main thread only.
|
||||
void NotifyPrincipalChanged();
|
||||
|
@ -134,12 +134,6 @@ public:
|
||||
// ImageContainer containing the video data.
|
||||
virtual VideoFrameContainer* GetVideoFrameContainer() = 0;
|
||||
|
||||
// Called by the decoder object, on the main thread,
|
||||
// when the connection between Rtsp server and client gets lost.
|
||||
// The decoder owner should call Shutdown() on the decoder and drop the
|
||||
// reference to the decoder to prevent further calls into the decoder.
|
||||
virtual void ResetConnectionState() = 0;
|
||||
|
||||
// Called by media decoder when the audible state changed
|
||||
virtual void SetAudibleState(bool aAudible) = 0;
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user