Merge m-c to fx-team.

This commit is contained in:
Ryan VanderMeulen 2014-03-03 17:23:01 -05:00
commit 9e03047a9b
143 changed files with 5892 additions and 1573 deletions

View File

@ -2,11 +2,16 @@
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
include $(topsrcdir)/toolkit/mozapps/installer/package-name.mk
installer:
@$(MAKE) -C b2g/installer installer
package:
@$(MAKE) -C b2g/installer
ifdef FXOS_SIMULATOR
$(PYTHON) $(srcdir)/b2g/simulator/build_xpi.py $(MOZ_PKG_PLATFORM)
endif
install::
@echo 'B2G can't be installed directly.'

View File

@ -35,8 +35,8 @@ XPCOMUtils.defineLazyGetter(this, 'MemoryFront', function() {
*/
let developerHUD = {
_apps: new Map(),
_urls: new Map(),
_targets: new Map(),
_frames: new Map(),
_client: null,
_webappsActor: null,
_watchers: [],
@ -72,19 +72,16 @@ let developerHUD = {
}
}
Services.obs.addObserver(this, 'remote-browser-pending', false);
Services.obs.addObserver(this, 'remote-browser-shown', false);
Services.obs.addObserver(this, 'inprocess-browser-shown', false);
Services.obs.addObserver(this, 'message-manager-disconnect', false);
let systemapp = document.querySelector('#systemapp');
let manifestURL = systemapp.getAttribute("mozapp");
this.trackApp(manifestURL);
this.trackFrame(systemapp);
let frames =
systemapp.contentWindow.document.querySelectorAll('iframe[mozapp]');
let frames = systemapp.contentWindow.document.querySelectorAll('iframe[mozapp]');
for (let frame of frames) {
let manifestURL = frame.getAttribute("mozapp");
this.trackApp(manifestURL);
this.trackFrame(frame);
}
});
});
@ -94,11 +91,11 @@ let developerHUD = {
if (!this._client)
return;
for (let manifest of this._apps.keys()) {
this.untrackApp(manifest);
for (let frame of this._targets.keys()) {
this.untrackFrame(frame);
}
Services.obs.removeObserver(this, 'remote-browser-pending');
Services.obs.removeObserver(this, 'remote-browser-shown');
Services.obs.removeObserver(this, 'inprocess-browser-shown');
Services.obs.removeObserver(this, 'message-manager-disconnect');
@ -108,43 +105,43 @@ let developerHUD = {
/**
* This method will ask all registered watchers to track and update metrics
* on an app.
* on an app frame.
*/
trackApp: function dwp_trackApp(manifestURL) {
if (this._apps.has(manifestURL))
trackFrame: function dwp_trackFrame(frame) {
if (this._targets.has(frame))
return;
// FIXME(Bug 962577) Factor getAppActor out of webappsActor.
this._client.request({
to: this._webappsActor,
type: 'getAppActor',
manifestURL: manifestURL
manifestURL: frame.appManifestURL
}, (res) => {
if (res.error) {
return;
}
let app = new App(manifestURL, res.actor);
this._apps.set(manifestURL, app);
let target = new Target(frame, res.actor);
this._targets.set(frame, target);
for (let w of this._watchers) {
w.trackApp(app);
w.trackTarget(target);
}
});
},
untrackApp: function dwp_untrackApp(manifestURL) {
let app = this._apps.get(manifestURL);
if (app) {
untrackFrame: function dwp_untrackFrame(frame) {
let target = this._targets.get(frame);
if (target) {
for (let w of this._watchers) {
w.untrackApp(app);
w.untrackTarget(target);
}
// Delete the metrics and call display() to clean up the front-end.
delete app.metrics;
app.display();
delete target.metrics;
target.display();
this._apps.delete(manifestURL);
this._target.delete(frame);
}
},
@ -152,12 +149,12 @@ let developerHUD = {
if (!this._client)
return;
let manifestURL;
let frame;
switch(topic) {
// listen for frame creation in OOP (device) as well as in parent process (b2g desktop)
case 'remote-browser-pending':
case 'remote-browser-shown':
case 'inprocess-browser-shown':
let frameLoader = subject;
// get a ref to the app <iframe>
@ -166,21 +163,21 @@ let developerHUD = {
if (!frameLoader.ownerIsBrowserOrAppFrame) {
return;
}
manifestURL = frameLoader.ownerElement.appManifestURL;
if (!manifestURL) // Ignore all frames but apps
frame = frameLoader.ownerElement;
if (!frame.appManifestURL) // Ignore all frames but app frames
return;
this.trackApp(manifestURL);
this._urls.set(frameLoader.messageManager, manifestURL);
this.trackFrame(frame);
this._frames.set(frameLoader.messageManager, frame);
break;
// Every time an iframe is destroyed, its message manager also is
case 'message-manager-disconnect':
let mm = subject;
manifestURL = this._urls.get(mm);
if (!manifestURL)
frame = this._frames.get(mm);
if (!frame)
return;
this.untrackApp(manifestURL);
this._urls.delete(mm);
this.untrackFrame(frame);
this._frames.delete(mm);
break;
}
},
@ -197,25 +194,27 @@ let developerHUD = {
* being tracked, e.g. its manifest information, current values of watched
* metrics, and how to update these values on the front-end.
*/
function App(manifest, actor) {
this.manifest = manifest;
function Target(frame, actor) {
this.frame = frame;
this.actor = actor;
this.metrics = new Map();
}
App.prototype = {
Target.prototype = {
display: function target_display() {
let data = {
metrics: []
};
display: function app_display() {
let data = {manifestURL: this.manifest, metrics: []};
let metrics = this.metrics;
if (metrics && metrics.size > 0) {
for (let name of metrics.keys()) {
data.metrics.push({name: name, value: metrics.get(name)});
}
}
shell.sendCustomEvent('developer-hud-update', data);
shell.sendEvent(this.frame, 'developer-hud-update', Cu.cloneInto(data, this.frame));
// FIXME(after bug 963239 lands) return event.isDefaultPrevented();
return false;
}
@ -229,7 +228,7 @@ App.prototype = {
*/
let consoleWatcher = {
_apps: new Map(),
_targets: new Map(),
_watching: {
reflows: false,
warnings: false,
@ -252,9 +251,9 @@ let consoleWatcher = {
}
// If unwatched, remove any existing widgets for that metric.
for (let app of this._apps.values()) {
app.metrics.set(metric, 0);
app.display();
for (let target of this._targets.values()) {
target.metrics.set(metric, 0);
target.display();
}
});
}
@ -265,42 +264,42 @@ let consoleWatcher = {
client.addListener('reflowActivity', this.consoleListener);
},
trackApp: function cw_trackApp(app) {
app.metrics.set('reflows', 0);
app.metrics.set('warnings', 0);
app.metrics.set('errors', 0);
trackTarget: function cw_trackTarget(target) {
target.metrics.set('reflows', 0);
target.metrics.set('warnings', 0);
target.metrics.set('errors', 0);
this._client.request({
to: app.actor.consoleActor,
to: target.actor.consoleActor,
type: 'startListeners',
listeners: ['LogMessage', 'PageError', 'ConsoleAPI', 'ReflowActivity']
}, (res) => {
this._apps.set(app.actor.consoleActor, app);
this._targets.set(target.actor.consoleActor, target);
});
},
untrackApp: function cw_untrackApp(app) {
untrackTarget: function cw_untrackTarget(target) {
this._client.request({
to: app.actor.consoleActor,
to: target.actor.consoleActor,
type: 'stopListeners',
listeners: ['LogMessage', 'PageError', 'ConsoleAPI', 'ReflowActivity']
}, (res) => { });
this._apps.delete(app.actor.consoleActor);
this._targets.delete(target.actor.consoleActor);
},
bump: function cw_bump(app, metric) {
bump: function cw_bump(target, metric) {
if (!this._watching[metric]) {
return false;
}
let metrics = app.metrics;
let metrics = target.metrics;
metrics.set(metric, metrics.get(metric) + 1);
return true;
},
consoleListener: function cw_consoleListener(type, packet) {
let app = this._apps.get(packet.from);
let target = this._targets.get(packet.from);
let output = '';
switch (packet.type) {
@ -309,12 +308,12 @@ let consoleWatcher = {
let pageError = packet.pageError;
if (pageError.warning || pageError.strict) {
if (!this.bump(app, 'warnings')) {
if (!this.bump(target, 'warnings')) {
return;
}
output = 'warning (';
} else {
if (!this.bump(app, 'errors')) {
if (!this.bump(target, 'errors')) {
return;
}
output += 'error (';
@ -329,14 +328,14 @@ let consoleWatcher = {
switch (packet.message.level) {
case 'error':
if (!this.bump(app, 'errors')) {
if (!this.bump(target, 'errors')) {
return;
}
output = 'error (console)';
break;
case 'warn':
if (!this.bump(app, 'warnings')) {
if (!this.bump(target, 'warnings')) {
return;
}
output = 'warning (console)';
@ -348,7 +347,7 @@ let consoleWatcher = {
break;
case 'reflowActivity':
if (!this.bump(app, 'reflows')) {
if (!this.bump(target, 'reflows')) {
return;
}
@ -361,7 +360,7 @@ let consoleWatcher = {
break;
}
if (!app.display()) {
if (!target.display()) {
// If the information was not displayed, log it.
developerHUD.log(output);
}
@ -401,27 +400,27 @@ let eventLoopLagWatcher = {
// Toggle the state of existing fronts.
let fronts = this._fronts;
for (let app of fronts.keys()) {
for (let target of fronts.keys()) {
if (value) {
fronts.get(app).start();
fronts.get(target).start();
} else {
fronts.get(app).stop();
app.metrics.set('jank', 0);
app.display();
fronts.get(target).stop();
target.metrics.set('jank', 0);
target.display();
}
}
},
trackApp: function(app) {
app.metrics.set('jank', 0);
trackTarget: function(target) {
target.metrics.set('jank', 0);
let front = new EventLoopLagFront(this._client, app.actor);
this._fronts.set(app, front);
let front = new EventLoopLagFront(this._client, target.actor);
this._fronts.set(target, front);
front.on('event-loop-lag', time => {
app.metrics.set('jank', time);
target.metrics.set('jank', time);
if (!app.display()) {
if (!target.display()) {
developerHUD.log('jank: ' + time + 'ms');
}
});
@ -431,11 +430,11 @@ let eventLoopLagWatcher = {
}
},
untrackApp: function(app) {
untrackTarget: function(target) {
let fronts = this._fronts;
if (fronts.has(app)) {
fronts.get(app).destroy();
fronts.delete(app);
if (fronts.has(target)) {
fronts.get(target).destroy();
fronts.delete(target);
}
}
};
@ -473,23 +472,25 @@ let memoryWatcher = {
SettingsListener.observe('hud.appmemory', false, enabled => {
if (this._active = enabled) {
for (let app of this._fronts.keys()) {
this.measure(app);
for (let target of this._fronts.keys()) {
this.measure(target);
}
} else {
for (let timer of this._timers.values()) {
clearTimeout(this._timers.get(app));
for (let target of this._fronts.keys()) {
clearTimeout(this._timers.get(target));
target.metrics.set('memory', 0);
target.display();
}
}
});
},
measure: function mw_measure(app) {
measure: function mw_measure(target) {
// TODO Also track USS (bug #976024).
let watch = this._watching;
let front = this._fronts.get(app);
let front = this._fronts.get(target);
front.measure().then((data) => {
@ -514,32 +515,32 @@ let memoryWatcher = {
}
// TODO Also count images size (bug #976007).
app.metrics.set('memory', total);
app.display();
target.metrics.set('memory', total);
target.display();
let duration = parseInt(data.jsMilliseconds) + parseInt(data.nonJSMilliseconds);
let timer = setTimeout(() => this.measure(app), 100 * duration);
this._timers.set(app, timer);
let timer = setTimeout(() => this.measure(target), 100 * duration);
this._timers.set(target, timer);
}, (err) => {
console.error(err);
});
},
trackApp: function mw_trackApp(app) {
app.metrics.set('uss', 0);
app.metrics.set('memory', 0);
this._fronts.set(app, MemoryFront(this._client, app.actor));
trackTarget: function mw_trackTarget(target) {
target.metrics.set('uss', 0);
target.metrics.set('memory', 0);
this._fronts.set(target, MemoryFront(this._client, target.actor));
if (this._active) {
this.measure(app);
this.measure(target);
}
},
untrackApp: function mw_untrackApp(app) {
let front = this._fronts.get(app);
untrackTarget: function mw_untrackTarget(target) {
let front = this._fronts.get(target);
if (front) {
front.destroy();
clearTimeout(this._timers.get(app));
this._fronts.delete(app);
this._timers.delete(app);
clearTimeout(this._timers.get(target));
this._fronts.delete(target);
this._timers.delete(target);
}
}
};

View File

@ -560,18 +560,18 @@ var shell = {
}
},
sendEvent: function shell_sendEvent(content, type, details) {
let event = content.document.createEvent('CustomEvent');
// Send an event to a specific window, document or element.
sendEvent: function shell_sendEvent(target, type, details) {
let doc = target.document || target.ownerDocument || target;
let event = doc.createEvent('CustomEvent');
event.initCustomEvent(type, true, true, details ? details : {});
content.dispatchEvent(event);
target.dispatchEvent(event);
},
sendCustomEvent: function shell_sendCustomEvent(type, details) {
let content = getContentWindow();
let event = content.document.createEvent('CustomEvent');
let payload = details ? Cu.cloneInto(details, content) : {};
event.initCustomEvent(type, true, true, payload);
content.dispatchEvent(event);
let target = getContentWindow();
let payload = details ? Cu.cloneInto(details, target) : {};
this.sendEvent(target, type, payload);
},
sendChromeEvent: function shell_sendChromeEvent(details) {

View File

@ -19,7 +19,7 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="dfae3744607257206e37483dc3f431108baf70fb"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="fd883f4f086f95f2a9d2f94c7299fa7780aee19d"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="15e8982284c4560f9c74c2b9fe8bb361ebfe0cb6"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="d11f524d00cacf5ba0dfbf25e4aa2158b1c3a036"/>

View File

@ -17,7 +17,7 @@
</project>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="dfae3744607257206e37483dc3f431108baf70fb"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="fd883f4f086f95f2a9d2f94c7299fa7780aee19d"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="15e8982284c4560f9c74c2b9fe8bb361ebfe0cb6"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="3d5c964015967ca8c86abe6dbbebee3cb82b1609"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="b2f773d8320d30648b89767dfe5b25ef94bc7e62"/>

View File

@ -19,7 +19,7 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="dfae3744607257206e37483dc3f431108baf70fb"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="fd883f4f086f95f2a9d2f94c7299fa7780aee19d"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="15e8982284c4560f9c74c2b9fe8bb361ebfe0cb6"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="d11f524d00cacf5ba0dfbf25e4aa2158b1c3a036"/>

View File

@ -4,6 +4,6 @@
"branch": "",
"revision": ""
},
"revision": "3d294ffa51afd8a8daafcdaa97cda8e38de81cb8",
"revision": "c195232a409ee2234eca18a63bac2d48c2db0c13",
"repo_path": "/integration/gaia-central"
}

View File

@ -17,7 +17,7 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="dfae3744607257206e37483dc3f431108baf70fb"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="fd883f4f086f95f2a9d2f94c7299fa7780aee19d"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="15e8982284c4560f9c74c2b9fe8bb361ebfe0cb6"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="84f2f2fce22605e17d511ff1767e54770067b5b5"/>

View File

@ -15,7 +15,7 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="dfae3744607257206e37483dc3f431108baf70fb"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="fd883f4f086f95f2a9d2f94c7299fa7780aee19d"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="15e8982284c4560f9c74c2b9fe8bb361ebfe0cb6"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="84f2f2fce22605e17d511ff1767e54770067b5b5"/>

View File

@ -19,7 +19,7 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="dfae3744607257206e37483dc3f431108baf70fb"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="fd883f4f086f95f2a9d2f94c7299fa7780aee19d"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="15e8982284c4560f9c74c2b9fe8bb361ebfe0cb6"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="84f2f2fce22605e17d511ff1767e54770067b5b5"/>

View File

@ -17,7 +17,7 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="dfae3744607257206e37483dc3f431108baf70fb"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="fd883f4f086f95f2a9d2f94c7299fa7780aee19d"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="15e8982284c4560f9c74c2b9fe8bb361ebfe0cb6"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="84f2f2fce22605e17d511ff1767e54770067b5b5"/>

View File

@ -17,7 +17,7 @@
</project>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="dfae3744607257206e37483dc3f431108baf70fb"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="fd883f4f086f95f2a9d2f94c7299fa7780aee19d"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="15e8982284c4560f9c74c2b9fe8bb361ebfe0cb6"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="3d5c964015967ca8c86abe6dbbebee3cb82b1609"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="b2f773d8320d30648b89767dfe5b25ef94bc7e62"/>

View File

@ -17,7 +17,7 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="dfae3744607257206e37483dc3f431108baf70fb"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="fd883f4f086f95f2a9d2f94c7299fa7780aee19d"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="15e8982284c4560f9c74c2b9fe8bb361ebfe0cb6"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="84f2f2fce22605e17d511ff1767e54770067b5b5"/>

145
b2g/simulator/build_xpi.py Normal file
View File

@ -0,0 +1,145 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
# Generate xpi for the simulator addon by:
# - building a special gaia profile for it, as we need:
# * more languages, and,
# * less apps
# than b2g desktop's one
# - retrieve usefull app version metadata from the build system
# - finally, use addon sdk's cfx tool to build the addon xpi
# that ships:
# * a small firefox addon registering to the app manager
# * b2g desktop runtime
# * gaia profile
import sys, os, re, subprocess
from mozbuild.preprocessor import Preprocessor
from mozbuild.base import MozbuildObject
from mozbuild.util import ensureParentDir
from zipfile import ZipFile
from distutils.version import LooseVersion
ftp_root_path = "/pub/mozilla.org/labs/fxos-simulator"
UPDATE_LINK = "https://ftp.mozilla.org" + ftp_root_path + "/%(update_path)s/%(xpi_name)s"
UPDATE_URL = "https://ftp.mozilla.org" + ftp_root_path + "/%(update_path)s/update.rdf"
XPI_NAME = "fxos-simulator-%(version)s-%(platform)s.xpi"
class GaiaBuilder(object):
def __init__(self, build, gaia_path):
self.build = build
self.gaia_path = gaia_path
def clean(self):
self.build._run_make(target="clean", directory=self.gaia_path)
def profile(self, env):
self.build._run_make(target="profile", directory=self.gaia_path, num_jobs=1, silent=False, append_env=env)
def override_prefs(self, srcfile):
# Note that each time we call `make profile` in gaia, a fresh new pref file is created
# cat srcfile >> profile/user.js
with open(os.path.join(self.gaia_path, "profile", "user.js"), "a") as userJs:
userJs.write(open(srcfile).read())
def process_package_overload(src, dst, version, app_buildid):
ensureParentDir(dst)
# First replace numeric version like '1.3'
# Then replace with 'slashed' version like '1_4'
# Finally set the full length addon version like 1.3.20131230
defines = {
"NUM_VERSION": version,
"SLASH_VERSION": version.replace(".", "_"),
"FULL_VERSION": ("%s.%s" % (version, app_buildid))
}
pp = Preprocessor(defines=defines)
pp.do_filter("substitution")
with open(dst, "w") as output:
with open(src, "r") as input:
pp.processFile(input=input, output=output)
def add_dir_to_zip(zip, top, pathInZip, blacklist=()):
zf = ZipFile(zip, "a")
for dirpath, subdirs, files in os.walk(top):
dir_relpath = os.path.relpath(dirpath, top)
if dir_relpath.startswith(blacklist):
continue
zf.write(dirpath, os.path.join(pathInZip, dir_relpath))
for filename in files:
relpath = os.path.join(dir_relpath, filename)
if relpath in blacklist:
continue
zf.write(os.path.join(dirpath, filename),
os.path.join(pathInZip, relpath))
zf.close()
def main(platform):
build = MozbuildObject.from_environment()
topsrcdir = build.topsrcdir
distdir = build.distdir
srcdir = os.path.join(topsrcdir, "b2g", "simulator")
app_buildid = open(os.path.join(build.topobjdir, "config", "buildid")).read().strip()
# The simulator uses a shorter version string,
# it only keeps the major version digits A.B
# whereas MOZ_B2G_VERSION is A.B.C.D
b2g_version = build.config_environment.defines["MOZ_B2G_VERSION"].replace('"', '')
version = ".".join(str(n) for n in LooseVersion(b2g_version).version[0:2])
# Build a gaia profile specific to the simulator in order to:
# - disable the FTU
# - set custom prefs to enable devtools debugger server
# - set custom settings to disable lockscreen and screen timeout
# - only ship production apps
gaia_path = build.config_environment.substs["GAIADIR"]
builder = GaiaBuilder(build, gaia_path)
builder.clean()
env = {
"NOFTU": "1",
"GAIA_APP_TARGET": "production",
"SETTINGS_PATH": os.path.join(srcdir, "custom-settings.json")
}
builder.profile(env)
builder.override_prefs(os.path.join(srcdir, "custom-prefs.js"))
# Substitute version strings in the package manifest overload file
manifest_overload = os.path.join(build.topobjdir, "b2g", "simulator", "package-overload.json")
process_package_overload(os.path.join(srcdir, "package-overload.json.in"),
manifest_overload,
version,
app_buildid)
# Build the simulator addon xpi
xpi_name = XPI_NAME % {"version": version, "platform": platform}
xpi_path = os.path.join(distdir, xpi_name)
update_path = "%s/%s" % (version, platform)
update_link = UPDATE_LINK % {"update_path": update_path, "xpi_name": xpi_name}
update_url = UPDATE_URL % {"update_path": update_path}
subprocess.check_call([
build.virtualenv_manager.python_path, os.path.join(topsrcdir, "addon-sdk", "source", "bin", "cfx"), "xpi", \
"--pkgdir", srcdir, \
"--manifest-overload", manifest_overload, \
"--strip-sdk", \
"--update-link", update_link, \
"--update-url", update_url, \
"--static-args", "{\"label\": \"Firefox OS %s\"}" % version, \
"--output-file", xpi_path \
])
# Ship b2g-desktop, but prevent its gaia profile to be shipped in the xpi
add_dir_to_zip(xpi_path, os.path.join(distdir, "b2g"), "b2g", ("gaia"))
# Then ship our own gaia profile
add_dir_to_zip(xpi_path, os.path.join(gaia_path, "profile"), "profile")
if __name__ == '__main__':
if 2 != len(sys.argv):
print("""Usage:
python {0} MOZ_PKG_PLATFORM
""".format(sys.argv[0]))
sys.exit(1)
main(*sys.argv[1:])

View File

@ -0,0 +1,2 @@
user_pref("devtools.debugger.prompt-connection", false);
user_pref("devtools.debugger.forbid-certified-apps", false);

View File

@ -0,0 +1,6 @@
{
"debugger.remote-mode": "adb-devtools",
"screen.timeout": 0,
"lockscreen.enabled": false,
"lockscreen.locked": false
}

BIN
b2g/simulator/icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

BIN
b2g/simulator/icon64.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.7 KiB

52
b2g/simulator/lib/main.js Normal file
View File

@ -0,0 +1,52 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
const { Cc, Ci, Cu } = require("chrome");
const { SimulatorProcess } = require("./simulator-process");
const Promise = require("sdk/core/promise");
const Self = require("sdk/self");
const System = require("sdk/system");
const { Simulator } = Cu.import("resource://gre/modules/devtools/Simulator.jsm");
let process;
function launch({ port }) {
// Close already opened simulation
if (process) {
return close().then(launch.bind(null, { port: port }));
}
process = SimulatorProcess();
process.remoteDebuggerPort = port;
process.run();
return Promise.resolve();
}
function close() {
if (!process) {
return Promise.resolve();
}
let p = process;
process = null;
return p.kill();
}
// Load data generated at build time that
// expose various information about the runtime we ship
let appinfo = System.staticArgs;
Simulator.register(appinfo.label, {
appinfo: appinfo,
launch: launch,
close: close
});
require("sdk/system/unload").when(function () {
Simulator.unregister(appinfo.label);
close();
});

View File

@ -0,0 +1,182 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
'use strict';
const { Cc, Ci, Cu, ChromeWorker } = require("chrome");
Cu.import("resource://gre/modules/Services.jsm");
const { EventTarget } = require("sdk/event/target");
const { emit, off } = require("sdk/event/core");
const { Class } = require("sdk/core/heritage");
const Environment = require("sdk/system/environment").env;
const Runtime = require("sdk/system/runtime");
const Self = require("sdk/self");
const URL = require("sdk/url");
const Subprocess = require("subprocess");
const Promise = require("sdk/core/promise");
const { rootURI: ROOT_URI } = require('@loader/options');
const PROFILE_URL = ROOT_URI + "profile/";
const BIN_URL = ROOT_URI + "b2g/";
// Log subprocess error and debug messages to the console. This logs messages
// for all consumers of the API. We trim the messages because they sometimes
// have trailing newlines. And note that registerLogHandler actually registers
// an error handler, despite its name.
Subprocess.registerLogHandler(
function(s) console.error("subprocess: " + s.trim())
);
Subprocess.registerDebugHandler(
function(s) console.debug("subprocess: " + s.trim())
);
exports.SimulatorProcess = Class({
extends: EventTarget,
initialize: function initialize(options) {
EventTarget.prototype.initialize.call(this, options);
this.on("stdout", function onStdout(data) console.log(data.trim()));
this.on("stderr", function onStderr(data) console.error(data.trim()));
},
// check if b2g is running
get isRunning() !!this.process,
/**
* Start the process and connect the debugger client.
*/
run: function() {
// kill before start if already running
if (this.process != null) {
this.process
.kill()
.then(this.run.bind(this));
return;
}
// resolve b2g binaries path (raise exception if not found)
let b2gExecutable = this.b2gExecutable;
this.once("stdout", function () {
if (Runtime.OS == "Darwin") {
console.debug("WORKAROUND run osascript to show b2g-desktop window"+
" on Runtime.OS=='Darwin'");
// Escape double quotes and escape characters for use in AppleScript.
let path = b2gExecutable.path
.replace(/\\/g, "\\\\").replace(/\"/g, '\\"');
Subprocess.call({
command: "/usr/bin/osascript",
arguments: ["-e", 'tell application "' + path + '" to activate'],
});
}
});
let environment;
if (Runtime.OS == "Linux") {
environment = ["TMPDIR=" + Services.dirsvc.get("TmpD",Ci.nsIFile).path];
if ("DISPLAY" in Environment) {
environment.push("DISPLAY=" + Environment.DISPLAY);
}
}
// spawn a b2g instance
this.process = Subprocess.call({
command: b2gExecutable,
arguments: this.b2gArguments,
environment: environment,
// emit stdout event
stdout: (function(data) {
emit(this, "stdout", data);
}).bind(this),
// emit stderr event
stderr: (function(data) {
emit(this, "stderr", data);
}).bind(this),
// on b2g instance exit, reset tracked process, remoteDebuggerPort and
// shuttingDown flag, then finally emit an exit event
done: (function(result) {
console.log(this.b2gFilename + " terminated with " + result.exitCode);
this.process = null;
emit(this, "exit", result.exitCode);
}).bind(this)
});
},
// request a b2g instance kill
kill: function() {
let deferred = Promise.defer();
if (this.process) {
this.once("exit", (exitCode) => {
this.shuttingDown = false;
deferred.resolve(exitCode);
});
if (!this.shuttingDown) {
this.shuttingDown = true;
emit(this, "kill", null);
this.process.kill();
}
return deferred.promise;
} else {
return Promise.resolve(undefined);
}
},
// compute current b2g filename
get b2gFilename() {
return this._executable ? this._executableFilename : "B2G";
},
// compute current b2g file handle
get b2gExecutable() {
if (this._executable) return this._executable;
let bin = URL.toFilename(BIN_URL);
let executables = {
WINNT: "b2g-bin.exe",
Darwin: "Contents/MacOS/b2g-bin",
Linux: "b2g-bin",
};
console.log("bin url: "+bin+"/"+executables[Runtime.OS]);
let path = bin + "/" + executables[Runtime.OS];
let executable = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
executable.initWithPath(path);
if (!executable.exists()) {
// B2G binaries not found
throw Error("b2g-desktop Executable not found.");
}
this._executable = executable;
this._executableFilename = "b2g-bin";
return executable;
},
// compute b2g CLI arguments
get b2gArguments() {
let args = [];
let profile = URL.toFilename(PROFILE_URL);
args.push("-profile", profile);
Cu.reportError(profile);
// NOTE: push dbgport option on the b2g-desktop commandline
args.push("-dbgport", "" + this.remoteDebuggerPort);
// Ignore eventual zombie instances of b2g that are left over
args.push("-no-remote");
return args;
},
});

View File

@ -0,0 +1,7 @@
{
"id": "fxos_@SLASH_VERSION@_simulator@mozilla.org",
"name": "fxos_@SLASH_VERSION@_simulator",
"version": "@FULL_VERSION@",
"fullName": "Firefox OS @NUM_VERSION@ Simulator",
"description": "a Firefox OS @NUM_VERSION@ simulator"
}

View File

@ -0,0 +1,37 @@
{
"id": "fxos_simulator@mozilla.org",
"name": "fxos_simulator",
"version": "1.0.dev",
"fullName": "Firefox OS Simulator",
"label": "Firefox OS",
"description": "a Firefox OS simulator",
"author": "Myk Melez (https://github.com/mykmelez)",
"contributors": [
"Alexandre Poirot (https://github.com/ochameau)",
"Anant Narayanan (https://github.com/anantn)",
"Brandon Kase (https://github.com/bkase)",
"Breck Yunits (https://github.com/breck7)",
"César Carruitero (https://github.com/ccarruitero)",
"David Gomes (https://github.com/davidgomes)",
"Fabrice Desré (https://github.com/fabricedesre)",
"Fraser Tweedale (https://github.com/frasertweedale)",
"Harald Kirschner (https://github.com/digitarald)",
"Jérémie Patonnier (https://github.com/JeremiePat)",
"J. Ryan Stinnett (https://github.com/jryans)",
"Kan-Ru Chen (陳侃如) (https://github.com/kanru)",
"Louis Stowasser (https://github.com/louisstow)",
"Luca Greco (https://github.com/rpl)",
"Matthew Claypotch (https://github.com/potch)",
"Matthew Riley MacPherson (https://github.com/tofumatt)",
"Nick Desaulniers (https://github.com/nickdesaulniers)",
"Soumen Ganguly (https://github.com/SoumenG)",
"Sudheesh Singanamalla (https://github.com/sudheesh001)",
"Victor Bjelkholm (https://github.com/VictorBjelkholm)"
],
"permissions": {
"private-browsing": true
},
"license": "MPL 2.0",
"unpack": true,
"dependencies": ["subprocess"]
}

View File

@ -0,0 +1,124 @@
<h2>What's that?</h2>
Simply package enigmail hard work on providing IPC feature in mozilla platform.
So we are able to launch child proccesses from javascript,
and in our case, from addon-sdk libraries :)
<h2>Sample of code:</h2>
This object allows to start a process, and read/write data to/from it
using stdin/stdout/stderr streams.
Usage example:
const subprocess = require("subprocess");
var p = subprocess.call({
command: '/bin/foo',
arguments: ['-v', 'foo'],
environment: [ "XYZ=abc", "MYVAR=def" ],
charset: 'UTF-8',
workdir: '/home/foo',
//stdin: "some value to write to stdin\nfoobar",
stdin: function(stdin) {
stdin.write("some value to write to stdin\nfoobar");
stdin.close();
},
stdout: function(data) {
dump("got data on stdout:" + data + "\n");
},
stderr: function(data) {
dump("got data on stderr:" + data + "\n");
},
done: function(result) {
dump("process terminated with " + result.exitCode + "\n");
},
mergeStderr: false
});
p.wait(); // wait for the subprocess to terminate
// this will block the main thread,
// only do if you can wait that long
Description of parameters:
--------------------------
Apart from <command>, all arguments are optional.
command: either a |nsIFile| object pointing to an executable file or a
String containing the platform-dependent path to an executable
file.
arguments: optional string array containing the arguments to the command.
environment: optional string array containing environment variables to pass
to the command. The array elements must have the form
"VAR=data". Please note that if environment is defined, it
replaces any existing environment variables for the subprocess.
charset: Output is decoded with given charset and a string is returned.
If charset is undefined, "UTF-8" is used as default.
To get binary data, set this to null and the returned string
is not decoded in any way.
workdir: optional; String containing the platform-dependent path to a
directory to become the current working directory of the subprocess.
stdin: optional input data for the process to be passed on standard
input. stdin can either be a string or a function.
A |string| gets written to stdin and stdin gets closed;
A |function| gets passed an object with write and close function.
Please note that the write() function will return almost immediately;
data is always written asynchronously on a separate thread.
stdout: an optional function that can receive output data from the
process. The stdout-function is called asynchronously; it can be
called mutliple times during the execution of a process.
At a minimum at each occurance of \n or \r.
Please note that null-characters might need to be escaped
with something like 'data.replace(/\0/g, "\\0");'.
stderr: an optional function that can receive stderr data from the
process. The stderr-function is called asynchronously; it can be
called mutliple times during the execution of a process. Please
note that null-characters might need to be escaped with
something like 'data.replace(/\0/g, "\\0");'.
(on windows it only gets called once right now)
done: optional function that is called when the process has terminated.
The exit code from the process available via result.exitCode. If
stdout is not defined, then the output from stdout is available
via result.stdout. stderr data is in result.stderr
mergeStderr: optional boolean value. If true, stderr is merged with stdout;
no data will be provided to stderr.
Description of object returned by subprocess.call(...)
------------------------------------------------------
The object returned by subprocess.call offers a few methods that can be
executed:
wait(): waits for the subprocess to terminate. It is not required to use
wait; done will be called in any case when the subprocess terminated.
kill(hardKill): kill the subprocess. Any open pipes will be closed and
done will be called.
hardKill [ignored on Windows]:
- false: signal the process terminate (SIGTERM)
- true: kill the process (SIGKILL)
Other methods in subprocess
---------------------------
registerDebugHandler(functionRef): register a handler that is called to get
debugging information
registerLogHandler(functionRef): register a handler that is called to get error
messages
example:
subprocess.registerLogHandler( function(s) { dump(s); } );
<h2>Credits:</h2>
All enigmail team working on IPC component.
The Initial Developer of this code is Jan Gerber.
Portions created by Jan Gerber <j@mailb.org>,
Patrick Brunschwig (author of almost all code) <patrick@mozilla-enigmail.org>,
Ramalingam Saravanan (from enigmail team) <svn@xmlterm.org>

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,248 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
/*
* ChromeWorker Object subprocess.jsm on Unix-like systems (Linux, Mac OS X, ...)
* to process stdin/stdout/stderr on separate threads.
*
*/
// Being a ChromeWorker object, implicitly uses the following:
// Components.utils.import("resource://gre/modules/ctypes.jsm");
'use strict';
const BufferSize = 1024;
var libc = null;
var libcFunc = {};
/*
struct pollfd {
int fd; // file descriptor
short events; // events to look for
short revents; // events returned
};
*/
var pollfd = new ctypes.StructType("pollfd",
[ {'fd': ctypes.int},
{'events': ctypes.short},
{'revents': ctypes.short}
]);
var WriteBuffer = ctypes.uint8_t.array(BufferSize);
var ReadBuffer = ctypes.char.array(BufferSize);
const POLLIN = 0x0001;
const POLLOUT = 0x0004;
const POLLERR = 0x0008; // some poll error occurred
const POLLHUP = 0x0010; // file descriptor was "hung up"
const POLLNVAL = 0x0020; // requested events "invalid"
const WNOHANG = 0x01;
const pid_t = ctypes.int32_t;
const INDEFINITE = -1;
const NOWAIT = 0;
const WAITTIME = 200 // wait time for poll() in ms
function initLibc(libName) {
postMessage({msg: "debug", data: "initialising library with "+ libName});
libc = ctypes.open(libName);
libcFunc.pollFds = pollfd.array(1);
// int poll(struct pollfd fds[], nfds_t nfds, int timeout);
libcFunc.poll = libc.declare("poll",
ctypes.default_abi,
ctypes.int,
libcFunc.pollFds,
ctypes.unsigned_int,
ctypes.int);
//ssize_t write(int fd, const void *buf, size_t count);
// NOTE: buf is declared as array of unsigned int8 instead of char to avoid
// implicit charset conversion
libcFunc.write = libc.declare("write",
ctypes.default_abi,
ctypes.int,
ctypes.int,
WriteBuffer,
ctypes.int);
//int read(int fd, void *buf, size_t count);
libcFunc.read = libc.declare("read",
ctypes.default_abi,
ctypes.int,
ctypes.int,
ReadBuffer,
ctypes.int);
//int pipe(int pipefd[2]);
libcFunc.pipefd = ctypes.int.array(2);
//int close(int fd);
libcFunc.close = libc.declare("close",
ctypes.default_abi,
ctypes.int,
ctypes.int);
//pid_t waitpid(pid_t pid, int *status, int options);
libcFunc.waitpid = libc.declare("waitpid",
ctypes.default_abi,
pid_t,
pid_t,
ctypes.int.ptr,
ctypes.int);
}
function closePipe(pipe) {
libcFunc.close(pipe);
}
function writePipe(pipe, data) {
postMessage({msg: "debug", data: "trying to write to "+pipe});
let numChunks = Math.floor(data.length / BufferSize);
let pData = new WriteBuffer();
for (var chunk = 0; chunk <= numChunks; chunk ++) {
let numBytes = chunk < numChunks ? BufferSize : data.length - chunk * BufferSize;
for (var i=0; i < numBytes; i++) {
pData[i] = data.charCodeAt(chunk * BufferSize + i) % 256;
}
let bytesWritten = libcFunc.write(pipe, pData, numBytes);
if (bytesWritten != numBytes) {
closePipe();
libc.close();
postMessage({ msg: "error", data: "error: wrote "+bytesWritten+" instead of "+numBytes+" bytes"});
close();
}
}
postMessage({msg: "info", data: "wrote "+data.length+" bytes of data"});
}
function readString(data, length, charset) {
var string = '', bytes = [];
for(var i = 0;i < length; i++) {
if(data[i] == 0 && charset != "null") // stop on NULL character for non-binary data
break;
bytes.push(data[i]);
}
return bytes;
}
function readPipe(pipe, charset, pid) {
var p = new libcFunc.pollFds;
p[0].fd = pipe;
p[0].events = POLLIN | POLLERR | POLLHUP;
p[0].revents = 0;
var pollTimeout = WAITTIME;
var exitCode = -1;
var readCount = 0;
var result, status = ctypes.int();
result = 0;
const i=0;
while (true) {
if (result == 0) {
result = libcFunc.waitpid(pid, status.address(), WNOHANG);
if (result > 0) {
pollTimeout = NOWAIT;
exitCode = parseInt(status.value);
postMessage({msg: "debug", data: "waitpid signaled subprocess stop, exitcode="+status.value });
}
}
var r = libcFunc.poll(p, 1, pollTimeout);
if (r > 0) {
if (p[i].revents & POLLIN) {
postMessage({msg: "debug", data: "reading next chunk"});
readCount = readPolledFd(p[i].fd, charset);
if (readCount == 0) break;
}
if (p[i].revents & POLLHUP) {
postMessage({msg: "debug", data: "poll returned HUP"});
break;
}
else if (p[i].revents & POLLERR) {
postMessage({msg: "error", data: "poll returned error"});
break;
}
else if (p[i].revents != POLLIN) {
postMessage({msg: "error", data: "poll returned "+p[i]});
break;
}
}
else
if (pollTimeout == 0 || r < 0) break;
}
// continue reading until the buffer is empty
while (readCount > 0) {
readCount = readPolledFd(pipe, charset);
}
libcFunc.close(pipe);
postMessage({msg: "done", data: exitCode });
libc.close();
close();
}
function readPolledFd(pipe, charset) {
var line = new ReadBuffer();
var r = libcFunc.read(pipe, line, BufferSize);
if (r > 0) {
var c = readString(line, r, charset);
postMessage({msg: "data", data: c, count: c.length});
}
return r;
}
onmessage = function (event) {
switch (event.data.msg) {
case "init":
initLibc(event.data.libc);
break;
case "read":
initLibc(event.data.libc);
readPipe(event.data.pipe, event.data.charset, event.data.pid);
break;
case "write":
// data contents:
// msg: 'write'
// data: the data (string) to write
// pipe: ptr to pipe
writePipe(event.data.pipe, event.data.data);
postMessage({msg: "info", data: "WriteOK"});
break;
case "close":
postMessage({msg: "debug", data: "closing stdin\n"});
closePipe(event.data.pipe);
postMessage({msg: "info", data: "ClosedOK"});
break;
case "stop":
libc.close(); // do not use libc after this point
close();
break;
default:
throw("error: Unknown command"+event.data.msg+"\n");
}
return;
};

View File

@ -0,0 +1,206 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
/*
* ChromeWorker Object subprocess.jsm on Windows to process stdin/stdout/stderr
* on separate threads.
*
*/
// Being a ChromeWorker object, implicitly uses the following:
// Components.utils.import("resource://gre/modules/ctypes.jsm");
'use strict';
const BufferSize = 1024;
const BOOL = ctypes.bool;
const HANDLE = ctypes.size_t;
const DWORD = ctypes.uint32_t;
const LPDWORD = DWORD.ptr;
const PVOID = ctypes.voidptr_t;
const LPVOID = PVOID;
/*
typedef struct _OVERLAPPED {
ULONG_PTR Internal;
ULONG_PTR InternalHigh;
union {
struct {
DWORD Offset;
DWORD OffsetHigh;
};
PVOID Pointer;
};
HANDLE hEvent;
} OVERLAPPED, *LPOVERLAPPED;
*/
const OVERLAPPED = new ctypes.StructType("OVERLAPPED");
var ReadFileBuffer = ctypes.char.array(BufferSize);
var WriteFileBuffer = ctypes.uint8_t.array(BufferSize);
var kernel32dll = null;
var libFunc = {};
function initLib(libName) {
if (ctypes.size_t.size == 8) {
var WinABI = ctypes.default_abi;
} else {
var WinABI = ctypes.winapi_abi;
}
kernel32dll = ctypes.open(libName);
/*
BOOL WINAPI WriteFile(
__in HANDLE hFile,
__in LPCVOID lpBuffer,
__in DWORD nNumberOfBytesToWrite,
__out_opt LPDWORD lpNumberOfBytesWritten,
__inout_opt LPOVERLAPPED lpOverlapped
);
NOTE: lpBuffer is declared as array of unsigned int8 instead of char to avoid
implicit charset conversion
*/
libFunc.WriteFile = kernel32dll.declare("WriteFile",
WinABI,
BOOL,
HANDLE,
WriteFileBuffer,
DWORD,
LPDWORD,
OVERLAPPED.ptr
);
/*
BOOL WINAPI ReadFile(
__in HANDLE hFile,
__out LPVOID ReadFileBuffer,
__in DWORD nNumberOfBytesToRead,
__out_opt LPDWORD lpNumberOfBytesRead,
__inout_opt LPOVERLAPPED lpOverlapped
);
*/
libFunc.ReadFile = kernel32dll.declare("ReadFile",
WinABI,
BOOL,
HANDLE,
ReadFileBuffer,
DWORD,
LPDWORD,
OVERLAPPED.ptr
);
/*
BOOL WINAPI CloseHandle(
__in HANDLE hObject
);
*/
libFunc.CloseHandle = kernel32dll.declare("CloseHandle",
WinABI,
BOOL,
HANDLE
);
}
function writePipe(pipe, data) {
var bytesWritten = DWORD(0);
var pData = new WriteFileBuffer();
var numChunks = Math.floor(data.length / BufferSize);
for (var chunk = 0; chunk <= numChunks; chunk ++) {
var numBytes = chunk < numChunks ? BufferSize : data.length - chunk * BufferSize;
for (var i=0; i < numBytes; i++) {
pData[i] = data.charCodeAt(chunk * BufferSize + i) % 256;
}
var r = libFunc.WriteFile(pipe, pData, numBytes, bytesWritten.address(), null);
if (bytesWritten.value != numBytes)
throw("error: wrote "+bytesWritten.value+" instead of "+numBytes+" bytes");
}
postMessage("wrote "+data.length+" bytes of data");
}
function readString(data, length, charset) {
var string = '', bytes = [];
for(var i = 0;i < length; i++) {
if(data[i] == 0 && charset != "null") // stop on NULL character for non-binary data
break;
bytes.push(data[i]);
}
return bytes;
}
function readPipe(pipe, charset) {
while (true) {
var bytesRead = DWORD(0);
var line = new ReadFileBuffer();
var r = libFunc.ReadFile(pipe, line, BufferSize, bytesRead.address(), null);
if (!r) {
// stop if we get an error (such as EOF reached)
postMessage({msg: "info", data: "ReadFile failed"});
break;
}
if (bytesRead.value > 0) {
var c = readString(line, bytesRead.value, charset);
postMessage({msg: "data", data: c, count: c.length});
}
else {
break;
}
}
libFunc.CloseHandle(pipe);
postMessage({msg: "done"});
kernel32dll.close();
close();
}
onmessage = function (event) {
let pipePtr;
switch (event.data.msg) {
case "init":
initLib(event.data.libc);
break;
case "write":
// data contents:
// msg: 'write'
// data: the data (string) to write
// pipe: ptr to pipe
pipePtr = HANDLE.ptr(event.data.pipe);
writePipe(pipePtr.contents, event.data.data);
postMessage("WriteOK");
break;
case "read":
initLib(event.data.libc);
pipePtr = HANDLE.ptr(event.data.pipe);
readPipe(pipePtr.contents, event.data.charset);
break;
case "close":
pipePtr = HANDLE.ptr(event.data.pipe);
postMessage("closing stdin\n");
if (libFunc.CloseHandle(pipePtr.contents)) {
postMessage("ClosedOK");
}
else
postMessage("Could not close stdin handle");
break;
case "stop":
kernel32dll.close();
close();
break;
default:
throw("error: Unknown command"+event.data.msg+"\n");
}
return;
};

View File

@ -0,0 +1,15 @@
{
"name": "subprocess",
"license": "MPL 1.1/GPL 2.0/LGPL 2.1",
"author": "Alexandre Poirot",
"contributors": [
"Jan Gerber (original creator) <j@mailb.org>",
"Patrick Brunschwig (author of almost all code) <patrick@mozilla-enigmail.org>",
"Ramalingam Saravanan (from enigmail team) <svn@xmlterm.org>"
],
"version": "0.1.1",
"dependencies": [
"api-utils"
],
"description": "Addon-sdk package for subprocess xpcom components from enigmail. Allow to run process, manipulate stdin/out and kill it."
}

View File

@ -0,0 +1,144 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
const { Cc, Ci } = require("chrome");
const subprocess = require("subprocess");
const env = Cc["@mozilla.org/process/environment;1"].getService(Ci.nsIEnvironment);
// For now, only test on windows
if (env.get('OS') && env.get('OS').match(/Windows/)) {
exports.testWindows = function (test) {
test.waitUntilDone();
let envTestValue = "OK";
let gotStdout = false;
var p = subprocess.call({
// Retrieve windows cmd.exe path from env
command: env.get('ComSpec'),
// In order to execute a simple "echo" function
arguments: ['/C', 'echo %ENV_TEST%'], // ' & type CON' should display stdin, but doesn't work
// Printing an environnement variable set here by the parent process
environment: ['ENV_TEST='+envTestValue],
stdin: function(stdin) {
// Win32 command line is not really made for stdin
// So it doesn't seems to work as it's hard to retrieve stdin
stdin.write("stdin");
stdin.close();
},
stdout: function(data) {
test.assert(!gotStdout,"don't get stdout twice");
test.assertEqual(data,envTestValue+"\r\n","stdout contains the environment variable");
gotStdout = true;
},
stderr: function(data) {
test.fail("shouldn't get stderr");
},
done: function() {
test.assert(gotStdout, "got stdout before finished");
test.done();
},
mergeStderr: false
});
}
exports.testWindowsStderr = function (test) {
test.waitUntilDone();
let gotStderr = false;
var p = subprocess.call({
command: env.get('ComSpec'),
arguments: ['/C', 'nonexistent'],
stdout: function(data) {
test.fail("shouldn't get stdout");
},
stderr: function(data) {
test.assert(!gotStderr,"don't get stderr twice");
test.assertEqual(
data,
"'nonexistent' is not recognized as an internal or external command,\r\n" +
"operable program or batch file.\r\n",
"stderr contains the error message"
);
gotStderr = true;
},
done: function() {
test.assert(gotStderr, "got stderr before finished");
test.done();
},
mergeStderr: false
});
}
}
if (env.get('USER') && env.get('SHELL')) {
exports.testUnix = function (test) {
test.waitUntilDone();
let envTestValue = "OK";
let gotStdout = false;
var p = subprocess.call({
command: '/bin/sh',
// Print stdin and our env variable
//arguments: ['-c', 'echo $@ $ENV_TEST'],
environment: ['ENV_TEST='+envTestValue],
stdin: function(stdin) {
stdin.write("echo $ENV_TEST");
stdin.close();
},
stdout: function(data) {
test.assert(!gotStdout,"don't get stdout twice");
test.assertEqual(data,envTestValue+"\n","stdout contains the environment variable");
gotStdout = true;
},
stderr: function(data) {
test.fail("shouldn't get stderr");
},
done: function() {
test.assert(gotStdout, "got stdout before finished");
test.done();
},
mergeStderr: false
});
}
exports.testUnixStderr = function (test) {
test.waitUntilDone();
let gotStderr = false;
var p = subprocess.call({
// Hope that we don't have to give absolute path on linux ...
command: '/bin/sh',
arguments: ['nonexistent'],
stdout: function(data) {
test.fail("shouldn't get stdout");
},
stderr: function(data) {
test.assert(!gotStderr,"don't get stderr twice");
// There is two variant of error message
if (data == "/bin/sh: 0: Can't open nonexistent\n")
test.pass("stderr containes the expected error message");
else
test.assertEqual(data, "/bin/sh: nonexistent: No such file or directory\n",
"stderr contains the error message");
gotStderr = true;
},
done: function() {
test.assert(gotStderr, "got stderr before finished");
test.done();
},
mergeStderr: false
});
}
}

View File

@ -1046,13 +1046,13 @@ BrowserGlue.prototype = {
// forced migration (due to a major schema change).
// If the database is corrupt or has been newly created we should
// import bookmarks.
var dbStatus = PlacesUtils.history.databaseStatus;
var importBookmarks = !aInitialMigrationPerformed &&
let dbStatus = PlacesUtils.history.databaseStatus;
let importBookmarks = !aInitialMigrationPerformed &&
(dbStatus == PlacesUtils.history.DATABASE_STATUS_CREATE ||
dbStatus == PlacesUtils.history.DATABASE_STATUS_CORRUPT);
// Check if user or an extension has required to import bookmarks.html
var importBookmarksHTML = false;
let importBookmarksHTML = false;
try {
importBookmarksHTML =
Services.prefs.getBoolPref("browser.places.importBookmarksHTML");
@ -1063,7 +1063,7 @@ BrowserGlue.prototype = {
Task.spawn(function() {
// Check if Safe Mode or the user has required to restore bookmarks from
// default profile's bookmarks.html
var restoreDefaultBookmarks = false;
let restoreDefaultBookmarks = false;
try {
restoreDefaultBookmarks =
Services.prefs.getBoolPref("browser.bookmarks.restore_default_bookmarks");
@ -1091,10 +1091,7 @@ BrowserGlue.prototype = {
else {
// We have created a new database but we don't have any backup available
importBookmarks = true;
var dirService = Cc["@mozilla.org/file/directory_service;1"].
getService(Ci.nsIProperties);
var bookmarksHTMLFile = dirService.get("BMarks", Ci.nsILocalFile);
if (bookmarksHTMLFile.exists()) {
if (yield OS.File.exists(BookmarkHTMLUtils.defaultPath)) {
// If bookmarks.html is available in current profile import it...
importBookmarksHTML = true;
}
@ -1120,36 +1117,30 @@ BrowserGlue.prototype = {
// An import operation is about to run.
// Don't try to recreate smart bookmarks if autoExportHTML is true or
// smart bookmarks are disabled.
var autoExportHTML = false;
let autoExportHTML = false;
try {
autoExportHTML = Services.prefs.getBoolPref("browser.bookmarks.autoExportHTML");
} catch(ex) {}
var smartBookmarksVersion = 0;
let smartBookmarksVersion = 0;
try {
smartBookmarksVersion = Services.prefs.getIntPref("browser.places.smartBookmarksVersion");
} catch(ex) {}
if (!autoExportHTML && smartBookmarksVersion != -1)
Services.prefs.setIntPref("browser.places.smartBookmarksVersion", 0);
// Get bookmarks.html file location
var dirService = Cc["@mozilla.org/file/directory_service;1"].
getService(Ci.nsIProperties);
var bookmarksURI = null;
let bookmarksUrl = null;
if (restoreDefaultBookmarks) {
// User wants to restore bookmarks.html file from default profile folder
bookmarksURI = NetUtil.newURI("resource:///defaults/profile/bookmarks.html");
bookmarksUrl = "resource:///defaults/profile/bookmarks.html";
}
else {
var bookmarksFile = dirService.get("BMarks", Ci.nsILocalFile);
if (bookmarksFile.exists())
bookmarksURI = NetUtil.newURI(bookmarksFile);
else if (yield OS.File.exists(BookmarkHTMLUtils.defaultPath)) {
bookmarksUrl = OS.Path.toFileURI(BookmarkHTMLUtils.defaultPath);
}
if (bookmarksURI) {
if (bookmarksUrl) {
// Import from bookmarks.html file.
try {
BookmarkHTMLUtils.importFromURL(bookmarksURI.spec, true).then(null,
BookmarkHTMLUtils.importFromURL(bookmarksUrl, true).then(null,
function onFailure() {
Cu.reportError("Bookmarks.html file could be corrupt.");
}
@ -1240,7 +1231,7 @@ BrowserGlue.prototype = {
// can safely add a profile-before-change blocker.
AsyncShutdown.profileBeforeChange.addBlocker(
"Places: bookmarks.html",
() => BookmarkHTMLUtils.exportToFile(Services.dirsvc.get("BMarks", Ci.nsIFile))
() => BookmarkHTMLUtils.exportToFile(BookmarkHTMLUtils.defaultPath)
.then(null, Cu.reportError)
);
}

View File

@ -383,7 +383,7 @@ var PlacesOrganizer = {
let fpCallback = function fpCallback_done(aResult) {
if (aResult != Ci.nsIFilePicker.returnCancel) {
Components.utils.import("resource://gre/modules/BookmarkHTMLUtils.jsm");
BookmarkHTMLUtils.exportToFile(fp.file)
BookmarkHTMLUtils.exportToFile(fp.file.path)
.then(null, Components.utils.reportError);
}
};

View File

@ -164,11 +164,20 @@ if test -z "$PERL" -o "$PERL" = ":"; then
AC_MSG_ERROR([perl not found in \$PATH])
fi
if test -n "$GAIADIR" -a ! -d "$GAIADIR" ; then
AC_MSG_ERROR([GAIADIR '$GAIADIR' isn't a valid directory])
fi
AC_SUBST(GAIADIR)
if test -n "$GAIADIR" ; then
AC_DEFINE(PACKAGE_GAIA)
fi
if test -n "$FXOS_SIMULATOR" -a -z "$GAIADIR" ; then
AC_MSG_ERROR([FXOS_SIMULATOR=1 requires GAIADIR to be defined])
fi
AC_SUBST(FXOS_SIMULATOR)
MOZ_ARG_WITH_STRING(gonk,
[ --with-gonk=DIR
location of gonk dir],
@ -4160,6 +4169,7 @@ AC_SUBST(MOZ_BUILD_APP)
AC_SUBST(MOZ_PHOENIX)
AC_SUBST(MOZ_XULRUNNER)
AC_SUBST(MOZ_B2G)
AC_SUBST(MOZ_B2G_VERSION)
AC_DEFINE_UNQUOTED(MOZ_BUILD_APP,$MOZ_BUILD_APP)
@ -7740,6 +7750,7 @@ XPCOM_LIBS="$LIBXUL_LIBS"
if test "$OS_ARCH" = "WINNT"; then
GKMEDIAS_SHARED_LIBRARY=1
AC_DEFINE(GKMEDIAS_SHARED_LIBRARY)
fi
AC_SUBST(GKMEDIAS_SHARED_LIBRARY)

View File

@ -492,6 +492,8 @@ public:
void ListAttributes(FILE* out) const;
#endif
void Describe(nsAString& aOutDescription) const MOZ_OVERRIDE;
/*
* Attribute Mapping Helpers
*/
@ -514,6 +516,8 @@ public:
}
private:
void DescribeAttribute(uint32_t index, nsAString& aOutDescription) const;
static bool
FindAttributeDependence(const nsIAtom* aAttribute,
const MappedAttributeEntry* const aMaps[],

View File

@ -950,6 +950,15 @@ public:
bool aDumpAll = true) const = 0;
#endif
/**
* Append to aOutDescription a short (preferably one line) string
* describing the content.
* Currently implemented for elements only.
*/
virtual void Describe(nsAString& aOutDescription) const {
aOutDescription = NS_LITERAL_STRING("(not an element)");
}
enum ETabFocusType {
//eTabFocus_textControlsMask = (1<<0), // unused - textboxes always tabbable
eTabFocus_formElementsMask = (1<<1), // non-text form elements

View File

@ -2132,30 +2132,35 @@ Element::GetAttrCount() const
return mAttrsAndChildren.AttrCount();
}
void
Element::DescribeAttribute(uint32_t index, nsAString& aOutDescription) const
{
// name
mAttrsAndChildren.AttrNameAt(index)->GetQualifiedName(aOutDescription);
// value
aOutDescription.AppendLiteral("=\"");
nsAutoString value;
mAttrsAndChildren.AttrAt(index)->ToString(value);
for (int i = value.Length(); i >= 0; --i) {
if (value[i] == char16_t('"'))
value.Insert(char16_t('\\'), uint32_t(i));
}
aOutDescription.Append(value);
aOutDescription.AppendLiteral("\"");
}
#ifdef DEBUG
void
Element::ListAttributes(FILE* out) const
{
uint32_t index, count = mAttrsAndChildren.AttrCount();
for (index = 0; index < count; index++) {
nsAutoString buffer;
// name
mAttrsAndChildren.AttrNameAt(index)->GetQualifiedName(buffer);
// value
buffer.AppendLiteral("=\"");
nsAutoString value;
mAttrsAndChildren.AttrAt(index)->ToString(value);
for (int i = value.Length(); i >= 0; --i) {
if (value[i] == char16_t('"'))
value.Insert(char16_t('\\'), uint32_t(i));
}
buffer.Append(value);
buffer.AppendLiteral("\"");
nsAutoString attributeDescription;
DescribeAttribute(index, attributeDescription);
fputs(" ", out);
fputs(NS_LossyConvertUTF16toASCII(buffer).get(), out);
fputs(NS_LossyConvertUTF16toASCII(attributeDescription).get(), out);
}
}
@ -2279,6 +2284,21 @@ Element::DumpContent(FILE* out, int32_t aIndent,
}
#endif
void
Element::Describe(nsAString& aOutDescription) const
{
aOutDescription.Append(mNodeInfo->QualifiedName());
aOutDescription.AppendPrintf("@%p", (void *)this);
uint32_t index, count = mAttrsAndChildren.AttrCount();
for (index = 0; index < count; index++) {
aOutDescription.Append(' ');
nsAutoString attributeDescription;
DescribeAttribute(index, attributeDescription);
aOutDescription.Append(attributeDescription);
}
}
bool
Element::CheckHandleEventForLinksPrecondition(nsEventChainVisitor& aVisitor,
nsIURI** aURI) const

View File

@ -246,13 +246,10 @@ void VP8TrackEncoder::PrepareMutedFrame()
nsresult VP8TrackEncoder::PrepareRawFrame(VideoChunk &aChunk)
{
if (aChunk.mFrame.GetForceBlack()) {
if (aChunk.mFrame.GetForceBlack() || aChunk.IsNull()) {
PrepareMutedFrame();
} else {
layers::Image* img = aChunk.mFrame.GetImage();
if (NS_WARN_IF(!img)) {
return NS_ERROR_NULL_POINTER;
}
ImageFormat format = img->GetFormat();
if (format != ImageFormat::PLANAR_YCBCR) {
VP8LOG("Unsupported video format\n");

View File

@ -387,6 +387,7 @@ support-files =
[test_mediarecorder_record_startstopstart.html]
[test_mediarecorder_getencodeddata.html]
[test_mediarecorder_unsupported_src.html]
[test_mediarecorder_record_gum_video_timeslice.html]
[test_playback.html]
[test_seekLies.html]
[test_media_sniffer.html]

View File

@ -28,21 +28,17 @@ SpecialPowers.pushPrefEnv({"set": [["media.ogg.enabled", false]]},
SimpleTest.finish();
}
mediaRecorder.ondataavailable = function(evt) {
if (onErrorFired) {
ondataavailableFired = true;
ok(evt instanceof BlobEvent,
'Events fired from ondataavailable should be BlobEvent');
is(evt.type, 'dataavailable',
'Event type should dataavailable');
is(evt.data.size, 0,
'Blob data size received is equal to zero');
is(evt.data.type, expectedMimeType,
'Blob data received should have type = ' + expectedMimeType);
is(evt.target.mimeType, expectedMimeType,
'Mime type in ondataavailable = ' + expectedMimeType);
} else {
ok(false, 'should get onError first');
}
ondataavailableFired = true;
ok(evt instanceof BlobEvent,
'Events fired from ondataavailable should be BlobEvent');
is(evt.type, 'dataavailable',
'Event type should dataavailable');
is(evt.data.size, 0,
'Blob data size received is equal to zero');
is(evt.data.type, expectedMimeType,
'Blob data received should have type = ' + expectedMimeType);
is(evt.target.mimeType, expectedMimeType,
'Mime type in ondataavailable = ' + expectedMimeType);
}
mediaRecorder.onerror = function(evt) {
ok(evt instanceof RecordErrorEvent,

View File

@ -0,0 +1,89 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Test MediaRecorder Record gUM video with Timeslice</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<pre id="test">
<div id="content" style="display: none">
</div>
<script class="testbody" type="text/javascript">
function startTest() {
navigator.mozGetUserMedia({audio: true, video: true, fake: true}, function(stream) {
var dataAvailableCount = 0;
var onDataAvailableFirst = false;
mediaRecorder = new MediaRecorder(stream);
is(mediaRecorder.stream, stream,
'Media recorder stream = element stream at the start of recording');
mediaRecorder.onwarning = function() {
ok(false, 'onwarning unexpectedly fired');
};
mediaRecorder.onerror = function() {
ok(false, 'onerror unexpectedly fired');
};
mediaRecorder.onstop = function() {
ok(false, 'Unexpected onstop callback fired');
};
mediaRecorder.ondataavailable = function (evt) {
info('ondataavailable fired');
dataAvailableCount++;
ok(evt instanceof BlobEvent,
'Events fired from ondataavailable should be BlobEvent');
is(evt.type, 'dataavailable',
'Event type should dataavailable');
ok(evt.data.size >= 0,
'Blob data size received is greater than or equal to zero');
is(evt.data.type, 'video/webm',
'Blob data received should have type = ' + 'video/webm');
is(mediaRecorder.mimeType, 'video/webm',
'Mime type in ondataavailable = ' + mediaRecorder.mimeType);
// We'll stop recording upon the 1st blob being received
if (dataAvailableCount === 1) {
mediaRecorder.onstop = function (evt) {
info('onstop fired');
if (!onDataAvailableFirst) {
ok(false, 'onstop unexpectedly fired before ondataavailable');
}
ok(true, 'onstop fired successfully');
is(mediaRecorder.state, 'inactive',
'check recording status is inactive');
SimpleTest.finish();
};
mediaRecorder.stop();
is(mediaRecorder.state, 'inactive',
'Media recorder is inactive after being stopped');
} else if (dataAvailableCount === 2) {
// Ensure we've received at least two ondataavailable events before
// onstop
onDataAvailableFirst = true;
}
};
mediaRecorder.start(250);
is(mediaRecorder.state, 'recording', 'Media recorder should be recording');
}, function(err) {
ok(false, 'Unexpected error fired with: ' + err);
SimpleTest.finish();
});
}
SimpleTest.waitForExplicitFinish();
startTest();
</script>
</pre>
</body>
</html>

View File

@ -721,8 +721,19 @@ static const char js_werror_option_str[] = JS_OPTIONS_DOT_STR "werror";
static const char js_zeal_option_str[] = JS_OPTIONS_DOT_STR "gczeal";
static const char js_zeal_frequency_str[] = JS_OPTIONS_DOT_STR "gczeal.frequency";
#endif
static const char js_typeinfer_content_str[] = JS_OPTIONS_DOT_STR "typeinference.content";
static const char js_typeinfer_chrome_str[] = JS_OPTIONS_DOT_STR "typeinference.chrome";
static const char js_memlog_option_str[] = JS_OPTIONS_DOT_STR "mem.log";
static const char js_memnotify_option_str[] = JS_OPTIONS_DOT_STR "mem.notify";
static const char js_asmjs_content_str[] = JS_OPTIONS_DOT_STR "asmjs";
static const char js_baselinejit_content_str[] = JS_OPTIONS_DOT_STR "baselinejit.content";
static const char js_baselinejit_chrome_str[] = JS_OPTIONS_DOT_STR "baselinejit.chrome";
static const char js_baselinejit_eager_str[] = JS_OPTIONS_DOT_STR "baselinejit.unsafe_eager_compilation";
static const char js_ion_content_str[] = JS_OPTIONS_DOT_STR "ion.content";
static const char js_ion_chrome_str[] = JS_OPTIONS_DOT_STR "ion.chrome";
static const char js_ion_eager_str[] = JS_OPTIONS_DOT_STR "ion.unsafe_eager_compilation";
static const char js_parallel_parsing_str[] = JS_OPTIONS_DOT_STR "parallel_parsing";
static const char js_ion_parallel_compilation_str[] = JS_OPTIONS_DOT_STR "ion.parallel_compilation";
void
nsJSContext::JSOptionChangedCallback(const char *pref, void *data)
@ -745,6 +756,39 @@ nsJSContext::JSOptionChangedCallback(const char *pref, void *data)
nsCOMPtr<nsIDOMWindow> contentWindow(do_QueryInterface(global));
nsCOMPtr<nsIDOMChromeWindow> chromeWindow(do_QueryInterface(global));
bool useTypeInference = Preferences::GetBool((chromeWindow || !contentWindow) ?
js_typeinfer_chrome_str :
js_typeinfer_content_str);
bool useBaselineJIT = Preferences::GetBool((chromeWindow || !contentWindow) ?
js_baselinejit_chrome_str :
js_baselinejit_content_str);
bool useBaselineJITEager = Preferences::GetBool(js_baselinejit_eager_str);
bool useIon = Preferences::GetBool((chromeWindow || !contentWindow) ?
js_ion_chrome_str :
js_ion_content_str);
bool useIonEager = Preferences::GetBool(js_ion_eager_str);
bool useAsmJS = Preferences::GetBool(js_asmjs_content_str);
bool parallelParsing = Preferences::GetBool(js_parallel_parsing_str);
bool parallelIonCompilation = Preferences::GetBool(js_ion_parallel_compilation_str);
nsCOMPtr<nsIXULRuntime> xr = do_GetService(XULRUNTIME_SERVICE_CONTRACTID);
if (xr) {
bool safeMode = false;
xr->GetInSafeMode(&safeMode);
if (safeMode) {
useTypeInference = false;
useBaselineJIT = false;
useBaselineJITEager = false;
useIon = false;
useIonEager = false;
useAsmJS = false;
}
}
JS::ContextOptionsRef(cx).setTypeInference(useTypeInference)
.setBaseline(useBaselineJIT)
.setIon(useIon)
.setAsmJS(useAsmJS);
#ifdef DEBUG
// In debug builds, warnings are enabled in chrome context if
// javascript.options.strict.debug is true
@ -756,6 +800,15 @@ nsJSContext::JSOptionChangedCallback(const char *pref, void *data)
JS::ContextOptionsRef(cx).setWerror(Preferences::GetBool(js_werror_option_str));
::JS_SetParallelParsingEnabled(context->mContext, parallelParsing);
::JS_SetParallelIonCompilationEnabled(context->mContext, parallelIonCompilation);
::JS_SetGlobalJitCompilerOption(context->mContext, JSJITCOMPILER_BASELINE_USECOUNT_TRIGGER,
(useBaselineJITEager ? 0 : -1));
::JS_SetGlobalJitCompilerOption(context->mContext, JSJITCOMPILER_ION_USECOUNT_TRIGGER,
(useIonEager ? 0 : -1));
#ifdef JS_GC_ZEAL
int32_t zeal = Preferences::GetInt(js_zeal_option_str, -1);
int32_t frequency = Preferences::GetInt(js_zeal_frequency_str, JS_DEFAULT_ZEAL_FREQ);

View File

@ -35,7 +35,7 @@ NS_IMPL_CYCLE_COLLECTING_RELEASE(CallbackObject)
NS_IMPL_CYCLE_COLLECTION_CLASS(CallbackObject)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(CallbackObject)
tmp->DropCallback();
tmp->DropJSObjects();
NS_IMPL_CYCLE_COLLECTION_UNLINK(mIncumbentGlobal)
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(CallbackObject)
@ -44,6 +44,7 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(CallbackObject)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(CallbackObject)
NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mCallback)
NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mIncumbentJSGlobal)
NS_IMPL_CYCLE_COLLECTION_TRACE_END
CallbackObject::CallSetup::CallSetup(CallbackObject* aCallback,
@ -122,8 +123,17 @@ CallbackObject::CallSetup::CallSetup(CallbackObject* aCallback,
mAutoEntryScript.construct(globalObject, mIsMainThread, cx);
mAutoEntryScript.ref().SetWebIDLCallerPrincipal(webIDLCallerPrincipal);
if (aCallback->IncumbentGlobalOrNull()) {
mAutoIncumbentScript.construct(aCallback->IncumbentGlobalOrNull());
nsIGlobalObject* incumbent = aCallback->IncumbentGlobalOrNull();
if (incumbent) {
// The callback object traces its incumbent JS global, so in general it
// should be alive here. However, it's possible that we could run afoul
// of the same IPC global weirdness described above, wherein the
// nsIGlobalObject has severed its reference to the JS global. Let's just
// be safe here, so that nobody has to waste a day debugging gaia-ui tests.
if (!incumbent->GetGlobalJSObject()) {
return;
}
mAutoIncumbentScript.construct(incumbent);
}
// Unmark the callable (by invoking Callback() and not the CallbackPreserveColor()

View File

@ -57,7 +57,7 @@ public:
virtual ~CallbackObject()
{
DropCallback();
DropJSObjects();
}
JS::Handle<JSObject*> Callback() const
@ -121,28 +121,41 @@ private:
inline void Init(JSObject* aCallback, nsIGlobalObject* aIncumbentGlobal)
{
MOZ_ASSERT(aCallback && !mCallback);
// Set mCallback before we hold, on the off chance that a GC could somehow
// happen in there... (which would be pretty odd, granted).
// Set script objects before we hold, on the off chance that a GC could
// somehow happen in there... (which would be pretty odd, granted).
mCallback = aCallback;
if (aIncumbentGlobal) {
mIncumbentGlobal = aIncumbentGlobal;
mIncumbentJSGlobal = aIncumbentGlobal->GetGlobalJSObject();
}
mozilla::HoldJSObjects(this);
mIncumbentGlobal = aIncumbentGlobal;
}
CallbackObject(const CallbackObject&) MOZ_DELETE;
CallbackObject& operator =(const CallbackObject&) MOZ_DELETE;
protected:
void DropCallback()
void DropJSObjects()
{
MOZ_ASSERT_IF(mIncumbentJSGlobal, mCallback);
if (mCallback) {
mCallback = nullptr;
mIncumbentJSGlobal = nullptr;
mozilla::DropJSObjects(this);
}
}
JS::Heap<JSObject*> mCallback;
// Ideally, we'd just hold a reference to the nsIGlobalObject, since that's
// what we need to pass to AutoIncumbentScript. Unfortunately, that doesn't
// hold the actual JS global alive. So we maintain an additional pointer to
// the JS global itself so that we can trace it.
//
// At some point we should consider trying to make native globals hold their
// scripted global alive, at which point we can get rid of the duplication
// here.
nsCOMPtr<nsIGlobalObject> mIncumbentGlobal;
JS::TenuredHeap<JSObject*> mIncumbentJSGlobal;
class MOZ_STACK_CLASS CallSetup
{

View File

@ -34,7 +34,6 @@
#include "nsISystemMessagesInternal.h"
#include "nsITimer.h"
#include "nsServiceManagerUtils.h"
#include "nsThreadUtils.h"
#include "nsXPCOM.h"
#if defined(MOZ_WIDGET_GONK)
@ -132,46 +131,53 @@ GetAllBluetoothActors(InfallibleTArray<BluetoothParent*>& aActors)
} // anonymous namespace
class BluetoothService::ToggleBtAck : public nsRunnable
BluetoothService::ToggleBtAck::ToggleBtAck(bool aEnabled)
: mEnabled(aEnabled)
{
public:
ToggleBtAck(bool aEnabled)
: mEnabled(aEnabled)
{
MOZ_ASSERT(!NS_IsMainThread());
MOZ_ASSERT(!NS_IsMainThread());
}
NS_METHOD
BluetoothService::ToggleBtAck::Run()
{
MOZ_ASSERT(NS_IsMainThread());
// This is requested in Bug 836516. With settings this property, WLAN
// firmware could be aware of Bluetooth has been turned on/off, so that the
// mecahnism of handling coexistence of WIFI and Bluetooth could be started.
//
// In the future, we may have our own way instead of setting a system
// property to let firmware developers be able to sense that Bluetooth has
// been toggled.
#if defined(MOZ_WIDGET_GONK)
if (property_set(PROP_BLUETOOTH_ENABLED, mEnabled ? "true" : "false") != 0) {
BT_WARNING("Failed to set bluetooth enabled property");
}
#endif
NS_IMETHOD Run()
{
MOZ_ASSERT(NS_IsMainThread());
NS_ENSURE_TRUE(sBluetoothService, NS_OK);
if (sInShutdown) {
sBluetoothService = nullptr;
return NS_OK;
}
// Update mEnabled of BluetoothService object since
// StartInternal/StopInternal have been already done.
sBluetoothService->SetEnabled(mEnabled);
sToggleInProgress = false;
nsAutoString signalName;
signalName = mEnabled ? NS_LITERAL_STRING("Enabled")
: NS_LITERAL_STRING("Disabled");
BluetoothSignal signal(signalName, NS_LITERAL_STRING(KEY_MANAGER), true);
sBluetoothService->DistributeSignal(signal);
// Event 'AdapterAdded' has to be fired after firing 'Enabled'
sBluetoothService->TryFiringAdapterAdded();
NS_ENSURE_TRUE(sBluetoothService, NS_OK);
if (sInShutdown) {
sBluetoothService = nullptr;
return NS_OK;
}
private:
bool mEnabled;
};
// Update mEnabled of BluetoothService object since
// StartInternal/StopInternal have been already done.
sBluetoothService->SetEnabled(mEnabled);
sToggleInProgress = false;
nsAutoString signalName;
signalName = mEnabled ? NS_LITERAL_STRING("Enabled")
: NS_LITERAL_STRING("Disabled");
BluetoothSignal signal(signalName, NS_LITERAL_STRING(KEY_MANAGER), true);
sBluetoothService->DistributeSignal(signal);
// Event 'AdapterAdded' has to be fired after firing 'Enabled'
sBluetoothService->TryFiringAdapterAdded();
return NS_OK;
}
class BluetoothService::ToggleBtTask : public nsRunnable
{
@ -200,6 +206,10 @@ public:
*/
if (!mIsStartup && mEnabled == sBluetoothService->IsEnabledInternal()) {
BT_WARNING("Bluetooth has already been enabled/disabled before.");
nsCOMPtr<nsIRunnable> ackTask = new BluetoothService::ToggleBtAck(mEnabled);
if (NS_FAILED(NS_DispatchToMainThread(ackTask))) {
BT_WARNING("Failed to dispatch to main thread!");
}
} else {
// Switch on/off bluetooth
if (mEnabled) {
@ -215,24 +225,6 @@ public:
}
}
// This is requested in Bug 836516. With settings this property, WLAN
// firmware could be aware of Bluetooth has been turned on/off, so that the
// mecahnism of handling coexistence of WIFI and Bluetooth could be started.
//
// In the future, we may have our own way instead of setting a system
// property to let firmware developers be able to sense that Bluetooth has
// been toggled.
#if defined(MOZ_WIDGET_GONK)
if (property_set(PROP_BLUETOOTH_ENABLED, mEnabled ? "true" : "false") != 0) {
BT_WARNING("Failed to set bluetooth enabled property");
}
#endif
nsCOMPtr<nsIRunnable> ackTask = new BluetoothService::ToggleBtAck(mEnabled);
if (NS_FAILED(NS_DispatchToMainThread(ackTask))) {
BT_WARNING("Failed to dispatch to main thread!");
}
return NS_OK;
}

View File

@ -16,6 +16,7 @@
#include "nsIObserver.h"
#include "nsIThread.h"
#include "nsTObserverArray.h"
#include "nsThreadUtils.h"
namespace mozilla {
namespace ipc {
@ -35,9 +36,6 @@ typedef mozilla::ObserverList<BluetoothSignal> BluetoothSignalObserverList;
class BluetoothService : public nsIObserver
, public BluetoothSignalObserver
{
class ToggleBtAck;
friend class ToggleBtAck;
class ToggleBtTask;
friend class ToggleBtTask;
@ -45,6 +43,17 @@ class BluetoothService : public nsIObserver
friend class StartupTask;
public:
class ToggleBtAck : public nsRunnable
{
public:
ToggleBtAck(bool aEnabled);
NS_IMETHOD Run();
private:
bool mEnabled;
};
friend class ToggleBtAck;
NS_DECL_ISUPPORTS
NS_DECL_NSIOBSERVER

View File

@ -741,9 +741,18 @@ BluetoothServiceBluedroid::StartInternal()
nsresult ret = StartStopGonkBluetooth(true);
if (NS_FAILED(ret)) {
nsCOMPtr<nsIRunnable> ackTask = new BluetoothService::ToggleBtAck(false);
if (NS_FAILED(NS_DispatchToMainThread(ackTask))) {
BT_WARNING("Failed to dispatch to main thread!");
}
BT_LOGR("Error");
}
nsCOMPtr<nsIRunnable> ackTask = new BluetoothService::ToggleBtAck(true);
if (NS_FAILED(NS_DispatchToMainThread(ackTask))) {
BT_WARNING("Failed to dispatch to main thread!");
}
return ret;
}
@ -754,9 +763,18 @@ BluetoothServiceBluedroid::StopInternal()
nsresult ret = StartStopGonkBluetooth(false);
if (NS_FAILED(ret)) {
nsCOMPtr<nsIRunnable> ackTask = new BluetoothService::ToggleBtAck(true);
if (NS_FAILED(NS_DispatchToMainThread(ackTask))) {
BT_WARNING("Failed to dispatch to main thread!");
}
BT_LOGR("Error");
}
nsCOMPtr<nsIRunnable> ackTask = new BluetoothService::ToggleBtAck(false);
if (NS_FAILED(NS_DispatchToMainThread(ackTask))) {
BT_WARNING("Failed to dispatch to main thread!");
}
return ret;
}

View File

@ -1889,12 +1889,20 @@ BluetoothDBusService::StartInternal()
if (sDBusConnection) {
// This should actually not happen.
BT_WARNING("Bluetooth is already running");
nsCOMPtr<nsIRunnable> ackTask = new BluetoothService::ToggleBtAck(true);
if (NS_FAILED(NS_DispatchToMainThread(ackTask))) {
BT_WARNING("Failed to dispatch to main thread!");
}
return NS_OK;
}
#ifdef MOZ_WIDGET_GONK
if (!sBluedroid.Enable()) {
BT_WARNING("Bluetooth not available.");
nsCOMPtr<nsIRunnable> ackTask = new BluetoothService::ToggleBtAck(false);
if (NS_FAILED(NS_DispatchToMainThread(ackTask))) {
BT_WARNING("Failed to dispatch to main thread!");
}
return NS_ERROR_FAILURE;
}
#endif
@ -1903,6 +1911,10 @@ BluetoothDBusService::StartInternal()
nsresult rv = connection->EstablishDBusConnection();
if (NS_FAILED(rv)) {
BT_WARNING("Failed to establish connection to BlueZ daemon");
nsCOMPtr<nsIRunnable> ackTask = new BluetoothService::ToggleBtAck(false);
if (NS_FAILED(NS_DispatchToMainThread(ackTask))) {
BT_WARNING("Failed to dispatch to main thread!");
}
return NS_ERROR_FAILURE;
}
@ -1926,6 +1938,10 @@ BluetoothDBusService::StartInternal()
if (!dbus_connection_add_filter(connection->GetConnection(),
EventFilter, nullptr, nullptr)) {
BT_WARNING("Cannot create DBus Event Filter for DBus Thread!");
nsCOMPtr<nsIRunnable> ackTask = new BluetoothService::ToggleBtAck(false);
if (NS_FAILED(NS_DispatchToMainThread(ackTask))) {
BT_WARNING("Failed to dispatch to main thread!");
}
return NS_ERROR_FAILURE;
}
@ -1938,6 +1954,11 @@ BluetoothDBusService::StartInternal()
Task* task = new StartDBusConnectionTask(connection, sAdapterPath.IsEmpty());
DispatchToDBusThread(task);
nsCOMPtr<nsIRunnable> ackTask = new BluetoothService::ToggleBtAck(true);
if (NS_FAILED(NS_DispatchToMainThread(ackTask))) {
BT_WARNING("Failed to dispatch to main thread!");
}
return NS_OK;
}
@ -1985,6 +2006,10 @@ BluetoothDBusService::StopInternal()
}
if (!sDBusConnection) {
nsCOMPtr<nsIRunnable> ackTask = new BluetoothService::ToggleBtAck(false);
if (NS_FAILED(NS_DispatchToMainThread(ackTask))) {
BT_WARNING("Failed to dispatch to main thread!");
}
return NS_OK;
}
@ -2032,10 +2057,18 @@ BluetoothDBusService::StopInternal()
#ifdef MOZ_WIDGET_GONK
MOZ_ASSERT(sBluedroid.IsEnabled());
if (!sBluedroid.Disable()) {
nsCOMPtr<nsIRunnable> ackTask = new BluetoothService::ToggleBtAck(true);
if (NS_FAILED(NS_DispatchToMainThread(ackTask))) {
BT_WARNING("Failed to dispatch to main thread!");
}
return NS_ERROR_FAILURE;
}
#endif
nsCOMPtr<nsIRunnable> ackTask = new BluetoothService::ToggleBtAck(false);
if (NS_FAILED(NS_DispatchToMainThread(ackTask))) {
BT_WARNING("Failed to dispatch to main thread!");
}
return NS_OK;
}

View File

@ -11,14 +11,18 @@ function waitEitherEnabledOrDisabled() {
let deferred = Promise.defer();
function onEnabledDisabled(aEvent) {
bluetoothManager.removeEventListener("enabled", onEnabledDisabled);
bluetoothManager.removeEventListener("adapteradded", onEnabledDisabled);
bluetoothManager.removeEventListener("disabled", onEnabledDisabled);
ok(true, "Got event " + aEvent.type);
deferred.resolve(aEvent.type === "enabled");
deferred.resolve(aEvent.type === "adapteradded");
}
bluetoothManager.addEventListener("enabled", onEnabledDisabled);
// Listen 'adapteradded' rather than 'enabled' since the current API can't
// disable BT before the BT adapter is initialized.
// We should listen to 'enabled' when gecko can handle the case I mentioned
// above, please refer to the follow-up bug 973482.
bluetoothManager.addEventListener("adapteradded", onEnabledDisabled);
bluetoothManager.addEventListener("disabled", onEnabledDisabled);
return deferred.promise;
@ -39,7 +43,7 @@ function test(aEnabled) {
log(" Examine results " + JSON.stringify(aResults));
is(bluetoothManager.enabled, aEnabled, "bluetoothManager.enabled");
is(aResults[1], aEnabled, "'enabled' event received");
is(aResults[1], aEnabled, "'adapteradded' event received");
if (bluetoothManager.enabled === aEnabled && aResults[1] === aEnabled) {
deferred.resolve();

View File

@ -148,7 +148,7 @@ namespace {
const uint32_t kNoIndex = uint32_t(-1);
const JS::ContextOptions kRequiredContextOptions =
const JS::ContextOptions kRequiredJSContextOptions =
JS::ContextOptions().setDontReportUncaught(true)
.setNoScriptRval(true);
@ -300,7 +300,7 @@ GenerateSharedWorkerKey(const nsACString& aScriptSpec, const nsACString& aName,
}
void
LoadRuntimeAndContextOptions(const char* aPrefName, void* /* aClosure */)
LoadJSContextOptions(const char* aPrefName, void* /* aClosure */)
{
AssertIsOnMainThread();
@ -330,47 +330,51 @@ LoadRuntimeAndContextOptions(const char* aPrefName, void* /* aClosure */)
}
#endif
// Runtime options.
JS::RuntimeOptions runtimeOptions;
if (GetWorkerPref<bool>(NS_LITERAL_CSTRING("asmjs"))) {
runtimeOptions.setAsmJS(true);
}
if (GetWorkerPref<bool>(NS_LITERAL_CSTRING("typeinference"))) {
runtimeOptions.setTypeInference(true);
}
if (GetWorkerPref<bool>(NS_LITERAL_CSTRING("baselinejit"))) {
runtimeOptions.setBaseline(true);
}
if (GetWorkerPref<bool>(NS_LITERAL_CSTRING("ion"))) {
runtimeOptions.setIon(true);
}
// Common options.
JS::ContextOptions commonContextOptions = kRequiredContextOptions;
JS::ContextOptions commonOptions = kRequiredJSContextOptions;
if (GetWorkerPref<bool>(NS_LITERAL_CSTRING("strict"))) {
commonContextOptions.setExtraWarnings(true);
commonOptions.setExtraWarnings(true);
}
if (GetWorkerPref<bool>(NS_LITERAL_CSTRING("werror"))) {
commonContextOptions.setWerror(true);
commonOptions.setWerror(true);
}
if (GetWorkerPref<bool>(NS_LITERAL_CSTRING("asmjs"))) {
commonOptions.setAsmJS(true);
}
// Content options.
JS::ContextOptions contentContextOptions = commonContextOptions;
JS::ContextOptions contentOptions = commonOptions;
if (GetWorkerPref<bool>(NS_LITERAL_CSTRING("baselinejit.content"))) {
contentOptions.setBaseline(true);
}
if (GetWorkerPref<bool>(NS_LITERAL_CSTRING("ion.content"))) {
contentOptions.setIon(true);
}
if (GetWorkerPref<bool>(NS_LITERAL_CSTRING("typeinference.content"))) {
contentOptions.setTypeInference(true);
}
// Chrome options.
JS::ContextOptions chromeContextOptions = commonContextOptions;
JS::ContextOptions chromeOptions = commonOptions;
if (GetWorkerPref<bool>(NS_LITERAL_CSTRING("baselinejit.chrome"))) {
chromeOptions.setBaseline(true);
}
if (GetWorkerPref<bool>(NS_LITERAL_CSTRING("ion.chrome"))) {
chromeOptions.setIon(true);
}
if (GetWorkerPref<bool>(NS_LITERAL_CSTRING("typeinference.chrome"))) {
chromeOptions.setTypeInference(true);
}
#ifdef DEBUG
if (GetWorkerPref<bool>(NS_LITERAL_CSTRING("strict.debug"))) {
chromeContextOptions.setExtraWarnings(true);
chromeOptions.setExtraWarnings(true);
}
#endif
RuntimeService::SetDefaultRuntimeAndContextOptions(runtimeOptions,
contentContextOptions,
chromeContextOptions);
RuntimeService::SetDefaultJSContextOptions(contentOptions, chromeOptions);
if (rts) {
rts->UpdateAllWorkerRuntimeAndContextOptions();
rts->UpdateAllWorkerJSContextOptions();
}
}
@ -767,8 +771,6 @@ CreateJSContextForWorker(WorkerPrivate* aWorkerPrivate, JSRuntime* aRuntime)
JSSettings settings;
aWorkerPrivate->CopyJSSettings(settings);
JS::RuntimeOptionsRef(aRuntime) = settings.runtimeOptions;
JSSettings::JSGCSettingsArray& gcSettings = settings.gcSettings;
// This is the real place where we set the max memory for the runtime.
@ -1612,11 +1614,10 @@ RuntimeService::Init()
// Initialize JSSettings.
if (!sDefaultJSSettings.gcSettings[0].IsSet()) {
sDefaultJSSettings.runtimeOptions = JS::RuntimeOptions();
sDefaultJSSettings.chrome.contextOptions = kRequiredContextOptions;
sDefaultJSSettings.chrome.contextOptions = kRequiredJSContextOptions;
sDefaultJSSettings.chrome.maxScriptRuntime = -1;
sDefaultJSSettings.chrome.compartmentOptions.setVersion(JSVERSION_LATEST);
sDefaultJSSettings.content.contextOptions = kRequiredContextOptions;
sDefaultJSSettings.content.contextOptions = kRequiredJSContextOptions;
sDefaultJSSettings.content.maxScriptRuntime = MAX_SCRIPT_RUN_TIME_SEC;
#ifdef JS_GC_ZEAL
sDefaultJSSettings.gcZealFrequency = JS_DEFAULT_ZEAL_FREQ;
@ -1691,13 +1692,13 @@ RuntimeService::Init()
PREF_DOM_WINDOW_DUMP_ENABLED,
reinterpret_cast<void *>(WORKERPREF_DUMP))) ||
#endif
NS_FAILED(Preferences::RegisterCallback(LoadRuntimeAndContextOptions,
NS_FAILED(Preferences::RegisterCallback(LoadJSContextOptions,
PREF_JS_OPTIONS_PREFIX,
nullptr)) ||
NS_FAILED(Preferences::RegisterCallbackAndCall(
LoadRuntimeAndContextOptions,
PREF_WORKERS_OPTIONS_PREFIX,
nullptr)) ||
LoadJSContextOptions,
PREF_WORKERS_OPTIONS_PREFIX,
nullptr)) ||
NS_FAILED(Preferences::RegisterCallbackAndCall(
JSVersionChanged,
PREF_WORKERS_LATEST_JS_VERSION,
@ -1844,10 +1845,10 @@ RuntimeService::Cleanup()
if (NS_FAILED(Preferences::UnregisterCallback(JSVersionChanged,
PREF_WORKERS_LATEST_JS_VERSION,
nullptr)) ||
NS_FAILED(Preferences::UnregisterCallback(LoadRuntimeAndContextOptions,
NS_FAILED(Preferences::UnregisterCallback(LoadJSContextOptions,
PREF_JS_OPTIONS_PREFIX,
nullptr)) ||
NS_FAILED(Preferences::UnregisterCallback(LoadRuntimeAndContextOptions,
NS_FAILED(Preferences::UnregisterCallback(LoadJSContextOptions,
PREF_WORKERS_OPTIONS_PREFIX,
nullptr)) ||
#if DUMP_CONTROLLED_BY_PREF
@ -2229,10 +2230,9 @@ RuntimeService::NoteIdleThread(WorkerThread* aThread)
}
void
RuntimeService::UpdateAllWorkerRuntimeAndContextOptions()
RuntimeService::UpdateAllWorkerJSContextOptions()
{
BROADCAST_ALL_WORKERS(UpdateRuntimeAndContextOptions,
sDefaultJSSettings.runtimeOptions,
BROADCAST_ALL_WORKERS(UpdateJSContextOptions,
sDefaultJSSettings.content.contextOptions,
sDefaultJSSettings.chrome.contextOptions);
}

View File

@ -174,19 +174,16 @@ public:
}
static void
SetDefaultRuntimeAndContextOptions(
const JS::RuntimeOptions& aRuntimeOptions,
const JS::ContextOptions& aContentCxOptions,
const JS::ContextOptions& aChromeCxOptions)
SetDefaultJSContextOptions(const JS::ContextOptions& aContentOptions,
const JS::ContextOptions& aChromeOptions)
{
AssertIsOnMainThread();
sDefaultJSSettings.runtimeOptions = aRuntimeOptions;
sDefaultJSSettings.content.contextOptions = aContentCxOptions;
sDefaultJSSettings.chrome.contextOptions = aChromeCxOptions;
sDefaultJSSettings.content.contextOptions = aContentOptions;
sDefaultJSSettings.chrome.contextOptions = aChromeOptions;
}
void
UpdateAllWorkerRuntimeAndContextOptions();
UpdateAllWorkerJSContextOptions();
void
UpdateAllWorkerPreference(WorkerPreference aPref, bool aValue);

View File

@ -1515,32 +1515,25 @@ private:
}
};
class UpdateRuntimeAndContextOptionsRunnable MOZ_FINAL : public WorkerControlRunnable
class UpdateJSContextOptionsRunnable MOZ_FINAL : public WorkerControlRunnable
{
JS::RuntimeOptions mRuntimeOptions;
JS::ContextOptions mContentCxOptions;
JS::ContextOptions mChromeCxOptions;
JS::ContextOptions mContentOptions;
JS::ContextOptions mChromeOptions;
public:
UpdateRuntimeAndContextOptionsRunnable(
WorkerPrivate* aWorkerPrivate,
const JS::RuntimeOptions& aRuntimeOptions,
const JS::ContextOptions& aContentCxOptions,
const JS::ContextOptions& aChromeCxOptions)
UpdateJSContextOptionsRunnable(WorkerPrivate* aWorkerPrivate,
const JS::ContextOptions& aContentOptions,
const JS::ContextOptions& aChromeOptions)
: WorkerControlRunnable(aWorkerPrivate, WorkerThreadUnchangedBusyCount),
mRuntimeOptions(aRuntimeOptions),
mContentCxOptions(aContentCxOptions),
mChromeCxOptions(aChromeCxOptions)
mContentOptions(aContentOptions), mChromeOptions(aChromeOptions)
{ }
private:
virtual bool
WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) MOZ_OVERRIDE
{
aWorkerPrivate->UpdateRuntimeAndContextOptionsInternal(aCx,
mRuntimeOptions,
mContentCxOptions,
mChromeCxOptions);
aWorkerPrivate->UpdateJSContextOptionsInternal(aCx, mContentOptions,
mChromeOptions);
return true;
}
};
@ -2842,26 +2835,22 @@ WorkerPrivateParent<Derived>::GetInnerWindowId()
template <class Derived>
void
WorkerPrivateParent<Derived>::UpdateRuntimeAndContextOptions(
JSContext* aCx,
const JS::RuntimeOptions& aRuntimeOptions,
const JS::ContextOptions& aContentCxOptions,
const JS::ContextOptions& aChromeCxOptions)
WorkerPrivateParent<Derived>::UpdateJSContextOptions(
JSContext* aCx,
const JS::ContextOptions& aContentOptions,
const JS::ContextOptions& aChromeOptions)
{
AssertIsOnParentThread();
{
MutexAutoLock lock(mMutex);
mJSSettings.runtimeOptions = aRuntimeOptions;
mJSSettings.content.contextOptions = aContentCxOptions;
mJSSettings.chrome.contextOptions = aChromeCxOptions;
mJSSettings.content.contextOptions = aContentOptions;
mJSSettings.chrome.contextOptions = aChromeOptions;
}
nsRefPtr<UpdateRuntimeAndContextOptionsRunnable> runnable =
new UpdateRuntimeAndContextOptionsRunnable(ParentAsWorkerPrivate(),
aRuntimeOptions,
aContentCxOptions,
aChromeCxOptions);
nsRefPtr<UpdateJSContextOptionsRunnable> runnable =
new UpdateJSContextOptionsRunnable(ParentAsWorkerPrivate(), aContentOptions,
aChromeOptions);
if (!runnable->Dispatch(aCx)) {
NS_WARNING("Failed to update worker context options!");
JS_ClearPendingException(aCx);
@ -5499,21 +5488,17 @@ WorkerPrivate::RescheduleTimeoutTimer(JSContext* aCx)
}
void
WorkerPrivate::UpdateRuntimeAndContextOptionsInternal(
JSContext* aCx,
const JS::RuntimeOptions& aRuntimeOptions,
const JS::ContextOptions& aContentCxOptions,
const JS::ContextOptions& aChromeCxOptions)
WorkerPrivate::UpdateJSContextOptionsInternal(JSContext* aCx,
const JS::ContextOptions& aContentOptions,
const JS::ContextOptions& aChromeOptions)
{
AssertIsOnWorkerThread();
JS::RuntimeOptionsRef(aCx) = aRuntimeOptions;
JS::ContextOptionsRef(aCx) = IsChromeWorker() ? aChromeCxOptions : aContentCxOptions;
JS::ContextOptionsRef(aCx) = IsChromeWorker() ? aChromeOptions : aContentOptions;
for (uint32_t index = 0; index < mChildWorkers.Length(); index++) {
mChildWorkers[index]->UpdateRuntimeAndContextOptions(aCx, aRuntimeOptions,
aContentCxOptions,
aChromeCxOptions);
mChildWorkers[index]->UpdateJSContextOptions(aCx, aContentOptions,
aChromeOptions);
}
}

View File

@ -389,10 +389,8 @@ public:
GetInnerWindowId();
void
UpdateRuntimeAndContextOptions(JSContext* aCx,
const JS::RuntimeOptions& aRuntimeOptions,
const JS::ContextOptions& aContentCxOptions,
const JS::ContextOptions& aChromeCxOptions);
UpdateJSContextOptions(JSContext* aCx, const JS::ContextOptions& aChromeOptions,
const JS::ContextOptions& aContentOptions);
void
UpdatePreference(JSContext* aCx, WorkerPreference aPref, bool aValue);
@ -908,11 +906,8 @@ public:
}
void
UpdateRuntimeAndContextOptionsInternal(
JSContext* aCx,
const JS::RuntimeOptions& aRuntimeOptions,
const JS::ContextOptions& aContentCxOptions,
const JS::ContextOptions& aChromeCxOptions);
UpdateJSContextOptionsInternal(JSContext* aCx, const JS::ContextOptions& aContentOptions,
const JS::ContextOptions& aChromeOptions);
void
UpdatePreferenceInternal(JSContext* aCx, WorkerPreference aPref, bool aValue);

View File

@ -107,7 +107,6 @@ struct JSSettings
JSContentChromeSettings chrome;
JSContentChromeSettings content;
JSGCSettingsArray gcSettings;
JS::RuntimeOptions runtimeOptions;
#ifdef JS_GC_ZEAL
uint8_t gcZeal;

View File

@ -9186,442 +9186,456 @@
< cider/S
---
> cider/MS
17072d22881
16652a22463
> ciphertext/S
17072d22882
< cocain/M
17102,17103c22911
17102,17103c22912
< cocksucker's
< cocksucker/S!
---
> cocksucker/SM!
17755c23563
17755c23564
< confer/S
---
> confer/SB
17800a23609
17800a23610
> conformant
18151d23959
18151d23960
< convenor/S
18206c24014
18206c24015
< cookie/M
---
> cookie/SM
18467a24276
18467a24277
> could've
19035a24845
18999a24810
> cryptologist/MS
19000a24812
> cryptosystem/S
19035a24848
> cul-de-sac
19246c25056
19246c25059
< cysteine
---
> cysteine/M
19935a25746
19935a25749
> dequeue/DSG
20196,20197c26007,26008
20196,20197c26010,26011
< dialog/SM
< dialogue/SM
---
> dialog/SMGD
> dialogue/SMRGD
20481a26293
20481a26296
> disclose/DSG
20830c26642
20830c26645
< dogie/M
---
> dogie/SM
20895a26708
20895a26711
> donator/MS
21820a27634
21820a27637
> elicitor/MS
22071a27886
22071a27889
> encyclopaedia
22196a28012
22196a28015
> enqueue/DSG
22556a28373
22556a28376
> estoppel
22638c28455
22638c28458
< euthanize
---
> euthanize/DSG
22719a28537
22719a28540
> exabyte/MS
22947a28766
22947a28769
> experimentalism
23207,23208d29025
23207,23208d29028
< faecal
< faeces/M
23215c29032
23215c29035
< faggoting's
---
> faggot/SMG
23701a29519
23701a29522
> filesystem/MS
24155c29973
24155c29976
< fluidized
---
> fluidize/DSG
24216a30035
24216a30038
> foci
24736d30554
24736d30557
< frier/M
24855,24856c30673,30674
24855,24856c30676,30677
< fucker/M!
< fuckhead/S!
---
> fucker/SM!
> fuckhead/SM!
24953d30770
24953d30773
< furore/MS
25125c30942
25125c30945
< gaolbird/S
---
> gaolbirds
25180d30996
25180d30999
< gasolene/M
25190a31007
25190a31010
> gastroenterologist/M
25262c31079
25262c31082
< geezer/M
---
> geezer/MS
25327c31144
25327c31147
< genomic
---
> genomic/S
25462a31280
25462a31283
> gigabit/MS
25464a31283,31285
25464a31286,31288
> gigajoule/MS
> gigapixel/MS
> gigawatt/MS
25560d31380
25560d31383
< glamourize/DSG
25674c31494
25674c31497
< glycerine's
---
> glycerine/M
25905c31725
25905c31728
< gram/MS
---
> gram/KMS
25909d31728
25909d31731
< gramme/SM
26063c31882,31883
26063c31885,31886
< greybeard
---
> grey/MDRTGSP
> greybeard/SM
26066c31886
26066c31889
< greyness
---
> greyness/M
26246,26247d32065
26246,26247d32068
< guerilla's
< guerillas
26432,26436d32249
26432,26436d32252
< haemoglobin's
< haemophilia/M
< haemorrhage/DSMG
< haemorrhoid/S
< haemorrhoids/M
27167c32980
27167c32983
< hexane
---
> hexane/SM
27273a33087
27273a33090
> hippopotami
27875d33688
27875d33691
< hyaena/SM
28017c33830
28017c33833
< iPod/M
---
> iPod/MS
28105a33919
28105a33922
> idolator/SM
28513c34327
28513c34330
< inbound
---
> inbound/s
28650a34465
28650a34468
> indices
28812d34626
28812d34629
< inflexion/SM
29216a35031
29216a35034
> intern/GDL
29266a35082
29266a35085
> interruptible/U
29272a35089,35092
29272a35092,35095
> intersex
> intersexual/MS
> intersexualism
> intersexuality
29724c35544
29724c35547
< jewellery's
---
> jewellery/M
29870a35691
29870a35694
> judgement/MS
30066c35887
30066c35890
< kiddie/M
---
> kiddie/SM
30262,30263c36083
30262,30263c36086
< kraut's
< kraut/S!
---
> kraut/MS!
30665a36486
30665a36489
> lector/MS
31031c36852
31031c36855
< linguini's
---
> linguini/M
31151,31152c36972
31034c36858
< linguistically
---
> linguistical/Y
31151,31152c36975
< liver's
< liver/S
---
> liver/MS
32230c38050
32230c38053
< meanie/M
---
> meanie/MS
32317,32318c38137
32317,32318c38140
< megadeath/M
< megadeaths
---
> megadeath/SM
32320c38139
32320c38142
< megajoules
---
> megajoule/SM
32329c38148
32329c38151
< megapixel/S
---
> megapixel/MS
32708a38528
32708a38531
> might've
32717a38538
32717a38541
> migrator/SM
32760a38582
32760a38585
> millennia
32777d38598
32777d38601
< millionnaire/M
32934a38756
32934a38759
> miscommunication/S
32991a38814
32991a38817
> misjudgement/MS
33784a39608
33784a39611
> must've
33963c39787
33963c39790
< native/MS
---
> native/MSY
34169,34171c39993,39994
34169,34171c39996,39997
< neurone/S
< neurophysiology
< neuroscience
---
> neurophysiology/M
> neuroscience/MS
34275c40098
34275c40101
< nightie/M
---
> nightie/SM
35104a40928
35104a40931
> octopi
35219d41042
35219d41045
< oleomargarin/M
35226a41050
35226a41053
> oligo
35913c41737
35913c41740
< oversize/D
---
> oversize
36056,36059d41879
36056,36059d41882
< paederast/S
< paediatrician's
< paediatricians
< paediatrics/M
36291a42112
36291a42115
> paralyses
36403d42223
36403d42226
< parrakeet/MS
36449d42268
36449d42271
< partizan/SM
37093a42913
37093a42916
> petabyte/MS
37102c42922
37102c42925
< petitioner/M
---
> petitioner/MS
37264a43085
37264a43088
> phosphorylate/DSGN
37316d43136
37316d43139
< phrenetic
37796a43617
37630a43454
> plaintext
37796a43621
> plugin/MS
37987c43808
37987c43812
< polypeptide/S
---
> polypeptide/MS
38291d44111
38291d44115
< practise's
38451a44272
38451a44276
> prejudgement/MS
38805a44627
38805a44631
> profiler/SM
38835a44658
38835a44662
> programmatically
38891a44715,44716
38891a44719,44720
> pronate/DSGN
> pronator/MS
38951c44776
38951c44780
< proprietorship/M
---
> proprietorship/MS
39039a44865
39039a44869
> provender/M
39564a45391
39095a44926
> pseudorandom/Y
39564a45396
> quinoa
39873a45701,45702
39873a45706,45707
> rasterization/M
> rasterize/SGDR
40036a45866
40036a45871
> recency
40140a45971
40140a45976
> recurse/DGSV
40141a45973
40141a45978
> recuse/DGS
40208a46041
40208a46046
> refactor/SMDG
40244d46076
40244d46081
< reflexion/SM
40659d46490
40659d46495
< resizing
40829c46660
40829c46665
< reverie/M
---
> reverie/MS
41415a47247
41415a47252
> sabre/MS
41914c47746
41914c47751
< schnaps's
---
> schnaps/M
41949c47781
41949c47786
< schrod's
---
> schrod/SM
41998a47831
41998a47836
> scot-free
42883,42885c48716
42883,42885c48721
< shit's
< shit/S!
< shite/S!
---
> shit/MS!
42887,42888c48718,48719
42887,42888c48723,48724
< shithead/S!
< shitload/!
---
> shithead/MS!
> shitload/MS!
42891c48722
42891c48727
< shitty/RT!
---
> shitty/TR!
42976a48808
42976a48813
> should've
43008c48840
43008c48845
< showtime
---
> showtime/MS
43328c49160
43328c49165
< size/MGBDRS
---
> size/AMGBDRS
43724,43726c49556
43724,43726c49561
< smoulder's
< smouldered
< smoulders
---
> smoulder/GSMD
43766a49597,49598
43766a49602,49603
> snarkily
> snarky/TR
44062c49894
44062c49899
< sonofabitch
---
> sonofabitch/!
44346a50179
44346a50184
> spelled
44348a50182
44348a50187
> spelt
44371a50206
44371a50211
> spick/S!
44383c50218
44383c50223
< spik/S
---
> spik/S!
46106a51942
46106a51947
> syllabi
46160c51996
46160c52001
< synch/GMD
---
> synch/GMDS
46167d52002
46167d52007
< synchs
46203,46204c52038,52039
46203,46204c52043,52044
< sysadmin/S
< sysop/S
---
> sysadmin/MS
> sysop/MS
46752a52588
46752a52593
> terabit/MS
46753a52590,52591
46753a52595,52596
> terahertz/M
> terapixel/MS
46817a52656
46817a52661
> testcase/MS
46831a52671
46831a52676
> testsuite/MS
46925a52766
46925a52771
> theremin/MS
47455c53296
47455c53301
< toolbar
---
> toolbar/MS
47755a53597
47755a53602
> transfect/DSMG
47774a53617,53618
47774a53622,53623
> transgenderism
> transgene/MS
47951c53795
47951c53800
< triage/M
---
> triage/MG
48869a54714
48869a54719
> unlikeable
49211c55056
49211c55061
< vagina/M
---
> vagina/MS
49368,49369c55213
49368,49369c55218
< velour's
< velours's
---
> velour/MS
49478a55323
49478a55328
> vertices
50148a55994
50148a55999
> weaponize/DSG
50260,50261d56105
50260,50261d56110
< werwolf/M
< werwolves
50728c56572
50728c56577
< women
---
> women/M
50794c56638
50794c56643
< wop/S!
---
> wop/MS!

View File

@ -1,4 +1,4 @@
57460
57465
0/nm
0th/pt
1/n1
@ -22722,6 +22722,7 @@ cinnabar/M
cinnamon/M
cipher's
cipher/CGDS
ciphertext/S
cir
circa
circadian
@ -25073,7 +25074,9 @@ cryptographer/MS
cryptographic
cryptographically
cryptography/M
cryptologist/MS
cryptology
cryptosystem/S
crystal/SM
crystalline
crystallization/M
@ -37149,7 +37152,7 @@ linguine/M
linguini/M
linguist/SM
linguistic/S
linguistically
linguistical/Y
linguistics/M
liniment/SM
lining/M
@ -43770,6 +43773,7 @@ plainsmen
plainsong/M
plainspoken
plaint/SMV
plaintext
plaintiff/SM
plaintive/Y
plait/MDGS
@ -45245,6 +45249,7 @@ pseudonym/SM
pseudonymous
pseudopod
pseudopodia
pseudorandom/Y
pseudoscience/MS
pseudy
pshaw/MS

View File

@ -53,8 +53,8 @@
#include "mozilla/CheckedInt.h"
#ifdef PR_LOGGING
PRLogModuleInfo *
#if defined(DEBUG) || defined(PR_LOGGING)
GFX2D_API PRLogModuleInfo *
GetGFX2DLog()
{
static PRLogModuleInfo *sLog;
@ -156,7 +156,7 @@ namespace mozilla {
namespace gfx {
// XXX - Need to define an API to set this.
int sGfxLogLevel = LOG_DEBUG;
GFX2D_API int sGfxLogLevel = LOG_DEBUG;
#ifdef WIN32
ID3D10Device1 *Factory::mD3D10Device;

View File

@ -10,17 +10,27 @@
#include <sstream>
#include <stdio.h>
#include "nsDebug.h"
#include "Point.h"
#include "BaseRect.h"
#include "Matrix.h"
#include "mozilla/TypedEnum.h"
#ifdef WIN32
#include <windows.h>
// This file gets included from nsGlobalWindow.cpp, which doesn't like
// having windows.h included in it. Since OutputDebugStringA is the only
// thing we need from windows.h, we just declare it here directly.
// Note: the function's documented signature is
// WINBASEAPI void WINAPI OutputDebugStringA(LPCSTR lpOutputString)
// but if we don't include windows.h, the macros WINBASEAPI, WINAPI, and
// LPCSTR are not defined, so we need to replace them with their expansions.
extern "C" __declspec(dllimport) void __stdcall OutputDebugStringA(const char* lpOutputString);
#endif
#ifdef PR_LOGGING
#if defined(DEBUG) || defined(PR_LOGGING)
#include <prlog.h>
extern PRLogModuleInfo *GetGFX2DLog();
extern GFX2D_API PRLogModuleInfo *GetGFX2DLog();
#endif
namespace mozilla {
@ -29,7 +39,7 @@ namespace gfx {
const int LOG_DEBUG = 1;
const int LOG_WARNING = 2;
#ifdef PR_LOGGING
#if defined(DEBUG) || defined(PR_LOGGING)
inline PRLogModuleLevel PRLogLevelForLevel(int aLevel) {
switch (aLevel) {
@ -43,20 +53,20 @@ inline PRLogModuleLevel PRLogLevelForLevel(int aLevel) {
#endif
extern int sGfxLogLevel;
extern GFX2D_API int sGfxLogLevel;
static inline void OutputMessage(const std::string &aString, int aLevel) {
#if defined(WIN32) && !defined(PR_LOGGING)
if (aLevel >= sGfxLogLevel) {
::OutputDebugStringA(aString.c_str());
}
#elif defined(PR_LOGGING)
#elif defined(PR_LOGGING) && !(defined(MOZ_WIDGET_GONK) || defined(MOZ_WIDGET_ANDROID))
if (PR_LOG_TEST(GetGFX2DLog(), PRLogLevelForLevel(aLevel))) {
PR_LogPrint(aString.c_str());
}
#else
if (aLevel >= sGfxLogLevel) {
printf("%s", aString.c_str());
printf_stderr("%s", aString.c_str());
}
#endif
}
@ -71,29 +81,49 @@ public:
NoLog &operator <<(const T &aLogText) { return *this; }
};
MOZ_BEGIN_ENUM_CLASS(LogOptions, int)
NoNewline = 0x01
MOZ_END_ENUM_CLASS(LogOptions)
template<int L>
class Log
{
public:
Log() {}
~Log() { mMessage << '\n'; WriteLog(mMessage.str()); }
Log(LogOptions aOptions = LogOptions(0)) : mOptions(aOptions) {}
~Log() {
Flush();
}
void Flush() {
if (!(int(mOptions) & int(LogOptions::NoNewline))) {
mMessage << '\n';
}
std::string str = mMessage.str();
if (!str.empty()) {
WriteLog(str);
}
mMessage.str("");
mMessage.clear();
}
Log &operator <<(char aChar) { mMessage << aChar; return *this; }
Log &operator <<(const std::string &aLogText) { mMessage << aLogText; return *this; }
Log &operator <<(const char aStr[]) { mMessage << static_cast<const char*>(aStr); return *this; }
Log &operator <<(bool aBool) { mMessage << (aBool ? "true" : "false"); return *this; }
Log &operator <<(int aInt) { mMessage << aInt; return *this; }
Log &operator <<(unsigned int aInt) { mMessage << aInt; return *this; }
Log &operator <<(long aLong) { mMessage << aLong; return *this; }
Log &operator <<(unsigned long aLong) { mMessage << aLong; return *this; }
Log &operator <<(int32_t aInt) { mMessage << aInt; return *this; }
Log &operator <<(uint32_t aInt) { mMessage << aInt; return *this; }
Log &operator <<(int64_t aLong) { mMessage << aLong; return *this; }
Log &operator <<(uint64_t aLong) { mMessage << aLong; return *this; }
Log &operator <<(Float aFloat) { mMessage << aFloat; return *this; }
Log &operator <<(double aDouble) { mMessage << aDouble; return *this; }
Log &operator <<(const Point &aPoint)
template <typename T, typename Sub>
Log &operator <<(const BasePoint<T, Sub>& aPoint)
{ mMessage << "Point(" << aPoint.x << "," << aPoint.y << ")"; return *this; }
Log &operator <<(const Size &aSize)
template <typename T, typename Sub>
Log &operator <<(const BaseSize<T, Sub>& aSize)
{ mMessage << "Size(" << aSize.width << "," << aSize.height << ")"; return *this; }
Log &operator <<(const IntSize &aSize)
{ mMessage << "IntSize(" << aSize.width << "," << aSize.height << ")"; return *this; }
Log &operator <<(const Rect &aRect)
template <typename T, typename Sub, typename Point, typename SizeT, typename Margin>
Log &operator <<(const BaseRect<T, Sub, Point, SizeT, Margin>& aRect)
{ mMessage << "Rect(" << aRect.x << "," << aRect.y << "," << aRect.width << "," << aRect.height << ")"; return *this; }
Log &operator<<(const Matrix& aMatrix)
{ mMessage << "Matrix(" << aMatrix._11 << " " << aMatrix._12 << " ; " << aMatrix._21 << " " << aMatrix._22 << " ; " << aMatrix._31 << " " << aMatrix._32 << ")"; return *this; }
@ -106,6 +136,7 @@ private:
}
std::stringstream mMessage;
LogOptions mOptions;
};
typedef Log<LOG_DEBUG> DebugLog;
@ -122,6 +153,84 @@ typedef Log<LOG_WARNING> WarningLog;
#define gfxWarning if (1) ; else NoLog
#endif
const int INDENT_PER_LEVEL = 2;
class TreeLog
{
public:
TreeLog(const std::string& aPrefix = "")
: mLog(LogOptions::NoNewline),
mPrefix(aPrefix),
mDepth(0),
mStartOfLine(true),
mConditionedOnPref(false),
mPref(nullptr) {}
template <typename T>
TreeLog& operator<<(const T& aObject) {
if (mConditionedOnPref && !*mPref) {
return *this;
}
if (mStartOfLine) {
mLog << '[' << mPrefix << "] " << std::string(mDepth * INDENT_PER_LEVEL, ' ');
mStartOfLine = false;
}
mLog << aObject;
if (EndsInNewline(aObject)) {
// Don't indent right here as the user may change the indent
// between now and the first output to the next line.
mLog.Flush();
mStartOfLine = true;
}
return *this;
}
void IncreaseIndent() { ++mDepth; }
void DecreaseIndent() { --mDepth; }
void ConditionOnPref(bool* aPref) {
mConditionedOnPref = true;
mPref = aPref;
}
private:
Log<LOG_DEBUG> mLog;
std::string mPrefix;
uint32_t mDepth;
bool mStartOfLine;
bool mConditionedOnPref;
bool* mPref;
template <typename T>
static bool EndsInNewline(const T& aObject) {
return false;
}
static bool EndsInNewline(const std::string& aString) {
return !aString.empty() && aString[aString.length() - 1] == '\n';
}
static bool EndsInNewline(char aChar) {
return aChar == '\n';
}
static bool EndsInNewline(const char* aString) {
return EndsInNewline(std::string(aString));
}
};
class TreeAutoIndent
{
public:
TreeAutoIndent(TreeLog& aTreeLog) : mTreeLog(aTreeLog) {
mTreeLog.IncreaseIndent();
}
~TreeAutoIndent() {
mTreeLog.DecreaseIndent();
}
private:
TreeLog& mTreeLog;
};
}
}

View File

@ -97,7 +97,7 @@ struct RectTyped :
Super(float(rect.x), float(rect.y),
float(rect.width), float(rect.height)) {}
GFX2D_API void NudgeToIntegers()
void NudgeToIntegers()
{
NudgeToInteger(&(this->x));
NudgeToInteger(&(this->y));

View File

@ -246,7 +246,7 @@ struct GradientStop
}
}
#if defined(XP_WIN) && defined(MOZ_GFX)
#if defined(XP_WIN) && defined(GKMEDIAS_SHARED_LIBRARY)
#ifdef GFX2D_INTERNAL
#define GFX2D_API __declspec(dllexport)
#else

View File

@ -21,6 +21,7 @@ EXPORTS.mozilla.gfx += [
'DataSurfaceHelpers.h',
'Filters.h',
'Helpers.h',
'Logging.h',
'Matrix.h',
'PathHelpers.h',
'Point.h',

View File

@ -623,6 +623,7 @@ struct ParamTraits<mozilla::layers::FrameMetrics>
WriteParam(aMsg, aParam.mDisableScrollingY);
WriteParam(aMsg, aParam.mUpdateScrollOffset);
WriteParam(aMsg, aParam.mScrollGeneration);
WriteParam(aMsg, aParam.mContentDescription);
}
static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
@ -645,7 +646,8 @@ struct ParamTraits<mozilla::layers::FrameMetrics>
ReadParam(aMsg, aIter, &aResult->mDisableScrollingX) &&
ReadParam(aMsg, aIter, &aResult->mDisableScrollingY) &&
ReadParam(aMsg, aIter, &aResult->mUpdateScrollOffset) &&
ReadParam(aMsg, aIter, &aResult->mScrollGeneration));
ReadParam(aMsg, aIter, &aResult->mScrollGeneration) &&
ReadParam(aMsg, aIter, &aResult->mContentDescription));
}
};

View File

@ -7,10 +7,12 @@
#define GFX_FRAMEMETRICS_H
#include <stdint.h> // for uint32_t, uint64_t
#include <string> // for std::string
#include "Units.h" // for CSSRect, CSSPixel, etc
#include "mozilla/gfx/BasePoint.h" // for BasePoint
#include "mozilla/gfx/Rect.h" // for RoundedIn
#include "mozilla/gfx/ScaleFactor.h" // for ScaleFactor
#include "mozilla/gfx/Logging.h" // for Log
namespace IPC {
template <typename T> struct ParamTraits;
@ -70,6 +72,8 @@ public:
bool operator==(const FrameMetrics& aOther) const
{
// mContentDescription is not compared on purpose as it's only used
// for debugging.
return mCompositionBounds.IsEqualEdges(aOther.mCompositionBounds) &&
mDisplayPort.IsEqualEdges(aOther.mDisplayPort) &&
mCriticalDisplayPort.IsEqualEdges(aOther.mCriticalDisplayPort) &&
@ -336,6 +340,16 @@ public:
return mScrollGeneration;
}
const std::string& GetContentDescription() const
{
return mContentDescription;
}
void SetContentDescription(const std::string& aContentDescription)
{
mContentDescription = aContentDescription;
}
private:
// New fields from now on should be made private and old fields should
// be refactored to be private.
@ -350,6 +364,10 @@ private:
bool mUpdateScrollOffset;
// The scroll generation counter used to acknowledge the scroll offset update.
uint32_t mScrollGeneration;
// A description of the content element corresponding to this frame.
// This is empty unless the apz.printtree pref is turned on.
std::string mContentDescription;
};
/**
@ -408,6 +426,11 @@ struct ScrollableLayerGuid {
}
};
template <int LogLevel>
gfx::Log<LogLevel>& operator<<(gfx::Log<LogLevel>& log, const ScrollableLayerGuid& aGuid) {
return log << '(' << aGuid.mLayersId << ',' << aGuid.mPresShellId << ',' << aGuid.mScrollId << ')';
}
struct ZoomConstraints {
bool mAllowZoom;
bool mAllowDoubleTapZoom;

View File

@ -16,6 +16,7 @@
#include "mozilla/MouseEvents.h"
#include "mozilla/mozalloc.h" // for operator new
#include "mozilla/TouchEvents.h"
#include "mozilla/Preferences.h" // for Preferences
#include "nsDebug.h" // for NS_WARNING
#include "nsPoint.h" // for nsIntPoint
#include "nsThreadUtils.h" // for NS_IsMainThread
@ -30,12 +31,18 @@ namespace layers {
float APZCTreeManager::sDPI = 160.0;
// Pref that enables printing of the APZC tree for debugging.
static bool gPrintApzcTree = false;
APZCTreeManager::APZCTreeManager()
: mTreeLock("APZCTreeLock"),
mTouchCount(0)
mTouchCount(0),
mApzcTreeLog("apzctree")
{
MOZ_ASSERT(NS_IsMainThread());
AsyncPanZoomController::InitializeGlobalState();
Preferences::AddBoolVarCache(&gPrintApzcTree, "apz.printtree", gPrintApzcTree);
mApzcTreeLog.ConditionOnPref(&gPrintApzcTree);
}
APZCTreeManager::~APZCTreeManager()
@ -116,6 +123,7 @@ APZCTreeManager::UpdatePanZoomControllerTree(CompositorParent* aCompositor, Laye
mRootApzc = nullptr;
if (aRoot) {
mApzcTreeLog << "[start]\n";
UpdatePanZoomControllerTree(aCompositor,
aRoot,
// aCompositor is null in gtest scenarios
@ -123,6 +131,7 @@ APZCTreeManager::UpdatePanZoomControllerTree(CompositorParent* aCompositor, Laye
gfx3DMatrix(), nullptr, nullptr,
aIsFirstPaint, aFirstPaintLayersId,
&apzcsToDestroy);
mApzcTreeLog << "[end]\n";
}
for (size_t i = 0; i < apzcsToDestroy.Length(); i++) {
@ -144,6 +153,7 @@ APZCTreeManager::UpdatePanZoomControllerTree(CompositorParent* aCompositor,
ContainerLayer* container = aLayer->AsContainerLayer();
AsyncPanZoomController* apzc = nullptr;
mApzcTreeLog << aLayer->Name() << '\t';
if (container) {
if (container->GetFrameMetrics().IsScrollable()) {
const CompositorParent::LayerTreeState* state = CompositorParent::GetIndirectShadowTree(aLayersId);
@ -158,7 +168,8 @@ APZCTreeManager::UpdatePanZoomControllerTree(CompositorParent* aCompositor,
// be possible because of DLBI heuristics) then we don't want to keep using
// the same old APZC for the new content. Null it out so we run through the
// code to find another one or create one.
if (apzc && !apzc->Matches(ScrollableLayerGuid(aLayersId, container->GetFrameMetrics()))) {
ScrollableLayerGuid guid(aLayersId, container->GetFrameMetrics());
if (apzc && !apzc->Matches(guid)) {
apzc = nullptr;
}
@ -169,9 +180,8 @@ APZCTreeManager::UpdatePanZoomControllerTree(CompositorParent* aCompositor,
// underlying content for which the APZC was originally created is still
// there. So it makes sense to pick up that APZC instance again and use it here.
if (apzc == nullptr) {
ScrollableLayerGuid target(aLayersId, container->GetFrameMetrics());
for (size_t i = 0; i < aApzcsToDestroy->Length(); i++) {
if (aApzcsToDestroy->ElementAt(i)->Matches(target)) {
if (aApzcsToDestroy->ElementAt(i)->Matches(guid)) {
apzc = aApzcsToDestroy->ElementAt(i);
break;
}
@ -222,6 +232,11 @@ APZCTreeManager::UpdatePanZoomControllerTree(CompositorParent* aCompositor,
visible.width, visible.height,
apzc);
mApzcTreeLog << "APZC " << guid
<< "\tcb=" << visible
<< "\tsr=" << container->GetFrameMetrics().mScrollableRect
<< "\t" << container->GetFrameMetrics().GetContentDescription();
// Bind the APZC instance into the tree of APZCs
if (aNextSibling) {
aNextSibling->SetPrevSibling(apzc);
@ -256,6 +271,7 @@ APZCTreeManager::UpdatePanZoomControllerTree(CompositorParent* aCompositor,
container->SetAsyncPanZoomController(apzc);
}
mApzcTreeLog << '\n';
// Accumulate the CSS transform between layers that have an APZC, but exclude any
// any layers that do have an APZC, and reset the accumulation at those layers.
@ -273,6 +289,7 @@ APZCTreeManager::UpdatePanZoomControllerTree(CompositorParent* aCompositor,
// have our siblings as siblings.
AsyncPanZoomController* next = apzc ? nullptr : aNextSibling;
for (Layer* child = aLayer->GetLastChild(); child; child = child->GetPrevSibling()) {
gfx::TreeAutoIndent indent(mApzcTreeLog);
next = UpdatePanZoomControllerTree(aCompositor, child, childLayersId, aTransform, aParent, next,
aIsFirstPaint, aFirstPaintLayersId, aApzcsToDestroy);
}

View File

@ -19,6 +19,7 @@
#include "nsISupportsImpl.h" // for MOZ_COUNT_CTOR, etc
#include "mozilla/Vector.h" // for mozilla::Vector
#include "nsTArray.h" // for nsTArray, nsTArray_Impl, etc
#include "mozilla/gfx/Logging.h" // for gfx::TreeLog
class gfx3DMatrix;
template <class E> class nsTArray;
@ -340,6 +341,9 @@ private:
* the next APZC in the chain.
*/
Vector< nsRefPtr<AsyncPanZoomController> > mOverscrollHandoffChain;
/* For logging the APZC tree for debugging (enabled by the apz.printtree
* pref). */
gfx::TreeLog mApzcTreeLog;
static float sDPI;
};

View File

@ -16,75 +16,62 @@
#include "nsMathUtils.h" // for NS_lround
#include "nsThreadUtils.h" // for NS_DispatchToMainThread, etc
#include "nscore.h" // for NS_IMETHOD
#include "gfxPrefs.h" // for the preferences
namespace mozilla {
namespace layers {
/**
* These are the preferences that control the behavior of APZ
*/
/**
* "apz.max_event_acceleration"
*
* Maximum acceleration that can happen between two frames. Velocity is
* throttled if it's above this. This may happen if a time delta is very low,
* or we get a touch point very far away from the previous position for some
* reason.
*
* The default value is 999.0f, set in gfxPrefs.h
*/
static float gMaxEventAcceleration = 999.0f;
/**
* "apz.fling_friction"
*
* Amount of friction applied during flings.
*
* The default value is 0.002f, set in gfxPrefs.h
*/
static float gFlingFriction = 0.002f;
/**
* "apz.fling_stopped_threshold"
*
* When flinging, if the velocity goes below this number, we just stop the
* animation completely. This is to prevent asymptotically approaching 0
* velocity and rerendering unnecessarily.
*
* The default value is 0.01f, set in gfxPrefs.h.
*/
static float gFlingStoppedThreshold = 0.01f;
/**
* "apz.max_velocity_queue_size"
*
* Maximum size of velocity queue. The queue contains last N velocity records.
* On touch end we calculate the average velocity in order to compensate
* touch/mouse drivers misbehaviour.
*
* The default value is 5, set in gfxPrefs.h
*/
static uint32_t gMaxVelocityQueueSize = 5;
/**
* "apz.max_velocity_pixels_per_ms"
*
* Maximum velocity in pixels per millisecond. Velocity will be capped at this
* value if a faster fling occurs. Negative values indicate unlimited velocity.
*
* The default value is -1.0f, set in gfxPrefs.h
*/
static float gMaxVelocity = -1.0f;
static void ReadAxisPrefs()
{
Preferences::AddFloatVarCache(&gMaxEventAcceleration, "apz.max_event_acceleration", gMaxEventAcceleration);
Preferences::AddFloatVarCache(&gFlingFriction, "apz.fling_friction", gFlingFriction);
Preferences::AddFloatVarCache(&gFlingStoppedThreshold, "apz.fling_stopped_threshold", gFlingStoppedThreshold);
Preferences::AddUintVarCache(&gMaxVelocityQueueSize, "apz.max_velocity_queue_size", gMaxVelocityQueueSize);
Preferences::AddFloatVarCache(&gMaxVelocity, "apz.max_velocity_pixels_per_ms", gMaxVelocity);
}
class ReadAxisPref MOZ_FINAL : public nsRunnable {
public:
NS_IMETHOD Run()
{
ReadAxisPrefs();
return NS_OK;
}
};
static void InitAxisPrefs()
{
static bool sInitialized = false;
if (sInitialized)
return;
sInitialized = true;
if (NS_IsMainThread()) {
ReadAxisPrefs();
} else {
// We have to dispatch an event to the main thread to read the pref.
NS_DispatchToMainThread(new ReadAxisPref());
}
}
Axis::Axis(AsyncPanZoomController* aAsyncPanZoomController)
: mPos(0),
@ -92,21 +79,20 @@ Axis::Axis(AsyncPanZoomController* aAsyncPanZoomController)
mAxisLocked(false),
mAsyncPanZoomController(aAsyncPanZoomController)
{
InitAxisPrefs();
}
void Axis::UpdateWithTouchAtDevicePoint(int32_t aPos, const TimeDuration& aTimeDelta) {
float newVelocity = mAxisLocked ? 0 : (mPos - aPos) / aTimeDelta.ToMilliseconds();
if (gMaxVelocity > 0.0f) {
newVelocity = std::min(newVelocity, gMaxVelocity);
if (gfxPrefs::APZMaxVelocity() > 0.0f) {
newVelocity = std::min(newVelocity, gfxPrefs::APZMaxVelocity());
}
mVelocity = newVelocity;
mPos = aPos;
// Keep last gMaxVelocityQueueSize or less velocities in the queue.
// Limit queue size pased on pref
mVelocityQueue.AppendElement(mVelocity);
if (mVelocityQueue.Length() > gMaxVelocityQueueSize) {
if (mVelocityQueue.Length() > gfxPrefs::APZMaxVelocityQueueSize()) {
mVelocityQueue.RemoveElementAt(0);
}
}
@ -180,14 +166,14 @@ bool Axis::Scrollable() {
}
bool Axis::FlingApplyFrictionOrCancel(const TimeDuration& aDelta) {
if (fabsf(mVelocity) <= gFlingStoppedThreshold) {
if (fabsf(mVelocity) <= gfxPrefs::APZFlingStoppedThreshold()) {
// If the velocity is very low, just set it to 0 and stop the fling,
// otherwise we'll just asymptotically approach 0 and the user won't
// actually see any changes.
mVelocity = 0.0f;
return false;
} else {
mVelocity *= pow(1.0f - gFlingFriction, float(aDelta.ToMilliseconds()));
mVelocity *= pow(1.0f - gfxPrefs::APZFlingFriction(), float(aDelta.ToMilliseconds()));
}
return true;
}

View File

@ -1408,13 +1408,15 @@ SourceNeededRegionForPrimitive(const FilterPrimitiveDescription& aDescription,
const AttributeMap& atts = aDescription.Attributes();
switch (aDescription.Type()) {
case FilterPrimitiveDescription::eNone:
case FilterPrimitiveDescription::eFlood:
case FilterPrimitiveDescription::eTurbulence:
case FilterPrimitiveDescription::eImage:
MOZ_CRASH("this shouldn't be called for filters without inputs");
return nsIntRegion();
case FilterPrimitiveDescription::eNone:
return nsIntRegion();
case FilterPrimitiveDescription::eBlend:
case FilterPrimitiveDescription::eComposite:
case FilterPrimitiveDescription::eMerge:

View File

@ -59,17 +59,30 @@ void gfxPrefs::PrefAddVarCache(uint32_t* aVariable,
Preferences::AddUintVarCache(aVariable, aPref, aDefault);
}
void gfxPrefs::PrefAddVarCache(float* aVariable,
const char* aPref,
float aDefault)
{
Preferences::AddFloatVarCache(aVariable, aPref, aDefault);
}
bool gfxPrefs::PrefGet(const char* aPref, bool aDefault)
{
return Preferences::GetBool(aPref,aDefault);
return Preferences::GetBool(aPref, aDefault);
}
int32_t gfxPrefs::PrefGet(const char* aPref, int32_t aDefault)
{
return Preferences::GetInt(aPref,aDefault);
return Preferences::GetInt(aPref, aDefault);
}
uint32_t gfxPrefs::PrefGet(const char* aPref, uint32_t aDefault)
{
return Preferences::GetUint(aPref,aDefault);
return Preferences::GetUint(aPref, aDefault);
}
float gfxPrefs::PrefGet(const char* aPref, float aDefault)
{
return Preferences::GetFloat(aPref, aDefault);
}

View File

@ -56,7 +56,8 @@ public: \
static Type Name() { MOZ_ASSERT(Exists()); return One().mPref##Name.mValue; } \
private: \
static const char* Get##Name##PrefName() { return Pref; } \
PrefTemplate<UpdatePolicy::Update, Type, Default, Get##Name##PrefName> mPref##Name
static Type Get##Name##PrefDefault() { return Default; } \
PrefTemplate<UpdatePolicy::Update, Type, Get##Name##PrefDefault, Get##Name##PrefName> mPref##Name
class gfxPrefs;
class gfxPrefs MOZ_FINAL
@ -70,12 +71,12 @@ private:
MOZ_END_NESTED_ENUM_CLASS(UpdatePolicy)
// Since we cannot use const char*, use a function that returns it.
template <MOZ_ENUM_CLASS_ENUM_TYPE(UpdatePolicy) Update, class T, T Default, const char* Pref(void)>
template <MOZ_ENUM_CLASS_ENUM_TYPE(UpdatePolicy) Update, class T, T Default(void), const char* Pref(void)>
class PrefTemplate
{
public:
PrefTemplate()
: mValue(Default)
: mValue(Default())
{
Register(Update, Pref());
}
@ -102,6 +103,12 @@ private:
// We will keep these in an alphabetical order to make it easier to see if
// a method accessing a pref already exists. Just add yours in the list.
DECL_GFX_PREF(Once, "apz.fling_friction", APZFlingFriction, float, 0.002f);
DECL_GFX_PREF(Once, "apz.fling_stopped_threshold", APZFlingStoppedThreshold, float, 0.01f);
DECL_GFX_PREF(Once, "apz.max_event_acceleration", APZMaxEventAcceleration, float, 999.0f);
DECL_GFX_PREF(Once, "apz.max_velocity_pixels_per_ms", APZMaxVelocity, float, -1.0f);
DECL_GFX_PREF(Once, "apz.max_velocity_queue_size", APZMaxVelocityQueueSize, uint32_t, 5);
#if defined(ANDROID)
DECL_GFX_PREF(Once, "gfx.apitrace.enabled", UseApitrace, bool, false);
#endif
@ -181,9 +188,11 @@ private:
static void PrefAddVarCache(bool*, const char*, bool);
static void PrefAddVarCache(int32_t*, const char*, int32_t);
static void PrefAddVarCache(uint32_t*, const char*, uint32_t);
static void PrefAddVarCache(float*, const char*, float);
static bool PrefGet(const char*, bool);
static int32_t PrefGet(const char*, int32_t);
static uint32_t PrefGet(const char*, uint32_t);
static float PrefGet(const char*, float);
gfxPrefs();
~gfxPrefs();

View File

@ -1655,7 +1655,11 @@ jsdContext::GetJSContext(JSContext **_rval)
#define JSOPTION_DONT_REPORT_UNCAUGHT JS_BIT(8)
#define JSOPTION_NO_DEFAULT_COMPARTMENT_OBJECT JS_BIT(11)
#define JSOPTION_NO_SCRIPT_RVAL JS_BIT(12)
#define JSOPTION_BASELINE JS_BIT(14)
#define JSOPTION_TYPE_INFERENCE JS_BIT(16)
#define JSOPTION_STRICT_MODE JS_BIT(17)
#define JSOPTION_ION JS_BIT(18)
#define JSOPTION_ASMJS JS_BIT(19)
#define JSOPTION_MASK JS_BITMASK(20)
NS_IMETHODIMP
@ -1669,7 +1673,11 @@ jsdContext::GetOptions(uint32_t *_rval)
| (JS::ContextOptionsRef(mJSCx).dontReportUncaught() ? JSOPTION_DONT_REPORT_UNCAUGHT : 0)
| (JS::ContextOptionsRef(mJSCx).noDefaultCompartmentObject() ? JSOPTION_NO_DEFAULT_COMPARTMENT_OBJECT : 0)
| (JS::ContextOptionsRef(mJSCx).noScriptRval() ? JSOPTION_NO_SCRIPT_RVAL : 0)
| (JS::ContextOptionsRef(mJSCx).strictMode() ? JSOPTION_STRICT_MODE : 0);
| (JS::ContextOptionsRef(mJSCx).strictMode() ? JSOPTION_STRICT_MODE : 0)
| (JS::ContextOptionsRef(mJSCx).baseline() ? JSOPTION_BASELINE : 0)
| (JS::ContextOptionsRef(mJSCx).typeInference() ? JSOPTION_TYPE_INFERENCE : 0)
| (JS::ContextOptionsRef(mJSCx).ion() ? JSOPTION_ION : 0)
| (JS::ContextOptionsRef(mJSCx).asmJS() ? JSOPTION_ASMJS : 0);
return NS_OK;
}
@ -1690,7 +1698,11 @@ jsdContext::SetOptions(uint32_t options)
.setDontReportUncaught(options & JSOPTION_DONT_REPORT_UNCAUGHT)
.setNoDefaultCompartmentObject(options & JSOPTION_NO_DEFAULT_COMPARTMENT_OBJECT)
.setNoScriptRval(options & JSOPTION_NO_SCRIPT_RVAL)
.setStrictMode(options & JSOPTION_STRICT_MODE);
.setStrictMode(options & JSOPTION_STRICT_MODE)
.setBaseline(options & JSOPTION_BASELINE)
.setTypeInference(options & JSOPTION_TYPE_INFERENCE)
.setIon(options & JSOPTION_ION)
.setAsmJS(options & JSOPTION_ASMJS);
return NS_OK;
}

View File

@ -324,7 +324,7 @@ class TenuredHeap : public js::HeapBase<T>
"TenuredHeap<T> must be binary compatible with T.");
}
explicit TenuredHeap(T p) : bits(0) { setPtr(p); }
explicit TenuredHeap(const TenuredHeap<T> &p) : bits(0) { setPtr(p.ptr); }
explicit TenuredHeap(const TenuredHeap<T> &p) : bits(0) { setPtr(p.getPtr()); }
bool operator==(const TenuredHeap<T> &other) { return bits == other.bits; }
bool operator!=(const TenuredHeap<T> &other) { return bits != other.bits; }

View File

@ -1160,7 +1160,7 @@ SetJitCompilerOption(JSContext *cx, unsigned argc, jsval *vp)
if (number < 0)
number = -1;
JS_SetGlobalJitCompilerOption(cx->runtime(), opt, uint32_t(number));
JS_SetGlobalJitCompilerOption(cx, opt, uint32_t(number));
args.rval().setUndefined();
return true;
@ -1175,10 +1175,10 @@ GetJitCompilerOptions(JSContext *cx, unsigned argc, jsval *vp)
RootedValue value(cx);
#define JIT_COMPILER_MATCH(key, string) \
opt = JSJITCOMPILER_ ## key; \
value.setInt32(JS_GetGlobalJitCompilerOption(cx->runtime(), opt)); \
if (!JS_SetProperty(cx, info, string, value)) \
#define JIT_COMPILER_MATCH(key, string) \
opt = JSJITCOMPILER_ ## key; \
value.setInt32(JS_GetGlobalJitCompilerOption(cx, opt)); \
if (!JS_SetProperty(cx, info, string, value)) \
return false;
JSJitCompilerOption opt = JSJITCOMPILER_NOT_AN_OPTION;

View File

@ -6952,7 +6952,7 @@ js::IsAsmJSCompilationAvailable(JSContext *cx, unsigned argc, Value *vp)
cx->signalHandlersInstalled() &&
cx->gcSystemPageSize() == AsmJSPageSize &&
!cx->compartment()->debugMode() &&
cx->runtime()->options().asmJS();
cx->compartment()->options().asmJS(cx);
args.rval().set(BooleanValue(available));
return true;

View File

@ -312,7 +312,7 @@ struct BaselineScript
inline bool
IsBaselineEnabled(JSContext *cx)
{
return cx->runtime()->options().baseline();
return cx->compartment()->options().baseline(cx);
}
MethodStatus

View File

@ -159,8 +159,8 @@ void StopAllOffThreadCompilations(JSCompartment *comp);
static inline bool
IsIonEnabled(JSContext *cx)
{
return cx->runtime()->options().ion() &&
cx->runtime()->options().baseline() &&
return cx->compartment()->options().ion(cx) &&
cx->compartment()->options().baseline(cx) &&
cx->typeInferenceEnabled();
}

View File

@ -133,7 +133,7 @@ JSContext *createContext()
JSContext *cx = JSAPITest::createContext();
if (!cx)
return nullptr;
JS::RuntimeOptionsRef(cx).setBaseline(true)
JS::ContextOptionsRef(cx).setBaseline(true)
.setIon(true);
return cx;
}

View File

@ -141,7 +141,7 @@ END_TEST(testProfileStrings_isCalledWithInterpreter)
BEGIN_TEST(testProfileStrings_isCalledWithJIT)
{
CHECK(initialize(cx));
JS::RuntimeOptionsRef(cx).setBaseline(true)
JS::ContextOptionsRef(cx).setBaseline(true)
.setIon(true);
EXEC("function g() { var p = new Prof(); p.test_fn(); }");
@ -190,7 +190,7 @@ END_TEST(testProfileStrings_isCalledWithJIT)
BEGIN_TEST(testProfileStrings_isCalledWhenError)
{
CHECK(initialize(cx));
JS::RuntimeOptionsRef(cx).setBaseline(true)
JS::ContextOptionsRef(cx).setBaseline(true)
.setIon(true);
EXEC("function check2() { throw 'a'; }");
@ -214,7 +214,7 @@ END_TEST(testProfileStrings_isCalledWhenError)
BEGIN_TEST(testProfileStrings_worksWhenEnabledOnTheFly)
{
CHECK(initialize(cx));
JS::RuntimeOptionsRef(cx).setBaseline(true)
JS::ContextOptionsRef(cx).setBaseline(true)
.setIon(true);
EXEC("function b(p) { p.test_fn(); }");

View File

@ -883,18 +883,6 @@ JS_StringToVersion(const char *string)
return JSVERSION_UNKNOWN;
}
JS_PUBLIC_API(JS::RuntimeOptions &)
JS::RuntimeOptionsRef(JSRuntime *rt)
{
return rt->options();
}
JS_PUBLIC_API(JS::RuntimeOptions &)
JS::RuntimeOptionsRef(JSContext *cx)
{
return cx->runtime()->options();
}
JS_PUBLIC_API(JS::ContextOptions &)
JS::ContextOptionsRef(JSContext *cx)
{
@ -2466,6 +2454,36 @@ class AutoHoldZone
} /* anonymous namespace */
bool
JS::CompartmentOptions::baseline(JSContext *cx) const
{
return baselineOverride_.get(cx->options().baseline());
}
bool
JS::CompartmentOptions::typeInference(const ExclusiveContext *cx) const
{
/* Unlike the other options that can be overriden on a per compartment
* basis, the default value for the typeInference option is stored on the
* compartment's type zone, rather than the current JSContext. Type zones
* copy this default value over from the current JSContext when they are
* created.
*/
return typeInferenceOverride_.get(cx->compartment()->zone()->types.inferenceEnabled);
}
bool
JS::CompartmentOptions::ion(JSContext *cx) const
{
return ionOverride_.get(cx->options().ion());
}
bool
JS::CompartmentOptions::asmJS(JSContext *cx) const
{
return asmJSOverride_.get(cx->options().asmJS());
}
bool
JS::CompartmentOptions::cloneSingletons(JSContext *cx) const
{
@ -4437,7 +4455,7 @@ JS::CompileOptions::CompileOptions(JSContext *cx, JSVersion version)
strictOption = cx->options().strictMode();
extraWarningsOption = cx->options().extraWarnings();
werrorOption = cx->options().werror();
asmJSOption = cx->runtime()->options().asmJS();
asmJSOption = cx->options().asmJS();
}
bool
@ -6013,23 +6031,23 @@ JS_ScheduleGC(JSContext *cx, uint32_t count)
#endif
JS_PUBLIC_API(void)
JS_SetParallelParsingEnabled(JSRuntime *rt, bool enabled)
JS_SetParallelParsingEnabled(JSContext *cx, bool enabled)
{
#ifdef JS_ION
rt->setParallelParsingEnabled(enabled);
cx->runtime()->setParallelParsingEnabled(enabled);
#endif
}
JS_PUBLIC_API(void)
JS_SetParallelIonCompilationEnabled(JSRuntime *rt, bool enabled)
JS_SetParallelIonCompilationEnabled(JSContext *cx, bool enabled)
{
#ifdef JS_ION
rt->setParallelIonCompilationEnabled(enabled);
cx->runtime()->setParallelIonCompilationEnabled(enabled);
#endif
}
JS_PUBLIC_API(void)
JS_SetGlobalJitCompilerOption(JSRuntime *rt, JSJitCompilerOption opt, uint32_t value)
JS_SetGlobalJitCompilerOption(JSContext *cx, JSJitCompilerOption opt, uint32_t value)
{
#ifdef JS_ION
@ -6052,19 +6070,19 @@ JS_SetGlobalJitCompilerOption(JSRuntime *rt, JSJitCompilerOption opt, uint32_t v
break;
case JSJITCOMPILER_ION_ENABLE:
if (value == 1) {
JS::RuntimeOptionsRef(rt).setIon(true);
JS::ContextOptionsRef(cx).setIon(true);
IonSpew(js::jit::IonSpew_Scripts, "Enable ion");
} else if (value == 0) {
JS::RuntimeOptionsRef(rt).setIon(false);
JS::ContextOptionsRef(cx).setIon(false);
IonSpew(js::jit::IonSpew_Scripts, "Disable ion");
}
break;
case JSJITCOMPILER_BASELINE_ENABLE:
if (value == 1) {
JS::RuntimeOptionsRef(rt).setBaseline(true);
JS::ContextOptionsRef(cx).setBaseline(true);
IonSpew(js::jit::IonSpew_BaselineScripts, "Enable baseline");
} else if (value == 0) {
JS::RuntimeOptionsRef(rt).setBaseline(false);
JS::ContextOptionsRef(cx).setBaseline(false);
IonSpew(js::jit::IonSpew_BaselineScripts, "Disable baseline");
}
break;
@ -6075,7 +6093,7 @@ JS_SetGlobalJitCompilerOption(JSRuntime *rt, JSJitCompilerOption opt, uint32_t v
}
JS_PUBLIC_API(int)
JS_GetGlobalJitCompilerOption(JSRuntime *rt, JSJitCompilerOption opt)
JS_GetGlobalJitCompilerOption(JSContext *cx, JSJitCompilerOption opt)
{
#ifdef JS_ION
switch (opt) {
@ -6084,9 +6102,9 @@ JS_GetGlobalJitCompilerOption(JSRuntime *rt, JSJitCompilerOption opt)
case JSJITCOMPILER_ION_USECOUNT_TRIGGER:
return jit::js_JitOptions.forcedDefaultIonUsesBeforeCompile;
case JSJITCOMPILER_ION_ENABLE:
return JS::RuntimeOptionsRef(rt).ion();
return JS::ContextOptionsRef(cx).ion();
case JSJITCOMPILER_BASELINE_ENABLE:
return JS::RuntimeOptionsRef(rt).baseline();
return JS::ContextOptionsRef(cx).baseline();
default:
break;
}

View File

@ -1438,69 +1438,6 @@ JS_StringToVersion(const char *string);
namespace JS {
class JS_PUBLIC_API(RuntimeOptions) {
public:
RuntimeOptions()
: baseline_(false),
typeInference_(false),
ion_(false),
asmJS_(false)
{
}
bool baseline() const { return baseline_; }
RuntimeOptions &setBaseline(bool flag) {
baseline_ = flag;
return *this;
}
RuntimeOptions &toggleBaseline() {
baseline_ = !baseline_;
return *this;
}
bool typeInference() const { return typeInference_; }
RuntimeOptions &setTypeInference(bool flag) {
typeInference_ = flag;
return *this;
}
RuntimeOptions &toggleTypeInference() {
typeInference_ = !typeInference_;
return *this;
}
bool ion() const { return ion_; }
RuntimeOptions &setIon(bool flag) {
ion_ = flag;
return *this;
}
RuntimeOptions &toggleIon() {
ion_ = !ion_;
return *this;
}
bool asmJS() const { return asmJS_; }
RuntimeOptions &setAsmJS(bool flag) {
asmJS_ = flag;
return *this;
}
RuntimeOptions &toggleAsmJS() {
asmJS_ = !asmJS_;
return *this;
}
private:
bool baseline_ : 1;
bool typeInference_ : 1;
bool ion_ : 1;
bool asmJS_ : 1;
};
JS_PUBLIC_API(RuntimeOptions &)
RuntimeOptionsRef(JSRuntime *rt);
JS_PUBLIC_API(RuntimeOptions &)
RuntimeOptionsRef(JSContext *cx);
class JS_PUBLIC_API(ContextOptions) {
public:
ContextOptions()
@ -1512,6 +1449,10 @@ class JS_PUBLIC_API(ContextOptions) {
noDefaultCompartmentObject_(false),
noScriptRval_(false),
strictMode_(false),
baseline_(false),
typeInference_(false),
ion_(false),
asmJS_(false),
cloneSingletons_(false)
{
}
@ -1596,6 +1537,46 @@ class JS_PUBLIC_API(ContextOptions) {
return *this;
}
bool baseline() const { return baseline_; }
ContextOptions &setBaseline(bool flag) {
baseline_ = flag;
return *this;
}
ContextOptions &toggleBaseline() {
baseline_ = !baseline_;
return *this;
}
bool typeInference() const { return typeInference_; }
ContextOptions &setTypeInference(bool flag) {
typeInference_ = flag;
return *this;
}
ContextOptions &toggleTypeInference() {
typeInference_ = !typeInference_;
return *this;
}
bool ion() const { return ion_; }
ContextOptions &setIon(bool flag) {
ion_ = flag;
return *this;
}
ContextOptions &toggleIon() {
ion_ = !ion_;
return *this;
}
bool asmJS() const { return asmJS_; }
ContextOptions &setAsmJS(bool flag) {
asmJS_ = flag;
return *this;
}
ContextOptions &toggleAsmJS() {
asmJS_ = !asmJS_;
return *this;
}
bool cloneSingletons() const { return cloneSingletons_; }
ContextOptions &setCloneSingletons(bool flag) {
cloneSingletons_ = flag;
@ -1615,6 +1596,10 @@ class JS_PUBLIC_API(ContextOptions) {
bool noDefaultCompartmentObject_ : 1;
bool noScriptRval_ : 1;
bool strictMode_ : 1;
bool baseline_ : 1;
bool typeInference_ : 1;
bool ion_ : 1;
bool asmJS_ : 1;
bool cloneSingletons_ : 1;
};
@ -2661,6 +2646,18 @@ class JS_PUBLIC_API(CompartmentOptions)
return *this;
}
bool baseline(JSContext *cx) const;
Override &baselineOverride() { return baselineOverride_; }
bool typeInference(const js::ExclusiveContext *cx) const;
Override &typeInferenceOverride() { return typeInferenceOverride_; }
bool ion(JSContext *cx) const;
Override &ionOverride() { return ionOverride_; }
bool asmJS(JSContext *cx) const;
Override &asmJSOverride() { return asmJSOverride_; }
bool cloneSingletons(JSContext *cx) const;
Override &cloneSingletonsOverride() { return cloneSingletonsOverride_; }
@ -2683,6 +2680,10 @@ class JS_PUBLIC_API(CompartmentOptions)
JSVersion version_;
bool invisibleToDebugger_;
bool mergeable_;
Override baselineOverride_;
Override typeInferenceOverride_;
Override ionOverride_;
Override asmJSOverride_;
Override cloneSingletonsOverride_;
union {
ZoneSpecifier spec;
@ -4717,10 +4718,10 @@ JS_ScheduleGC(JSContext *cx, uint32_t count);
#endif
extern JS_PUBLIC_API(void)
JS_SetParallelParsingEnabled(JSRuntime *rt, bool enabled);
JS_SetParallelParsingEnabled(JSContext *cx, bool enabled);
extern JS_PUBLIC_API(void)
JS_SetParallelIonCompilationEnabled(JSRuntime *rt, bool enabled);
JS_SetParallelIonCompilationEnabled(JSContext *cx, bool enabled);
#define JIT_COMPILER_OPTIONS(Register) \
Register(BASELINE_USECOUNT_TRIGGER, "baseline.usecount.trigger") \
@ -4739,9 +4740,9 @@ typedef enum JSJitCompilerOption {
} JSJitCompilerOption;
extern JS_PUBLIC_API(void)
JS_SetGlobalJitCompilerOption(JSRuntime *rt, JSJitCompilerOption opt, uint32_t value);
JS_SetGlobalJitCompilerOption(JSContext *cx, JSJitCompilerOption opt, uint32_t value);
extern JS_PUBLIC_API(int)
JS_GetGlobalJitCompilerOption(JSRuntime *rt, JSJitCompilerOption opt);
JS_GetGlobalJitCompilerOption(JSContext *cx, JSJitCompilerOption opt);
/*
* Convert a uint32_t index into a jsid.

View File

@ -521,7 +521,7 @@ namespace js {
inline bool
ExclusiveContext::typeInferenceEnabled() const
{
return zone()->types.inferenceEnabled;
return compartment_->options().typeInference(this);
}
inline js::Handle<js::GlobalObject*>

View File

@ -1862,7 +1862,7 @@ void
TypeZone::init(JSContext *cx)
{
if (!cx ||
!cx->runtime()->options().typeInference() ||
!cx->options().typeInference() ||
!cx->runtime()->jitSupportsFloatingPoint)
{
return;

View File

@ -118,7 +118,11 @@ static double gTimeoutInterval = -1.0;
static volatile bool gTimedOut = false;
static JS::Value gTimeoutFunc;
static bool enableTypeInference = true;
static bool enableDisassemblyDumps = false;
static bool enableIon = true;
static bool enableBaseline = true;
static bool enableAsmJS = true;
static bool printTiming = false;
static const char *jsCacheDir = nullptr;
@ -648,8 +652,7 @@ Options(JSContext *cx, unsigned argc, jsval *vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
JS::RuntimeOptions oldRuntimeOptions = JS::RuntimeOptionsRef(cx);
JS::ContextOptions oldContextOptions = JS::ContextOptionsRef(cx);
JS::ContextOptions oldOptions = JS::ContextOptionsRef(cx);
for (unsigned i = 0; i < args.length(); i++) {
JSString *str = JS::ToString(cx, args[i]);
if (!str)
@ -663,7 +666,7 @@ Options(JSContext *cx, unsigned argc, jsval *vp)
if (strcmp(opt.ptr(), "strict") == 0)
JS::ContextOptionsRef(cx).toggleExtraWarnings();
else if (strcmp(opt.ptr(), "typeinfer") == 0)
JS::RuntimeOptionsRef(cx).toggleTypeInference();
JS::ContextOptionsRef(cx).toggleTypeInference();
else if (strcmp(opt.ptr(), "werror") == 0)
JS::ContextOptionsRef(cx).toggleWerror();
else if (strcmp(opt.ptr(), "strict_mode") == 0)
@ -687,19 +690,19 @@ Options(JSContext *cx, unsigned argc, jsval *vp)
char *names = strdup("");
bool found = false;
if (!names && oldContextOptions.extraWarnings()) {
if (!names && oldOptions.extraWarnings()) {
names = JS_sprintf_append(names, "%s%s", found ? "," : "", "strict");
found = true;
}
if (!names && oldRuntimeOptions.typeInference()) {
if (!names && oldOptions.typeInference()) {
names = JS_sprintf_append(names, "%s%s", found ? "," : "", "typeinfer");
found = true;
}
if (!names && oldContextOptions.werror()) {
if (!names && oldOptions.werror()) {
names = JS_sprintf_append(names, "%s%s", found ? "," : "", "werror");
found = true;
}
if (!names && oldContextOptions.strictMode()) {
if (!names && oldOptions.strictMode()) {
names = JS_sprintf_append(names, "%s%s", found ? "," : "", "strict_mode");
found = true;
}
@ -5482,6 +5485,14 @@ NewContext(JSRuntime *rt)
JS_SetContextPrivate(cx, data);
JS_SetErrorReporter(cx, my_ErrorReporter);
if (enableTypeInference)
JS::ContextOptionsRef(cx).toggleTypeInference();
if (enableIon)
JS::ContextOptionsRef(cx).toggleIon();
if (enableBaseline)
JS::ContextOptionsRef(cx).toggleBaseline();
if (enableAsmJS)
JS::ContextOptionsRef(cx).toggleAsmJS();
return cx;
}
@ -5583,11 +5594,11 @@ BindScriptArgs(JSContext *cx, JSObject *obj_, OptionParser *op)
// so we're guarding the function definition with an #ifdef, too, to avoid
// build warning for unused function in non-ion-enabled builds:
#if defined(JS_ION)
static bool
static int
OptionFailure(const char *option, const char *str)
{
fprintf(stderr, "Unrecognized option for %s: %s\n", option, str);
return false;
return EXIT_FAILURE;
}
#endif /* JS_ION */
@ -5596,6 +5607,14 @@ ProcessArgs(JSContext *cx, JSObject *obj_, OptionParser *op)
{
RootedObject obj(cx, obj_);
if (op->getBoolOption('c'))
compileOnly = true;
if (op->getBoolOption('w'))
reportWarnings = true;
else if (op->getBoolOption('W'))
reportWarnings = false;
if (op->getBoolOption('s'))
JS::ContextOptionsRef(cx).toggleExtraWarnings();
@ -5604,6 +5623,163 @@ ProcessArgs(JSContext *cx, JSObject *obj_, OptionParser *op)
JS_SetDebugMode(cx, true);
}
jsCacheDir = op->getStringOption("js-cache");
if (jsCacheDir) {
if (op->getBoolOption("js-cache-per-process"))
jsCacheDir = JS_smprintf("%s/%u", jsCacheDir, (unsigned)getpid());
jsCacheAsmJSPath = JS_smprintf("%s/asmjs.cache", jsCacheDir);
}
if (op->getBoolOption('b'))
printTiming = true;
if (op->getBoolOption('D')) {
cx->runtime()->profilingScripts = true;
enableDisassemblyDumps = true;
}
#ifdef JS_THREADSAFE
int32_t threadCount = op->getIntOption("thread-count");
if (threadCount >= 0)
SetFakeCPUCount(threadCount);
#endif /* JS_THREADSAFE */
#if defined(JS_ION)
if (op->getBoolOption("no-ion")) {
enableIon = false;
JS::ContextOptionsRef(cx).toggleIon();
}
if (op->getBoolOption("no-asmjs")) {
enableAsmJS = false;
JS::ContextOptionsRef(cx).toggleAsmJS();
}
if (op->getBoolOption("no-baseline")) {
enableBaseline = false;
JS::ContextOptionsRef(cx).toggleBaseline();
}
if (const char *str = op->getStringOption("ion-gvn")) {
if (strcmp(str, "off") == 0) {
jit::js_JitOptions.disableGvn = true;
} else if (strcmp(str, "pessimistic") == 0) {
jit::js_JitOptions.forceGvnKind = true;
jit::js_JitOptions.forcedGvnKind = jit::GVN_Pessimistic;
} else if (strcmp(str, "optimistic") == 0) {
jit::js_JitOptions.forceGvnKind = true;
jit::js_JitOptions.forcedGvnKind = jit::GVN_Optimistic;
} else {
return OptionFailure("ion-gvn", str);
}
}
if (const char *str = op->getStringOption("ion-licm")) {
if (strcmp(str, "on") == 0)
jit::js_JitOptions.disableLicm = false;
else if (strcmp(str, "off") == 0)
jit::js_JitOptions.disableLicm = true;
else
return OptionFailure("ion-licm", str);
}
if (const char *str = op->getStringOption("ion-edgecase-analysis")) {
if (strcmp(str, "on") == 0)
jit::js_JitOptions.disableEdgeCaseAnalysis = false;
else if (strcmp(str, "off") == 0)
jit::js_JitOptions.disableEdgeCaseAnalysis = true;
else
return OptionFailure("ion-edgecase-analysis", str);
}
if (const char *str = op->getStringOption("ion-range-analysis")) {
if (strcmp(str, "on") == 0)
jit::js_JitOptions.disableRangeAnalysis = false;
else if (strcmp(str, "off") == 0)
jit::js_JitOptions.disableRangeAnalysis = true;
else
return OptionFailure("ion-range-analysis", str);
}
if (op->getBoolOption("ion-check-range-analysis"))
jit::js_JitOptions.checkRangeAnalysis = true;
if (const char *str = op->getStringOption("ion-inlining")) {
if (strcmp(str, "on") == 0)
jit::js_JitOptions.disableInlining = false;
else if (strcmp(str, "off") == 0)
jit::js_JitOptions.disableInlining = true;
else
return OptionFailure("ion-inlining", str);
}
if (const char *str = op->getStringOption("ion-osr")) {
if (strcmp(str, "on") == 0)
jit::js_JitOptions.osr = true;
else if (strcmp(str, "off") == 0)
jit::js_JitOptions.osr = false;
else
return OptionFailure("ion-osr", str);
}
if (const char *str = op->getStringOption("ion-limit-script-size")) {
if (strcmp(str, "on") == 0)
jit::js_JitOptions.limitScriptSize = true;
else if (strcmp(str, "off") == 0)
jit::js_JitOptions.limitScriptSize = false;
else
return OptionFailure("ion-limit-script-size", str);
}
int32_t useCount = op->getIntOption("ion-uses-before-compile");
if (useCount >= 0)
jit::js_JitOptions.setUsesBeforeCompile(useCount);
useCount = op->getIntOption("baseline-uses-before-compile");
if (useCount >= 0)
jit::js_JitOptions.baselineUsesBeforeCompile = useCount;
if (op->getBoolOption("baseline-eager"))
jit::js_JitOptions.baselineUsesBeforeCompile = 0;
if (const char *str = op->getStringOption("ion-regalloc")) {
if (strcmp(str, "lsra") == 0) {
jit::js_JitOptions.forceRegisterAllocator = true;
jit::js_JitOptions.forcedRegisterAllocator = jit::RegisterAllocator_LSRA;
} else if (strcmp(str, "backtracking") == 0) {
jit::js_JitOptions.forceRegisterAllocator = true;
jit::js_JitOptions.forcedRegisterAllocator = jit::RegisterAllocator_Backtracking;
} else if (strcmp(str, "stupid") == 0) {
jit::js_JitOptions.forceRegisterAllocator = true;
jit::js_JitOptions.forcedRegisterAllocator = jit::RegisterAllocator_Stupid;
} else {
return OptionFailure("ion-regalloc", str);
}
}
if (op->getBoolOption("ion-eager"))
jit::js_JitOptions.setEagerCompilation();
if (op->getBoolOption("ion-compile-try-catch"))
jit::js_JitOptions.compileTryCatch = true;
bool parallelCompilation = true;
if (const char *str = op->getStringOption("ion-parallel-compile")) {
if (strcmp(str, "off") == 0)
parallelCompilation = false;
else if (strcmp(str, "on") != 0)
return OptionFailure("ion-parallel-compile", str);
}
#ifdef JS_THREADSAFE
cx->runtime()->setParallelIonCompilationEnabled(parallelCompilation);
#endif
#endif /* JS_ION */
#ifdef DEBUG
if (op->getBoolOption("dump-entrained-variables"))
dumpEntrainedVariables = true;
#endif
/* |scriptArgs| gets bound on the global before any code is run. */
if (!BindScriptArgs(cx, obj, op))
return EXIT_FAILURE;
@ -5647,191 +5823,20 @@ ProcessArgs(JSContext *cx, JSObject *obj_, OptionParser *op)
return gExitCode ? gExitCode : EXIT_SUCCESS;
}
static bool
SetRuntimeOptions(JSRuntime *rt, const OptionParser &op)
{
#if defined(JS_ION)
bool enableBaseline = !op.getBoolOption("no-baseline");
bool enableIon = !op.getBoolOption("no-ion");
bool enableTypeInference = !op.getBoolOption("no-ti");
bool enableAsmJS = !op.getBoolOption("no-asmjs");
JS::RuntimeOptionsRef(rt).setBaseline(enableBaseline)
.setIon(enableIon)
.setTypeInference(enableTypeInference)
.setAsmJS(enableAsmJS);
if (const char *str = op.getStringOption("ion-gvn")) {
if (strcmp(str, "off") == 0) {
jit::js_JitOptions.disableGvn = true;
} else if (strcmp(str, "pessimistic") == 0) {
jit::js_JitOptions.forceGvnKind = true;
jit::js_JitOptions.forcedGvnKind = jit::GVN_Pessimistic;
} else if (strcmp(str, "optimistic") == 0) {
jit::js_JitOptions.forceGvnKind = true;
jit::js_JitOptions.forcedGvnKind = jit::GVN_Optimistic;
} else {
return OptionFailure("ion-gvn", str);
}
}
if (const char *str = op.getStringOption("ion-licm")) {
if (strcmp(str, "on") == 0)
jit::js_JitOptions.disableLicm = false;
else if (strcmp(str, "off") == 0)
jit::js_JitOptions.disableLicm = true;
else
return OptionFailure("ion-licm", str);
}
if (const char *str = op.getStringOption("ion-edgecase-analysis")) {
if (strcmp(str, "on") == 0)
jit::js_JitOptions.disableEdgeCaseAnalysis = false;
else if (strcmp(str, "off") == 0)
jit::js_JitOptions.disableEdgeCaseAnalysis = true;
else
return OptionFailure("ion-edgecase-analysis", str);
}
if (const char *str = op.getStringOption("ion-range-analysis")) {
if (strcmp(str, "on") == 0)
jit::js_JitOptions.disableRangeAnalysis = false;
else if (strcmp(str, "off") == 0)
jit::js_JitOptions.disableRangeAnalysis = true;
else
return OptionFailure("ion-range-analysis", str);
}
if (op.getBoolOption("ion-check-range-analysis"))
jit::js_JitOptions.checkRangeAnalysis = true;
if (const char *str = op.getStringOption("ion-inlining")) {
if (strcmp(str, "on") == 0)
jit::js_JitOptions.disableInlining = false;
else if (strcmp(str, "off") == 0)
jit::js_JitOptions.disableInlining = true;
else
return OptionFailure("ion-inlining", str);
}
if (const char *str = op.getStringOption("ion-osr")) {
if (strcmp(str, "on") == 0)
jit::js_JitOptions.osr = true;
else if (strcmp(str, "off") == 0)
jit::js_JitOptions.osr = false;
else
return OptionFailure("ion-osr", str);
}
if (const char *str = op.getStringOption("ion-limit-script-size")) {
if (strcmp(str, "on") == 0)
jit::js_JitOptions.limitScriptSize = true;
else if (strcmp(str, "off") == 0)
jit::js_JitOptions.limitScriptSize = false;
else
return OptionFailure("ion-limit-script-size", str);
}
int32_t useCount = op.getIntOption("ion-uses-before-compile");
if (useCount >= 0)
jit::js_JitOptions.setUsesBeforeCompile(useCount);
useCount = op.getIntOption("baseline-uses-before-compile");
if (useCount >= 0)
jit::js_JitOptions.baselineUsesBeforeCompile = useCount;
if (op.getBoolOption("baseline-eager"))
jit::js_JitOptions.baselineUsesBeforeCompile = 0;
if (const char *str = op.getStringOption("ion-regalloc")) {
if (strcmp(str, "lsra") == 0) {
jit::js_JitOptions.forceRegisterAllocator = true;
jit::js_JitOptions.forcedRegisterAllocator = jit::RegisterAllocator_LSRA;
} else if (strcmp(str, "backtracking") == 0) {
jit::js_JitOptions.forceRegisterAllocator = true;
jit::js_JitOptions.forcedRegisterAllocator = jit::RegisterAllocator_Backtracking;
} else if (strcmp(str, "stupid") == 0) {
jit::js_JitOptions.forceRegisterAllocator = true;
jit::js_JitOptions.forcedRegisterAllocator = jit::RegisterAllocator_Stupid;
} else {
return OptionFailure("ion-regalloc", str);
}
}
if (op.getBoolOption("ion-eager"))
jit::js_JitOptions.setEagerCompilation();
if (op.getBoolOption("ion-compile-try-catch"))
jit::js_JitOptions.compileTryCatch = true;
bool parallelCompilation = true;
if (const char *str = op.getStringOption("ion-parallel-compile")) {
if (strcmp(str, "off") == 0)
parallelCompilation = false;
else if (strcmp(str, "on") != 0)
return OptionFailure("ion-parallel-compile", str);
}
#ifdef JS_THREADSAFE
rt->setParallelIonCompilationEnabled(parallelCompilation);
#endif
#if defined(JS_CODEGEN_X86) && defined(DEBUG)
if (op.getBoolOption("no-fpu"))
JSC::MacroAssembler::SetFloatingPointDisabled();
#endif
#if (defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_X64)) && defined(DEBUG)
if (op.getBoolOption("no-sse3")) {
JSC::MacroAssembler::SetSSE3Disabled();
PropagateFlagToNestedShells("--no-sse3");
}
if (op.getBoolOption("no-sse4")) {
JSC::MacroAssembler::SetSSE4Disabled();
PropagateFlagToNestedShells("--no-sse4");
}
#endif
#endif // JS_ION
#ifdef JS_ARM_SIMULATOR
if (op.getBoolOption("arm-sim-icache-checks"))
jit::Simulator::ICacheCheckingEnabled = true;
int32_t stopAt = op.getIntOption("arm-sim-stop-at");
if (stopAt >= 0)
jit::Simulator::StopSimAt = stopAt;
#endif
reportWarnings = op.getBoolOption('w');
compileOnly = op.getBoolOption('c');
printTiming = op.getBoolOption('b');
rt->profilingScripts = enableDisassemblyDumps = op.getBoolOption('D');
jsCacheDir = op.getStringOption("js-cache");
if (jsCacheDir) {
if (op.getBoolOption("js-cache-per-process"))
jsCacheDir = JS_smprintf("%s/%u", jsCacheDir, (unsigned)getpid());
jsCacheAsmJSPath = JS_smprintf("%s/asmjs.cache", jsCacheDir);
}
#ifdef JS_THREADSAFE
int32_t threadCount = op.getIntOption("thread-count");
if (threadCount >= 0)
SetFakeCPUCount(threadCount);
#endif /* JS_THREADSAFE */
#ifdef DEBUG
dumpEntrainedVariables = op.getBoolOption("dump-entrained-variables");
#endif
return true;
}
static int
Shell(JSContext *cx, OptionParser *op, char **envp)
{
JSAutoRequest ar(cx);
/*
* First check to see if type inference is enabled. These flags
* must be set on the compartment when it is constructed.
*/
if (op->getBoolOption("no-ti")) {
enableTypeInference = false;
JS::ContextOptionsRef(cx).toggleTypeInference();
}
if (op->getBoolOption("fuzzing-safe"))
fuzzingSafe = true;
else
@ -6047,7 +6052,33 @@ main(int argc, char **argv, char **envp)
* Process OOM options as early as possible so that we can observe as many
* allocations as possible.
*/
OOM_printAllocationCount = op.getBoolOption('O');
if (op.getBoolOption('O'))
OOM_printAllocationCount = true;
#if defined(JS_CODEGEN_X86) && defined(JS_ION)
if (op.getBoolOption("no-fpu"))
JSC::MacroAssembler::SetFloatingPointDisabled();
#endif
#if (defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_X64)) && defined(JS_ION)
if (op.getBoolOption("no-sse3")) {
JSC::MacroAssembler::SetSSE3Disabled();
PropagateFlagToNestedShells("--no-sse3");
}
if (op.getBoolOption("no-sse4")) {
JSC::MacroAssembler::SetSSE4Disabled();
PropagateFlagToNestedShells("--no-sse4");
}
#endif
#endif
#ifdef JS_ARM_SIMULATOR
if (op.getBoolOption("arm-sim-icache-checks"))
jit::Simulator::ICacheCheckingEnabled = true;
int32_t stopAt = op.getIntOption("arm-sim-stop-at");
if (stopAt >= 0)
jit::Simulator::StopSimAt = stopAt;
#endif
// Start the engine.
@ -6058,10 +6089,6 @@ main(int argc, char **argv, char **envp)
rt = JS_NewRuntime(32L * 1024L * 1024L, JS_USE_HELPER_THREADS);
if (!rt)
return 1;
if (!SetRuntimeOptions(rt, op))
return 1;
gTimeoutFunc = NullValue();
if (!JS_AddNamedValueRootRT(rt, &gTimeoutFunc, "gTimeoutFunc"))
return 1;

View File

@ -1694,7 +1694,6 @@ struct JSRuntime : public JS::shadow::Runtime,
void addSizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf, JS::RuntimeSizes *runtime);
private:
JS::RuntimeOptions options_;
JSUseHelperThreads useHelperThreads_;
@ -1742,13 +1741,6 @@ struct JSRuntime : public JS::shadow::Runtime,
return isWorkerRuntime_;
}
const JS::RuntimeOptions &options() const {
return options_;
}
JS::RuntimeOptions &options() {
return options_;
}
#ifdef DEBUG
public:
js::AutoEnterPolicy *enteredPolicy;

View File

@ -10,6 +10,8 @@
#include "nsIPrincipal.h"
#include "nsWeakReference.h"
#include "js/RootingAPI.h"
// This interface is public only because it is used in jsd.
// Once jsd is gone this file should be moved back to xpconnect/src.
@ -43,7 +45,7 @@ public:
}
private:
nsCOMPtr<nsIPrincipal> mPrincipal;
JSObject *mGlobalJSObject;
JS::TenuredHeap<JSObject*> mGlobalJSObject;
};
#endif // __SANDBOXPRIVATE_H__

View File

@ -12,6 +12,8 @@
#include "nsIScriptObjectPrincipal.h"
#include "nsIXPCScriptable.h"
#include "js/HeapAPI.h"
class BackstagePass : public nsIGlobalObject,
public nsIScriptObjectPrincipal,
public nsIXPCScriptable,
@ -48,7 +50,7 @@ public:
private:
nsCOMPtr<nsIPrincipal> mPrincipal;
JSObject *mGlobal;
JS::TenuredHeap<JSObject*> mGlobal;
};
NS_EXPORT nsresult

View File

@ -3245,41 +3245,26 @@ nsXPCComponents_Utils::Dispatch(HandleValue runnableArg, HandleValue scope,
return NS_DispatchToMainThread(run);
}
#define GENERATE_JSCONTEXTOPTION_GETTER_SETTER(_attr, _getter, _setter) \
NS_IMETHODIMP \
nsXPCComponents_Utils::Get## _attr(JSContext* cx, bool* aValue) \
{ \
*aValue = ContextOptionsRef(cx)._getter(); \
return NS_OK; \
} \
NS_IMETHODIMP \
nsXPCComponents_Utils::Set## _attr(JSContext* cx, bool aValue) \
{ \
ContextOptionsRef(cx)._setter(aValue); \
return NS_OK; \
#define GENERATE_JSOPTION_GETTER_SETTER(_attr, _getter, _setter) \
NS_IMETHODIMP \
nsXPCComponents_Utils::Get## _attr(JSContext* cx, bool* aValue) \
{ \
*aValue = ContextOptionsRef(cx)._getter(); \
return NS_OK; \
} \
NS_IMETHODIMP \
nsXPCComponents_Utils::Set## _attr(JSContext* cx, bool aValue) \
{ \
ContextOptionsRef(cx)._setter(aValue); \
return NS_OK; \
}
#define GENERATE_JSRUNTIMEOPTION_GETTER_SETTER(_attr, _getter, _setter) \
NS_IMETHODIMP \
nsXPCComponents_Utils::Get## _attr(JSContext* cx, bool* aValue) \
{ \
*aValue = RuntimeOptionsRef(cx)._getter(); \
return NS_OK; \
} \
NS_IMETHODIMP \
nsXPCComponents_Utils::Set## _attr(JSContext* cx, bool aValue) \
{ \
RuntimeOptionsRef(cx)._setter(aValue); \
return NS_OK; \
}
GENERATE_JSOPTION_GETTER_SETTER(Strict, extraWarnings, setExtraWarnings)
GENERATE_JSOPTION_GETTER_SETTER(Werror, werror, setWerror)
GENERATE_JSOPTION_GETTER_SETTER(Strict_mode, strictMode, setStrictMode)
GENERATE_JSOPTION_GETTER_SETTER(Ion, ion, setIon)
GENERATE_JSCONTEXTOPTION_GETTER_SETTER(Strict, extraWarnings, setExtraWarnings)
GENERATE_JSCONTEXTOPTION_GETTER_SETTER(Werror, werror, setWerror)
GENERATE_JSCONTEXTOPTION_GETTER_SETTER(Strict_mode, strictMode, setStrictMode)
GENERATE_JSRUNTIMEOPTION_GETTER_SETTER(Ion, ion, setIon)
#undef GENERATE_JSCONTEXTOPTION_GETTER_SETTER
#undef GENERATE_JSRUNTIMEOPTION_GETTER_SETTER
#undef GENERATE_JSOPTION_GETTER_SETTER
NS_IMETHODIMP
nsXPCComponents_Utils::SetGCZeal(int32_t aValue, JSContext* cx)

View File

@ -46,7 +46,6 @@
#include "nsAboutProtocolUtils.h"
#include "GeckoProfiler.h"
#include "nsIXULRuntime.h"
#include "nsJSPrincipals.h"
#ifdef MOZ_CRASHREPORTER
@ -1499,45 +1498,6 @@ void XPCJSRuntime::SystemIsBeingShutDown()
Enumerate(DetachedWrappedNativeProtoShutdownMarker, nullptr);
}
#define JS_OPTIONS_DOT_STR "javascript.options."
static void
ReloadPrefsCallback(const char *pref, void *data)
{
XPCJSRuntime *runtime = reinterpret_cast<XPCJSRuntime *>(data);
JSRuntime *rt = runtime->Runtime();
bool safeMode = false;
nsCOMPtr<nsIXULRuntime> xr = do_GetService("@mozilla.org/xre/runtime;1");
if (xr) {
xr->GetInSafeMode(&safeMode);
}
bool useBaseline = Preferences::GetBool(JS_OPTIONS_DOT_STR "baselinejit") && !safeMode;
bool useTypeInference = Preferences::GetBool(JS_OPTIONS_DOT_STR "typeinference") && !safeMode;
bool useIon = Preferences::GetBool(JS_OPTIONS_DOT_STR "ion") && !safeMode;
bool useAsmJS = Preferences::GetBool(JS_OPTIONS_DOT_STR "asmjs") && !safeMode;
bool parallelParsing = Preferences::GetBool(JS_OPTIONS_DOT_STR "parallel_parsing");
bool parallelIonCompilation = Preferences::GetBool(JS_OPTIONS_DOT_STR
"ion.parallel_compilation");
bool useBaselineEager = Preferences::GetBool(JS_OPTIONS_DOT_STR
"baselinejit.unsafe_eager_compilation");
bool useIonEager = Preferences::GetBool(JS_OPTIONS_DOT_STR "ion.unsafe_eager_compilation");
JS::RuntimeOptionsRef(rt).setBaseline(useBaseline)
.setTypeInference(useTypeInference)
.setIon(useIon)
. setAsmJS(useAsmJS);
JS_SetParallelParsingEnabled(rt, parallelParsing);
JS_SetParallelIonCompilationEnabled(rt, parallelIonCompilation);
JS_SetGlobalJitCompilerOption(rt, JSJITCOMPILER_BASELINE_USECOUNT_TRIGGER,
useBaselineEager ? 0 : -1);
JS_SetGlobalJitCompilerOption(rt, JSJITCOMPILER_ION_USECOUNT_TRIGGER,
useIonEager ? 0 : -1);
}
XPCJSRuntime::~XPCJSRuntime()
{
// This destructor runs before ~CycleCollectedJSRuntime, which does the
@ -1623,8 +1583,6 @@ XPCJSRuntime::~XPCJSRuntime()
MOZ_ASSERT(mScratchStrings[i].empty(), "Short lived string still in use");
}
#endif
Preferences::UnregisterCallback(ReloadPrefsCallback, JS_OPTIONS_DOT_STR, this);
}
static void
@ -3178,10 +3136,6 @@ XPCJSRuntime::XPCJSRuntime(nsXPConnect* aXPConnect)
if (!JS_GetGlobalDebugHooks(runtime)->debuggerHandler)
xpc_InstallJSDebuggerKeywordHandler(runtime);
#endif
// Watch for the JS boolean options.
ReloadPrefsCallback(nullptr, this);
Preferences::RegisterCallback(ReloadPrefsCallback, JS_OPTIONS_DOT_STR, this);
}
// static

View File

@ -1039,11 +1039,11 @@ ProcessArgsForCompartment(JSContext *cx, char **argv, int argc)
ContextOptionsRef(cx).toggleExtraWarnings();
break;
case 'I':
RuntimeOptionsRef(cx).toggleIon()
ContextOptionsRef(cx).toggleIon()
.toggleAsmJS();
break;
case 'n':
RuntimeOptionsRef(cx).toggleTypeInference();
ContextOptionsRef(cx).toggleTypeInference();
break;
}
}
@ -1487,6 +1487,9 @@ XRE_XPCShellMain(int argc, char **argv, char **envp)
return 1;
}
// Ion not enabled yet here because of bug 931861.
JS::ContextOptionsRef(cx).setBaseline(true);
argc--;
argv++;
ProcessArgsForCompartment(cx, argv, argc);

View File

@ -361,12 +361,56 @@ TraceXPCGlobal(JSTracer *trc, JSObject *obj)
mozilla::dom::TraceProtoAndIfaceCache(trc, obj);
}
#ifdef DEBUG
#include "mozilla/Preferences.h"
#include "nsIXULRuntime.h"
static void
CheckTypeInference(JSContext *cx, const JSClass *clasp, nsIPrincipal *principal)
{
// Check that the global class isn't whitelisted.
if (strcmp(clasp->name, "Sandbox") ||
strcmp(clasp->name, "nsXBLPrototypeScript compilation scope") ||
strcmp(clasp->name, "nsXULPrototypeScript compilation scope"))
return;
// Check that the pref is on.
if (!mozilla::Preferences::GetBool("javascript.options.typeinference"))
return;
// Check that we're not chrome.
bool isSystem;
nsIScriptSecurityManager* ssm;
ssm = XPCWrapper::GetSecurityManager();
if (NS_FAILED(ssm->IsSystemPrincipal(principal, &isSystem)) || !isSystem)
return;
// Check that safe mode isn't on.
bool safeMode;
nsCOMPtr<nsIXULRuntime> xr = do_GetService("@mozilla.org/xre/runtime;1");
if (!xr) {
NS_WARNING("Couldn't get XUL runtime!");
return;
}
if (NS_FAILED(xr->GetInSafeMode(&safeMode)) || safeMode)
return;
// Finally, do the damn assert.
MOZ_ASSERT(ContextOptionsRef(cx).typeInference());
}
#else
#define CheckTypeInference(cx, clasp, principal) {}
#endif
namespace xpc {
JSObject*
CreateGlobalObject(JSContext *cx, const JSClass *clasp, nsIPrincipal *principal,
JS::CompartmentOptions& aOptions)
{
// Make sure that Type Inference is enabled for everything non-chrome.
// Sandboxes and compilation scopes are exceptions. See bug 744034.
CheckTypeInference(cx, clasp, principal);
MOZ_ASSERT(NS_IsMainThread(), "using a principal off the main thread?");
MOZ_ASSERT(principal);
@ -376,7 +420,6 @@ CreateGlobalObject(JSContext *cx, const JSClass *clasp, nsIPrincipal *principal,
if (!global)
return nullptr;
JSAutoCompartment ac(cx, global);
// The constructor automatically attaches the scope to the compartment private
// of |global|.
(void) new XPCWrappedNativeScope(cx, global);

View File

@ -600,6 +600,17 @@ static void AdjustForScrollBars(ScreenIntRect& aToAdjust, nsIScrollableFrame* aS
}
}
static bool gPrintApzcTree = false;
static bool GetApzcTreePrintPref() {
static bool initialized = false;
if (!initialized) {
Preferences::AddBoolVarCache(&gPrintApzcTree, "apz.printtree", gPrintApzcTree);
initialized = true;
}
return gPrintApzcTree;
}
static void RecordFrameMetrics(nsIFrame* aForFrame,
nsIFrame* aScrollFrame,
const nsIFrame* aReferenceFrame,
@ -741,6 +752,14 @@ static void RecordFrameMetrics(nsIFrame* aForFrame,
AdjustForScrollBars(metrics.mCompositionBounds, scrollableFrame);
}
if (GetApzcTreePrintPref()) {
if (nsIContent* content = frameForCompositionBoundsCalculation->GetContent()) {
nsAutoString contentDescription;
content->Describe(contentDescription);
metrics.SetContentDescription(NS_LossyConvertUTF16toASCII(contentDescription).get());
}
}
metrics.mPresShellId = presShell->GetPresShellId();
// If the scroll frame's content is marked 'scrollgrab', record this
@ -2684,13 +2703,18 @@ nsRect
nsDisplayBorder::GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap)
{
*aSnap = true;
const nsStyleBorder *styleBorder = mFrame->StyleBorder();
return CalculateBounds(*mFrame->StyleBorder());
}
nsRect
nsDisplayBorder::CalculateBounds(const nsStyleBorder& aStyleBorder)
{
nsRect borderBounds(ToReferenceFrame(), mFrame->GetSize());
if (styleBorder->IsBorderImageLoaded()) {
borderBounds.Inflate(mFrame->StyleBorder()->GetImageOutset());
if (aStyleBorder.IsBorderImageLoaded()) {
borderBounds.Inflate(aStyleBorder.GetImageOutset());
return borderBounds;
} else {
nsMargin border = styleBorder->GetComputedBorder();
nsMargin border = aStyleBorder.GetComputedBorder();
nsRect result;
if (border.top > 0) {
result = nsRect(borderBounds.X(), borderBounds.Y(), borderBounds.Width(), border.top);

View File

@ -1919,6 +1919,9 @@ public:
virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
const nsDisplayItemGeometry* aGeometry,
nsRegion* aInvalidRegion) MOZ_OVERRIDE;
protected:
nsRect CalculateBounds(const nsStyleBorder& aStyleBorder);
};
/**

View File

@ -999,10 +999,11 @@ nsIFrame::IsTransformed() const
}
bool
nsIFrame::HasOpacity() const
nsIFrame::HasOpacityInternal(float aThreshold) const
{
MOZ_ASSERT(0.0 <= aThreshold && aThreshold <= 1.0, "Invalid argument");
const nsStyleDisplay* displayStyle = StyleDisplay();
return StyleDisplay()->mOpacity < 1.0f ||
return StyleDisplay()->mOpacity < aThreshold ||
(displayStyle->mWillChangeBitField & NS_STYLE_WILL_CHANGE_OPACITY) ||
(mContent &&
nsLayoutUtils::HasAnimationsForCompositor(mContent,
@ -1863,7 +1864,7 @@ nsIFrame::BuildDisplayListForStackingContext(nsDisplayListBuilder* aBuilder,
inTransform = true;
}
bool useOpacity = HasOpacity() && !nsSVGUtils::CanOptimizeOpacity(this);
bool useOpacity = HasVisualOpacity() && !nsSVGUtils::CanOptimizeOpacity(this);
bool useBlendMode = disp->mMixBlendMode != NS_STYLE_BLEND_NORMAL;
bool usingSVGEffects = nsSVGIntegrationUtils::UsingEffectsForFrame(this);
bool useStickyPosition = disp->mPosition == NS_STYLE_POSITION_STICKY &&

View File

@ -1136,8 +1136,25 @@ public:
* an SVG viewBox attribute).
*/
bool IsTransformed() const;
bool HasOpacity() const;
/**
* Returns true if the frame is translucent for the purposes of creating a
* stacking context.
*/
bool HasOpacity() const
{
return HasOpacityInternal(1.0f);
}
/**
* Returns true if the frame is translucent for display purposes.
*/
bool HasVisualOpacity() const
{
// Treat an opacity value of 0.99 and above as opaque. This is an
// optimization aimed at Web content which use opacity:0.99 as a hint for
// creating a stacking context only.
return HasOpacityInternal(0.99f);
}
/**
* Return true if this frame might be using a transform getter.
@ -3050,6 +3067,8 @@ private:
template<bool IsLessThanOrEqual(nsIFrame*, nsIFrame*)>
static nsIFrame* MergeSort(nsIFrame *aSource);
bool HasOpacityInternal(float aThreshold) const;
#ifdef DEBUG_FRAME_DUMP
public:
static void IndentBy(FILE* out, int32_t aIndent) {

View File

@ -180,6 +180,55 @@ FindCellProperty(const nsIFrame* aCellFrame,
return propertyData;
}
static void
ApplyBorderToStyle(const nsMathMLmtdFrame* aFrame,
nsStyleBorder& aStyleBorder)
{
int32_t rowIndex;
int32_t columnIndex;
aFrame->GetRowIndex(rowIndex);
aFrame->GetColIndex(columnIndex);
nscoord borderWidth =
aFrame->PresContext()->GetBorderWidthTable()[NS_STYLE_BORDER_WIDTH_THIN];
nsTArray<int8_t>* rowLinesList =
FindCellProperty(aFrame, RowLinesProperty());
nsTArray<int8_t>* columnLinesList =
FindCellProperty(aFrame, ColumnLinesProperty());
// We don't place a row line on top of the first row
if (rowIndex > 0 && rowLinesList) {
// If the row number is greater than the number of provided rowline
// values, we simply repeat the last value.
int32_t listLength = rowLinesList->Length();
if (rowIndex < listLength) {
aStyleBorder.SetBorderStyle(NS_SIDE_TOP,
rowLinesList->ElementAt(rowIndex - 1));
} else {
aStyleBorder.SetBorderStyle(NS_SIDE_TOP,
rowLinesList->ElementAt(listLength - 1));
}
aStyleBorder.SetBorderWidth(NS_SIDE_TOP, borderWidth);
}
// We don't place a column line on the left of the first column.
if (columnIndex > 0 && columnLinesList) {
// If the column number is greater than the number of provided columline
// values, we simply repeat the last value.
int32_t listLength = columnLinesList->Length();
if (columnIndex < listLength) {
aStyleBorder.SetBorderStyle(NS_SIDE_LEFT,
columnLinesList->ElementAt(columnIndex - 1));
} else {
aStyleBorder.SetBorderStyle(NS_SIDE_LEFT,
columnLinesList->ElementAt(listLength - 1));
}
aStyleBorder.SetBorderWidth(NS_SIDE_LEFT, borderWidth);
}
}
/*
* A variant of the nsDisplayBorder contains special code to render a border
* around a nsMathMLmtdFrame based on the rowline and columnline properties
@ -192,52 +241,17 @@ public:
{
}
virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) MOZ_OVERRIDE
{
nsStyleBorder styleBorder = *mFrame->StyleBorder();
ApplyBorderToStyle(static_cast<nsMathMLmtdFrame*>(mFrame), styleBorder);
return CalculateBounds(styleBorder);
}
virtual void Paint(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx) MOZ_OVERRIDE
{
int32_t rowIndex;
int32_t columnIndex;
static_cast<nsTableCellFrame*>(mFrame)->
GetCellIndexes(rowIndex, columnIndex);
nsStyleBorder styleBorder = *mFrame->StyleBorder();
nscoord borderWidth =
mFrame->PresContext()->GetBorderWidthTable()[NS_STYLE_BORDER_WIDTH_THIN];
nsTArray<int8_t>* rowLinesList =
FindCellProperty(mFrame, RowLinesProperty());
nsTArray<int8_t>* columnLinesList =
FindCellProperty(mFrame, ColumnLinesProperty());
// We don't place a row line on top of the first row
if (rowIndex > 0 && rowLinesList) {
// If the row number is greater than the number of provided rowline
// values, we simply repeat the last value.
int32_t listLength = rowLinesList->Length();
if (rowIndex < listLength) {
styleBorder.SetBorderStyle(NS_SIDE_TOP,
rowLinesList->ElementAt(rowIndex - 1));
} else {
styleBorder.SetBorderStyle(NS_SIDE_TOP,
rowLinesList->ElementAt(listLength - 1));
}
styleBorder.SetBorderWidth(NS_SIDE_TOP, borderWidth);
}
// We don't place a column line on the left of the first column.
if (columnIndex > 0 && columnLinesList) {
// If the column number is greater than the number of provided columline
// values, we simply repeat the last value.
int32_t listLength = columnLinesList->Length();
if (columnIndex < listLength) {
styleBorder.SetBorderStyle(NS_SIDE_LEFT,
columnLinesList->ElementAt(columnIndex - 1));
} else {
styleBorder.SetBorderStyle(NS_SIDE_LEFT,
columnLinesList->ElementAt(listLength - 1));
}
styleBorder.SetBorderWidth(NS_SIDE_LEFT, borderWidth);
}
ApplyBorderToStyle(static_cast<nsMathMLmtdFrame*>(mFrame), styleBorder);
nsPoint offset = ToReferenceFrame();
nsCSSRendering::PaintBorderWithStyleBorder(mFrame->PresContext(), *aCtx,
@ -837,6 +851,16 @@ nsMathMLmtdFrame::ProcessBorders(nsTableFrame* aFrame,
nsDisplaymtdBorder(aBuilder, this));
return NS_OK;
}
nsMargin*
nsMathMLmtdFrame::GetBorderWidth(nsMargin& aBorder) const
{
nsStyleBorder styleBorder = *StyleBorder();
ApplyBorderToStyle(this, styleBorder);
aBorder = styleBorder.GetComputedBorder();
return &aBorder;
}
// --------
// implementation of nsMathMLmtdInnerFrame

View File

@ -206,6 +206,8 @@ public:
return nsTableCellFrame::IsFrameOfType(aFlags & ~(nsIFrame::eMathML));
}
virtual nsMargin* GetBorderWidth(nsMargin& aBorder) const MOZ_OVERRIDE;
protected:
nsMathMLmtdFrame(nsStyleContext* aContext) : nsTableCellFrame(aContext) {}
virtual ~nsMathMLmtdFrame();

View File

@ -1562,14 +1562,14 @@ random-if(!winWidget) == 574907-2.html 574907-2-ref.html
random-if(!winWidget) fails-if(winWidget&&!d2d) random-if(winWidget&&d2d) != 574907-3.html 574907-3-notref.html
== 577838-1.html 577838-1-ref.html
== 577838-2.html 577838-2-ref.html
fails-if(Android&&AndroidVersion!=17) == 579323-1.html 579323-1-ref.html
== 579323-1.html 579323-1-ref.html
== 579349-1.html 579349-1-ref.html
== 579655-1.html 579655-1-ref.html
skip-if(B2G) fails-if(Android) == 579808-1.html 579808-1-ref.html
skip-if(B2G) fails-if(Android) random-if(layersGPUAccelerated) == 579985-1.html 579985-1-ref.html # bug 623452 for WinXP; this bug was only for a regression in BasicLayers anyway
skip-if(B2G) skip-if(Android) == 580160-1.html 580160-1-ref.html # bug 920927 for Android; issues without the test-plugin
HTTP(..) == 580863-1.html 580863-1-ref.html
skip-if(B2G) fails-if(Android) random-if(layersGPUAccelerated) fails-if(/^Windows\x20NT\x205\.1/.test(http.oscpu)) == 581317-1.html 581317-1-ref.html # bug 623456 for WinXP
skip-if(B2G) fails-if(Android) random-if(layersGPUAccelerated) == 581317-1.html 581317-1-ref.html
== 581579-1.html 581579-1-ref.html
== 582037-1a.html 582037-1-ref.html
== 582037-1b.html 582037-1-ref.html
@ -1607,7 +1607,7 @@ skip-if(B2G) == 600803-1.html 600803-1-ref.html
== 602200-1.html 602200-1-ref.html
== 602200-2.html 602200-2-ref.html
fuzzy-if(Android&&AndroidVersion>=15,8,20) == 602200-3.html 602200-3-ref.html
fails-if(Android&&AndroidVersion!=17) == 602200-4.html 602200-4-ref.html
== 602200-4.html 602200-4-ref.html
== 603423-1.html 603423-1-ref.html
== 604737.html 604737-ref.html
== 605138-1.html 605138-1-ref.html

View File

@ -0,0 +1,77 @@
<!-- -*- mode: HTML; tab-width: 2; indent-tabs-mode: nil; -*- -->
<!-- vim: set tabstop=2 expandtab shiftwidth=2 textwidth=80: -->
<!DOCTYPE html>
<html>
<head>
<title>mtable frame</title>
<!-- Copyright (c) 2011 Design Science, Inc.
License: Apache License 2.0 -->
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
</head>
<body>
<math>
<mtable>
<mtr>
<mtd>
<mn>1</mn>
</mtd>
<mtd>
<mn>2</mn>
</mtd>
<mtd>
<mn>3</mn>
</mtd>
<mtd>
<mn>4</mn>
</mtd>
</mtr>
<mtr>
<mtd>
<mn>5</mn>
</mtd>
<mtd>
<mn>6</mn>
</mtd>
<mtd>
<mn>7</mn>
</mtd>
<mtd>
<mn>8</mn>
</mtd>
</mtr>
<mtr>
<mtd>
<mn>9</mn>
</mtd>
<mtd>
<mn>10</mn>
</mtd>
<mtd>
<mn>11</mn>
</mtd>
<mtd>
<mn>12</mn>
</mtd>
</mtr>
<mtr>
<mtd>
<mn>13</mn>
</mtd>
<mtd>
<mn>14</mn>
</mtd>
<mtd>
<mn>15</mn>
</mtd>
<mtd>
<mn>16</mn>
</mtd>
</mtr>
</mtable>
</math>
</body>
</html>

View File

@ -0,0 +1,77 @@
<!-- -*- mode: HTML; tab-width: 2; indent-tabs-mode: nil; -*- -->
<!-- vim: set tabstop=2 expandtab shiftwidth=2 textwidth=80: -->
<!DOCTYPE html>
<html>
<head>
<title>mtable frame</title>
<!-- Copyright (c) 2011 Design Science, Inc.
License: Apache License 2.0 -->
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
</head>
<body>
<math>
<mtable columnlines="none">
<mtr>
<mtd>
<mn>1</mn>
</mtd>
<mtd>
<mn>2</mn>
</mtd>
<mtd>
<mn>3</mn>
</mtd>
<mtd>
<mn>4</mn>
</mtd>
</mtr>
<mtr>
<mtd>
<mn>5</mn>
</mtd>
<mtd>
<mn>6</mn>
</mtd>
<mtd>
<mn>7</mn>
</mtd>
<mtd>
<mn>8</mn>
</mtd>
</mtr>
<mtr>
<mtd>
<mn>9</mn>
</mtd>
<mtd>
<mn>10</mn>
</mtd>
<mtd>
<mn>11</mn>
</mtd>
<mtd>
<mn>12</mn>
</mtd>
</mtr>
<mtr>
<mtd>
<mn>13</mn>
</mtd>
<mtd>
<mn>14</mn>
</mtd>
<mtd>
<mn>15</mn>
</mtd>
<mtd>
<mn>16</mn>
</mtd>
</mtr>
</mtable>
</math>
</body>
</html>

View File

@ -0,0 +1,77 @@
<!-- -*- mode: HTML; tab-width: 2; indent-tabs-mode: nil; -*- -->
<!-- vim: set tabstop=2 expandtab shiftwidth=2 textwidth=80: -->
<!DOCTYPE html>
<html>
<head>
<title>mtable frame</title>
<!-- Copyright (c) 2011 Design Science, Inc.
License: Apache License 2.0 -->
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
</head>
<body>
<math>
<mtable columnlines="solid">
<mtr>
<mtd>
<mn>1</mn>
</mtd>
<mtd>
<mn>2</mn>
</mtd>
<mtd>
<mn>3</mn>
</mtd>
<mtd>
<mn>4</mn>
</mtd>
</mtr>
<mtr>
<mtd>
<mn>5</mn>
</mtd>
<mtd>
<mn>6</mn>
</mtd>
<mtd>
<mn>7</mn>
</mtd>
<mtd>
<mn>8</mn>
</mtd>
</mtr>
<mtr>
<mtd>
<mn>9</mn>
</mtd>
<mtd>
<mn>10</mn>
</mtd>
<mtd>
<mn>11</mn>
</mtd>
<mtd>
<mn>12</mn>
</mtd>
</mtr>
<mtr>
<mtd>
<mn>13</mn>
</mtd>
<mtd>
<mn>14</mn>
</mtd>
<mtd>
<mn>15</mn>
</mtd>
<mtd>
<mn>16</mn>
</mtd>
</mtr>
</mtable>
</math>
</body>
</html>

View File

@ -0,0 +1,77 @@
<!-- -*- mode: HTML; tab-width: 2; indent-tabs-mode: nil; -*- -->
<!-- vim: set tabstop=2 expandtab shiftwidth=2 textwidth=80: -->
<!DOCTYPE html>
<html>
<head>
<title>mtable frame</title>
<!-- Copyright (c) 2011 Design Science, Inc.
License: Apache License 2.0 -->
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
</head>
<body>
<math>
<mtable columnlines="dashed">
<mtr>
<mtd>
<mn>1</mn>
</mtd>
<mtd>
<mn>2</mn>
</mtd>
<mtd>
<mn>3</mn>
</mtd>
<mtd>
<mn>4</mn>
</mtd>
</mtr>
<mtr>
<mtd>
<mn>5</mn>
</mtd>
<mtd>
<mn>6</mn>
</mtd>
<mtd>
<mn>7</mn>
</mtd>
<mtd>
<mn>8</mn>
</mtd>
</mtr>
<mtr>
<mtd>
<mn>9</mn>
</mtd>
<mtd>
<mn>10</mn>
</mtd>
<mtd>
<mn>11</mn>
</mtd>
<mtd>
<mn>12</mn>
</mtd>
</mtr>
<mtr>
<mtd>
<mn>13</mn>
</mtd>
<mtd>
<mn>14</mn>
</mtd>
<mtd>
<mn>15</mn>
</mtd>
<mtd>
<mn>16</mn>
</mtd>
</mtr>
</mtable>
</math>
</body>
</html>

View File

@ -0,0 +1,41 @@
<!-- -*- mode: HTML; tab-width: 2; indent-tabs-mode: nil; -*- -->
<!-- vim: set tabstop=2 expandtab shiftwidth=2 textwidth=80: -->
<!DOCTYPE html>
<html>
<head>
<title>mtable frame</title>
<!-- Copyright (c) 2011 Design Science, Inc.
License: Apache License 2.0 -->
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
</head>
<body>
<math>
<mtable columnlines="solid none dashed dashed dashed">
<mtr>
<mtd>
<mn>1</mn>
</mtd>
<mtd>
<mn>2</mn>
</mtd>
<mtd>
<mn>3</mn>
</mtd>
<mtd>
<mn>4</mn>
</mtd>
<mtd>
<mn>5</mn>
</mtd>
<mtd>
<mn>*</mn>
</mtd>
</mtr>
</mtable>
</math>
</body>
</html>

View File

@ -0,0 +1,41 @@
<!-- -*- mode: HTML; tab-width: 2; indent-tabs-mode: nil; -*- -->
<!-- vim: set tabstop=2 expandtab shiftwidth=2 textwidth=80: -->
<!DOCTYPE html>
<html>
<head>
<title>mtable frame</title>
<!-- Copyright (c) 2011 Design Science, Inc.
License: Apache License 2.0 -->
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
</head>
<body>
<math>
<mtable columnlines="solid none dashed">
<mtr>
<mtd>
<mn>1</mn>
</mtd>
<mtd>
<mn>2</mn>
</mtd>
<mtd>
<mn>3</mn>
</mtd>
<mtd>
<mn>4</mn>
</mtd>
<mtd>
<mn>5</mn>
</mtd>
<mtd>
<mn>*</mn>
</mtd>
</mtr>
</mtable>
</math>
</body>
</html>

View File

@ -0,0 +1,41 @@
<!-- -*- mode: HTML; tab-width: 2; indent-tabs-mode: nil; -*- -->
<!-- vim: set tabstop=2 expandtab shiftwidth=2 textwidth=80: -->
<!DOCTYPE html>
<html>
<head>
<title>mtable frame</title>
<!-- Copyright (c) 2011 Design Science, Inc.
License: Apache License 2.0 -->
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
</head>
<body>
<math>
<mtable columnlines="solid none dashed dashed dashed solid solid none solid none">
<mtr>
<mtd>
<mn>1</mn>
</mtd>
<mtd>
<mn>2</mn>
</mtd>
<mtd>
<mn>3</mn>
</mtd>
<mtd>
<mn>4</mn>
</mtd>
<mtd>
<mn>5</mn>
</mtd>
<mtd>
<mn>*</mn>
</mtd>
</mtr>
</mtable>
</math>
</body>
</html>

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