зеркало из https://github.com/mozilla/gecko-dev.git
merge mozilla-inbound to mozilla-central
This commit is contained in:
Коммит
560c22d1e6
|
@ -918,10 +918,18 @@ var Input = {
|
|||
},
|
||||
|
||||
moveToPoint: function moveToPoint(aRule, aX, aY) {
|
||||
// XXX: Bug 1013408 - There is no alignment between the chrome window's
|
||||
// viewport size and the content viewport size in Android. This makes
|
||||
// sending mouse events beyond its bounds impossible.
|
||||
if (Utils.MozBuildApp === 'mobile/android') {
|
||||
let mm = Utils.getMessageManager(Utils.CurrentBrowser);
|
||||
mm.sendAsyncMessage('AccessFu:MoveToPoint', {rule: aRule,
|
||||
x: aX, y: aY,
|
||||
origin: 'top'});
|
||||
mm.sendAsyncMessage('AccessFu:MoveToPoint',
|
||||
{rule: aRule, x: aX, y: aY, origin: 'top'});
|
||||
} else {
|
||||
let win = Utils.win;
|
||||
Utils.winUtils.sendMouseEvent('mousemove',
|
||||
aX - win.mozInnerScreenX, aY - win.mozInnerScreenY, 0, 0, 0);
|
||||
}
|
||||
},
|
||||
|
||||
moveCursor: function moveCursor(aAction, aRule, aInputType) {
|
||||
|
@ -999,9 +1007,7 @@ var Input = {
|
|||
let page = aDetails.page;
|
||||
let p = AccessFu.adjustContentBounds(aDetails.bounds, Utils.CurrentBrowser,
|
||||
true, true).center();
|
||||
let wu = Utils.win.QueryInterface(Ci.nsIInterfaceRequestor).
|
||||
getInterface(Ci.nsIDOMWindowUtils);
|
||||
wu.sendWheelEvent(p.x, p.y,
|
||||
Utils.winUtils.sendWheelEvent(p.x, p.y,
|
||||
horizontal ? page : 0, horizontal ? 0 : page, 0,
|
||||
Utils.win.WheelEvent.DOM_DELTA_PAGE, 0, 0, 0, 0);
|
||||
},
|
||||
|
|
|
@ -45,6 +45,7 @@ this.ContentControl.prototype = {
|
|||
for (let message of this.messagesOfInterest) {
|
||||
cs.addMessageListener(message, this);
|
||||
}
|
||||
cs.addEventListener('mousemove', this);
|
||||
},
|
||||
|
||||
stop: function cc_stop() {
|
||||
|
@ -52,6 +53,7 @@ this.ContentControl.prototype = {
|
|||
for (let message of this.messagesOfInterest) {
|
||||
cs.removeMessageListener(message, this);
|
||||
}
|
||||
cs.removeEventListener('mousemove', this);
|
||||
},
|
||||
|
||||
get document() {
|
||||
|
@ -124,18 +126,22 @@ this.ContentControl.prototype = {
|
|||
}
|
||||
},
|
||||
|
||||
handleEvent: function cc_handleEvent(aEvent) {
|
||||
if (aEvent.type === 'mousemove') {
|
||||
this.handleMoveToPoint(
|
||||
{ json: { x: aEvent.screenX, y: aEvent.screenY, rule: 'Simple' } });
|
||||
}
|
||||
if (!Utils.getMessageManager(aEvent.target)) {
|
||||
aEvent.preventDefault();
|
||||
}
|
||||
},
|
||||
|
||||
handleMoveToPoint: function cc_handleMoveToPoint(aMessage) {
|
||||
let [x, y] = [aMessage.json.x, aMessage.json.y];
|
||||
let rule = TraversalRules[aMessage.json.rule];
|
||||
let vc = this.vc;
|
||||
let win = this.window;
|
||||
|
||||
let dpr = win.devicePixelRatio;
|
||||
let dpr = this.window.devicePixelRatio;
|
||||
this.vc.moveToPoint(rule, x * dpr, y * dpr, true);
|
||||
|
||||
let delta = Utils.isContentProcess ?
|
||||
{ x: x - win.mozInnerScreenX, y: y - win.mozInnerScreenY } : {};
|
||||
this.sendToChild(vc, aMessage, delta);
|
||||
},
|
||||
|
||||
handleClearCursor: function cc_handleClearCursor(aMessage) {
|
||||
|
|
|
@ -110,36 +110,14 @@ let PointerRelay = { // jshint ignore:line
|
|||
}
|
||||
},
|
||||
|
||||
_suppressPointerMove: function PointerRelay__suppressPointerMove(aChangedTouches) {
|
||||
if (!this.lastPointerMove) {
|
||||
return false;
|
||||
}
|
||||
for (let i = 0; i < aChangedTouches.length; ++i) {
|
||||
let touch = aChangedTouches[i];
|
||||
let lastTouch;
|
||||
try {
|
||||
lastTouch = this.lastPointerMove.identifiedTouch ?
|
||||
this.lastPointerMove.identifiedTouch(touch.identifier) :
|
||||
this.lastPointerMove[i];
|
||||
} catch (x) {
|
||||
// Sometimes touch object can't be accessed after page navigation.
|
||||
}
|
||||
if (!lastTouch || lastTouch.target !== touch.target ||
|
||||
Math.hypot(touch.screenX - lastTouch.screenX, touch.screenY -
|
||||
lastTouch.screenY) / Utils.dpi >= GestureSettings.travelThreshold) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
},
|
||||
|
||||
handleEvent: function PointerRelay_handleEvent(aEvent) {
|
||||
// Don't bother with chrome mouse events.
|
||||
if (Utils.MozBuildApp === 'browser' &&
|
||||
aEvent.view.top instanceof Ci.nsIDOMChromeWindow) {
|
||||
return;
|
||||
}
|
||||
if (aEvent.mozInputSource === Ci.nsIDOMMouseEvent.MOZ_SOURCE_UNKNOWN) {
|
||||
if (aEvent.mozInputSource === Ci.nsIDOMMouseEvent.MOZ_SOURCE_UNKNOWN ||
|
||||
aEvent.isSynthesized) {
|
||||
// Ignore events that are scripted or clicks from the a11y API.
|
||||
return;
|
||||
}
|
||||
|
@ -164,13 +142,6 @@ let PointerRelay = { // jshint ignore:line
|
|||
return;
|
||||
}
|
||||
let pointerType = this._eventMap[type];
|
||||
if (pointerType === 'pointermove') {
|
||||
if (this._suppressPointerMove(changedTouches)) {
|
||||
// Do not fire pointermove more than every POINTERMOVE_THROTTLE.
|
||||
return;
|
||||
}
|
||||
this.lastPointerMove = changedTouches;
|
||||
}
|
||||
this.onPointerEvent({
|
||||
type: pointerType,
|
||||
points: Array.prototype.map.call(changedTouches,
|
||||
|
|
|
@ -113,6 +113,11 @@ var gSimpleMatchFunc = function gSimpleMatchFunc(aAccessible) {
|
|||
|
||||
function isFlatSubtree(acc) {
|
||||
for (let child = acc.firstChild; child; child = child.nextSibling) {
|
||||
// text leafs inherit the actionCount of any ancestor that has a click
|
||||
// listener.
|
||||
if ([Roles.TEXT_LEAF, Roles.STATICTEXT].indexOf(child.role) >= 0) {
|
||||
continue;
|
||||
}
|
||||
if (child.childCount > 0 || child.actionCount > 0) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -54,6 +54,15 @@ this.Utils = {
|
|||
return this._win.get();
|
||||
},
|
||||
|
||||
get winUtils() {
|
||||
let win = this.win;
|
||||
if (!win) {
|
||||
return null;
|
||||
}
|
||||
return win.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(
|
||||
Ci.nsIDOMWindowUtils);
|
||||
},
|
||||
|
||||
get AccRetrieval() {
|
||||
if (!this._AccRetrieval) {
|
||||
this._AccRetrieval = Cc['@mozilla.org/accessibleRetrieval;1'].
|
||||
|
@ -181,7 +190,6 @@ this.Utils = {
|
|||
return aBrowser.QueryInterface(Ci.nsIFrameLoaderOwner).
|
||||
frameLoader.messageManager;
|
||||
} catch (x) {
|
||||
Logger.logException(x);
|
||||
return null;
|
||||
}
|
||||
},
|
||||
|
@ -252,8 +260,7 @@ this.Utils = {
|
|||
*/
|
||||
get dpi() {
|
||||
delete this.dpi;
|
||||
this.dpi = this.win.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(
|
||||
Ci.nsIDOMWindowUtils).displayDPI;
|
||||
this.dpi = this.winUtils.displayDPI;
|
||||
return this.dpi;
|
||||
},
|
||||
|
||||
|
|
|
@ -60,7 +60,7 @@
|
|||
<dd>A esoteric weapon wielded by only the most formidable warriors,
|
||||
for its unrelenting strict power is unfathomable.</dd>
|
||||
</dl>
|
||||
<ul id="list-2">
|
||||
<ul id="list-2" onclick="alert('hi');">
|
||||
<li id="listitem-2-1">Lists of Programming Languages</li>
|
||||
<li id="listitem-2-2">Lisp
|
||||
<ol id="list-3">
|
||||
|
|
|
@ -6,8 +6,8 @@
|
|||
"filename": "setup.sh"
|
||||
},
|
||||
{
|
||||
"size": 165464,
|
||||
"digest": "ee87db68eb63e417a366333e34a32d9220232bfb9c3e91b9941513acf0551f2603a836537ffef41a240430200970d83fa9271f55b8b5168d6967be595cdb50db",
|
||||
"size": 165226,
|
||||
"digest": "79280f7595bc9e1613e05f8b2f0db3798ac739b96191e0f133e8ccd8ad149fedc84a1046e59863574189db28363a01712ae7b368ad1714e30ff88e7ebd5dad23",
|
||||
"algorithm": "sha512",
|
||||
"filename": "sccache.tar.bz2"
|
||||
}
|
||||
|
|
|
@ -6,8 +6,8 @@
|
|||
"filename": "setup.sh"
|
||||
},
|
||||
{
|
||||
"size": 165464,
|
||||
"digest": "ee87db68eb63e417a366333e34a32d9220232bfb9c3e91b9941513acf0551f2603a836537ffef41a240430200970d83fa9271f55b8b5168d6967be595cdb50db",
|
||||
"size": 165226,
|
||||
"digest": "79280f7595bc9e1613e05f8b2f0db3798ac739b96191e0f133e8ccd8ad149fedc84a1046e59863574189db28363a01712ae7b368ad1714e30ff88e7ebd5dad23",
|
||||
"algorithm": "sha512",
|
||||
"filename": "sccache.tar.bz2"
|
||||
}
|
||||
|
|
|
@ -15,8 +15,8 @@
|
|||
"filename": "clang.tar.bz2"
|
||||
},
|
||||
{
|
||||
"size": 165464,
|
||||
"digest": "ee87db68eb63e417a366333e34a32d9220232bfb9c3e91b9941513acf0551f2603a836537ffef41a240430200970d83fa9271f55b8b5168d6967be595cdb50db",
|
||||
"size": 165226,
|
||||
"digest": "79280f7595bc9e1613e05f8b2f0db3798ac739b96191e0f133e8ccd8ad149fedc84a1046e59863574189db28363a01712ae7b368ad1714e30ff88e7ebd5dad23",
|
||||
"algorithm": "sha512",
|
||||
"filename": "sccache.tar.bz2"
|
||||
}
|
||||
|
|
|
@ -32,13 +32,14 @@ ul {
|
|||
max-width: 512px;
|
||||
}
|
||||
|
||||
#errorTitle {
|
||||
#errorTitleText {
|
||||
background: url("info.svg") left 0 no-repeat;
|
||||
-moz-margin-start: -5em;
|
||||
-moz-padding-start: 5em;
|
||||
background-size: 1.2em;
|
||||
-moz-margin-start: -2em;
|
||||
-moz-padding-start: 2em;
|
||||
}
|
||||
|
||||
#errorTitle:-moz-locale-dir(rtl) {
|
||||
#errorTitleText:-moz-locale-dir(rtl) {
|
||||
background-position: right 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -12,8 +12,8 @@
|
|||
"filename": "gcc.tar.xz"
|
||||
},
|
||||
{
|
||||
"size": 165464,
|
||||
"digest": "ee87db68eb63e417a366333e34a32d9220232bfb9c3e91b9941513acf0551f2603a836537ffef41a240430200970d83fa9271f55b8b5168d6967be595cdb50db",
|
||||
"size": 165226,
|
||||
"digest": "79280f7595bc9e1613e05f8b2f0db3798ac739b96191e0f133e8ccd8ad149fedc84a1046e59863574189db28363a01712ae7b368ad1714e30ff88e7ebd5dad23",
|
||||
"algorithm": "sha512",
|
||||
"filename": "sccache.tar.bz2"
|
||||
}
|
||||
|
|
|
@ -12,8 +12,8 @@
|
|||
"filename": "gcc.tar.xz"
|
||||
},
|
||||
{
|
||||
"size": 165464,
|
||||
"digest": "ee87db68eb63e417a366333e34a32d9220232bfb9c3e91b9941513acf0551f2603a836537ffef41a240430200970d83fa9271f55b8b5168d6967be595cdb50db",
|
||||
"size": 165226,
|
||||
"digest": "79280f7595bc9e1613e05f8b2f0db3798ac739b96191e0f133e8ccd8ad149fedc84a1046e59863574189db28363a01712ae7b368ad1714e30ff88e7ebd5dad23",
|
||||
"algorithm": "sha512",
|
||||
"filename": "sccache.tar.bz2"
|
||||
}
|
||||
|
|
|
@ -15,8 +15,8 @@
|
|||
"filename": "clang.tar.bz2"
|
||||
},
|
||||
{
|
||||
"size": 165464,
|
||||
"digest": "ee87db68eb63e417a366333e34a32d9220232bfb9c3e91b9941513acf0551f2603a836537ffef41a240430200970d83fa9271f55b8b5168d6967be595cdb50db",
|
||||
"size": 165226,
|
||||
"digest": "79280f7595bc9e1613e05f8b2f0db3798ac739b96191e0f133e8ccd8ad149fedc84a1046e59863574189db28363a01712ae7b368ad1714e30ff88e7ebd5dad23",
|
||||
"algorithm": "sha512",
|
||||
"filename": "sccache.tar.bz2"
|
||||
}
|
||||
|
|
|
@ -12,8 +12,8 @@
|
|||
"filename": "setup.sh"
|
||||
},
|
||||
{
|
||||
"size": 165464,
|
||||
"digest": "ee87db68eb63e417a366333e34a32d9220232bfb9c3e91b9941513acf0551f2603a836537ffef41a240430200970d83fa9271f55b8b5168d6967be595cdb50db",
|
||||
"size": 165226,
|
||||
"digest": "79280f7595bc9e1613e05f8b2f0db3798ac739b96191e0f133e8ccd8ad149fedc84a1046e59863574189db28363a01712ae7b368ad1714e30ff88e7ebd5dad23",
|
||||
"algorithm": "sha512",
|
||||
"filename": "sccache.tar.bz2"
|
||||
}
|
||||
|
|
|
@ -462,6 +462,13 @@ ThreadState.prototype = {
|
|||
* Update the UI after a thread state change.
|
||||
*/
|
||||
_update: function(aEvent) {
|
||||
// Ignore "interrupted" events, which are generated by the slow script
|
||||
// dialog and internal events such as setting breakpoints, to avoid UI
|
||||
// flicker.
|
||||
if (aEvent == "interrupted") {
|
||||
return;
|
||||
}
|
||||
|
||||
DebuggerView.Toolbar.toggleResumeButtonState(this.activeThread.state);
|
||||
|
||||
if (gTarget && (aEvent == "paused" || aEvent == "resumed")) {
|
||||
|
@ -568,6 +575,11 @@ StackFrames.prototype = {
|
|||
this._currentReturnedValue = aPacket.why.frameFinished.return;
|
||||
}
|
||||
break;
|
||||
// If paused by an explicit interrupt, which are generated by the slow
|
||||
// script dialog and internal events such as setting breakpoints, ignore
|
||||
// the event to avoid UI flicker.
|
||||
case "interrupted":
|
||||
return;
|
||||
}
|
||||
|
||||
this.activeThread.fillFrames(CALL_STACK_PAGE_SIZE);
|
||||
|
|
|
@ -78,6 +78,7 @@ support-files =
|
|||
doc_script-switching-01.html
|
||||
doc_script-switching-02.html
|
||||
doc_step-out.html
|
||||
doc_terminate-on-tab-close.html
|
||||
doc_tracing-01.html
|
||||
doc_watch-expressions.html
|
||||
doc_watch-expression-button.html
|
||||
|
@ -237,6 +238,7 @@ skip-if = true # Bug 933950 (leaky test)
|
|||
[browser_dbg_step-out.js]
|
||||
[browser_dbg_tabactor-01.js]
|
||||
[browser_dbg_tabactor-02.js]
|
||||
[browser_dbg_terminate-on-tab-close.js]
|
||||
[browser_dbg_tracing-01.js]
|
||||
[browser_dbg_tracing-02.js]
|
||||
[browser_dbg_tracing-03.js]
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Tests that debuggee scripts are terminated on tab closure.
|
||||
*/
|
||||
|
||||
const TAB_URL = EXAMPLE_URL + "doc_terminate-on-tab-close.html";
|
||||
|
||||
let gTab, gDebuggee, gDebugger, gPanel;
|
||||
|
||||
function test() {
|
||||
initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => {
|
||||
gTab = aTab;
|
||||
gDebuggee = aDebuggee;
|
||||
gPanel = aPanel;
|
||||
gDebugger = gPanel.panelWin;
|
||||
|
||||
testTerminate();
|
||||
});
|
||||
}
|
||||
|
||||
function testTerminate() {
|
||||
gDebugger.gThreadClient.addOneTimeListener("paused", () => {
|
||||
resumeDebuggerThenCloseAndFinish(gPanel).then(function () {
|
||||
ok(true, "should not throw after this point");
|
||||
});
|
||||
});
|
||||
|
||||
gDebuggee.debuggerThenThrow();
|
||||
}
|
||||
|
||||
registerCleanupFunction(function() {
|
||||
gTab = null;
|
||||
gDebuggee = null;
|
||||
gPanel = null;
|
||||
gDebugger = null;
|
||||
});
|
|
@ -0,0 +1,20 @@
|
|||
<!-- 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 test page</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<script type="text/javascript">
|
||||
function debuggerThenThrow() {
|
||||
debugger;
|
||||
throw "unreachable";
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
|
@ -580,6 +580,79 @@ let gDevToolsBrowser = {
|
|||
mainKeyset.parentNode.insertBefore(devtoolsKeyset, mainKeyset);
|
||||
},
|
||||
|
||||
/**
|
||||
* Hook the JS debugger tool to the "Debug Script" button of the slow script
|
||||
* dialog.
|
||||
*/
|
||||
setSlowScriptDebugHandler: function DT_setSlowScriptDebugHandler() {
|
||||
let debugService = Cc["@mozilla.org/dom/slow-script-debug;1"]
|
||||
.getService(Ci.nsISlowScriptDebug);
|
||||
let tm = Cc["@mozilla.org/thread-manager;1"].getService(Ci.nsIThreadManager);
|
||||
|
||||
debugService.activationHandler = function(aWindow) {
|
||||
let chromeWindow = aWindow.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIWebNavigation)
|
||||
.QueryInterface(Ci.nsIDocShellTreeItem)
|
||||
.rootTreeItem
|
||||
.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindow)
|
||||
.QueryInterface(Ci.nsIDOMChromeWindow);
|
||||
let target = devtools.TargetFactory.forTab(chromeWindow.gBrowser.selectedTab);
|
||||
|
||||
let setupFinished = false;
|
||||
gDevTools.showToolbox(target, "jsdebugger").then(toolbox => {
|
||||
let threadClient = toolbox.getCurrentPanel().panelWin.gThreadClient;
|
||||
|
||||
// Break in place, which means resuming the debuggee thread and pausing
|
||||
// right before the next step happens.
|
||||
switch (threadClient.state) {
|
||||
case "paused":
|
||||
// When the debugger is already paused.
|
||||
threadClient.breakOnNext();
|
||||
setupFinished = true;
|
||||
break;
|
||||
case "attached":
|
||||
// When the debugger is already open.
|
||||
threadClient.interrupt(() => {
|
||||
threadClient.breakOnNext();
|
||||
setupFinished = true;
|
||||
});
|
||||
break;
|
||||
case "resuming":
|
||||
// The debugger is newly opened.
|
||||
threadClient.addOneTimeListener("resumed", () => {
|
||||
threadClient.interrupt(() => {
|
||||
threadClient.breakOnNext();
|
||||
setupFinished = true;
|
||||
});
|
||||
});
|
||||
break;
|
||||
default:
|
||||
throw Error("invalid thread client state in slow script debug handler: " +
|
||||
threadClient.state);
|
||||
}
|
||||
});
|
||||
|
||||
// Don't return from the interrupt handler until the debugger is brought
|
||||
// up; no reason to continue executing the slow script.
|
||||
let utils = aWindow.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindowUtils);
|
||||
utils.enterModalState();
|
||||
while (!setupFinished) {
|
||||
tm.currentThread.processNextEvent(true);
|
||||
}
|
||||
utils.leaveModalState();
|
||||
};
|
||||
},
|
||||
|
||||
/**
|
||||
* Unset the slow script debug handler.
|
||||
*/
|
||||
unsetSlowScriptDebugHandler: function DT_unsetSlowScriptDebugHandler() {
|
||||
let debugService = Cc["@mozilla.org/dom/slow-script-debug;1"]
|
||||
.getService(Ci.nsISlowScriptDebug);
|
||||
debugService.activationHandler = undefined;
|
||||
},
|
||||
|
||||
/**
|
||||
* Detect the presence of a Firebug.
|
||||
|
@ -669,6 +742,10 @@ let gDevToolsBrowser = {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (toolDefinition.id === "jsdebugger") {
|
||||
gDevToolsBrowser.setSlowScriptDebugHandler();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -844,6 +921,10 @@ let gDevToolsBrowser = {
|
|||
for (let win of gDevToolsBrowser._trackedBrowserWindows) {
|
||||
gDevToolsBrowser._removeToolFromMenu(toolId, win.document);
|
||||
}
|
||||
|
||||
if (toolId === "jsdebugger") {
|
||||
gDevToolsBrowser.unsetSlowScriptDebugHandler();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
|
|
|
@ -531,6 +531,9 @@
|
|||
@BINPATH@/components/Push.manifest
|
||||
@BINPATH@/components/PushServiceLauncher.js
|
||||
|
||||
@BINPATH@/components/SlowScriptDebug.manifest
|
||||
@BINPATH@/components/SlowScriptDebug.js
|
||||
|
||||
#ifndef RELEASE_BUILD
|
||||
@BINPATH@/components/InterAppComm.manifest
|
||||
@BINPATH@/components/InterAppCommService.js
|
||||
|
|
|
@ -20,3 +20,5 @@ GENERATED_SOURCES += [
|
|||
DEFINES['ELFHACK_BUILD'] = True
|
||||
|
||||
NO_PGO = True
|
||||
|
||||
NO_VISIBILITY_FLAGS = True
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
/* 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/. */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
#endif
|
||||
void *__dso_handle;
|
||||
|
||||
/* Begin all files as hidden visibility */
|
||||
#pragma GCC visibility push(hidden)
|
|
@ -407,9 +407,6 @@ DriverServices.h
|
|||
DriverSynchronization.h
|
||||
DropInPanel.h
|
||||
dvidef.h
|
||||
#ifdef ANDROID
|
||||
EffectApi.h
|
||||
#endif
|
||||
elf.h
|
||||
endian.h
|
||||
Entry.h
|
||||
|
@ -516,6 +513,8 @@ gtk/gtkprinter.h
|
|||
gtk/gtkprintjob.h
|
||||
gtk/gtkprintunixdialog.h
|
||||
#ifdef ANDROID
|
||||
gui/BufferQueue.h
|
||||
gui/ConsumerBase.h
|
||||
gui/GraphicBufferAlloc.h
|
||||
gui/IConsumerListener.h
|
||||
gui/IGraphicBufferAlloc.h
|
||||
|
@ -542,14 +541,6 @@ hlink.h
|
|||
HTTPBase.h
|
||||
#endif
|
||||
ia64/sys/inline.h
|
||||
#ifdef ANDROID
|
||||
IAudioFlingerClient.h
|
||||
IAudioFlinger.h
|
||||
IAudioRecord.h
|
||||
IAudioTrack.h
|
||||
IEffect.h
|
||||
IEffectClient.h
|
||||
#endif
|
||||
Icons.h
|
||||
iconv.h
|
||||
ieeefp.h
|
||||
|
@ -911,6 +902,7 @@ rpc/types.h
|
|||
sane/sane.h
|
||||
sane/sanei.h
|
||||
sane/saneopts.h
|
||||
sched.h
|
||||
Scrap.h
|
||||
Screen.h
|
||||
Script.h
|
||||
|
|
16
configure.in
16
configure.in
|
@ -2550,17 +2550,19 @@ dnl ===============================================================
|
|||
if test "$GNU_CC" -a "$OS_TARGET" != WINNT; then
|
||||
AC_DEFINE(HAVE_VISIBILITY_HIDDEN_ATTRIBUTE)
|
||||
AC_DEFINE(HAVE_VISIBILITY_ATTRIBUTE)
|
||||
if test -n "$gonkdir"; then
|
||||
visibility_target=Gonk
|
||||
else
|
||||
visibility_target=$OS_TARGET
|
||||
fi
|
||||
case "$visibility_target" in
|
||||
Darwin|Gonk)
|
||||
case "$OS_TARGET" in
|
||||
Darwin)
|
||||
VISIBILITY_FLAGS='-fvisibility=hidden'
|
||||
;;
|
||||
*)
|
||||
case $GCC_VERSION in
|
||||
4.4*)
|
||||
VISIBILITY_FLAGS='-I$(DIST)/system_wrappers -include $(topsrcdir)/config/gcc_hidden_dso_handle.h'
|
||||
;;
|
||||
*)
|
||||
VISIBILITY_FLAGS='-I$(DIST)/system_wrappers -include $(topsrcdir)/config/gcc_hidden.h'
|
||||
;;
|
||||
esac
|
||||
WRAP_SYSTEM_INCLUDES=1
|
||||
;;
|
||||
esac
|
||||
|
|
|
@ -1334,6 +1334,12 @@ public:
|
|||
*/
|
||||
static nsIPrincipal* GetSystemPrincipal();
|
||||
|
||||
/**
|
||||
* Gets the null subject principal singleton. This is only useful for
|
||||
* assertions.
|
||||
*/
|
||||
static nsIPrincipal* GetNullSubjectPrincipal() { return sNullSubjectPrincipal; }
|
||||
|
||||
/**
|
||||
* *aResourcePrincipal is a principal describing who may access the contents
|
||||
* of a resource. The resource can only be consumed by a principal that
|
||||
|
@ -2169,6 +2175,7 @@ private:
|
|||
|
||||
static nsIScriptSecurityManager *sSecurityManager;
|
||||
static nsIPrincipal *sSystemPrincipal;
|
||||
static nsIPrincipal *sNullSubjectPrincipal;
|
||||
|
||||
static nsIParserService *sParserService;
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include "nsIDOMHTMLDocument.h"
|
||||
#include "nsIDOMHTMLElement.h"
|
||||
#include "nsIHttpChannel.h"
|
||||
#include "nsIInterfaceRequestor.h"
|
||||
#include "nsIInterfaceRequestorUtils.h"
|
||||
#include "nsIObjectInputStream.h"
|
||||
#include "nsIObjectOutputStream.h"
|
||||
|
@ -26,6 +27,7 @@
|
|||
#include "nsIPrincipal.h"
|
||||
#include "nsIPropertyBag2.h"
|
||||
#include "nsIScriptError.h"
|
||||
#include "nsIWebNavigation.h"
|
||||
#include "nsIWritablePropertyBag2.h"
|
||||
#include "nsString.h"
|
||||
#include "prlog.h"
|
||||
|
@ -45,6 +47,47 @@ GetCspContextLog()
|
|||
|
||||
#define CSPCONTEXTLOG(args) PR_LOG(GetCspContextLog(), 4, args)
|
||||
|
||||
static const uint32_t CSP_CACHE_URI_CUTOFF_SIZE = 512;
|
||||
|
||||
/**
|
||||
* Creates a key for use in the ShouldLoad cache.
|
||||
* Looks like: <uri>!<nsIContentPolicy::LOAD_TYPE>
|
||||
*/
|
||||
nsresult
|
||||
CreateCacheKey_Internal(nsIURI* aContentLocation,
|
||||
nsContentPolicyType aContentType,
|
||||
nsACString& outCacheKey)
|
||||
{
|
||||
if (!aContentLocation) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
bool isDataScheme = false;
|
||||
nsresult rv = aContentLocation->SchemeIs("data", &isDataScheme);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
outCacheKey.Truncate();
|
||||
if (aContentType != nsIContentPolicy::TYPE_SCRIPT && isDataScheme) {
|
||||
// For non-script data: URI, use ("data:", aContentType) as the cache key.
|
||||
outCacheKey.Append(NS_LITERAL_CSTRING("data:"));
|
||||
outCacheKey.AppendInt(aContentType);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsAutoCString spec;
|
||||
rv = aContentLocation->GetSpec(spec);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Don't cache for a URI longer than the cutoff size.
|
||||
if (spec.Length() <= CSP_CACHE_URI_CUTOFF_SIZE) {
|
||||
outCacheKey.Append(spec);
|
||||
outCacheKey.Append(NS_LITERAL_CSTRING("!"));
|
||||
outCacheKey.AppendInt(aContentType);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* ===== nsIContentSecurityPolicy impl ====== */
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -74,6 +117,16 @@ nsCSPContext::ShouldLoad(nsContentPolicyType aContentType,
|
|||
// * Content Type is not whitelisted (CSP Reports, TYPE_DOCUMENT, etc).
|
||||
// * Fast Path for Apps
|
||||
|
||||
nsAutoCString cacheKey;
|
||||
rv = CreateCacheKey_Internal(aContentLocation, aContentType, cacheKey);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
bool isCached = mShouldLoadCache.Get(cacheKey, outDecision);
|
||||
if (isCached && cacheKey.Length() > 0) {
|
||||
// this is cached, use the cached value.
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Default decision, CSP can revise it if there's a policy to enforce
|
||||
*outDecision = nsIContentPolicy::ACCEPT;
|
||||
|
||||
|
@ -137,6 +190,11 @@ nsCSPContext::ShouldLoad(nsContentPolicyType aContentType,
|
|||
// * Console error reporting, bug 994322
|
||||
}
|
||||
}
|
||||
// Done looping, cache any relevant result
|
||||
if (cacheKey.Length() > 0 && !isPreload) {
|
||||
mShouldLoadCache.Put(cacheKey, *outDecision);
|
||||
}
|
||||
|
||||
#ifdef PR_LOGGING
|
||||
{
|
||||
nsAutoCString spec;
|
||||
|
@ -183,6 +241,7 @@ nsCSPContext::~nsCSPContext()
|
|||
for (uint32_t i = 0; i < mPolicies.Length(); i++) {
|
||||
delete mPolicies[i];
|
||||
}
|
||||
mShouldLoadCache.Clear();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -215,6 +274,8 @@ nsCSPContext::RemovePolicy(uint32_t aIndex)
|
|||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
}
|
||||
mPolicies.RemoveElementAt(aIndex);
|
||||
// reset cache since effective policy changes
|
||||
mShouldLoadCache.Clear();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -237,6 +298,8 @@ nsCSPContext::AppendPolicy(const nsAString& aPolicyString,
|
|||
nsCSPPolicy* policy = nsCSPParser::parseContentSecurityPolicy(aPolicyString, mSelfURI, aReportOnly, 0);
|
||||
if (policy) {
|
||||
mPolicies.AppendElement(policy);
|
||||
// reset cache since effective policy changes
|
||||
mShouldLoadCache.Clear();
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -378,11 +441,118 @@ nsCSPContext::SetRequestContext(nsIURI* aSelfURI,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Based on the given docshell, determines if this CSP context allows the
|
||||
* ancestry.
|
||||
*
|
||||
* In order to determine the URI of the parent document (one causing the load
|
||||
* of this protected document), this function obtains the docShellTreeItem,
|
||||
* then walks up the hierarchy until it finds a privileged (chrome) tree item.
|
||||
* Getting the parent's URI looks like this in pseudocode:
|
||||
*
|
||||
* nsIDocShell->QI(nsIInterfaceRequestor)
|
||||
* ->GI(nsIDocShellTreeItem)
|
||||
* ->QI(nsIInterfaceRequestor)
|
||||
* ->GI(nsIWebNavigation)
|
||||
* ->GetCurrentURI();
|
||||
*
|
||||
* aDocShell is the docShell for the protected document.
|
||||
*/
|
||||
NS_IMETHODIMP
|
||||
nsCSPContext::PermitsAncestry(nsIDocShell* aDocShell, bool* outPermitsAncestry)
|
||||
{
|
||||
// For now, we allows permitsAncestry, this will be fixed in Bug 994320
|
||||
nsresult rv;
|
||||
|
||||
// Can't check ancestry without a docShell.
|
||||
if (aDocShell == nullptr) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
*outPermitsAncestry = true;
|
||||
|
||||
// extract the ancestry as an array
|
||||
nsCOMArray<nsIURI> ancestorsArray;
|
||||
|
||||
nsCOMPtr<nsIInterfaceRequestor> ir(do_QueryInterface(aDocShell));
|
||||
nsCOMPtr<nsIDocShellTreeItem> treeItem(do_GetInterface(ir));
|
||||
nsCOMPtr<nsIDocShellTreeItem> parentTreeItem;
|
||||
nsCOMPtr<nsIWebNavigation> webNav;
|
||||
nsCOMPtr<nsIURI> currentURI;
|
||||
nsCOMPtr<nsIURI> uriClone;
|
||||
|
||||
// iterate through each docShell parent item
|
||||
while (NS_SUCCEEDED(treeItem->GetParent(getter_AddRefs(parentTreeItem))) &&
|
||||
parentTreeItem != nullptr) {
|
||||
ir = do_QueryInterface(parentTreeItem);
|
||||
NS_ASSERTION(ir, "Could not QI docShellTreeItem to nsIInterfaceRequestor");
|
||||
|
||||
webNav = do_GetInterface(ir);
|
||||
NS_ENSURE_TRUE(webNav, NS_ERROR_FAILURE);
|
||||
|
||||
rv = webNav->GetCurrentURI(getter_AddRefs(currentURI));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (currentURI) {
|
||||
// stop when reaching chrome
|
||||
bool isChrome = false;
|
||||
rv = currentURI->SchemeIs("chrome", &isChrome);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (isChrome) { break; }
|
||||
|
||||
// delete the userpass from the URI.
|
||||
rv = currentURI->CloneIgnoringRef(getter_AddRefs(uriClone));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = uriClone->SetUserPass(EmptyCString());
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
#ifdef PR_LOGGING
|
||||
{
|
||||
nsAutoCString spec;
|
||||
uriClone->GetSpec(spec);
|
||||
CSPCONTEXTLOG(("nsCSPContext::PermitsAncestry, found ancestor: %s", spec.get()));
|
||||
}
|
||||
#endif
|
||||
ancestorsArray.AppendElement(uriClone);
|
||||
}
|
||||
|
||||
// next ancestor
|
||||
treeItem = parentTreeItem;
|
||||
}
|
||||
|
||||
nsAutoString violatedDirective;
|
||||
|
||||
// Now that we've got the ancestry chain in ancestorsArray, time to check
|
||||
// them against any CSP.
|
||||
for (uint32_t i = 0; i < mPolicies.Length(); i++) {
|
||||
for (uint32_t a = 0; a < ancestorsArray.Length(); a++) {
|
||||
// TODO(sid) the mapping from frame-ancestors context to TYPE_DOCUMENT is
|
||||
// forced. while this works for now, we will implement something in
|
||||
// bug 999656.
|
||||
#ifdef PR_LOGGING
|
||||
{
|
||||
nsAutoCString spec;
|
||||
ancestorsArray[a]->GetSpec(spec);
|
||||
CSPCONTEXTLOG(("nsCSPContext::PermitsAncestry, checking ancestor: %s", spec.get()));
|
||||
}
|
||||
#endif
|
||||
if (!mPolicies[i]->permits(nsIContentPolicy::TYPE_DOCUMENT,
|
||||
ancestorsArray[a],
|
||||
EmptyString(), // no nonce
|
||||
violatedDirective)) {
|
||||
// Policy is violated
|
||||
nsCOMPtr<nsIObserverService> observerService =
|
||||
mozilla::services::GetObserverService();
|
||||
NS_ENSURE_TRUE(observerService, NS_ERROR_NOT_AVAILABLE);
|
||||
|
||||
observerService->NotifyObservers(ancestorsArray[a],
|
||||
CSP_VIOLATION_TOPIC,
|
||||
violatedDirective.get());
|
||||
// TODO(sid) generate violation reports and remove NotifyObservers
|
||||
// call. (in bug 994322)
|
||||
// TODO(sid) implement logic for report-only (in bug 994322)
|
||||
*outPermitsAncestry = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#define nsCSPContext_h___
|
||||
|
||||
#include "nsCSPUtils.h"
|
||||
#include "nsDataHashtable.h"
|
||||
#include "nsIChannel.h"
|
||||
#include "nsIClassInfo.h"
|
||||
#include "nsIContentSecurityPolicy.h"
|
||||
|
@ -38,6 +39,7 @@ class nsCSPContext : public nsIContentSecurityPolicy
|
|||
|
||||
nsTArray<nsCSPPolicy*> mPolicies;
|
||||
nsCOMPtr<nsIURI> mSelfURI;
|
||||
nsDataHashtable<nsCStringHashKey, int16_t> mShouldLoadCache;
|
||||
};
|
||||
|
||||
#endif /* nsCSPContext_h___ */
|
||||
|
|
|
@ -636,6 +636,8 @@ CSP_DirectiveToContentType(enum CSPDirective aDir)
|
|||
case CSP_MEDIA_SRC: return nsIContentPolicy::TYPE_MEDIA;
|
||||
case CSP_OBJECT_SRC: return nsIContentPolicy::TYPE_OBJECT;
|
||||
case CSP_FRAME_SRC: return nsIContentPolicy::TYPE_SUBDOCUMENT;
|
||||
// TODO(sid): fix this mapping to be more precise (bug 999656)
|
||||
case CSP_FRAME_ANCESTORS: return nsIContentPolicy::TYPE_DOCUMENT;
|
||||
|
||||
// Fall through to error for the following Directives:
|
||||
case CSP_DEFAULT_SRC:
|
||||
|
|
|
@ -49,6 +49,7 @@ enum CSPDirective {
|
|||
CSP_FONT_SRC,
|
||||
CSP_CONNECT_SRC,
|
||||
CSP_REPORT_URI,
|
||||
CSP_FRAME_ANCESTORS,
|
||||
// CSP_LAST_DIRECTIVE_VALUE always needs to be the last element in the enum
|
||||
// because we use it to calculate the size for the char* array.
|
||||
CSP_LAST_DIRECTIVE_VALUE
|
||||
|
@ -65,6 +66,7 @@ static const char* CSPStrDirectives[] = {
|
|||
"font-src", // CSP_FONT_SRC
|
||||
"connect-src", // CSP_CONNECT_SRC
|
||||
"report-uri", // CSP_REPORT_URI
|
||||
"frame-ancestors" // CSP_FRAME_ANCESTORS
|
||||
};
|
||||
|
||||
inline const char* CSP_EnumToDirective(enum CSPDirective aDir)
|
||||
|
|
|
@ -196,6 +196,7 @@ const char kLoadAsData[] = "loadAsData";
|
|||
nsIXPConnect *nsContentUtils::sXPConnect;
|
||||
nsIScriptSecurityManager *nsContentUtils::sSecurityManager;
|
||||
nsIPrincipal *nsContentUtils::sSystemPrincipal;
|
||||
nsIPrincipal *nsContentUtils::sNullSubjectPrincipal;
|
||||
nsIParserService *nsContentUtils::sParserService = nullptr;
|
||||
nsNameSpaceManager *nsContentUtils::sNameSpaceManager;
|
||||
nsIIOService *nsContentUtils::sIOService;
|
||||
|
@ -379,6 +380,7 @@ nsContentUtils::Init()
|
|||
|
||||
sSecurityManager->GetSystemPrincipal(&sSystemPrincipal);
|
||||
MOZ_ASSERT(sSystemPrincipal);
|
||||
NS_ADDREF(sNullSubjectPrincipal = new nsNullPrincipal());
|
||||
|
||||
nsresult rv = CallGetService(NS_IOSERVICE_CONTRACTID, &sIOService);
|
||||
if (NS_FAILED(rv)) {
|
||||
|
@ -1436,6 +1438,7 @@ nsContentUtils::Shutdown()
|
|||
sXPConnect = nullptr;
|
||||
NS_IF_RELEASE(sSecurityManager);
|
||||
NS_IF_RELEASE(sSystemPrincipal);
|
||||
NS_IF_RELEASE(sNullSubjectPrincipal);
|
||||
NS_IF_RELEASE(sParserService);
|
||||
NS_IF_RELEASE(sIOService);
|
||||
NS_IF_RELEASE(sLineBreaker);
|
||||
|
@ -2322,9 +2325,33 @@ nsContentUtils::SubjectPrincipal()
|
|||
return GetSystemPrincipal();
|
||||
}
|
||||
|
||||
JSCompartment* compartment = js::GetContextCompartment(cx);
|
||||
MOZ_ASSERT(compartment);
|
||||
JSPrincipals* principals = JS_GetCompartmentPrincipals(compartment);
|
||||
JSCompartment *compartment = js::GetContextCompartment(cx);
|
||||
|
||||
// When an AutoJSAPI is instantiated, we are in a null compartment until the
|
||||
// first JSAutoCompartment, which is kind of a purgatory as far as permissions
|
||||
// go. It would be nice to just hard-abort if somebody does a security check
|
||||
// in this purgatory zone, but that would be too fragile, since it could be
|
||||
// triggered by random IsCallerChrome() checks 20-levels deep.
|
||||
//
|
||||
// So we want to return _something_ here - and definitely not the System
|
||||
// Principal, since that would make an AutoJSAPI a very dangerous thing to
|
||||
// instantiate.
|
||||
//
|
||||
// The natural thing to return is a null principal. Ideally, we'd return a
|
||||
// different null principal each time, to avoid any unexpected interactions
|
||||
// when the principal accidentally gets inherited somewhere. But
|
||||
// GetSubjectPrincipal doesn't return strong references, so there's no way to
|
||||
// sanely manage the lifetime of multiple null principals.
|
||||
//
|
||||
// So we use a singleton null principal. To avoid it being accidentally
|
||||
// inherited and becoming a "real" subject or object principal, we do a
|
||||
// release-mode assert during compartment creation against using this
|
||||
// principal on an actual global.
|
||||
if (!compartment) {
|
||||
return sNullSubjectPrincipal;
|
||||
}
|
||||
|
||||
JSPrincipals *principals = JS_GetCompartmentPrincipals(compartment);
|
||||
return nsJSPrincipals::get(principals);
|
||||
}
|
||||
|
||||
|
|
|
@ -667,6 +667,28 @@ nsresult TestGoodGeneratedPolicies() {
|
|||
"script-src http://policy-uri" },
|
||||
{ "img-src 'self'; ",
|
||||
"img-src http://www.selfuri.com" },
|
||||
{ "frame-ancestors foo-bar.com",
|
||||
"frame-ancestors http://foo-bar.com" },
|
||||
{ "frame-ancestors http://a.com",
|
||||
"frame-ancestors http://a.com" },
|
||||
{ "frame-ancestors 'self'",
|
||||
"frame-ancestors http://www.selfuri.com" },
|
||||
{ "frame-ancestors http://self.com:88",
|
||||
"frame-ancestors http://self.com:88" },
|
||||
{ "frame-ancestors http://a.b.c.d.e.f.g.h.i.j.k.l.x.com",
|
||||
"frame-ancestors http://a.b.c.d.e.f.g.h.i.j.k.l.x.com" },
|
||||
{ "frame-ancestors https://self.com:34",
|
||||
"frame-ancestors https://self.com:34" },
|
||||
{ "default-src 'none'; frame-ancestors 'self'",
|
||||
"default-src 'none'; frame-ancestors http://www.selfuri.com" },
|
||||
{ "frame-ancestors http://self:80",
|
||||
"frame-ancestors http://self:80" },
|
||||
{ "frame-ancestors http://self.com/bar",
|
||||
"frame-ancestors http://self.com" },
|
||||
{ "default-src 'self'; frame-ancestors 'self'",
|
||||
"default-src http://www.selfuri.com; frame-ancestors http://www.selfuri.com" },
|
||||
{ "frame-ancestors http://bar.com/foo.png",
|
||||
"frame-ancestors http://bar.com" },
|
||||
};
|
||||
|
||||
uint32_t policyCount = sizeof(policies) / sizeof(PolicyTest);
|
||||
|
|
|
@ -154,15 +154,6 @@ fuzzy(1,65536) random-if(gtk2Widget) fails-if(B2G) fuzzy-if(Android,9,65536) fai
|
|||
# random-if(B2G) from bug 983650
|
||||
fuzzy(1,65536) random-if(B2G) fuzzy-if(Android,9,65536) random-if(Android&&AndroidVersion<15) == webgl-color-alpha-test.html?colorVal=0.5&alphaVal=0.5&alpha&premult wrapper.html?colors-half-alpha.png
|
||||
|
||||
# Test over-bright premult:
|
||||
# random-if(B2G) from bug 983650
|
||||
# This test assumes that the compositor is able to correctly handle superluminant
|
||||
# pixels in a WebGL canvas with premultiplied alpha. This is not handled by
|
||||
# Skia's software blending code. Consequently, this test is random on
|
||||
# basic-layers when using skia. See bug 1004483.
|
||||
fuzzy(1,65536) random-if(B2G) fuzzy-if(Android,9,65536) random-if(Android&&AndroidVersion<15) random-if(skiaContent&&!layersGPUAccelerated) == webgl-color-alpha-test.html?colorVal=1.0&alphaVal=0.5&alpha&premult wrapper.html?colors-half-alpha.png
|
||||
|
||||
|
||||
# Check for hanging framebuffer bindings:
|
||||
random-if(Android&&AndroidVersion<15) == webgl-hanging-fb-test.html?__&________ wrapper.html?green.png
|
||||
random-if(Android&&AndroidVersion<15) == webgl-hanging-fb-test.html?aa&________ wrapper.html?green.png
|
||||
|
|
|
@ -6,43 +6,10 @@
|
|||
|
||||
#include "mozilla/dom/HTMLAllCollection.h"
|
||||
|
||||
#include "jsapi.h"
|
||||
#include "mozilla/HoldDropJSObjects.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsDOMClassInfo.h"
|
||||
#include "mozilla/dom/HTMLAllCollectionBinding.h"
|
||||
#include "mozilla/dom/Nullable.h"
|
||||
#include "mozilla/dom/UnionTypes.h"
|
||||
#include "nsHTMLDocument.h"
|
||||
#include "nsJSUtils.h"
|
||||
#include "nsWrapperCacheInlines.h"
|
||||
#include "xpcpublic.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
|
||||
class nsHTMLDocumentSH
|
||||
{
|
||||
public:
|
||||
static bool DocumentAllGetProperty(JSContext *cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id,
|
||||
JS::MutableHandle<JS::Value> vp);
|
||||
static bool DocumentAllNewResolve(JSContext *cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id,
|
||||
JS::MutableHandle<JSObject*> objp);
|
||||
static void ReleaseDocument(JSFreeOp *fop, JSObject *obj);
|
||||
static bool CallToGetPropMapper(JSContext *cx, unsigned argc, JS::Value *vp);
|
||||
};
|
||||
|
||||
const JSClass sHTMLDocumentAllClass = {
|
||||
"HTML document.all class",
|
||||
JSCLASS_HAS_PRIVATE | JSCLASS_PRIVATE_IS_NSISUPPORTS | JSCLASS_NEW_RESOLVE |
|
||||
JSCLASS_EMULATES_UNDEFINED,
|
||||
JS_PropertyStub, /* addProperty */
|
||||
JS_DeletePropertyStub, /* delProperty */
|
||||
nsHTMLDocumentSH::DocumentAllGetProperty, /* getProperty */
|
||||
JS_StrictPropertyStub, /* setProperty */
|
||||
JS_EnumerateStub,
|
||||
(JSResolveOp)nsHTMLDocumentSH::DocumentAllNewResolve,
|
||||
JS_ConvertStub,
|
||||
nsHTMLDocumentSH::ReleaseDocument,
|
||||
nsHTMLDocumentSH::CallToGetPropMapper
|
||||
};
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
@ -51,37 +18,31 @@ HTMLAllCollection::HTMLAllCollection(nsHTMLDocument* aDocument)
|
|||
: mDocument(aDocument)
|
||||
{
|
||||
MOZ_ASSERT(mDocument);
|
||||
mozilla::HoldJSObjects(this);
|
||||
SetIsDOMBinding();
|
||||
}
|
||||
|
||||
HTMLAllCollection::~HTMLAllCollection()
|
||||
{
|
||||
mObject = nullptr;
|
||||
mozilla::DropJSObjects(this);
|
||||
}
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(HTMLAllCollection, AddRef)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(HTMLAllCollection, Release)
|
||||
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(HTMLAllCollection,
|
||||
mDocument,
|
||||
mCollection,
|
||||
mNamedMap)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_CLASS(HTMLAllCollection)
|
||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(HTMLAllCollection)
|
||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(HTMLAllCollection)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(HTMLAllCollection)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocument)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCollection)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mNamedMap)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(HTMLAllCollection)
|
||||
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
|
||||
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(HTMLAllCollection)
|
||||
tmp->mObject = nullptr;
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocument)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mCollection)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mNamedMap)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(HTMLAllCollection)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mObject)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_END
|
||||
nsINode*
|
||||
HTMLAllCollection::GetParentObject() const
|
||||
{
|
||||
return mDocument;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
HTMLAllCollection::Length()
|
||||
|
@ -95,32 +56,6 @@ HTMLAllCollection::Item(uint32_t aIndex)
|
|||
return Collection()->Item(aIndex);
|
||||
}
|
||||
|
||||
JSObject*
|
||||
HTMLAllCollection::GetObject(JSContext* aCx, ErrorResult& aRv)
|
||||
{
|
||||
MOZ_ASSERT(aCx);
|
||||
|
||||
if (!mObject) {
|
||||
JS::Rooted<JSObject*> wrapper(aCx, mDocument->GetWrapper());
|
||||
MOZ_ASSERT(wrapper);
|
||||
|
||||
JSAutoCompartment ac(aCx, wrapper);
|
||||
JS::Rooted<JSObject*> global(aCx, JS_GetGlobalForObject(aCx, wrapper));
|
||||
mObject = JS_NewObject(aCx, &sHTMLDocumentAllClass, JS::NullPtr(), global);
|
||||
if (!mObject) {
|
||||
aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Make the JSObject hold a reference to the document.
|
||||
JS_SetPrivate(mObject, ToSupports(mDocument));
|
||||
NS_ADDREF(mDocument);
|
||||
}
|
||||
|
||||
JS::ExposeObjectToActiveJS(mObject);
|
||||
return mObject;
|
||||
}
|
||||
|
||||
nsContentList*
|
||||
HTMLAllCollection::Collection()
|
||||
{
|
||||
|
@ -186,197 +121,43 @@ HTMLAllCollection::GetDocumentAllList(const nsAString& aID)
|
|||
return docAllList;
|
||||
}
|
||||
|
||||
nsISupports*
|
||||
HTMLAllCollection::GetNamedItem(const nsAString& aID,
|
||||
nsWrapperCache** aCache)
|
||||
void
|
||||
HTMLAllCollection::NamedGetter(const nsAString& aID,
|
||||
bool& aFound,
|
||||
Nullable<OwningNodeOrHTMLCollection>& aResult)
|
||||
{
|
||||
nsContentList* docAllList = GetDocumentAllList(aID);
|
||||
if (!docAllList) {
|
||||
return nullptr;
|
||||
aFound = false;
|
||||
aResult.SetNull();
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if there are more than 1 entries. Do this by getting the second one
|
||||
// rather than the length since getting the length always requires walking
|
||||
// the entire document.
|
||||
|
||||
nsIContent* cont = docAllList->Item(1, true);
|
||||
if (cont) {
|
||||
*aCache = docAllList;
|
||||
return static_cast<nsINodeList*>(docAllList);
|
||||
if (docAllList->Item(1, true)) {
|
||||
aFound = true;
|
||||
aResult.SetValue().SetAsHTMLCollection() = docAllList;
|
||||
return;
|
||||
}
|
||||
|
||||
// There's only 0 or 1 items. Return the first one or null.
|
||||
*aCache = cont = docAllList->Item(0, true);
|
||||
return cont;
|
||||
if (nsIContent* node = docAllList->Item(0, true)) {
|
||||
aFound = true;
|
||||
aResult.SetValue().SetAsNode() = node;
|
||||
return;
|
||||
}
|
||||
|
||||
aFound = false;
|
||||
aResult.SetNull();
|
||||
}
|
||||
|
||||
JSObject*
|
||||
HTMLAllCollection::WrapObject(JSContext* aCx)
|
||||
{
|
||||
return HTMLAllCollectionBinding::Wrap(aCx, this);
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
static nsHTMLDocument*
|
||||
GetDocument(JSObject *obj)
|
||||
{
|
||||
MOZ_ASSERT(js::GetObjectJSClass(obj) == &sHTMLDocumentAllClass);
|
||||
return static_cast<nsHTMLDocument*>(
|
||||
static_cast<nsINode*>(JS_GetPrivate(obj)));
|
||||
}
|
||||
|
||||
bool
|
||||
nsHTMLDocumentSH::DocumentAllGetProperty(JSContext *cx, JS::Handle<JSObject*> obj_,
|
||||
JS::Handle<jsid> id, JS::MutableHandle<JS::Value> vp)
|
||||
{
|
||||
JS::Rooted<JSObject*> obj(cx, obj_);
|
||||
|
||||
// document.all.item and .namedItem get their value in the
|
||||
// newResolve hook, so nothing to do for those properties here. And
|
||||
// we need to return early to prevent <div id="item"> from shadowing
|
||||
// document.all.item(), etc.
|
||||
if (nsDOMClassInfo::sItem_id == id || nsDOMClassInfo::sNamedItem_id == id) {
|
||||
return true;
|
||||
}
|
||||
|
||||
JS::Rooted<JSObject*> proto(cx);
|
||||
while (js::GetObjectJSClass(obj) != &sHTMLDocumentAllClass) {
|
||||
if (!js::GetObjectProto(cx, obj, &proto)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!proto) {
|
||||
NS_ERROR("The JS engine lies!");
|
||||
return true;
|
||||
}
|
||||
|
||||
obj = proto;
|
||||
}
|
||||
|
||||
HTMLAllCollection* allCollection = GetDocument(obj)->All();
|
||||
nsISupports *result;
|
||||
nsWrapperCache *cache;
|
||||
|
||||
if (JSID_IS_STRING(id)) {
|
||||
if (nsDOMClassInfo::sLength_id == id) {
|
||||
// Make sure <div id="length"> doesn't shadow document.all.length.
|
||||
vp.setNumber(allCollection->Length());
|
||||
return true;
|
||||
}
|
||||
|
||||
// For all other strings, look for an element by id or name.
|
||||
nsDependentJSString str(id);
|
||||
result = allCollection->GetNamedItem(str, &cache);
|
||||
} else if (JSID_IS_INT(id) && JSID_TO_INT(id) >= 0) {
|
||||
// Map document.all[n] (where n is a number) to the n:th item in
|
||||
// the document.all node list.
|
||||
|
||||
nsIContent* node = allCollection->Item(SafeCast<uint32_t>(JSID_TO_INT(id)));
|
||||
|
||||
result = node;
|
||||
cache = node;
|
||||
} else {
|
||||
result = nullptr;
|
||||
}
|
||||
|
||||
if (result) {
|
||||
nsresult rv = nsContentUtils::WrapNative(cx, result, cache, vp);
|
||||
if (NS_FAILED(rv)) {
|
||||
xpc::Throw(cx, rv);
|
||||
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
vp.setUndefined();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
nsHTMLDocumentSH::DocumentAllNewResolve(JSContext *cx, JS::Handle<JSObject*> obj,
|
||||
JS::Handle<jsid> id,
|
||||
JS::MutableHandle<JSObject*> objp)
|
||||
{
|
||||
JS::Rooted<JS::Value> v(cx);
|
||||
|
||||
if (nsDOMClassInfo::sItem_id == id || nsDOMClassInfo::sNamedItem_id == id) {
|
||||
// Define the item() or namedItem() method.
|
||||
|
||||
JSFunction *fnc = ::JS_DefineFunctionById(cx, obj, id, CallToGetPropMapper,
|
||||
0, JSPROP_ENUMERATE);
|
||||
objp.set(obj);
|
||||
|
||||
return fnc != nullptr;
|
||||
}
|
||||
|
||||
if (nsDOMClassInfo::sLength_id == id) {
|
||||
// document.all.length. Any jsval other than undefined would do
|
||||
// here, all we need is to get into the code below that defines
|
||||
// this propery on obj, the rest happens in
|
||||
// DocumentAllGetProperty().
|
||||
|
||||
v = JSVAL_ONE;
|
||||
} else {
|
||||
if (!DocumentAllGetProperty(cx, obj, id, &v)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool ok = true;
|
||||
|
||||
if (v.get() != JSVAL_VOID) {
|
||||
ok = ::JS_DefinePropertyById(cx, obj, id, v, 0);
|
||||
objp.set(obj);
|
||||
}
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
void
|
||||
nsHTMLDocumentSH::ReleaseDocument(JSFreeOp *fop, JSObject *obj)
|
||||
{
|
||||
nsIHTMLDocument* doc = GetDocument(obj);
|
||||
if (doc) {
|
||||
nsContentUtils::DeferredFinalize(doc);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
nsHTMLDocumentSH::CallToGetPropMapper(JSContext *cx, unsigned argc, jsval *vp)
|
||||
{
|
||||
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
|
||||
// Handle document.all("foo") style access to document.all.
|
||||
|
||||
if (args.length() != 1) {
|
||||
// XXX: Should throw NS_ERROR_XPC_NOT_ENOUGH_ARGS for argc < 1,
|
||||
// and create a new NS_ERROR_XPC_TOO_MANY_ARGS for argc > 1? IE
|
||||
// accepts nothing other than one arg.
|
||||
xpc::Throw(cx, NS_ERROR_INVALID_ARG);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Convert all types to string.
|
||||
JS::Rooted<JSString*> str(cx, JS::ToString(cx, args[0]));
|
||||
if (!str) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// If we are called via document.all(id) instead of document.all.item(i) or
|
||||
// another method, use the document.all callee object as self.
|
||||
JS::Rooted<JSObject*> self(cx);
|
||||
if (args.calleev().isObject() &&
|
||||
JS_GetClass(&args.calleev().toObject()) == &sHTMLDocumentAllClass) {
|
||||
self = &args.calleev().toObject();
|
||||
} else {
|
||||
self = JS_THIS_OBJECT(cx, vp);
|
||||
if (!self)
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t length;
|
||||
JS::Anchor<JSString *> anchor(str);
|
||||
const jschar *chars = ::JS_GetStringCharsAndLength(cx, str, &length);
|
||||
if (!chars) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return ::JS_GetUCProperty(cx, self, chars, length, args.rval());
|
||||
}
|
||||
|
|
|
@ -7,49 +7,84 @@
|
|||
#ifndef mozilla_dom_HTMLAllCollection_h
|
||||
#define mozilla_dom_HTMLAllCollection_h
|
||||
|
||||
#include "js/RootingAPI.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "nsISupportsImpl.h"
|
||||
#include "nsRefPtrHashtable.h"
|
||||
#include "nsWrapperCache.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
class nsContentList;
|
||||
class nsHTMLDocument;
|
||||
class nsIContent;
|
||||
class nsWrapperCache;
|
||||
class nsINode;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class ErrorResult;
|
||||
|
||||
namespace dom {
|
||||
|
||||
class HTMLAllCollection
|
||||
class OwningNodeOrHTMLCollection;
|
||||
template<typename> class Nullable;
|
||||
|
||||
class HTMLAllCollection MOZ_FINAL : public nsISupports
|
||||
, public nsWrapperCache
|
||||
{
|
||||
public:
|
||||
HTMLAllCollection(nsHTMLDocument* aDocument);
|
||||
~HTMLAllCollection();
|
||||
|
||||
NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(HTMLAllCollection)
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(HTMLAllCollection)
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(HTMLAllCollection)
|
||||
|
||||
virtual JSObject* WrapObject(JSContext* aCx) MOZ_OVERRIDE;
|
||||
nsINode* GetParentObject() const;
|
||||
|
||||
uint32_t Length();
|
||||
nsIContent* Item(uint32_t aIndex);
|
||||
void Item(const nsAString& aName, Nullable<OwningNodeOrHTMLCollection>& aResult)
|
||||
{
|
||||
NamedItem(aName, aResult);
|
||||
}
|
||||
nsIContent* IndexedGetter(uint32_t aIndex, bool& aFound)
|
||||
{
|
||||
nsIContent* result = Item(aIndex);
|
||||
aFound = !!result;
|
||||
return result;
|
||||
}
|
||||
|
||||
JSObject* GetObject(JSContext* aCx, ErrorResult& aRv);
|
||||
|
||||
nsISupports* GetNamedItem(const nsAString& aID, nsWrapperCache** aCache);
|
||||
void NamedItem(const nsAString& aName,
|
||||
Nullable<OwningNodeOrHTMLCollection>& aResult)
|
||||
{
|
||||
bool found = false;
|
||||
NamedGetter(aName, found, aResult);
|
||||
}
|
||||
void NamedGetter(const nsAString& aName,
|
||||
bool& aFound,
|
||||
Nullable<OwningNodeOrHTMLCollection>& aResult);
|
||||
void GetSupportedNames(unsigned flags, nsTArray<nsString>& aNames)
|
||||
{
|
||||
}
|
||||
bool NameIsEnumerable(const nsAString& aName)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
void LegacyCall(JS::Handle<JS::Value>, const nsAString& aName,
|
||||
Nullable<OwningNodeOrHTMLCollection>& aResult)
|
||||
{
|
||||
NamedItem(aName, aResult);
|
||||
}
|
||||
|
||||
private:
|
||||
nsContentList* Collection();
|
||||
|
||||
/**
|
||||
* Returns the NodeList for document.all[aID], or null if there isn't one.
|
||||
* Returns the HTMLCollection for document.all[aID], or null if there isn't one.
|
||||
*/
|
||||
nsContentList* GetDocumentAllList(const nsAString& aID);
|
||||
|
||||
JS::Heap<JSObject*> mObject;
|
||||
nsRefPtr<nsHTMLDocument> mDocument;
|
||||
nsRefPtr<nsContentList> mCollection;
|
||||
nsRefPtrHashtable<nsStringHashKey, nsContentList> mNamedMap;
|
||||
|
|
|
@ -2564,12 +2564,6 @@ nsHTMLDocument::All()
|
|||
return mAll;
|
||||
}
|
||||
|
||||
JSObject*
|
||||
nsHTMLDocument::GetAll(JSContext* aCx, ErrorResult& aRv)
|
||||
{
|
||||
return All()->GetObject(aCx, aRv);
|
||||
}
|
||||
|
||||
static void
|
||||
NotifyEditableStateChange(nsINode *aNode, nsIDocument *aDocument)
|
||||
{
|
||||
|
|
|
@ -104,7 +104,6 @@ public:
|
|||
NS_DECL_NSIDOMHTMLDOCUMENT
|
||||
|
||||
mozilla::dom::HTMLAllCollection* All();
|
||||
JSObject* GetAll(JSContext* aCx, mozilla::ErrorResult& aRv);
|
||||
|
||||
nsISupports* ResolveName(const nsAString& aName, nsWrapperCache **aCache);
|
||||
|
||||
|
|
|
@ -78,16 +78,17 @@ public:
|
|||
int64_t aEndTime,
|
||||
int64_t aCurrentTime) = 0;
|
||||
|
||||
// Called to move the reader into idle/active state. When the reader is
|
||||
// Called to move the reader into idle state. When the reader is
|
||||
// created it is assumed to be active (i.e. not idle). When the media
|
||||
// element is paused and we don't need to decode any more data, the state
|
||||
// machine calls SetIdle() to inform the reader that its decoder won't be
|
||||
// needed for a while. When we need to decode data again, the state machine
|
||||
// calls SetActive() to activate the decoder. The reader can use these
|
||||
// notifications to enter/exit a low power state when the decoder isn't
|
||||
// needed, if desired. This is most useful on mobile.
|
||||
// needed for a while. The reader can use these notifications to enter
|
||||
// a low power state when the decoder isn't needed, if desired.
|
||||
// This is most useful on mobile.
|
||||
// Note: DecodeVideoFrame, DecodeAudioData, ReadMetadata and Seek should
|
||||
// activate the decoder if necessary. The state machine only needs to know
|
||||
// when to call SetIdle().
|
||||
virtual void SetIdle() { }
|
||||
virtual void SetActive() { }
|
||||
|
||||
// Tell the reader that the data decoded are not for direct playback, so it
|
||||
// can accept more files, in particular those which have more channels than
|
||||
|
|
|
@ -194,7 +194,6 @@ MediaDecoderStateMachine::MediaDecoderStateMachine(MediaDecoder* aDecoder,
|
|||
mAmpleAudioThresholdUsecs(AMPLE_AUDIO_USECS),
|
||||
mDispatchedAudioDecodeTask(false),
|
||||
mDispatchedVideoDecodeTask(false),
|
||||
mIsReaderIdle(false),
|
||||
mAudioCaptured(false),
|
||||
mTransportSeekable(true),
|
||||
mMediaSeekable(true),
|
||||
|
@ -573,7 +572,6 @@ MediaDecoderStateMachine::DecodeVideo()
|
|||
mDispatchedVideoDecodeTask = false;
|
||||
return;
|
||||
}
|
||||
EnsureActive();
|
||||
|
||||
// We don't want to consider skipping to the next keyframe if we've
|
||||
// only just started up the decode loop, so wait until we've decoded
|
||||
|
@ -667,7 +665,6 @@ MediaDecoderStateMachine::DecodeAudio()
|
|||
mDispatchedAudioDecodeTask = false;
|
||||
return;
|
||||
}
|
||||
EnsureActive();
|
||||
|
||||
// We don't want to consider skipping to the next keyframe if we've
|
||||
// only just started up the decode loop, so wait until we've decoded
|
||||
|
@ -1499,21 +1496,6 @@ MediaDecoderStateMachine::EnqueueDecodeMetadataTask()
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
MediaDecoderStateMachine::EnsureActive()
|
||||
{
|
||||
AssertCurrentThreadInMonitor();
|
||||
MOZ_ASSERT(OnDecodeThread());
|
||||
if (!mIsReaderIdle) {
|
||||
return;
|
||||
}
|
||||
mIsReaderIdle = false;
|
||||
{
|
||||
ReentrantMonitorAutoExit exitMon(mDecoder->GetReentrantMonitor());
|
||||
SetReaderActive();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MediaDecoderStateMachine::SetReaderIdle()
|
||||
{
|
||||
|
@ -1529,14 +1511,6 @@ MediaDecoderStateMachine::SetReaderIdle()
|
|||
mReader->SetIdle();
|
||||
}
|
||||
|
||||
void
|
||||
MediaDecoderStateMachine::SetReaderActive()
|
||||
{
|
||||
DECODER_LOG(PR_LOG_DEBUG, "SetReaderActive()");
|
||||
MOZ_ASSERT(OnDecodeThread());
|
||||
mReader->SetActive();
|
||||
}
|
||||
|
||||
void
|
||||
MediaDecoderStateMachine::DispatchDecodeTasksIfNeeded()
|
||||
{
|
||||
|
@ -1575,20 +1549,14 @@ MediaDecoderStateMachine::DispatchDecodeTasksIfNeeded()
|
|||
EnsureVideoDecodeTaskQueued();
|
||||
}
|
||||
|
||||
if (mIsReaderIdle == needIdle) {
|
||||
return;
|
||||
}
|
||||
mIsReaderIdle = needIdle;
|
||||
RefPtr<nsIRunnable> event;
|
||||
if (mIsReaderIdle) {
|
||||
event = NS_NewRunnableMethod(this, &MediaDecoderStateMachine::SetReaderIdle);
|
||||
} else {
|
||||
event = NS_NewRunnableMethod(this, &MediaDecoderStateMachine::SetReaderActive);
|
||||
}
|
||||
if (NS_FAILED(mDecodeTaskQueue->Dispatch(event.forget())) &&
|
||||
mState != DECODER_STATE_SHUTDOWN) {
|
||||
if (needIdle) {
|
||||
RefPtr<nsIRunnable> event = NS_NewRunnableMethod(
|
||||
this, &MediaDecoderStateMachine::SetReaderIdle);
|
||||
nsresult rv = mDecodeTaskQueue->Dispatch(event.forget());
|
||||
if (NS_FAILED(rv) && mState != DECODER_STATE_SHUTDOWN) {
|
||||
NS_WARNING("Failed to dispatch event to set decoder idle state");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
@ -1828,7 +1796,6 @@ nsresult MediaDecoderStateMachine::DecodeMetadata()
|
|||
if (mState != DECODER_STATE_DECODING_METADATA) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
EnsureActive();
|
||||
|
||||
nsresult res;
|
||||
MediaInfo info;
|
||||
|
@ -1930,7 +1897,6 @@ void MediaDecoderStateMachine::DecodeSeek()
|
|||
if (mState != DECODER_STATE_SEEKING) {
|
||||
return;
|
||||
}
|
||||
EnsureActive();
|
||||
|
||||
// During the seek, don't have a lock on the decoder state,
|
||||
// otherwise long seek operations can block the main thread.
|
||||
|
|
|
@ -565,11 +565,9 @@ protected:
|
|||
// The decoder monitor must be held.
|
||||
nsresult EnqueueDecodeSeekTask();
|
||||
|
||||
// Calls the reader's SetIdle(), with aIsIdle as parameter. This is only
|
||||
// called in a task dispatched to the decode task queue, don't call it
|
||||
// directly.
|
||||
// Calls the reader's SetIdle(). This is only called in a task dispatched to
|
||||
// the decode task queue, don't call it directly.
|
||||
void SetReaderIdle();
|
||||
void SetReaderActive();
|
||||
|
||||
// Re-evaluates the state and determines whether we need to dispatch
|
||||
// events to run the decode, or if not whether we should set the reader
|
||||
|
@ -577,11 +575,6 @@ protected:
|
|||
// The decoder monitor must be held.
|
||||
void DispatchDecodeTasksIfNeeded();
|
||||
|
||||
// Called before we do anything on the decode task queue to set the reader
|
||||
// as not idle if it was idle. This is called before we decode, seek, or
|
||||
// decode metadata (in case we were dormant or awaiting resources).
|
||||
void EnsureActive();
|
||||
|
||||
// Queries our state to see whether the decode has finished for all streams.
|
||||
// If so, we move into DECODER_STATE_COMPLETED and schedule the state machine
|
||||
// to run.
|
||||
|
@ -851,12 +844,6 @@ protected:
|
|||
// the video decode.
|
||||
bool mDispatchedVideoDecodeTask;
|
||||
|
||||
// True when the reader is initialized, but has been ordered "idle" by the
|
||||
// state machine. This happens when the MediaQueue's of decoded data are
|
||||
// "full" and playback is paused. The reader may choose to use the idle
|
||||
// notification to enter a low power state.
|
||||
bool mIsReaderIdle;
|
||||
|
||||
// If the video decode is falling behind the audio, we'll start dropping the
|
||||
// inter-frames up until the next keyframe which is at or before the current
|
||||
// playback position. skipToNextKeyframe is true if we're currently
|
||||
|
|
|
@ -147,7 +147,6 @@ private:
|
|||
mActiveVideoDecoder = i;
|
||||
MSE_DEBUG("%p MSR::DecodeVF switching to %d", this, mActiveVideoDecoder);
|
||||
|
||||
GetVideoReader()->SetActive();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -326,7 +325,6 @@ MediaSourceReader::CallDecoderInitialization()
|
|||
MediaDecoderReader* reader = decoder->GetReader();
|
||||
MSE_DEBUG("%p: Initializating subdecoder %p reader %p", this, decoder.get(), reader);
|
||||
|
||||
reader->SetActive();
|
||||
MediaInfo mi;
|
||||
nsAutoPtr<MetadataTags> tags; // TODO: Handle metadata.
|
||||
nsresult rv;
|
||||
|
@ -456,8 +454,6 @@ MediaSourceReader::ReadMetadata(MediaInfo* aInfo, MetadataTags** aTags)
|
|||
for (uint32_t i = 0; i < mDecoders.Length(); ++i) {
|
||||
MediaDecoderReader* reader = mDecoders[i]->GetReader();
|
||||
|
||||
reader->SetActive(); // XXX check where this should be called
|
||||
|
||||
MediaInfo mi = reader->GetMediaInfo();
|
||||
|
||||
if (mi.HasVideo() && !mInfo.HasVideo()) {
|
||||
|
|
|
@ -47,9 +47,6 @@ MediaOmxReader::MediaOmxReader(AbstractMediaDecoder *aDecoder)
|
|||
, mVideoSeekTimeUs(-1)
|
||||
, mAudioSeekTimeUs(-1)
|
||||
, mSkipCount(0)
|
||||
#ifdef DEBUG
|
||||
, mIsActive(true)
|
||||
#endif
|
||||
{
|
||||
#ifdef PR_LOGGING
|
||||
if (!gMediaDecoderLog) {
|
||||
|
@ -135,7 +132,7 @@ nsresult MediaOmxReader::ReadMetadata(MediaInfo* aInfo,
|
|||
MetadataTags** aTags)
|
||||
{
|
||||
NS_ASSERTION(mDecoder->OnDecodeThread(), "Should be on decode thread.");
|
||||
MOZ_ASSERT(mIsActive);
|
||||
EnsureActive();
|
||||
|
||||
*aTags = nullptr;
|
||||
|
||||
|
@ -211,7 +208,8 @@ nsresult MediaOmxReader::ReadMetadata(MediaInfo* aInfo,
|
|||
bool MediaOmxReader::DecodeVideoFrame(bool &aKeyframeSkip,
|
||||
int64_t aTimeThreshold)
|
||||
{
|
||||
MOZ_ASSERT(mIsActive);
|
||||
NS_ASSERTION(mDecoder->OnDecodeThread(), "Should be on decode thread.");
|
||||
EnsureActive();
|
||||
|
||||
// Record number of frames decoded and parsed. Automatically update the
|
||||
// stats counters using the AutoNotifyDecoded stack-based class.
|
||||
|
@ -341,7 +339,7 @@ void MediaOmxReader::NotifyDataArrived(const char* aBuffer, uint32_t aLength, in
|
|||
bool MediaOmxReader::DecodeAudioData()
|
||||
{
|
||||
NS_ASSERTION(mDecoder->OnDecodeThread(), "Should be on decode thread.");
|
||||
MOZ_ASSERT(mIsActive);
|
||||
EnsureActive();
|
||||
|
||||
// This is the approximate byte position in the stream.
|
||||
int64_t pos = mDecoder->GetResource()->Tell();
|
||||
|
@ -375,7 +373,7 @@ bool MediaOmxReader::DecodeAudioData()
|
|||
nsresult MediaOmxReader::Seek(int64_t aTarget, int64_t aStartTime, int64_t aEndTime, int64_t aCurrentTime)
|
||||
{
|
||||
NS_ASSERTION(mDecoder->OnDecodeThread(), "Should be on decode thread.");
|
||||
MOZ_ASSERT(mIsActive);
|
||||
EnsureActive();
|
||||
|
||||
ResetDecode();
|
||||
VideoFrameContainer* container = mDecoder->GetVideoFrameContainer();
|
||||
|
@ -410,19 +408,13 @@ static uint64_t BytesToTime(int64_t offset, uint64_t length, uint64_t durationUs
|
|||
}
|
||||
|
||||
void MediaOmxReader::SetIdle() {
|
||||
#ifdef DEBUG
|
||||
mIsActive = false;
|
||||
#endif
|
||||
if (!mOmxDecoder.get()) {
|
||||
return;
|
||||
}
|
||||
mOmxDecoder->Pause();
|
||||
}
|
||||
|
||||
void MediaOmxReader::SetActive() {
|
||||
#ifdef DEBUG
|
||||
mIsActive = true;
|
||||
#endif
|
||||
void MediaOmxReader::EnsureActive() {
|
||||
if (!mOmxDecoder.get()) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -49,6 +49,10 @@ protected:
|
|||
// information used for creating OMX decoder such as video/audio codec.
|
||||
virtual nsresult InitOmxDecoder();
|
||||
|
||||
// Called inside DecodeVideoFrame, DecodeAudioData, ReadMetadata and Seek
|
||||
// to activate the decoder automatically.
|
||||
virtual void EnsureActive();
|
||||
|
||||
public:
|
||||
MediaOmxReader(AbstractMediaDecoder* aDecoder);
|
||||
~MediaOmxReader();
|
||||
|
@ -83,7 +87,6 @@ public:
|
|||
virtual nsresult Seek(int64_t aTime, int64_t aStartTime, int64_t aEndTime, int64_t aCurrentTime);
|
||||
|
||||
virtual void SetIdle() MOZ_OVERRIDE;
|
||||
virtual void SetActive() MOZ_OVERRIDE;
|
||||
|
||||
void SetAudioChannel(dom::AudioChannel aAudioChannel) {
|
||||
mAudioChannel = aAudioChannel;
|
||||
|
@ -99,12 +102,6 @@ public:
|
|||
// ANDROID_VERSION < 19
|
||||
void CheckAudioOffload();
|
||||
#endif
|
||||
|
||||
private:
|
||||
// This flag is true when SetActive() has been called without a matching
|
||||
// SetIdle(). This is used to sanity check the SetIdle/SetActive calls, to
|
||||
// ensure SetActive has been called before a decode call.
|
||||
DebugOnly<bool> mIsActive;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -299,18 +299,6 @@ nsresult RtspOmxReader::Seek(int64_t aTime, int64_t aStartTime,
|
|||
return MediaOmxReader::Seek(aTime, aStartTime, aEndTime, aCurrentTime);
|
||||
}
|
||||
|
||||
nsresult
|
||||
RtspOmxReader::ReadMetadata(MediaInfo* aInfo,
|
||||
MetadataTags** aTags)
|
||||
{
|
||||
SetActive();
|
||||
|
||||
nsresult rv = MediaOmxReader::ReadMetadata(aInfo, aTags);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void RtspOmxReader::SetIdle() {
|
||||
// Call parent class to set OMXCodec idle.
|
||||
MediaOmxReader::SetIdle();
|
||||
|
@ -326,7 +314,7 @@ void RtspOmxReader::SetIdle() {
|
|||
}
|
||||
}
|
||||
|
||||
void RtspOmxReader::SetActive() {
|
||||
void RtspOmxReader::EnsureActive() {
|
||||
// Need to start RTSP streaming OMXCodec decoding.
|
||||
if (mRtspResource) {
|
||||
nsIStreamingProtocolController* controller =
|
||||
|
@ -338,7 +326,7 @@ void RtspOmxReader::SetActive() {
|
|||
}
|
||||
|
||||
// Call parent class to set OMXCodec active.
|
||||
MediaOmxReader::SetActive();
|
||||
MediaOmxReader::EnsureActive();
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -28,6 +28,7 @@ class RtspOmxReader : public MediaOmxReader
|
|||
protected:
|
||||
// Provide a Rtsp extractor.
|
||||
nsresult InitOmxDecoder() MOZ_FINAL MOZ_OVERRIDE;
|
||||
virtual void EnsureActive() MOZ_OVERRIDE;
|
||||
|
||||
public:
|
||||
RtspOmxReader(AbstractMediaDecoder* aDecoder)
|
||||
|
@ -44,9 +45,6 @@ public:
|
|||
MOZ_COUNT_DTOR(RtspOmxReader);
|
||||
}
|
||||
|
||||
virtual nsresult ReadMetadata(MediaInfo* aInfo,
|
||||
MetadataTags** aTags) MOZ_OVERRIDE;
|
||||
|
||||
// Implement a time-based seek instead of byte-based..
|
||||
virtual nsresult Seek(int64_t aTime, int64_t aStartTime, int64_t aEndTime,
|
||||
int64_t aCurrentTime) MOZ_FINAL MOZ_OVERRIDE;
|
||||
|
@ -66,7 +64,6 @@ public:
|
|||
}
|
||||
|
||||
virtual void SetIdle() MOZ_OVERRIDE;
|
||||
virtual void SetActive() MOZ_OVERRIDE;
|
||||
|
||||
private:
|
||||
// A pointer to RtspMediaResource for calling the Rtsp specific function.
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
#include "gfx2DGlue.h"
|
||||
#include "mozilla/dom/SVGAnimatedTransformList.h"
|
||||
#include "mozilla/dom/SVGGraphicsElementBinding.h"
|
||||
#include "mozilla/dom/SVGTransformableElement.h"
|
||||
#include "mozilla/dom/SVGMatrix.h"
|
||||
#include "mozilla/dom/SVGSVGElement.h"
|
||||
|
@ -182,7 +183,8 @@ SVGTransformableElement::GetFarthestViewportElement()
|
|||
}
|
||||
|
||||
already_AddRefed<SVGIRect>
|
||||
SVGTransformableElement::GetBBox(ErrorResult& rv)
|
||||
SVGTransformableElement::GetBBox(const SVGBoundingBoxOptions& aOptions,
|
||||
ErrorResult& rv)
|
||||
{
|
||||
nsIFrame* frame = GetPrimaryFrame(Flush_Layout);
|
||||
|
||||
|
@ -190,14 +192,37 @@ SVGTransformableElement::GetBBox(ErrorResult& rv)
|
|||
rv.Throw(NS_ERROR_FAILURE);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsISVGChildFrame* svgframe = do_QueryFrame(frame);
|
||||
if (!svgframe) {
|
||||
rv.Throw(NS_ERROR_NOT_IMPLEMENTED); // XXX: outer svg
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!NS_SVGNewGetBBoxEnabled()) {
|
||||
return NS_NewSVGRect(this, ToRect(nsSVGUtils::GetBBox(frame)));
|
||||
} else {
|
||||
uint32_t aFlags = 0;
|
||||
if (aOptions.mFill) {
|
||||
aFlags |= nsSVGUtils::eBBoxIncludeFill;
|
||||
}
|
||||
if (aOptions.mStroke) {
|
||||
aFlags |= nsSVGUtils::eBBoxIncludeStroke;
|
||||
}
|
||||
if (aOptions.mMarkers) {
|
||||
aFlags |= nsSVGUtils::eBBoxIncludeMarkers;
|
||||
}
|
||||
if (aOptions.mClipped) {
|
||||
aFlags |= nsSVGUtils::eBBoxIncludeClipped;
|
||||
}
|
||||
if (aFlags == 0) {
|
||||
return NS_NewSVGRect(this,0,0,0,0);
|
||||
}
|
||||
if (aFlags == nsSVGUtils::eBBoxIncludeMarkers ||
|
||||
aFlags == nsSVGUtils::eBBoxIncludeClipped) {
|
||||
aFlags |= nsSVGUtils::eBBoxIncludeFill;
|
||||
}
|
||||
return NS_NewSVGRect(this, ToRect(nsSVGUtils::GetBBox(frame, aFlags)));
|
||||
}
|
||||
}
|
||||
|
||||
already_AddRefed<SVGMatrix>
|
||||
|
|
|
@ -19,6 +19,7 @@ class SVGAnimatedTransformList;
|
|||
class SVGGraphicsElement;
|
||||
class SVGMatrix;
|
||||
class SVGIRect;
|
||||
class SVGBoundingBoxOptions;
|
||||
|
||||
class SVGTransformableElement : public nsSVGElement
|
||||
{
|
||||
|
@ -33,7 +34,8 @@ public:
|
|||
already_AddRefed<SVGAnimatedTransformList> Transform();
|
||||
nsSVGElement* GetNearestViewportElement();
|
||||
nsSVGElement* GetFarthestViewportElement();
|
||||
already_AddRefed<SVGIRect> GetBBox(ErrorResult& rv);
|
||||
already_AddRefed<SVGIRect> GetBBox(const SVGBoundingBoxOptions& aOptions,
|
||||
ErrorResult& rv);
|
||||
already_AddRefed<SVGMatrix> GetCTM();
|
||||
already_AddRefed<SVGMatrix> GetScreenCTM();
|
||||
already_AddRefed<SVGMatrix> GetTransformToElement(SVGGraphicsElement& aElement,
|
||||
|
|
|
@ -0,0 +1,299 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
viewBox="0 0 500 500" width="500px" height="500px">
|
||||
<defs>
|
||||
<clipPath id="rect01" clip-rule="evenodd" clipPathUnits="objectBoundingBox">
|
||||
<rect x="0" y="0" width="0.5" height="1.0"/>
|
||||
</clipPath>
|
||||
<clipPath id="rect02" clip-rule="evenodd" clipPathUnits="objectBoundingBox">
|
||||
<rect x="0.5" y="0" width="0.5" height="1.0"/>
|
||||
</clipPath>
|
||||
<clipPath id="rect03" clip-rule="evenodd" clipPathUnits="objectBoundingBox">
|
||||
<rect x="0.5" y="0" width="0.5" height="1.0"/>
|
||||
</clipPath>
|
||||
<clipPath id="rect04" clip-rule="evenodd" clipPathUnits="objectBoundingBox">
|
||||
<rect x="0" y="0" width="0.5" height="1.0"/>
|
||||
</clipPath>
|
||||
<clipPath id="rect05" clip-rule="evenodd">
|
||||
<rect x="0" y="60" width="10px" height="23px"/>
|
||||
</clipPath>
|
||||
<clipPath id="rect06" clip-rule="evenodd">
|
||||
<rect x="10" y="60" width="10px" height="23px"/>
|
||||
</clipPath>
|
||||
<clipPath id="rect4" clip-rule="evenodd">
|
||||
<rect x="200" y="200" width="200" height="200"/>
|
||||
</clipPath>
|
||||
<clipPath id="rect-none" clip-rule="evenodd">
|
||||
</clipPath>
|
||||
<clipPath id="rect5" clip-rule="evenodd">
|
||||
<rect x="0" y="0" width="100" height="100"/>
|
||||
</clipPath>
|
||||
<clipPath id="rect6" clip-rule="evenodd">
|
||||
<rect x="150" y="0" width="100" height="100"/>
|
||||
</clipPath>
|
||||
<clipPath id="rect7" clip-rule="evenodd">
|
||||
<rect x="0" y="100" width="100" height="100"/>
|
||||
</clipPath>
|
||||
<clipPath id="rect8" clip-rule="evenodd">
|
||||
<rect x="10" y="10" width="180" height="180"/>
|
||||
</clipPath>
|
||||
<clipPath id="rect9" clip-rule="evenodd">
|
||||
<rect x="100" y="100" width="200" height="200"/>
|
||||
</clipPath>
|
||||
|
||||
<clipPath id="circle1" clip-rule="evenodd">
|
||||
<circle cx="203" cy="203" r="150"/>
|
||||
</clipPath>
|
||||
<clipPath id="circle2" clip-rule="evenodd" clipPathUnits="objectBoundingBox">
|
||||
<circle cx="0.5" cy="0.5" r="0.25"/>
|
||||
</clipPath>
|
||||
<clipPath id="circle3" clip-rule="evenodd">
|
||||
<circle cx="100" cy="100" r="50"/>
|
||||
<circle cx="300" cy="300" r="50"/>
|
||||
</clipPath>
|
||||
|
||||
<clipPath id="circle4" clip-rule="evenodd">
|
||||
<circle cx="50" cy="50" r="50"/>
|
||||
</clipPath>
|
||||
<clipPath id="circle5" clip-rule="evenodd">
|
||||
<circle cx="150" cy="50" r="50"/>
|
||||
</clipPath>
|
||||
<clipPath id="circle6" clip-rule="evenodd">
|
||||
<circle cx="50" cy="200" r="50"/>
|
||||
</clipPath>
|
||||
<clipPath id="circle7" clip-rule="evenodd" clipPathUnits="objectBoundingBox">
|
||||
<circle cx="0.5" cy="0.5" r="0.5"/>
|
||||
</clipPath>
|
||||
|
||||
<clipPath id="circle8" clip-rule="evenodd" clipPathUnits="userSpaceOnUse">
|
||||
<circle cx="110" cy="20" r="90"/>
|
||||
</clipPath>
|
||||
|
||||
<clipPath id="circle9" clip-rule="evenodd" clipPathUnits="userSpaceOnUse">
|
||||
<circle cx="290" cy="20" r="90"/>
|
||||
</clipPath>
|
||||
|
||||
<clipPath id="circle10" clip-rule="evenodd" clipPathUnits="userSpaceOnUse">
|
||||
<circle cx="110" cy="200" r="90"/>
|
||||
</clipPath>
|
||||
|
||||
<clipPath id="circle11" clip-rule="evenodd">
|
||||
<circle cx="0" cy="0" r="150"/>
|
||||
</clipPath>
|
||||
|
||||
<clipPath id="star" clip-rule="evenodd">
|
||||
<path d="M400,25 L619,703 43,283 757,283 181,703 z" />
|
||||
</clipPath>
|
||||
|
||||
<marker id="m_atr" markerUnits="strokeWidth" markerWidth="3" markerHeight="3" viewBox="0 0 10 10" refX="5" refY="5">
|
||||
<polygon points="0,0 5,5 0,10 10,5" fill="red"/>
|
||||
</marker>
|
||||
|
||||
<switch>
|
||||
<rect id="rect-10" x="20" y="20" width="180" height="180" fill="blue" stroke="cyan" stroke-width="8"/>
|
||||
<rect id="rect-11" x="200" y="20" width="180" height="180" fill="lightgreen" stroke="none" />
|
||||
<rect id="rect-12" x="20" y="200" width="180" height="180" fill="darkcyan" stroke="none" />
|
||||
</switch>
|
||||
|
||||
<clipPath id="clipCircle1">
|
||||
<circle id="c1" cx="100" cy="100" r="50"/>
|
||||
</clipPath>
|
||||
|
||||
<clipPath id="clipCircle2">
|
||||
<circle id="c2" cx="150" cy="150" r="50"/>
|
||||
</clipPath>
|
||||
|
||||
<clipPath id="clipPath1">
|
||||
<path id="p1" d="M10 10l100 0 0 100 -100 0ZM50 50l40 0 0 40 -40 0Z" clip-rule="evenodd"/>
|
||||
</clipPath>
|
||||
|
||||
<!-- "If a valid 'clip-path' reference is placed on one of the children of a 'clipPath' element,
|
||||
then the given child element is clipped by the referenced clipping path before OR'ing the
|
||||
silhouette of the child element with the silhouettes of the other child elements." -->
|
||||
|
||||
<clipPath id="clipRects1">
|
||||
<rect x="50" y="30" width="25" height="100"/>
|
||||
<rect x="25" y="50" width="10" height="10" clip-path="url(#clipTwoCircles)"/>
|
||||
</clipPath>
|
||||
|
||||
<!-- Test use in a clipPath -->
|
||||
<clipPath id="clipTwoCircles">
|
||||
<use xlink:href="#c1"/>
|
||||
<use xlink:href="#c2"/>
|
||||
</clipPath>
|
||||
|
||||
<clipPath id="clipInClip1">
|
||||
<use xlink:href="#c2" clip-path="url(#clipCircle1)"/>
|
||||
<use xlink:href="#p1"/>
|
||||
</clipPath>
|
||||
|
||||
<clipPath id="clipOnClip1" clip-path="url(#clipCircle1)">
|
||||
<use xlink:href="#c2"/>
|
||||
<use xlink:href="#p1"/>
|
||||
</clipPath>
|
||||
|
||||
</defs>
|
||||
|
||||
<!-- text -->
|
||||
<text id="text1" font-size="20px" font-familiy="monospace" fill="red" x="0" y="50" clip-path="url('#rect01')">99</text>
|
||||
<text id="text2" font-size="20px" font-familiy="monospace" fill="blue" x="100" y="120" clip-path="url('#rect02')">99</text>
|
||||
<text id="text3" font-size="20px" font-familiy="monospace" clip-path="url('#rect03')" x="0" y="120">
|
||||
<tspan x="0" y="50" fill="red">99</tspan>
|
||||
</text>
|
||||
<text id="text4" font-size="20px" font-familiy="monospace" clip-path="url('#rect04')" x="0" y="120">
|
||||
<tspan x="100" y="120" fill="blue">99</tspan>
|
||||
</text>
|
||||
<text id="text5" font-size="20px" font-familiy="monospace" fill="red" x="0" y="80" clip-path="url('#rect05')">99</text>
|
||||
<text id="text6" font-size="20px" font-familiy="monospace" fill="blue" x="0" y="80" clip-path="url('#rect06')">99</text>
|
||||
|
||||
<!-- image -->
|
||||
<image id="image1" x="150" y="150" width="200" height="200" preserveApectRatio="none" clip="rect(200,300,300,200)"
|
||||
xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAAKXRFWHRDcmVhdGlvbiBUaW1lAJCFIDMwIDQgMjAxNCAwOToyODo0MyArMDkwMH73aTcAAAAHdElNRQfeBB4AHhEfV06+AAAACXBIWXMAAB7BAAAewQHDaVRTAAAABGdBTUEAALGPC/xhBQAAABlJREFUeNpjZPj/n4EUwESS6lENoxqGlAYASU8CHux7qQ4AAAAASUVORK5CYII="/>
|
||||
|
||||
<image id="image2" x="2" y="2" width="200" height="200" clip-path="url('#circle1')" preserveApectRatio="none"
|
||||
xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAAKXRFWHRDcmVhdGlvbiBUaW1lAJCFIDMwIDQgMjAxNCAwOToyODo0MyArMDkwMH73aTcAAAAHdElNRQfeBB4AHhEfV06+AAAACXBIWXMAAB7BAAAewQHDaVRTAAAABGdBTUEAALGPC/xhBQAAABlJREFUeNpjZPj/n4EUwESS6lENoxqGlAYASU8CHux7qQ4AAAAASUVORK5CYII="/>
|
||||
|
||||
<image id="image3" x="205" y="2" width="200" height="200" clip-path="url('#circle1')" preserveApectRatio="none"
|
||||
xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAAKXRFWHRDcmVhdGlvbiBUaW1lAJCFIDMwIDQgMjAxNCAwOToyODo0MyArMDkwMH73aTcAAAAHdElNRQfeBB4AHhEfV06+AAAACXBIWXMAAB7BAAAewQHDaVRTAAAABGdBTUEAALGPC/xhBQAAABlJREFUeNpjZPj/n4EUwESS6lENoxqGlAYASU8CHux7qQ4AAAAASUVORK5CYII="/>
|
||||
|
||||
<image id="image4" x="2" y="205" width="200" height="200" clip-path="url('#circle1')" preserveApectRatio="none"
|
||||
xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAAKXRFWHRDcmVhdGlvbiBUaW1lAJCFIDMwIDQgMjAxNCAwOToyODo0MyArMDkwMH73aTcAAAAHdElNRQfeBB4AHhEfV06+AAAACXBIWXMAAB7BAAAewQHDaVRTAAAABGdBTUEAALGPC/xhBQAAABlJREFUeNpjZPj/n4EUwESS6lENoxqGlAYASU8CHux7qQ4AAAAASUVORK5CYII="/>
|
||||
|
||||
<image id="image5" x="205" y="205" width="200" height="200" clip-path="url('#circle1')" preserveApectRatio="none"
|
||||
xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAAKXRFWHRDcmVhdGlvbiBUaW1lAJCFIDMwIDQgMjAxNCAwOToyODo0MyArMDkwMH73aTcAAAAHdElNRQfeBB4AHhEfV06+AAAACXBIWXMAAB7BAAAewQHDaVRTAAAABGdBTUEAALGPC/xhBQAAABlJREFUeNpjZPj/n4EUwESS6lENoxqGlAYASU8CHux7qQ4AAAAASUVORK5CYII="/>
|
||||
|
||||
<image id="image6" x="2" y="2" width="200" height="200" clip-path="url('#circle2')" preserveApectRatio="none"
|
||||
xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAAKXRFWHRDcmVhdGlvbiBUaW1lAJCFIDMwIDQgMjAxNCAwOToyODo0MyArMDkwMH73aTcAAAAHdElNRQfeBB4AHhEfV06+AAAACXBIWXMAAB7BAAAewQHDaVRTAAAABGdBTUEAALGPC/xhBQAAABlJREFUeNpjZPj/n4EUwESS6lENoxqGlAYASU8CHux7qQ4AAAAASUVORK5CYII="/>
|
||||
|
||||
<image id="image7" x="205" y="2" width="200" height="200" clip-path="url('#circle2')" preserveApectRatio="none"
|
||||
xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAAKXRFWHRDcmVhdGlvbiBUaW1lAJCFIDMwIDQgMjAxNCAwOToyODo0MyArMDkwMH73aTcAAAAHdElNRQfeBB4AHhEfV06+AAAACXBIWXMAAB7BAAAewQHDaVRTAAAABGdBTUEAALGPC/xhBQAAABlJREFUeNpjZPj/n4EUwESS6lENoxqGlAYASU8CHux7qQ4AAAAASUVORK5CYII="/>
|
||||
|
||||
<image id="image8" x="2" y="205" width="200" height="200" clip-path="url('#circle2')" preserveApectRatio="none"
|
||||
xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAAKXRFWHRDcmVhdGlvbiBUaW1lAJCFIDMwIDQgMjAxNCAwOToyODo0MyArMDkwMH73aTcAAAAHdElNRQfeBB4AHhEfV06+AAAACXBIWXMAAB7BAAAewQHDaVRTAAAABGdBTUEAALGPC/xhBQAAABlJREFUeNpjZPj/n4EUwESS6lENoxqGlAYASU8CHux7qQ4AAAAASUVORK5CYII="/>
|
||||
|
||||
<image id="image9" x="205" y="205" width="200" height="200" clip-path="url('#circle2')" preserveApectRatio="none"
|
||||
xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAAKXRFWHRDcmVhdGlvbiBUaW1lAJCFIDMwIDQgMjAxNCAwOToyODo0MyArMDkwMH73aTcAAAAHdElNRQfeBB4AHhEfV06+AAAACXBIWXMAAB7BAAAewQHDaVRTAAAABGdBTUEAALGPC/xhBQAAABlJREFUeNpjZPj/n4EUwESS6lENoxqGlAYASU8CHux7qQ4AAAAASUVORK5CYII="/>
|
||||
|
||||
<image id="image10" x="0" y="0" width="400" height="400" clip-path="url('#rect4')"
|
||||
xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAAKXRFWHRDcmVhdGlvbiBUaW1lAJCFIDMwIDQgMjAxNCAwOToyODo0MyArMDkwMH73aTcAAAAHdElNRQfeBB4AHhEfV06+AAAACXBIWXMAAB7BAAAewQHDaVRTAAAABGdBTUEAALGPC/xhBQAAABlJREFUeNpjZPj/n4EUwESS6lENoxqGlAYASU8CHux7qQ4AAAAASUVORK5CYII="/>
|
||||
|
||||
<image id="image11" x="0" y="0" width="400" height="400" clip-path="url('#rect-none')"
|
||||
xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAAKXRFWHRDcmVhdGlvbiBUaW1lAJCFIDMwIDQgMjAxNCAwOToyODo0MyArMDkwMH73aTcAAAAHdElNRQfeBB4AHhEfV06+AAAACXBIWXMAAB7BAAAewQHDaVRTAAAABGdBTUEAALGPC/xhBQAAABlJREFUeNpjZPj/n4EUwESS6lENoxqGlAYASU8CHux7qQ4AAAAASUVORK5CYII="/>
|
||||
|
||||
<image id="image12" x="25" y="43" width="768" height="768" clip-path="url('#star')" preserveApectRatio="none"
|
||||
xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAAKXRFWHRDcmVhdGlvbiBUaW1lAJCFIDMwIDQgMjAxNCAwOToyODo0MyArMDkwMH73aTcAAAAHdElNRQfeBB4AHhEfV06+AAAACXBIWXMAAB7BAAAewQHDaVRTAAAABGdBTUEAALGPC/xhBQAAABlJREFUeNpjZPj/n4EUwESS6lENoxqGlAYASU8CHux7qQ4AAAAASUVORK5CYII="/>
|
||||
|
||||
<image id="image13" x="0" y="0" width="400" height="400" clip-path="url('#circle3')"
|
||||
xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAAKXRFWHRDcmVhdGlvbiBUaW1lAJCFIDMwIDQgMjAxNCAwOToyODo0MyArMDkwMH73aTcAAAAHdElNRQfeBB4AHhEfV06+AAAACXBIWXMAAB7BAAAewQHDaVRTAAAABGdBTUEAALGPC/xhBQAAABlJREFUeNpjZPj/n4EUwESS6lENoxqGlAYASU8CHux7qQ4AAAAASUVORK5CYII="/>
|
||||
|
||||
<image id="image14" x="0" y="0" width="400" height="400" clip-path="url('#m_atr')"
|
||||
xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAAKXRFWHRDcmVhdGlvbiBUaW1lAJCFIDMwIDQgMjAxNCAwOToyODo0MyArMDkwMH73aTcAAAAHdElNRQfeBB4AHhEfV06+AAAACXBIWXMAAB7BAAAewQHDaVRTAAAABGdBTUEAALGPC/xhBQAAABlJREFUeNpjZPj/n4EUwESS6lENoxqGlAYASU8CHux7qQ4AAAAASUVORK5CYII="/>
|
||||
|
||||
<!-- path -->
|
||||
<path id="path1" d="M10,50 L25,100 H110 V50 Q60,0 10,50" stroke="black" stroke-width="8" stroke-miterlimit="1" stroke-linejoin="miter" fill="lightcyan" marker-mid="url(#m_atr)"/>
|
||||
<path id="path2" d="M160,50 L175,100 H260 V50 Q210,0 160,50" stroke="black" stroke-width="8" stroke-linejoin="bevel" fill="lightcyan" marker-mid="url(#m_atr)"/>
|
||||
<path id="path3" d="M10,150 L25,200 H110 V150 Q60,100 10,150" stroke="black" stroke-width="8" stroke-linejoin="round" fill="lightcyan" marker-mid="url(#m_atr)"/>
|
||||
|
||||
|
||||
<path id="path4" d="M10,50 L25,100 H110 V50 Q60,0 10,50" stroke="black" stroke-width="8" stroke-miterlimit="1" stroke-linejoin="miter" fill="lightcyan"
|
||||
marker-mid="url(#m_atr)" clip-path="url(#circle4)"/>
|
||||
|
||||
<path id="path5" d="M160,50 L175,100 H260 V50 Q210,0 160,50" stroke="black" stroke-width="8" stroke-linejoin="bevel" fill="lightcyan"
|
||||
marker-mid="url(#m_atr)" clip-path="url(#circle5)"/>
|
||||
|
||||
<path id="path6" d="M10,150 L25,200 H110 V150 Q60,100 10,150" stroke="black" stroke-width="8" stroke-linejoin="round" fill="lightcyan"
|
||||
marker-mid="url(#m_atr)" clip-path="url(#circle6)"/>
|
||||
|
||||
<path id="path7" d="M10,50 L25,100 H110 V50 Q60,0 10,50"
|
||||
stroke="black" stroke-width="8" stroke-miterlimit="1" stroke-linejoin="miter" fill="lightcyan"
|
||||
clip-path="url('#rect5')" marker-mid="url(#m_atr)"/>
|
||||
|
||||
<path id="path8" d="M160,50 L175,100 H260 V50 Q210,0 160,50"
|
||||
stroke="black" stroke-width="8" stroke-linejoin="bevel" fill="lightcyan"
|
||||
clip-path="url('#rect6')" marker-mid="url(#m_atr)"/>
|
||||
|
||||
<path id="path9" d="M10,150 L25,200 H110 V150 Q60,100 10,150"
|
||||
stroke="black" stroke-width="8" stroke-linejoin="round" fill="lightcyan"
|
||||
clip-path="url('#rect7')" marker-mid="url(#m_atr)"/>
|
||||
|
||||
<path id="path10" d="M10,50 L25,100 H110 V50 Q60,0 10,50"
|
||||
stroke="black" stroke-width="8" stroke-miterlimit="1" stroke-linejoin="miter" fill="lightcyan"
|
||||
clip-path="url('#circle7')" marker-mid="url(#m_atr)"/>
|
||||
|
||||
<path id="path11" d="M160,50 L175,100 H260 V50 Q210,0 160,50"
|
||||
stroke="black" stroke-width="8" stroke-linejoin="bevel" fill="lightcyan"
|
||||
clip-path="url('#circle7')" marker-mid="url(#m_atr)"/>
|
||||
|
||||
<path id="path12" d="M10,150 L25,200 H110 V150 Q60,100 10,150"
|
||||
stroke="black" stroke-width="8" stroke-linejoin="round" fill="lightcyan"
|
||||
clip-path="url('#circle7')" marker-mid="url(#m_atr)"/>
|
||||
|
||||
<!-- use -->
|
||||
<use id="use1" xlink:href="#rect-10" x="50" y="50" clip-path="url('#circle8')"/>
|
||||
<use id="use2" xlink:href="#rect-11" x="50" y="50" clip-path="url('#circle9')"/>
|
||||
<use id="use3" xlink:href="#rect-12" x="50" y="50" clip-path="url('#circle10')"/>
|
||||
|
||||
<use id="use4" xlink:href="#rect-10" x="2" y="2" width="200" height="200" clip-path="url('#circle11')"/>
|
||||
<use id="use5" xlink:href="#rect-10" x="205" y="2" width="200" height="200" clip-path="url('#circle11')"/>
|
||||
<use id="use6" xlink:href="#rect-10" x="2" y="205" width="200" height="200" clip-path="url('#circle11')"/>
|
||||
<use id="use7" xlink:href="#rect-10" x="205" y="205" width="200" height="200" clip-path="url('#circle11')"/>
|
||||
|
||||
<use id="use8" xlink:href="#rect-10" x="50" y="50" clip-path="url('#m_atr')"/>
|
||||
|
||||
<!-- foreignObject -->
|
||||
<foreignObject id="fo1" x="2" y="2" width="200" height="200" clip-path="url('#circle1')" clip="rect(2,102,102,2)">
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" style="background-color:pink;width:100%;height:100%;">
|
||||
There are issues of dynamic loading required for tiling. Accroding to 'postpone' attribute of Resource Priorities, the dynamic loading is controlled by positional relation with bounding box of embedded contents and container's viewport. However, each bounding boxes of embedded contents should be whole earth basically when this method is used. (green part on Example) Tiling is impossible unless this situation is changed.
|
||||
</div>
|
||||
</foreignObject>
|
||||
<foreignObject id="fo2" x="205" y="2" width="200" height="200" clip-path="url('#circle1')" >
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" style="background-color:pink;width:100%;height:100%;">
|
||||
There are issues of dynamic loading required for tiling. Accroding to 'postpone' attribute of Resource Priorities, the dynamic loading is controlled by positional relation with bounding box of embedded contents and container's viewport. However, each bounding boxes of embedded contents should be whole earth basically when this method is used. (green part on Example) Tiling is impossible unless this situation is changed.
|
||||
</div>
|
||||
</foreignObject>
|
||||
<foreignObject id="fo3" x="2" y="205" width="200" height="200" clip-path="url('#circle1')" >
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" style="background-color:pink;width:100%;height:100%;">
|
||||
There are issues of dynamic loading required for tiling. Accroding to 'postpone' attribute of Resource Priorities, the dynamic loading is controlled by positional relation with bounding box of embedded contents and container's viewport. However, each bounding boxes of embedded contents should be whole earth basically when this method is used. (green part on Example) Tiling is impossible unless this situation is changed.
|
||||
</div>
|
||||
</foreignObject>
|
||||
<foreignObject id="fo4" x="205" y="205" width="200" height="200" clip-path="url('#circle1')" clip="rect(2,102,102,2)">
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" style="background-color:pink;width:100%;height:100%;">
|
||||
There are issues of dynamic loading required for tiling. Accroding to 'postpone' attribute of Resource Priorities, the dynamic loading is controlled by positional relation with bounding box of embedded contents and container's viewport. However, each bounding boxes of embedded contents should be whole earth basically when this method is used. (green part on Example) Tiling is impossible unless this situation is changed.
|
||||
</div>
|
||||
</foreignObject>
|
||||
|
||||
<foreignObject id="fo5" x="250" y="250" width="200" height="200" clip-path="url('#rect8')">
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" style="background-color:pink;width:100%;height:100%;">
|
||||
There are issues of dynamic loading required for tiling. Accroding to 'postpone' attribute of Resource Priorities, the dynamic loading is controlled by positional relation with bounding box of embedded contents and container's viewport. However, each bounding boxes of embedded contents should be whole earth basically when this method is used. (green part on Example) Tiling is impossible unless this situation is changed.
|
||||
</div>
|
||||
</foreignObject>
|
||||
|
||||
<foreignObject id="fo6" x="0" y="0" width="200" height="200" clip-path="url('#rect9')">
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" style="background-color:pink;width:100%;height:100%;">
|
||||
There are issues of dynamic loading required for tiling. Accroding to 'postpone' attribute of Resource Priorities, the dynamic loading is controlled by positional relation with bounding box of embedded contents and container's viewport. However, each bounding boxes of embedded contents should be whole earth basically when this method is used. (green part on Example) Tiling is impossible unless this situation is changed.
|
||||
</div>
|
||||
</foreignObject>
|
||||
|
||||
<foreignObject id="fo7" x="0" y="0" width="200" height="200" clip-path="url('#rect8')">
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" style="background-color:pink;width:100%;height:100%;">
|
||||
There are issues of dynamic loading required for tiling. Accroding to 'postpone' attribute of Resource Priorities, the dynamic loading is controlled by positional relation with bounding box of embedded contents and container's viewport. However, each bounding boxes of embedded contents should be whole earth basically when this method is used. (green part on Example) Tiling is impossible unless this situation is changed.
|
||||
</div>
|
||||
</foreignObject>
|
||||
|
||||
<foreignObject id="fo8" x="0" y="0" width="200" height="200" clip-path="url('#m_atr')">
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" style="background-color:pink;width:100%;height:100%;">
|
||||
There are issues of dynamic loading required for tiling. Accroding to 'postpone' attribute of Resource Priorities, the dynamic loading is controlled by positional relation with bounding box of embedded contents and container's viewport. However, each bounding boxes of embedded contents should be whole earth basically when this method is used. (green part on Example) Tiling is impossible unless this situation is changed.
|
||||
</div>
|
||||
</foreignObject>
|
||||
|
||||
<!-- -->
|
||||
<rect id="rect-1" width="200" height="200" fill="blue" clip-path="url(#clipInClip1)"/>
|
||||
<rect id="rect-2" width="200" height="200" fill="blue" clip-path="url(#clipRects1)"/>
|
||||
<rect id="rect-3" width="300" height="300" fill="blue" clip-path="url(#clipOnClip1)"/>
|
||||
|
||||
<g clip-path="url(#clipCircle1)" id="g1">
|
||||
<use xlink:href="#c2" fill="red"/>
|
||||
<use xlink:href="#p1" fill="red" fill-rule="evenodd"/>
|
||||
</g>
|
||||
|
||||
</svg>
|
После Ширина: | Высота: | Размер: 20 KiB |
|
@ -9,6 +9,7 @@ support-files =
|
|||
animated-svg-image-helper.svg
|
||||
bbox-helper.svg
|
||||
bounds-helper.svg
|
||||
getBBox-method-helper.svg
|
||||
dataTypes-helper.svg
|
||||
fragments-helper.svg
|
||||
getCTM-helper.svg
|
||||
|
@ -34,6 +35,7 @@ support-files =
|
|||
[test_bbox.xhtml]
|
||||
[test_bounds.html]
|
||||
[test_bug872812.html]
|
||||
[test_getBBox-method.html]
|
||||
[test_dataTypes.html]
|
||||
[test_dataTypesModEvents.html]
|
||||
[test_fragments.html]
|
||||
|
|
|
@ -0,0 +1,249 @@
|
|||
<!DOCTYPE HTML>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=999964
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<title>Test case for Bug 999964</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=999964">Mozilla Bug 999964</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none"></div>
|
||||
|
||||
<iframe id="svg" src="getBBox-method-helper.svg"></iframe>
|
||||
|
||||
<pre id="test">
|
||||
<script class="testbody" type="application/javascript">
|
||||
|
||||
/** Test case for Bug 999964 **/
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
function run()
|
||||
{
|
||||
var flag = SpecialPowers.getBoolPref("svg.new-getBBox.enabled");
|
||||
if (!flag) {
|
||||
ok(!flag, "skip test for bug999964.");
|
||||
SimpleTest.finish();
|
||||
return;
|
||||
}
|
||||
|
||||
var doc = $("svg").contentDocument;
|
||||
|
||||
function isFuzzy(a, b, error, name)
|
||||
{
|
||||
ok(!(Math.abs(a - b) > error), name, "got " + a + ", expected " + b + " (within " + error + ")");
|
||||
}
|
||||
|
||||
function getBBox(id, opt) {
|
||||
return doc.getElementById(id).getBBox(opt);
|
||||
}
|
||||
|
||||
function checkBBox(id, opt, x, y, width, height, error) {
|
||||
var bbox = getBBox(id, opt);
|
||||
isFuzzy(bbox.x, x, error, id + ".getBBox().x");
|
||||
isFuzzy(bbox.y, y, error, id + ".getBBox().y");
|
||||
isFuzzy(bbox.width, width, error, id + ".getBBox().width");
|
||||
isFuzzy(bbox.height, height, error, id + ".getBBox().height");
|
||||
}
|
||||
|
||||
function compareBBox1(id1, id2) {
|
||||
var bbox1 = getBBox(id1);
|
||||
var bbox2 = getBBox(id2);
|
||||
is(bbox1.x, bbox2.x, id1 + ".getBBox().x");
|
||||
is(bbox1.y, bbox2.y, id1 + ".getBBox().y");
|
||||
isFuzzy(bbox1.width, bbox2.width, 0.0002, id1 + ".getBBox().width");
|
||||
isFuzzy(bbox1.height, bbox2.height, 0.0001, id1 + ".getBBox().height");
|
||||
}
|
||||
|
||||
function compareBBox2(id1, id2) {
|
||||
// without 'x'
|
||||
var bbox1 = getBBox(id1);
|
||||
var bbox2 = getBBox(id2);
|
||||
is(bbox1.y, bbox2.y, id1 + ".getBBox().y");
|
||||
isFuzzy(bbox1.width, bbox2.width, 0.0002, id1 + ".getBBox().width");
|
||||
isFuzzy(bbox1.height, bbox2.height, 0.0001, id1 + ".getBBox().height");
|
||||
}
|
||||
|
||||
var opt = { fill: true, stroke: true, markers: true, clipped: true };
|
||||
|
||||
// <text>
|
||||
// fill
|
||||
opt = { fill: true, stroke: false, markers: false, clipped: false };
|
||||
compareBBox1("text1","text3");
|
||||
compareBBox1("text2","text4");
|
||||
compareBBox1("text5","text6");
|
||||
// all
|
||||
opt = { fill: true, stroke: true, markers: true, clipped: true };
|
||||
compareBBox2("text1","text3");
|
||||
compareBBox2("text2","text4");
|
||||
compareBBox2("text5","text6");
|
||||
// clipped
|
||||
opt = { fill: false, stroke: false, markers: false, clipped: true };
|
||||
compareBBox2("text1","text3");
|
||||
compareBBox2("text2","text4");
|
||||
compareBBox2("text5","text6");
|
||||
|
||||
// <image>
|
||||
opt = { fill: true, stroke: true, markers: true, clipped: true };
|
||||
checkBBox("image1", opt, 250, 250, 100, 100);
|
||||
checkBBox("image2", opt, 53, 53, 149, 149);
|
||||
checkBBox("image3", opt, 205, 53, 148, 149);
|
||||
checkBBox("image4", opt, 53, 205, 149, 148);
|
||||
checkBBox("image5", opt, 205, 205, 148, 148);
|
||||
checkBBox("image6", opt, 52, 52, 100, 100);
|
||||
checkBBox("image7", opt, 255, 52, 100, 100);
|
||||
checkBBox("image8", opt, 52, 255, 100, 100);
|
||||
checkBBox("image9", opt, 255, 255, 100, 100);
|
||||
checkBBox("image10", opt, 200, 200, 200, 200);
|
||||
checkBBox("image11", opt, 0, 0, 0, 0);
|
||||
checkBBox("image12", opt, 43, 43, 714, 660);
|
||||
checkBBox("image13", opt, 50, 50, 300, 300);
|
||||
checkBBox("image14", opt, 0, 0, 0, 0);
|
||||
|
||||
opt = { fill: true, stroke: false, markers: false, clipped: false };
|
||||
checkBBox("image1", opt, 150,150,200,200, 0);
|
||||
checkBBox("image2", opt, 2,2,200,200, 0);
|
||||
checkBBox("image3", opt, 205,2,200,200, 0);
|
||||
checkBBox("image4", opt, 2,205,200,200, 0);
|
||||
checkBBox("image5", opt, 205,205,200,200, 0);
|
||||
checkBBox("image6", opt, 2,2,200,200, 0);
|
||||
checkBBox("image7", opt, 205,2,200,200, 0);
|
||||
checkBBox("image8", opt, 2,205,200,200, 0);
|
||||
checkBBox("image9", opt, 205,205,200,200, 0);
|
||||
checkBBox("image10", opt, 0,0,400,400, 0);
|
||||
checkBBox("image11", opt, 0,0,400,400, 0);
|
||||
checkBBox("image12", opt, 25,43,768,768, 0);
|
||||
checkBBox("image13", opt, 0,0,400,400, 0);
|
||||
|
||||
// <path>
|
||||
opt = { fill: true, stroke: true, markers: true, clipped: true };
|
||||
checkBBox("path1", opt, 2,17,120,95, 0);
|
||||
checkBBox("path2", opt, 156,21,116,91, 0);
|
||||
checkBBox("path3", opt, 6,121,116,91, 0);
|
||||
checkBBox("path4", opt, 2,17,98,83, 0);
|
||||
checkBBox("path5", opt, 156,21,44,79, 0);
|
||||
checkBBox("path6", opt, 6,150,94,62, 0);
|
||||
checkBBox("path7", opt, 2,17,98,83, 0);
|
||||
checkBBox("path8", opt, 156,21,94,79, 0);
|
||||
checkBBox("path9", opt, 6,121,94,79, 0);
|
||||
checkBBox("path10", opt, 10,25,100,75, 0);
|
||||
checkBBox("path11", opt, 160,25,100,75, 0);
|
||||
checkBBox("path12", opt, 10,125,100,75, 0);
|
||||
|
||||
opt = { fill: true, stroke: false, markers: false, clipped: true };
|
||||
checkBBox("path1", opt, 10,25,100,75, 0);
|
||||
checkBBox("path2", opt, 160,25,100,75, 0);
|
||||
checkBBox("path3", opt, 10,125,100,75, 0);
|
||||
checkBBox("path4", opt, 10,25,90,75, 0);
|
||||
checkBBox("path5", opt, 160,25,40,75, 0);
|
||||
checkBBox("path6", opt, 10,150,90,50, 0);
|
||||
checkBBox("path7", opt, 10,25,90,75, 0);
|
||||
checkBBox("path8", opt, 160,25,90,75, 0);
|
||||
checkBBox("path9", opt, 10,125,90,75, 0);
|
||||
checkBBox("path10", opt, 10,25,100,75, 0);
|
||||
checkBBox("path11", opt, 160,25,100,75, 0);
|
||||
checkBBox("path12", opt, 10,125,100,75, 0);
|
||||
|
||||
opt = { fill: true, stroke: false, markers: false, clipped: false };
|
||||
checkBBox("path1", opt, 10,25,100,75, 0);
|
||||
checkBBox("path2", opt, 160,25,100,75, 0);
|
||||
checkBBox("path3", opt, 10,125,100,75, 0);
|
||||
checkBBox("path4", opt, 10,25,100,75, 0);
|
||||
checkBBox("path5", opt, 160,25,100,75, 0);
|
||||
checkBBox("path6", opt, 10,125,100,75, 0);
|
||||
checkBBox("path7", opt, 10,25,100,75, 0);
|
||||
checkBBox("path8", opt, 160,25,100,75, 0);
|
||||
checkBBox("path9", opt, 10,125,100,75, 0);
|
||||
checkBBox("path10", opt, 10,25,100,75, 0);
|
||||
checkBBox("path11", opt, 160,25,100,75, 0);
|
||||
checkBBox("path12", opt, 10,125,100,75, 0);
|
||||
|
||||
opt = { fill: false, stroke: true, markers: false, clipped: false };
|
||||
checkBBox("path1", opt, 2,17,116,91, 0);
|
||||
checkBBox("path2", opt, 156,21,108,83, 0);
|
||||
checkBBox("path3", opt, 6,121,108,83, 0);
|
||||
checkBBox("path4", opt, 2,17,116,91, 0);
|
||||
checkBBox("path5", opt, 156,21,108,83, 0);
|
||||
checkBBox("path6", opt, 6,121,108,83, 0);
|
||||
checkBBox("path7", opt, 2,17,116,91, 0);
|
||||
checkBBox("path8", opt, 156,21,108,83, 0);
|
||||
checkBBox("path9", opt, 6,121,108,83, 0);
|
||||
checkBBox("path10", opt, 2,17,116,91, 0);
|
||||
checkBBox("path11", opt, 156,21,108,83, 0);
|
||||
checkBBox("path12", opt, 6,121,108,83, 0);
|
||||
|
||||
opt = { fill: false, stroke: false, markers: true, clipped: false };
|
||||
checkBBox("path1", opt, 10,25,112,87, 0);
|
||||
checkBBox("path2", opt, 160,25,112,87, 0);
|
||||
checkBBox("path3", opt, 10,125,112,87, 0);
|
||||
checkBBox("path4", opt, 10,25,112,87, 0);
|
||||
checkBBox("path5", opt, 160,25,112,87, 0);
|
||||
checkBBox("path6", opt, 10,125,112,87, 0);
|
||||
checkBBox("path7", opt, 10,25,112,87, 0);
|
||||
checkBBox("path8", opt, 160,25,112,87, 0);
|
||||
checkBBox("path9", opt, 10,125,112,87, 0);
|
||||
checkBBox("path10", opt, 10,25,112,87, 0);
|
||||
checkBBox("path11", opt, 160,25,112,87, 0);
|
||||
checkBBox("path12", opt, 10,125,112,87, 0);
|
||||
|
||||
// <use>
|
||||
opt = { fill: true, stroke: false, markers: false, clipped: false };
|
||||
checkBBox("use1", opt, 70,70,180,180, 0);
|
||||
checkBBox("use2", opt, 250,70,180,180, 0);
|
||||
checkBBox("use3", opt, 70,250,180,180, 0);
|
||||
checkBBox("use4", opt, 22,22,180,180, 0);
|
||||
checkBBox("use5", opt, 225,22,180,180, 0);
|
||||
checkBBox("use6", opt, 22,225,180,180, 0);
|
||||
checkBBox("use7", opt, 225,225,180,180, 0);
|
||||
|
||||
opt = { fill: true, stroke: true, markers: true, clipped: true };
|
||||
checkBBox("use1", opt, 70,66,180,94, 0);
|
||||
checkBBox("use2", opt, 250,70,180,90, 0);
|
||||
checkBBox("use3", opt, 70,250,180,90, 0);
|
||||
checkBBox("use4", opt, 18,18,134,134, 0);
|
||||
checkBBox("use5", opt, 221,18,134,134, 0);
|
||||
checkBBox("use6", opt, 18,221,134,134, 0);
|
||||
checkBBox("use7", opt, 221,221,134,134, 0);
|
||||
checkBBox("use8", opt, 0,0,0,0, 0);
|
||||
|
||||
// <foreignObject>
|
||||
opt = { fill: true, stroke: false, markers: false, clipped: false };
|
||||
checkBBox("fo1", opt, 2,2,200,200, 0);
|
||||
checkBBox("fo2", opt, 205,2,200,200, 0);
|
||||
checkBBox("fo3", opt, 2,205,200,200, 0);
|
||||
checkBBox("fo4", opt, 205,205,200,200, 0);
|
||||
checkBBox("fo5", opt, 250,250,200,200, 0);
|
||||
checkBBox("fo6", opt, 0,0,200,200, 0);
|
||||
checkBBox("fo7", opt, 0,0,200,200, 0);
|
||||
|
||||
opt = { fill: true, stroke: true, markers: true, clipped: true };
|
||||
checkBBox("fo1", opt, 53,53,51,51, 0);
|
||||
checkBBox("fo2", opt, 205,53,148,149, 0);
|
||||
checkBBox("fo3", opt, 53,205,149,148, 0);
|
||||
checkBBox("fo4", opt, 207,207,100,100, 0);
|
||||
checkBBox("fo5", opt, 0,0,0,0, 0);
|
||||
checkBBox("fo6", opt, 100,100,100,100, 0);
|
||||
checkBBox("fo7", opt, 10,10,180,180, 0);
|
||||
checkBBox("fo8", opt, 0,0,0,0, 0);
|
||||
|
||||
// from http://www.w3.org/Graphics/SVG/Test/20110816/harness/htmlObjectApproved/masking-path-07-b.html
|
||||
opt = { fill: true, stroke: true, markers: true, clipped: true };
|
||||
checkBBox("rect-1", opt, 10,10,140,140, 0);
|
||||
checkBBox("rect-2", opt, 50,30,25,100, 0);
|
||||
checkBBox("rect-3", opt, 50,50,100,100, 0);
|
||||
checkBBox("g1", opt, 50,50,100,100, 0);
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
window.addEventListener("load", run, false);
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
|
@ -98,6 +98,11 @@
|
|||
#include "WorkerPrivate.h"
|
||||
#include "WorkerRunnable.h"
|
||||
|
||||
#if defined(XP_LINUX)
|
||||
#include "mozilla/Hal.h"
|
||||
#endif
|
||||
#include "mozilla/dom/ContentChild.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
|
@ -1483,41 +1488,27 @@ Navigator::GetFeature(const nsAString& aName)
|
|||
|
||||
#if defined(XP_LINUX)
|
||||
if (aName.EqualsLiteral("hardware.memory")) {
|
||||
static int memLevel = 1;
|
||||
if (memLevel == 1) {
|
||||
FILE* f = fopen("/proc/meminfo", "r");
|
||||
if (!f) {
|
||||
p->MaybeReject(NS_LITERAL_STRING("CannotOpenMeminfo"));
|
||||
return p.forget();
|
||||
}
|
||||
|
||||
int memTotal;
|
||||
int n = fscanf(f, "MemTotal: %d kB\n", &memTotal);
|
||||
fclose(f);
|
||||
|
||||
if (memTotal == 0 || n != 1) {
|
||||
// with seccomp enabled, fopen() should be in a non-sandboxed process
|
||||
if (XRE_GetProcessType() == GeckoProcessType_Default) {
|
||||
uint32_t memLevel = mozilla::hal::GetTotalSystemMemoryLevel();
|
||||
if (memLevel == 0) {
|
||||
p->MaybeReject(NS_LITERAL_STRING("Abnormal"));
|
||||
return p.forget();
|
||||
}
|
||||
// From KB to MB
|
||||
memTotal /= 1024;
|
||||
|
||||
// round the value up to the next power of two
|
||||
while (memLevel <= memTotal) {
|
||||
memLevel *= 2;
|
||||
p->MaybeResolve((int)memLevel);
|
||||
} else {
|
||||
mozilla::dom::ContentChild* cc =
|
||||
mozilla::dom::ContentChild::GetSingleton();
|
||||
nsRefPtr<Promise> ipcRef(p);
|
||||
cc->SendGetSystemMemory(reinterpret_cast<uint64_t>(ipcRef.forget().take()));
|
||||
}
|
||||
}
|
||||
p->MaybeResolve(memLevel);
|
||||
return p.forget();
|
||||
} // hardware.memory
|
||||
else
|
||||
#endif
|
||||
{
|
||||
// resolve with <undefined> because the feature name is not supported
|
||||
p->MaybeResolve(JS::UndefinedHandleValue);
|
||||
}
|
||||
|
||||
return p.forget();
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
/* 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";
|
||||
|
||||
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
||||
function SlowScriptDebug() { }
|
||||
|
||||
SlowScriptDebug.prototype = {
|
||||
classID: Components.ID("{e740ddb4-18b4-4aac-8ae1-9b0f4320769d}"),
|
||||
classDescription: "Slow script debug handler",
|
||||
contractID: "@mozilla.org/dom/slow-script-debug;1",
|
||||
QueryInterface: XPCOMUtils.generateQI([Components.interfaces.nsISlowScriptDebug]),
|
||||
|
||||
get activationHandler() { return this._activationHandler; },
|
||||
set activationHandler(cb) { return this._activationHandler = cb; },
|
||||
};
|
||||
|
||||
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([SlowScriptDebug]);
|
|
@ -0,0 +1,2 @@
|
|||
component {e740ddb4-18b4-4aac-8ae1-9b0f4320769d} SlowScriptDebug.js
|
||||
contract @mozilla.org/dom/slow-script-debug;1 {e740ddb4-18b4-4aac-8ae1-9b0f4320769d}
|
|
@ -13,6 +13,7 @@ XPIDL_SOURCES += [
|
|||
'nsIEntropyCollector.idl',
|
||||
'nsIScriptChannel.idl',
|
||||
'nsISiteSpecificUserAgent.idl',
|
||||
'nsISlowScriptDebug.idl',
|
||||
]
|
||||
|
||||
XPIDL_MODULE = 'dom'
|
||||
|
@ -128,6 +129,8 @@ EXTRA_COMPONENTS += [
|
|||
'ConsoleAPIStorage.js',
|
||||
'SiteSpecificUserAgent.js',
|
||||
'SiteSpecificUserAgent.manifest',
|
||||
'SlowScriptDebug.js',
|
||||
'SlowScriptDebug.manifest',
|
||||
]
|
||||
|
||||
EXTRA_JS_MODULES += [
|
||||
|
|
|
@ -485,10 +485,6 @@ bool nsDOMClassInfo::sIsInitialized = false;
|
|||
|
||||
jsid nsDOMClassInfo::sLocation_id = JSID_VOID;
|
||||
jsid nsDOMClassInfo::sConstructor_id = JSID_VOID;
|
||||
jsid nsDOMClassInfo::sLength_id = JSID_VOID;
|
||||
jsid nsDOMClassInfo::sItem_id = JSID_VOID;
|
||||
jsid nsDOMClassInfo::sNamedItem_id = JSID_VOID;
|
||||
jsid nsDOMClassInfo::sEnumerate_id = JSID_VOID;
|
||||
jsid nsDOMClassInfo::sTop_id = JSID_VOID;
|
||||
jsid nsDOMClassInfo::sDocument_id = JSID_VOID;
|
||||
jsid nsDOMClassInfo::sWrappedJSObject_id = JSID_VOID;
|
||||
|
@ -595,10 +591,6 @@ nsDOMClassInfo::DefineStaticJSVals(JSContext *cx)
|
|||
|
||||
SET_JSID_TO_STRING(sLocation_id, cx, "location");
|
||||
SET_JSID_TO_STRING(sConstructor_id, cx, "constructor");
|
||||
SET_JSID_TO_STRING(sLength_id, cx, "length");
|
||||
SET_JSID_TO_STRING(sItem_id, cx, "item");
|
||||
SET_JSID_TO_STRING(sNamedItem_id, cx, "namedItem");
|
||||
SET_JSID_TO_STRING(sEnumerate_id, cx, "enumerateProperties");
|
||||
SET_JSID_TO_STRING(sTop_id, cx, "top");
|
||||
SET_JSID_TO_STRING(sDocument_id, cx, "document");
|
||||
SET_JSID_TO_STRING(sWrappedJSObject_id, cx, "wrappedJSObject");
|
||||
|
@ -1717,9 +1709,6 @@ nsDOMClassInfo::ShutDown()
|
|||
|
||||
sLocation_id = JSID_VOID;
|
||||
sConstructor_id = JSID_VOID;
|
||||
sLength_id = JSID_VOID;
|
||||
sItem_id = JSID_VOID;
|
||||
sEnumerate_id = JSID_VOID;
|
||||
sTop_id = JSID_VOID;
|
||||
sDocument_id = JSID_VOID;
|
||||
sWrappedJSObject_id = JSID_VOID;
|
||||
|
|
|
@ -166,10 +166,6 @@ protected:
|
|||
public:
|
||||
static jsid sLocation_id;
|
||||
static jsid sConstructor_id;
|
||||
static jsid sLength_id;
|
||||
static jsid sItem_id;
|
||||
static jsid sNamedItem_id;
|
||||
static jsid sEnumerate_id;
|
||||
static jsid sTop_id;
|
||||
static jsid sDocument_id;
|
||||
static jsid sWrappedJSObject_id;
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
#include "nsIScriptTimeoutHandler.h"
|
||||
#include "nsIController.h"
|
||||
#include "nsScriptNameSpaceManager.h"
|
||||
#include "nsISlowScriptDebug.h"
|
||||
#include "nsWindowMemoryReporter.h"
|
||||
#include "WindowNamedPropertiesHandler.h"
|
||||
|
||||
|
@ -1344,12 +1345,14 @@ nsGlobalWindow::~nsGlobalWindow()
|
|||
void
|
||||
nsGlobalWindow::AddEventTargetObject(DOMEventTargetHelper* aObject)
|
||||
{
|
||||
MOZ_ASSERT(IsInnerWindow());
|
||||
mEventTargetObjects.PutEntry(aObject);
|
||||
}
|
||||
|
||||
void
|
||||
nsGlobalWindow::RemoveEventTargetObject(DOMEventTargetHelper* aObject)
|
||||
{
|
||||
MOZ_ASSERT(IsInnerWindow());
|
||||
mEventTargetObjects.RemoveEntry(aObject);
|
||||
}
|
||||
|
||||
|
@ -1986,8 +1989,10 @@ nsGlobalWindow::OuterObject(JSContext* aCx, JS::Handle<JSObject*> aObj)
|
|||
}
|
||||
|
||||
bool
|
||||
nsGlobalWindow::WouldReuseInnerWindow(nsIDocument *aNewDocument)
|
||||
nsGlobalWindow::WouldReuseInnerWindow(nsIDocument* aNewDocument)
|
||||
{
|
||||
MOZ_ASSERT(IsOuterWindow());
|
||||
|
||||
// We reuse the inner window when:
|
||||
// a. We are currently at our original document.
|
||||
// b. At least one of the following conditions are true:
|
||||
|
@ -2027,7 +2032,7 @@ nsGlobalWindow::WouldReuseInnerWindow(nsIDocument *aNewDocument)
|
|||
void
|
||||
nsGlobalWindow::SetInitialPrincipalToSubject()
|
||||
{
|
||||
FORWARD_TO_OUTER_VOID(SetInitialPrincipalToSubject, ());
|
||||
MOZ_ASSERT(IsOuterWindow());
|
||||
|
||||
// First, grab the subject principal.
|
||||
nsCOMPtr<nsIPrincipal> newWindowPrincipal = nsContentUtils::SubjectPrincipal();
|
||||
|
@ -2296,11 +2301,6 @@ nsGlobalWindow::SetNewDocument(nsIDocument* aDocument,
|
|||
|
||||
nsCOMPtr<nsIDocument> oldDoc = mDoc;
|
||||
|
||||
nsIScriptContext *scx = GetContextInternal();
|
||||
NS_ENSURE_TRUE(scx, NS_ERROR_NOT_INITIALIZED);
|
||||
|
||||
JSContext *cx = scx->GetNativeContext();
|
||||
|
||||
#ifndef MOZ_DISABLE_CRYPTOLEGACY
|
||||
// clear smartcard events, our document has gone away.
|
||||
if (mCrypto && XRE_GetProcessType() != GeckoProcessType_Content) {
|
||||
|
@ -2309,6 +2309,9 @@ nsGlobalWindow::SetNewDocument(nsIDocument* aDocument,
|
|||
}
|
||||
#endif
|
||||
|
||||
AutoJSAPI jsapi;
|
||||
JSContext *cx = jsapi.cx();
|
||||
|
||||
if (!mDoc) {
|
||||
// First document load.
|
||||
|
||||
|
@ -2365,9 +2368,6 @@ nsGlobalWindow::SetNewDocument(nsIDocument* aDocument,
|
|||
|
||||
bool thisChrome = IsChromeWindow();
|
||||
|
||||
nsCxPusher cxPusher;
|
||||
cxPusher.Push(cx);
|
||||
|
||||
// Check if we're near the stack limit before we get anywhere near the
|
||||
// transplanting code.
|
||||
JS_CHECK_RECURSION(cx, return NS_ERROR_FAILURE);
|
||||
|
@ -2660,8 +2660,11 @@ nsGlobalWindow::SetNewDocument(nsIDocument* aDocument,
|
|||
// We wait to fire the debugger hook until the window is all set up and hooked
|
||||
// up with the outer. See bug 969156.
|
||||
if (createdInnerWindow) {
|
||||
JS::Rooted<JSObject*> global(cx, newInnerWindow->GetWrapper());
|
||||
JS_FireOnNewGlobalObject(cx, global);
|
||||
// AutoEntryScript required to invoke debugger hook, which is a
|
||||
// Gecko-specific concept at present.
|
||||
AutoEntryScript aes(newInnerWindow);
|
||||
JS::Rooted<JSObject*> global(aes.cx(), newInnerWindow->GetWrapper());
|
||||
JS_FireOnNewGlobalObject(aes.cx(), global);
|
||||
}
|
||||
|
||||
if (newInnerWindow && !newInnerWindow->mHasNotifiedGlobalCreated && mDoc) {
|
||||
|
@ -2686,6 +2689,8 @@ nsGlobalWindow::SetNewDocument(nsIDocument* aDocument,
|
|||
void
|
||||
nsGlobalWindow::PreloadLocalStorage()
|
||||
{
|
||||
MOZ_ASSERT(IsOuterWindow());
|
||||
|
||||
if (!Preferences::GetBool(kStorageEnabled)) {
|
||||
return;
|
||||
}
|
||||
|
@ -2713,6 +2718,8 @@ nsGlobalWindow::PreloadLocalStorage()
|
|||
void
|
||||
nsGlobalWindow::DispatchDOMWindowCreated()
|
||||
{
|
||||
MOZ_ASSERT(IsOuterWindow());
|
||||
|
||||
if (!mDoc) {
|
||||
return;
|
||||
}
|
||||
|
@ -3063,6 +3070,8 @@ nsGlobalWindow::ShouldPromptToBlockDialogs()
|
|||
bool
|
||||
nsGlobalWindow::AreDialogsEnabled()
|
||||
{
|
||||
MOZ_ASSERT(IsOuterWindow());
|
||||
|
||||
nsGlobalWindow *topWindow = GetScriptableTop();
|
||||
if (!topWindow) {
|
||||
NS_ERROR("AreDialogsEnabled() called without a top window?");
|
||||
|
@ -6263,6 +6272,12 @@ nsGlobalWindow::AlertOrConfirm(bool aAlert,
|
|||
return result;
|
||||
}
|
||||
|
||||
void
|
||||
nsGlobalWindow::Alert(mozilla::ErrorResult& aError)
|
||||
{
|
||||
Alert(EmptyString(), aError);
|
||||
}
|
||||
|
||||
void
|
||||
nsGlobalWindow::Alert(const nsAString& aMessage, mozilla::ErrorResult& aError)
|
||||
{
|
||||
|
@ -8216,8 +8231,11 @@ public:
|
|||
bool
|
||||
nsGlobalWindow::CanClose()
|
||||
{
|
||||
if (!mDocShell)
|
||||
MOZ_ASSERT(IsOuterWindow());
|
||||
|
||||
if (!mDocShell) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Ask the content viewer whether the toplevel window can close.
|
||||
// If the content viewer returns false, it is responsible for calling
|
||||
|
@ -8311,7 +8329,7 @@ nsGlobalWindow::Close(ErrorResult& aError)
|
|||
return;
|
||||
}
|
||||
|
||||
aError = FinalClose();
|
||||
FinalClose();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -8323,32 +8341,35 @@ nsGlobalWindow::Close()
|
|||
return rv.ErrorCode();
|
||||
}
|
||||
|
||||
nsresult
|
||||
void
|
||||
nsGlobalWindow::ForceClose()
|
||||
{
|
||||
MOZ_ASSERT(IsOuterWindow());
|
||||
|
||||
if (IsFrame() || !mDocShell) {
|
||||
// This may be a frame in a frameset, or a window that's already closed.
|
||||
// Ignore such calls.
|
||||
|
||||
return NS_OK;
|
||||
return;
|
||||
}
|
||||
|
||||
if (mHavePendingClose) {
|
||||
// We're going to be closed anyway; do nothing since we don't want
|
||||
// to double-close
|
||||
return NS_OK;
|
||||
return;
|
||||
}
|
||||
|
||||
mInClose = true;
|
||||
|
||||
DispatchCustomEvent("DOMWindowClose");
|
||||
|
||||
return FinalClose();
|
||||
FinalClose();
|
||||
}
|
||||
|
||||
nsresult
|
||||
void
|
||||
nsGlobalWindow::FinalClose()
|
||||
{
|
||||
MOZ_ASSERT(IsOuterWindow());
|
||||
|
||||
// Flag that we were closed.
|
||||
mIsClosed = true;
|
||||
|
||||
|
@ -8372,8 +8393,6 @@ nsGlobalWindow::FinalClose()
|
|||
} else {
|
||||
mHavePendingClose = true;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
|
@ -10749,10 +10768,22 @@ nsGlobalWindow::ShowSlowScriptDialog()
|
|||
unsigned lineno;
|
||||
bool hasFrame = JS::DescribeScriptedCaller(cx, &filename, &lineno);
|
||||
|
||||
bool debugPossible = hasFrame && js::CanCallContextDebugHandler(cx);
|
||||
// Prioritize the SlowScriptDebug interface over JSD1.
|
||||
nsCOMPtr<nsISlowScriptDebugCallback> debugCallback;
|
||||
bool oldDebugPossible = false;
|
||||
|
||||
if (hasFrame) {
|
||||
const char *debugCID = "@mozilla.org/dom/slow-script-debug;1";
|
||||
nsCOMPtr<nsISlowScriptDebug> debugService = do_GetService(debugCID, &rv);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
debugService->GetActivationHandler(getter_AddRefs(debugCallback));
|
||||
}
|
||||
|
||||
if (!debugCallback) {
|
||||
oldDebugPossible = js::CanCallContextDebugHandler(cx);
|
||||
#ifdef MOZ_JSDEBUGGER
|
||||
// Get the debugger service if necessary.
|
||||
if (debugPossible) {
|
||||
if (oldDebugPossible) {
|
||||
bool jsds_IsOn = false;
|
||||
const char jsdServiceCtrID[] = "@mozilla.org/js/jsd/debugger-service;1";
|
||||
nsCOMPtr<jsdIExecutionHook> jsdHook;
|
||||
|
@ -10767,9 +10798,13 @@ nsGlobalWindow::ShowSlowScriptDialog()
|
|||
// If there is a debug handler registered for this runtime AND
|
||||
// ((jsd is on AND has a hook) OR (jsd isn't on (something else debugs)))
|
||||
// then something useful will be done with our request to debug.
|
||||
debugPossible = ((jsds_IsOn && (jsdHook != nullptr)) || !jsds_IsOn);
|
||||
oldDebugPossible = ((jsds_IsOn && (jsdHook != nullptr)) || !jsds_IsOn);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
bool showDebugButton = debugCallback || oldDebugPossible;
|
||||
|
||||
// Get localizable strings
|
||||
nsXPIDLString title, msg, stopButton, waitButton, debugButton, neverShowDlg;
|
||||
|
@ -10800,7 +10835,7 @@ nsGlobalWindow::ShowSlowScriptDialog()
|
|||
}
|
||||
|
||||
|
||||
if (debugPossible) {
|
||||
if (showDebugButton) {
|
||||
tmp = nsContentUtils::GetLocalizedString(nsContentUtils::eDOM_PROPERTIES,
|
||||
"DebugScriptButton",
|
||||
debugButton);
|
||||
|
@ -10826,7 +10861,7 @@ nsGlobalWindow::ShowSlowScriptDialog()
|
|||
|
||||
// GetStringFromName can return NS_OK and still give nullptr string
|
||||
if (NS_FAILED(rv) || !title || !msg || !stopButton || !waitButton ||
|
||||
(!debugButton && debugPossible) || !neverShowDlg) {
|
||||
(!debugButton && showDebugButton) || !neverShowDlg) {
|
||||
NS_ERROR("Failed to get localized strings.");
|
||||
return ContinueSlowScript;
|
||||
}
|
||||
|
@ -10856,7 +10891,7 @@ nsGlobalWindow::ShowSlowScriptDialog()
|
|||
(nsIPrompt::BUTTON_POS_0 + nsIPrompt::BUTTON_POS_1));
|
||||
|
||||
// Add a third button if necessary.
|
||||
if (debugPossible)
|
||||
if (showDebugButton)
|
||||
buttonFlags += nsIPrompt::BUTTON_TITLE_IS_STRING * nsIPrompt::BUTTON_POS_2;
|
||||
|
||||
// Null out the operation callback while we're re-entering JS here.
|
||||
|
@ -10873,9 +10908,16 @@ nsGlobalWindow::ShowSlowScriptDialog()
|
|||
if (NS_SUCCEEDED(rv) && (buttonPressed == 0)) {
|
||||
return neverShowDlgChk ? AlwaysContinueSlowScript : ContinueSlowScript;
|
||||
}
|
||||
if ((buttonPressed == 2) && debugPossible) {
|
||||
if (buttonPressed == 2) {
|
||||
if (debugCallback) {
|
||||
rv = debugCallback->HandleSlowScriptDebug(this);
|
||||
return NS_SUCCEEDED(rv) ? ContinueSlowScript : KillSlowScript;
|
||||
}
|
||||
|
||||
if (oldDebugPossible) {
|
||||
return js_CallContextDebugHandler(cx) ? ContinueSlowScript : KillSlowScript;
|
||||
}
|
||||
}
|
||||
JS_ClearPendingException(cx);
|
||||
return KillSlowScript;
|
||||
}
|
||||
|
|
|
@ -434,6 +434,7 @@ public:
|
|||
virtual NS_HIDDEN_(void) SetIsBackground(bool aIsBackground);
|
||||
virtual NS_HIDDEN_(void) SetChromeEventHandler(mozilla::dom::EventTarget* aChromeEventHandler);
|
||||
|
||||
// Outer windows only.
|
||||
virtual NS_HIDDEN_(void) SetInitialPrincipalToSubject();
|
||||
|
||||
virtual NS_HIDDEN_(PopupControlState) PushPopupControlState(PopupControlState state, bool aForce) const;
|
||||
|
@ -453,14 +454,18 @@ public:
|
|||
}
|
||||
virtual NS_HIDDEN_(bool) IsRunningTimeout() { return mTimeoutFiringDepth > 0; }
|
||||
|
||||
virtual NS_HIDDEN_(bool) WouldReuseInnerWindow(nsIDocument *aNewDocument);
|
||||
// Outer windows only.
|
||||
virtual NS_HIDDEN_(bool) WouldReuseInnerWindow(nsIDocument* aNewDocument);
|
||||
|
||||
virtual NS_HIDDEN_(void) SetDocShell(nsIDocShell* aDocShell);
|
||||
virtual void DetachFromDocShell();
|
||||
virtual NS_HIDDEN_(nsresult) SetNewDocument(nsIDocument *aDocument,
|
||||
nsISupports *aState,
|
||||
bool aForceReuseInnerWindow);
|
||||
|
||||
// Outer windows only.
|
||||
void DispatchDOMWindowCreated();
|
||||
|
||||
virtual NS_HIDDEN_(void) SetOpenerWindow(nsIDOMWindow* aOpener,
|
||||
bool aOriginalOpener);
|
||||
|
||||
|
@ -470,8 +475,9 @@ public:
|
|||
virtual NS_HIDDEN_(void) EnterModalState();
|
||||
virtual NS_HIDDEN_(void) LeaveModalState();
|
||||
|
||||
// Outer windows only.
|
||||
virtual NS_HIDDEN_(bool) CanClose();
|
||||
virtual NS_HIDDEN_(nsresult) ForceClose();
|
||||
virtual NS_HIDDEN_(void) ForceClose();
|
||||
|
||||
virtual NS_HIDDEN_(void) MaybeUpdateTouchState();
|
||||
virtual NS_HIDDEN_(void) UpdateTouchState();
|
||||
|
@ -557,6 +563,7 @@ public:
|
|||
// (alert, prompt, confirm) are currently allowed in this window.
|
||||
void EnableDialogs();
|
||||
void DisableDialogs();
|
||||
// Outer windows only.
|
||||
bool AreDialogsEnabled();
|
||||
|
||||
nsIScriptContext *GetContextInternal()
|
||||
|
@ -696,6 +703,7 @@ public:
|
|||
|
||||
void UnmarkGrayTimers();
|
||||
|
||||
// Inner windows only.
|
||||
void AddEventTargetObject(mozilla::DOMEventTargetHelper* aObject);
|
||||
void RemoveEventTargetObject(mozilla::DOMEventTargetHelper* aObject);
|
||||
|
||||
|
@ -848,6 +856,7 @@ protected:
|
|||
mozilla::ErrorResult& aError);
|
||||
|
||||
public:
|
||||
void Alert(mozilla::ErrorResult& aError);
|
||||
void Alert(const nsAString& aMessage, mozilla::ErrorResult& aError);
|
||||
bool Confirm(const nsAString& aMessage, mozilla::ErrorResult& aError);
|
||||
void Prompt(const nsAString& aMessage, const nsAString& aInitial,
|
||||
|
@ -1044,7 +1053,8 @@ protected:
|
|||
void DropOuterWindowDocs();
|
||||
void CleanUp();
|
||||
void ClearControllers();
|
||||
nsresult FinalClose();
|
||||
// Outer windows only.
|
||||
void FinalClose();
|
||||
|
||||
inline void MaybeClearInnerWindow(nsGlobalWindow* aExpectedInner)
|
||||
{
|
||||
|
@ -1343,6 +1353,7 @@ protected:
|
|||
bool aDefaultStylesOnly,
|
||||
nsIDOMCSSStyleDeclaration** aReturn);
|
||||
|
||||
// Outer windows only.
|
||||
void PreloadLocalStorage();
|
||||
|
||||
// Returns device pixels. Outer windows only.
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
/* 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/. */
|
||||
|
||||
#include "nsISupports.idl"
|
||||
|
||||
interface nsIDOMWindow;
|
||||
|
||||
[scriptable, function, uuid(f7dbb80c-5d1e-4fd9-b55c-a9ffda4a75b1)]
|
||||
interface nsISlowScriptDebugCallback : nsISupports
|
||||
{
|
||||
void handleSlowScriptDebug(in nsIDOMWindow aWindow);
|
||||
};
|
||||
|
||||
[scriptable, uuid(f75d4164-3aa7-4395-ba44-a5f95b2e8427)]
|
||||
interface nsISlowScriptDebug : nsISupports
|
||||
{
|
||||
attribute nsISlowScriptDebugCallback activationHandler;
|
||||
};
|
|
@ -277,13 +277,11 @@ nsJSEnvironmentObserver::Observe(nsISupports* aSubject, const char* aTopic,
|
|||
}
|
||||
nsJSContext::GarbageCollectNow(JS::gcreason::MEM_PRESSURE,
|
||||
nsJSContext::NonIncrementalGC,
|
||||
nsJSContext::NonCompartmentGC,
|
||||
nsJSContext::ShrinkingGC);
|
||||
nsJSContext::CycleCollectNow();
|
||||
if (NeedsGCAfterCC()) {
|
||||
nsJSContext::GarbageCollectNow(JS::gcreason::MEM_PRESSURE,
|
||||
nsJSContext::NonIncrementalGC,
|
||||
nsJSContext::NonCompartmentGC,
|
||||
nsJSContext::ShrinkingGC);
|
||||
}
|
||||
} else if (!nsCRT::strcmp(aTopic, "quit-application")) {
|
||||
|
@ -388,10 +386,8 @@ AsyncErrorReporter::AsyncErrorReporter(JSRuntime* aRuntime,
|
|||
NS_LITERAL_CSTRING("content javascript");
|
||||
|
||||
mInnerWindowID = 0;
|
||||
if (aWindow && aWindow->IsOuterWindow()) {
|
||||
aWindow = aWindow->GetCurrentInnerWindow();
|
||||
}
|
||||
if (aWindow) {
|
||||
MOZ_ASSERT(aWindow->IsInnerWindow());
|
||||
mInnerWindowID = aWindow->WindowID();
|
||||
}
|
||||
}
|
||||
|
@ -429,8 +425,7 @@ AsyncErrorReporter::ReportError()
|
|||
class ScriptErrorEvent : public AsyncErrorReporter
|
||||
{
|
||||
public:
|
||||
ScriptErrorEvent(nsIScriptGlobalObject* aScriptGlobal,
|
||||
JSRuntime* aRuntime,
|
||||
ScriptErrorEvent(JSRuntime* aRuntime,
|
||||
JSErrorReport* aErrorReport,
|
||||
const char* aFallbackMessage,
|
||||
nsIPrincipal* aScriptOriginPrincipal,
|
||||
|
@ -442,20 +437,21 @@ public:
|
|||
: AsyncErrorReporter(aRuntime, aErrorReport, aFallbackMessage,
|
||||
nsContentUtils::IsSystemPrincipal(aGlobalPrincipal),
|
||||
aWindow)
|
||||
, mScriptGlobal(aScriptGlobal)
|
||||
, mOriginPrincipal(aScriptOriginPrincipal)
|
||||
, mDispatchEvent(aDispatchEvent)
|
||||
, mError(aRuntime, aError)
|
||||
, mWindow(aWindow)
|
||||
{
|
||||
MOZ_ASSERT_IF(mWindow, mWindow->IsInnerWindow());
|
||||
}
|
||||
|
||||
NS_IMETHOD Run()
|
||||
{
|
||||
nsEventStatus status = nsEventStatus_eIgnore;
|
||||
// First, notify the DOM that we have a script error.
|
||||
if (mDispatchEvent) {
|
||||
nsCOMPtr<nsPIDOMWindow> win(do_QueryInterface(mScriptGlobal));
|
||||
nsIDocShell* docShell = win ? win->GetDocShell() : nullptr;
|
||||
// First, notify the DOM that we have a script error, but only if
|
||||
// our window is still the current inner, if we're associated with a window.
|
||||
if (mDispatchEvent && (!mWindow || mWindow->IsCurrentInnerWindow())) {
|
||||
nsIDocShell* docShell = mWindow ? mWindow->GetDocShell() : nullptr;
|
||||
if (docShell &&
|
||||
!JSREPORT_IS_WARNING(mFlags) &&
|
||||
!sHandlingScriptError) {
|
||||
|
@ -471,7 +467,7 @@ public:
|
|||
init.mFilename = mFileName;
|
||||
init.mBubbles = true;
|
||||
|
||||
nsCOMPtr<nsIScriptObjectPrincipal> sop(do_QueryInterface(win));
|
||||
nsCOMPtr<nsIScriptObjectPrincipal> sop(do_QueryInterface(mWindow));
|
||||
NS_ENSURE_STATE(sop);
|
||||
nsIPrincipal* p = sop->GetPrincipal();
|
||||
NS_ENSURE_STATE(p);
|
||||
|
@ -497,11 +493,11 @@ public:
|
|||
}
|
||||
|
||||
nsRefPtr<ErrorEvent> event =
|
||||
ErrorEvent::Constructor(static_cast<nsGlobalWindow*>(win.get()),
|
||||
ErrorEvent::Constructor(static_cast<nsGlobalWindow*>(mWindow.get()),
|
||||
NS_LITERAL_STRING("error"), init);
|
||||
event->SetTrusted(true);
|
||||
|
||||
EventDispatcher::DispatchDOMEvent(win, nullptr, event, presContext,
|
||||
EventDispatcher::DispatchDOMEvent(mWindow, nullptr, event, presContext,
|
||||
&status);
|
||||
}
|
||||
}
|
||||
|
@ -514,10 +510,10 @@ public:
|
|||
}
|
||||
|
||||
private:
|
||||
nsCOMPtr<nsIScriptGlobalObject> mScriptGlobal;
|
||||
nsCOMPtr<nsIPrincipal> mOriginPrincipal;
|
||||
bool mDispatchEvent;
|
||||
JS::PersistentRootedValue mError;
|
||||
nsCOMPtr<nsPIDOMWindow> mWindow;
|
||||
|
||||
static bool sHandlingScriptError;
|
||||
};
|
||||
|
@ -575,13 +571,15 @@ NS_ScriptErrorReporter(JSContext *cx,
|
|||
if (globalObject) {
|
||||
|
||||
nsCOMPtr<nsPIDOMWindow> win = do_QueryInterface(globalObject);
|
||||
if (win) {
|
||||
win = win->GetCurrentInnerWindow();
|
||||
}
|
||||
nsCOMPtr<nsIScriptObjectPrincipal> scriptPrincipal =
|
||||
do_QueryInterface(globalObject);
|
||||
NS_ASSERTION(scriptPrincipal, "Global objects must implement "
|
||||
"nsIScriptObjectPrincipal");
|
||||
nsContentUtils::AddScriptRunner(
|
||||
new ScriptErrorEvent(globalObject,
|
||||
JS_GetRuntime(cx),
|
||||
new ScriptErrorEvent(JS_GetRuntime(cx),
|
||||
report,
|
||||
message,
|
||||
nsJSPrincipals::get(report->originPrincipals),
|
||||
|
@ -1708,7 +1706,6 @@ FullGCTimerFired(nsITimer* aTimer, void* aClosure)
|
|||
void
|
||||
nsJSContext::GarbageCollectNow(JS::gcreason::Reason aReason,
|
||||
IsIncremental aIncremental,
|
||||
IsCompartment aCompartment,
|
||||
IsShrinking aShrinking,
|
||||
int64_t aSliceMillis)
|
||||
{
|
||||
|
@ -2201,7 +2198,6 @@ InterSliceGCTimerFired(nsITimer *aTimer, void *aClosure)
|
|||
nsJSContext::KillInterSliceGCTimer();
|
||||
nsJSContext::GarbageCollectNow(JS::gcreason::INTER_SLICE_GC,
|
||||
nsJSContext::IncrementalGC,
|
||||
nsJSContext::CompartmentGC,
|
||||
nsJSContext::NonShrinkingGC,
|
||||
NS_INTERSLICE_GC_BUDGET);
|
||||
}
|
||||
|
@ -2213,8 +2209,7 @@ GCTimerFired(nsITimer *aTimer, void *aClosure)
|
|||
nsJSContext::KillGCTimer();
|
||||
uintptr_t reason = reinterpret_cast<uintptr_t>(aClosure);
|
||||
nsJSContext::GarbageCollectNow(static_cast<JS::gcreason::Reason>(reason),
|
||||
nsJSContext::IncrementalGC,
|
||||
nsJSContext::CompartmentGC);
|
||||
nsJSContext::IncrementalGC);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -68,11 +68,6 @@ public:
|
|||
static void LoadStart();
|
||||
static void LoadEnd();
|
||||
|
||||
enum IsCompartment {
|
||||
CompartmentGC,
|
||||
NonCompartmentGC
|
||||
};
|
||||
|
||||
enum IsShrinking {
|
||||
ShrinkingGC,
|
||||
NonShrinkingGC
|
||||
|
@ -88,7 +83,6 @@ public:
|
|||
|
||||
static void GarbageCollectNow(JS::gcreason::Reason reason,
|
||||
IsIncremental aIncremental = NonIncrementalGC,
|
||||
IsCompartment aCompartment = NonCompartmentGC,
|
||||
IsShrinking aShrinking = NonShrinkingGC,
|
||||
int64_t aSliceMillis = 0);
|
||||
static void ShrinkGCBuffersNow();
|
||||
|
|
|
@ -278,6 +278,7 @@ public:
|
|||
|
||||
// Set the window up with an about:blank document with the current subject
|
||||
// principal.
|
||||
// Outer windows only.
|
||||
virtual void SetInitialPrincipalToSubject() = 0;
|
||||
|
||||
virtual PopupControlState PushPopupControlState(PopupControlState aState,
|
||||
|
@ -364,7 +365,8 @@ public:
|
|||
return !IsInnerWindow();
|
||||
}
|
||||
|
||||
virtual bool WouldReuseInnerWindow(nsIDocument *aNewDocument) = 0;
|
||||
// Outer windows only.
|
||||
virtual bool WouldReuseInnerWindow(nsIDocument* aNewDocument) = 0;
|
||||
|
||||
/**
|
||||
* Get the docshell in this window.
|
||||
|
@ -424,8 +426,9 @@ public:
|
|||
virtual void EnterModalState() = 0;
|
||||
virtual void LeaveModalState() = 0;
|
||||
|
||||
// Outer windows only.
|
||||
virtual bool CanClose() = 0;
|
||||
virtual nsresult ForceClose() = 0;
|
||||
virtual void ForceClose() = 0;
|
||||
|
||||
bool IsModalContentWindow() const
|
||||
{
|
||||
|
|
|
@ -48,12 +48,9 @@ support-files =
|
|||
[test_named_frames.html]
|
||||
[test_navigator_resolve_identity.html]
|
||||
[test_navigator_language.html]
|
||||
[test_nondomexception.html]
|
||||
[test_openDialogChromeOnly.html]
|
||||
|
||||
[test_open_null_features.html]
|
||||
skip-if = (buildapp == 'b2g' && toolkit != 'gonk') # Fails on b2g-desktop, tracked in bug 1011874
|
||||
|
||||
[test_postMessage_solidus.html]
|
||||
[test_screen_orientation.html]
|
||||
[test_settimeout_extra_arguments.html]
|
||||
|
|
|
@ -1,28 +0,0 @@
|
|||
<!-- intentionally omiting doctype because this test requires document.all -->
|
||||
<html>
|
||||
<head>
|
||||
<title>Test for non-DOM module exceptions</title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="application/javascript;version=1.7">
|
||||
"use strict";
|
||||
|
||||
try {
|
||||
document.all();
|
||||
} catch (e) {
|
||||
is(typeof e, "object");
|
||||
is(e.filename, location);
|
||||
is(e.lineNumber, 18);
|
||||
}
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
|
@ -91,7 +91,7 @@ DOMEventTargetHelper::~DOMEventTargetHelper()
|
|||
void
|
||||
DOMEventTargetHelper::BindToOwner(nsPIDOMWindow* aOwner)
|
||||
{
|
||||
MOZ_ASSERT(!aOwner || aOwner->IsInnerWindow());
|
||||
MOZ_ASSERT_IF(aOwner, aOwner->IsInnerWindow());
|
||||
nsCOMPtr<nsIGlobalObject> glob = do_QueryInterface(aOwner);
|
||||
BindToOwner(glob);
|
||||
}
|
||||
|
@ -112,6 +112,7 @@ DOMEventTargetHelper::BindToOwner(nsIGlobalObject* aOwner)
|
|||
// Let's cache the result of this QI for fast access and off main thread usage
|
||||
mOwnerWindow = nsCOMPtr<nsPIDOMWindow>(do_QueryInterface(aOwner)).get();
|
||||
if (mOwnerWindow) {
|
||||
MOZ_ASSERT(mOwnerWindow->IsInnerWindow());
|
||||
mHasOrHasHadOwnerWindow = true;
|
||||
static_cast<nsGlobalWindow*>(mOwnerWindow)->AddEventTargetObject(this);
|
||||
}
|
||||
|
@ -134,6 +135,7 @@ DOMEventTargetHelper::BindToOwner(DOMEventTargetHelper* aOther)
|
|||
// Let's cache the result of this QI for fast access and off main thread usage
|
||||
mOwnerWindow = nsCOMPtr<nsPIDOMWindow>(do_QueryInterface(mParentObject)).get();
|
||||
if (mOwnerWindow) {
|
||||
MOZ_ASSERT(mOwnerWindow->IsInnerWindow());
|
||||
mHasOrHasHadOwnerWindow = true;
|
||||
static_cast<nsGlobalWindow*>(mOwnerWindow)->AddEventTargetObject(this);
|
||||
}
|
||||
|
|
|
@ -120,13 +120,9 @@ public:
|
|||
nsresult CheckInnerWindowCorrectness()
|
||||
{
|
||||
NS_ENSURE_STATE(!mHasOrHasHadOwnerWindow || mOwnerWindow);
|
||||
if (mOwnerWindow) {
|
||||
NS_ASSERTION(mOwnerWindow->IsInnerWindow(), "Should have inner window here!\n");
|
||||
nsPIDOMWindow* outer = mOwnerWindow->GetOuterWindow();
|
||||
if (!outer || outer->GetCurrentInnerWindow() != mOwnerWindow) {
|
||||
if (mOwnerWindow && !mOwnerWindow->IsCurrentInnerWindow()) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -159,7 +155,7 @@ protected:
|
|||
private:
|
||||
// Inner window or sandbox.
|
||||
nsIGlobalObject* mParentObject;
|
||||
// mParentObject pre QI-ed and cached
|
||||
// mParentObject pre QI-ed and cached (inner window)
|
||||
// (it is needed for off main thread access)
|
||||
nsPIDOMWindow* mOwnerWindow;
|
||||
bool mHasOrHasHadOwnerWindow;
|
||||
|
|
|
@ -660,15 +660,10 @@ IDBTransaction::GetMode(ErrorResult& aRv) const
|
|||
}
|
||||
|
||||
DOMError*
|
||||
IDBTransaction::GetError(ErrorResult& aRv)
|
||||
IDBTransaction::GetError() const
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
if (IsOpen()) {
|
||||
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return mError;
|
||||
}
|
||||
|
||||
|
|
|
@ -242,7 +242,7 @@ public:
|
|||
}
|
||||
|
||||
DOMError*
|
||||
GetError(ErrorResult& aRv);
|
||||
GetError() const;
|
||||
|
||||
already_AddRefed<IDBObjectStore>
|
||||
ObjectStore(const nsAString& aName, ErrorResult& aRv);
|
||||
|
|
|
@ -58,6 +58,7 @@ tail =
|
|||
[test_success_events_after_abort.js]
|
||||
[test_traffic_jam.js]
|
||||
[test_transaction_abort.js]
|
||||
[test_transaction_error.js]
|
||||
[test_transaction_lifetimes.js]
|
||||
[test_transaction_lifetimes_nested.js]
|
||||
[test_transaction_ordering.js]
|
||||
|
|
|
@ -192,6 +192,8 @@ skip-if = (buildapp == 'b2g' && toolkit != 'gonk') #Bug 931116, b2g desktop spec
|
|||
skip-if = (buildapp == 'b2g' && toolkit != 'gonk') #Bug 931116, b2g desktop specific, initial triage
|
||||
[test_transaction_abort_hang.html]
|
||||
skip-if = (buildapp == 'b2g' && toolkit != 'gonk') #Bug 931116, b2g desktop specific, initial triage
|
||||
[test_transaction_error.html]
|
||||
skip-if = (buildapp == 'b2g' && toolkit != 'gonk') #Bug 931116, b2g desktop specific, initial triage
|
||||
[test_transaction_lifetimes.html]
|
||||
skip-if = (buildapp == 'b2g' && toolkit != 'gonk') #Bug 931116, b2g desktop specific, initial triage
|
||||
[test_transaction_lifetimes_nested.html]
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
<!--
|
||||
Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
||||
-->
|
||||
<html>
|
||||
<head>
|
||||
<title>Indexed Database Test</title>
|
||||
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
|
||||
<script type="text/javascript;version=1.7" src="unit/test_transaction_error.js"></script>
|
||||
<script type="text/javascript;version=1.7" src="helpers.js"></script>
|
||||
</head>
|
||||
|
||||
<body onload="runTest();"></body>
|
||||
|
||||
</html>
|
|
@ -64,6 +64,7 @@
|
|||
[test_traffic_jam.js]
|
||||
[test_transaction_abort.js]
|
||||
[test_transaction_abort_hang.js]
|
||||
[test_transaction_error.js]
|
||||
[test_transaction_lifetimes.js]
|
||||
[test_transaction_lifetimes_nested.js]
|
||||
[test_transaction_ordering.js]
|
||||
|
|
|
@ -34,13 +34,7 @@ function testSteps()
|
|||
|
||||
transaction = event.target.transaction;
|
||||
|
||||
try {
|
||||
let error = transaction.error;
|
||||
ok(false, "Expect an exception");
|
||||
} catch(e) {
|
||||
ok(true, "Got an exception.");
|
||||
is(e.name, "InvalidStateError", "Got the right exception");
|
||||
}
|
||||
is(transaction.error, null, "Expect a null error");
|
||||
|
||||
objectStore = db.createObjectStore("foo", { autoIncrement: true });
|
||||
index = objectStore.createIndex("fooindex", "indexKey", { unique: true });
|
||||
|
|
|
@ -0,0 +1,116 @@
|
|||
/**
|
||||
* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
let testGenerator = testSteps();
|
||||
|
||||
function testSteps() {
|
||||
const dbName = this.window ?
|
||||
window.location.pathname :
|
||||
"test_transaction_error";
|
||||
const dbVersion = 1;
|
||||
const objectStoreName = "foo";
|
||||
const data = { };
|
||||
const dataKey = 1;
|
||||
const expectedError = "ConstraintError";
|
||||
|
||||
let request = indexedDB.open(dbName, dbVersion);
|
||||
request.onerror = errorHandler;
|
||||
request.onupgradeneeded = grabEventAndContinueHandler;
|
||||
request.onsuccess = unexpectedSuccessHandler;
|
||||
|
||||
let event = yield undefined;
|
||||
|
||||
info("Creating database");
|
||||
|
||||
let db = event.target.result;
|
||||
let objectStore = db.createObjectStore(objectStoreName);
|
||||
objectStore.add(data, dataKey);
|
||||
|
||||
request.onupgradeneeded = unexpectedSuccessHandler;
|
||||
request.onsuccess = grabEventAndContinueHandler;
|
||||
|
||||
event = yield undefined;
|
||||
|
||||
db = event.target.result;
|
||||
|
||||
let transaction = db.transaction(objectStoreName, "readwrite");
|
||||
transaction.onerror = grabEventAndContinueHandler;
|
||||
transaction.oncomplete = grabEventAndContinueHandler;
|
||||
|
||||
objectStore = transaction.objectStore(objectStoreName);
|
||||
|
||||
info("Adding duplicate entry with preventDefault()");
|
||||
|
||||
let request = objectStore.add(data, dataKey);
|
||||
request.onsuccess = unexpectedSuccessHandler;
|
||||
request.onerror = grabEventAndContinueHandler;
|
||||
event = yield undefined;
|
||||
|
||||
is(event.type, "error", "Got an error event");
|
||||
is(event.target, request, "Error event targeted request");
|
||||
is(event.currentTarget, request, "Got request error first");
|
||||
is(event.currentTarget.error.name, expectedError,
|
||||
"Request has correct error");
|
||||
event.preventDefault();
|
||||
|
||||
event = yield undefined;
|
||||
|
||||
is(event.type, "error", "Got an error event");
|
||||
is(event.target, request, "Error event targeted request");
|
||||
is(event.currentTarget, transaction, "Got transaction error second");
|
||||
is(event.currentTarget.error, null, "Transaction has null error");
|
||||
|
||||
event = yield undefined;
|
||||
|
||||
is(event.type, "complete", "Got a complete event");
|
||||
is(event.target, transaction, "Complete event targeted transaction");
|
||||
is(event.currentTarget, transaction,
|
||||
"Complete event only targeted transaction");
|
||||
is(event.currentTarget.error, null, "Transaction has null error");
|
||||
|
||||
// Try again without preventDefault().
|
||||
|
||||
transaction = db.transaction(objectStoreName, "readwrite");
|
||||
transaction.onerror = grabEventAndContinueHandler;
|
||||
transaction.onabort = grabEventAndContinueHandler;
|
||||
|
||||
objectStore = transaction.objectStore(objectStoreName);
|
||||
|
||||
info("Adding duplicate entry without preventDefault()");
|
||||
|
||||
if ("SimpleTest" in this) {
|
||||
SimpleTest.expectUncaughtException();
|
||||
}
|
||||
|
||||
request = objectStore.add(data, dataKey);
|
||||
request.onsuccess = unexpectedSuccessHandler;
|
||||
request.onerror = grabEventAndContinueHandler;
|
||||
event = yield undefined;
|
||||
|
||||
is(event.type, "error", "Got an error event");
|
||||
is(event.target, request, "Error event targeted request");
|
||||
is(event.currentTarget, request, "Got request error first");
|
||||
is(event.currentTarget.error.name, expectedError,
|
||||
"Request has correct error");
|
||||
|
||||
event = yield undefined;
|
||||
|
||||
is(event.type, "error", "Got an error event");
|
||||
is(event.target, request, "Error event targeted request");
|
||||
is(event.currentTarget, transaction, "Got transaction error second");
|
||||
is(event.currentTarget.error, null, "Transaction has null error");
|
||||
|
||||
event = yield undefined;
|
||||
|
||||
is(event.type, "abort", "Got an abort event");
|
||||
is(event.target, transaction, "Abort event targeted transaction");
|
||||
is(event.currentTarget, transaction,
|
||||
"Abort event only targeted transaction");
|
||||
is(event.currentTarget.error.name, expectedError,
|
||||
"Transaction has correct error");
|
||||
|
||||
finishTest();
|
||||
yield undefined;
|
||||
}
|
|
@ -79,6 +79,7 @@ skip-if = os == "android" && processor == "x86"
|
|||
[test_traffic_jam.js]
|
||||
[test_transaction_abort.js]
|
||||
[test_transaction_abort_hang.js]
|
||||
[test_transaction_error.js]
|
||||
[test_transaction_lifetimes.js]
|
||||
[test_transaction_lifetimes_nested.js]
|
||||
[test_transaction_ordering.js]
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include "mozilla/dom/ExternalHelperAppChild.h"
|
||||
#include "mozilla/dom/PCrashReporterChild.h"
|
||||
#include "mozilla/dom/DOMStorageIPC.h"
|
||||
#include "mozilla/dom/Promise.h"
|
||||
#include "mozilla/hal_sandbox/PHalChild.h"
|
||||
#include "mozilla/ipc/BackgroundChild.h"
|
||||
#include "mozilla/ipc/FileDescriptorUtils.h"
|
||||
|
@ -1437,6 +1438,22 @@ ContentChild::AddRemoteAlertObserver(const nsString& aData,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
ContentChild::RecvSystemMemoryAvailable(const uint64_t& aGetterId,
|
||||
const uint32_t& aMemoryAvailable)
|
||||
{
|
||||
nsRefPtr<Promise> p = dont_AddRef(reinterpret_cast<Promise*>(aGetterId));
|
||||
|
||||
if (!aMemoryAvailable) {
|
||||
p->MaybeReject(NS_LITERAL_STRING("Abnormal"));
|
||||
return true;
|
||||
}
|
||||
|
||||
p->MaybeResolve((int)aMemoryAvailable);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ContentChild::RecvPreferenceUpdate(const PrefSetting& aPref)
|
||||
{
|
||||
|
|
|
@ -218,6 +218,9 @@ public:
|
|||
// auto remove when alertfinished is received.
|
||||
nsresult AddRemoteAlertObserver(const nsString& aData, nsIObserver* aObserver);
|
||||
|
||||
virtual bool RecvSystemMemoryAvailable(const uint64_t& aGetterId,
|
||||
const uint32_t& aMemoryAvailable) MOZ_OVERRIDE;
|
||||
|
||||
virtual bool RecvPreferenceUpdate(const PrefSetting& aPref) MOZ_OVERRIDE;
|
||||
|
||||
virtual bool RecvNotifyAlertsObserver(const nsCString& aType,
|
||||
|
|
|
@ -119,6 +119,10 @@
|
|||
#include "nsSystemInfo.h"
|
||||
#endif
|
||||
|
||||
#if defined(XP_LINUX)
|
||||
#include "mozilla/Hal.h"
|
||||
#endif
|
||||
|
||||
#ifdef ANDROID
|
||||
# include "gfxAndroidPlatform.h"
|
||||
#endif
|
||||
|
@ -3056,6 +3060,21 @@ ContentParent::RecvGetRandomValues(const uint32_t& length,
|
|||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ContentParent::RecvGetSystemMemory(const uint64_t& aGetterId)
|
||||
{
|
||||
uint32_t memoryTotal = 0;
|
||||
|
||||
#if defined(XP_LINUX)
|
||||
memoryTotal = mozilla::hal::GetTotalSystemMemoryLevel();
|
||||
#endif
|
||||
|
||||
unused << SendSystemMemoryAvailable(aGetterId, memoryTotal);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
ContentParent::RecvLoadURIExternal(const URIParams& uri)
|
||||
{
|
||||
|
|
|
@ -523,7 +523,7 @@ private:
|
|||
|
||||
virtual bool RecvAudioChannelChangeDefVolChannel(const int32_t& aChannel,
|
||||
const bool& aHidden) MOZ_OVERRIDE;
|
||||
|
||||
virtual bool RecvGetSystemMemory(const uint64_t& getterId) MOZ_OVERRIDE;
|
||||
virtual bool RecvBroadcastVolume(const nsString& aVolumeName) MOZ_OVERRIDE;
|
||||
|
||||
virtual bool RecvSpeakerManagerGetSpeakerStatus(bool* aValue) MOZ_OVERRIDE;
|
||||
|
|
|
@ -357,6 +357,8 @@ child:
|
|||
|
||||
async NotifyVisited(URIParams uri);
|
||||
|
||||
async SystemMemoryAvailable(uint64_t getterId, uint32_t memoryAvailable);
|
||||
|
||||
PreferenceUpdate(PrefSetting pref);
|
||||
|
||||
NotifyAlertsObserver(nsCString topic, nsString data);
|
||||
|
@ -436,6 +438,8 @@ parent:
|
|||
sync GetRandomValues(uint32_t length)
|
||||
returns (uint8_t[] randomValues);
|
||||
|
||||
async GetSystemMemory(uint64_t getterId);
|
||||
|
||||
PHal();
|
||||
|
||||
PIndexedDB();
|
||||
|
|
|
@ -168,6 +168,209 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
enum {
|
||||
SLOT_PROMISE = 0,
|
||||
SLOT_DATA
|
||||
};
|
||||
|
||||
/*
|
||||
* Utilities for thenable callbacks.
|
||||
*
|
||||
* A thenable is a { then: function(resolve, reject) { } }.
|
||||
* `then` is called with a resolve and reject callback pair.
|
||||
* Since only one of these should be called at most once (first call wins), the
|
||||
* two keep a reference to each other in SLOT_DATA. When either of them is
|
||||
* called, the references are cleared. Further calls are ignored.
|
||||
*/
|
||||
namespace {
|
||||
void
|
||||
LinkThenableCallables(JSContext* aCx, JS::Handle<JSObject*> aResolveFunc,
|
||||
JS::Handle<JSObject*> aRejectFunc)
|
||||
{
|
||||
js::SetFunctionNativeReserved(aResolveFunc, SLOT_DATA,
|
||||
JS::ObjectValue(*aRejectFunc));
|
||||
js::SetFunctionNativeReserved(aRejectFunc, SLOT_DATA,
|
||||
JS::ObjectValue(*aResolveFunc));
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns false if callback was already called before, otherwise breaks the
|
||||
* links and returns true.
|
||||
*/
|
||||
bool
|
||||
MarkAsCalledIfNotCalledBefore(JSContext* aCx, JS::Handle<JSObject*> aFunc)
|
||||
{
|
||||
JS::Value otherFuncVal = js::GetFunctionNativeReserved(aFunc, SLOT_DATA);
|
||||
|
||||
if (!otherFuncVal.isObject()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
JSObject* otherFuncObj = &otherFuncVal.toObject();
|
||||
MOZ_ASSERT(js::GetFunctionNativeReserved(otherFuncObj, SLOT_DATA).isObject());
|
||||
|
||||
// Break both references.
|
||||
js::SetFunctionNativeReserved(aFunc, SLOT_DATA, JS::UndefinedValue());
|
||||
js::SetFunctionNativeReserved(otherFuncObj, SLOT_DATA, JS::UndefinedValue());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Promise*
|
||||
GetPromise(JSContext* aCx, JS::Handle<JSObject*> aFunc)
|
||||
{
|
||||
JS::Value promiseVal = js::GetFunctionNativeReserved(aFunc, SLOT_PROMISE);
|
||||
|
||||
MOZ_ASSERT(promiseVal.isObject());
|
||||
|
||||
Promise* promise;
|
||||
UNWRAP_OBJECT(Promise, &promiseVal.toObject(), promise);
|
||||
return promise;
|
||||
}
|
||||
};
|
||||
|
||||
// Equivalent to the specification's ResolvePromiseViaThenableTask.
|
||||
class ThenableResolverMixin
|
||||
{
|
||||
public:
|
||||
ThenableResolverMixin(Promise* aPromise,
|
||||
JS::Handle<JSObject*> aThenable,
|
||||
PromiseInit* aThen)
|
||||
: mPromise(aPromise)
|
||||
, mThenable(CycleCollectedJSRuntime::Get()->Runtime(), aThenable)
|
||||
, mThen(aThen)
|
||||
{
|
||||
MOZ_ASSERT(aPromise);
|
||||
MOZ_COUNT_CTOR(ThenableResolverMixin);
|
||||
}
|
||||
|
||||
virtual ~ThenableResolverMixin()
|
||||
{
|
||||
NS_ASSERT_OWNINGTHREAD(ThenableResolverMixin);
|
||||
MOZ_COUNT_DTOR(ThenableResolverMixin);
|
||||
}
|
||||
|
||||
protected:
|
||||
void
|
||||
RunInternal()
|
||||
{
|
||||
NS_ASSERT_OWNINGTHREAD(ThenableResolverMixin);
|
||||
ThreadsafeAutoJSContext cx;
|
||||
JS::Rooted<JSObject*> wrapper(cx, mPromise->GetOrCreateWrapper(cx));
|
||||
if (!wrapper) {
|
||||
return;
|
||||
}
|
||||
JSAutoCompartment ac(cx, wrapper);
|
||||
|
||||
JS::Rooted<JSObject*> resolveFunc(cx,
|
||||
mPromise->CreateThenableFunction(cx, mPromise, PromiseCallback::Resolve));
|
||||
|
||||
if (!resolveFunc) {
|
||||
mPromise->HandleException(cx);
|
||||
return;
|
||||
}
|
||||
|
||||
JS::Rooted<JSObject*> rejectFunc(cx,
|
||||
mPromise->CreateThenableFunction(cx, mPromise, PromiseCallback::Reject));
|
||||
if (!rejectFunc) {
|
||||
mPromise->HandleException(cx);
|
||||
return;
|
||||
}
|
||||
|
||||
LinkThenableCallables(cx, resolveFunc, rejectFunc);
|
||||
|
||||
ErrorResult rv;
|
||||
|
||||
JS::Rooted<JSObject*> rootedThenable(cx, mThenable);
|
||||
|
||||
mThen->Call(rootedThenable, resolveFunc, rejectFunc, rv,
|
||||
CallbackObject::eRethrowExceptions);
|
||||
|
||||
rv.WouldReportJSException();
|
||||
if (rv.IsJSException()) {
|
||||
JS::Rooted<JS::Value> exn(cx);
|
||||
rv.StealJSException(cx, &exn);
|
||||
|
||||
bool couldMarkAsCalled = MarkAsCalledIfNotCalledBefore(cx, resolveFunc);
|
||||
|
||||
// If we could mark as called, neither of the callbacks had been called
|
||||
// when the exception was thrown. So we can reject the Promise.
|
||||
if (couldMarkAsCalled) {
|
||||
bool ok = JS_WrapValue(cx, &exn);
|
||||
MOZ_ASSERT(ok);
|
||||
if (!ok) {
|
||||
NS_WARNING("Failed to wrap value into the right compartment.");
|
||||
}
|
||||
|
||||
mPromise->RejectInternal(cx, exn, Promise::SyncTask);
|
||||
}
|
||||
// At least one of resolveFunc or rejectFunc have been called, so ignore
|
||||
// the exception. FIXME(nsm): This should be reported to the error
|
||||
// console though, for debugging.
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
nsRefPtr<Promise> mPromise;
|
||||
JS::PersistentRooted<JSObject*> mThenable;
|
||||
nsRefPtr<PromiseInit> mThen;
|
||||
NS_DECL_OWNINGTHREAD;
|
||||
};
|
||||
|
||||
// Main thread runnable to resolve thenables.
|
||||
class ThenableResolverTask MOZ_FINAL : public nsRunnable,
|
||||
public ThenableResolverMixin
|
||||
{
|
||||
public:
|
||||
ThenableResolverTask(Promise* aPromise,
|
||||
JS::Handle<JSObject*> aThenable,
|
||||
PromiseInit* aThen)
|
||||
: ThenableResolverMixin(aPromise, aThenable, aThen)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
}
|
||||
|
||||
~ThenableResolverTask()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
}
|
||||
|
||||
NS_IMETHOD Run()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
RunInternal();
|
||||
return NS_OK;
|
||||
}
|
||||
};
|
||||
|
||||
// Worker thread runnable to resolve thenables.
|
||||
class WorkerThenableResolverTask MOZ_FINAL : public WorkerSameThreadRunnable,
|
||||
public ThenableResolverMixin
|
||||
{
|
||||
public:
|
||||
WorkerThenableResolverTask(WorkerPrivate* aWorkerPrivate,
|
||||
Promise* aPromise,
|
||||
JS::Handle<JSObject*> aThenable,
|
||||
PromiseInit* aThen)
|
||||
: WorkerSameThreadRunnable(aWorkerPrivate),
|
||||
ThenableResolverMixin(aPromise, aThenable, aThen)
|
||||
{
|
||||
MOZ_ASSERT(aWorkerPrivate);
|
||||
aWorkerPrivate->AssertIsOnWorkerThread();
|
||||
}
|
||||
|
||||
~WorkerThenableResolverTask()
|
||||
{}
|
||||
|
||||
bool
|
||||
WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate)
|
||||
{
|
||||
aWorkerPrivate->AssertIsOnWorkerThread();
|
||||
RunInternal();
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
// Promise
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_CLASS(Promise)
|
||||
|
@ -267,11 +470,6 @@ Promise::MaybeReject(JSContext* aCx,
|
|||
MaybeRejectInternal(aCx, aValue);
|
||||
}
|
||||
|
||||
enum {
|
||||
SLOT_PROMISE = 0,
|
||||
SLOT_DATA
|
||||
};
|
||||
|
||||
/* static */ bool
|
||||
Promise::JSCallback(JSContext* aCx, unsigned aArgc, JS::Value* aVp)
|
||||
{
|
||||
|
@ -299,62 +497,6 @@ Promise::JSCallback(JSContext* aCx, unsigned aArgc, JS::Value* aVp)
|
|||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Utilities for thenable callbacks.
|
||||
*
|
||||
* A thenable is a { then: function(resolve, reject) { } }.
|
||||
* `then` is called with a resolve and reject callback pair.
|
||||
* Since only one of these should be called at most once (first call wins), the
|
||||
* two keep a reference to each other in SLOT_DATA. When either of them is
|
||||
* called, the references are cleared. Further calls are ignored.
|
||||
*/
|
||||
namespace {
|
||||
void
|
||||
LinkThenableCallables(JSContext* aCx, JS::Handle<JSObject*> aResolveFunc,
|
||||
JS::Handle<JSObject*> aRejectFunc)
|
||||
{
|
||||
js::SetFunctionNativeReserved(aResolveFunc, SLOT_DATA,
|
||||
JS::ObjectValue(*aRejectFunc));
|
||||
js::SetFunctionNativeReserved(aRejectFunc, SLOT_DATA,
|
||||
JS::ObjectValue(*aResolveFunc));
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns false if callback was already called before, otherwise breaks the
|
||||
* links and returns true.
|
||||
*/
|
||||
bool
|
||||
MarkAsCalledIfNotCalledBefore(JSContext* aCx, JS::Handle<JSObject*> aFunc)
|
||||
{
|
||||
JS::Value otherFuncVal = js::GetFunctionNativeReserved(aFunc, SLOT_DATA);
|
||||
|
||||
if (!otherFuncVal.isObject()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
JSObject* otherFuncObj = &otherFuncVal.toObject();
|
||||
MOZ_ASSERT(js::GetFunctionNativeReserved(otherFuncObj, SLOT_DATA).isObject());
|
||||
|
||||
// Break both references.
|
||||
js::SetFunctionNativeReserved(aFunc, SLOT_DATA, JS::UndefinedValue());
|
||||
js::SetFunctionNativeReserved(otherFuncObj, SLOT_DATA, JS::UndefinedValue());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Promise*
|
||||
GetPromise(JSContext* aCx, JS::Handle<JSObject*> aFunc)
|
||||
{
|
||||
JS::Value promiseVal = js::GetFunctionNativeReserved(aFunc, SLOT_PROMISE);
|
||||
|
||||
MOZ_ASSERT(promiseVal.isObject());
|
||||
|
||||
Promise* promise;
|
||||
UNWRAP_OBJECT(Promise, &promiseVal.toObject(), promise);
|
||||
return promise;
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* Common bits of (JSCallbackThenableResolver/JSCallbackThenableRejecter).
|
||||
* Resolves/rejects the Promise if it is ok to do so, based on whether either of
|
||||
|
@ -375,9 +517,9 @@ Promise::ThenableResolverCommon(JSContext* aCx, uint32_t aTask,
|
|||
MOZ_ASSERT(promise);
|
||||
|
||||
if (aTask == PromiseCallback::Resolve) {
|
||||
promise->ResolveInternal(aCx, args.get(0), SyncTask);
|
||||
promise->ResolveInternal(aCx, args.get(0));
|
||||
} else {
|
||||
promise->RejectInternal(aCx, args.get(0), SyncTask);
|
||||
promise->RejectInternal(aCx, args.get(0));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -982,52 +1124,20 @@ Promise::ResolveInternal(JSContext* aCx,
|
|||
}
|
||||
|
||||
if (then.isObject() && JS_ObjectIsCallable(aCx, &then.toObject())) {
|
||||
JS::Rooted<JSObject*> resolveFunc(aCx,
|
||||
CreateThenableFunction(aCx, this, PromiseCallback::Resolve));
|
||||
|
||||
if (!resolveFunc) {
|
||||
HandleException(aCx);
|
||||
return;
|
||||
}
|
||||
|
||||
JS::Rooted<JSObject*> rejectFunc(aCx,
|
||||
CreateThenableFunction(aCx, this, PromiseCallback::Reject));
|
||||
if (!rejectFunc) {
|
||||
HandleException(aCx);
|
||||
return;
|
||||
}
|
||||
|
||||
LinkThenableCallables(aCx, resolveFunc, rejectFunc);
|
||||
|
||||
// This is the then() function of the thenable aValueObj.
|
||||
JS::Rooted<JSObject*> thenObj(aCx, &then.toObject());
|
||||
nsRefPtr<PromiseInit> thenCallback =
|
||||
new PromiseInit(thenObj, mozilla::dom::GetIncumbentGlobal());
|
||||
|
||||
ErrorResult rv;
|
||||
thenCallback->Call(valueObj, resolveFunc, rejectFunc,
|
||||
rv, CallbackObject::eRethrowExceptions);
|
||||
rv.WouldReportJSException();
|
||||
|
||||
if (rv.IsJSException()) {
|
||||
JS::Rooted<JS::Value> exn(aCx);
|
||||
rv.StealJSException(aCx, &exn);
|
||||
|
||||
bool couldMarkAsCalled = MarkAsCalledIfNotCalledBefore(aCx, resolveFunc);
|
||||
|
||||
// If we could mark as called, neither of the callbacks had been called
|
||||
// when the exception was thrown. So we can reject the Promise.
|
||||
if (couldMarkAsCalled) {
|
||||
bool ok = JS_WrapValue(aCx, &exn);
|
||||
MOZ_ASSERT(ok);
|
||||
if (!ok) {
|
||||
NS_WARNING("Failed to wrap value into the right compartment.");
|
||||
}
|
||||
|
||||
RejectInternal(aCx, exn, Promise::SyncTask);
|
||||
}
|
||||
// At least one of resolveFunc or rejectFunc have been called, so ignore
|
||||
// the exception. FIXME(nsm): This should be reported to the error
|
||||
// console though, for debugging.
|
||||
if (NS_IsMainThread()) {
|
||||
nsRefPtr<ThenableResolverTask> task =
|
||||
new ThenableResolverTask(this, valueObj, thenCallback);
|
||||
NS_DispatchToCurrentThread(task);
|
||||
} else {
|
||||
WorkerPrivate* worker = GetCurrentThreadWorkerPrivate();
|
||||
MOZ_ASSERT(worker);
|
||||
nsRefPtr<WorkerThenableResolverTask> task =
|
||||
new WorkerThenableResolverTask(worker, this, valueObj, thenCallback);
|
||||
task->Dispatch(worker->GetJSContext());
|
||||
}
|
||||
|
||||
return;
|
||||
|
|
|
@ -59,6 +59,7 @@ class Promise MOZ_FINAL : public nsISupports,
|
|||
friend class PromiseWorkerProxyRunnable;
|
||||
friend class RejectPromiseCallback;
|
||||
friend class ResolvePromiseCallback;
|
||||
friend class ThenableResolverMixin;
|
||||
friend class WorkerPromiseResolverTask;
|
||||
friend class WorkerPromiseTask;
|
||||
friend class WrapperPromiseCallback;
|
||||
|
|
|
@ -618,6 +618,59 @@ function promiseResolvePromise() {
|
|||
});
|
||||
}
|
||||
|
||||
// Bug 1009569.
|
||||
// Ensure that thenables are run on a clean stack asynchronously.
|
||||
// Test case adopted from
|
||||
// https://gist.github.com/getify/d64bb01751b50ed6b281#file-bug1-js.
|
||||
function promiseResolveThenableCleanStack() {
|
||||
function immed(s) { x++; s(); }
|
||||
function incX(){ x++; }
|
||||
|
||||
var x = 0;
|
||||
var thenable = { then: immed };
|
||||
var results = [];
|
||||
|
||||
Promise.resolve(thenable).then(incX);
|
||||
results.push(x);
|
||||
|
||||
// check what happens after all "next cycle" steps
|
||||
// have had a chance to complete
|
||||
setTimeout(function(){
|
||||
results.push(x);
|
||||
// Result should be [0, 2] since `thenable` will be called async.
|
||||
is(results[0], 0, "Expected thenable to be called asynchronously");
|
||||
is(results[1], 2, "Expected thenable to be called asynchronously");
|
||||
runTest();
|
||||
},1000);
|
||||
}
|
||||
|
||||
// Bug 1008467 - Promise fails with "too much recursion".
|
||||
// The bug was that the callbacks passed to a thenable would resolve the
|
||||
// promise synchronously when the fulfill handler returned a non-thenable.
|
||||
//
|
||||
// For example:
|
||||
// var p = new Promise(function(resolve) {
|
||||
// resolve(5);
|
||||
// });
|
||||
// var m = Promise.resolve(p);
|
||||
//
|
||||
// At this point `m` is a Promise that is resolved with a thenable `p`, so it
|
||||
// calls `p.then()` with two callbacks, both of which would synchronously resolve
|
||||
// `m` when `p` invoked them (on account of itself being resolved, possibly
|
||||
// synchronously. A chain of these 'Promise resolved by a Promise' would lead to
|
||||
// stack overflow.
|
||||
function promiseTestAsyncThenableResolution()
|
||||
{
|
||||
var k = 3000;
|
||||
Promise.resolve().then(function next() {
|
||||
k--;
|
||||
if (k > 0) return Promise.resolve().then(next);
|
||||
}).then(function () {
|
||||
ok(true, "Resolution of a chain of thenables should not be synchronous.");
|
||||
runTest();
|
||||
});
|
||||
}
|
||||
|
||||
var tests = [ promiseResolve, promiseReject,
|
||||
promiseException, promiseGC, promiseAsync,
|
||||
promiseDoubleThen, promiseThenException,
|
||||
|
@ -648,6 +701,8 @@ var tests = [ promiseResolve, promiseReject,
|
|||
promiseResolveArray,
|
||||
promiseResolveThenable,
|
||||
promiseResolvePromise,
|
||||
promiseResolveThenableCleanStack,
|
||||
promiseTestAsyncThenableResolution,
|
||||
];
|
||||
|
||||
function runTest() {
|
||||
|
|
|
@ -17,6 +17,8 @@
|
|||
#ifndef ANDROID_AUDIOSYSTEM_H_
|
||||
#define ANDROID_AUDIOSYSTEM_H_
|
||||
|
||||
#pragma GCC visibility push(default)
|
||||
|
||||
#include <utils/RefBase.h>
|
||||
#include <utils/threads.h>
|
||||
#include "IAudioFlinger.h"
|
||||
|
@ -961,4 +963,6 @@ private:
|
|||
|
||||
}; // namespace android
|
||||
|
||||
#pragma GCC visibility pop
|
||||
|
||||
#endif /*ANDROID_AUDIOSYSTEM_H_*/
|
||||
|
|
|
@ -381,6 +381,8 @@ var interfaceNamesInGlobalScope =
|
|||
"HashChangeEvent",
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
"History",
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
"HTMLAllCollection",
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
"HTMLAnchorElement",
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
/* 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/. */
|
||||
|
||||
/* Emulates undefined through Codegen.py. */
|
||||
interface HTMLAllCollection {
|
||||
readonly attribute unsigned long length;
|
||||
getter Node? (unsigned long index);
|
||||
Node? item(unsigned long index);
|
||||
(Node or HTMLCollection)? item(DOMString name);
|
||||
legacycaller (Node or HTMLCollection)? (DOMString name);
|
||||
getter (Node or HTMLCollection)? namedItem(DOMString name);
|
||||
};
|
|
@ -72,8 +72,7 @@ interface HTMLDocument : Document {
|
|||
|
||||
void clear();
|
||||
|
||||
[Throws]
|
||||
readonly attribute object all;
|
||||
readonly attribute HTMLAllCollection all;
|
||||
|
||||
// https://dvcs.w3.org/hg/editing/raw-file/tip/editing.html#selections
|
||||
[Throws]
|
||||
|
|
|
@ -19,7 +19,6 @@ interface IDBTransaction : EventTarget {
|
|||
readonly attribute IDBTransactionMode mode;
|
||||
readonly attribute IDBDatabase db;
|
||||
|
||||
[Throws]
|
||||
readonly attribute DOMError? error;
|
||||
|
||||
[Throws]
|
||||
|
|
|
@ -10,6 +10,13 @@
|
|||
* liability, trademark and document use rules apply.
|
||||
*/
|
||||
|
||||
dictionary SVGBoundingBoxOptions {
|
||||
boolean fill = true;
|
||||
boolean stroke = false;
|
||||
boolean markers = false;
|
||||
boolean clipped = false;
|
||||
};
|
||||
|
||||
interface SVGGraphicsElement : SVGElement {
|
||||
readonly attribute SVGAnimatedTransformList transform;
|
||||
|
||||
|
@ -17,7 +24,7 @@ interface SVGGraphicsElement : SVGElement {
|
|||
readonly attribute SVGElement? farthestViewportElement;
|
||||
|
||||
[NewObject, Throws]
|
||||
SVGRect getBBox();
|
||||
SVGRect getBBox(optional SVGBoundingBoxOptions aOptions);
|
||||
// Not implemented
|
||||
// SVGRect getStrokeBBox();
|
||||
SVGMatrix? getCTM();
|
||||
|
|
|
@ -72,7 +72,8 @@ typedef any Transferable;
|
|||
[Throws] readonly attribute ApplicationCache applicationCache;
|
||||
|
||||
// user prompts
|
||||
[Throws] void alert(optional DOMString message = "");
|
||||
[Throws] void alert();
|
||||
[Throws] void alert(DOMString message);
|
||||
[Throws] boolean confirm(optional DOMString message = "");
|
||||
[Throws] DOMString? prompt(optional DOMString message = "", optional DOMString default = "");
|
||||
[Throws] void print();
|
||||
|
@ -294,9 +295,9 @@ partial interface Window {
|
|||
|
||||
[Throws] attribute boolean fullScreen;
|
||||
|
||||
[Throws] void back();
|
||||
[Throws] void forward();
|
||||
[Throws] void home();
|
||||
[Throws, ChromeOnly] void back();
|
||||
[Throws, ChromeOnly] void forward();
|
||||
[Throws, ChromeOnly] void home();
|
||||
|
||||
// XXX Should this be in nsIDOMChromeWindow?
|
||||
void updateCommands(DOMString action);
|
||||
|
|
|
@ -124,6 +124,7 @@ WEBIDL_FILES = [
|
|||
'GeometryUtils.webidl',
|
||||
'GetUserMediaRequest.webidl',
|
||||
'History.webidl',
|
||||
'HTMLAllCollection.webidl',
|
||||
'HTMLAnchorElement.webidl',
|
||||
'HTMLAppletElement.webidl',
|
||||
'HTMLAreaElement.webidl',
|
||||
|
|
|
@ -654,6 +654,32 @@ function promiseResolvePromise() {
|
|||
});
|
||||
}
|
||||
|
||||
// Bug 1009569.
|
||||
// Ensure that thenables are run on a clean stack asynchronously.
|
||||
// Test case adopted from
|
||||
// https://gist.github.com/getify/d64bb01751b50ed6b281#file-bug1-js.
|
||||
function promiseResolveThenableCleanStack() {
|
||||
function immed(s) { x++; s(); }
|
||||
function incX(){ x++; }
|
||||
|
||||
var x = 0;
|
||||
var thenable = { then: immed };
|
||||
var results = [];
|
||||
|
||||
Promise.resolve(thenable).then(incX);
|
||||
results.push(x);
|
||||
|
||||
// check what happens after all "next cycle" steps
|
||||
// have had a chance to complete
|
||||
setTimeout(function(){
|
||||
results.push(x);
|
||||
// Result should be [0, 2] since `thenable` will be called async.
|
||||
is(results[0], 0, "Expected thenable to be called asynchronously");
|
||||
is(results[1], 2, "Expected thenable to be called asynchronously");
|
||||
runTest();
|
||||
},1000);
|
||||
}
|
||||
|
||||
var tests = [
|
||||
promiseResolve,
|
||||
promiseReject,
|
||||
|
@ -698,6 +724,8 @@ var tests = [
|
|||
promiseResolveArray,
|
||||
promiseResolveThenable,
|
||||
promiseResolvePromise,
|
||||
|
||||
promiseResolveThenableCleanStack,
|
||||
];
|
||||
|
||||
function runTest() {
|
||||
|
|
|
@ -63,7 +63,9 @@ txExecutionState::~txExecutionState()
|
|||
|
||||
delete mResultHandler;
|
||||
delete mLocalVariables;
|
||||
if (mEvalContext != mInitialEvalContext) {
|
||||
delete mEvalContext;
|
||||
}
|
||||
|
||||
txStackIterator varsIter(&mLocalVarsStack);
|
||||
while (varsIter.hasNext()) {
|
||||
|
@ -87,6 +89,8 @@ txExecutionState::~txExecutionState()
|
|||
while (paramIter.hasNext()) {
|
||||
delete (txVariableMap*)paramIter.next();
|
||||
}
|
||||
|
||||
delete mInitialEvalContext;
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
|
|
@ -546,9 +546,6 @@ const knownFailures = {
|
|||
"S-Proposed-SM:e.b.lb_P.P.P-1_SIR-2-dM": true,
|
||||
"S-Proposed-SM:e.b.lb_P.P.P-1_SIR-2-body": true,
|
||||
"S-Proposed-SM:e.b.lb_P.P.P-1_SIR-2-div": true,
|
||||
"S-Proposed-SM:e.f.l_BR.BR-2_SI-1-dM": true,
|
||||
"S-Proposed-SM:e.f.l_BR.BR-2_SI-1-body": true,
|
||||
"S-Proposed-SM:e.f.l_BR.BR-2_SI-1-div": true,
|
||||
"A-Proposed-B_TEXT-1_SI-dM": true,
|
||||
"A-Proposed-B_TEXT-1_SI-body": true,
|
||||
"A-Proposed-B_TEXT-1_SI-div": true,
|
||||
|
|
|
@ -9103,557 +9103,564 @@
|
|||
< anecdotal
|
||||
---
|
||||
> anecdotal/Y
|
||||
11804c17614
|
||||
11750a17561,17562
|
||||
> anonymization/SM
|
||||
> anonymize/DSG
|
||||
11804c17616
|
||||
< anthropomorphizing
|
||||
---
|
||||
> anthropomorphize/DSG
|
||||
11983c17793
|
||||
11983c17795
|
||||
< app/S
|
||||
---
|
||||
> app/MS
|
||||
12137a17948
|
||||
12137a17950
|
||||
> archaeology/M
|
||||
12152c17963
|
||||
12152c17965
|
||||
< archeological
|
||||
---
|
||||
> archeological/Y
|
||||
12432c18243
|
||||
12432c18245
|
||||
< assignees
|
||||
---
|
||||
> assignee/MS
|
||||
12685c18496
|
||||
12685c18498
|
||||
< auteur
|
||||
---
|
||||
> auteur/MS
|
||||
12713a18525
|
||||
12713a18527
|
||||
> autocomplete/S
|
||||
12754a18567
|
||||
12754a18569
|
||||
> avant-garde
|
||||
12827d18639
|
||||
12827d18641
|
||||
< awol
|
||||
12829a18642
|
||||
12829a18644
|
||||
> axe/M
|
||||
13864a19678
|
||||
13864a19680
|
||||
> biodiesel/M
|
||||
14210d20023
|
||||
14210d20025
|
||||
< blueing's
|
||||
14434a20248
|
||||
14434a20250
|
||||
> bookselling
|
||||
14841c20655
|
||||
14841c20657
|
||||
< broadcast/AMGS
|
||||
---
|
||||
> broadcast/AMGSD
|
||||
15039,15040c20853
|
||||
15039,15040c20855
|
||||
< bullshitter's
|
||||
< bullshitter/S!
|
||||
---
|
||||
> bullshitter/SM!
|
||||
15230d21042
|
||||
15230d21044
|
||||
< byelaw/SM
|
||||
15383d21194
|
||||
15383d21196
|
||||
< callisthenics/M
|
||||
15460a21272,21274
|
||||
15460a21274,21276
|
||||
> cancelled/U
|
||||
> canceller/M
|
||||
> cancelling
|
||||
15559a21374
|
||||
15559a21376
|
||||
> capita
|
||||
15629,15630d21443
|
||||
15629,15630d21445
|
||||
< carburetter/SM
|
||||
< carburettor/SM
|
||||
15701a21515
|
||||
15701a21517
|
||||
> carnitas
|
||||
15788d21601
|
||||
15788d21603
|
||||
< cashpoint/S
|
||||
15797d21609
|
||||
15797d21611
|
||||
< cassino/M
|
||||
15832a21645
|
||||
15832a21647
|
||||
> catalyses
|
||||
15940d21752
|
||||
15940d21754
|
||||
< caviare/M
|
||||
16372c22184
|
||||
16372c22186
|
||||
< chickenshit/S!
|
||||
---
|
||||
> chickenshit/SM!
|
||||
16404c22216
|
||||
16404c22218
|
||||
< children
|
||||
---
|
||||
> children/M
|
||||
16488d22299
|
||||
16488d22301
|
||||
< chlorophyl/M
|
||||
16629,16630c22440
|
||||
16629,16630c22442
|
||||
< cider's
|
||||
< cider/S
|
||||
---
|
||||
> cider/MS
|
||||
16652a22463
|
||||
16652a22465
|
||||
> ciphertext/S
|
||||
17072d22882
|
||||
17072d22884
|
||||
< cocain/M
|
||||
17102,17103c22912
|
||||
17102,17103c22914
|
||||
< cocksucker's
|
||||
< cocksucker/S!
|
||||
---
|
||||
> cocksucker/SM!
|
||||
17755c23564
|
||||
17755c23566
|
||||
< confer/S
|
||||
---
|
||||
> confer/SB
|
||||
17800a23610
|
||||
17800a23612
|
||||
> conformant
|
||||
18151d23960
|
||||
18151d23962
|
||||
< convenor/S
|
||||
18206c24015
|
||||
18206c24017
|
||||
< cookie/M
|
||||
---
|
||||
> cookie/SM
|
||||
18375a24185,24186
|
||||
18375a24187,24188
|
||||
> corrigibility/IM
|
||||
> corrigible/I
|
||||
18389a24201
|
||||
18389a24203
|
||||
> corruptibly/I
|
||||
18467a24280
|
||||
18467a24282
|
||||
> could've
|
||||
18999a24813
|
||||
18999a24815
|
||||
> cryptologist/MS
|
||||
19000a24815
|
||||
19000a24817
|
||||
> cryptosystem/S
|
||||
19035a24851
|
||||
19035a24853
|
||||
> cul-de-sac
|
||||
19246c25062
|
||||
19246c25064
|
||||
< cysteine
|
||||
---
|
||||
> cysteine/M
|
||||
19935a25752
|
||||
19935a25754
|
||||
> dequeue/DSG
|
||||
20196,20197c26013,26014
|
||||
20196,20197c26015,26016
|
||||
< dialog/SM
|
||||
< dialogue/SM
|
||||
---
|
||||
> dialog/SMGD
|
||||
> dialogue/SMRGD
|
||||
20220a26038
|
||||
20220a26040
|
||||
> diatomaceous
|
||||
20481a26300
|
||||
20481a26302
|
||||
> disclose/DSG
|
||||
20633a26453
|
||||
20633a26455
|
||||
> dissentious
|
||||
20830c26650
|
||||
20830c26652
|
||||
< dogie/M
|
||||
---
|
||||
> dogie/SM
|
||||
20895a26716
|
||||
20895a26718
|
||||
> donator/MS
|
||||
21820a27642
|
||||
21820a27644
|
||||
> elicitor/MS
|
||||
22071a27894
|
||||
22071a27896
|
||||
> encyclopaedia
|
||||
22196a28020
|
||||
22196a28022
|
||||
> enqueue/DSG
|
||||
22556a28381
|
||||
22556a28383
|
||||
> estoppel
|
||||
22638c28463
|
||||
22638c28465
|
||||
< euthanize
|
||||
---
|
||||
> euthanize/DSG
|
||||
22719a28545
|
||||
22719a28547
|
||||
> exabyte/MS
|
||||
22947a28774
|
||||
22947a28776
|
||||
> experimentalism
|
||||
23207,23208d29033
|
||||
23207,23208d29035
|
||||
< faecal
|
||||
< faeces/M
|
||||
23215c29040
|
||||
23215c29042
|
||||
< faggoting's
|
||||
---
|
||||
> faggot/SMG
|
||||
23701a29527
|
||||
23701a29529
|
||||
> filesystem/MS
|
||||
24155c29981
|
||||
24155c29983
|
||||
< fluidized
|
||||
---
|
||||
> fluidize/DSG
|
||||
24216a30043
|
||||
24216a30045
|
||||
> foci
|
||||
24736d30562
|
||||
24736d30564
|
||||
< frier/M
|
||||
24855,24856c30681,30682
|
||||
24855,24856c30683,30684
|
||||
< fucker/M!
|
||||
< fuckhead/S!
|
||||
---
|
||||
> fucker/SM!
|
||||
> fuckhead/SM!
|
||||
24953d30778
|
||||
24953d30780
|
||||
< furore/MS
|
||||
25125c30950
|
||||
25125c30952
|
||||
< gaolbird/S
|
||||
---
|
||||
> gaolbirds
|
||||
25180d31004
|
||||
25180d31006
|
||||
< gasolene/M
|
||||
25190a31015
|
||||
25190a31017
|
||||
> gastroenterologist/M
|
||||
25262c31087
|
||||
25262c31089
|
||||
< geezer/M
|
||||
---
|
||||
> geezer/MS
|
||||
25327c31152
|
||||
25327c31154
|
||||
< genomic
|
||||
---
|
||||
> genomic/S
|
||||
25462a31288
|
||||
25462a31290
|
||||
> gigabit/MS
|
||||
25464a31291,31293
|
||||
25464a31293,31295
|
||||
> gigajoule/MS
|
||||
> gigapixel/MS
|
||||
> gigawatt/MS
|
||||
25560d31388
|
||||
25560d31390
|
||||
< glamourize/DSG
|
||||
25674c31502
|
||||
25674c31504
|
||||
< glycerine's
|
||||
---
|
||||
> glycerine/M
|
||||
25905c31733
|
||||
25905c31735
|
||||
< gram/MS
|
||||
---
|
||||
> gram/KMS
|
||||
25909d31736
|
||||
25909d31738
|
||||
< gramme/SM
|
||||
26063c31890,31891
|
||||
26063c31892,31893
|
||||
< greybeard
|
||||
---
|
||||
> grey/MDRTGSP
|
||||
> greybeard/SM
|
||||
26066c31894
|
||||
26066c31896
|
||||
< greyness
|
||||
---
|
||||
> greyness/M
|
||||
26246,26247d32073
|
||||
26246,26247d32075
|
||||
< guerilla's
|
||||
< guerillas
|
||||
26432,26436d32257
|
||||
26432,26436d32259
|
||||
< haemoglobin's
|
||||
< haemophilia/M
|
||||
< haemorrhage/DSMG
|
||||
< haemorrhoid/S
|
||||
< haemorrhoids/M
|
||||
27167c32988
|
||||
27167c32990
|
||||
< hexane
|
||||
---
|
||||
> hexane/SM
|
||||
27273a33095
|
||||
27273a33097
|
||||
> hippopotami
|
||||
27875d33696
|
||||
27875d33698
|
||||
< hyaena/SM
|
||||
28017c33838
|
||||
28017c33840
|
||||
< iPod/M
|
||||
---
|
||||
> iPod/MS
|
||||
28105a33927
|
||||
28105a33929
|
||||
> idolator/SM
|
||||
28513c34335
|
||||
28227c34051
|
||||
< immerse/XDSGN
|
||||
---
|
||||
> immerse/XDSGNV
|
||||
28513c34337
|
||||
< inbound
|
||||
---
|
||||
> inbound/s
|
||||
28590,28591c34412
|
||||
28590,28591c34414
|
||||
< incorrigibility/M
|
||||
< incorrigible
|
||||
---
|
||||
> incorrigibleness
|
||||
28593d34413
|
||||
28593d34415
|
||||
< incorruptibly
|
||||
28650a34471
|
||||
28650a34473
|
||||
> indices
|
||||
28812d34632
|
||||
28812d34634
|
||||
< inflexion/SM
|
||||
29216a35037
|
||||
29216a35039
|
||||
> intern/GDL
|
||||
29266a35088
|
||||
29266a35090
|
||||
> interruptible/U
|
||||
29272a35095,35098
|
||||
29272a35097,35100
|
||||
> intersex
|
||||
> intersexual/MS
|
||||
> intersexualism
|
||||
> intersexuality
|
||||
29724c35550
|
||||
29724c35552
|
||||
< jewellery's
|
||||
---
|
||||
> jewellery/M
|
||||
29870a35697
|
||||
29870a35699
|
||||
> judgement/MS
|
||||
30066c35893
|
||||
30066c35895
|
||||
< kiddie/M
|
||||
---
|
||||
> kiddie/SM
|
||||
30262,30263c36089
|
||||
30262,30263c36091
|
||||
< kraut's
|
||||
< kraut/S!
|
||||
---
|
||||
> kraut/MS!
|
||||
30665a36492
|
||||
30665a36494
|
||||
> lector/MS
|
||||
31031c36858
|
||||
31031c36860
|
||||
< linguini's
|
||||
---
|
||||
> linguini/M
|
||||
31034c36861
|
||||
31034c36863
|
||||
< linguistically
|
||||
---
|
||||
> linguistical/Y
|
||||
31151,31152c36978
|
||||
31151,31152c36980
|
||||
< liver's
|
||||
< liver/S
|
||||
---
|
||||
> liver/MS
|
||||
32230c38056
|
||||
32230c38058
|
||||
< meanie/M
|
||||
---
|
||||
> meanie/MS
|
||||
32317,32318c38143
|
||||
32317,32318c38145
|
||||
< megadeath/M
|
||||
< megadeaths
|
||||
---
|
||||
> megadeath/SM
|
||||
32320c38145
|
||||
32320c38147
|
||||
< megajoules
|
||||
---
|
||||
> megajoule/SM
|
||||
32329c38154
|
||||
32329c38156
|
||||
< megapixel/S
|
||||
---
|
||||
> megapixel/MS
|
||||
32708a38534
|
||||
32708a38536
|
||||
> might've
|
||||
32717a38544
|
||||
32717a38546
|
||||
> migrator/SM
|
||||
32760a38588
|
||||
32760a38590
|
||||
> millennia
|
||||
32777d38604
|
||||
32777d38606
|
||||
< millionnaire/M
|
||||
32934a38762
|
||||
32934a38764
|
||||
> miscommunication/S
|
||||
32991a38820
|
||||
32991a38822
|
||||
> misjudgement/MS
|
||||
33784a39614
|
||||
33784a39616
|
||||
> must've
|
||||
33963c39793
|
||||
33963c39795
|
||||
< native/MS
|
||||
---
|
||||
> native/MSY
|
||||
34169,34171c39999,40000
|
||||
34169,34171c40001,40002
|
||||
< neurone/S
|
||||
< neurophysiology
|
||||
< neuroscience
|
||||
---
|
||||
> neurophysiology/M
|
||||
> neuroscience/MS
|
||||
34275c40104
|
||||
34275c40106
|
||||
< nightie/M
|
||||
---
|
||||
> nightie/SM
|
||||
35104a40934
|
||||
35104a40936
|
||||
> octopi
|
||||
35219d41048
|
||||
35219d41050
|
||||
< oleomargarin/M
|
||||
35226a41056
|
||||
35226a41058
|
||||
> oligo
|
||||
35913c41743
|
||||
35913c41745
|
||||
< oversize/D
|
||||
---
|
||||
> oversize
|
||||
36056,36059d41885
|
||||
36056,36059d41887
|
||||
< paederast/S
|
||||
< paediatrician's
|
||||
< paediatricians
|
||||
< paediatrics/M
|
||||
36291a42118
|
||||
36291a42120
|
||||
> paralyses
|
||||
36403d42229
|
||||
36403d42231
|
||||
< parrakeet/MS
|
||||
36449d42274
|
||||
36449d42276
|
||||
< partizan/SM
|
||||
37093a42919
|
||||
37093a42921
|
||||
> petabyte/MS
|
||||
37102c42928
|
||||
37102c42930
|
||||
< petitioner/M
|
||||
---
|
||||
> petitioner/MS
|
||||
37264a43091
|
||||
37264a43093
|
||||
> phosphorylate/DSGN
|
||||
37316d43142
|
||||
37316d43144
|
||||
< phrenetic
|
||||
37630a43457
|
||||
37630a43459
|
||||
> plaintext
|
||||
37796a43624
|
||||
37796a43626
|
||||
> plugin/MS
|
||||
37987c43815
|
||||
37987c43817
|
||||
< polypeptide/S
|
||||
---
|
||||
> polypeptide/MS
|
||||
38291d44118
|
||||
38291d44120
|
||||
< practise's
|
||||
38451a44279
|
||||
38451a44281
|
||||
> prejudgement/MS
|
||||
38805a44634
|
||||
38805a44636
|
||||
> profiler/SM
|
||||
38835a44665
|
||||
38835a44667
|
||||
> programmatically
|
||||
38891a44722,44723
|
||||
38891a44724,44725
|
||||
> pronate/DSGN
|
||||
> pronator/MS
|
||||
38951c44783
|
||||
38951c44785
|
||||
< proprietorship/M
|
||||
---
|
||||
> proprietorship/MS
|
||||
39039a44872
|
||||
39039a44874
|
||||
> provender/M
|
||||
39095a44929
|
||||
39095a44931
|
||||
> pseudorandom/Y
|
||||
39564a45399
|
||||
39564a45401
|
||||
> quinoa
|
||||
39873a45709,45710
|
||||
39873a45711,45712
|
||||
> rasterization/M
|
||||
> rasterize/SGDR
|
||||
40036a45874
|
||||
40036a45876
|
||||
> recency
|
||||
40140a45979
|
||||
40140a45981
|
||||
> recurse/DGSV
|
||||
40141a45981
|
||||
40141a45983
|
||||
> recuse/DGS
|
||||
40208a46049
|
||||
40208a46051
|
||||
> refactor/SMDG
|
||||
40244d46084
|
||||
40244d46086
|
||||
< reflexion/SM
|
||||
40659d46498
|
||||
40659d46500
|
||||
< resizing
|
||||
40829c46668
|
||||
40829c46670
|
||||
< reverie/M
|
||||
---
|
||||
> reverie/MS
|
||||
41415a47255
|
||||
41415a47257
|
||||
> sabre/MS
|
||||
41914c47754
|
||||
41914c47756
|
||||
< schnaps's
|
||||
---
|
||||
> schnaps/M
|
||||
41949c47789
|
||||
41949c47791
|
||||
< schrod's
|
||||
---
|
||||
> schrod/SM
|
||||
41998a47839
|
||||
41998a47841
|
||||
> scot-free
|
||||
42883,42885c48724
|
||||
42883,42885c48726
|
||||
< shit's
|
||||
< shit/S!
|
||||
< shite/S!
|
||||
---
|
||||
> shit/MS!
|
||||
42887,42888c48726,48727
|
||||
42887,42888c48728,48729
|
||||
< shithead/S!
|
||||
< shitload/!
|
||||
---
|
||||
> shithead/MS!
|
||||
> shitload/MS!
|
||||
42891c48730
|
||||
42891c48732
|
||||
< shitty/RT!
|
||||
---
|
||||
> shitty/TR!
|
||||
42976a48816
|
||||
42976a48818
|
||||
> should've
|
||||
43008c48848
|
||||
43008c48850
|
||||
< showtime
|
||||
---
|
||||
> showtime/MS
|
||||
43328c49168
|
||||
43328c49170
|
||||
< size/MGBDRS
|
||||
---
|
||||
> size/AMGBDRS
|
||||
43724,43726c49564
|
||||
43724,43726c49566
|
||||
< smoulder's
|
||||
< smouldered
|
||||
< smoulders
|
||||
---
|
||||
> smoulder/GSMD
|
||||
43766a49605,49606
|
||||
43766a49607,49608
|
||||
> snarkily
|
||||
> snarky/TR
|
||||
44062c49902
|
||||
44062c49904
|
||||
< sonofabitch
|
||||
---
|
||||
> sonofabitch/!
|
||||
44346a50187
|
||||
44346a50189
|
||||
> spelled
|
||||
44348a50190
|
||||
44348a50192
|
||||
> spelt
|
||||
44371a50214
|
||||
44371a50216
|
||||
> spick/S!
|
||||
44383c50226
|
||||
44383c50228
|
||||
< spik/S
|
||||
---
|
||||
> spik/S!
|
||||
46106a51950
|
||||
46106a51952
|
||||
> syllabi
|
||||
46160c52004
|
||||
46160c52006
|
||||
< synch/GMD
|
||||
---
|
||||
> synch/GMDS
|
||||
46167d52010
|
||||
46167d52012
|
||||
< synchs
|
||||
46203,46204c52046,52047
|
||||
46203,46204c52048,52049
|
||||
< sysadmin/S
|
||||
< sysop/S
|
||||
---
|
||||
> sysadmin/MS
|
||||
> sysop/MS
|
||||
46752a52596
|
||||
46752a52598
|
||||
> terabit/MS
|
||||
46753a52598,52599
|
||||
46753a52600,52601
|
||||
> terahertz/M
|
||||
> terapixel/MS
|
||||
46817a52664
|
||||
46817a52666
|
||||
> testcase/MS
|
||||
46831a52679
|
||||
46831a52681
|
||||
> testsuite/MS
|
||||
46845a52694
|
||||
46845a52696
|
||||
> textbox/SM
|
||||
46925a52775
|
||||
46925a52777
|
||||
> theremin/MS
|
||||
47455c53305
|
||||
47455c53307
|
||||
< toolbar
|
||||
---
|
||||
> toolbar/MS
|
||||
47755a53606
|
||||
47755a53608
|
||||
> transfect/DSMG
|
||||
47774a53626,53627
|
||||
47774a53628,53629
|
||||
> transgenderism
|
||||
> transgene/MS
|
||||
47951c53804
|
||||
47951c53806
|
||||
< triage/M
|
||||
---
|
||||
> triage/MG
|
||||
48869a54723
|
||||
48869a54725
|
||||
> unlikeable
|
||||
49211c55065
|
||||
49211c55067
|
||||
< vagina/M
|
||||
---
|
||||
> vagina/MS
|
||||
49368,49369c55222
|
||||
49368,49369c55224
|
||||
< velour's
|
||||
< velours's
|
||||
---
|
||||
> velour/MS
|
||||
49478a55332
|
||||
49478a55334
|
||||
> vertices
|
||||
50148a56003
|
||||
50148a56005
|
||||
> weaponize/DSG
|
||||
50260,50261d56114
|
||||
50260,50261d56116
|
||||
< werwolf/M
|
||||
< werwolves
|
||||
50728c56581
|
||||
50728c56583
|
||||
< women
|
||||
---
|
||||
> women/M
|
||||
50794c56647
|
||||
50794c56649
|
||||
< wop/S!
|
||||
---
|
||||
> wop/MS!
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
57469
|
||||
57471
|
||||
0/nm
|
||||
0th/pt
|
||||
1/n1
|
||||
|
@ -17802,6 +17802,8 @@ anomalous/Y
|
|||
anomaly/SM
|
||||
anon/S
|
||||
anonymity/M
|
||||
anonymization/SM
|
||||
anonymize/DSG
|
||||
anonymous/Y
|
||||
anopheles/M
|
||||
anorak/MS
|
||||
|
@ -34336,7 +34338,7 @@ immediateness/M
|
|||
immemorial/Y
|
||||
immense/RYTP
|
||||
immensity/SM
|
||||
immerse/XDSGN
|
||||
immerse/XDSGNV
|
||||
immersible
|
||||
immersion/M
|
||||
immigrant/SM
|
||||
|
|
|
@ -1253,6 +1253,7 @@ DrawTargetCG::CopySurface(SourceSurface *aSurface,
|
|||
CGContextDrawImage(mCg, flippedRect, image);
|
||||
|
||||
CGContextRestoreGState(mCg);
|
||||
CGImageRelease(image);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1232,6 +1232,11 @@ GetTotalSystemMemory()
|
|||
return hal_impl::GetTotalSystemMemory();
|
||||
}
|
||||
|
||||
uint32_t
|
||||
GetTotalSystemMemoryLevel()
|
||||
{
|
||||
return hal_impl::GetTotalSystemMemoryLevel();
|
||||
}
|
||||
|
||||
} // namespace hal
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -616,6 +616,14 @@ void StopDiskSpaceWatcher();
|
|||
*/
|
||||
uint32_t GetTotalSystemMemory();
|
||||
|
||||
/**
|
||||
* Get the level of total system memory on device in MiB.
|
||||
* (round the value up to the next power of two)
|
||||
*
|
||||
* Returns 0 if we are unable to determine this information from /proc/meminfo.
|
||||
*/
|
||||
uint32_t GetTotalSystemMemoryLevel();
|
||||
|
||||
} // namespace MOZ_HAL_NAMESPACE
|
||||
} // namespace mozilla
|
||||
|
||||
|
|
|
@ -16,5 +16,11 @@ GetTotalSystemMemory()
|
|||
return 0;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
GetTotalSystemMemoryLevel()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace hal_impl
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -35,5 +35,37 @@ GetTotalSystemMemory()
|
|||
return sTotalMemory * 1024;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
GetTotalSystemMemoryLevel()
|
||||
{
|
||||
static uint32_t sTotalMemoryLevel = 1;
|
||||
uint32_t sTotalMemory;
|
||||
static bool sTotalMemoryObtained = false;
|
||||
|
||||
if (!sTotalMemoryObtained) {
|
||||
sTotalMemoryObtained = true;
|
||||
|
||||
FILE* fd = fopen("/proc/meminfo", "r");
|
||||
if (!fd) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rv = fscanf(fd, "MemTotal: %i kB", &sTotalMemory);
|
||||
|
||||
if (fclose(fd) || rv != 1) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// From KB to MiB
|
||||
sTotalMemory /= 1024;
|
||||
|
||||
while (sTotalMemoryLevel <= sTotalMemory) {
|
||||
sTotalMemoryLevel *= 2;
|
||||
}
|
||||
}
|
||||
|
||||
return sTotalMemoryLevel;
|
||||
}
|
||||
|
||||
} // namespace hal_impl
|
||||
} // namespace mozilla
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче