mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-12 04:45:45 +00:00
Merge m-c to fx-team.
This commit is contained in:
commit
9e03047a9b
@ -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.'
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -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) {
|
||||
|
@ -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"/>
|
||||
|
@ -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"/>
|
||||
|
@ -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"/>
|
||||
|
@ -4,6 +4,6 @@
|
||||
"branch": "",
|
||||
"revision": ""
|
||||
},
|
||||
"revision": "3d294ffa51afd8a8daafcdaa97cda8e38de81cb8",
|
||||
"revision": "c195232a409ee2234eca18a63bac2d48c2db0c13",
|
||||
"repo_path": "/integration/gaia-central"
|
||||
}
|
||||
|
@ -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"/>
|
||||
|
@ -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"/>
|
||||
|
@ -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"/>
|
||||
|
@ -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"/>
|
||||
|
@ -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"/>
|
||||
|
@ -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
145
b2g/simulator/build_xpi.py
Normal 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:])
|
||||
|
2
b2g/simulator/custom-prefs.js
Normal file
2
b2g/simulator/custom-prefs.js
Normal file
@ -0,0 +1,2 @@
|
||||
user_pref("devtools.debugger.prompt-connection", false);
|
||||
user_pref("devtools.debugger.forbid-certified-apps", false);
|
6
b2g/simulator/custom-settings.json
Normal file
6
b2g/simulator/custom-settings.json
Normal 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
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
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
52
b2g/simulator/lib/main.js
Normal 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();
|
||||
});
|
182
b2g/simulator/lib/simulator-process.js
Normal file
182
b2g/simulator/lib/simulator-process.js
Normal 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;
|
||||
},
|
||||
});
|
||||
|
7
b2g/simulator/package-overload.json.in
Normal file
7
b2g/simulator/package-overload.json.in
Normal 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"
|
||||
}
|
37
b2g/simulator/package.json
Normal file
37
b2g/simulator/package.json
Normal 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"]
|
||||
}
|
124
b2g/simulator/packages/subprocess/README.md
Normal file
124
b2g/simulator/packages/subprocess/README.md
Normal 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>
|
1543
b2g/simulator/packages/subprocess/lib/subprocess.js
Normal file
1543
b2g/simulator/packages/subprocess/lib/subprocess.js
Normal file
File diff suppressed because it is too large
Load Diff
248
b2g/simulator/packages/subprocess/lib/subprocess_worker_unix.js
Normal file
248
b2g/simulator/packages/subprocess/lib/subprocess_worker_unix.js
Normal 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;
|
||||
};
|
206
b2g/simulator/packages/subprocess/lib/subprocess_worker_win.js
Normal file
206
b2g/simulator/packages/subprocess/lib/subprocess_worker_win.js
Normal 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;
|
||||
};
|
15
b2g/simulator/packages/subprocess/package.json
Normal file
15
b2g/simulator/packages/subprocess/package.json
Normal 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."
|
||||
}
|
144
b2g/simulator/packages/subprocess/tests/test-subprocess.js
Normal file
144
b2g/simulator/packages/subprocess/tests/test-subprocess.js
Normal 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
|
||||
});
|
||||
}
|
||||
|
||||
}
|
@ -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)
|
||||
);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
};
|
||||
|
11
configure.in
11
configure.in
@ -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)
|
||||
|
||||
|
@ -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[],
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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");
|
||||
|
@ -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]
|
||||
|
@ -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,
|
||||
|
@ -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>
|
@ -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);
|
||||
|
@ -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()
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -107,7 +107,6 @@ struct JSSettings
|
||||
JSContentChromeSettings chrome;
|
||||
JSContentChromeSettings content;
|
||||
JSGCSettingsArray gcSettings;
|
||||
JS::RuntimeOptions runtimeOptions;
|
||||
|
||||
#ifdef JS_GC_ZEAL
|
||||
uint8_t gcZeal;
|
||||
|
@ -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!
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
145
gfx/2d/Logging.h
145
gfx/2d/Logging.h
@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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));
|
||||
|
@ -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
|
||||
|
@ -21,6 +21,7 @@ EXPORTS.mozilla.gfx += [
|
||||
'DataSurfaceHelpers.h',
|
||||
'Filters.h',
|
||||
'Helpers.h',
|
||||
'Logging.h',
|
||||
'Matrix.h',
|
||||
'PathHelpers.h',
|
||||
'Point.h',
|
||||
|
@ -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));
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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:
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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; }
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -312,7 +312,7 @@ struct BaselineScript
|
||||
inline bool
|
||||
IsBaselineEnabled(JSContext *cx)
|
||||
{
|
||||
return cx->runtime()->options().baseline();
|
||||
return cx->compartment()->options().baseline(cx);
|
||||
}
|
||||
|
||||
MethodStatus
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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(); }");
|
||||
|
@ -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;
|
||||
}
|
||||
|
135
js/src/jsapi.h
135
js/src/jsapi.h
@ -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.
|
||||
|
@ -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*>
|
||||
|
@ -1862,7 +1862,7 @@ void
|
||||
TypeZone::init(JSContext *cx)
|
||||
{
|
||||
if (!cx ||
|
||||
!cx->runtime()->options().typeInference() ||
|
||||
!cx->options().typeInference() ||
|
||||
!cx->runtime()->jitSupportsFloatingPoint)
|
||||
{
|
||||
return;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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__
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -1919,6 +1919,9 @@ public:
|
||||
virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
|
||||
const nsDisplayItemGeometry* aGeometry,
|
||||
nsRegion* aInvalidRegion) MOZ_OVERRIDE;
|
||||
|
||||
protected:
|
||||
nsRect CalculateBounds(const nsStyleBorder& aStyleBorder);
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -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 &&
|
||||
|
@ -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) {
|
||||
|
@ -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
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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
|
||||
|
77
layout/reftests/mathml/columnlines-1-ref.html
Normal file
77
layout/reftests/mathml/columnlines-1-ref.html
Normal 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>
|
77
layout/reftests/mathml/columnlines-1a.html
Normal file
77
layout/reftests/mathml/columnlines-1a.html
Normal 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>
|
77
layout/reftests/mathml/columnlines-1b.html
Normal file
77
layout/reftests/mathml/columnlines-1b.html
Normal 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>
|
77
layout/reftests/mathml/columnlines-1c.html
Normal file
77
layout/reftests/mathml/columnlines-1c.html
Normal 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>
|
41
layout/reftests/mathml/columnlines-2-ref.html
Normal file
41
layout/reftests/mathml/columnlines-2-ref.html
Normal 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>
|
41
layout/reftests/mathml/columnlines-2a.html
Normal file
41
layout/reftests/mathml/columnlines-2a.html
Normal 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>
|
41
layout/reftests/mathml/columnlines-2b.html
Normal file
41
layout/reftests/mathml/columnlines-2b.html
Normal 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
Loading…
Reference in New Issue
Block a user