mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-07 20:17:37 +00:00
Merge m-c to b2g-inbound. a=merge
This commit is contained in:
commit
0289206652
@ -272,7 +272,14 @@ Target.prototype = {
|
||||
},
|
||||
|
||||
_send: function target_send(data) {
|
||||
shell.sendEvent(this.frame, 'developer-hud-update', Cu.cloneInto(data, this.frame));
|
||||
let frame = this.frame;
|
||||
|
||||
let systemapp = document.querySelector('#systemapp');
|
||||
if (this.frame === systemapp) {
|
||||
frame = getContentWindow();
|
||||
}
|
||||
|
||||
shell.sendEvent(frame, 'developer-hud-update', Cu.cloneInto(data, frame));
|
||||
}
|
||||
|
||||
};
|
||||
|
@ -1363,6 +1363,11 @@ pref("devtools.gcli.hideIntro", false);
|
||||
// How eager are we to show help: never=1, sometimes=2, always=3
|
||||
pref("devtools.gcli.eagerHelper", 2);
|
||||
|
||||
// Alias to the script URLs for inject command.
|
||||
pref("devtools.gcli.jquerySrc", "http://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js");
|
||||
pref("devtools.gcli.lodashSrc", "http://cdnjs.cloudflare.com/ajax/libs/lodash.js/2.4.1/lodash.min.js");
|
||||
pref("devtools.gcli.underscoreSrc", "http://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.6.0/underscore-min.js");
|
||||
|
||||
// Remember the Web Console filters
|
||||
pref("devtools.webconsole.filter.network", true);
|
||||
pref("devtools.webconsole.filter.networkinfo", false);
|
||||
|
@ -14,6 +14,7 @@ const commandModules = [
|
||||
"gcli/commands/cmd",
|
||||
"gcli/commands/cookie",
|
||||
"gcli/commands/csscoverage",
|
||||
"gcli/commands/inject",
|
||||
"gcli/commands/jsb",
|
||||
"gcli/commands/listen",
|
||||
"gcli/commands/media",
|
||||
|
@ -50,6 +50,9 @@ support-files =
|
||||
browser_cmd_csscoverage_sheetB.css
|
||||
browser_cmd_csscoverage_sheetC.css
|
||||
browser_cmd_csscoverage_sheetD.css
|
||||
[browser_cmd_inject.js]
|
||||
support-files =
|
||||
browser_cmd_inject.html
|
||||
[browser_cmd_csscoverage_util.js]
|
||||
[browser_cmd_jsb.js]
|
||||
support-files =
|
||||
|
@ -0,0 +1,8 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<head>
|
||||
<body>
|
||||
</body>
|
||||
</html>
|
98
browser/devtools/commandline/test/browser_cmd_inject.js
Normal file
98
browser/devtools/commandline/test/browser_cmd_inject.js
Normal file
@ -0,0 +1,98 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
// Tests that the inject commands works as they should
|
||||
|
||||
const TEST_URI = 'http://example.com/browser/browser/devtools/commandline/'+
|
||||
'test/browser_cmd_inject.html';
|
||||
|
||||
function test() {
|
||||
helpers.addTabWithToolbar(TEST_URI, function(options) {
|
||||
return helpers.audit(options, [
|
||||
{
|
||||
setup: 'inject',
|
||||
check: {
|
||||
input: 'inject',
|
||||
hints: ' <library>',
|
||||
markup: 'VVVVVV',
|
||||
status: 'ERROR'
|
||||
},
|
||||
},
|
||||
{
|
||||
setup: 'inject j',
|
||||
check: {
|
||||
input: 'inject j',
|
||||
hints: 'Query',
|
||||
markup: 'VVVVVVVI',
|
||||
status: 'ERROR'
|
||||
},
|
||||
},
|
||||
{
|
||||
setup: 'inject http://example.com/browser/browser/devtools/commandline/test/browser_cmd_inject.js',
|
||||
check: {
|
||||
input: 'inject http://example.com/browser/browser/devtools/commandline/test/browser_cmd_inject.js',
|
||||
hints: '',
|
||||
markup: 'VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV',
|
||||
status: 'VALID',
|
||||
args: {
|
||||
library: {
|
||||
value: function(library) {
|
||||
is(library.type, 'string', 'inject type name');
|
||||
is(library.string, 'http://example.com/browser/browser/devtools/commandline/test/browser_cmd_inject.js',
|
||||
'inject uri data');
|
||||
},
|
||||
status: 'VALID'
|
||||
}
|
||||
}
|
||||
},
|
||||
exec: {
|
||||
output: [ /http:\/\/example.com\/browser\/browser\/devtools\/commandline\/test\/browser_cmd_inject.js loaded/ ]
|
||||
}
|
||||
},
|
||||
{
|
||||
setup: 'inject notauri',
|
||||
check: {
|
||||
input: 'inject notauri',
|
||||
hints: '',
|
||||
markup: 'VVVVVVVVVVVVVV',
|
||||
status: 'VALID',
|
||||
args: {
|
||||
library: {
|
||||
value: function(library) {
|
||||
is(library.type, 'string', 'inject type name');
|
||||
is(library.string, 'notauri', 'inject notauri data');
|
||||
},
|
||||
status: 'VALID'
|
||||
}
|
||||
}
|
||||
},
|
||||
exec: {
|
||||
output: [ /Failed to load notauri - Invalid URI/ ]
|
||||
}
|
||||
},
|
||||
{
|
||||
setup: 'inject jQuery',
|
||||
check: {
|
||||
input: 'inject jQuery',
|
||||
hints: '',
|
||||
markup: 'VVVVVVVVVVVVV',
|
||||
status: 'VALID',
|
||||
args: {
|
||||
library: {
|
||||
value: function(library) {
|
||||
is(library.type, 'selection', 'inject type name');
|
||||
is(library.selection.name, 'jQuery', 'inject jquery name');
|
||||
is(library.selection.src, 'http://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js',
|
||||
'inject jquery src');
|
||||
},
|
||||
status: 'VALID'
|
||||
}
|
||||
}
|
||||
},
|
||||
exec: {
|
||||
output: [ /jQuery loaded/ ]
|
||||
}
|
||||
},
|
||||
]);
|
||||
}).then(finish, helpers.handleError);
|
||||
}
|
@ -76,6 +76,9 @@ function forEachType(options, typeSpec, callback) {
|
||||
else if (name === 'remote') {
|
||||
return;
|
||||
}
|
||||
else if (name === 'union') {
|
||||
typeSpec.types = [{ name: "string" }];
|
||||
}
|
||||
|
||||
var type = types.createType(typeSpec);
|
||||
var reply = callback(type);
|
||||
@ -86,6 +89,7 @@ function forEachType(options, typeSpec, callback) {
|
||||
delete typeSpec.data;
|
||||
delete typeSpec.delegateType;
|
||||
delete typeSpec.subtype;
|
||||
delete typeSpec.types;
|
||||
|
||||
return value;
|
||||
});
|
||||
|
@ -177,6 +177,10 @@ helpIntro=GCLI is an experiment to create a highly usable command line for web d
|
||||
# sub-commands.
|
||||
subCommands=Sub-Commands
|
||||
|
||||
# LOCALIZATION NOTE: This error message is displayed when the command line is
|
||||
# cannot find a match for the parse types.
|
||||
commandParseError=Command line parsing error
|
||||
|
||||
# LOCALIZATION NOTE (contextDesc, contextManual, contextPrefixDesc): These
|
||||
# strings are used to describe the 'context' command and its 'prefix'
|
||||
# parameter. See localization comment for 'connect' for an explanation about
|
||||
|
@ -1391,3 +1391,12 @@ mediaEmulateDesc=Emulate a specified CSS media type
|
||||
mediaEmulateManual=View the document as if rendered on a device supporting the given media type, with the relevant CSS rules applied.
|
||||
mediaEmulateType=The media type to emulate
|
||||
mediaResetDesc=Stop emulating a CSS media type
|
||||
|
||||
# LOCALIZATION NOTE (injectDesc, injectManual, injectLibraryDesc, injectLoaded,
|
||||
# injectFailed) These strings describe the 'inject' commands and all available
|
||||
# parameters.
|
||||
injectDesc=Inject common libraries into the page
|
||||
injectManual=Inject common libraries into the content of the page which can also be accessed from the Firefox console.
|
||||
injectLibraryDesc=Select the library to inject or enter a valid script URI to inject
|
||||
injectLoaded=%1$S loaded
|
||||
injectFailed=Failed to load %1$S - Invalid URI
|
||||
|
@ -318,6 +318,7 @@ browser.jar:
|
||||
skin/classic/browser/devtools/font-inspector.css (../shared/devtools/font-inspector.css)
|
||||
skin/classic/browser/devtools/computedview.css (../shared/devtools/computedview.css)
|
||||
skin/classic/browser/devtools/arrow-e.png (../shared/devtools/images/arrow-e.png)
|
||||
skin/classic/browser/devtools/arrow-e@2x.png (../shared/devtools/images/arrow-e@2x.png)
|
||||
skin/classic/browser/devtools/projecteditor/projecteditor.css (../shared/devtools/projecteditor/projecteditor.css)
|
||||
skin/classic/browser/devtools/projecteditor/file-icons-sheet@2x.png (../shared/devtools/projecteditor/file-icons-sheet@2x.png)
|
||||
skin/classic/browser/devtools/app-manager/connection-footer.css (../shared/devtools/app-manager/connection-footer.css)
|
||||
|
@ -436,6 +436,7 @@ browser.jar:
|
||||
skin/classic/browser/devtools/font-inspector.css (../shared/devtools/font-inspector.css)
|
||||
skin/classic/browser/devtools/computedview.css (../shared/devtools/computedview.css)
|
||||
skin/classic/browser/devtools/arrow-e.png (../shared/devtools/images/arrow-e.png)
|
||||
skin/classic/browser/devtools/arrow-e@2x.png (../shared/devtools/images/arrow-e@2x.png)
|
||||
skin/classic/browser/devtools/projecteditor/projecteditor.css (../shared/devtools/projecteditor/projecteditor.css)
|
||||
skin/classic/browser/devtools/projecteditor/file-icons-sheet@2x.png (../shared/devtools/projecteditor/file-icons-sheet@2x.png)
|
||||
skin/classic/browser/devtools/app-manager/connection-footer.css (../shared/devtools/app-manager/connection-footer.css)
|
||||
|
@ -29,6 +29,13 @@ menulist:not([editable="true"]) > .menulist-dropmarker {
|
||||
margin-bottom: 1px;
|
||||
}
|
||||
|
||||
menulist > menupopup menu,
|
||||
menulist > menupopup menuitem,
|
||||
button[type="menu"] > menupopup menu,
|
||||
button[type="menu"] > menupopup menuitem {
|
||||
-moz-padding-end: 34px;
|
||||
}
|
||||
|
||||
.help-button > .button-box > .button-icon {
|
||||
-moz-margin-start: 0;
|
||||
}
|
||||
|
@ -51,23 +51,29 @@ body {
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
.property-value, .other-property-value {
|
||||
background-image: url(arrow-e.png);
|
||||
background-repeat: no-repeat;
|
||||
background-size: 5px 8px;
|
||||
}
|
||||
|
||||
@media (min-resolution: 2dppx) {
|
||||
.property-value, .other-property-value {
|
||||
background-image: url(arrow-e@2x.png);
|
||||
}
|
||||
}
|
||||
|
||||
.property-value {
|
||||
width: 100%;
|
||||
overflow-x: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
background-image: url(arrow-e.png);
|
||||
background-repeat: no-repeat;
|
||||
background-size: 5px 8px;
|
||||
background-position: 2px center;
|
||||
padding-left: 10px;
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
.other-property-value {
|
||||
background-image: url(arrow-e.png);
|
||||
background-repeat: no-repeat;
|
||||
background-size: 5px 8px;
|
||||
background-position: left center;
|
||||
padding-left: 8px;
|
||||
}
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 177 B After Width: | Height: | Size: 168 B |
BIN
browser/themes/shared/devtools/images/arrow-e@2x.png
Normal file
BIN
browser/themes/shared/devtools/images/arrow-e@2x.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 417 B |
@ -66,27 +66,29 @@
|
||||
|
||||
.stylesheet-sidebar {
|
||||
width: 230px;
|
||||
-moz-border-start: 1px solid;
|
||||
}
|
||||
|
||||
.theme-light .stylesheet-sidebar {
|
||||
border-left: 1px solid #A6A6A6;
|
||||
border-color: #aaa; /* Splitters */
|
||||
}
|
||||
|
||||
.theme-dark .stylesheet-sidebar {
|
||||
border-left: 1px solid #606C75;
|
||||
border-color: #000; /* Splitters */
|
||||
}
|
||||
|
||||
.theme-light .media-rule-label {
|
||||
border-bottom: 1px solid #CCC;
|
||||
border-bottom-color: #cddae5; /* Grey */
|
||||
}
|
||||
|
||||
.theme-dark .media-rule-label {
|
||||
border-bottom: 1px solid #343C45;
|
||||
border-bottom-color: #303b47; /* Grey */
|
||||
}
|
||||
|
||||
.media-rule-label {
|
||||
padding: 4px;
|
||||
cursor: pointer;
|
||||
border-bottom: 1px solid;
|
||||
}
|
||||
|
||||
.theme-light .media-condition-unmatched {
|
||||
|
@ -355,6 +355,7 @@ browser.jar:
|
||||
skin/classic/browser/devtools/font-inspector.css (../shared/devtools/font-inspector.css)
|
||||
skin/classic/browser/devtools/computedview.css (../shared/devtools/computedview.css)
|
||||
skin/classic/browser/devtools/arrow-e.png (../shared/devtools/images/arrow-e.png)
|
||||
skin/classic/browser/devtools/arrow-e@2x.png (../shared/devtools/images/arrow-e@2x.png)
|
||||
skin/classic/browser/devtools/projecteditor/projecteditor.css (../shared/devtools/projecteditor/projecteditor.css)
|
||||
skin/classic/browser/devtools/projecteditor/file-icons-sheet@2x.png (../shared/devtools/projecteditor/file-icons-sheet@2x.png)
|
||||
skin/classic/browser/devtools/app-manager/connection-footer.css (../shared/devtools/app-manager/connection-footer.css)
|
||||
@ -758,6 +759,7 @@ browser.jar:
|
||||
skin/classic/aero/browser/devtools/font-inspector.css (../shared/devtools/font-inspector.css)
|
||||
skin/classic/aero/browser/devtools/computedview.css (../shared/devtools/computedview.css)
|
||||
skin/classic/aero/browser/devtools/arrow-e.png (../shared/devtools/images/arrow-e.png)
|
||||
skin/classic/aero/browser/devtools/arrow-e.png (../shared/devtools/images/arrow-e@2x.png)
|
||||
skin/classic/aero/browser/devtools/projecteditor/projecteditor.css (../shared/devtools/projecteditor/projecteditor.css)
|
||||
skin/classic/aero/browser/devtools/projecteditor/file-icons-sheet@2x.png (../shared/devtools/projecteditor/file-icons-sheet@2x.png)
|
||||
skin/classic/aero/browser/devtools/app-manager/connection-footer.css (../shared/devtools/app-manager/connection-footer.css)
|
||||
|
@ -13630,6 +13630,11 @@ nsGlobalWindow::GetDialogArguments(JSContext* aCx, ErrorResult& aError)
|
||||
MOZ_ASSERT(IsModalContentWindow(),
|
||||
"This should only be called on modal windows!");
|
||||
|
||||
if (!mDialogArguments) {
|
||||
MOZ_ASSERT(mIsClosed, "This window should be closed!");
|
||||
return JS::UndefinedValue();
|
||||
}
|
||||
|
||||
// This does an internal origin check, and returns undefined if the subject
|
||||
// does not subsumes the origin of the arguments.
|
||||
JS::Rooted<JSObject*> wrapper(aCx, GetWrapper());
|
||||
|
@ -350,9 +350,7 @@ public:
|
||||
// nsWrapperCache
|
||||
virtual JSObject *WrapObject(JSContext *cx) MOZ_OVERRIDE
|
||||
{
|
||||
NS_ASSERTION(IsOuterWindow(),
|
||||
"Inner window supports nsWrapperCache, fix WrapObject!");
|
||||
return EnsureInnerWindow() ? GetWrapper() : nullptr;
|
||||
return IsInnerWindow() || EnsureInnerWindow() ? GetWrapper() : nullptr;
|
||||
}
|
||||
|
||||
// nsIGlobalJSObjectHolder
|
||||
|
@ -8,7 +8,6 @@ support-files =
|
||||
file_empty.html
|
||||
iframe_postMessage_solidus.html
|
||||
|
||||
[test_Image_constructor.html]
|
||||
[test_appname_override.html]
|
||||
[test_audioWindowUtils.html]
|
||||
[test_audioNotification.html]
|
||||
@ -22,6 +21,8 @@ support-files =
|
||||
[test_consoleEmptyStack.html]
|
||||
[test_constructor-assignment.html]
|
||||
[test_constructor.html]
|
||||
[test_dialogArguments.html]
|
||||
skip-if = buildapp == 'b2g' || toolkit == 'android' || e10s
|
||||
[test_document.all_unqualified.html]
|
||||
[test_domcursor.html]
|
||||
[test_domrequest.html]
|
||||
@ -37,6 +38,7 @@ support-files =
|
||||
[test_getFeature_without_perm.html]
|
||||
[test_history_document_open.html]
|
||||
[test_history_state_null.html]
|
||||
[test_Image_constructor.html]
|
||||
[test_innersize_scrollport.html]
|
||||
[test_messageChannel.html]
|
||||
[test_messageChannel_cloning.html]
|
||||
|
31
dom/base/test/test_dialogArguments.html
Normal file
31
dom/base/test/test_dialogArguments.html
Normal file
@ -0,0 +1,31 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test for Bug 1019761</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
|
||||
<meta http-equiv="content-type" content="text/html; charset=utf-8">
|
||||
</head>
|
||||
<body>
|
||||
<script type="application/javascript">
|
||||
|
||||
/*
|
||||
Tests whether Firefox crashes when accessing the dialogArguments property
|
||||
of a modal window that has been closed.
|
||||
*/
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
function openModal() {
|
||||
showModalDialog("javascript:opener.winRef = window; \
|
||||
window.opener.setTimeout(\'winRef.dialogArguments;\', 0);\
|
||||
window.close();");
|
||||
|
||||
ok(true, "dialogArguments did not cause a crash.");
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
window.onload = openModal;
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -45,14 +45,13 @@
|
||||
#include "MediaEngineDefault.h"
|
||||
#if defined(MOZ_WEBRTC)
|
||||
#include "MediaEngineWebRTC.h"
|
||||
#include "browser_logging/WebRtcLog.h"
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_B2G
|
||||
#include "MediaPermissionGonk.h"
|
||||
#endif
|
||||
|
||||
#include "browser_logging/WebRtcLog.h"
|
||||
|
||||
// GetCurrentTime is defined in winbase.h as zero argument macro forwarding to
|
||||
// GetTickCount() and conflicts with MediaStream::GetCurrentTime.
|
||||
#ifdef GetCurrentTime
|
||||
@ -1577,7 +1576,9 @@ MediaManager::GetUserMedia(bool aPrivileged,
|
||||
obs->NotifyObservers(req, "getUserMedia:request", nullptr);
|
||||
}
|
||||
|
||||
#ifdef MOZ_WEBRTC
|
||||
EnableWebRtcLog();
|
||||
#endif
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -1 +1 @@
|
||||
skip load 408431-1.html # bug 1022509 - renable when the cause of that is backed out
|
||||
load 408431-1.html
|
||||
|
@ -9,19 +9,27 @@ const Ci = Components.interfaces;
|
||||
const Cc = Components.classes;
|
||||
|
||||
const POSITION_UNAVAILABLE = Ci.nsIDOMGeoPositionError.POSITION_UNAVAILABLE;
|
||||
const SETTING_DEBUG_ENABLED = "geolocation.debugging.enabled";
|
||||
const SETTING_CHANGED_TOPIC = "mozsettings-changed";
|
||||
const SETTINGS_DEBUG_ENABLED = "geolocation.debugging.enabled";
|
||||
const SETTINGS_CHANGED_TOPIC = "mozsettings-changed";
|
||||
const SETTINGS_WIFI_ENABLED = "wifi.enabled";
|
||||
|
||||
let gLoggingEnabled = false;
|
||||
|
||||
// if we don't see any wifi responses in 5 seconds, send the request.
|
||||
let gTimeToWaitBeforeSending = 5000; //ms
|
||||
/*
|
||||
The gLocationRequestTimeout controls how long we wait on receiving an update
|
||||
from the Wifi subsystem. If this timer fires, we believe the Wifi scan has
|
||||
had a problem and we no longer can use Wifi to position the user this time
|
||||
around (we will continue to be hopeful that Wifi will recover).
|
||||
|
||||
This timeout value is also used when Wifi scanning is disabled (see
|
||||
gWifiScanningEnabled). In this case, we use this timer to collect cell/ip
|
||||
data and xhr it to the location server.
|
||||
*/
|
||||
|
||||
let gLocationRequestTimeout = 5000;
|
||||
|
||||
let gWifiScanningEnabled = true;
|
||||
let gWifiResults;
|
||||
|
||||
let gCellScanningEnabled = false;
|
||||
let gCellResults;
|
||||
|
||||
function LOG(aMsg) {
|
||||
if (gLoggingEnabled) {
|
||||
@ -59,7 +67,7 @@ function WifiGeoPositionProvider() {
|
||||
} catch (e) {}
|
||||
|
||||
try {
|
||||
gTimeToWaitBeforeSending = Services.prefs.getIntPref("geo.wifi.timeToWaitBeforeSending");
|
||||
gLocationRequestTimeout = Services.prefs.getIntPref("geo.wifi.timeToWaitBeforeSending");
|
||||
} catch (e) {}
|
||||
|
||||
try {
|
||||
@ -71,7 +79,7 @@ function WifiGeoPositionProvider() {
|
||||
} catch (e) {}
|
||||
|
||||
this.wifiService = null;
|
||||
this.timeoutTimer = null;
|
||||
this.timer = null;
|
||||
this.started = false;
|
||||
}
|
||||
|
||||
@ -84,28 +92,53 @@ WifiGeoPositionProvider.prototype = {
|
||||
listener: null,
|
||||
|
||||
observe: function(aSubject, aTopic, aData) {
|
||||
if (aTopic != SETTING_CHANGED_TOPIC) {
|
||||
if (aTopic != SETTINGS_CHANGED_TOPIC) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
let setting = JSON.parse(aData);
|
||||
if (setting.key != SETTING_DEBUG_ENABLED) {
|
||||
return;
|
||||
if (setting.key == SETTINGS_DEBUG_ENABLED) {
|
||||
gLoggingEnabled = setting.value;
|
||||
} else if (setting.key == SETTINGS_WIFI_ENABLED) {
|
||||
gWifiScanningEnabled = setting.value;
|
||||
}
|
||||
gLoggingEnabled = setting.value;
|
||||
} catch (e) {
|
||||
}
|
||||
},
|
||||
|
||||
resetTimer: function() {
|
||||
if (this.timer) {
|
||||
this.timer.cancel();
|
||||
this.timer = null;
|
||||
}
|
||||
// wifi thread triggers WifiGeoPositionProvider to proceed, with no wifi, do manual timeout
|
||||
this.timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
|
||||
this.timer.initWithCallback(this,
|
||||
gLocationRequestTimeout,
|
||||
this.timer.TYPE_REPEATING_SLACK);
|
||||
},
|
||||
|
||||
startup: function() {
|
||||
if (this.started)
|
||||
return;
|
||||
|
||||
this.started = true;
|
||||
let self = this;
|
||||
let settingsCallback = {
|
||||
handle: function(name, result) {
|
||||
gLoggingEnabled = result && result.value === true ? true : false;
|
||||
if (name == SETTINGS_DEBUG_ENABLED) {
|
||||
gLoggingEnabled = result;
|
||||
} else if (name == SETTINGS_WIFI_ENABLED) {
|
||||
gWifiScanningEnabled = result;
|
||||
if (self.wifiService) {
|
||||
self.wifiService.stopWatching(self);
|
||||
}
|
||||
if (gWifiScanningEnabled) {
|
||||
self.wifiService = Cc["@mozilla.org/wifi/monitor;1"].getService(Ci.nsIWifiMonitor);
|
||||
self.wifiService.startWatching(self);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
handleError: function(message) {
|
||||
@ -115,21 +148,23 @@ WifiGeoPositionProvider.prototype = {
|
||||
};
|
||||
|
||||
try {
|
||||
Services.obs.addObserver(this, SETTING_CHANGED_TOPIC, false);
|
||||
Services.obs.addObserver(this, SETTINGS_CHANGED_TOPIC, false);
|
||||
let settings = Cc["@mozilla.org/settingsService;1"].getService(Ci.nsISettingsService);
|
||||
settings.createLock().get(SETTING_DEBUG_ENABLED, settingsCallback);
|
||||
settings.createLock().get(SETTINGS_WIFI_ENABLED, settingsCallback);
|
||||
settings.createLock().get(SETTINGS_DEBUG_ENABLED, settingsCallback);
|
||||
} catch(ex) {
|
||||
// This platform doesn't have the settings interface, and that is just peachy
|
||||
}
|
||||
|
||||
if (gWifiScanningEnabled && Cc["@mozilla.org/wifi/monitor;1"]) {
|
||||
this.wifiService = Cc["@mozilla.org/wifi/monitor;1"].getService(Components.interfaces.nsIWifiMonitor);
|
||||
if (this.wifiService) {
|
||||
this.wifiService.stopWatching(this);
|
||||
}
|
||||
this.wifiService = Cc["@mozilla.org/wifi/monitor;1"].getService(Ci.nsIWifiMonitor);
|
||||
this.wifiService.startWatching(this);
|
||||
}
|
||||
this.timeoutTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
|
||||
this.timeoutTimer.initWithCallback(this,
|
||||
gTimeToWaitBeforeSending,
|
||||
this.timeoutTimer.TYPE_REPEATING_SLACK);
|
||||
|
||||
this.resetTimer();
|
||||
LOG("startup called.");
|
||||
},
|
||||
|
||||
@ -143,9 +178,9 @@ WifiGeoPositionProvider.prototype = {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.timeoutTimer) {
|
||||
this.timeoutTimer.cancel();
|
||||
this.timeoutTimer = null;
|
||||
if (this.timer) {
|
||||
this.timer.cancel();
|
||||
this.timer = null;
|
||||
}
|
||||
|
||||
if(this.wifiService) {
|
||||
@ -153,7 +188,7 @@ WifiGeoPositionProvider.prototype = {
|
||||
this.wifiService = null;
|
||||
}
|
||||
|
||||
Services.obs.removeObserver(this, SETTING_CHANGED_TOPIC);
|
||||
Services.obs.removeObserver(this, SETTINGS_CHANGED_TOPIC);
|
||||
|
||||
this.listener = null;
|
||||
this.started = false;
|
||||
@ -164,6 +199,9 @@ WifiGeoPositionProvider.prototype = {
|
||||
|
||||
onChange: function(accessPoints) {
|
||||
|
||||
// we got some wifi data, rearm the timer.
|
||||
this.resetTimer();
|
||||
|
||||
function isPublic(ap) {
|
||||
let mask = "_nomap"
|
||||
let result = ap.ssid.indexOf(mask, ap.ssid.length - mask.length);
|
||||
@ -181,18 +219,19 @@ WifiGeoPositionProvider.prototype = {
|
||||
return { 'macAddress': ap.mac, 'signalStrength': ap.signal };
|
||||
};
|
||||
|
||||
let wifiData = null;
|
||||
if (accessPoints) {
|
||||
gWifiResults = accessPoints.filter(isPublic).sort(sort).map(encode);
|
||||
} else {
|
||||
gWifiResults = null;
|
||||
wifiData = accessPoints.filter(isPublic).sort(sort).map(encode);
|
||||
}
|
||||
this.sendLocationRequest(wifiData);
|
||||
},
|
||||
|
||||
onError: function (code) {
|
||||
LOG("wifi error: " + code);
|
||||
this.sendLocationRequest(null);
|
||||
},
|
||||
|
||||
updateMobileInfo: function() {
|
||||
getMobileInfo: function() {
|
||||
LOG("updateMobileInfo called");
|
||||
try {
|
||||
let radioService = Cc["@mozilla.org/ril;1"]
|
||||
@ -216,11 +255,15 @@ WifiGeoPositionProvider.prototype = {
|
||||
}
|
||||
return result;
|
||||
} catch (e) {
|
||||
gCellResults = null;
|
||||
return null;
|
||||
}
|
||||
},
|
||||
|
||||
notify: function (timeoutTimer) {
|
||||
notify: function (timer) {
|
||||
this.sendLocationRequest(null);
|
||||
},
|
||||
|
||||
sendLocationRequest: function (wifiData) {
|
||||
let url = Services.urlFormatter.formatURLPref("geo.wifi.uri");
|
||||
let listener = this.listener;
|
||||
LOG("Sending request: " + url + "\n");
|
||||
@ -258,19 +301,19 @@ WifiGeoPositionProvider.prototype = {
|
||||
listener.update(newLocation);
|
||||
};
|
||||
|
||||
if (gCellScanningEnabled) {
|
||||
this.updateMobileInfo();
|
||||
let data = {};
|
||||
if (wifiData) {
|
||||
data.wifiAccessPoints = wifiData;
|
||||
}
|
||||
|
||||
let data = {};
|
||||
if (gWifiResults) {
|
||||
data.wifiAccessPoints = gWifiResults;
|
||||
}
|
||||
if (gCellResults) {
|
||||
data.cellTowers = gCellResults;
|
||||
if (gCellScanningEnabled) {
|
||||
let cellData = this.getMobileInfo();
|
||||
if (cellData) {
|
||||
data.cellTowers = cellData;
|
||||
}
|
||||
}
|
||||
|
||||
data = JSON.stringify(data);
|
||||
gWifiResults = gCellResults = null;
|
||||
LOG("sending " + data);
|
||||
xhr.send(data);
|
||||
},
|
||||
|
@ -703,10 +703,11 @@ GonkGPSGeolocationProvider::NetworkLocationUpdate::Update(nsIDOMGeoPosition *pos
|
||||
// assume the MLS coord is unchanged, and stick with the GPS location
|
||||
const double kMinMLSCoordChangeInMeters = 10;
|
||||
|
||||
// if we haven't seen anything from the GPS device for 1s,
|
||||
// if we haven't seen anything from the GPS device for 10s,
|
||||
// use this network derived location.
|
||||
const int kMaxGPSDelayBeforeConsideringMLS = 10000;
|
||||
int64_t diff = PR_Now() - provider->mLastGPSDerivedLocationTime;
|
||||
if (provider->mLocationCallback && diff > kDefaultPeriod
|
||||
if (provider->mLocationCallback && diff > kMaxGPSDelayBeforeConsideringMLS
|
||||
&& delta > kMinMLSCoordChangeInMeters)
|
||||
{
|
||||
provider->mLocationCallback->Update(position);
|
||||
|
@ -118,6 +118,7 @@ AppendToString(nsACString& s, const FrameMetrics& m,
|
||||
{
|
||||
s += pfx;
|
||||
AppendToString(s, m.mViewport, "{ viewport=");
|
||||
AppendToString(s, m.mCompositionBounds, " cb=");
|
||||
AppendToString(s, m.GetScrollOffset(), " viewportScroll=");
|
||||
AppendToString(s, m.mDisplayPort, " displayport=");
|
||||
AppendToString(s, m.mCriticalDisplayPort, " critdp=");
|
||||
|
@ -16,7 +16,6 @@
|
||||
#include "nsRegion.h" // for nsIntRegion
|
||||
#include "nscore.h" // for nsACString, etc
|
||||
|
||||
class gfx3DMatrix;
|
||||
struct gfxRGBA;
|
||||
struct nsIntPoint;
|
||||
struct nsIntRect;
|
||||
@ -46,10 +45,6 @@ nsACString&
|
||||
AppendToString(nsACString& s, const gfxRGBA& c,
|
||||
const char* pfx="", const char* sfx="");
|
||||
|
||||
nsACString&
|
||||
AppendToString(nsACString& s, const gfx3DMatrix& m,
|
||||
const char* pfx="", const char* sfx="");
|
||||
|
||||
nsACString&
|
||||
AppendToString(nsACString& s, const nsIntPoint& p,
|
||||
const char* pfx="", const char* sfx="");
|
||||
@ -80,6 +75,18 @@ AppendToString(nsACString& s, const mozilla::gfx::RectTyped<T>& r,
|
||||
return s += sfx;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
nsACString&
|
||||
AppendToString(nsACString& s, const mozilla::gfx::IntRectTyped<T>& r,
|
||||
const char* pfx="", const char* sfx="")
|
||||
{
|
||||
s += pfx;
|
||||
s.AppendPrintf(
|
||||
"(x=%d, y=%d, w=%d, h=%d)",
|
||||
r.x, r.y, r.width, r.height);
|
||||
return s += sfx;
|
||||
}
|
||||
|
||||
nsACString&
|
||||
AppendToString(nsACString& s, const nsIntRegion& r,
|
||||
const char* pfx="", const char* sfx="");
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include "nsRect.h" // for nsIntRect
|
||||
#include "nsRegion.h" // for nsIntRegion
|
||||
#include "nsTArray.h" // for nsTArray
|
||||
#include "prlog.h" // for PR_LOG
|
||||
|
||||
#if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 17
|
||||
#include <ui/Fence.h>
|
||||
@ -25,6 +26,24 @@
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
// To get this logging, you need PR logging enabled (either by
|
||||
// doing a debug build, or #define'ing FORCE_PR_LOG at the top
|
||||
// of a .cpp file), and then run with NSPR_LOG_MODULES=tiling:5
|
||||
// in your environment at runtime.
|
||||
#ifdef PR_LOGGING
|
||||
# define TILING_PRLOG(_args) PR_LOG(gTilingLog, PR_LOG_DEBUG, _args)
|
||||
# define TILING_PRLOG_OBJ(_args, obj) \
|
||||
{ \
|
||||
nsAutoCString tmpstr; \
|
||||
AppendToString(tmpstr, obj); \
|
||||
PR_LOG(gTilingLog, PR_LOG_DEBUG, _args); \
|
||||
}
|
||||
extern PRLogModuleInfo* gTilingLog;
|
||||
#else
|
||||
# define TILING_PRLOG(_args)
|
||||
# define TILING_PRLOG_OBJ(_args, obj)
|
||||
#endif
|
||||
|
||||
// An abstract implementation of a tile buffer. This code covers the logic of
|
||||
// moving and reusing tiles and leaves the validation up to the implementor. To
|
||||
// avoid the overhead of virtual dispatch, we employ the curiously recurring
|
||||
|
@ -9,6 +9,7 @@
|
||||
|
||||
#include "CrossProcessMutex.h"
|
||||
#include "mozilla/layers/GeckoContentController.h"
|
||||
#include "mozilla/layers/APZCTreeManager.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/EventForwards.h"
|
||||
#include "mozilla/Monitor.h"
|
||||
@ -38,7 +39,6 @@ class GestureEventListener;
|
||||
class ContainerLayer;
|
||||
class PCompositorParent;
|
||||
class ViewTransform;
|
||||
class APZCTreeManager;
|
||||
class AsyncPanZoomAnimation;
|
||||
class FlingAnimation;
|
||||
|
||||
|
@ -28,6 +28,8 @@
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
PRLogModuleInfo* gTilingLog;
|
||||
|
||||
using namespace mozilla::gfx;
|
||||
|
||||
void
|
||||
@ -143,6 +145,9 @@ ClientLayerManager::CreateThebesLayerWithHint(ThebesLayerCreationHint aHint)
|
||||
(AsShadowForwarder()->GetCompositorBackendType() == LayersBackend::LAYERS_OPENGL ||
|
||||
AsShadowForwarder()->GetCompositorBackendType() == LayersBackend::LAYERS_D3D9 ||
|
||||
AsShadowForwarder()->GetCompositorBackendType() == LayersBackend::LAYERS_D3D11)) {
|
||||
if (!gTilingLog) {
|
||||
gTilingLog = PR_NewLogModule("tiling");
|
||||
}
|
||||
if (gfxPrefs::LayersUseSimpleTiles()) {
|
||||
nsRefPtr<SimpleClientTiledThebesLayer> layer =
|
||||
new SimpleClientTiledThebesLayer(this);
|
||||
|
@ -2,6 +2,11 @@
|
||||
* 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/. */
|
||||
|
||||
// Uncomment this to enable the TILING_PRLOG stuff in this file
|
||||
// for release builds. To get the output you need to have
|
||||
// NSPR_LOG_MODULES=tiling:5 in your environment at runtime.
|
||||
// #define FORCE_PR_LOG
|
||||
|
||||
#include "ClientTiledThebesLayer.h"
|
||||
#include "FrameMetrics.h" // for FrameMetrics
|
||||
#include "Units.h" // for ScreenIntRect, CSSPoint, etc
|
||||
@ -18,6 +23,7 @@
|
||||
#include "mozilla/mozalloc.h" // for operator delete, etc
|
||||
#include "nsISupportsImpl.h" // for MOZ_COUNT_CTOR, etc
|
||||
#include "nsRect.h" // for nsIntRect
|
||||
#include "LayersLogging.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
@ -52,10 +58,10 @@ ClientTiledThebesLayer::FillSpecificAttributes(SpecificLayerAttributes& aAttrs)
|
||||
aAttrs = ThebesLayerAttributes(GetValidRegion());
|
||||
}
|
||||
|
||||
static LayoutDeviceRect
|
||||
ApplyParentLayerToLayoutTransform(const gfx3DMatrix& aTransform, const ParentLayerRect& aParentLayerRect)
|
||||
static LayerRect
|
||||
ApplyParentLayerToLayerTransform(const gfx3DMatrix& aTransform, const ParentLayerRect& aParentLayerRect)
|
||||
{
|
||||
return TransformTo<LayoutDevicePixel>(aTransform, aParentLayerRect);
|
||||
return TransformTo<LayerPixel>(aTransform, aParentLayerRect);
|
||||
}
|
||||
|
||||
static gfx3DMatrix
|
||||
@ -64,6 +70,12 @@ GetTransformToAncestorsParentLayer(Layer* aStart, Layer* aAncestor)
|
||||
gfx::Matrix4x4 transform;
|
||||
Layer* ancestorParent = aAncestor->GetParent();
|
||||
for (Layer* iter = aStart; iter != ancestorParent; iter = iter->GetParent()) {
|
||||
if (iter->AsContainerLayer()) {
|
||||
// If the layer has a non-transient async transform then we need to apply it here
|
||||
// because it will get applied by the APZ in the compositor as well
|
||||
const FrameMetrics& metrics = iter->AsContainerLayer()->GetFrameMetrics();
|
||||
transform = transform * gfx::Matrix4x4().Scale(metrics.mResolution.scale, metrics.mResolution.scale, 1.f);
|
||||
}
|
||||
transform = transform * iter->GetTransform();
|
||||
}
|
||||
gfx3DMatrix ret;
|
||||
@ -117,49 +129,58 @@ ClientTiledThebesLayer::BeginPaint()
|
||||
return;
|
||||
}
|
||||
|
||||
TILING_PRLOG(("TILING 0x%p: Found scrollAncestor 0x%p and displayPortAncestor 0x%p\n", this,
|
||||
scrollAncestor, displayPortAncestor));
|
||||
|
||||
const FrameMetrics& scrollMetrics = scrollAncestor->GetFrameMetrics();
|
||||
const FrameMetrics& displayportMetrics = displayPortAncestor->GetFrameMetrics();
|
||||
|
||||
// Calculate the transform required to convert ParentLayer space of our
|
||||
// display port ancestor to the LayoutDevice space of this layer.
|
||||
gfx3DMatrix layoutDeviceToDisplayPort =
|
||||
// display port ancestor to the Layer space of this layer.
|
||||
gfx3DMatrix transformToDisplayPort =
|
||||
GetTransformToAncestorsParentLayer(this, displayPortAncestor);
|
||||
layoutDeviceToDisplayPort.ScalePost(scrollMetrics.mCumulativeResolution.scale,
|
||||
scrollMetrics.mCumulativeResolution.scale,
|
||||
1.f);
|
||||
|
||||
mPaintData.mTransformDisplayPortToLayoutDevice = layoutDeviceToDisplayPort.Inverse();
|
||||
mPaintData.mTransformDisplayPortToLayer = transformToDisplayPort.Inverse();
|
||||
|
||||
// Note that below we use GetZoomToParent() in a number of places. Because this
|
||||
// code runs on the client side, the mTransformScale field of the FrameMetrics
|
||||
// will not have been set. This can result in incorrect values being returned
|
||||
// by GetZoomToParent() when we have CSS transforms set on some of these layers.
|
||||
// This code should be audited and updated as part of fixing bug 993525.
|
||||
|
||||
// Compute the critical display port that applies to this layer in the
|
||||
// LayoutDevice space of this layer.
|
||||
ParentLayerRect criticalDisplayPort =
|
||||
(displayportMetrics.mCriticalDisplayPort * displayportMetrics.GetZoomToParent())
|
||||
+ displayportMetrics.mCompositionBounds.TopLeft();
|
||||
mPaintData.mCriticalDisplayPort = LayoutDeviceIntRect::ToUntyped(RoundedOut(
|
||||
ApplyParentLayerToLayoutTransform(mPaintData.mTransformDisplayPortToLayoutDevice,
|
||||
criticalDisplayPort)));
|
||||
mPaintData.mCriticalDisplayPort = RoundedOut(
|
||||
ApplyParentLayerToLayerTransform(mPaintData.mTransformDisplayPortToLayer, criticalDisplayPort));
|
||||
TILING_PRLOG_OBJ(("TILING 0x%p: Critical displayport %s\n", this, tmpstr.get()), mPaintData.mCriticalDisplayPort);
|
||||
|
||||
// Compute the viewport that applies to this layer in the LayoutDevice
|
||||
// space of this layer.
|
||||
ParentLayerRect viewport =
|
||||
(displayportMetrics.mViewport * displayportMetrics.GetZoomToParent())
|
||||
+ displayportMetrics.mCompositionBounds.TopLeft();
|
||||
mPaintData.mViewport = ApplyParentLayerToLayoutTransform(
|
||||
mPaintData.mTransformDisplayPortToLayoutDevice, viewport);
|
||||
mPaintData.mViewport = ApplyParentLayerToLayerTransform(
|
||||
mPaintData.mTransformDisplayPortToLayer, viewport);
|
||||
TILING_PRLOG_OBJ(("TILING 0x%p: Viewport %s\n", this, tmpstr.get()), mPaintData.mViewport);
|
||||
|
||||
// Store the resolution from the displayport ancestor layer. Because this is Gecko-side,
|
||||
// before any async transforms have occurred, we can use the zoom for this.
|
||||
mPaintData.mResolution = displayportMetrics.GetZoomToParent();
|
||||
TILING_PRLOG(("TILING 0x%p: Resolution %f\n", this, mPaintData.mResolution.scale));
|
||||
|
||||
// Store the applicable composition bounds in this layer's LayoutDevice units.
|
||||
gfx3DMatrix layoutDeviceToCompBounds =
|
||||
// Store the applicable composition bounds in this layer's Layer units.
|
||||
gfx3DMatrix transformToCompBounds =
|
||||
GetTransformToAncestorsParentLayer(this, scrollAncestor);
|
||||
mPaintData.mCompositionBounds = TransformTo<LayoutDevicePixel>(
|
||||
layoutDeviceToCompBounds.Inverse(),
|
||||
scrollMetrics.mCompositionBounds / scrollMetrics.GetParentResolution());
|
||||
mPaintData.mCompositionBounds = ApplyParentLayerToLayerTransform(
|
||||
transformToCompBounds.Inverse(), ParentLayerRect(scrollMetrics.mCompositionBounds));
|
||||
TILING_PRLOG_OBJ(("TILING 0x%p: Composition bounds %s\n", this, tmpstr.get()), mPaintData.mCompositionBounds);
|
||||
|
||||
// Calculate the scroll offset since the last transaction
|
||||
mPaintData.mScrollOffset = displayportMetrics.GetScrollOffset() * displayportMetrics.GetZoomToParent();
|
||||
TILING_PRLOG_OBJ(("TILING 0x%p: Scroll offset %s\n", this, tmpstr.get()), mPaintData.mScrollOffset);
|
||||
}
|
||||
|
||||
void
|
||||
@ -172,6 +193,7 @@ ClientTiledThebesLayer::EndPaint(bool aFinish)
|
||||
mPaintData.mLastScrollOffset = mPaintData.mScrollOffset;
|
||||
mPaintData.mPaintFinished = true;
|
||||
mPaintData.mFirstPaint = false;
|
||||
TILING_PRLOG(("TILING 0x%p: Paint finished\n", this));
|
||||
}
|
||||
|
||||
void
|
||||
@ -197,6 +219,9 @@ ClientTiledThebesLayer::RenderLayer()
|
||||
mValidRegion = nsIntRegion();
|
||||
}
|
||||
|
||||
TILING_PRLOG_OBJ(("TILING 0x%p: Initial visible region %s\n", this, tmpstr.get()), mVisibleRegion);
|
||||
TILING_PRLOG_OBJ(("TILING 0x%p: Initial valid region %s\n", this, tmpstr.get()), mValidRegion);
|
||||
|
||||
nsIntRegion invalidRegion = mVisibleRegion;
|
||||
invalidRegion.Sub(invalidRegion, mValidRegion);
|
||||
if (invalidRegion.IsEmpty()) {
|
||||
@ -239,6 +264,9 @@ ClientTiledThebesLayer::RenderLayer()
|
||||
return;
|
||||
}
|
||||
|
||||
TILING_PRLOG_OBJ(("TILING 0x%p: Valid region %s\n", this, tmpstr.get()), mValidRegion);
|
||||
TILING_PRLOG_OBJ(("TILING 0x%p: Visible region %s\n", this, tmpstr.get()), mVisibleRegion);
|
||||
|
||||
// Make sure that tiles that fall outside of the visible region are
|
||||
// discarded on the first update.
|
||||
if (!ClientManager()->IsRepeatTransaction()) {
|
||||
@ -246,7 +274,7 @@ ClientTiledThebesLayer::RenderLayer()
|
||||
if (!mPaintData.mCriticalDisplayPort.IsEmpty()) {
|
||||
// Make sure that tiles that fall outside of the critical displayport are
|
||||
// discarded on the first update.
|
||||
mValidRegion.And(mValidRegion, mPaintData.mCriticalDisplayPort);
|
||||
mValidRegion.And(mValidRegion, LayerIntRect::ToUntyped(mPaintData.mCriticalDisplayPort));
|
||||
}
|
||||
}
|
||||
|
||||
@ -262,13 +290,15 @@ ClientTiledThebesLayer::RenderLayer()
|
||||
}
|
||||
|
||||
// Clip the invalid region to the critical display-port
|
||||
invalidRegion.And(invalidRegion, mPaintData.mCriticalDisplayPort);
|
||||
invalidRegion.And(invalidRegion, LayerIntRect::ToUntyped(mPaintData.mCriticalDisplayPort));
|
||||
if (invalidRegion.IsEmpty() && lowPrecisionInvalidRegion.IsEmpty()) {
|
||||
EndPaint(true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
TILING_PRLOG_OBJ(("TILING 0x%p: Invalid region %s\n", this, tmpstr.get()), invalidRegion);
|
||||
|
||||
if (!invalidRegion.IsEmpty() && mPaintData.mLowPrecisionPaintCount == 0) {
|
||||
bool updatedBuffer = false;
|
||||
// Only draw progressively when the resolution is unchanged.
|
||||
@ -281,9 +311,11 @@ ClientTiledThebesLayer::RenderLayer()
|
||||
nsIntRegion oldValidRegion = mContentClient->mTiledBuffer.GetValidRegion();
|
||||
oldValidRegion.And(oldValidRegion, mVisibleRegion);
|
||||
if (!mPaintData.mCriticalDisplayPort.IsEmpty()) {
|
||||
oldValidRegion.And(oldValidRegion, mPaintData.mCriticalDisplayPort);
|
||||
oldValidRegion.And(oldValidRegion, LayerIntRect::ToUntyped(mPaintData.mCriticalDisplayPort));
|
||||
}
|
||||
|
||||
TILING_PRLOG_OBJ(("TILING 0x%p: Progressive update with old valid region %s\n", this, tmpstr.get()), oldValidRegion);
|
||||
|
||||
updatedBuffer =
|
||||
mContentClient->mTiledBuffer.ProgressiveUpdate(mValidRegion, invalidRegion,
|
||||
oldValidRegion, &mPaintData,
|
||||
@ -292,8 +324,12 @@ ClientTiledThebesLayer::RenderLayer()
|
||||
updatedBuffer = true;
|
||||
mValidRegion = mVisibleRegion;
|
||||
if (!mPaintData.mCriticalDisplayPort.IsEmpty()) {
|
||||
mValidRegion.And(mValidRegion, mPaintData.mCriticalDisplayPort);
|
||||
mValidRegion.And(mValidRegion, LayerIntRect::ToUntyped(mPaintData.mCriticalDisplayPort));
|
||||
}
|
||||
|
||||
TILING_PRLOG_OBJ(("TILING 0x%p: Painting: valid region %s\n", this, tmpstr.get()), mValidRegion);
|
||||
TILING_PRLOG_OBJ(("TILING 0x%p: and invalid region %s\n", this, tmpstr.get()), invalidRegion);
|
||||
|
||||
mContentClient->mTiledBuffer.SetFrameResolution(mPaintData.mResolution);
|
||||
mContentClient->mTiledBuffer.PaintThebes(mValidRegion, invalidRegion,
|
||||
callback, data);
|
||||
@ -318,11 +354,14 @@ ClientTiledThebesLayer::RenderLayer()
|
||||
}
|
||||
}
|
||||
|
||||
TILING_PRLOG_OBJ(("TILING 0x%p: Low-precision valid region is %s\n", this, tmpstr.get()), mLowPrecisionValidRegion);
|
||||
TILING_PRLOG_OBJ(("TILING 0x%p: Low-precision invalid region is %s\n", this, tmpstr.get()), lowPrecisionInvalidRegion);
|
||||
|
||||
// Render the low precision buffer, if there's area to invalidate and the
|
||||
// visible region is larger than the critical display port.
|
||||
bool updatedLowPrecision = false;
|
||||
if (!lowPrecisionInvalidRegion.IsEmpty() &&
|
||||
!nsIntRegion(mPaintData.mCriticalDisplayPort).Contains(mVisibleRegion)) {
|
||||
!nsIntRegion(LayerIntRect::ToUntyped(mPaintData.mCriticalDisplayPort)).Contains(mVisibleRegion)) {
|
||||
nsIntRegion oldValidRegion =
|
||||
mContentClient->mLowPrecisionTiledBuffer.GetValidRegion();
|
||||
oldValidRegion.And(oldValidRegion, mVisibleRegion);
|
||||
|
@ -929,6 +929,7 @@ ContentClientIncremental::GetUpdateSurface(BufferType aType,
|
||||
mContentType,
|
||||
&desc)) {
|
||||
NS_WARNING("creating SurfaceDescriptor failed!");
|
||||
Clear();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -889,29 +889,29 @@ ClientTiledLayerBuffer::ValidateTile(TileClient aTile,
|
||||
return aTile;
|
||||
}
|
||||
|
||||
static LayoutDeviceRect
|
||||
static LayerRect
|
||||
TransformCompositionBounds(const ParentLayerRect& aCompositionBounds,
|
||||
const CSSToParentLayerScale& aZoom,
|
||||
const ParentLayerPoint& aScrollOffset,
|
||||
const CSSToParentLayerScale& aResolution,
|
||||
const gfx3DMatrix& aTransformDisplayPortToLayoutDevice)
|
||||
const gfx3DMatrix& aTransformDisplayPortToLayer)
|
||||
{
|
||||
// Transform the composition bounds from the space of the displayport ancestor
|
||||
// layer into the LayoutDevice space of this layer. Do this by
|
||||
// layer into the Layer space of this layer. Do this by
|
||||
// compensating for the difference in resolution and subtracting the
|
||||
// old composition bounds origin.
|
||||
ParentLayerRect offsetViewportRect = (aCompositionBounds / aZoom) * aResolution;
|
||||
offsetViewportRect.MoveBy(-aScrollOffset);
|
||||
|
||||
gfxRect transformedViewport =
|
||||
aTransformDisplayPortToLayoutDevice.TransformBounds(
|
||||
aTransformDisplayPortToLayer.TransformBounds(
|
||||
gfxRect(offsetViewportRect.x, offsetViewportRect.y,
|
||||
offsetViewportRect.width, offsetViewportRect.height));
|
||||
|
||||
return LayoutDeviceRect(transformedViewport.x,
|
||||
transformedViewport.y,
|
||||
transformedViewport.width,
|
||||
transformedViewport.height);
|
||||
return LayerRect(transformedViewport.x,
|
||||
transformedViewport.y,
|
||||
transformedViewport.width,
|
||||
transformedViewport.height);
|
||||
}
|
||||
|
||||
bool
|
||||
@ -976,26 +976,27 @@ ClientTiledLayerBuffer::ComputeProgressiveUpdateRegion(const nsIntRegion& aInval
|
||||
}
|
||||
}
|
||||
|
||||
LayoutDeviceRect transformedCompositionBounds =
|
||||
LayerRect transformedCompositionBounds =
|
||||
TransformCompositionBounds(compositionBounds, zoom, aPaintData->mScrollOffset,
|
||||
aPaintData->mResolution, aPaintData->mTransformDisplayPortToLayoutDevice);
|
||||
aPaintData->mResolution, aPaintData->mTransformDisplayPortToLayer);
|
||||
|
||||
// Paint tiles that have stale content or that intersected with the screen
|
||||
// at the time of issuing the draw command in a single transaction first.
|
||||
// This is to avoid rendering glitches on animated page content, and when
|
||||
// layers change size/shape.
|
||||
LayoutDeviceRect typedCoherentUpdateRect =
|
||||
LayerRect typedCoherentUpdateRect =
|
||||
transformedCompositionBounds.Intersect(aPaintData->mCompositionBounds);
|
||||
|
||||
// Offset by the viewport origin, as the composition bounds are stored in
|
||||
// Layer space and not LayoutDevice space.
|
||||
// TODO(kats): does this make sense?
|
||||
typedCoherentUpdateRect.MoveBy(aPaintData->mViewport.TopLeft());
|
||||
|
||||
// Convert to untyped to intersect with the invalid region.
|
||||
nsIntRect roundedCoherentUpdateRect =
|
||||
LayoutDeviceIntRect::ToUntyped(RoundedOut(typedCoherentUpdateRect));
|
||||
nsIntRect untypedCoherentUpdateRect(LayerIntRect::ToUntyped(
|
||||
RoundedOut(typedCoherentUpdateRect)));
|
||||
|
||||
aRegionToPaint.And(aInvalidRegion, roundedCoherentUpdateRect);
|
||||
aRegionToPaint.And(aInvalidRegion, untypedCoherentUpdateRect);
|
||||
aRegionToPaint.Or(aRegionToPaint, staleRegion);
|
||||
bool drawingStale = !aRegionToPaint.IsEmpty();
|
||||
if (!drawingStale) {
|
||||
@ -1004,8 +1005,8 @@ ClientTiledLayerBuffer::ComputeProgressiveUpdateRegion(const nsIntRegion& aInval
|
||||
|
||||
// Prioritise tiles that are currently visible on the screen.
|
||||
bool paintVisible = false;
|
||||
if (aRegionToPaint.Intersects(roundedCoherentUpdateRect)) {
|
||||
aRegionToPaint.And(aRegionToPaint, roundedCoherentUpdateRect);
|
||||
if (aRegionToPaint.Intersects(untypedCoherentUpdateRect)) {
|
||||
aRegionToPaint.And(aRegionToPaint, untypedCoherentUpdateRect);
|
||||
paintVisible = true;
|
||||
}
|
||||
|
||||
|
@ -255,26 +255,23 @@ struct BasicTiledLayerPaintData {
|
||||
|
||||
/*
|
||||
* The transform matrix to go from the display port layer's ParentLayer
|
||||
* units to this layer's LayoutDevice units. The "display port layer" is
|
||||
* units to this layer's Layer units. The "display port layer" is
|
||||
* the closest ancestor layer with a displayport.
|
||||
*/
|
||||
gfx3DMatrix mTransformDisplayPortToLayoutDevice;
|
||||
gfx3DMatrix mTransformDisplayPortToLayer;
|
||||
|
||||
/*
|
||||
* The critical displayport of the content from the nearest ancestor layer
|
||||
* that represents scrollable content with a display port set. Empty if a
|
||||
* critical displayport is not set.
|
||||
*
|
||||
* This is in LayoutDevice coordinates, but is stored as an nsIntRect for
|
||||
* convenience when intersecting with the layer's mValidRegion.
|
||||
*/
|
||||
nsIntRect mCriticalDisplayPort;
|
||||
LayerIntRect mCriticalDisplayPort;
|
||||
|
||||
/*
|
||||
* The viewport of the content from the nearest ancestor layer that
|
||||
* represents scrollable content with a display port set.
|
||||
*/
|
||||
LayoutDeviceRect mViewport;
|
||||
LayerRect mViewport;
|
||||
|
||||
/*
|
||||
* The render resolution of the document that the content this layer
|
||||
@ -283,11 +280,11 @@ struct BasicTiledLayerPaintData {
|
||||
CSSToParentLayerScale mResolution;
|
||||
|
||||
/*
|
||||
* The composition bounds of the layer, in LayoutDevice coordinates. This is
|
||||
* The composition bounds of the layer, in Layer coordinates. This is
|
||||
* used to make sure that tiled updates to regions that are visible to the
|
||||
* user are grouped coherently.
|
||||
*/
|
||||
LayoutDeviceRect mCompositionBounds;
|
||||
LayerRect mCompositionBounds;
|
||||
|
||||
/*
|
||||
* Low precision updates are always executed a tile at a time in repeated
|
||||
|
@ -406,14 +406,6 @@ ContentHostIncremental::~ContentHostIncremental()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
ContentHostIncremental::DestroyTextures()
|
||||
{
|
||||
mSource = nullptr;
|
||||
mSourceOnWhite = nullptr;
|
||||
mUpdateList.Clear();
|
||||
}
|
||||
|
||||
bool
|
||||
ContentHostIncremental::CreatedIncrementalTexture(ISurfaceAllocator* aAllocator,
|
||||
const TextureInfo& aTextureInfo,
|
||||
@ -501,6 +493,8 @@ ContentHostIncremental::TextureCreationRequest::Execute(ContentHostIncremental*
|
||||
}
|
||||
|
||||
if (mTextureInfo.mDeprecatedTextureHostFlags & DeprecatedTextureHostFlags::COPY_PREVIOUS) {
|
||||
MOZ_ASSERT(aHost->mSource);
|
||||
MOZ_ASSERT(aHost->mSource->IsValid());
|
||||
nsIntRect bufferRect = aHost->mBufferRect;
|
||||
nsIntPoint bufferRotation = aHost->mBufferRotation;
|
||||
nsIntRect overlap;
|
||||
|
@ -281,8 +281,6 @@ public:
|
||||
|
||||
virtual void PrintInfo(nsACString& aTo, const char* aPrefix) MOZ_OVERRIDE;
|
||||
|
||||
virtual void DestroyTextures();
|
||||
|
||||
virtual bool Lock() {
|
||||
MOZ_ASSERT(!mLocked);
|
||||
ProcessTextureUpdates();
|
||||
|
@ -385,8 +385,11 @@ TextureImageTextureSourceOGL::GetSize() const
|
||||
gfx::SurfaceFormat
|
||||
TextureImageTextureSourceOGL::GetFormat() const
|
||||
{
|
||||
MOZ_ASSERT(mTexImage);
|
||||
return mTexImage->GetTextureFormat();
|
||||
if (mTexImage) {
|
||||
return mTexImage->GetTextureFormat();
|
||||
}
|
||||
NS_WARNING("Trying to query the format of an empty TextureSource.");
|
||||
return gfx::SurfaceFormat::UNKNOWN;
|
||||
}
|
||||
|
||||
nsIntRect TextureImageTextureSourceOGL::GetTileRect()
|
||||
|
@ -2,9 +2,10 @@ This is the Sanitiser for OpenType project, from http://code.google.com/p/ots/.
|
||||
|
||||
Our reference repository is https://github.com/khaledhosny/ots/.
|
||||
|
||||
Current revision: d7d831edd171054c7974f5e0dec2fc19bf869574
|
||||
Current revision: d6018b62bf41f6b419aeae6d2795725a55715481
|
||||
|
||||
Applied local patches:
|
||||
ots-visibility.patch - make Process function externally visible for Windows DLL (bug 711079)
|
||||
Upstream files included: LICENSE, src/, include/
|
||||
|
||||
ots-woff2 - disable WOFF2 support (bug 941019)
|
||||
Additional files: README.mozilla, src/moz.build
|
||||
|
||||
Additional patch: ots-visibility.patch (bug 711079).
|
||||
|
@ -199,16 +199,6 @@ class OTSStream {
|
||||
unsigned chksum_buffer_offset_;
|
||||
};
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Process a given OpenType file and write out a sanitised version
|
||||
// output: a pointer to an object implementing the OTSStream interface. The
|
||||
// sanitisied output will be written to this. In the even of a failure,
|
||||
// partial output may have been written.
|
||||
// input: the OpenType file
|
||||
// length: the size, in bytes, of |input|
|
||||
// -----------------------------------------------------------------------------
|
||||
bool OTS_API Process(OTSStream *output, const uint8_t *input, size_t length);
|
||||
|
||||
// Signature of the function to be provided by the client in order to report errors.
|
||||
// The return type is a boolean so that it can be used within an expression,
|
||||
// but the actual value is ignored. (Suggested convention is to always return 'false'.)
|
||||
@ -219,9 +209,6 @@ bool OTS_API Process(OTSStream *output, const uint8_t *input, size_t length);
|
||||
#endif
|
||||
typedef bool (*MessageFunc)(void *user_data, const char *format, ...) MSGFUNC_FMT_ATTR;
|
||||
|
||||
// Set a callback function that will be called when OTS is reporting an error.
|
||||
void OTS_API SetMessageCallback(MessageFunc func, void *user_data);
|
||||
|
||||
enum TableAction {
|
||||
TABLE_ACTION_DEFAULT, // Use OTS's default action for that table
|
||||
TABLE_ACTION_SANITIZE, // Sanitize the table, potentially droping it
|
||||
@ -231,20 +218,56 @@ enum TableAction {
|
||||
|
||||
// Signature of the function to be provided by the client to decide what action
|
||||
// to do for a given table.
|
||||
// tag: table tag as an integer in big-endian byte order, independent of platform endianness
|
||||
// user_data: user defined data that are passed to SetTableActionCallback()
|
||||
typedef TableAction (*TableActionFunc)(uint32_t tag, void *user_data);
|
||||
|
||||
// Set a callback function that will be called when OTS needs to decide what to
|
||||
// do for a font table.
|
||||
void OTS_API SetTableActionCallback(TableActionFunc func, void *user_data);
|
||||
class OTS_API OTSContext {
|
||||
public:
|
||||
OTSContext()
|
||||
: message_func(0),
|
||||
message_user_data(0),
|
||||
table_action_func(0),
|
||||
table_action_user_data(0)
|
||||
{}
|
||||
|
||||
~OTSContext() {}
|
||||
|
||||
// Process a given OpenType file and write out a sanitised version
|
||||
// output: a pointer to an object implementing the OTSStream interface. The
|
||||
// sanitisied output will be written to this. In the even of a failure,
|
||||
// partial output may have been written.
|
||||
// input: the OpenType file
|
||||
// length: the size, in bytes, of |input|
|
||||
// context: optional context that holds various OTS settings like user callbacks
|
||||
bool Process(OTSStream *output, const uint8_t *input, size_t length);
|
||||
|
||||
// Set a callback function that will be called when OTS is reporting an error.
|
||||
void SetMessageCallback(MessageFunc func, void *user_data) {
|
||||
message_func = func;
|
||||
message_user_data = user_data;
|
||||
}
|
||||
|
||||
// Set a callback function that will be called when OTS needs to decide what to
|
||||
// do for a font table.
|
||||
void SetTableActionCallback(TableActionFunc func, void *user_data) {
|
||||
table_action_func = func;
|
||||
table_action_user_data = user_data;
|
||||
}
|
||||
|
||||
private:
|
||||
MessageFunc message_func;
|
||||
void *message_user_data;
|
||||
TableActionFunc table_action_func;
|
||||
void *table_action_user_data;
|
||||
};
|
||||
|
||||
// Force to disable debug output even when the library is compiled with
|
||||
// -DOTS_DEBUG.
|
||||
void DisableDebugOutput();
|
||||
|
||||
#ifdef MOZ_OTS_WOFF2
|
||||
// Enable WOFF2 support(experimental).
|
||||
void EnableWOFF2();
|
||||
#endif
|
||||
|
||||
} // namespace ots
|
||||
|
||||
|
@ -37,52 +37,22 @@ diff --git a/gfx/ots/include/opentype-sanitiser.h b/gfx/ots/include/opentype-san
|
||||
typedef unsigned short uint16_t;
|
||||
typedef int int32_t;
|
||||
typedef unsigned int uint32_t;
|
||||
@@ -182,45 +202,45 @@ class OTSStream {
|
||||
// -----------------------------------------------------------------------------
|
||||
// Process a given OpenType file and write out a sanitised version
|
||||
// output: a pointer to an object implementing the OTSStream interface. The
|
||||
// sanitisied output will be written to this. In the even of a failure,
|
||||
// partial output may have been written.
|
||||
// input: the OpenType file
|
||||
// length: the size, in bytes, of |input|
|
||||
// -----------------------------------------------------------------------------
|
||||
-bool Process(OTSStream *output, const uint8_t *input, size_t length);
|
||||
+bool OTS_API Process(OTSStream *output, const uint8_t *input, size_t length);
|
||||
|
||||
// Signature of the function to be provided by the client in order to report errors.
|
||||
// The return type is a boolean so that it can be used within an expression,
|
||||
// but the actual value is ignored. (Suggested convention is to always return 'false'.)
|
||||
#ifdef __GCC__
|
||||
#define MSGFUNC_FMT_ATTR __attribute__((format(printf, 2, 3)))
|
||||
#else
|
||||
#define MSGFUNC_FMT_ATTR
|
||||
#endif
|
||||
typedef bool (*MessageFunc)(void *user_data, const char *format, ...) MSGFUNC_FMT_ATTR;
|
||||
|
||||
// Set a callback function that will be called when OTS is reporting an error.
|
||||
-void SetMessageCallback(MessageFunc func, void *user_data);
|
||||
+void OTS_API SetMessageCallback(MessageFunc func, void *user_data);
|
||||
|
||||
enum TableAction {
|
||||
TABLE_ACTION_DEFAULT, // Use OTS's default action for that table
|
||||
TABLE_ACTION_SANITIZE, // Sanitize the table, potentially droping it
|
||||
TABLE_ACTION_PASSTHRU, // Serialize the table unchanged
|
||||
TABLE_ACTION_DROP // Drop the table
|
||||
@@ -197,17 +217,17 @@ enum TableAction {
|
||||
};
|
||||
|
||||
// Signature of the function to be provided by the client to decide what action
|
||||
// to do for a given table.
|
||||
// tag: table tag as an integer in big-endian byte order, independent of platform endianness
|
||||
// user_data: user defined data that are passed to SetTableActionCallback()
|
||||
typedef TableAction (*TableActionFunc)(uint32_t tag, void *user_data);
|
||||
|
||||
// Set a callback function that will be called when OTS needs to decide what to
|
||||
// do for a font table.
|
||||
-void SetTableActionCallback(TableActionFunc func, void *user_data);
|
||||
+void OTS_API SetTableActionCallback(TableActionFunc func, void *user_data);
|
||||
|
||||
// Force to disable debug output even when the library is compiled with
|
||||
// -DOTS_DEBUG.
|
||||
void DisableDebugOutput();
|
||||
|
||||
// Enable WOFF2 support(experimental).
|
||||
void EnableWOFF2();
|
||||
-class OTSContext {
|
||||
+class OTS_API OTSContext {
|
||||
public:
|
||||
OTSContext()
|
||||
: message_func(0),
|
||||
message_user_data(0),
|
||||
table_action_func(0),
|
||||
table_action_user_data(0)
|
||||
{}
|
||||
|
||||
|
@ -1,134 +0,0 @@
|
||||
diff --git a/gfx/ots/include/opentype-sanitiser.h b/gfx/ots/include/opentype-sanitiser.h
|
||||
--- a/gfx/ots/include/opentype-sanitiser.h
|
||||
+++ b/gfx/ots/include/opentype-sanitiser.h
|
||||
@@ -236,14 +236,16 @@ typedef TableAction (*TableActionFunc)(u
|
||||
// Set a callback function that will be called when OTS needs to decide what to
|
||||
// do for a font table.
|
||||
void OTS_API SetTableActionCallback(TableActionFunc func, void *user_data);
|
||||
|
||||
// Force to disable debug output even when the library is compiled with
|
||||
// -DOTS_DEBUG.
|
||||
void DisableDebugOutput();
|
||||
|
||||
+#ifdef MOZ_OTS_WOFF2
|
||||
// Enable WOFF2 support(experimental).
|
||||
void EnableWOFF2();
|
||||
+#endif
|
||||
|
||||
} // namespace ots
|
||||
|
||||
#endif // OPENTYPE_SANITISER_H_
|
||||
diff --git a/gfx/ots/src/ots.cc b/gfx/ots/src/ots.cc
|
||||
--- a/gfx/ots/src/ots.cc
|
||||
+++ b/gfx/ots/src/ots.cc
|
||||
@@ -9,25 +9,29 @@
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <limits>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
+#ifdef MOZ_OTS_WOFF2
|
||||
#include "woff2.h"
|
||||
+#endif
|
||||
|
||||
// The OpenType Font File
|
||||
// http://www.microsoft.com/typography/otspec/cmap.htm
|
||||
|
||||
namespace {
|
||||
|
||||
bool g_debug_output = true;
|
||||
+#ifdef MOZ_OTS_WOFF2
|
||||
bool g_enable_woff2 = false;
|
||||
+#endif
|
||||
|
||||
ots::MessageFunc g_message_func = NULL;
|
||||
void *g_message_user_data = NULL;
|
||||
|
||||
ots::TableActionFunc g_table_action_func = NULL;
|
||||
void *g_table_action_user_data = NULL;
|
||||
|
||||
// Generate a message with or without a table tag, when 'header' is the OpenTypeFile pointer
|
||||
@@ -395,16 +399,17 @@ bool ProcessWOFF(ots::OpenTypeFile *head
|
||||
}
|
||||
if (block_end != ots::Round4(length)) {
|
||||
return OTS_FAILURE_MSG_HDR("file length mismatch (trailing junk?)");
|
||||
}
|
||||
|
||||
return ProcessGeneric(header, woff_tag, output, data, length, tables, file);
|
||||
}
|
||||
|
||||
+#ifdef MOZ_OTS_WOFF2
|
||||
bool ProcessWOFF2(ots::OpenTypeFile *header,
|
||||
ots::OTSStream *output, const uint8_t *data, size_t length) {
|
||||
size_t decompressed_size = ots::ComputeWOFF2FinalSize(data, length);
|
||||
if (decompressed_size == 0) {
|
||||
return OTS_FAILURE();
|
||||
}
|
||||
// decompressed font must be <= 30MB
|
||||
if (decompressed_size > 30 * 1024 * 1024) {
|
||||
@@ -413,16 +418,17 @@ bool ProcessWOFF2(ots::OpenTypeFile *hea
|
||||
|
||||
std::vector<uint8_t> decompressed_buffer(decompressed_size);
|
||||
if (!ots::ConvertWOFF2ToTTF(&decompressed_buffer[0], decompressed_size,
|
||||
data, length)) {
|
||||
return OTS_FAILURE();
|
||||
}
|
||||
return ProcessTTF(header, output, &decompressed_buffer[0], decompressed_size);
|
||||
}
|
||||
+#endif
|
||||
|
||||
ots::TableAction GetTableAction(uint32_t tag) {
|
||||
ots::TableAction action = ots::TABLE_ACTION_DEFAULT;
|
||||
|
||||
if (g_table_action_func != NULL) {
|
||||
action = g_table_action_func(htonl(tag), g_table_action_user_data);
|
||||
}
|
||||
|
||||
@@ -795,19 +801,21 @@ bool IsValidVersionTag(uint32_t tag) {
|
||||
tag == Tag("true") ||
|
||||
tag == Tag("typ1");
|
||||
}
|
||||
|
||||
void DisableDebugOutput() {
|
||||
g_debug_output = false;
|
||||
}
|
||||
|
||||
+#ifdef MOZ_OTS_WOFF2
|
||||
void EnableWOFF2() {
|
||||
g_enable_woff2 = true;
|
||||
}
|
||||
+#endif
|
||||
|
||||
void SetMessageCallback(MessageFunc func, void *user_data) {
|
||||
g_message_func = func;
|
||||
g_message_user_data = user_data;
|
||||
}
|
||||
|
||||
void SetTableActionCallback(TableActionFunc func, void *user_data) {
|
||||
g_table_action_func = func;
|
||||
@@ -822,20 +830,22 @@ bool Process(OTSStream *output, const ui
|
||||
|
||||
if (length < 4) {
|
||||
return OTS_FAILURE_MSG_(&header, "file less than 4 bytes");
|
||||
}
|
||||
|
||||
bool result;
|
||||
if (data[0] == 'w' && data[1] == 'O' && data[2] == 'F' && data[3] == 'F') {
|
||||
result = ProcessWOFF(&header, output, data, length);
|
||||
+#ifdef MOZ_OTS_WOFF2
|
||||
} else if (g_enable_woff2 &&
|
||||
data[0] == 'w' && data[1] == 'O' && data[2] == 'F' &&
|
||||
data[3] == '2') {
|
||||
result = ProcessWOFF2(&header, output, data, length);
|
||||
+#endif
|
||||
} else {
|
||||
result = ProcessTTF(&header, output, data, length);
|
||||
}
|
||||
|
||||
for (unsigned i = 0; ; ++i) {
|
||||
if (table_parsers[i].parse == NULL) break;
|
||||
table_parsers[i].free(&header);
|
||||
}
|
@ -1028,3 +1028,5 @@ void ots_cff_free(OpenTypeFile *file) {
|
||||
}
|
||||
|
||||
} // namespace ots
|
||||
|
||||
#undef TABLE_NAME
|
||||
|
@ -360,8 +360,8 @@ bool Parse31013(ots::OpenTypeFile *file,
|
||||
if (!subtable.Skip(8)) {
|
||||
return OTS_FAILURE_MSG("Bad cmap subtable length");
|
||||
}
|
||||
uint16_t language = 0;
|
||||
if (!subtable.ReadU16(&language)) {
|
||||
uint32_t language = 0;
|
||||
if (!subtable.ReadU32(&language)) {
|
||||
return OTS_FAILURE_MSG("Can't read cmap subtable language");
|
||||
}
|
||||
if (language) {
|
||||
@ -876,7 +876,7 @@ bool ots_cmap_serialise(OTSStream *out, OpenTypeFile *file) {
|
||||
|
||||
// Some fonts don't have 3-0-4 MS Symbol nor 3-1-4 Unicode BMP tables
|
||||
// (e.g., old fonts for Mac). We don't support them.
|
||||
if (!have_304 && !have_314 && !have_034) {
|
||||
if (!have_304 && !have_314 && !have_034 && !have_31012 && !have_31013) {
|
||||
return OTS_FAILURE();
|
||||
}
|
||||
|
||||
@ -1005,7 +1005,7 @@ bool ots_cmap_serialise(OTSStream *out, OpenTypeFile *file) {
|
||||
= file->cmap->subtable_3_10_13;
|
||||
const unsigned num_groups = groups.size();
|
||||
if (!out->WriteU16(13) ||
|
||||
!out->WriteU16(0) ||
|
||||
!out->WriteU32(0) ||
|
||||
!out->WriteU32(num_groups * 12 + 14) ||
|
||||
!out->WriteU32(0) ||
|
||||
!out->WriteU32(num_groups)) {
|
||||
@ -1101,3 +1101,5 @@ void ots_cmap_free(OpenTypeFile *file) {
|
||||
}
|
||||
|
||||
} // namespace ots
|
||||
|
||||
#undef TABLE_NAME
|
||||
|
@ -56,3 +56,5 @@ void ots_cvt_free(OpenTypeFile *file) {
|
||||
}
|
||||
|
||||
} // namespace ots
|
||||
|
||||
#undef TABLE_NAME
|
||||
|
@ -50,3 +50,5 @@ void ots_fpgm_free(OpenTypeFile *file) {
|
||||
}
|
||||
|
||||
} // namespace ots
|
||||
|
||||
#undef TABLE_NAME
|
||||
|
@ -110,3 +110,6 @@ void ots_gasp_free(OpenTypeFile *file) {
|
||||
}
|
||||
|
||||
} // namespace ots
|
||||
|
||||
#undef TABLE_NAME
|
||||
#undef DROP_THIS_TABLE
|
||||
|
@ -384,3 +384,5 @@ void ots_gdef_free(OpenTypeFile *file) {
|
||||
|
||||
} // namespace ots
|
||||
|
||||
#undef TABLE_NAME
|
||||
#undef DROP_THIS_TABLE
|
||||
|
@ -307,3 +307,5 @@ void ots_glyf_free(OpenTypeFile *file) {
|
||||
}
|
||||
|
||||
} // namespace ots
|
||||
|
||||
#undef TABLE_NAME
|
||||
|
@ -757,36 +757,48 @@ bool ots_gpos_parse(OpenTypeFile *file, const uint8_t *data, size_t length) {
|
||||
DROP_THIS_TABLE("Bad version");
|
||||
return true;
|
||||
}
|
||||
if ((offset_script_list < kGposHeaderSize ||
|
||||
offset_script_list >= length) ||
|
||||
(offset_feature_list < kGposHeaderSize ||
|
||||
offset_feature_list >= length) ||
|
||||
(offset_lookup_list < kGposHeaderSize ||
|
||||
offset_lookup_list >= length)) {
|
||||
DROP_THIS_TABLE("Bad offset in table header");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!ParseLookupListTable(file, data + offset_lookup_list,
|
||||
length - offset_lookup_list,
|
||||
&kGposLookupSubtableParser,
|
||||
&gpos->num_lookups)) {
|
||||
DROP_THIS_TABLE("Failed to parse lookup list table");
|
||||
return true;
|
||||
if (offset_lookup_list) {
|
||||
if (offset_lookup_list < kGposHeaderSize || offset_lookup_list >= length) {
|
||||
DROP_THIS_TABLE("Bad lookup list offset in table header");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!ParseLookupListTable(file, data + offset_lookup_list,
|
||||
length - offset_lookup_list,
|
||||
&kGposLookupSubtableParser,
|
||||
&gpos->num_lookups)) {
|
||||
DROP_THIS_TABLE("Failed to parse lookup list table");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t num_features = 0;
|
||||
if (!ParseFeatureListTable(file, data + offset_feature_list,
|
||||
length - offset_feature_list, gpos->num_lookups,
|
||||
&num_features)) {
|
||||
DROP_THIS_TABLE("Failed to parse feature list table");
|
||||
return true;
|
||||
if (offset_feature_list) {
|
||||
if (offset_feature_list < kGposHeaderSize || offset_feature_list >= length) {
|
||||
DROP_THIS_TABLE("Bad feature list offset in table header");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!ParseFeatureListTable(file, data + offset_feature_list,
|
||||
length - offset_feature_list, gpos->num_lookups,
|
||||
&num_features)) {
|
||||
DROP_THIS_TABLE("Failed to parse feature list table");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!ParseScriptListTable(file, data + offset_script_list,
|
||||
length - offset_script_list, num_features)) {
|
||||
DROP_THIS_TABLE("Failed to parse script list table");
|
||||
return true;
|
||||
if (offset_script_list) {
|
||||
if (offset_script_list < kGposHeaderSize || offset_script_list >= length) {
|
||||
DROP_THIS_TABLE("Bad script list offset in table header");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!ParseScriptListTable(file, data + offset_script_list,
|
||||
length - offset_script_list, num_features)) {
|
||||
DROP_THIS_TABLE("Failed to parse script list table");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
gpos->data = data;
|
||||
@ -812,3 +824,5 @@ void ots_gpos_free(OpenTypeFile *file) {
|
||||
|
||||
} // namespace ots
|
||||
|
||||
#undef TABLE_NAME
|
||||
#undef DROP_THIS_TABLE
|
||||
|
@ -614,36 +614,48 @@ bool ots_gsub_parse(OpenTypeFile *file, const uint8_t *data, size_t length) {
|
||||
DROP_THIS_TABLE("Bad version");
|
||||
return true;
|
||||
}
|
||||
if ((offset_script_list < kGsubHeaderSize ||
|
||||
offset_script_list >= length) ||
|
||||
(offset_feature_list < kGsubHeaderSize ||
|
||||
offset_feature_list >= length) ||
|
||||
(offset_lookup_list < kGsubHeaderSize ||
|
||||
offset_lookup_list >= length)) {
|
||||
DROP_THIS_TABLE("Bad offset in table header");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!ParseLookupListTable(file, data + offset_lookup_list,
|
||||
length - offset_lookup_list,
|
||||
&kGsubLookupSubtableParser,
|
||||
&gsub->num_lookups)) {
|
||||
DROP_THIS_TABLE("Failed to parse lookup list table");
|
||||
return true;
|
||||
if (offset_lookup_list) {
|
||||
if (offset_lookup_list < kGsubHeaderSize || offset_lookup_list >= length) {
|
||||
DROP_THIS_TABLE("Bad lookup list offset in table header");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!ParseLookupListTable(file, data + offset_lookup_list,
|
||||
length - offset_lookup_list,
|
||||
&kGsubLookupSubtableParser,
|
||||
&gsub->num_lookups)) {
|
||||
DROP_THIS_TABLE("Failed to parse lookup list table");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t num_features = 0;
|
||||
if (!ParseFeatureListTable(file, data + offset_feature_list,
|
||||
length - offset_feature_list, gsub->num_lookups,
|
||||
&num_features)) {
|
||||
DROP_THIS_TABLE("Failed to parse feature list table");
|
||||
return true;
|
||||
if (offset_feature_list) {
|
||||
if (offset_feature_list < kGsubHeaderSize || offset_feature_list >= length) {
|
||||
DROP_THIS_TABLE("Bad feature list offset in table header");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!ParseFeatureListTable(file, data + offset_feature_list,
|
||||
length - offset_feature_list, gsub->num_lookups,
|
||||
&num_features)) {
|
||||
DROP_THIS_TABLE("Failed to parse feature list table");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!ParseScriptListTable(file, data + offset_script_list,
|
||||
length - offset_script_list, num_features)) {
|
||||
DROP_THIS_TABLE("Failed to parse script list table");
|
||||
return true;
|
||||
if (offset_script_list) {
|
||||
if (offset_script_list < kGsubHeaderSize || offset_script_list >= length) {
|
||||
DROP_THIS_TABLE("Bad script list offset in table header");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!ParseScriptListTable(file, data + offset_script_list,
|
||||
length - offset_script_list, num_features)) {
|
||||
DROP_THIS_TABLE("Failed to parse script list table");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
gsub->data = data;
|
||||
@ -669,3 +681,5 @@ void ots_gsub_free(OpenTypeFile *file) {
|
||||
|
||||
} // namespace ots
|
||||
|
||||
#undef TABLE_NAME
|
||||
#undef DROP_THIS_TABLE
|
||||
|
@ -138,3 +138,6 @@ void ots_hdmx_free(OpenTypeFile *file) {
|
||||
}
|
||||
|
||||
} // namespace ots
|
||||
|
||||
#undef TABLE_NAME
|
||||
#undef DROP_THIS_TABLE
|
||||
|
@ -149,3 +149,5 @@ void ots_head_free(OpenTypeFile *file) {
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
#undef TABLE_NAME
|
||||
|
@ -49,3 +49,5 @@ void ots_hhea_free(OpenTypeFile *file) {
|
||||
}
|
||||
|
||||
} // namespace ots
|
||||
|
||||
#undef TABLE_NAME
|
||||
|
@ -47,3 +47,5 @@ void ots_hmtx_free(OpenTypeFile *file) {
|
||||
}
|
||||
|
||||
} // namespace ots
|
||||
|
||||
#undef TABLE_NAME
|
||||
|
@ -200,3 +200,6 @@ void ots_kern_free(OpenTypeFile *file) {
|
||||
}
|
||||
|
||||
} // namespace ots
|
||||
|
||||
#undef TABLE_NAME
|
||||
#undef DROP_THIS_TABLE
|
||||
|
@ -1510,3 +1510,4 @@ bool ParseExtensionSubtable(const OpenTypeFile *file,
|
||||
|
||||
} // namespace ots
|
||||
|
||||
#undef TABLE_NAME
|
||||
|
@ -98,3 +98,5 @@ void ots_loca_free(OpenTypeFile *file) {
|
||||
}
|
||||
|
||||
} // namespace ots
|
||||
|
||||
#undef TABLE_NAME
|
||||
|
@ -86,3 +86,6 @@ void ots_ltsh_free(OpenTypeFile *file) {
|
||||
}
|
||||
|
||||
} // namespace ots
|
||||
|
||||
#undef TABLE_NAME
|
||||
#undef DROP_THIS_TABLE
|
||||
|
@ -606,3 +606,5 @@ void ots_math_free(OpenTypeFile *file) {
|
||||
|
||||
} // namespace ots
|
||||
|
||||
#undef TABLE_NAME
|
||||
#undef DROP_THIS_TABLE
|
||||
|
@ -128,3 +128,5 @@ void ots_maxp_free(OpenTypeFile *file) {
|
||||
}
|
||||
|
||||
} // namespace ots
|
||||
|
||||
#undef TABLE_NAME
|
||||
|
@ -184,3 +184,4 @@ bool SerialiseMetricsTable(const ots::OpenTypeFile *file,
|
||||
|
||||
} // namespace ots
|
||||
|
||||
#undef TABLE_NAME
|
||||
|
@ -60,3 +60,6 @@ DEFINES['NOMINMAX'] = True
|
||||
if CONFIG['OS_TARGET'] == 'WINNT':
|
||||
DEFINES['OTS_DLL'] = True
|
||||
DEFINES['OTS_DLL_EXPORTS'] = True
|
||||
|
||||
# Disable WOFF2 support.
|
||||
DEFINES['OTS_DISABLE_WOFF2'] = True;
|
||||
|
@ -332,3 +332,5 @@ void ots_name_free(OpenTypeFile* file) {
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
#undef TABLE_NAME
|
||||
|
@ -290,3 +290,5 @@ void ots_os2_free(OpenTypeFile *file) {
|
||||
}
|
||||
|
||||
} // namespace ots
|
||||
|
||||
#undef TABLE_NAME
|
||||
|
@ -14,7 +14,7 @@
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
#ifdef MOZ_OTS_WOFF2
|
||||
#ifndef OTS_DISABLE_WOFF2
|
||||
#include "woff2.h"
|
||||
#endif
|
||||
|
||||
@ -24,15 +24,7 @@
|
||||
namespace {
|
||||
|
||||
bool g_debug_output = true;
|
||||
#ifdef MOZ_OTS_WOFF2
|
||||
bool g_enable_woff2 = false;
|
||||
#endif
|
||||
|
||||
ots::MessageFunc g_message_func = NULL;
|
||||
void *g_message_user_data = NULL;
|
||||
|
||||
ots::TableActionFunc g_table_action_func = NULL;
|
||||
void *g_table_action_user_data = NULL;
|
||||
|
||||
// Generate a message with or without a table tag, when 'header' is the OpenTypeFile pointer
|
||||
#define OTS_FAILURE_MSG_TAG(msg_,tag_) OTS_FAILURE_MSG_TAG_(header, msg_, tag_)
|
||||
@ -404,7 +396,7 @@ bool ProcessWOFF(ots::OpenTypeFile *header,
|
||||
return ProcessGeneric(header, woff_tag, output, data, length, tables, file);
|
||||
}
|
||||
|
||||
#ifdef MOZ_OTS_WOFF2
|
||||
#ifndef OTS_DISABLE_WOFF2
|
||||
bool ProcessWOFF2(ots::OpenTypeFile *header,
|
||||
ots::OTSStream *output, const uint8_t *data, size_t length) {
|
||||
size_t decompressed_size = ots::ComputeWOFF2FinalSize(data, length);
|
||||
@ -425,11 +417,11 @@ bool ProcessWOFF2(ots::OpenTypeFile *header,
|
||||
}
|
||||
#endif
|
||||
|
||||
ots::TableAction GetTableAction(uint32_t tag) {
|
||||
ots::TableAction GetTableAction(ots::OpenTypeFile *header, uint32_t tag) {
|
||||
ots::TableAction action = ots::TABLE_ACTION_DEFAULT;
|
||||
|
||||
if (g_table_action_func != NULL) {
|
||||
action = g_table_action_func(htonl(tag), g_table_action_user_data);
|
||||
if (header->table_action_func != NULL) {
|
||||
action = header->table_action_func(htonl(tag), header->table_action_user_data);
|
||||
}
|
||||
|
||||
if (action == ots::TABLE_ACTION_DEFAULT) {
|
||||
@ -578,10 +570,10 @@ bool ProcessGeneric(ots::OpenTypeFile *header, uint32_t signature,
|
||||
for (unsigned i = 0; ; ++i) {
|
||||
if (table_parsers[i].parse == NULL) break;
|
||||
|
||||
const std::map<uint32_t, OpenTypeTable>::const_iterator it
|
||||
= table_map.find(Tag(table_parsers[i].tag));
|
||||
uint32_t tag = Tag(table_parsers[i].tag);
|
||||
const std::map<uint32_t, OpenTypeTable>::const_iterator it = table_map.find(tag);
|
||||
|
||||
ots::TableAction action = GetTableAction(Tag(table_parsers[i].tag));
|
||||
ots::TableAction action = GetTableAction(header, tag);
|
||||
if (it == table_map.end()) {
|
||||
if (table_parsers[i].required && action == ots::TABLE_ACTION_SANITIZE) {
|
||||
return OTS_FAILURE_MSG_TAG("missing required table", table_parsers[i].tag);
|
||||
@ -634,7 +626,7 @@ bool ProcessGeneric(ots::OpenTypeFile *header, uint32_t signature,
|
||||
|
||||
for (std::map<uint32_t, OpenTypeTable>::const_iterator it = table_map.begin();
|
||||
it != table_map.end(); ++it) {
|
||||
ots::TableAction action = GetTableAction(it->first);
|
||||
ots::TableAction action = GetTableAction(header, it->first);
|
||||
if (action == ots::TABLE_ACTION_PASSTHRU) {
|
||||
num_output_tables++;
|
||||
}
|
||||
@ -706,7 +698,7 @@ bool ProcessGeneric(ots::OpenTypeFile *header, uint32_t signature,
|
||||
|
||||
for (std::map<uint32_t, OpenTypeTable>::const_iterator it = table_map.begin();
|
||||
it != table_map.end(); ++it) {
|
||||
ots::TableAction action = GetTableAction(it->first);
|
||||
ots::TableAction action = GetTableAction(header, it->first);
|
||||
if (action == ots::TABLE_ACTION_PASSTHRU) {
|
||||
OutputTable out;
|
||||
out.tag = it->second.tag;
|
||||
@ -806,27 +798,19 @@ void DisableDebugOutput() {
|
||||
g_debug_output = false;
|
||||
}
|
||||
|
||||
#ifdef MOZ_OTS_WOFF2
|
||||
void EnableWOFF2() {
|
||||
g_enable_woff2 = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
void SetMessageCallback(MessageFunc func, void *user_data) {
|
||||
g_message_func = func;
|
||||
g_message_user_data = user_data;
|
||||
}
|
||||
|
||||
void SetTableActionCallback(TableActionFunc func, void *user_data) {
|
||||
g_table_action_func = func;
|
||||
g_table_action_user_data = user_data;
|
||||
}
|
||||
|
||||
bool Process(OTSStream *output, const uint8_t *data, size_t length) {
|
||||
bool OTSContext::Process(OTSStream *output,
|
||||
const uint8_t *data,
|
||||
size_t length) {
|
||||
OpenTypeFile header;
|
||||
|
||||
header.message_func = g_message_func;
|
||||
header.user_data = g_message_user_data;
|
||||
header.message_func = message_func;
|
||||
header.message_user_data = message_user_data;
|
||||
header.table_action_func = table_action_func;
|
||||
header.table_action_user_data = table_action_user_data;
|
||||
|
||||
if (length < 4) {
|
||||
return OTS_FAILURE_MSG_(&header, "file less than 4 bytes");
|
||||
@ -835,7 +819,7 @@ bool Process(OTSStream *output, const uint8_t *data, size_t length) {
|
||||
bool result;
|
||||
if (data[0] == 'w' && data[1] == 'O' && data[2] == 'F' && data[3] == 'F') {
|
||||
result = ProcessWOFF(&header, output, data, length);
|
||||
#ifdef MOZ_OTS_WOFF2
|
||||
#ifndef OTS_DISABLE_WOFF2
|
||||
} else if (g_enable_woff2 &&
|
||||
data[0] == 'w' && data[1] == 'O' && data[2] == 'F' &&
|
||||
data[3] == '2') {
|
||||
|
@ -53,13 +53,13 @@ void Warning(const char *f, int l, const char *format, ...)
|
||||
// Generate a simple message
|
||||
#define OTS_FAILURE_MSG_(otf_,...) \
|
||||
((otf_)->message_func && \
|
||||
(*(otf_)->message_func)((otf_)->user_data, __VA_ARGS__) && \
|
||||
(*(otf_)->message_func)((otf_)->message_user_data, __VA_ARGS__) && \
|
||||
false)
|
||||
|
||||
// Generate a message with an associated table tag
|
||||
#define OTS_FAILURE_MSG_TAG_(otf_,msg_,tag_) \
|
||||
((otf_)->message_func && \
|
||||
(*(otf_)->message_func)((otf_)->user_data, "%4.4s: %s", tag_, msg_) && \
|
||||
(*(otf_)->message_func)((otf_)->message_user_data, "%4.4s: %s", tag_, msg_) && \
|
||||
false)
|
||||
|
||||
// Convenience macro for use in files that only handle a single table tag,
|
||||
@ -250,8 +250,11 @@ struct OpenTypeFile {
|
||||
uint16_t entry_selector;
|
||||
uint16_t range_shift;
|
||||
|
||||
MessageFunc message_func;
|
||||
void *user_data;
|
||||
MessageFunc message_func;
|
||||
void *message_user_data;
|
||||
|
||||
TableActionFunc table_action_func;
|
||||
void *table_action_user_data;
|
||||
|
||||
#define F(name, capname) OpenType##capname *name;
|
||||
FOR_EACH_TABLE_TYPE
|
||||
|
@ -180,3 +180,5 @@ void ots_post_free(OpenTypeFile *file) {
|
||||
}
|
||||
|
||||
} // namespace ots
|
||||
|
||||
#undef TABLE_NAME
|
||||
|
@ -50,3 +50,5 @@ void ots_prep_free(OpenTypeFile *file) {
|
||||
}
|
||||
|
||||
} // namespace ots
|
||||
|
||||
#undef TABLE_NAME
|
||||
|
@ -181,3 +181,6 @@ void ots_vdmx_free(OpenTypeFile *file) {
|
||||
}
|
||||
|
||||
} // namespace ots
|
||||
|
||||
#undef TABLE_NAME
|
||||
#undef DROP_THIS_TABLE
|
||||
|
@ -56,3 +56,4 @@ void ots_vhea_free(OpenTypeFile *file) {
|
||||
|
||||
} // namespace ots
|
||||
|
||||
#undef TABLE_NAME
|
||||
|
@ -52,3 +52,4 @@ void ots_vmtx_free(OpenTypeFile *file) {
|
||||
|
||||
} // namespace ots
|
||||
|
||||
#undef TABLE_NAME
|
||||
|
@ -101,3 +101,6 @@ void ots_vorg_free(OpenTypeFile *file) {
|
||||
}
|
||||
|
||||
} // namespace ots
|
||||
|
||||
#undef TABLE_NAME
|
||||
#undef DROP_THIS_TABLE
|
||||
|
1022
gfx/ots/src/woff2.cc
Normal file
1022
gfx/ots/src/woff2.cc
Normal file
File diff suppressed because it is too large
Load Diff
20
gfx/ots/src/woff2.h
Normal file
20
gfx/ots/src/woff2.h
Normal file
@ -0,0 +1,20 @@
|
||||
// Copyright (c) 2013 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef OTS_WOFF2_H_
|
||||
#define OTS_WOFF2_H_
|
||||
|
||||
namespace ots {
|
||||
|
||||
// Compute the size of the final uncompressed font, or 0 on error.
|
||||
size_t ComputeWOFF2FinalSize(const uint8_t *data, size_t length);
|
||||
|
||||
// Decompresses the font into the target buffer. The result_length should
|
||||
// be the same as determined by ComputeFinalSize(). Returns true on successful
|
||||
// decompression.
|
||||
bool ConvertWOFF2ToTTF(uint8_t *result, size_t result_length,
|
||||
const uint8_t *data, size_t length);
|
||||
}
|
||||
|
||||
#endif // OTS_WOFF2_H_
|
@ -388,10 +388,11 @@ gfxUserFontSet::SanitizeOpenTypeData(gfxMixedFontFamily *aFamily,
|
||||
userData.mFamily = aFamily;
|
||||
userData.mProxy = aProxy;
|
||||
|
||||
ots::SetTableActionCallback(&OTSTableAction, nullptr);
|
||||
ots::SetMessageCallback(&gfxUserFontSet::OTSMessage, &userData);
|
||||
ots::OTSContext otsContext;
|
||||
otsContext.SetTableActionCallback(&OTSTableAction, nullptr);
|
||||
otsContext.SetMessageCallback(&gfxUserFontSet::OTSMessage, &userData);
|
||||
|
||||
if (ots::Process(&output, aData, aLength)) {
|
||||
if (otsContext.Process(&output, aData, aLength)) {
|
||||
aSaneLength = output.Tell();
|
||||
return static_cast<uint8_t*>(output.forget());
|
||||
} else {
|
||||
|
@ -45,7 +45,7 @@ namespace JS {
|
||||
D(TOO_MUCH_MALLOC) \
|
||||
D(ALLOC_TRIGGER) \
|
||||
D(DEBUG_GC) \
|
||||
D(COMPARTMENT_REVIVED) \
|
||||
D(TRANSPLANT) \
|
||||
D(RESET) \
|
||||
D(OUT_OF_NURSERY) \
|
||||
D(EVICT_NURSERY) \
|
||||
|
@ -32,7 +32,6 @@ class AutoValueVector;
|
||||
|
||||
class AutoIdArray;
|
||||
|
||||
class JS_PUBLIC_API(AutoGCRooter);
|
||||
template <typename T> class AutoVectorRooter;
|
||||
template<typename K, typename V> class AutoHashMapRooter;
|
||||
template<typename T> class AutoHashSetRooter;
|
||||
@ -42,8 +41,6 @@ class MOZ_STACK_CLASS SourceBufferHolder;
|
||||
|
||||
class HandleValueArray;
|
||||
|
||||
class AutoCheckCannotGC;
|
||||
|
||||
}
|
||||
|
||||
// Do the importing.
|
||||
@ -80,7 +77,6 @@ using JS::AutoValueVector;
|
||||
|
||||
using JS::AutoIdArray;
|
||||
|
||||
using JS::AutoGCRooter;
|
||||
using JS::AutoHashMapRooter;
|
||||
using JS::AutoHashSetRooter;
|
||||
using JS::AutoVectorRooter;
|
||||
@ -135,8 +131,6 @@ using JS::HandleValueArray;
|
||||
|
||||
using JS::Zone;
|
||||
|
||||
using JS::AutoCheckCannotGC;
|
||||
|
||||
} /* namespace js */
|
||||
|
||||
#endif /* NamespaceImports_h */
|
||||
|
@ -42,12 +42,12 @@ class HashableValue {
|
||||
Value get() const { return value.get(); }
|
||||
};
|
||||
|
||||
class AutoHashableValueRooter : private AutoGCRooter
|
||||
class AutoHashableValueRooter : private JS::AutoGCRooter
|
||||
{
|
||||
public:
|
||||
explicit AutoHashableValueRooter(JSContext *cx
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
|
||||
: AutoGCRooter(cx, HASHABLEVALUE)
|
||||
: JS::AutoGCRooter(cx, HASHABLEVALUE)
|
||||
{
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
|
||||
}
|
||||
@ -62,7 +62,7 @@ class AutoHashableValueRooter : private AutoGCRooter
|
||||
|
||||
Value get() const { return value.get(); }
|
||||
|
||||
friend void AutoGCRooter::trace(JSTracer *trc);
|
||||
friend void JS::AutoGCRooter::trace(JSTracer *trc);
|
||||
void trace(JSTracer *trc);
|
||||
|
||||
private:
|
||||
|
@ -68,7 +68,7 @@ IsKeyword(JSLinearString *str);
|
||||
|
||||
/* GC marking. Defined in Parser.cpp. */
|
||||
void
|
||||
MarkParser(JSTracer *trc, AutoGCRooter *parser);
|
||||
MarkParser(JSTracer *trc, JS::AutoGCRooter *parser);
|
||||
|
||||
} /* namespace frontend */
|
||||
} /* namespace js */
|
||||
|
@ -42,8 +42,11 @@
|
||||
|
||||
using namespace js;
|
||||
using namespace js::gc;
|
||||
|
||||
using mozilla::Maybe;
|
||||
|
||||
using JS::AutoGCRooter;
|
||||
|
||||
namespace js {
|
||||
namespace frontend {
|
||||
|
||||
|
@ -313,7 +313,7 @@ enum VarContext { HoistVars, DontHoistVars };
|
||||
enum FunctionType { Getter, Setter, Normal };
|
||||
|
||||
template <typename ParseHandler>
|
||||
class Parser : private AutoGCRooter, public StrictModeGetter
|
||||
class Parser : private JS::AutoGCRooter, public StrictModeGetter
|
||||
{
|
||||
public:
|
||||
ExclusiveContext *const context;
|
||||
@ -392,7 +392,7 @@ class Parser : private AutoGCRooter, public StrictModeGetter
|
||||
traceListHead = m.traceListHead;
|
||||
}
|
||||
|
||||
friend void js::frontend::MarkParser(JSTracer *trc, AutoGCRooter *parser);
|
||||
friend void js::frontend::MarkParser(JSTracer *trc, JS::AutoGCRooter *parser);
|
||||
|
||||
const char *getFilename() const { return tokenStream.getFilename(); }
|
||||
JSVersion versionNumber() const { return tokenStream.versionNumber(); }
|
||||
|
@ -188,6 +188,9 @@ CheckMarkedThing(JSTracer *trc, T **thingp)
|
||||
|
||||
DebugOnly<JSRuntime *> rt = trc->runtime();
|
||||
|
||||
JS_ASSERT_IF(IS_GC_MARKING_TRACER(trc) && rt->gc.manipulatingDeadZones,
|
||||
!thing->zone()->scheduledForDestruction);
|
||||
|
||||
JS_ASSERT(CurrentThreadCanAccessRuntime(rt));
|
||||
|
||||
JS_ASSERT_IF(thing->zone()->requireGCTracer(),
|
||||
@ -218,33 +221,6 @@ CheckMarkedThing(JSTracer *trc, T **thingp)
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* We only set the maybeAlive flag for objects and scripts. It's assumed that,
|
||||
* if a compartment is alive, then it will have at least some live object or
|
||||
* script it in. Even if we get this wrong, the worst that will happen is that
|
||||
* scheduledForDestruction will be set on the compartment, which will cause some
|
||||
* extra GC activity to try to free the compartment.
|
||||
*/
|
||||
template<typename T>
|
||||
static inline void
|
||||
SetMaybeAliveFlag(T *thing)
|
||||
{
|
||||
}
|
||||
|
||||
template<>
|
||||
void
|
||||
SetMaybeAliveFlag(JSObject *thing)
|
||||
{
|
||||
thing->compartment()->maybeAlive = true;
|
||||
}
|
||||
|
||||
template<>
|
||||
void
|
||||
SetMaybeAliveFlag(JSScript *thing)
|
||||
{
|
||||
thing->compartment()->maybeAlive = true;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static void
|
||||
MarkInternal(JSTracer *trc, T **thingp)
|
||||
@ -278,7 +254,7 @@ MarkInternal(JSTracer *trc, T **thingp)
|
||||
return;
|
||||
|
||||
PushMarkStack(AsGCMarker(trc), thing);
|
||||
SetMaybeAliveFlag(thing);
|
||||
thing->zone()->maybeAlive = true;
|
||||
} else {
|
||||
trc->callback(trc, (void **)thingp, MapTypeToTraceKind<T>::kind);
|
||||
trc->unsetTracingLocation();
|
||||
|
@ -244,7 +244,7 @@ js::Nursery::reallocateSlots(JSContext *cx, JSObject *obj, HeapSlot *oldSlots,
|
||||
|
||||
if (!isInside(oldSlots)) {
|
||||
HeapSlot *newSlots = static_cast<HeapSlot *>(cx->realloc_(oldSlots, oldSize, newSize));
|
||||
if (oldSlots != newSlots) {
|
||||
if (newSlots && oldSlots != newSlots) {
|
||||
hugeSlots.remove(oldSlots);
|
||||
/* If this put fails, we will only leak the slots. */
|
||||
(void)hugeSlots.put(newSlots);
|
||||
@ -257,7 +257,8 @@ js::Nursery::reallocateSlots(JSContext *cx, JSObject *obj, HeapSlot *oldSlots,
|
||||
return oldSlots;
|
||||
|
||||
HeapSlot *newSlots = allocateSlots(cx, obj, newCount);
|
||||
PodCopy(newSlots, oldSlots, oldCount);
|
||||
if (newSlots)
|
||||
PodCopy(newSlots, oldSlots, oldCount);
|
||||
return newSlots;
|
||||
}
|
||||
|
||||
@ -284,7 +285,8 @@ js::Nursery::allocateHugeSlots(JSContext *cx, size_t nslots)
|
||||
{
|
||||
HeapSlot *slots = cx->pod_malloc<HeapSlot>(nslots);
|
||||
/* If this put fails, we will only leak the slots. */
|
||||
(void)hugeSlots.put(slots);
|
||||
if (slots)
|
||||
(void)hugeSlots.put(slots);
|
||||
return slots;
|
||||
}
|
||||
|
||||
|
@ -36,6 +36,8 @@ using namespace js::gc;
|
||||
|
||||
using mozilla::ArrayEnd;
|
||||
|
||||
using JS::AutoGCRooter;
|
||||
|
||||
typedef RootedValueMap::Range RootRange;
|
||||
typedef RootedValueMap::Entry RootEntry;
|
||||
typedef RootedValueMap::Enum RootEnum;
|
||||
@ -582,7 +584,7 @@ AutoGCRooter::trace(JSTracer *trc)
|
||||
AutoGCRooter::traceAll(JSTracer *trc)
|
||||
{
|
||||
for (ContextIter cx(trc->runtime()); !cx.done(); cx.next()) {
|
||||
for (js::AutoGCRooter *gcr = cx->autoGCRooters; gcr; gcr = gcr->down)
|
||||
for (AutoGCRooter *gcr = cx->autoGCRooters; gcr; gcr = gcr->down)
|
||||
gcr->trace(trc);
|
||||
}
|
||||
}
|
||||
@ -591,7 +593,7 @@ AutoGCRooter::traceAll(JSTracer *trc)
|
||||
AutoGCRooter::traceAllWrappers(JSTracer *trc)
|
||||
{
|
||||
for (ContextIter cx(trc->runtime()); !cx.done(); cx.next()) {
|
||||
for (js::AutoGCRooter *gcr = cx->autoGCRooters; gcr; gcr = gcr->down) {
|
||||
for (AutoGCRooter *gcr = cx->autoGCRooters; gcr; gcr = gcr->down) {
|
||||
if (gcr->tag_ == WRAPVECTOR || gcr->tag_ == WRAPPER)
|
||||
gcr->trace(trc);
|
||||
}
|
||||
|
@ -638,20 +638,7 @@ GCMarker::appendGrayRoot(void *thing, JSGCTraceKind kind)
|
||||
|
||||
Zone *zone = static_cast<Cell *>(thing)->tenuredZone();
|
||||
if (zone->isCollecting()) {
|
||||
// See the comment on SetMaybeAliveFlag to see why we only do this for
|
||||
// objects and scripts. We rely on gray root buffering for this to work,
|
||||
// but we only need to worry about uncollected dead compartments during
|
||||
// incremental GCs (when we do gray root buffering).
|
||||
switch (kind) {
|
||||
case JSTRACE_OBJECT:
|
||||
static_cast<JSObject *>(thing)->compartment()->maybeAlive = true;
|
||||
break;
|
||||
case JSTRACE_SCRIPT:
|
||||
static_cast<JSScript *>(thing)->compartment()->maybeAlive = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
zone->maybeAlive = true;
|
||||
if (!zone->gcGrayRoots.append(root)) {
|
||||
resetBufferedGrayRoots();
|
||||
grayBufferState = GRAY_BUFFER_FAILED;
|
||||
|
@ -35,6 +35,8 @@ JS::Zone::Zone(JSRuntime *rt)
|
||||
data(nullptr),
|
||||
isSystem(false),
|
||||
usedByExclusiveThread(false),
|
||||
scheduledForDestruction(false),
|
||||
maybeAlive(true),
|
||||
active(false),
|
||||
jitZone_(nullptr),
|
||||
gcState_(NoGC),
|
||||
|
@ -258,6 +258,11 @@ struct Zone : public JS::shadow::Zone,
|
||||
|
||||
bool usedByExclusiveThread;
|
||||
|
||||
// These flags help us to discover if a compartment that shouldn't be alive
|
||||
// manages to outlive a GC.
|
||||
bool scheduledForDestruction;
|
||||
bool maybeAlive;
|
||||
|
||||
// True when there are active frames.
|
||||
bool active;
|
||||
|
||||
|
@ -1,20 +0,0 @@
|
||||
assertEq(Number.toInteger(4), 4);
|
||||
assertEq(Number.toInteger(4.), 4);
|
||||
assertEq(Number.toInteger(4.3), 4);
|
||||
assertEq(Number.toInteger(-4), -4);
|
||||
assertEq(Number.toInteger(-4.), -4);
|
||||
assertEq(Number.toInteger(-4.3), -4);
|
||||
assertEq(Number.toInteger(0.), 0.);
|
||||
assertEq(Number.toInteger(-0.), -0.);
|
||||
assertEq(Number.toInteger(Infinity), Infinity);
|
||||
assertEq(Number.toInteger(-Infinity), -Infinity);
|
||||
assertEq(Number.toInteger(NaN), 0);
|
||||
assertEq(Number.toInteger(null), 0);
|
||||
assertEq(Number.toInteger(undefined), 0);
|
||||
assertEq(Number.toInteger(true), 1);
|
||||
assertEq(Number.toInteger(false), 0);
|
||||
assertEq(Number.toInteger({valueOf : function () { return 4; }}), 4);
|
||||
assertEq(Number.toInteger({valueOf : function () { return 4.3; }}), 4);
|
||||
assertEq(Number.toInteger({valueOf : function () { return "4"; }}), 4);
|
||||
assertEq(Number.toInteger({valueOf : function () { return {};}}), 0);
|
||||
assertEq(Number.toInteger(), 0);
|
@ -74,17 +74,17 @@ class TempAllocator
|
||||
};
|
||||
|
||||
// Stack allocated rooter for all roots associated with a TempAllocator
|
||||
class AutoTempAllocatorRooter : private AutoGCRooter
|
||||
class AutoTempAllocatorRooter : private JS::AutoGCRooter
|
||||
{
|
||||
public:
|
||||
explicit AutoTempAllocatorRooter(JSContext *cx, TempAllocator *temp
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
|
||||
: AutoGCRooter(cx, IONALLOC), temp(temp)
|
||||
: JS::AutoGCRooter(cx, IONALLOC), temp(temp)
|
||||
{
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
|
||||
}
|
||||
|
||||
friend void AutoGCRooter::trace(JSTracer *trc);
|
||||
friend void JS::AutoGCRooter::trace(JSTracer *trc);
|
||||
void trace(JSTracer *trc);
|
||||
|
||||
private:
|
||||
|
@ -548,6 +548,13 @@ MacroAssembler::allocateObject(Register result, Register slots, gc::AllocKind al
|
||||
{
|
||||
JS_ASSERT(allocKind >= gc::FINALIZE_OBJECT0 && allocKind <= gc::FINALIZE_OBJECT_LAST);
|
||||
|
||||
#ifdef JS_CODEGEN_ARM
|
||||
// Bug 1011474: Always take the ool path when allocating malloc slots on
|
||||
// ARM to work around a top-crasher while we investigate.
|
||||
if (nDynamicSlots)
|
||||
return jump(fail);
|
||||
#endif
|
||||
|
||||
checkAllocatorState(fail);
|
||||
|
||||
if (shouldNurseryAllocate(allocKind, initialHeap))
|
||||
|
@ -41,13 +41,13 @@ class MacroAssembler : public MacroAssemblerSpecific
|
||||
}
|
||||
|
||||
public:
|
||||
class AutoRooter : public AutoGCRooter
|
||||
class AutoRooter : public JS::AutoGCRooter
|
||||
{
|
||||
MacroAssembler *masm_;
|
||||
|
||||
public:
|
||||
AutoRooter(JSContext *cx, MacroAssembler *masm)
|
||||
: AutoGCRooter(cx, IONMASM),
|
||||
: JS::AutoGCRooter(cx, IONMASM),
|
||||
masm_(masm)
|
||||
{ }
|
||||
|
||||
|
@ -17,6 +17,8 @@
|
||||
using namespace js;
|
||||
using namespace jit;
|
||||
|
||||
using JS::AutoCheckCannotGC;
|
||||
|
||||
using parallel::Spew;
|
||||
using parallel::SpewOps;
|
||||
using parallel::SpewBailouts;
|
||||
|
@ -98,6 +98,8 @@ using mozilla::Maybe;
|
||||
using mozilla::PodCopy;
|
||||
using mozilla::PodZero;
|
||||
|
||||
using JS::AutoGCRooter;
|
||||
|
||||
using js::frontend::Parser;
|
||||
|
||||
#ifdef HAVE_VA_LIST_AS_ARRAY
|
||||
@ -1088,6 +1090,7 @@ JS_TransplantObject(JSContext *cx, HandleObject origobj, HandleObject target)
|
||||
JS_ASSERT(!origobj->is<CrossCompartmentWrapperObject>());
|
||||
JS_ASSERT(!target->is<CrossCompartmentWrapperObject>());
|
||||
|
||||
AutoMaybeTouchDeadZones agc(cx);
|
||||
AutoDisableProxyCheck adpc(cx->runtime());
|
||||
|
||||
JSCompartment *destination = target->compartment();
|
||||
|
@ -74,66 +74,6 @@ inline void AssertArgumentsAreSane(JSContext *cx, JS::HandleValue v) {
|
||||
}
|
||||
#endif /* JS_DEBUG */
|
||||
|
||||
class JS_PUBLIC_API(AutoGCRooter) {
|
||||
public:
|
||||
AutoGCRooter(JSContext *cx, ptrdiff_t tag);
|
||||
AutoGCRooter(js::ContextFriendFields *cx, ptrdiff_t tag);
|
||||
|
||||
~AutoGCRooter() {
|
||||
JS_ASSERT(this == *stackTop);
|
||||
*stackTop = down;
|
||||
}
|
||||
|
||||
/* Implemented in gc/RootMarking.cpp. */
|
||||
inline void trace(JSTracer *trc);
|
||||
static void traceAll(JSTracer *trc);
|
||||
static void traceAllWrappers(JSTracer *trc);
|
||||
|
||||
protected:
|
||||
AutoGCRooter * const down;
|
||||
|
||||
/*
|
||||
* Discriminates actual subclass of this being used. If non-negative, the
|
||||
* subclass roots an array of values of the length stored in this field.
|
||||
* If negative, meaning is indicated by the corresponding value in the enum
|
||||
* below. Any other negative value indicates some deeper problem such as
|
||||
* memory corruption.
|
||||
*/
|
||||
ptrdiff_t tag_;
|
||||
|
||||
enum {
|
||||
VALARRAY = -2, /* js::AutoValueArray */
|
||||
PARSER = -3, /* js::frontend::Parser */
|
||||
SHAPEVECTOR = -4, /* js::AutoShapeVector */
|
||||
IDARRAY = -6, /* js::AutoIdArray */
|
||||
DESCVECTOR = -7, /* js::AutoPropDescVector */
|
||||
VALVECTOR = -10, /* js::AutoValueVector */
|
||||
IDVECTOR = -13, /* js::AutoIdVector */
|
||||
OBJVECTOR = -14, /* js::AutoObjectVector */
|
||||
STRINGVECTOR =-15, /* js::AutoStringVector */
|
||||
SCRIPTVECTOR =-16, /* js::AutoScriptVector */
|
||||
NAMEVECTOR = -17, /* js::AutoNameVector */
|
||||
HASHABLEVALUE=-18, /* js::HashableValue */
|
||||
IONMASM = -19, /* js::jit::MacroAssembler */
|
||||
IONALLOC = -20, /* js::jit::AutoTempAllocatorRooter */
|
||||
WRAPVECTOR = -21, /* js::AutoWrapperVector */
|
||||
WRAPPER = -22, /* js::AutoWrapperRooter */
|
||||
OBJOBJHASHMAP=-23, /* js::AutoObjectObjectHashMap */
|
||||
OBJU32HASHMAP=-24, /* js::AutoObjectUnsigned32HashMap */
|
||||
OBJHASHSET = -25, /* js::AutoObjectHashSet */
|
||||
JSONPARSER = -26, /* js::JSONParser */
|
||||
CUSTOM = -27, /* js::CustomAutoRooter */
|
||||
FUNVECTOR = -28 /* js::AutoFunctionVector */
|
||||
};
|
||||
|
||||
private:
|
||||
AutoGCRooter ** const stackTop;
|
||||
|
||||
/* No copy or assignment semantics. */
|
||||
AutoGCRooter(AutoGCRooter &ida) MOZ_DELETE;
|
||||
void operator=(AutoGCRooter &ida) MOZ_DELETE;
|
||||
};
|
||||
|
||||
/* AutoValueArray roots an internal fixed-size array of Values. */
|
||||
template <size_t N>
|
||||
class AutoValueArray : public AutoGCRooter
|
||||
|
@ -49,6 +49,8 @@ using mozilla::DebugOnly;
|
||||
using mozilla::IsNaN;
|
||||
using mozilla::PointerRangeSize;
|
||||
|
||||
using JS::AutoCheckCannotGC;
|
||||
|
||||
bool
|
||||
js::GetLengthProperty(JSContext *cx, HandleObject obj, uint32_t *lengthp)
|
||||
{
|
||||
|
@ -914,12 +914,12 @@ class AutoObjectHashSet : public AutoHashSetRooter<JSObject *>
|
||||
};
|
||||
|
||||
/* AutoArrayRooter roots an external array of Values. */
|
||||
class AutoArrayRooter : private AutoGCRooter
|
||||
class AutoArrayRooter : private JS::AutoGCRooter
|
||||
{
|
||||
public:
|
||||
AutoArrayRooter(JSContext *cx, size_t len, Value *vec
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
|
||||
: AutoGCRooter(cx, len), array(vec)
|
||||
: JS::AutoGCRooter(cx, len), array(vec)
|
||||
{
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
|
||||
JS_ASSERT(tag_ >= 0);
|
||||
@ -961,7 +961,7 @@ class AutoArrayRooter : private AutoGCRooter
|
||||
return HandleValue::fromMarkedLocation(&array[i]);
|
||||
}
|
||||
|
||||
friend void AutoGCRooter::trace(JSTracer *trc);
|
||||
friend void JS::AutoGCRooter::trace(JSTracer *trc);
|
||||
|
||||
private:
|
||||
Value *array;
|
||||
|
@ -65,9 +65,7 @@ JSCompartment::JSCompartment(Zone *zone, const JS::CompartmentOptions &options =
|
||||
debugScriptMap(nullptr),
|
||||
debugScopes(nullptr),
|
||||
enumerators(nullptr),
|
||||
compartmentStats(nullptr),
|
||||
scheduledForDestruction(false),
|
||||
maybeAlive(true)
|
||||
compartmentStats(nullptr)
|
||||
#ifdef JS_ION
|
||||
, jitCompartment_(nullptr)
|
||||
#endif
|
||||
|
@ -448,11 +448,6 @@ struct JSCompartment
|
||||
/* Used by memory reporters and invalid otherwise. */
|
||||
void *compartmentStats;
|
||||
|
||||
// These flags help us to discover if a compartment that shouldn't be alive
|
||||
// manages to outlive a GC.
|
||||
bool scheduledForDestruction;
|
||||
bool maybeAlive;
|
||||
|
||||
#ifdef JS_ION
|
||||
private:
|
||||
js::jit::JitCompartment *jitCompartment_;
|
||||
@ -656,11 +651,11 @@ class AutoWrapperVector : public AutoVectorRooter<WrapperValue>
|
||||
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
|
||||
};
|
||||
|
||||
class AutoWrapperRooter : private AutoGCRooter {
|
||||
class AutoWrapperRooter : private JS::AutoGCRooter {
|
||||
public:
|
||||
AutoWrapperRooter(JSContext *cx, WrapperValue v
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
|
||||
: AutoGCRooter(cx, WRAPPER), value(v)
|
||||
: JS::AutoGCRooter(cx, WRAPPER), value(v)
|
||||
{
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
|
||||
}
|
||||
@ -669,7 +664,7 @@ class AutoWrapperRooter : private AutoGCRooter {
|
||||
return value.get().toObjectOrNull();
|
||||
}
|
||||
|
||||
friend void AutoGCRooter::trace(JSTracer *trc);
|
||||
friend void JS::AutoGCRooter::trace(JSTracer *trc);
|
||||
|
||||
private:
|
||||
WrapperValue value;
|
||||
|
@ -978,6 +978,8 @@ JS::IncrementalObjectBarrier(JSObject *obj)
|
||||
|
||||
JS_ASSERT(!obj->zone()->runtimeFromMainThread()->isHeapMajorCollecting());
|
||||
|
||||
AutoMarkInDeadZone amn(obj->zone());
|
||||
|
||||
JSObject::writeBarrierPre(obj);
|
||||
}
|
||||
|
||||
@ -988,13 +990,13 @@ JS::IncrementalReferenceBarrier(void *ptr, JSGCTraceKind kind)
|
||||
return;
|
||||
|
||||
gc::Cell *cell = static_cast<gc::Cell *>(ptr);
|
||||
|
||||
#ifdef DEBUG
|
||||
Zone *zone = kind == JSTRACE_OBJECT
|
||||
? static_cast<JSObject *>(cell)->zone()
|
||||
: cell->tenuredZone();
|
||||
|
||||
JS_ASSERT(!zone->runtimeFromMainThread()->isHeapMajorCollecting());
|
||||
#endif
|
||||
|
||||
AutoMarkInDeadZone amn(zone);
|
||||
|
||||
if (kind == JSTRACE_OBJECT)
|
||||
JSObject::writeBarrierPre(static_cast<JSObject*>(cell));
|
||||
|
121
js/src/jsgc.cpp
121
js/src/jsgc.cpp
@ -230,6 +230,8 @@ using mozilla::DebugOnly;
|
||||
using mozilla::Maybe;
|
||||
using mozilla::Swap;
|
||||
|
||||
using JS::AutoGCRooter;
|
||||
|
||||
/* Perform a Full GC every 20 seconds if MaybeGC is called */
|
||||
static const uint64_t GC_IDLE_FULL_SPAN = 20 * 1000 * 1000;
|
||||
|
||||
@ -2982,14 +2984,14 @@ GCRuntime::beginMarkPhase()
|
||||
isFull = false;
|
||||
}
|
||||
|
||||
zone->scheduledForDestruction = false;
|
||||
zone->maybeAlive = false;
|
||||
zone->setPreservingCode(false);
|
||||
}
|
||||
|
||||
for (CompartmentsIter c(rt, WithAtoms); !c.done(); c.next()) {
|
||||
JS_ASSERT(c->gcLiveArrayBuffers.empty());
|
||||
c->marked = false;
|
||||
c->scheduledForDestruction = false;
|
||||
c->maybeAlive = false;
|
||||
if (shouldPreserveJITCode(c, currentTime))
|
||||
c->zone()->setPreservingCode(true);
|
||||
}
|
||||
@ -3090,50 +3092,40 @@ GCRuntime::beginMarkPhase()
|
||||
bufferGrayRoots();
|
||||
|
||||
/*
|
||||
* This code ensures that if a compartment is "dead", then it will be
|
||||
* collected in this GC. A compartment is considered dead if its maybeAlive
|
||||
* This code ensures that if a zone is "dead", then it will be
|
||||
* collected in this GC. A zone is considered dead if its maybeAlive
|
||||
* flag is false. The maybeAlive flag is set if:
|
||||
* (1) the compartment has incoming cross-compartment edges, or
|
||||
* (2) an object in the compartment was marked during root marking, either
|
||||
* (1) the zone has incoming cross-compartment edges, or
|
||||
* (2) an object in the zone was marked during root marking, either
|
||||
* as a black root or a gray root.
|
||||
* If the maybeAlive is false, then we set the scheduledForDestruction flag.
|
||||
* At the end of the GC, we look for compartments where
|
||||
* scheduledForDestruction is true. These are compartments that were somehow
|
||||
* "revived" during the incremental GC. If any are found, we do a special,
|
||||
* non-incremental GC of those compartments to try to collect them.
|
||||
* At any time later in the GC, if we try to mark an object whose
|
||||
* zone is scheduled for destruction, we will assert.
|
||||
* NOTE: Due to bug 811587, we only assert if gcManipulatingDeadCompartments
|
||||
* is true (e.g., if we're doing a brain transplant).
|
||||
*
|
||||
* Compartments can be revived for a variety of reasons. On reason is bug
|
||||
* 811587, where a reflector that was dead can be revived by DOM code that
|
||||
* still refers to the underlying DOM node.
|
||||
* The purpose of this check is to ensure that a zone that we would
|
||||
* normally destroy is not resurrected by a read barrier or an
|
||||
* allocation. This might happen during a function like JS_TransplantObject,
|
||||
* which iterates over all compartments, live or dead, and operates on their
|
||||
* objects. See bug 803376 for details on this problem. To avoid the
|
||||
* problem, we are very careful to avoid allocation and read barriers during
|
||||
* JS_TransplantObject and the like. The code here ensures that we don't
|
||||
* regress.
|
||||
*
|
||||
* Read barriers and allocations can also cause revival. This might happen
|
||||
* during a function like JS_TransplantObject, which iterates over all
|
||||
* compartments, live or dead, and operates on their objects. See bug 803376
|
||||
* for details on this problem. To avoid the problem, we try to avoid
|
||||
* allocation and read barriers during JS_TransplantObject and the like.
|
||||
* Note that there are certain cases where allocations or read barriers in
|
||||
* dead zone are difficult to avoid. We detect such cases (via the
|
||||
* gcObjectsMarkedInDeadCompartment counter) and redo any ongoing GCs after
|
||||
* the JS_TransplantObject function has finished. This ensures that the dead
|
||||
* zones will be cleaned up. See AutoMarkInDeadZone and
|
||||
* AutoMaybeTouchDeadZones for details.
|
||||
*/
|
||||
|
||||
/* Set the maybeAlive flag based on cross-compartment edges. */
|
||||
for (CompartmentsIter c(rt, SkipAtoms); !c.done(); c.next()) {
|
||||
for (JSCompartment::WrapperEnum e(c); !e.empty(); e.popFront()) {
|
||||
const CrossCompartmentKey &key = e.front().key();
|
||||
JSCompartment *dest;
|
||||
switch (key.kind) {
|
||||
case CrossCompartmentKey::ObjectWrapper:
|
||||
case CrossCompartmentKey::DebuggerObject:
|
||||
case CrossCompartmentKey::DebuggerSource:
|
||||
case CrossCompartmentKey::DebuggerEnvironment:
|
||||
dest = static_cast<JSObject *>(key.wrapped)->compartment();
|
||||
break;
|
||||
case CrossCompartmentKey::DebuggerScript:
|
||||
dest = static_cast<JSScript *>(key.wrapped)->compartment();
|
||||
break;
|
||||
default:
|
||||
dest = nullptr;
|
||||
break;
|
||||
}
|
||||
if (dest)
|
||||
dest->maybeAlive = true;
|
||||
Cell *dst = e.front().key().wrapped;
|
||||
dst->tenuredZone()->maybeAlive = true;
|
||||
}
|
||||
}
|
||||
|
||||
@ -3142,9 +3134,9 @@ GCRuntime::beginMarkPhase()
|
||||
* during MarkRuntime.
|
||||
*/
|
||||
|
||||
for (GCCompartmentsIter c(rt); !c.done(); c.next()) {
|
||||
if (!c->maybeAlive && !rt->isAtomsCompartment(c))
|
||||
c->scheduledForDestruction = true;
|
||||
for (GCZonesIter zone(rt); !zone.done(); zone.next()) {
|
||||
if (!zone->maybeAlive && !rt->isAtomsZone(zone))
|
||||
zone->scheduledForDestruction = true;
|
||||
}
|
||||
foundBlackGrayEdges = false;
|
||||
|
||||
@ -4520,8 +4512,8 @@ GCRuntime::resetIncrementalGC(const char *reason)
|
||||
case SWEEP:
|
||||
marker.reset();
|
||||
|
||||
for (CompartmentsIter c(rt, SkipAtoms); !c.done(); c.next())
|
||||
c->scheduledForDestruction = false;
|
||||
for (ZonesIter zone(rt, WithAtoms); !zone.done(); zone.next())
|
||||
zone->scheduledForDestruction = false;
|
||||
|
||||
/* Finish sweeping the current zone group, then abort. */
|
||||
abortSweepAfterCurrentGroup = true;
|
||||
@ -4999,30 +4991,13 @@ GCRuntime::collect(bool incremental, int64_t budget, JSGCInvocationKind gckind,
|
||||
if (poked && shouldCleanUpEverything)
|
||||
JS::PrepareForFullGC(rt);
|
||||
|
||||
/*
|
||||
* This code makes an extra effort to collect compartments that we
|
||||
* thought were dead at the start of the GC. See the large comment in
|
||||
* beginMarkPhase.
|
||||
*/
|
||||
bool repeatForDeadZone = false;
|
||||
if (incremental && incrementalState == NO_INCREMENTAL) {
|
||||
for (CompartmentsIter c(rt, SkipAtoms); !c.done(); c.next()) {
|
||||
if (c->scheduledForDestruction) {
|
||||
incremental = false;
|
||||
repeatForDeadZone = true;
|
||||
reason = JS::gcreason::COMPARTMENT_REVIVED;
|
||||
c->zone()->scheduleGC();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If we reset an existing GC, we need to start a new one. Also, we
|
||||
* repeat GCs that happen during shutdown (the gcShouldCleanUpEverything
|
||||
* case) until we can be sure that no additional garbage is created
|
||||
* (which typically happens if roots are dropped during finalizers).
|
||||
*/
|
||||
repeat = (poked && shouldCleanUpEverything) || wasReset || repeatForDeadZone;
|
||||
repeat = (poked && shouldCleanUpEverything) || wasReset;
|
||||
} while (repeat);
|
||||
|
||||
if (incrementalState == NO_INCREMENTAL) {
|
||||
@ -5559,6 +5534,34 @@ ArenaLists::containsArena(JSRuntime *rt, ArenaHeader *needle)
|
||||
}
|
||||
|
||||
|
||||
AutoMaybeTouchDeadZones::AutoMaybeTouchDeadZones(JSContext *cx)
|
||||
: runtime(cx->runtime()),
|
||||
markCount(runtime->gc.objectsMarkedInDeadZones),
|
||||
inIncremental(JS::IsIncrementalGCInProgress(runtime)),
|
||||
manipulatingDeadZones(runtime->gc.manipulatingDeadZones)
|
||||
{
|
||||
runtime->gc.manipulatingDeadZones = true;
|
||||
}
|
||||
|
||||
AutoMaybeTouchDeadZones::AutoMaybeTouchDeadZones(JSObject *obj)
|
||||
: runtime(obj->compartment()->runtimeFromMainThread()),
|
||||
markCount(runtime->gc.objectsMarkedInDeadZones),
|
||||
inIncremental(JS::IsIncrementalGCInProgress(runtime)),
|
||||
manipulatingDeadZones(runtime->gc.manipulatingDeadZones)
|
||||
{
|
||||
runtime->gc.manipulatingDeadZones = true;
|
||||
}
|
||||
|
||||
AutoMaybeTouchDeadZones::~AutoMaybeTouchDeadZones()
|
||||
{
|
||||
runtime->gc.manipulatingDeadZones = manipulatingDeadZones;
|
||||
|
||||
if (inIncremental && runtime->gc.objectsMarkedInDeadZones != markCount) {
|
||||
JS::PrepareForFullGC(runtime);
|
||||
js::GC(runtime, GC_NORMAL, JS::gcreason::TRANSPLANT);
|
||||
}
|
||||
}
|
||||
|
||||
AutoSuppressGC::AutoSuppressGC(ExclusiveContext *cx)
|
||||
: suppressGC_(cx->perThreadData->suppressGC)
|
||||
{
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user