mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-31 22:25:30 +00:00
Merge m-c to b2g-inbound
This commit is contained in:
commit
27a86159e9
@ -1078,7 +1078,7 @@ pref("devtools.commands.dir", "");
|
||||
|
||||
// Enable the app manager
|
||||
pref("devtools.appmanager.enabled", true);
|
||||
pref("devtools.appmanager.firstrun", true);
|
||||
pref("devtools.appmanager.lastTab", "help");
|
||||
pref("devtools.appmanager.manifestEditor.enabled", false);
|
||||
|
||||
// Toolbox preferences
|
||||
|
@ -986,16 +986,15 @@ nsContextMenu.prototype = {
|
||||
},
|
||||
|
||||
saveVideoFrameAsImage: function () {
|
||||
urlSecurityCheck(this.mediaURL,
|
||||
this._unremotePrincipal(this.browser.contentPrincipal),
|
||||
Ci.nsIScriptSecurityManager.DISALLOW_SCRIPT);
|
||||
let name = "";
|
||||
try {
|
||||
let uri = makeURI(this.mediaURL);
|
||||
let url = uri.QueryInterface(Ci.nsIURL);
|
||||
if (url.fileBaseName)
|
||||
name = decodeURI(url.fileBaseName) + ".jpg";
|
||||
} catch (e) { }
|
||||
if (this.mediaURL) {
|
||||
try {
|
||||
let uri = makeURI(this.mediaURL);
|
||||
let url = uri.QueryInterface(Ci.nsIURL);
|
||||
if (url.fileBaseName)
|
||||
name = decodeURI(url.fileBaseName) + ".jpg";
|
||||
} catch (e) { }
|
||||
}
|
||||
if (!name)
|
||||
name = "snapshot.jpg";
|
||||
var video = this.target;
|
||||
|
@ -162,16 +162,13 @@ let UI = {
|
||||
if (!this.connected) {
|
||||
return;
|
||||
}
|
||||
|
||||
let app = this.store.object.apps.all.filter(a => a.manifestURL == manifest)[0];
|
||||
getTargetForApp(this.connection.client,
|
||||
this.listTabsResponse.webappsActor,
|
||||
manifest).then((target) => {
|
||||
gDevTools.showToolbox(target,
|
||||
null,
|
||||
devtools.Toolbox.HostType.WINDOW).then(toolbox => {
|
||||
this.connection.once(Connection.Events.DISCONNECTED, () => {
|
||||
toolbox.destroy();
|
||||
});
|
||||
});
|
||||
|
||||
top.UI.openAndShowToolboxForTarget(target, app.name, app.iconURL);
|
||||
}, console.error);
|
||||
},
|
||||
|
||||
|
@ -7,76 +7,176 @@ Cu.import("resource:///modules/devtools/gDevTools.jsm");
|
||||
const {devtools} = Cu.import("resource://gre/modules/devtools/Loader.jsm", {});
|
||||
const {require} = devtools;
|
||||
const {ConnectionManager, Connection} = require("devtools/client/connection-manager");
|
||||
const promise = require("sdk/core/promise");
|
||||
const prefs = require('sdk/preferences/service');
|
||||
|
||||
let connection;
|
||||
|
||||
window.addEventListener("message", function(event) {
|
||||
try {
|
||||
let json = JSON.parse(event.data);
|
||||
switch (json.name) {
|
||||
case "connection":
|
||||
let cid = +json.cid;
|
||||
for (let c of ConnectionManager.connections) {
|
||||
if (c.uid == cid) {
|
||||
connection = c;
|
||||
onNewConnection();
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case "closeHelp":
|
||||
selectTab("projects");
|
||||
break;
|
||||
default:
|
||||
Cu.reportError("Unknown message: " + json.name);
|
||||
let UI = {
|
||||
_toolboxTabCursor: 0,
|
||||
_handledTargets: new Map(),
|
||||
|
||||
connection: null,
|
||||
|
||||
init: function() {
|
||||
this.onLoad = this.onLoad.bind(this);
|
||||
this.onUnload = this.onUnload.bind(this);
|
||||
this.onMessage = this.onMessage.bind(this);
|
||||
this.onConnected = this.onConnected.bind(this);
|
||||
this.onDisconnected = this.onDisconnected.bind(this);
|
||||
|
||||
window.addEventListener("load", this.onLoad);
|
||||
window.addEventListener("unload", this.onUnload);
|
||||
window.addEventListener("message", this.onMessage);
|
||||
},
|
||||
|
||||
onLoad: function() {
|
||||
window.removeEventListener("load", this.onLoad);
|
||||
let defaultPanel = prefs.get("devtools.appmanager.lastTab");
|
||||
let panelExists = !!document.querySelector("." + defaultPanel + "-panel");
|
||||
this.selectTab(panelExists ? defaultPanel : "projects");
|
||||
},
|
||||
|
||||
onUnload: function() {
|
||||
window.removeEventListener("unload", this.onUnload);
|
||||
window.removeEventListener("message", this.onMessage);
|
||||
if (this.connection) {
|
||||
this.connection.off(Connection.Status.CONNECTED, this.onConnected);
|
||||
this.connection.off(Connection.Status.DISCONNECTED, this.onDisconnected);
|
||||
}
|
||||
} catch(e) { Cu.reportError(e); }
|
||||
},
|
||||
|
||||
// Forward message
|
||||
let panels = document.querySelectorAll(".panel");
|
||||
for (let frame of panels) {
|
||||
frame.contentWindow.postMessage(event.data, "*");
|
||||
}
|
||||
}, false);
|
||||
onMessage: function(event) {
|
||||
try {
|
||||
let json = JSON.parse(event.data);
|
||||
switch (json.name) {
|
||||
case "connection":
|
||||
let cid = +json.cid;
|
||||
for (let c of ConnectionManager.connections) {
|
||||
if (c.uid == cid) {
|
||||
this.onNewConnection(c);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case "closeHelp":
|
||||
this.selectTab("projects");
|
||||
break;
|
||||
case "toolbox-raise":
|
||||
this.selectTab(json.uid);
|
||||
break;
|
||||
case "toolbox-close":
|
||||
this.closeToolboxTab(json.uid);
|
||||
break;
|
||||
default:
|
||||
Cu.reportError("Unknown message: " + json.name);
|
||||
}
|
||||
} catch(e) { Cu.reportError(e); }
|
||||
|
||||
window.addEventListener("unload", function onUnload() {
|
||||
window.removeEventListener("unload", onUnload);
|
||||
if (connection) {
|
||||
connection.off(Connection.Status.CONNECTED, onConnected);
|
||||
connection.off(Connection.Status.DISCONNECTED, onDisconnected);
|
||||
}
|
||||
});
|
||||
// Forward message
|
||||
let panels = document.querySelectorAll(".panel");
|
||||
for (let frame of panels) {
|
||||
frame.contentWindow.postMessage(event.data, "*");
|
||||
}
|
||||
},
|
||||
|
||||
function onNewConnection() {
|
||||
connection.on(Connection.Status.CONNECTED, onConnected);
|
||||
connection.on(Connection.Status.DISCONNECTED, onDisconnected);
|
||||
}
|
||||
selectTabFromButton: function(button) {
|
||||
if (!button.hasAttribute("panel"))
|
||||
return;
|
||||
this.selectTab(button.getAttribute("panel"));
|
||||
},
|
||||
|
||||
function onConnected() {
|
||||
document.querySelector("#content").classList.add("connected");
|
||||
}
|
||||
selectTab: function(panel) {
|
||||
let isToolboxTab = false;
|
||||
for (let type of ["button", "panel"]) {
|
||||
let oldSelection = document.querySelector("." + type + "[selected]");
|
||||
let newSelection = document.querySelector("." + panel + "-" + type);
|
||||
if (oldSelection) oldSelection.removeAttribute("selected");
|
||||
if (newSelection) {
|
||||
newSelection.scrollIntoView(false);
|
||||
newSelection.setAttribute("selected", "true");
|
||||
if (newSelection.classList.contains("toolbox")) {
|
||||
isToolboxTab = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!isToolboxTab) {
|
||||
prefs.set("devtools.appmanager.lastTab", panel);
|
||||
}
|
||||
},
|
||||
|
||||
function onDisconnected() {
|
||||
document.querySelector("#content").classList.remove("connected");
|
||||
}
|
||||
onNewConnection: function(connection) {
|
||||
this.connection = connection;
|
||||
this.connection.on(Connection.Status.CONNECTED, this.onConnected);
|
||||
this.connection.on(Connection.Status.DISCONNECTED, this.onDisconnected);
|
||||
},
|
||||
|
||||
function selectTab(id) {
|
||||
for (let type of ["button", "panel"]) {
|
||||
let oldSelection = document.querySelector("." + type + "[selected]");
|
||||
let newSelection = document.querySelector("." + id + "-" + type);
|
||||
if (oldSelection) oldSelection.removeAttribute("selected");
|
||||
if (newSelection) newSelection.setAttribute("selected", "true");
|
||||
}
|
||||
if (id != "help") {
|
||||
// Might be the first time the user is accessing the actual app manager
|
||||
prefs.set("devtools.appmanager.firstrun", false);
|
||||
onConnected: function() {
|
||||
document.querySelector("#content").classList.add("connected");
|
||||
},
|
||||
|
||||
onDisconnected: function() {
|
||||
for (let [,toolbox] of this._handledTargets) {
|
||||
if (toolbox) {
|
||||
toolbox.destroy();
|
||||
}
|
||||
}
|
||||
this._handledTargets.clear();
|
||||
document.querySelector("#content").classList.remove("connected");
|
||||
},
|
||||
|
||||
createToolboxTab: function(name, iconURL, uid) {
|
||||
let button = document.createElement("button");
|
||||
button.className = "button toolbox " + uid + "-button";
|
||||
button.setAttribute("panel", uid);
|
||||
button.textContent = name;
|
||||
button.setAttribute("style", "background-image: url(" + iconURL + ")");
|
||||
let toolboxTabs = document.querySelector("#toolbox-tabs");
|
||||
toolboxTabs.appendChild(button);
|
||||
let iframe = document.createElement("iframe");
|
||||
iframe.setAttribute("flex", "1");
|
||||
iframe.className = "panel toolbox " + uid + "-panel";
|
||||
let panels = document.querySelector("#tab-panels");
|
||||
panels.appendChild(iframe);
|
||||
this.selectTab(uid);
|
||||
return iframe;
|
||||
},
|
||||
|
||||
closeToolboxTab: function(uid) {
|
||||
let buttonToDestroy = document.querySelector("." + uid + "-button");
|
||||
let panelToDestroy = document.querySelector("." + uid + "-panel");
|
||||
|
||||
if (buttonToDestroy.hasAttribute("selected")) {
|
||||
let lastTab = prefs.get("devtools.appmanager.lastTab");
|
||||
this.selectTab(lastTab);
|
||||
}
|
||||
|
||||
buttonToDestroy.remove();
|
||||
panelToDestroy.remove();
|
||||
},
|
||||
|
||||
openAndShowToolboxForTarget: function(target, name, icon) {
|
||||
let host = devtools.Toolbox.HostType.CUSTOM;
|
||||
if (!this._handledTargets.has(target)) {
|
||||
let uid = "uid" + this._toolboxTabCursor++;
|
||||
let iframe = this.createToolboxTab(name, icon, uid);
|
||||
let options = { customIframe: iframe , uid: uid };
|
||||
this._handledTargets.set(target, null);
|
||||
return gDevTools.showToolbox(target, null, host, options).then(toolbox => {
|
||||
this._handledTargets.set(target, toolbox);
|
||||
toolbox.once("destroyed", () => {
|
||||
this._handledTargets.delete(target)
|
||||
});
|
||||
});
|
||||
} else {
|
||||
let toolbox = this._handledTargets.get(target);
|
||||
if (!toolbox) {
|
||||
// Target is handled, but toolbox is still being
|
||||
// created.
|
||||
return promise.resolve(null);
|
||||
}
|
||||
return gDevTools.showToolbox(target, null, host);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let firstRun = prefs.get("devtools.appmanager.firstrun");
|
||||
if (firstRun) {
|
||||
selectTab("help");
|
||||
} else {
|
||||
selectTab("projects");
|
||||
}
|
||||
UI.init();
|
||||
|
@ -22,11 +22,11 @@
|
||||
|
||||
<vbox id="root" flex="1">
|
||||
<hbox id="content" flex="1">
|
||||
<vbox id="tabs">
|
||||
<button class="button projects-button" onclick="selectTab('projects')">&index.projects2;</button>
|
||||
<button class="button device-button" onclick="selectTab('device')">&index.device2;</button>
|
||||
<spacer flex="1"/>
|
||||
<button class="button help-button" onclick="selectTab('help')">&index.help;</button>
|
||||
<vbox id="tabs" onclick="UI.selectTabFromButton(event.target)">
|
||||
<button class="button projects-button" panel="projects">&index.projects2;</button>
|
||||
<button class="button device-button" panel="device">&index.device2;</button>
|
||||
<vbox id="toolbox-tabs" flex="1"/>
|
||||
<button class="button help-button" panel="help">&index.help;</button>
|
||||
</vbox>
|
||||
<hbox id="tab-panels" flex="1">
|
||||
<iframe flex="1" class="panel projects-panel" src="chrome://browser/content/devtools/app-manager/projects.xhtml"/>
|
||||
|
@ -356,25 +356,15 @@ let UI = {
|
||||
loop(0);
|
||||
return deferred.promise;
|
||||
};
|
||||
let onTargetReady = (target) => {
|
||||
// Finally, when it's finally opened, display the toolbox
|
||||
let deferred = promise.defer();
|
||||
gDevTools.showToolbox(target,
|
||||
null,
|
||||
devtools.Toolbox.HostType.WINDOW).then(toolbox => {
|
||||
this.connection.once(Connection.Events.DISCONNECTED, () => {
|
||||
toolbox.destroy();
|
||||
});
|
||||
deferred.resolve(toolbox);
|
||||
});
|
||||
return deferred.promise;
|
||||
};
|
||||
|
||||
// First try to open the app
|
||||
this.start(project)
|
||||
.then(null, onFailedToStart)
|
||||
.then(onStarted)
|
||||
.then(onTargetReady)
|
||||
.then((target) =>
|
||||
top.UI.openAndShowToolboxForTarget(target,
|
||||
project.manifest.name,
|
||||
project.icon))
|
||||
.then(() => {
|
||||
// And only when the toolbox is opened, release the button
|
||||
button.disabled = false;
|
||||
|
@ -33,7 +33,7 @@ function test() {
|
||||
});
|
||||
}
|
||||
|
||||
function testNavigate() {
|
||||
function testNavigate([aGrip, aResponse]) {
|
||||
let outstanding = [promise.defer(), promise.defer()];
|
||||
|
||||
gClient.addListener("tabNavigated", function onTabNavigated(aEvent, aPacket) {
|
||||
@ -51,14 +51,16 @@ function testNavigate() {
|
||||
});
|
||||
|
||||
gBrowser.selectedTab.linkedBrowser.loadURI(TAB2_URL);
|
||||
return promise.all(outstanding.map(e => e.promise));
|
||||
return promise.all(outstanding.map(e => e.promise))
|
||||
.then(() => aGrip.actor);
|
||||
}
|
||||
|
||||
function testDetach() {
|
||||
function testDetach(aActor) {
|
||||
let deferred = promise.defer();
|
||||
|
||||
gClient.addOneTimeListener("tabDetached", () => {
|
||||
gClient.addOneTimeListener("tabDetached", (aType, aPacket) => {
|
||||
ok(true, "Got a tab detach notification.");
|
||||
is(aPacket.from, aActor, "tab detach message comes from the expected actor");
|
||||
gClient.close(deferred.resolve);
|
||||
});
|
||||
|
||||
|
@ -206,11 +206,13 @@ DevTools.prototype = {
|
||||
* The id of the tool to show
|
||||
* @param {Toolbox.HostType} hostType
|
||||
* The type of host (bottom, window, side)
|
||||
* @param {object} hostOptions
|
||||
* Options for host specifically
|
||||
*
|
||||
* @return {Toolbox} toolbox
|
||||
* The toolbox that was opened
|
||||
*/
|
||||
showToolbox: function(target, toolId, hostType) {
|
||||
showToolbox: function(target, toolId, hostType, hostOptions) {
|
||||
let deferred = promise.defer();
|
||||
|
||||
let toolbox = this._toolboxes.get(target);
|
||||
@ -233,7 +235,7 @@ DevTools.prototype = {
|
||||
}
|
||||
else {
|
||||
// No toolbox for target, create one
|
||||
toolbox = new devtools.Toolbox(target, toolId, hostType);
|
||||
toolbox = new devtools.Toolbox(target, toolId, hostType, hostOptions);
|
||||
|
||||
this._toolboxes.set(target, toolbox);
|
||||
|
||||
|
@ -350,7 +350,13 @@ TabTarget.prototype = {
|
||||
* Setup listeners for remote debugging, updating existing ones as necessary.
|
||||
*/
|
||||
_setupRemoteListeners: function TabTarget__setupRemoteListeners() {
|
||||
this.client.addListener("tabDetached", this.destroy);
|
||||
this._onTabDetached = (aType, aPacket) => {
|
||||
// We have to filter message to ensure that this detach is for this tab
|
||||
if (aPacket.from == this._form.actor) {
|
||||
this.destroy();
|
||||
}
|
||||
};
|
||||
this.client.addListener("tabDetached", this._onTabDetached);
|
||||
|
||||
this._onTabNavigated = function onRemoteTabNavigated(aType, aPacket) {
|
||||
let event = Object.create(null);
|
||||
@ -377,7 +383,7 @@ TabTarget.prototype = {
|
||||
*/
|
||||
_teardownRemoteListeners: function TabTarget__teardownRemoteListeners() {
|
||||
this.client.removeListener("tabNavigated", this._onTabNavigated);
|
||||
this.client.removeListener("tabDetached", this.destroy);
|
||||
this.client.removeListener("tabDetached", this._onTabDetached);
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -22,3 +22,4 @@ support-files = head.js
|
||||
[browser_toolbox_window_shortcuts.js]
|
||||
[browser_toolbox_window_title_changes.js]
|
||||
[browser_toolbox_zoom.js]
|
||||
[browser_toolbox_custom_host.js]
|
||||
|
@ -0,0 +1,60 @@
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
function test() {
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
let temp = {}
|
||||
Cu.import("resource:///modules/devtools/gDevTools.jsm", temp);
|
||||
let DevTools = temp.DevTools;
|
||||
Cu.import("resource://gre/modules/devtools/LayoutHelpers.jsm", temp);
|
||||
let LayoutHelpers = temp.LayoutHelpers;
|
||||
|
||||
Cu.import("resource://gre/modules/devtools/Loader.jsm", temp);
|
||||
let devtools = temp.devtools;
|
||||
|
||||
let Toolbox = devtools.Toolbox;
|
||||
|
||||
let toolbox, iframe, target, tab;
|
||||
|
||||
waitForExplicitFinish();
|
||||
|
||||
gBrowser.selectedTab = gBrowser.addTab();
|
||||
target = TargetFactory.forTab(gBrowser.selectedTab);
|
||||
|
||||
window.addEventListener("message", onMessage);
|
||||
|
||||
iframe = document.createElement("iframe");
|
||||
document.documentElement.appendChild(iframe);
|
||||
|
||||
gBrowser.selectedBrowser.addEventListener("load", function onLoad(evt) {
|
||||
gBrowser.selectedBrowser.removeEventListener(evt.type, onLoad, true);
|
||||
let options = {customIframe: iframe};
|
||||
gDevTools.showToolbox(target, null, Toolbox.HostType.CUSTOM, options)
|
||||
.then(testCustomHost, console.error)
|
||||
.then(null, console.error);
|
||||
}, true);
|
||||
|
||||
content.location = "data:text/html,test custom host";
|
||||
|
||||
function onMessage(event) {
|
||||
info("onMessage: " + event.data);
|
||||
let json = JSON.parse(event.data);
|
||||
if (json.name == "toolbox-close") {
|
||||
ok("Got the `toolbox-close` message");
|
||||
cleanup();
|
||||
}
|
||||
}
|
||||
|
||||
function testCustomHost(toolbox) {
|
||||
is(toolbox.doc.defaultView.top, window, "Toolbox is included in browser.xul");
|
||||
is(toolbox.doc, iframe.contentDocument, "Toolbox is in the custom iframe");
|
||||
executeSoon(() => gBrowser.removeCurrentTab());
|
||||
}
|
||||
|
||||
function cleanup() {
|
||||
window.removeEventListener("message", onMessage);
|
||||
iframe.remove();
|
||||
finish();
|
||||
}
|
||||
}
|
@ -10,6 +10,7 @@ let promise = require("sdk/core/promise");
|
||||
let EventEmitter = require("devtools/shared/event-emitter");
|
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource:///modules/devtools/DOMHelpers.jsm");
|
||||
|
||||
/**
|
||||
* A toolbox host represents an object that contains a toolbox (e.g. the
|
||||
@ -23,7 +24,8 @@ Cu.import("resource://gre/modules/Services.jsm");
|
||||
exports.Hosts = {
|
||||
"bottom": BottomHost,
|
||||
"side": SidebarHost,
|
||||
"window": WindowHost
|
||||
"window": WindowHost,
|
||||
"custom": CustomHost
|
||||
}
|
||||
|
||||
/**
|
||||
@ -61,18 +63,18 @@ BottomHost.prototype = {
|
||||
this._nbox.appendChild(this.frame);
|
||||
|
||||
let frameLoad = function() {
|
||||
this.frame.removeEventListener("DOMContentLoaded", frameLoad, true);
|
||||
this.emit("ready", this.frame);
|
||||
|
||||
deferred.resolve(this.frame);
|
||||
}.bind(this);
|
||||
|
||||
this.frame.tooltip = "aHTMLTooltip";
|
||||
this.frame.addEventListener("DOMContentLoaded", frameLoad, true);
|
||||
|
||||
// we have to load something so we can switch documents if we have to
|
||||
this.frame.setAttribute("src", "about:blank");
|
||||
|
||||
let domHelper = new DOMHelpers(this.frame.contentWindow);
|
||||
domHelper.onceDOMReady(frameLoad);
|
||||
|
||||
focusTab(this.hostTab);
|
||||
|
||||
return deferred.promise;
|
||||
@ -272,6 +274,59 @@ WindowHost.prototype = {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Host object for the toolbox in its own tab
|
||||
*/
|
||||
function CustomHost(hostTab, options) {
|
||||
this.frame = options.customIframe;
|
||||
this.uid = options.uid;
|
||||
EventEmitter.decorate(this);
|
||||
}
|
||||
|
||||
CustomHost.prototype = {
|
||||
type: "custom",
|
||||
|
||||
_sendMessageToTopWindow: function CH__sendMessageToTopWindow(msg) {
|
||||
// It's up to the custom frame owner (parent window) to honor
|
||||
// "close" or "raise" instructions.
|
||||
let topWindow = this.frame.ownerDocument.defaultView;
|
||||
let json = {name:"toolbox-" + msg, uid: this.uid}
|
||||
topWindow.postMessage(JSON.stringify(json), "*");
|
||||
},
|
||||
|
||||
/**
|
||||
* Create a new xul window to contain the toolbox.
|
||||
*/
|
||||
create: function CH_create() {
|
||||
return promise.resolve(this.frame);
|
||||
},
|
||||
|
||||
/**
|
||||
* Raise the host.
|
||||
*/
|
||||
raise: function CH_raise() {
|
||||
this._sendMessageToTopWindow("raise");
|
||||
},
|
||||
|
||||
/**
|
||||
* Set the toolbox title.
|
||||
*/
|
||||
setTitle: function CH_setTitle(title) {
|
||||
// Not supported
|
||||
},
|
||||
|
||||
/**
|
||||
* Destroy the window.
|
||||
*/
|
||||
destroy: function WH_destroy() {
|
||||
if (!this._destroyed) {
|
||||
this._destroyed = true;
|
||||
this._sendMessageToTopWindow("close");
|
||||
}
|
||||
return promise.resolve(null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Switch to the given tab in a browser and focus the browser window
|
||||
*/
|
||||
|
@ -19,6 +19,7 @@ Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource:///modules/devtools/gDevTools.jsm");
|
||||
Cu.import("resource:///modules/devtools/scratchpad-manager.jsm");
|
||||
Cu.import("resource:///modules/devtools/DOMHelpers.jsm");
|
||||
|
||||
loader.lazyGetter(this, "Hosts", () => require("devtools/framework/toolbox-hosts").Hosts);
|
||||
|
||||
@ -55,8 +56,10 @@ loader.lazyGetter(this, "Requisition", () => {
|
||||
* Tool to select initially
|
||||
* @param {Toolbox.HostType} hostType
|
||||
* Type of host that will host the toolbox (e.g. sidebar, window)
|
||||
* @param {object} hostOptions
|
||||
* Options for host specifically
|
||||
*/
|
||||
function Toolbox(target, selectedTool, hostType) {
|
||||
function Toolbox(target, selectedTool, hostType, hostOptions) {
|
||||
this._target = target;
|
||||
this._toolPanels = new Map();
|
||||
this._telemetry = new Telemetry();
|
||||
@ -79,7 +82,7 @@ function Toolbox(target, selectedTool, hostType) {
|
||||
}
|
||||
this._defaultToolId = selectedTool;
|
||||
|
||||
this._host = this._createHost(hostType);
|
||||
this._host = this._createHost(hostType, hostOptions);
|
||||
|
||||
EventEmitter.decorate(this);
|
||||
|
||||
@ -99,7 +102,8 @@ exports.Toolbox = Toolbox;
|
||||
Toolbox.HostType = {
|
||||
BOTTOM: "bottom",
|
||||
SIDE: "side",
|
||||
WINDOW: "window"
|
||||
WINDOW: "window",
|
||||
CUSTOM: "custom"
|
||||
};
|
||||
|
||||
Toolbox.prototype = {
|
||||
@ -187,8 +191,6 @@ Toolbox.prototype = {
|
||||
let deferred = promise.defer();
|
||||
|
||||
let domReady = () => {
|
||||
iframe.removeEventListener("DOMContentLoaded", domReady, true);
|
||||
|
||||
this.isReady = true;
|
||||
|
||||
let closeButton = this.doc.getElementById("toolbox-close");
|
||||
@ -211,9 +213,11 @@ Toolbox.prototype = {
|
||||
});
|
||||
};
|
||||
|
||||
iframe.addEventListener("DOMContentLoaded", domReady, true);
|
||||
iframe.setAttribute("src", this._URL);
|
||||
|
||||
let domHelper = new DOMHelpers(iframe.contentWindow);
|
||||
domHelper.onceDOMReady(domReady);
|
||||
|
||||
return deferred.promise;
|
||||
});
|
||||
},
|
||||
@ -387,6 +391,7 @@ Toolbox.prototype = {
|
||||
for (let type in Toolbox.HostType) {
|
||||
let position = Toolbox.HostType[type];
|
||||
if (position == this.hostType ||
|
||||
position == Toolbox.HostType.CUSTOM ||
|
||||
(!sideEnabled && position == Toolbox.HostType.SIDE)) {
|
||||
continue;
|
||||
}
|
||||
@ -555,8 +560,6 @@ Toolbox.prototype = {
|
||||
vbox.appendChild(iframe);
|
||||
|
||||
let onLoad = () => {
|
||||
iframe.removeEventListener("DOMContentLoaded", onLoad, true);
|
||||
|
||||
let built = definition.build(iframe.contentWindow, this);
|
||||
promise.resolve(built).then((panel) => {
|
||||
this._toolPanels.set(id, panel);
|
||||
@ -566,8 +569,25 @@ Toolbox.prototype = {
|
||||
});
|
||||
};
|
||||
|
||||
iframe.addEventListener("DOMContentLoaded", onLoad, true);
|
||||
iframe.setAttribute("src", definition.url);
|
||||
|
||||
// Depending on the host, iframe.contentWindow is not always
|
||||
// defined at this moment. If it is not defined, we use an
|
||||
// event listener on the iframe DOM node. If it's defined,
|
||||
// we use the chromeEventHandler. We can't use a listener
|
||||
// on the DOM node every time because this won't work
|
||||
// if the (xul chrome) iframe is loaded in a content docshell.
|
||||
if (iframe.contentWindow) {
|
||||
let domHelper = new DOMHelpers(iframe.contentWindow);
|
||||
domHelper.onceDOMReady(onLoad);
|
||||
} else {
|
||||
let callback = () => {
|
||||
iframe.removeEventListener("DOMContentLoaded", callback);
|
||||
onLoad();
|
||||
}
|
||||
iframe.addEventListener("DOMContentLoaded", callback);
|
||||
}
|
||||
|
||||
return deferred.promise;
|
||||
},
|
||||
|
||||
@ -732,13 +752,13 @@ Toolbox.prototype = {
|
||||
* @return {Host} host
|
||||
* The created host object
|
||||
*/
|
||||
_createHost: function(hostType) {
|
||||
_createHost: function(hostType, options) {
|
||||
if (!Hosts[hostType]) {
|
||||
throw new Error("Unknown hostType: " + hostType);
|
||||
}
|
||||
|
||||
// clean up the toolbox if its window is closed
|
||||
let newHost = new Hosts[hostType](this.target.tab);
|
||||
let newHost = new Hosts[hostType](this.target.tab, options);
|
||||
newHost.on("window-closed", this.destroy);
|
||||
return newHost;
|
||||
},
|
||||
@ -766,7 +786,9 @@ Toolbox.prototype = {
|
||||
|
||||
this._host = newHost;
|
||||
|
||||
Services.prefs.setCharPref(this._prefs.LAST_HOST, this._host.type);
|
||||
if (this.hostType != Toolbox.HostType.CUSTOM) {
|
||||
Services.prefs.setCharPref(this._prefs.LAST_HOST, this._host.type);
|
||||
}
|
||||
|
||||
this._buildDockButtons();
|
||||
this._addKeysToWindow();
|
||||
|
@ -181,6 +181,13 @@ function ResponsiveUI(aWindow, aTab)
|
||||
this.buildUI();
|
||||
this.checkMenus();
|
||||
|
||||
this.docShell = this.browser.contentWindow.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIWebNavigation)
|
||||
.QueryInterface(Ci.nsIDocShell);
|
||||
|
||||
this._deviceSizeWasPageSize = this.docShell.deviceSizeIsPageSize;
|
||||
this.docShell.deviceSizeIsPageSize = true;
|
||||
|
||||
try {
|
||||
if (Services.prefs.getBoolPref("devtools.responsiveUI.rotate")) {
|
||||
this.rotate();
|
||||
@ -249,6 +256,8 @@ ResponsiveUI.prototype = {
|
||||
return;
|
||||
this.closing = true;
|
||||
|
||||
this.docShell.deviceSizeIsPageSize = this._deviceSizeWasPageSize;
|
||||
|
||||
this.browser.removeEventListener("load", this.bound_onPageLoad, true);
|
||||
this.browser.removeEventListener("unload", this.bound_onPageUnload, true);
|
||||
|
||||
@ -288,6 +297,7 @@ ResponsiveUI.prototype = {
|
||||
this.container.removeAttribute("responsivemode");
|
||||
this.stack.removeAttribute("responsivemode");
|
||||
|
||||
delete this.docShell;
|
||||
delete this.tab.__responsiveUI;
|
||||
if (this.touchEventHandler)
|
||||
this.touchEventHandler.stop();
|
||||
|
@ -9,3 +9,4 @@ support-files =
|
||||
[browser_responsiveui.js]
|
||||
[browser_responsiveui_touch.js]
|
||||
[browser_responsiveuiaddcustompreset.js]
|
||||
[browser_responsive_devicewidth.js]
|
||||
|
@ -0,0 +1,64 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
function test() {
|
||||
let instance;
|
||||
let mgr = ResponsiveUI.ResponsiveUIManager;
|
||||
|
||||
waitForExplicitFinish();
|
||||
|
||||
gBrowser.selectedTab = gBrowser.addTab();
|
||||
gBrowser.selectedBrowser.addEventListener("load", function onload() {
|
||||
gBrowser.selectedBrowser.removeEventListener("load", onload, true);
|
||||
waitForFocus(startTest, content);
|
||||
}, true);
|
||||
|
||||
content.location = "data:text/html,mop";
|
||||
|
||||
function startTest() {
|
||||
mgr.once("on", function() {executeSoon(onUIOpen)});
|
||||
document.getElementById("Tools:ResponsiveUI").doCommand();
|
||||
}
|
||||
|
||||
function onUIOpen() {
|
||||
instance = gBrowser.selectedTab.__responsiveUI;
|
||||
instance.stack.setAttribute("notransition", "true");
|
||||
ok(instance, "instance of the module is attached to the tab.");
|
||||
|
||||
instance.setSize(110, 500);
|
||||
ok(content.innerWidth, 110, "initial width is valid");
|
||||
|
||||
let mql = content.matchMedia("(max-device-width:100px)")
|
||||
|
||||
ok(!mql.matches, "media query doesn't match.");
|
||||
|
||||
mql.addListener(onMediaChange);
|
||||
instance.setSize(90, 500);
|
||||
}
|
||||
|
||||
function onMediaChange(mql) {
|
||||
mql.removeListener(onMediaChange);
|
||||
ok(mql.matches, "media query matches.");
|
||||
ok(window.screen.width != content.screen.width, "screen.width is not the size of the screen.");
|
||||
is(content.screen.width, 90, "screen.width is the width of the page.");
|
||||
is(content.screen.height, 500, "screen.height is the height of the page.");
|
||||
|
||||
|
||||
let docShell = content.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIWebNavigation)
|
||||
.QueryInterface(Ci.nsIDocShell);
|
||||
|
||||
mql.addListener(onMediaChange2);
|
||||
docShell.deviceSizeIsPageSize = false;
|
||||
}
|
||||
|
||||
function onMediaChange2(mql) {
|
||||
mql.removeListener(onMediaChange);
|
||||
ok(!mql.matches, "media query has been re-evaluated.");
|
||||
ok(window.screen.width == content.screen.width, "screen.width is not the size of the screen.");
|
||||
instance.stack.removeAttribute("notransition");
|
||||
document.getElementById("Tools:ResponsiveUI").doCommand();
|
||||
gBrowser.removeCurrentTab();
|
||||
finish();
|
||||
}
|
||||
}
|
@ -2,6 +2,10 @@
|
||||
* 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 Ci = Components.interfaces;
|
||||
const Cu = Components.utils;
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
this.EXPORTED_SYMBOLS = ["DOMHelpers"];
|
||||
|
||||
/**
|
||||
@ -13,6 +17,9 @@ this.EXPORTED_SYMBOLS = ["DOMHelpers"];
|
||||
* The content window, owning the document to traverse.
|
||||
*/
|
||||
this.DOMHelpers = function DOMHelpers(aWindow) {
|
||||
if (!aWindow) {
|
||||
throw new Error("window can't be null or undefined");
|
||||
}
|
||||
this.window = aWindow;
|
||||
};
|
||||
|
||||
@ -120,5 +127,30 @@ DOMHelpers.prototype = {
|
||||
{
|
||||
delete this.window;
|
||||
delete this.treeWalker;
|
||||
},
|
||||
|
||||
/**
|
||||
* A simple way to be notified (once) when a window becomes
|
||||
* interactive (DOMContentLoaded).
|
||||
*
|
||||
* It is based on the chromeEventHandler. This is useful when
|
||||
* chrome iframes are loaded in content docshells (in Firefox
|
||||
* tabs for example).
|
||||
*/
|
||||
onceDOMReady: function Helpers_onLocationChange(callback) {
|
||||
let window = this.window;
|
||||
let docShell = window.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIWebNavigation)
|
||||
.QueryInterface(Ci.nsIDocShell);
|
||||
let onReady = function(event) {
|
||||
if (event.target == window.document) {
|
||||
docShell.chromeEventHandler.removeEventListener("DOMContentLoaded", onReady, false);
|
||||
// If in `callback` the URL of the window is changed and a listener to DOMContentLoaded
|
||||
// is attached, the event we just received will be also be caught by the new listener.
|
||||
// We want to avoid that so we execute the callback in the next queue.
|
||||
Services.tm.mainThread.dispatch(callback, 0);
|
||||
}
|
||||
}
|
||||
docShell.chromeEventHandler.addEventListener("DOMContentLoaded", onReady, false);
|
||||
}
|
||||
};
|
||||
|
@ -12,6 +12,7 @@
|
||||
|
||||
#banners-and-logs {
|
||||
display: flex;
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
#logs {
|
||||
|
@ -14,6 +14,10 @@
|
||||
background: #252C33;
|
||||
}
|
||||
|
||||
#toolbox-tabs {
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.button {
|
||||
width: 80px;
|
||||
height: 85px;
|
||||
@ -54,6 +58,12 @@
|
||||
display: none;
|
||||
}
|
||||
|
||||
.button.toolbox {
|
||||
background-repeat: no-repeat;
|
||||
background-position: center 15px;
|
||||
background-size: 40px 40px;
|
||||
}
|
||||
|
||||
.projects-button {
|
||||
background: url('chrome://browser/skin/devtools/app-manager/index-icons.svg') no-repeat;
|
||||
background-position: left -5px;
|
||||
|
@ -1,9 +1,8 @@
|
||||
#filter substitution
|
||||
/* 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/. */
|
||||
|
||||
package @ANDROID_PACKAGE_NAME@;
|
||||
package org.mozilla.gecko;
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
|
@ -8,7 +8,7 @@
|
||||
<uses-sdk android:minSdkVersion="8" />
|
||||
|
||||
<instrumentation
|
||||
android:name="@ANDROID_PACKAGE_NAME@.FennecInstrumentationTestRunner"
|
||||
android:name="org.mozilla.gecko.FennecInstrumentationTestRunner"
|
||||
android:targetPackage="@ANDROID_PACKAGE_NAME@" />
|
||||
|
||||
<application
|
||||
|
@ -1,9 +1,8 @@
|
||||
#filter substitution
|
||||
/* 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/. */
|
||||
|
||||
package @ANDROID_PACKAGE_NAME@;
|
||||
package org.mozilla.gecko;
|
||||
|
||||
public interface Assert {
|
||||
void dumpLog(String message);
|
@ -1,9 +1,8 @@
|
||||
#filter substitution
|
||||
/* 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/. */
|
||||
|
||||
package @ANDROID_PACKAGE_NAME@;
|
||||
package org.mozilla.gecko;
|
||||
|
||||
import java.util.List;
|
||||
import android.app.Activity;
|
@ -1,9 +1,8 @@
|
||||
#filter substitution
|
||||
/* 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/. */
|
||||
|
||||
package @ANDROID_PACKAGE_NAME@;
|
||||
package org.mozilla.gecko;
|
||||
|
||||
/**
|
||||
* Element provides access to a specific UI view (android.view.View).
|
@ -1,9 +1,8 @@
|
||||
#filter substitution
|
||||
/* 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/. */
|
||||
|
||||
package @ANDROID_PACKAGE_NAME@;
|
||||
package org.mozilla.gecko;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.test.InstrumentationTestRunner;
|
@ -1,9 +1,8 @@
|
||||
#filter substitution
|
||||
/* 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/. */
|
||||
|
||||
package @ANDROID_PACKAGE_NAME@;
|
||||
package org.mozilla.gecko;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import android.os.SystemClock;
|
@ -1,9 +1,8 @@
|
||||
#filter substitution
|
||||
/* 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/. */
|
||||
|
||||
package @ANDROID_PACKAGE_NAME@;
|
||||
package org.mozilla.gecko;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
@ -28,7 +27,7 @@ import android.view.ViewConfiguration;
|
||||
|
||||
import com.jayway.android.robotium.solo.Solo;
|
||||
|
||||
import static @ANDROID_PACKAGE_NAME@.FennecNativeDriver.LogLevel;
|
||||
import static org.mozilla.gecko.FennecNativeDriver.LogLevel;
|
||||
|
||||
public class FennecNativeActions implements Actions {
|
||||
private Solo mSolo;
|
@ -1,9 +1,8 @@
|
||||
#filter substitution
|
||||
/* 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/. */
|
||||
|
||||
package @ANDROID_PACKAGE_NAME@;
|
||||
package org.mozilla.gecko;
|
||||
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.BufferedReader;
|
@ -1,9 +1,8 @@
|
||||
#filter substitution
|
||||
/* 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/. */
|
||||
|
||||
package @ANDROID_PACKAGE_NAME@;
|
||||
package org.mozilla.gecko;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.view.View;
|
@ -1,9 +1,8 @@
|
||||
#filter substitution
|
||||
/* 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/. */
|
||||
|
||||
package @ANDROID_PACKAGE_NAME@;
|
||||
package org.mozilla.gecko;
|
||||
|
||||
|
||||
public class FennecTalosAssert implements Assert {
|
@ -30,18 +30,14 @@ _JAVA_HARNESS := \
|
||||
PaintedSurface.java \
|
||||
$(NULL)
|
||||
|
||||
# pre-process harness sources
|
||||
PP_TARGETS += java-harness
|
||||
java-harness := $(addprefix $(srcdir)/,$(addsuffix .in,$(_JAVA_HARNESS)))
|
||||
java-harness-dep := $(addprefix $(CURDIR)/,$(_JAVA_HARNESS))
|
||||
java-harness_PATH := $(CURDIR)
|
||||
java-harness := $(addprefix $(srcdir)/,$(_JAVA_HARNESS))
|
||||
java-tests := $(wildcard $(TESTPATH)/*.java)
|
||||
|
||||
# pre-process test sources
|
||||
PP_TARGETS += java-tests
|
||||
java-tests-src := $(wildcard $(TESTPATH)/*.java.in)
|
||||
java-tests-dep := $(patsubst $(TESTPATH)/%.java.in,$(dir-tests)/%.java,$(java-tests-src))
|
||||
java-tests := $(java-tests-src)
|
||||
java-tests_PATH := $(dir-tests)
|
||||
# pre-process TestConstants.java.in
|
||||
PP_TARGETS += testconstants
|
||||
testconstants-dep := $(dir-tests)/TestConstants.java
|
||||
testconstants := $(TESTPATH)/TestConstants.java.in
|
||||
testconstants_PATH := $(dir-tests)
|
||||
|
||||
PP_TARGETS += manifest
|
||||
manifest := $(srcdir)/AndroidManifest.xml.in
|
||||
@ -68,15 +64,15 @@ MOCHITEST_ROBOCOP_FILES := \
|
||||
|
||||
GARBAGE += \
|
||||
AndroidManifest.xml \
|
||||
$(java-tests-dep) \
|
||||
$(java-harness-dep) \
|
||||
$(robocop-deps) \
|
||||
$(testconstants-dep) \
|
||||
$(NULL)
|
||||
|
||||
JAVAFILES += \
|
||||
$(java-harness) \
|
||||
$(java-tests) \
|
||||
$(robocop-deps) \
|
||||
$(java-harness-dep) \
|
||||
$(java-tests-dep) \
|
||||
$(testconstants-dep) \
|
||||
$(NULL)
|
||||
|
||||
DEFINES += \
|
||||
@ -88,8 +84,3 @@ include $(topsrcdir)/config/rules.mk
|
||||
tools:: $(ANDROID_APK_NAME).apk
|
||||
|
||||
GENERATED_DIRS += $(dir-tests)
|
||||
|
||||
# PP_java-tests not fully usable here
|
||||
# Intermediate step toward a library rule.
|
||||
$(dir-tests)/%.java: $(TESTPATH)/%.java.in $(call mkdir_deps,$(dir-tests))
|
||||
$(PYTHON) $(topsrcdir)/config/Preprocessor.py $(DEFINES) $< > $@
|
||||
|
@ -1,9 +1,8 @@
|
||||
#filter substitution
|
||||
/* 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/. */
|
||||
|
||||
package @ANDROID_PACKAGE_NAME@;
|
||||
package org.mozilla.gecko;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
import android.util.Base64;
|
@ -1,9 +1,8 @@
|
||||
#filter substitution
|
||||
/* 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/. */
|
||||
|
||||
package @ANDROID_PACKAGE_NAME@;
|
||||
package org.mozilla.gecko;
|
||||
|
||||
public class RoboCopException extends RuntimeException {
|
||||
|
@ -1,10 +1,8 @@
|
||||
#filter substitution
|
||||
|
||||
/* 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/. */
|
||||
|
||||
package @ANDROID_PACKAGE_NAME@;
|
||||
package org.mozilla.gecko;
|
||||
|
||||
import android.app.Activity;
|
||||
|
@ -95,6 +95,10 @@ public:
|
||||
virtual JSObject* WrapObject(JSContext *cx, JS::Handle<JSObject*> scope)
|
||||
MOZ_OVERRIDE = 0;
|
||||
|
||||
void SetCapacity(uint32_t aCapacity)
|
||||
{
|
||||
mElements.SetCapacity(aCapacity);
|
||||
}
|
||||
protected:
|
||||
/**
|
||||
* To be called from non-destructor locations (e.g. unlink) that want to
|
||||
|
@ -2337,8 +2337,8 @@ AddScopeElements(TreeMatchContext& aMatchContext,
|
||||
// Actually find elements matching aSelectorList (which must not be
|
||||
// null) and which are descendants of aRoot and put them in aList. If
|
||||
// onlyFirstMatch, then stop once the first one is found.
|
||||
template<bool onlyFirstMatch, class T>
|
||||
inline static nsresult
|
||||
template<bool onlyFirstMatch, class Collector, class T>
|
||||
MOZ_ALWAYS_INLINE static nsresult
|
||||
FindMatchingElements(nsINode* aRoot, const nsAString& aSelector, T &aList)
|
||||
{
|
||||
|
||||
@ -2424,6 +2424,7 @@ FindMatchingElements(nsINode* aRoot, const nsAString& aSelector, T &aList)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
Collector results;
|
||||
for (nsIContent* cur = aRoot->GetFirstChild();
|
||||
cur;
|
||||
cur = cur->GetNextNode(aRoot)) {
|
||||
@ -2431,10 +2432,19 @@ FindMatchingElements(nsINode* aRoot, const nsAString& aSelector, T &aList)
|
||||
nsCSSRuleProcessor::SelectorListMatches(cur->AsElement(),
|
||||
matchingContext,
|
||||
selectorList)) {
|
||||
aList.AppendElement(cur->AsElement());
|
||||
if (onlyFirstMatch) {
|
||||
aList.AppendElement(cur->AsElement());
|
||||
return NS_OK;
|
||||
}
|
||||
results.AppendElement(cur->AsElement());
|
||||
}
|
||||
}
|
||||
|
||||
const uint32_t len = results.Length();
|
||||
if (len) {
|
||||
aList.SetCapacity(len);
|
||||
for (uint32_t i = 0; i < len; ++i) {
|
||||
aList.AppendElement(results.ElementAt(i));
|
||||
}
|
||||
}
|
||||
|
||||
@ -2447,6 +2457,10 @@ struct ElementHolder {
|
||||
NS_ABORT_IF_FALSE(!mElement, "Should only get one element");
|
||||
mElement = aElement;
|
||||
}
|
||||
void SetCapacity(uint32_t aCapacity) { MOZ_CRASH("Don't call me!"); }
|
||||
uint32_t Length() { return 0; }
|
||||
Element* ElementAt(uint32_t aIndex) { return nullptr; }
|
||||
|
||||
Element* mElement;
|
||||
};
|
||||
|
||||
@ -2454,7 +2468,7 @@ Element*
|
||||
nsINode::QuerySelector(const nsAString& aSelector, ErrorResult& aResult)
|
||||
{
|
||||
ElementHolder holder;
|
||||
aResult = FindMatchingElements<true>(this, aSelector, holder);
|
||||
aResult = FindMatchingElements<true, ElementHolder>(this, aSelector, holder);
|
||||
|
||||
return holder.mElement;
|
||||
}
|
||||
@ -2464,7 +2478,10 @@ nsINode::QuerySelectorAll(const nsAString& aSelector, ErrorResult& aResult)
|
||||
{
|
||||
nsRefPtr<nsSimpleContentList> contentList = new nsSimpleContentList(this);
|
||||
|
||||
aResult = FindMatchingElements<false>(this, aSelector, *contentList);
|
||||
aResult =
|
||||
FindMatchingElements<false, nsAutoTArray<Element*, 128>>(this,
|
||||
aSelector,
|
||||
*contentList);
|
||||
|
||||
return contentList.forget();
|
||||
}
|
||||
|
@ -755,6 +755,7 @@ nsDocShell::nsDocShell():
|
||||
mIsAppTab(false),
|
||||
mUseGlobalHistory(false),
|
||||
mInPrivateBrowsing(false),
|
||||
mDeviceSizeIsPageSize(false),
|
||||
mFiredUnloadEvent(false),
|
||||
mEODForCurrentDocument(false),
|
||||
mURIResultedInDocument(false),
|
||||
@ -3920,6 +3921,27 @@ nsDocShell::GetCurrentSHEntry(nsISHEntry** aEntry, bool* aOSHE)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDocShell::SetDeviceSizeIsPageSize(bool aValue)
|
||||
{
|
||||
if (mDeviceSizeIsPageSize != aValue) {
|
||||
mDeviceSizeIsPageSize = aValue;
|
||||
nsRefPtr<nsPresContext> presContext;
|
||||
GetPresContext(getter_AddRefs(presContext));
|
||||
if (presContext) {
|
||||
presContext->MediaFeatureValuesChanged(presContext->eAlwaysRebuildStyle);
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDocShell::GetDeviceSizeIsPageSize(bool* aValue)
|
||||
{
|
||||
*aValue = mDeviceSizeIsPageSize;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsDocShell::ClearFrameHistory(nsISHEntry* aEntry)
|
||||
{
|
||||
@ -4929,6 +4951,10 @@ nsDocShell::Create()
|
||||
gAddedPreferencesVarCache = true;
|
||||
}
|
||||
|
||||
mDeviceSizeIsPageSize =
|
||||
Preferences::GetBool("docshell.device_size_is_page_size",
|
||||
mDeviceSizeIsPageSize);
|
||||
|
||||
nsCOMPtr<nsIObserverService> serv = services::GetObserverService();
|
||||
if (serv) {
|
||||
const char* msg = mItemType == typeContent ?
|
||||
|
@ -815,6 +815,7 @@ protected:
|
||||
bool mIsAppTab;
|
||||
bool mUseGlobalHistory;
|
||||
bool mInPrivateBrowsing;
|
||||
bool mDeviceSizeIsPageSize;
|
||||
|
||||
// This boolean is set to true right before we fire pagehide and generally
|
||||
// unset when we embed a new content viewer. While it's true no navigation
|
||||
|
@ -43,7 +43,7 @@ interface nsIReflowObserver;
|
||||
|
||||
typedef unsigned long nsLoadFlags;
|
||||
|
||||
[scriptable, builtinclass, uuid(1470A132-99B2-44C3-B37D-D8093B2E29BF)]
|
||||
[scriptable, builtinclass, uuid(77aca3ee-7417-4cd2-994e-9bd95ca1d98a)]
|
||||
interface nsIDocShell : nsIDocShellTreeItem
|
||||
{
|
||||
/**
|
||||
@ -907,4 +907,16 @@ interface nsIDocShell : nsIDocShellTreeItem
|
||||
*/
|
||||
[noscript, notxpcom] bool IsInvisible();
|
||||
[noscript, notxpcom] void SetInvisible(in bool aIsInvisibleDochsell);
|
||||
|
||||
/**
|
||||
* If deviceSizeIsPageSize is set to true, device-width/height media queries
|
||||
* will be calculated from the page size, not the device size.
|
||||
*
|
||||
* Used by the Responsive Design View and B2G Simulator.
|
||||
*
|
||||
* Default is False.
|
||||
* Default value can be overriden with
|
||||
* docshell.device_size_is_page_size pref.
|
||||
*/
|
||||
[infallible] attribute boolean deviceSizeIsPageSize;
|
||||
};
|
||||
|
@ -390,6 +390,19 @@ nsScreen::SlowMozUnlockOrientation()
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
bool
|
||||
nsScreen::IsDeviceSizePageSize()
|
||||
{
|
||||
nsPIDOMWindow* owner = GetOwner();
|
||||
if (owner) {
|
||||
nsIDocShell* docShell = owner->GetDocShell();
|
||||
if (docShell) {
|
||||
return docShell->GetDeviceSizeIsPageSize();
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/* virtual */
|
||||
JSObject*
|
||||
nsScreen::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope)
|
||||
|
@ -51,6 +51,15 @@ public:
|
||||
int32_t GetWidth(ErrorResult& aRv)
|
||||
{
|
||||
nsRect rect;
|
||||
if (IsDeviceSizePageSize()) {
|
||||
nsCOMPtr<nsPIDOMWindow> owner = GetOwner();
|
||||
if (owner) {
|
||||
int32_t innerWidth = 0;
|
||||
aRv = owner->GetInnerWidth(&innerWidth);
|
||||
return innerWidth;
|
||||
}
|
||||
}
|
||||
|
||||
aRv = GetRect(rect);
|
||||
return rect.width;
|
||||
}
|
||||
@ -58,6 +67,15 @@ public:
|
||||
int32_t GetHeight(ErrorResult& aRv)
|
||||
{
|
||||
nsRect rect;
|
||||
if (IsDeviceSizePageSize()) {
|
||||
nsCOMPtr<nsPIDOMWindow> owner = GetOwner();
|
||||
if (owner) {
|
||||
int32_t innerHeight = 0;
|
||||
aRv = owner->GetInnerHeight(&innerHeight);
|
||||
return innerHeight;
|
||||
}
|
||||
}
|
||||
|
||||
aRv = GetRect(rect);
|
||||
return rect.height;
|
||||
}
|
||||
@ -137,6 +155,8 @@ private:
|
||||
|
||||
LockPermission GetLockOrientationPermission() const;
|
||||
|
||||
bool IsDeviceSizePageSize();
|
||||
|
||||
nsRefPtr<FullScreenEventListener> mEventListener;
|
||||
};
|
||||
|
||||
|
@ -410,7 +410,7 @@ CreateStrokeStyleForOptions(const StrokeOptions &aStrokeOptions)
|
||||
capStyle, joinStyle,
|
||||
aStrokeOptions.mMiterLimit,
|
||||
D2D1_DASH_STYLE_CUSTOM,
|
||||
aStrokeOptions.mDashOffset),
|
||||
aStrokeOptions.mDashOffset / lineWidth),
|
||||
&dash[0], // data() is not C++98, although it's in recent gcc
|
||||
// and VC10's STL
|
||||
dash.size(),
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include "mozilla/MouseEvents.h"
|
||||
#include "mozilla/mozalloc.h" // for operator new
|
||||
#include "mozilla/TouchEvents.h"
|
||||
#include "nsDebug.h" // for NS_WARNING
|
||||
#include "nsPoint.h" // for nsIntPoint
|
||||
#include "nsTArray.h" // for nsTArray, nsTArray_Impl, etc
|
||||
#include "nsThreadUtils.h" // for NS_IsMainThread
|
||||
@ -29,7 +30,8 @@ namespace layers {
|
||||
float APZCTreeManager::sDPI = 72.0;
|
||||
|
||||
APZCTreeManager::APZCTreeManager()
|
||||
: mTreeLock("APZCTreeLock")
|
||||
: mTreeLock("APZCTreeLock"),
|
||||
mTouchCount(0)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
AsyncPanZoomController::InitializeGlobalState();
|
||||
@ -238,6 +240,7 @@ APZCTreeManager::ReceiveInputEvent(const InputData& aEvent)
|
||||
case MULTITOUCH_INPUT: {
|
||||
const MultiTouchInput& multiTouchInput = aEvent.AsMultiTouchInput();
|
||||
if (multiTouchInput.mType == MultiTouchInput::MULTITOUCH_START) {
|
||||
mTouchCount++;
|
||||
mApzcForInputBlock = GetTargetAPZC(ScreenPoint(multiTouchInput.mTouches[0].mScreenPoint));
|
||||
for (size_t i = 1; i < multiTouchInput.mTouches.Length(); i++) {
|
||||
nsRefPtr<AsyncPanZoomController> apzc2 = GetTargetAPZC(ScreenPoint(multiTouchInput.mTouches[i].mScreenPoint));
|
||||
@ -267,10 +270,18 @@ APZCTreeManager::ReceiveInputEvent(const InputData& aEvent)
|
||||
ApplyTransform(&(inputForApzc.mTouches[i].mScreenPoint), transformToApzc);
|
||||
}
|
||||
result = mApzcForInputBlock->ReceiveInputEvent(inputForApzc);
|
||||
}
|
||||
if (multiTouchInput.mType == MultiTouchInput::MULTITOUCH_CANCEL ||
|
||||
multiTouchInput.mType == MultiTouchInput::MULTITOUCH_END) {
|
||||
if (mTouchCount >= multiTouchInput.mTouches.Length()) {
|
||||
mTouchCount -= multiTouchInput.mTouches.Length();
|
||||
} else {
|
||||
NS_WARNING("Got an unexpected touchend/touchcancel");
|
||||
mTouchCount = 0;
|
||||
}
|
||||
// If we have an mApzcForInputBlock and it's the end of the touch sequence
|
||||
// then null it out so we don't keep a dangling reference and leak things.
|
||||
if (multiTouchInput.mType == MultiTouchInput::MULTITOUCH_CANCEL ||
|
||||
(multiTouchInput.mType == MultiTouchInput::MULTITOUCH_END && multiTouchInput.mTouches.Length() == 1)) {
|
||||
if (mTouchCount == 0) {
|
||||
mApzcForInputBlock = nullptr;
|
||||
}
|
||||
}
|
||||
@ -333,31 +344,50 @@ nsEventStatus
|
||||
APZCTreeManager::ProcessTouchEvent(const WidgetTouchEvent& aEvent,
|
||||
WidgetTouchEvent* aOutEvent)
|
||||
{
|
||||
// For computing the input for the APZC, used the cached transform.
|
||||
// This ensures that the sequence of touch points an APZC sees in an
|
||||
// input block are all in the same coordinate space.
|
||||
gfx3DMatrix transformToApzc = mCachedTransformToApzcForInputBlock;
|
||||
MultiTouchInput inputForApzc(aEvent);
|
||||
for (size_t i = 0; i < inputForApzc.mTouches.Length(); i++) {
|
||||
ApplyTransform(&(inputForApzc.mTouches[i].mScreenPoint), transformToApzc);
|
||||
nsEventStatus ret = nsEventStatus_eIgnore;
|
||||
if (!aEvent.touches.Length()) {
|
||||
return ret;
|
||||
}
|
||||
nsEventStatus ret = mApzcForInputBlock->ReceiveInputEvent(inputForApzc);
|
||||
|
||||
// For computing the event to pass back to Gecko, use the up-to-date transforms.
|
||||
// This ensures that transformToApzc and transformToGecko are in sync
|
||||
// (note that transformToGecko isn't cached).
|
||||
gfx3DMatrix transformToGecko;
|
||||
GetInputTransforms(mApzcForInputBlock, transformToApzc, transformToGecko);
|
||||
gfx3DMatrix outTransform = transformToApzc * transformToGecko;
|
||||
for (size_t i = 0; i < aOutEvent->touches.Length(); i++) {
|
||||
ApplyTransform(&(aOutEvent->touches[i]->mRefPoint), outTransform);
|
||||
if (aEvent.message == NS_TOUCH_START) {
|
||||
mTouchCount++;
|
||||
ScreenPoint point = ScreenPoint(aEvent.touches[0]->mRefPoint.x, aEvent.touches[0]->mRefPoint.y);
|
||||
mApzcForInputBlock = GetTouchInputBlockAPZC(aEvent, point);
|
||||
}
|
||||
|
||||
if (mApzcForInputBlock) {
|
||||
// For computing the input for the APZC, used the cached transform.
|
||||
// This ensures that the sequence of touch points an APZC sees in an
|
||||
// input block are all in the same coordinate space.
|
||||
gfx3DMatrix transformToApzc = mCachedTransformToApzcForInputBlock;
|
||||
MultiTouchInput inputForApzc(aEvent);
|
||||
for (size_t i = 0; i < inputForApzc.mTouches.Length(); i++) {
|
||||
ApplyTransform(&(inputForApzc.mTouches[i].mScreenPoint), transformToApzc);
|
||||
}
|
||||
ret = mApzcForInputBlock->ReceiveInputEvent(inputForApzc);
|
||||
|
||||
// For computing the event to pass back to Gecko, use the up-to-date transforms.
|
||||
// This ensures that transformToApzc and transformToGecko are in sync
|
||||
// (note that transformToGecko isn't cached).
|
||||
gfx3DMatrix transformToGecko;
|
||||
GetInputTransforms(mApzcForInputBlock, transformToApzc, transformToGecko);
|
||||
gfx3DMatrix outTransform = transformToApzc * transformToGecko;
|
||||
for (size_t i = 0; i < aOutEvent->touches.Length(); i++) {
|
||||
ApplyTransform(&(aOutEvent->touches[i]->mRefPoint), outTransform);
|
||||
}
|
||||
}
|
||||
// If we have an mApzcForInputBlock and it's the end of the touch sequence
|
||||
// then null it out so we don't keep a dangling reference and leak things.
|
||||
if (aEvent.message == NS_TOUCH_CANCEL ||
|
||||
(aEvent.message == NS_TOUCH_END && aEvent.touches.Length() == 1)) {
|
||||
mApzcForInputBlock = nullptr;
|
||||
aEvent.message == NS_TOUCH_END) {
|
||||
if (mTouchCount >= aEvent.touches.Length()) {
|
||||
mTouchCount -= aEvent.touches.Length();
|
||||
} else {
|
||||
NS_WARNING("Got an unexpected touchend/touchcancel");
|
||||
mTouchCount = 0;
|
||||
}
|
||||
if (mTouchCount == 0) {
|
||||
mApzcForInputBlock = nullptr;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@ -406,16 +436,6 @@ APZCTreeManager::ReceiveInputEvent(const WidgetInputEvent& aEvent,
|
||||
switch (aEvent.eventStructType) {
|
||||
case NS_TOUCH_EVENT: {
|
||||
const WidgetTouchEvent& touchEvent = *aEvent.AsTouchEvent();
|
||||
if (!touchEvent.touches.Length()) {
|
||||
return nsEventStatus_eIgnore;
|
||||
}
|
||||
if (touchEvent.message == NS_TOUCH_START) {
|
||||
ScreenPoint point = ScreenPoint(touchEvent.touches[0]->mRefPoint.x, touchEvent.touches[0]->mRefPoint.y);
|
||||
mApzcForInputBlock = GetTouchInputBlockAPZC(touchEvent, point);
|
||||
}
|
||||
if (!mApzcForInputBlock) {
|
||||
return nsEventStatus_eIgnore;
|
||||
}
|
||||
return ProcessTouchEvent(touchEvent, aOutEvent->AsTouchEvent());
|
||||
}
|
||||
case NS_MOUSE_EVENT: {
|
||||
@ -438,16 +458,6 @@ APZCTreeManager::ReceiveInputEvent(WidgetInputEvent& aEvent)
|
||||
switch (aEvent.eventStructType) {
|
||||
case NS_TOUCH_EVENT: {
|
||||
WidgetTouchEvent& touchEvent = *aEvent.AsTouchEvent();
|
||||
if (!touchEvent.touches.Length()) {
|
||||
return nsEventStatus_eIgnore;
|
||||
}
|
||||
if (touchEvent.message == NS_TOUCH_START) {
|
||||
ScreenPoint point = ScreenPoint(touchEvent.touches[0]->mRefPoint.x, touchEvent.touches[0]->mRefPoint.y);
|
||||
mApzcForInputBlock = GetTouchInputBlockAPZC(touchEvent, point);
|
||||
}
|
||||
if (!mApzcForInputBlock) {
|
||||
return nsEventStatus_eIgnore;
|
||||
}
|
||||
return ProcessTouchEvent(touchEvent, &touchEvent);
|
||||
}
|
||||
default: {
|
||||
|
@ -321,6 +321,8 @@ private:
|
||||
* input delivery thread, and so does not require locking.
|
||||
*/
|
||||
nsRefPtr<AsyncPanZoomController> mApzcForInputBlock;
|
||||
/* The number of touch points we are tracking that are currently on the screen. */
|
||||
uint32_t mTouchCount;
|
||||
/* The transform from root screen coordinates into mApzcForInputBlock's
|
||||
* screen coordinates, as returned through the 'aTransformToApzcOut' parameter
|
||||
* of GetInputTransform(), at the start of the input block. This is cached
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set sw=4 ts=8 et tw=80 : */
|
||||
/* vim: set sw=2 ts=8 et tw=80 : */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
@ -73,11 +73,7 @@ nsEventStatus GestureEventListener::HandleInputEvent(const InputData& aEvent)
|
||||
}
|
||||
}
|
||||
|
||||
NS_WARN_IF_FALSE(!foundAlreadyExistingTouch, "Tried to add a touch that already exists");
|
||||
|
||||
// If we didn't find a touch in our list that matches this, then add it.
|
||||
// If it already existed, we don't want to add it twice because that
|
||||
// messes with our touch move/end code.
|
||||
if (!foundAlreadyExistingTouch) {
|
||||
mTouches.AppendElement(event.mTouches[i]);
|
||||
}
|
||||
@ -137,18 +133,17 @@ nsEventStatus GestureEventListener::HandleInputEvent(const InputData& aEvent)
|
||||
}
|
||||
case MultiTouchInput::MULTITOUCH_END:
|
||||
case MultiTouchInput::MULTITOUCH_LEAVE: {
|
||||
bool foundAlreadyExistingTouch = false;
|
||||
for (size_t i = 0; i < event.mTouches.Length() && !foundAlreadyExistingTouch; i++) {
|
||||
for (size_t i = 0; i < event.mTouches.Length(); i++) {
|
||||
bool foundAlreadyExistingTouch = false;
|
||||
for (size_t j = 0; j < mTouches.Length() && !foundAlreadyExistingTouch; j++) {
|
||||
if (event.mTouches[i].mIdentifier == mTouches[j].mIdentifier) {
|
||||
foundAlreadyExistingTouch = true;
|
||||
mTouches.RemoveElementAt(j);
|
||||
}
|
||||
}
|
||||
NS_WARN_IF_FALSE(foundAlreadyExistingTouch, "Touch ended, but not in list");
|
||||
}
|
||||
|
||||
NS_WARN_IF_FALSE(foundAlreadyExistingTouch, "Touch ended, but not in list");
|
||||
|
||||
if (mState == GESTURE_WAITING_DOUBLE_TAP) {
|
||||
CancelDoubleTapTimeoutTask();
|
||||
if (mTapStartTime - mLastTapEndTime > MAX_TAP_TIME ||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set sw=4 ts=8 et tw=80 : */
|
||||
/* vim: set sw=2 ts=8 et tw=80 : */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
@ -250,63 +250,141 @@ static inline void js_free(void* p)
|
||||
}\
|
||||
\
|
||||
template <class T, class P1>\
|
||||
QUALIFIERS T *NEWNAME(P1 p1) {\
|
||||
JS_NEW_BODY(ALLOCATOR, T, (p1))\
|
||||
QUALIFIERS T *NEWNAME(P1 &&p1) {\
|
||||
JS_NEW_BODY(ALLOCATOR, T,\
|
||||
(mozilla::Forward<P1>(p1)))\
|
||||
}\
|
||||
\
|
||||
template <class T, class P1, class P2>\
|
||||
QUALIFIERS T *NEWNAME(P1 p1, P2 p2) {\
|
||||
JS_NEW_BODY(ALLOCATOR, T, (p1, p2))\
|
||||
QUALIFIERS T *NEWNAME(P1 &&p1, P2 &&p2) {\
|
||||
JS_NEW_BODY(ALLOCATOR, T,\
|
||||
(mozilla::Forward<P1>(p1),\
|
||||
mozilla::Forward<P2>(p2)))\
|
||||
}\
|
||||
\
|
||||
template <class T, class P1, class P2, class P3>\
|
||||
QUALIFIERS T *NEWNAME(P1 p1, P2 p2, P3 p3) {\
|
||||
JS_NEW_BODY(ALLOCATOR, T, (p1, p2, p3))\
|
||||
QUALIFIERS T *NEWNAME(P1 &&p1, P2 &&p2, P3 &&p3) {\
|
||||
JS_NEW_BODY(ALLOCATOR, T,\
|
||||
(mozilla::Forward<P1>(p1),\
|
||||
mozilla::Forward<P2>(p2),\
|
||||
mozilla::Forward<P3>(p3)))\
|
||||
}\
|
||||
\
|
||||
template <class T, class P1, class P2, class P3, class P4>\
|
||||
QUALIFIERS T *NEWNAME(P1 p1, P2 p2, P3 p3, P4 p4) {\
|
||||
JS_NEW_BODY(ALLOCATOR, T, (p1, p2, p3, p4))\
|
||||
QUALIFIERS T *NEWNAME(P1 &&p1, P2 &&p2, P3 &&p3, P4 &&p4) {\
|
||||
JS_NEW_BODY(ALLOCATOR, T,\
|
||||
(mozilla::Forward<P1>(p1),\
|
||||
mozilla::Forward<P2>(p2),\
|
||||
mozilla::Forward<P3>(p3),\
|
||||
mozilla::Forward<P4>(p4)))\
|
||||
}\
|
||||
\
|
||||
template <class T, class P1, class P2, class P3, class P4, class P5>\
|
||||
QUALIFIERS T *NEWNAME(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) {\
|
||||
JS_NEW_BODY(ALLOCATOR, T, (p1, p2, p3, p4, p5))\
|
||||
QUALIFIERS T *NEWNAME(P1 &&p1, P2 &&p2, P3 &&p3, P4 &&p4, P5 &&p5) {\
|
||||
JS_NEW_BODY(ALLOCATOR, T,\
|
||||
(mozilla::Forward<P1>(p1),\
|
||||
mozilla::Forward<P2>(p2),\
|
||||
mozilla::Forward<P3>(p3),\
|
||||
mozilla::Forward<P4>(p4),\
|
||||
mozilla::Forward<P5>(p5)))\
|
||||
}\
|
||||
\
|
||||
template <class T, class P1, class P2, class P3, class P4, class P5, class P6>\
|
||||
QUALIFIERS T *NEWNAME(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6) {\
|
||||
JS_NEW_BODY(ALLOCATOR, T, (p1, p2, p3, p4, p5, p6))\
|
||||
QUALIFIERS T *NEWNAME(P1 &&p1, P2 &&p2, P3 &&p3, P4 &&p4, P5 &&p5, P6 &&p6) {\
|
||||
JS_NEW_BODY(ALLOCATOR, T,\
|
||||
(mozilla::Forward<P1>(p1),\
|
||||
mozilla::Forward<P2>(p2),\
|
||||
mozilla::Forward<P3>(p3),\
|
||||
mozilla::Forward<P4>(p4),\
|
||||
mozilla::Forward<P5>(p5),\
|
||||
mozilla::Forward<P6>(p6)))\
|
||||
}\
|
||||
\
|
||||
template <class T, class P1, class P2, class P3, class P4, class P5, class P6, class P7>\
|
||||
QUALIFIERS T *NEWNAME(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7) {\
|
||||
JS_NEW_BODY(ALLOCATOR, T, (p1, p2, p3, p4, p5, p6, p7))\
|
||||
QUALIFIERS T *NEWNAME(P1 &&p1, P2 &&p2, P3 &&p3, P4 &&p4, P5 &&p5, P6 &&p6, P7 &&p7) {\
|
||||
JS_NEW_BODY(ALLOCATOR, T,\
|
||||
(mozilla::Forward<P1>(p1),\
|
||||
mozilla::Forward<P2>(p2),\
|
||||
mozilla::Forward<P3>(p3),\
|
||||
mozilla::Forward<P4>(p4),\
|
||||
mozilla::Forward<P5>(p5),\
|
||||
mozilla::Forward<P6>(p6),\
|
||||
mozilla::Forward<P7>(p7)))\
|
||||
}\
|
||||
\
|
||||
template <class T, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8>\
|
||||
QUALIFIERS T *NEWNAME(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8) {\
|
||||
JS_NEW_BODY(ALLOCATOR, T, (p1, p2, p3, p4, p5, p6, p7, p8))\
|
||||
QUALIFIERS T *NEWNAME(P1 &&p1, P2 &&p2, P3 &&p3, P4 &&p4, P5 &&p5, P6 &&p6, P7 &&p7, P8 &&p8) {\
|
||||
JS_NEW_BODY(ALLOCATOR, T,\
|
||||
(mozilla::Forward<P1>(p1),\
|
||||
mozilla::Forward<P2>(p2),\
|
||||
mozilla::Forward<P3>(p3),\
|
||||
mozilla::Forward<P4>(p4),\
|
||||
mozilla::Forward<P5>(p5),\
|
||||
mozilla::Forward<P6>(p6),\
|
||||
mozilla::Forward<P7>(p7),\
|
||||
mozilla::Forward<P8>(p8)))\
|
||||
}\
|
||||
\
|
||||
template <class T, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8, class P9>\
|
||||
QUALIFIERS T *NEWNAME(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8, P9 p9) {\
|
||||
JS_NEW_BODY(ALLOCATOR, T, (p1, p2, p3, p4, p5, p6, p7, p8, p9))\
|
||||
QUALIFIERS T *NEWNAME(P1 &&p1, P2 &&p2, P3 &&p3, P4 &&p4, P5 &&p5, P6 &&p6, P7 &&p7, P8 &&p8, P9 &&p9) {\
|
||||
JS_NEW_BODY(ALLOCATOR, T,\
|
||||
(mozilla::Forward<P1>(p1),\
|
||||
mozilla::Forward<P2>(p2),\
|
||||
mozilla::Forward<P3>(p3),\
|
||||
mozilla::Forward<P4>(p4),\
|
||||
mozilla::Forward<P5>(p5),\
|
||||
mozilla::Forward<P6>(p6),\
|
||||
mozilla::Forward<P7>(p7),\
|
||||
mozilla::Forward<P8>(p8),\
|
||||
mozilla::Forward<P9>(p9)))\
|
||||
}\
|
||||
\
|
||||
template <class T, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8, class P9, class P10>\
|
||||
QUALIFIERS T *NEWNAME(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8, P9 p9, P10 p10) {\
|
||||
JS_NEW_BODY(ALLOCATOR, T, (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10))\
|
||||
QUALIFIERS T *NEWNAME(P1 &&p1, P2 &&p2, P3 &&p3, P4 &&p4, P5 &&p5, P6 &&p6, P7 &&p7, P8 &&p8, P9 &&p9, P10 &&p10) {\
|
||||
JS_NEW_BODY(ALLOCATOR, T,\
|
||||
(mozilla::Forward<P1>(p1),\
|
||||
mozilla::Forward<P2>(p2),\
|
||||
mozilla::Forward<P3>(p3),\
|
||||
mozilla::Forward<P4>(p4),\
|
||||
mozilla::Forward<P5>(p5),\
|
||||
mozilla::Forward<P6>(p6),\
|
||||
mozilla::Forward<P7>(p7),\
|
||||
mozilla::Forward<P8>(p8),\
|
||||
mozilla::Forward<P9>(p9),\
|
||||
mozilla::Forward<P10>(p10)))\
|
||||
}\
|
||||
\
|
||||
template <class T, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8, class P9, class P10, class P11>\
|
||||
QUALIFIERS T *NEWNAME(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8, P9 p9, P10 p10, P11 p11) {\
|
||||
JS_NEW_BODY(ALLOCATOR, T, (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11))\
|
||||
QUALIFIERS T *NEWNAME(P1 &&p1, P2 &&p2, P3 &&p3, P4 &&p4, P5 &&p5, P6 &&p6, P7 &&p7, P8 &&p8, P9 &&p9, P10 &&p10, P11 &&p11) {\
|
||||
JS_NEW_BODY(ALLOCATOR, T,\
|
||||
(mozilla::Forward<P1>(p1),\
|
||||
mozilla::Forward<P2>(p2),\
|
||||
mozilla::Forward<P3>(p3),\
|
||||
mozilla::Forward<P4>(p4),\
|
||||
mozilla::Forward<P5>(p5),\
|
||||
mozilla::Forward<P6>(p6),\
|
||||
mozilla::Forward<P7>(p7),\
|
||||
mozilla::Forward<P8>(p8),\
|
||||
mozilla::Forward<P9>(p9),\
|
||||
mozilla::Forward<P10>(p10),\
|
||||
mozilla::Forward<P11>(p11)))\
|
||||
}\
|
||||
\
|
||||
template <class T, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8, class P9, class P10, class P11, class P12>\
|
||||
QUALIFIERS T *NEWNAME(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8, P9 p9, P10 p10, P11 p11, P12 p12) {\
|
||||
JS_NEW_BODY(ALLOCATOR, T, (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12))\
|
||||
QUALIFIERS T *NEWNAME(P1 &&p1, P2 &&p2, P3 &&p3, P4 &&p4, P5 &&p5, P6 &&p6, P7 &&p7, P8 &&p8, P9 &&p9, P10 &&p10, P11 &&p11, P12 &&p12) {\
|
||||
JS_NEW_BODY(ALLOCATOR, T,\
|
||||
(mozilla::Forward<P1>(p1),\
|
||||
mozilla::Forward<P2>(p2),\
|
||||
mozilla::Forward<P3>(p3),\
|
||||
mozilla::Forward<P4>(p4),\
|
||||
mozilla::Forward<P5>(p5),\
|
||||
mozilla::Forward<P6>(p6),\
|
||||
mozilla::Forward<P7>(p7),\
|
||||
mozilla::Forward<P8>(p8),\
|
||||
mozilla::Forward<P9>(p9),\
|
||||
mozilla::Forward<P10>(p10),\
|
||||
mozilla::Forward<P11>(p11),\
|
||||
mozilla::Forward<P12>(p12)))\
|
||||
}\
|
||||
|
||||
JS_DECLARE_NEW_METHODS(js_new, js_malloc, static JS_ALWAYS_INLINE)
|
||||
|
13
js/src/jit-test/tests/baseline/bug934427.js
Normal file
13
js/src/jit-test/tests/baseline/bug934427.js
Normal file
@ -0,0 +1,13 @@
|
||||
// |jit-test| error: InternalError
|
||||
|
||||
function f(){
|
||||
var j;
|
||||
f(0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,
|
||||
0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,
|
||||
0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,
|
||||
0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,
|
||||
0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,
|
||||
0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,
|
||||
0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9);
|
||||
}
|
||||
f()
|
@ -489,7 +489,14 @@ BaselineCompiler::emitStackCheck(bool earlyCheck)
|
||||
pushArg(Imm32(tolerance));
|
||||
masm.loadBaselineFramePtr(BaselineFrameReg, R1.scratchReg());
|
||||
pushArg(R1.scratchReg());
|
||||
if (!callVM(CheckOverRecursedWithExtraInfo, /*preInitialize=*/earlyCheck))
|
||||
|
||||
CallVMPhase phase = POST_INITIALIZE;
|
||||
if (earlyCheck)
|
||||
phase = PRE_INITIALIZE;
|
||||
else if (needsEarlyStackCheck())
|
||||
phase = CHECK_OVER_RECURSED;
|
||||
|
||||
if (!callVM(CheckOverRecursedWithExtraInfo, phase))
|
||||
return false;
|
||||
|
||||
masm.bind(&skipCall);
|
||||
@ -536,6 +543,10 @@ static const VMFunction HeavyweightFunPrologueInfo =
|
||||
bool
|
||||
BaselineCompiler::initScopeChain()
|
||||
{
|
||||
CallVMPhase phase = POST_INITIALIZE;
|
||||
if (needsEarlyStackCheck())
|
||||
phase = CHECK_OVER_RECURSED;
|
||||
|
||||
RootedFunction fun(cx, function());
|
||||
if (fun) {
|
||||
// Use callee->environment as scope chain. Note that we do
|
||||
@ -554,7 +565,7 @@ BaselineCompiler::initScopeChain()
|
||||
masm.loadBaselineFramePtr(BaselineFrameReg, R0.scratchReg());
|
||||
pushArg(R0.scratchReg());
|
||||
|
||||
if (!callVM(HeavyweightFunPrologueInfo))
|
||||
if (!callVM(HeavyweightFunPrologueInfo, phase))
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
@ -568,7 +579,7 @@ BaselineCompiler::initScopeChain()
|
||||
masm.loadBaselineFramePtr(BaselineFrameReg, R0.scratchReg());
|
||||
pushArg(R0.scratchReg());
|
||||
|
||||
if (!callVM(StrictEvalPrologueInfo))
|
||||
if (!callVM(StrictEvalPrologueInfo, phase))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -1976,7 +1976,7 @@ AnalyzePoppedThis(JSContext *cx, types::TypeObject *type,
|
||||
RootedId id(cx, NameToId(setprop->name()));
|
||||
RootedValue value(cx, UndefinedValue());
|
||||
if (!DefineNativeProperty(cx, baseobj, id, value, nullptr, nullptr,
|
||||
JSPROP_ENUMERATE, 0, 0, DNP_SKIP_TYPE))
|
||||
JSPROP_ENUMERATE, 0, 0))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
@ -6310,14 +6310,9 @@ IonBuilder::setStaticName(JSObject *staticObject, PropertyName *name)
|
||||
// If the property has a known type, we may be able to optimize typed stores by not
|
||||
// storing the type tag.
|
||||
MIRType slotType = MIRType_None;
|
||||
{
|
||||
Shape *shape = staticObject->nativeLookup(cx, id);
|
||||
if (!shape || !shape->hasSlot() || !staticObject->getSlot(shape->slot()).isUndefined()) {
|
||||
JSValueType knownType = property.knownTypeTag(constraints());
|
||||
if (knownType != JSVAL_TYPE_UNKNOWN)
|
||||
slotType = MIRTypeFromValueType(knownType);
|
||||
}
|
||||
}
|
||||
JSValueType knownType = property.knownTypeTag(constraints());
|
||||
if (knownType != JSVAL_TYPE_UNKNOWN)
|
||||
slotType = MIRTypeFromValueType(knownType);
|
||||
|
||||
bool needsBarrier = property.needsBarrier(constraints());
|
||||
return storeSlot(obj, property.maybeTypes()->definiteSlot(), NumFixedSlots(staticObject),
|
||||
|
@ -462,7 +462,7 @@ SetProperty(JSContext *cx, HandleObject obj, HandlePropertyName name, HandleValu
|
||||
// required for initializing 'const' closure variables.
|
||||
Shape *shape = obj->nativeLookup(cx, name);
|
||||
JS_ASSERT(shape && shape->hasSlot());
|
||||
JSObject::nativeSetSlotWithType(cx, obj, shape, value);
|
||||
obj->nativeSetSlotWithType(cx, shape, value);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -31,7 +31,7 @@ BaselineCompilerShared::BaselineCompilerShared(JSContext *cx, HandleScript scrip
|
||||
{ }
|
||||
|
||||
bool
|
||||
BaselineCompilerShared::callVM(const VMFunction &fun, bool preInitialize)
|
||||
BaselineCompilerShared::callVM(const VMFunction &fun, CallVMPhase phase)
|
||||
{
|
||||
IonCode *code = cx->runtime()->jitRuntime()->getVMWrapper(fun);
|
||||
if (!code)
|
||||
@ -50,14 +50,43 @@ BaselineCompilerShared::callVM(const VMFunction &fun, bool preInitialize)
|
||||
// Assert all arguments were pushed.
|
||||
JS_ASSERT(masm.framePushed() - pushedBeforeCall_ == argSize);
|
||||
|
||||
uint32_t frameVals = preInitialize ? 0 : frame.nlocals() + frame.stackDepth();
|
||||
uint32_t frameSize = BaselineFrame::FramePointerOffset + BaselineFrame::Size() +
|
||||
(frameVals * sizeof(Value));
|
||||
Address frameSizeAddress(BaselineFrameReg, BaselineFrame::reverseOffsetOfFrameSize());
|
||||
uint32_t frameVals = frame.nlocals() + frame.stackDepth();
|
||||
uint32_t frameBaseSize = BaselineFrame::FramePointerOffset + BaselineFrame::Size();
|
||||
uint32_t frameFullSize = frameBaseSize + (frameVals * sizeof(Value));
|
||||
if (phase == POST_INITIALIZE) {
|
||||
masm.store32(Imm32(frameFullSize), frameSizeAddress);
|
||||
uint32_t descriptor = MakeFrameDescriptor(frameFullSize + argSize, IonFrame_BaselineJS);
|
||||
masm.push(Imm32(descriptor));
|
||||
|
||||
masm.store32(Imm32(frameSize), Address(BaselineFrameReg, BaselineFrame::reverseOffsetOfFrameSize()));
|
||||
} else if (phase == PRE_INITIALIZE) {
|
||||
masm.store32(Imm32(frameBaseSize), frameSizeAddress);
|
||||
uint32_t descriptor = MakeFrameDescriptor(frameBaseSize + argSize, IonFrame_BaselineJS);
|
||||
masm.push(Imm32(descriptor));
|
||||
|
||||
uint32_t descriptor = MakeFrameDescriptor(frameSize + argSize, IonFrame_BaselineJS);
|
||||
masm.push(Imm32(descriptor));
|
||||
} else {
|
||||
JS_ASSERT(phase == CHECK_OVER_RECURSED);
|
||||
Label afterWrite;
|
||||
Label writePostInitialize;
|
||||
|
||||
// If OVER_RECURSED is set, then frame locals haven't been pushed yet.
|
||||
masm.branchTest32(Assembler::Zero,
|
||||
frame.addressOfFlags(),
|
||||
Imm32(BaselineFrame::OVER_RECURSED),
|
||||
&writePostInitialize);
|
||||
|
||||
masm.move32(Imm32(frameBaseSize), BaselineTailCallReg);
|
||||
masm.jump(&afterWrite);
|
||||
|
||||
masm.bind(&writePostInitialize);
|
||||
masm.move32(Imm32(frameFullSize), BaselineTailCallReg);
|
||||
|
||||
masm.bind(&afterWrite);
|
||||
masm.store32(BaselineTailCallReg, frameSizeAddress);
|
||||
masm.add32(Imm32(argSize), BaselineTailCallReg);
|
||||
masm.makeFrameDescriptor(BaselineTailCallReg, IonFrame_BaselineJS);
|
||||
masm.push(BaselineTailCallReg);
|
||||
}
|
||||
|
||||
// Perform the call.
|
||||
masm.call(code);
|
||||
|
@ -127,7 +127,12 @@ class BaselineCompilerShared
|
||||
masm.Push(BaselineFrameReg);
|
||||
}
|
||||
|
||||
bool callVM(const VMFunction &fun, bool preInitialize=false);
|
||||
enum CallVMPhase {
|
||||
POST_INITIALIZE,
|
||||
PRE_INITIALIZE,
|
||||
CHECK_OVER_RECURSED
|
||||
};
|
||||
bool callVM(const VMFunction &fun, CallVMPhase phase=POST_INITIALIZE);
|
||||
|
||||
public:
|
||||
BytecodeAnalysis &analysis() {
|
||||
|
@ -520,7 +520,8 @@ ScriptAnalysis::analyzeLifetimes(JSContext *cx)
|
||||
/* Restore all saved variables. :FIXME: maybe do this precisely. */
|
||||
for (unsigned i = 0; i < savedCount; i++) {
|
||||
LifetimeVariable &var = *saved[i];
|
||||
var.lifetime = alloc.new_<Lifetime>(offset, var.savedEnd, var.saved);
|
||||
uint32_t savedEnd = var.savedEnd;
|
||||
var.lifetime = alloc.new_<Lifetime>(offset, savedEnd, var.saved);
|
||||
if (!var.lifetime) {
|
||||
js_free(saved);
|
||||
setOOM(cx);
|
||||
@ -612,7 +613,8 @@ ScriptAnalysis::analyzeLifetimes(JSContext *cx)
|
||||
* Jumping to a place where this variable is live. Make a new
|
||||
* lifetime segment for the variable.
|
||||
*/
|
||||
var.lifetime = alloc.new_<Lifetime>(offset, var.savedEnd, var.saved);
|
||||
uint32_t savedEnd = var.savedEnd;
|
||||
var.lifetime = alloc.new_<Lifetime>(offset, savedEnd, var.saved);
|
||||
if (!var.lifetime) {
|
||||
js_free(saved);
|
||||
setOOM(cx);
|
||||
@ -676,7 +678,8 @@ ScriptAnalysis::addVariable(JSContext *cx, LifetimeVariable &var, unsigned offse
|
||||
}
|
||||
}
|
||||
}
|
||||
var.lifetime = cx->typeLifoAlloc().new_<Lifetime>(offset, var.savedEnd, var.saved);
|
||||
uint32_t savedEnd = var.savedEnd;
|
||||
var.lifetime = cx->typeLifoAlloc().new_<Lifetime>(offset, savedEnd, var.saved);
|
||||
if (!var.lifetime) {
|
||||
setOOM(cx);
|
||||
return;
|
||||
@ -691,7 +694,8 @@ ScriptAnalysis::killVariable(JSContext *cx, LifetimeVariable &var, unsigned offs
|
||||
{
|
||||
if (!var.lifetime) {
|
||||
/* Make a point lifetime indicating the write. */
|
||||
Lifetime *lifetime = cx->typeLifoAlloc().new_<Lifetime>(offset, var.savedEnd, var.saved);
|
||||
uint32_t savedEnd = var.savedEnd;
|
||||
Lifetime *lifetime = cx->typeLifoAlloc().new_<Lifetime>(offset, savedEnd, var.saved);
|
||||
if (!lifetime) {
|
||||
setOOM(cx);
|
||||
return;
|
||||
|
@ -286,7 +286,7 @@ SetArrayElement(JSContext *cx, HandleObject obj, double index, HandleValue v)
|
||||
break;
|
||||
if (idx >= arr->length())
|
||||
arr->setLengthInt32(idx + 1);
|
||||
JSObject::setDenseElementWithType(cx, arr, idx, v);
|
||||
arr->setDenseElementWithType(cx, idx, v);
|
||||
return true;
|
||||
} while (false);
|
||||
|
||||
@ -677,14 +677,12 @@ js::ArraySetLength(typename ExecutionModeTraits<mode>::ContextType cxArg,
|
||||
|
||||
RootedValue v(cxArg, NumberValue(newLen));
|
||||
if (mode == ParallelExecution) {
|
||||
// Adding the property type or overflowing int32 requires changing TI
|
||||
// state.
|
||||
if (!HasTypePropertyId(arr, id, v) || newLen > INT32_MAX)
|
||||
// Overflowing int32 requires changing TI state.
|
||||
if (newLen > INT32_MAX)
|
||||
return false;
|
||||
arr->setLengthInt32(newLen);
|
||||
} else {
|
||||
JSContext *cx = cxArg->asJSContext();
|
||||
AddTypePropertyId(cx, arr, id, v);
|
||||
ArrayObject::setLength(cx, arr, newLen);
|
||||
}
|
||||
|
||||
@ -2022,7 +2020,7 @@ NewbornArrayPushImpl(JSContext *cx, HandleObject obj, const Value &v)
|
||||
|
||||
arr->setDenseInitializedLength(length + 1);
|
||||
arr->setLengthInt32(length + 1);
|
||||
JSObject::initDenseElementWithType(cx, arr, length, v);
|
||||
arr->initDenseElementWithType(cx, length, v);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -2066,7 +2064,7 @@ js::array_push(JSContext *cx, unsigned argc, Value *vp)
|
||||
|
||||
if (result == JSObject::ED_OK) {
|
||||
for (uint32_t i = 0, index = length; i < argCount; index++, i++)
|
||||
JSObject::setDenseElementWithType(cx, obj, index, args[i]);
|
||||
obj->setDenseElementWithType(cx, index, args[i]);
|
||||
uint32_t newlength = length + argCount;
|
||||
args.rval().setNumber(newlength);
|
||||
if (obj->is<ArrayObject>()) {
|
||||
|
@ -1000,7 +1000,7 @@ class ConstraintDataFreeze
|
||||
const char *kind() { return "freeze"; }
|
||||
|
||||
bool invalidateOnNewType(Type type) { return true; }
|
||||
bool invalidateOnNewPropertyState(TypeSet *property) { return false; }
|
||||
bool invalidateOnNewPropertyState(TypeSet *property) { return true; }
|
||||
bool invalidateOnNewObjectState(TypeObject *object) { return false; }
|
||||
|
||||
bool constraintHolds(JSContext *cx,
|
||||
@ -1103,7 +1103,7 @@ HeapTypeSetKey::knownTypeTag(CompilerConstraintList *constraints)
|
||||
bool
|
||||
HeapTypeSetKey::isOwnProperty(CompilerConstraintList *constraints)
|
||||
{
|
||||
if (maybeTypes() && !maybeTypes()->empty())
|
||||
if (maybeTypes() && (!maybeTypes()->empty() || maybeTypes()->configuredProperty()))
|
||||
return true;
|
||||
if (JSObject *obj = object()->singleton()) {
|
||||
if (CanHaveEmptyPropertyTypesForOwnProperty(obj))
|
||||
@ -1138,9 +1138,9 @@ TemporaryTypeSet::getSingleton()
|
||||
JSObject *
|
||||
HeapTypeSetKey::singleton(CompilerConstraintList *constraints)
|
||||
{
|
||||
TypeSet *types = maybeTypes();
|
||||
HeapTypeSet *types = maybeTypes();
|
||||
|
||||
if (!types || types->baseFlags() != 0 || types->getObjectCount() != 1)
|
||||
if (!types || types->configuredProperty() || types->baseFlags() != 0 || types->getObjectCount() != 1)
|
||||
return nullptr;
|
||||
|
||||
JSObject *obj = types->getSingleObject(0);
|
||||
|
@ -536,7 +536,7 @@ MarkTypeObjectUnknownProperties(JSContext *cx, TypeObject *obj,
|
||||
* have a getter/setter.
|
||||
*/
|
||||
inline void
|
||||
MarkTypePropertyConfigured(ExclusiveContext *cx, HandleObject obj, jsid id)
|
||||
MarkTypePropertyConfigured(ExclusiveContext *cx, JSObject *obj, jsid id)
|
||||
{
|
||||
if (cx->typeInferenceEnabled()) {
|
||||
id = IdToTypeId(id);
|
||||
|
138
js/src/jsobj.cpp
138
js/src/jsobj.cpp
@ -1442,9 +1442,9 @@ js::NewObjectWithClassProtoCommon(ExclusiveContext *cxArg,
|
||||
* Create a plain object with the specified type. This bypasses getNewType to
|
||||
* avoid losing creation site information for objects made by scripted 'new'.
|
||||
*/
|
||||
static JSObject *
|
||||
NewObjectWithType(JSContext *cx, HandleTypeObject type, JSObject *parent, gc::AllocKind allocKind,
|
||||
NewObjectKind newKind = GenericObject)
|
||||
JSObject *
|
||||
js::NewObjectWithType(JSContext *cx, HandleTypeObject type, JSObject *parent, gc::AllocKind allocKind,
|
||||
NewObjectKind newKind)
|
||||
{
|
||||
JS_ASSERT(type->proto->hasNewType(&JSObject::class_, type));
|
||||
JS_ASSERT(parent);
|
||||
@ -1500,46 +1500,6 @@ js::NewObjectScriptedCall(JSContext *cx, MutableHandleObject pobj)
|
||||
return true;
|
||||
}
|
||||
|
||||
JSObject *
|
||||
js::NewReshapedObject(JSContext *cx, HandleTypeObject type, JSObject *parent,
|
||||
gc::AllocKind allocKind, HandleShape shape, NewObjectKind newKind)
|
||||
{
|
||||
RootedObject res(cx, NewObjectWithType(cx, type, parent, allocKind, newKind));
|
||||
if (!res)
|
||||
return nullptr;
|
||||
|
||||
if (shape->isEmptyShape())
|
||||
return res;
|
||||
|
||||
/* Get all the ids in the object, in order. */
|
||||
js::AutoIdVector ids(cx);
|
||||
{
|
||||
for (unsigned i = 0; i <= shape->slot(); i++) {
|
||||
if (!ids.append(JSID_VOID))
|
||||
return nullptr;
|
||||
}
|
||||
Shape *nshape = shape;
|
||||
while (!nshape->isEmptyShape()) {
|
||||
ids[nshape->slot()] = nshape->propid();
|
||||
nshape = nshape->previous();
|
||||
}
|
||||
}
|
||||
|
||||
/* Construct the new shape. */
|
||||
RootedId id(cx);
|
||||
RootedValue undefinedValue(cx, UndefinedValue());
|
||||
for (unsigned i = 0; i < ids.length(); i++) {
|
||||
id = ids[i];
|
||||
if (!DefineNativeProperty(cx, res, id, undefinedValue, nullptr, nullptr,
|
||||
JSPROP_ENUMERATE, 0, 0, DNP_SKIP_TYPE)) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
JS_ASSERT(!res->inDictionaryMode());
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
JSObject*
|
||||
js::CreateThis(JSContext *cx, const Class *newclasp, HandleObject callee)
|
||||
{
|
||||
@ -2224,7 +2184,6 @@ DefineStandardSlot(JSContext *cx, HandleObject obj, JSProtoKey key, JSAtom *atom
|
||||
uint32_t slot = GlobalObject::constructorPropertySlot(key);
|
||||
if (!JSObject::addProperty(cx, obj, id, JS_PropertyStub, JS_StrictPropertyStub, slot, attrs, 0, 0))
|
||||
return false;
|
||||
AddTypePropertyId(cx, obj, id, v);
|
||||
|
||||
named = true;
|
||||
return true;
|
||||
@ -3431,7 +3390,7 @@ CallAddPropertyHook(typename ExecutionModeTraits<mode>::ExclusiveContextType cxA
|
||||
}
|
||||
if (value.get() != nominal) {
|
||||
if (shape->hasSlot())
|
||||
JSObject::nativeSetSlotWithType(cx, obj, shape, value);
|
||||
obj->nativeSetSlotWithType(cx, shape, value);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
@ -3473,16 +3432,43 @@ CallAddPropertyHookDense(typename ExecutionModeTraits<mode>::ExclusiveContextTyp
|
||||
|
||||
Rooted<jsid> id(cx, INT_TO_JSID(index));
|
||||
if (!CallJSPropertyOp(cx->asJSContext(), clasp->addProperty, obj, id, &value)) {
|
||||
JSObject::setDenseElementHole(cx, obj, index);
|
||||
obj->setDenseElementHole(cx, index);
|
||||
return false;
|
||||
}
|
||||
if (value.get() != nominal)
|
||||
JSObject::setDenseElementWithType(cx, obj, index, value);
|
||||
obj->setDenseElementWithType(cx, index, value);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template <ExecutionMode mode>
|
||||
static bool
|
||||
UpdateShapeTypeAndValue(typename ExecutionModeTraits<mode>::ExclusiveContextType cx,
|
||||
JSObject *obj, Shape *shape, const Value &value)
|
||||
{
|
||||
jsid id = shape->propid();
|
||||
if (shape->hasSlot()) {
|
||||
if (mode == ParallelExecution) {
|
||||
if (!obj->nativeSetSlotIfHasType(shape, value))
|
||||
return false;
|
||||
} else {
|
||||
obj->nativeSetSlotWithType(cx->asExclusiveContext(), shape, value);
|
||||
}
|
||||
}
|
||||
if (!shape->hasSlot() || !shape->writable() ||
|
||||
!shape->hasDefaultGetter() || !shape->hasDefaultSetter())
|
||||
{
|
||||
if (mode == ParallelExecution) {
|
||||
if (!IsTypePropertyIdMarkedConfigured(obj, id))
|
||||
return false;
|
||||
} else {
|
||||
MarkTypePropertyConfigured(cx->asExclusiveContext(), obj, id);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template <ExecutionMode mode>
|
||||
static inline bool
|
||||
DefinePropertyOrElement(typename ExecutionModeTraits<mode>::ExclusiveContextType cx,
|
||||
@ -3517,7 +3503,12 @@ DefinePropertyOrElement(typename ExecutionModeTraits<mode>::ExclusiveContextType
|
||||
if (result == JSObject::ED_FAILED)
|
||||
return false;
|
||||
if (result == JSObject::ED_OK) {
|
||||
obj->setDenseElementMaybeConvertDouble(index, value);
|
||||
if (mode == ParallelExecution) {
|
||||
if (!obj->setDenseElementIfHasType(index, value))
|
||||
return false;
|
||||
} else {
|
||||
obj->setDenseElementWithType(cx->asExclusiveContext(), index, value);
|
||||
}
|
||||
return CallAddPropertyHookDense<mode>(cx, obj->getClass(), obj, index, value);
|
||||
}
|
||||
}
|
||||
@ -3549,8 +3540,8 @@ DefinePropertyOrElement(typename ExecutionModeTraits<mode>::ExclusiveContextType
|
||||
if (!shape)
|
||||
return false;
|
||||
|
||||
if (shape->hasSlot())
|
||||
obj->nativeSetSlot(shape->slot(), value);
|
||||
if (!UpdateShapeTypeAndValue<mode>(cx, obj, shape, value))
|
||||
return false;
|
||||
|
||||
/*
|
||||
* Clear any existing dense index after adding a sparse indexed property,
|
||||
@ -3594,7 +3585,7 @@ js::DefineNativeProperty(ExclusiveContext *cx, HandleObject obj, HandleId id, Ha
|
||||
PropertyOp getter, StrictPropertyOp setter, unsigned attrs,
|
||||
unsigned flags, int shortid, unsigned defineHow /* = 0 */)
|
||||
{
|
||||
JS_ASSERT((defineHow & ~(DNP_DONT_PURGE | DNP_SKIP_TYPE)) == 0);
|
||||
JS_ASSERT((defineHow & ~DNP_DONT_PURGE) == 0);
|
||||
JS_ASSERT(!(attrs & JSPROP_NATIVE_ACCESSORS));
|
||||
|
||||
AutoRooterGetterSetter gsRoot(cx, attrs, &getter, &setter);
|
||||
@ -3606,10 +3597,6 @@ js::DefineNativeProperty(ExclusiveContext *cx, HandleObject obj, HandleId id, Ha
|
||||
*/
|
||||
RootedShape shape(cx);
|
||||
if (attrs & (JSPROP_GETTER | JSPROP_SETTER)) {
|
||||
/* Type information for getter/setter properties is unknown. */
|
||||
AddTypePropertyId(cx, obj, id, types::Type::UnknownType());
|
||||
MarkTypePropertyConfigured(cx, obj, id);
|
||||
|
||||
/*
|
||||
* If we are defining a getter whose setter was already defined, or
|
||||
* vice versa, finish the job via obj->changeProperty.
|
||||
@ -3656,24 +3643,13 @@ js::DefineNativeProperty(ExclusiveContext *cx, HandleObject obj, HandleId id, Ha
|
||||
if (!setter && !(attrs & JSPROP_SETTER))
|
||||
setter = clasp->setProperty;
|
||||
|
||||
if ((getter == JS_PropertyStub) && !(defineHow & DNP_SKIP_TYPE)) {
|
||||
/*
|
||||
* Type information for normal native properties should reflect the
|
||||
* initial value of the property.
|
||||
*/
|
||||
AddTypePropertyId(cx, obj, id, value);
|
||||
if (attrs & JSPROP_READONLY)
|
||||
MarkTypePropertyConfigured(cx, obj, id);
|
||||
}
|
||||
|
||||
if (!shape) {
|
||||
return DefinePropertyOrElement<SequentialExecution>(cx, obj, id, getter, setter,
|
||||
attrs, flags, shortid, value,
|
||||
false, false);
|
||||
}
|
||||
|
||||
if (shape->hasSlot())
|
||||
obj->nativeSetSlot(shape->slot(), value);
|
||||
JS_ALWAYS_TRUE(UpdateShapeTypeAndValue<SequentialExecution>(cx, obj, shape, value));
|
||||
|
||||
return CallAddPropertyHook<SequentialExecution>(cx, clasp, obj, shape, value);
|
||||
}
|
||||
@ -4162,7 +4138,7 @@ js::NativeSet(typename ExecutionModeTraits<mode>::ContextType cxArg,
|
||||
if (!obj->nativeSetSlotIfHasType(shape, vp))
|
||||
return false;
|
||||
} else {
|
||||
obj->nativeSetSlotWithType(cxArg->asExclusiveContext(), obj, shape, vp);
|
||||
obj->nativeSetSlotWithType(cxArg->asExclusiveContext(), shape, vp);
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -4197,8 +4173,7 @@ js::NativeSet(typename ExecutionModeTraits<mode>::ContextType cxArg,
|
||||
if (shape->hasSlot() &&
|
||||
(JS_LIKELY(cx->runtime()->propertyRemovals == sample) ||
|
||||
obj->nativeContains(cx, shape)))
|
||||
{
|
||||
AddTypePropertyId(cx, obj, shape->propid(), ovp);
|
||||
{
|
||||
obj->setSlot(shape->slot(), vp);
|
||||
}
|
||||
|
||||
@ -4242,10 +4217,6 @@ GetPropertyHelperInline(JSContext *cx,
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Record non-undefined values produced by the class getter hook. */
|
||||
if (!vp.isUndefined())
|
||||
AddTypePropertyId(cx, obj, id, vp);
|
||||
|
||||
/*
|
||||
* Give a strict warning if foo.bar is evaluated by a script for an
|
||||
* object foo with no property named 'bar'.
|
||||
@ -4830,7 +4801,7 @@ baseops::SetPropertyHelper(typename ExecutionModeTraits<mode>::ContextType cxArg
|
||||
if (mode == ParallelExecution)
|
||||
obj->setDenseElementIfHasType(index, vp);
|
||||
else
|
||||
JSObject::setDenseElementWithType(cxArg->asJSContext(), obj, index, vp);
|
||||
obj->setDenseElementWithType(cxArg->asJSContext(), index, vp);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -4871,9 +4842,6 @@ baseops::SetPropertyHelper(typename ExecutionModeTraits<mode>::ContextType cxArg
|
||||
/* Purge the property cache of now-shadowed id in obj's scope chain. */
|
||||
if (!PurgeScopeChain(cx, obj, id))
|
||||
return false;
|
||||
|
||||
if (getter == JS_PropertyStub)
|
||||
AddTypePropertyId(cx, obj, id, vp);
|
||||
}
|
||||
|
||||
return DefinePropertyOrElement<mode>(cxArg, obj, id, getter, setter,
|
||||
@ -4937,9 +4905,15 @@ baseops::SetAttributes(JSContext *cx, HandleObject obj, HandleId id, unsigned *a
|
||||
return false;
|
||||
shape = obj->nativeLookup(cx, id);
|
||||
}
|
||||
return nobj->isNative()
|
||||
? JSObject::changePropertyAttributes(cx, nobj, shape, *attrsp)
|
||||
: JSObject::setGenericAttributes(cx, nobj, id, attrsp);
|
||||
if (nobj->isNative()) {
|
||||
if (!JSObject::changePropertyAttributes(cx, nobj, shape, *attrsp))
|
||||
return false;
|
||||
if (*attrsp & JSPROP_READONLY)
|
||||
MarkTypePropertyConfigured(cx, obj, id);
|
||||
return true;
|
||||
} else {
|
||||
return JSObject::setGenericAttributes(cx, nobj, id, attrsp);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
@ -4965,7 +4939,7 @@ baseops::DeleteGeneric(JSContext *cx, HandleObject obj, HandleId id, bool *succe
|
||||
if (!succeeded)
|
||||
return true;
|
||||
|
||||
JSObject::setDenseElementHole(cx, obj, JSID_TO_INT(id));
|
||||
obj->setDenseElementHole(cx, JSID_TO_INT(id));
|
||||
return js_SuppressDeletedProperty(cx, obj, id);
|
||||
}
|
||||
|
||||
|
@ -409,10 +409,8 @@ class JSObject : public js::ObjectImpl
|
||||
}
|
||||
|
||||
inline bool nativeSetSlotIfHasType(js::Shape *shape, const js::Value &value);
|
||||
|
||||
static inline void nativeSetSlotWithType(js::ExclusiveContext *cx,
|
||||
js::HandleObject, js::Shape *shape,
|
||||
const js::Value &value);
|
||||
inline void nativeSetSlotWithType(js::ExclusiveContext *cx, js::Shape *shape,
|
||||
const js::Value &value);
|
||||
|
||||
inline const js::Value &getReservedSlot(uint32_t index) const {
|
||||
JS_ASSERT(index < JSSLOT_FREE(getClass()));
|
||||
@ -642,12 +640,11 @@ class JSObject : public js::ObjectImpl
|
||||
}
|
||||
|
||||
inline bool setDenseElementIfHasType(uint32_t index, const js::Value &val);
|
||||
static inline void setDenseElementWithType(js::ExclusiveContext *cx, js::HandleObject obj,
|
||||
uint32_t index, const js::Value &val);
|
||||
static inline void initDenseElementWithType(js::ExclusiveContext *cx, js::HandleObject obj,
|
||||
uint32_t index, const js::Value &val);
|
||||
static inline void setDenseElementHole(js::ExclusiveContext *cx,
|
||||
js::HandleObject obj, uint32_t index);
|
||||
inline void setDenseElementWithType(js::ExclusiveContext *cx, uint32_t index,
|
||||
const js::Value &val);
|
||||
inline void initDenseElementWithType(js::ExclusiveContext *cx, uint32_t index,
|
||||
const js::Value &val);
|
||||
inline void setDenseElementHole(js::ExclusiveContext *cx, uint32_t index);
|
||||
static inline void removeDenseElementForSparseIndex(js::ExclusiveContext *cx,
|
||||
js::HandleObject obj, uint32_t index);
|
||||
|
||||
@ -1394,7 +1391,6 @@ const unsigned DNP_DONT_PURGE = 1; /* suppress js_PurgeScopeChain */
|
||||
const unsigned DNP_UNQUALIFIED = 2; /* Unqualified property set. Only used in
|
||||
the defineHow argument of
|
||||
js_SetPropertyHelper. */
|
||||
const unsigned DNP_SKIP_TYPE = 4; /* Don't update type information */
|
||||
|
||||
/*
|
||||
* Return successfully added or changed shape or nullptr on error.
|
||||
|
@ -43,7 +43,6 @@ JSObject::deleteProperty(JSContext *cx, js::HandleObject obj, js::HandleProperty
|
||||
bool *succeeded)
|
||||
{
|
||||
JS::RootedId id(cx, js::NameToId(name));
|
||||
js::types::AddTypePropertyId(cx, obj, id, js::types::Type::UndefinedType());
|
||||
js::types::MarkTypePropertyConfigured(cx, obj, id);
|
||||
js::DeletePropertyOp op = obj->getOps()->deleteProperty;
|
||||
return (op ? op : js::baseops::DeleteProperty)(cx, obj, name, succeeded);
|
||||
@ -55,7 +54,6 @@ JSObject::deleteElement(JSContext *cx, js::HandleObject obj, uint32_t index, boo
|
||||
JS::RootedId id(cx);
|
||||
if (!js::IndexToId(cx, index, &id))
|
||||
return false;
|
||||
js::types::AddTypePropertyId(cx, obj, id, js::types::Type::UndefinedType());
|
||||
js::types::MarkTypePropertyConfigured(cx, obj, id);
|
||||
js::DeleteElementOp op = obj->getOps()->deleteElement;
|
||||
return (op ? op : js::baseops::DeleteElement)(cx, obj, index, succeeded);
|
||||
@ -66,7 +64,6 @@ JSObject::deleteSpecial(JSContext *cx, js::HandleObject obj, js::HandleSpecialId
|
||||
bool *succeeded)
|
||||
{
|
||||
JS::RootedId id(cx, SPECIALID_TO_JSID(sid));
|
||||
js::types::AddTypePropertyId(cx, obj, id, js::types::Type::UndefinedType());
|
||||
js::types::MarkTypePropertyConfigured(cx, obj, id);
|
||||
js::DeleteSpecialOp op = obj->getOps()->deleteSpecial;
|
||||
return (op ? op : js::baseops::DeleteSpecial)(cx, obj, sid, succeeded);
|
||||
@ -145,32 +142,32 @@ JSObject::setDenseElementIfHasType(uint32_t index, const js::Value &val)
|
||||
return true;
|
||||
}
|
||||
|
||||
/* static */ inline void
|
||||
JSObject::setDenseElementWithType(js::ExclusiveContext *cx, js::HandleObject obj, uint32_t index,
|
||||
inline void
|
||||
JSObject::setDenseElementWithType(js::ExclusiveContext *cx, uint32_t index,
|
||||
const js::Value &val)
|
||||
{
|
||||
// Avoid a slow AddTypePropertyId call if the type is the same as the type
|
||||
// of the previous element.
|
||||
js::types::Type thisType = js::types::GetValueType(val);
|
||||
if (index == 0 || js::types::GetValueType(obj->elements[index - 1]) != thisType)
|
||||
js::types::AddTypePropertyId(cx, obj, JSID_VOID, thisType);
|
||||
obj->setDenseElementMaybeConvertDouble(index, val);
|
||||
if (index == 0 || js::types::GetValueType(elements[index - 1]) != thisType)
|
||||
js::types::AddTypePropertyId(cx, this, JSID_VOID, thisType);
|
||||
setDenseElementMaybeConvertDouble(index, val);
|
||||
}
|
||||
|
||||
/* static */ inline void
|
||||
JSObject::initDenseElementWithType(js::ExclusiveContext *cx, js::HandleObject obj, uint32_t index,
|
||||
inline void
|
||||
JSObject::initDenseElementWithType(js::ExclusiveContext *cx, uint32_t index,
|
||||
const js::Value &val)
|
||||
{
|
||||
JS_ASSERT(!obj->shouldConvertDoubleElements());
|
||||
js::types::AddTypePropertyId(cx, obj, JSID_VOID, val);
|
||||
obj->initDenseElement(index, val);
|
||||
JS_ASSERT(!shouldConvertDoubleElements());
|
||||
js::types::AddTypePropertyId(cx, this, JSID_VOID, val);
|
||||
initDenseElement(index, val);
|
||||
}
|
||||
|
||||
/* static */ inline void
|
||||
JSObject::setDenseElementHole(js::ExclusiveContext *cx, js::HandleObject obj, uint32_t index)
|
||||
inline void
|
||||
JSObject::setDenseElementHole(js::ExclusiveContext *cx, uint32_t index)
|
||||
{
|
||||
js::types::MarkTypeObjectFlags(cx, obj, js::types::OBJECT_FLAG_NON_PACKED);
|
||||
obj->setDenseElement(index, js::MagicValue(JS_ELEMENTS_HOLE));
|
||||
js::types::MarkTypeObjectFlags(cx, this, js::types::OBJECT_FLAG_NON_PACKED);
|
||||
setDenseElement(index, js::MagicValue(JS_ELEMENTS_HOLE));
|
||||
}
|
||||
|
||||
/* static */ inline void
|
||||
@ -535,12 +532,12 @@ JSObject::nativeSetSlotIfHasType(js::Shape *shape, const js::Value &value)
|
||||
return true;
|
||||
}
|
||||
|
||||
/* static */ inline void
|
||||
JSObject::nativeSetSlotWithType(js::ExclusiveContext *cx, js::HandleObject obj, js::Shape *shape,
|
||||
inline void
|
||||
JSObject::nativeSetSlotWithType(js::ExclusiveContext *cx, js::Shape *shape,
|
||||
const js::Value &value)
|
||||
{
|
||||
obj->nativeSetSlot(shape->slot(), value);
|
||||
js::types::AddTypePropertyId(cx, obj, shape->propid(), value);
|
||||
nativeSetSlot(shape->slot(), value);
|
||||
js::types::AddTypePropertyId(cx, this, shape->propid(), value);
|
||||
}
|
||||
|
||||
/* static */ inline bool
|
||||
@ -903,6 +900,10 @@ CopyInitializerObject(JSContext *cx, HandleObject baseobj, NewObjectKind newKind
|
||||
return obj;
|
||||
}
|
||||
|
||||
JSObject *
|
||||
NewObjectWithType(JSContext *cx, HandleTypeObject type, JSObject *parent, gc::AllocKind allocKind,
|
||||
NewObjectKind newKind = GenericObject);
|
||||
|
||||
JSObject *
|
||||
NewReshapedObject(JSContext *cx, HandleTypeObject type, JSObject *parent,
|
||||
gc::AllocKind allocKind, HandleShape shape,
|
||||
@ -945,7 +946,6 @@ DefineConstructorAndPrototype(JSContext *cx, Handle<GlobalObject*> global,
|
||||
global->setPrototype(key, ObjectValue(*proto));
|
||||
global->setConstructorPropertySlot(key, ObjectValue(*ctor));
|
||||
|
||||
types::AddTypePropertyId(cx, global, id, ObjectValue(*ctor));
|
||||
if (!global->addDataProperty(cx, id, GlobalObject::constructorPropertySlot(key), 0)) {
|
||||
global->setConstructor(key, UndefinedValue());
|
||||
global->setPrototype(key, UndefinedValue());
|
||||
@ -953,6 +953,7 @@ DefineConstructorAndPrototype(JSContext *cx, Handle<GlobalObject*> global,
|
||||
return false;
|
||||
}
|
||||
|
||||
types::AddTypePropertyId(cx, global, id, ObjectValue(*ctor));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -23,8 +23,6 @@ ArrayObject::setLength(ExclusiveContext *cx, Handle<ArrayObject*> arr, uint32_t
|
||||
if (length > INT32_MAX) {
|
||||
/* Track objects with overflowing lengths in type information. */
|
||||
types::MarkTypeObjectFlags(cx, arr, types::OBJECT_FLAG_LENGTH_OVERFLOW);
|
||||
jsid lengthId = NameToId(cx->names().length);
|
||||
types::AddTypePropertyId(cx, arr, lengthId, types::Type::DoubleType());
|
||||
}
|
||||
|
||||
arr->getElementsHeader()->length = length;
|
||||
|
@ -411,7 +411,7 @@ js::intrinsic_UnsafePutElements(JSContext *cx, unsigned argc, Value *vp)
|
||||
|
||||
if (arrobj->isNative()) {
|
||||
JS_ASSERT(idx < arrobj->getDenseInitializedLength());
|
||||
JSObject::setDenseElementWithType(cx, arrobj, idx, args[elemi]);
|
||||
arrobj->setDenseElementWithType(cx, idx, args[elemi]);
|
||||
} else {
|
||||
JS_ASSERT(idx < arrobj->as<TypedArrayObject>().length());
|
||||
RootedValue tmp(cx, args[elemi]);
|
||||
|
@ -673,6 +673,61 @@ JSObject::addPropertyInternal<ParallelExecution>(ForkJoinSlice *cx,
|
||||
unsigned flags, int shortid, Shape **spp,
|
||||
bool allowDictionary);
|
||||
|
||||
JSObject *
|
||||
js::NewReshapedObject(JSContext *cx, HandleTypeObject type, JSObject *parent,
|
||||
gc::AllocKind allocKind, HandleShape shape, NewObjectKind newKind)
|
||||
{
|
||||
RootedObject res(cx, NewObjectWithType(cx, type, parent, allocKind, newKind));
|
||||
if (!res)
|
||||
return nullptr;
|
||||
|
||||
if (shape->isEmptyShape())
|
||||
return res;
|
||||
|
||||
/* Get all the ids in the object, in order. */
|
||||
js::AutoIdVector ids(cx);
|
||||
{
|
||||
for (unsigned i = 0; i <= shape->slot(); i++) {
|
||||
if (!ids.append(JSID_VOID))
|
||||
return nullptr;
|
||||
}
|
||||
Shape *nshape = shape;
|
||||
while (!nshape->isEmptyShape()) {
|
||||
ids[nshape->slot()] = nshape->propid();
|
||||
nshape = nshape->previous();
|
||||
}
|
||||
}
|
||||
|
||||
/* Construct the new shape, without updating type information. */
|
||||
RootedId id(cx);
|
||||
RootedShape newShape(cx, res->lastProperty());
|
||||
for (unsigned i = 0; i < ids.length(); i++) {
|
||||
id = ids[i];
|
||||
JS_ASSERT(!res->nativeContains(cx, id));
|
||||
|
||||
uint32_t index;
|
||||
bool indexed = js_IdIsIndex(id, &index);
|
||||
|
||||
Rooted<UnownedBaseShape*> nbase(cx, newShape->base()->toUnowned());
|
||||
if (indexed) {
|
||||
StackBaseShape base(nbase);
|
||||
base.flags |= BaseShape::INDEXED;
|
||||
nbase = GetOrLookupUnownedBaseShape<SequentialExecution>(cx, base);
|
||||
if (!nbase)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
StackShape child(nbase, id, i, res->numFixedSlots(), JSPROP_ENUMERATE, 0, 0);
|
||||
newShape = cx->compartment()->propertyTree.getChild(cx, newShape, res->numFixedSlots(), child);
|
||||
if (!newShape)
|
||||
return nullptr;
|
||||
if (!JSObject::setLastProperty(cx, res, newShape))
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check and adjust the new attributes for the shape to make sure that our
|
||||
* slot access optimizations are sound. It is responsibility of the callers to
|
||||
@ -925,16 +980,6 @@ JSObject::changeProperty(typename ExecutionModeTraits<mode>::ExclusiveContextTyp
|
||||
types::MarkTypePropertyConfigured(cx->asExclusiveContext(), obj, shape->propid());
|
||||
}
|
||||
|
||||
if (attrs & (JSPROP_GETTER | JSPROP_SETTER)) {
|
||||
if (mode == ParallelExecution) {
|
||||
if (!types::HasTypePropertyId(obj, shape->propid(), types::Type::UnknownType()))
|
||||
return nullptr;
|
||||
} else {
|
||||
types::AddTypePropertyId(cx->asExclusiveContext(), obj, shape->propid(),
|
||||
types::Type::UnknownType());
|
||||
}
|
||||
}
|
||||
|
||||
if (getter == JS_PropertyStub)
|
||||
getter = nullptr;
|
||||
if (setter == JS_StrictPropertyStub)
|
||||
|
@ -1260,6 +1260,13 @@ nsLayoutUtils::GetActiveScrolledRootFor(nsIFrame* aFrame,
|
||||
nsIFrame* parent = GetCrossDocParentFrame(f);
|
||||
if (!parent)
|
||||
break;
|
||||
nsIAtom* parentType = parent->GetType();
|
||||
#ifdef ANDROID
|
||||
// Treat the slider thumb as being as an active scrolled root
|
||||
// on mobile so that it can move without repainting.
|
||||
if (parentType == nsGkAtoms::sliderFrame)
|
||||
break;
|
||||
#endif
|
||||
// Sticky frames are active if their nearest scrollable frame
|
||||
// is also active, just keep a record of sticky frames that we
|
||||
// encounter for now.
|
||||
@ -1267,8 +1274,8 @@ nsLayoutUtils::GetActiveScrolledRootFor(nsIFrame* aFrame,
|
||||
!stickyFrame) {
|
||||
stickyFrame = f;
|
||||
}
|
||||
nsIScrollableFrame* sf = do_QueryFrame(parent);
|
||||
if (sf) {
|
||||
if (parentType == nsGkAtoms::scrollFrame) {
|
||||
nsIScrollableFrame* sf = do_QueryFrame(parent);
|
||||
if (sf->IsScrollingActive() && sf->GetScrolledFrame() == f) {
|
||||
// If we found a sticky frame inside this active scroll frame,
|
||||
// then use that. Otherwise use the scroll frame.
|
||||
|
@ -2688,6 +2688,17 @@ nsPresContext::AppUnitsToGfxUnits(nscoord aAppUnits) const
|
||||
return mDeviceContext->AppUnitsToGfxUnits(aAppUnits);
|
||||
}
|
||||
|
||||
bool
|
||||
nsPresContext::IsDeviceSizePageSize()
|
||||
{
|
||||
bool isDeviceSizePageSize = false;
|
||||
nsCOMPtr<nsIDocShell> docShell(do_QueryReferent(mContainer));
|
||||
if (docShell) {
|
||||
isDeviceSizePageSize = docShell->GetDeviceSizeIsPageSize();
|
||||
}
|
||||
return isDeviceSizePageSize;
|
||||
}
|
||||
|
||||
nsRootPresContext::nsRootPresContext(nsIDocument* aDocument,
|
||||
nsPresContextType aType)
|
||||
: nsPresContext(aDocument, aType),
|
||||
|
@ -1000,6 +1000,8 @@ public:
|
||||
mExistThrottledUpdates = aExistThrottledUpdates;
|
||||
}
|
||||
|
||||
bool IsDeviceSizePageSize();
|
||||
|
||||
protected:
|
||||
friend class nsRunnableMethod<nsPresContext>;
|
||||
NS_HIDDEN_(void) ThemeChangedInternal();
|
||||
|
@ -113,14 +113,18 @@ static nsSize
|
||||
GetDeviceSize(nsPresContext* aPresContext)
|
||||
{
|
||||
nsSize size;
|
||||
if (aPresContext->IsRootPaginatedDocument())
|
||||
|
||||
if (aPresContext->IsDeviceSizePageSize()) {
|
||||
size = GetSize(aPresContext);
|
||||
} else if (aPresContext->IsRootPaginatedDocument()) {
|
||||
// We want the page size, including unprintable areas and margins.
|
||||
// XXX The spec actually says we want the "page sheet size", but
|
||||
// how is that different?
|
||||
size = aPresContext->GetPageSize();
|
||||
else
|
||||
} else {
|
||||
GetDeviceContextFor(aPresContext)->
|
||||
GetDeviceSurfaceDimensions(size.width, size.height);
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
|
@ -20,16 +20,9 @@ import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Paint;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.view.SurfaceHolder;
|
||||
import android.view.SurfaceView;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
@ -49,6 +42,10 @@ public class GeckoView extends LayerView
|
||||
boolean doInit = a.getBoolean(R.styleable.GeckoView_doinit, true);
|
||||
a.recycle();
|
||||
|
||||
// TODO: Fennec currently takes care of its own initialization, so this
|
||||
// flag is a hack used in Fennec to prevent GeckoView initialization.
|
||||
// This should go away once Fennec also uses GeckoView for
|
||||
// initialization.
|
||||
if (!doInit)
|
||||
return;
|
||||
|
||||
@ -97,12 +94,17 @@ public class GeckoView extends LayerView
|
||||
ThreadUtils.setUiThread(Thread.currentThread(), new Handler());
|
||||
initializeView(GeckoAppShell.getEventDispatcher());
|
||||
|
||||
GeckoProfile profile = GeckoProfile.get(context).forceCreate();
|
||||
BrowserDB.initialize(profile.getName());
|
||||
|
||||
if (GeckoThread.checkAndSetLaunchState(GeckoThread.LaunchState.Launching, GeckoThread.LaunchState.Launched)) {
|
||||
// This is the first launch, so finish initialization and go.
|
||||
GeckoProfile profile = GeckoProfile.get(context).forceCreate();
|
||||
BrowserDB.initialize(profile.getName());
|
||||
|
||||
GeckoAppShell.setLayerView(this);
|
||||
GeckoThread.createAndStart();
|
||||
} else if(GeckoThread.checkLaunchState(GeckoThread.LaunchState.GeckoRunning)) {
|
||||
// If Gecko is already running, that means the Activity was
|
||||
// destroyed, so we need to re-attach Gecko to this GeckoView.
|
||||
connectToGecko();
|
||||
}
|
||||
}
|
||||
|
||||
@ -195,7 +197,7 @@ public class GeckoView extends LayerView
|
||||
});
|
||||
}
|
||||
|
||||
private void handleReady(final JSONObject message) {
|
||||
private void connectToGecko() {
|
||||
GeckoThread.setLaunchState(GeckoThread.LaunchState.GeckoRunning);
|
||||
Tab selectedTab = Tabs.getInstance().getSelectedTab();
|
||||
if (selectedTab != null)
|
||||
@ -203,8 +205,10 @@ public class GeckoView extends LayerView
|
||||
geckoConnected();
|
||||
GeckoAppShell.setLayerClient(getLayerClient());
|
||||
GeckoAppShell.sendEventToGecko(GeckoEvent.createBroadcastEvent("Viewport:Flush", null));
|
||||
show();
|
||||
requestRender();
|
||||
}
|
||||
|
||||
private void handleReady(final JSONObject message) {
|
||||
connectToGecko();
|
||||
|
||||
if (mChromeDelegate != null) {
|
||||
mChromeDelegate.onReady(this);
|
||||
|
@ -1,8 +1,7 @@
|
||||
#filter substitution
|
||||
package @ANDROID_PACKAGE_NAME@.tests;
|
||||
package org.mozilla.gecko.tests;
|
||||
|
||||
import com.jayway.android.robotium.solo.Condition;
|
||||
import @ANDROID_PACKAGE_NAME@.*;
|
||||
import org.mozilla.gecko.*;
|
||||
|
||||
import android.content.ContentResolver;
|
||||
import android.database.Cursor;
|
@ -1,9 +1,8 @@
|
||||
#filter substitution
|
||||
package @ANDROID_PACKAGE_NAME@.tests;
|
||||
package org.mozilla.gecko.tests;
|
||||
|
||||
import com.jayway.android.robotium.solo.Condition;
|
||||
import com.jayway.android.robotium.solo.Solo;
|
||||
import @ANDROID_PACKAGE_NAME@.*;
|
||||
import org.mozilla.gecko.*;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.Instrumentation;
|
||||
@ -46,7 +45,7 @@ abstract class BaseTest extends ActivityInstrumentationTestCase2<Activity> {
|
||||
public static final int TEST_TALOS = 1;
|
||||
|
||||
private static final String TARGET_PACKAGE_ID = "org.mozilla.gecko";
|
||||
private static final String LAUNCH_ACTIVITY_FULL_CLASSNAME ="@ANDROID_PACKAGE_NAME@.App";
|
||||
private static final String LAUNCH_ACTIVITY_FULL_CLASSNAME = TestConstants.ANDROID_PACKAGE_NAME + ".App";
|
||||
private static final int VERIFY_URL_TIMEOUT = 2000;
|
||||
private static final int MAX_LIST_ATTEMPTS = 3;
|
||||
private static final int MAX_WAIT_ENABLED_TEXT_MS = 10000;
|
@ -1,7 +1,6 @@
|
||||
#filter substitution
|
||||
package @ANDROID_PACKAGE_NAME@.tests;
|
||||
package org.mozilla.gecko.tests;
|
||||
|
||||
import @ANDROID_PACKAGE_NAME@.*;
|
||||
import org.mozilla.gecko.*;
|
||||
import android.content.ContentResolver;
|
||||
import android.util.DisplayMetrics;
|
||||
|
@ -1,5 +1,4 @@
|
||||
#filter substitution
|
||||
package @ANDROID_PACKAGE_NAME@.tests;
|
||||
package org.mozilla.gecko.tests;
|
||||
|
||||
import android.content.ContentProvider;
|
||||
import android.content.ContentValues;
|
@ -1,7 +1,6 @@
|
||||
#filter substitution
|
||||
package @ANDROID_PACKAGE_NAME@.tests;
|
||||
package org.mozilla.gecko.tests;
|
||||
|
||||
import @ANDROID_PACKAGE_NAME@.*;
|
||||
import org.mozilla.gecko.*;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.ContentResolver;
|
||||
@ -39,7 +38,7 @@ class DatabaseHelper {
|
||||
protected Uri buildUri(BrowserDataType dataType) {
|
||||
Uri uri = null;
|
||||
if (dataType == BrowserDataType.BOOKMARKS || dataType == BrowserDataType.HISTORY) {
|
||||
uri = Uri.parse("content://@ANDROID_PACKAGE_NAME@.db.browser/" + dataType.toString().toLowerCase());
|
||||
uri = Uri.parse("content://" + TestConstants.ANDROID_PACKAGE_NAME + ".db.browser/" + dataType.toString().toLowerCase());
|
||||
} else {
|
||||
mAsserter.ok(false, "The wrong data type has been provided = " + dataType.toString(), "Please provide the correct data type");
|
||||
}
|
@ -1,7 +1,6 @@
|
||||
#filter substitution
|
||||
package @ANDROID_PACKAGE_NAME@.tests;
|
||||
package org.mozilla.gecko.tests;
|
||||
|
||||
import @ANDROID_PACKAGE_NAME@.*;
|
||||
import org.mozilla.gecko.*;
|
||||
|
||||
import android.util.Log;
|
||||
|
@ -1,5 +1,4 @@
|
||||
#filter substitution
|
||||
package @ANDROID_PACKAGE_NAME@.tests;
|
||||
package org.mozilla.gecko.tests;
|
||||
|
||||
import android.app.Instrumentation;
|
||||
import android.os.SystemClock;
|
@ -1,5 +1,4 @@
|
||||
#filter substitution
|
||||
package @ANDROID_PACKAGE_NAME@.tests;
|
||||
package org.mozilla.gecko.tests;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.InputStream;
|
@ -1,7 +1,6 @@
|
||||
#filter substitution
|
||||
package @ANDROID_PACKAGE_NAME@.tests;
|
||||
package org.mozilla.gecko.tests;
|
||||
|
||||
import @ANDROID_PACKAGE_NAME@.*;
|
||||
import org.mozilla.gecko.*;
|
||||
|
||||
abstract class PixelTest extends BaseTest {
|
||||
private static final long PAINT_CLEAR_DELAY = 10000; // milliseconds
|
@ -1,7 +1,6 @@
|
||||
#filter substitution
|
||||
package @ANDROID_PACKAGE_NAME@.tests;
|
||||
package org.mozilla.gecko.tests;
|
||||
|
||||
import @ANDROID_PACKAGE_NAME@.*;
|
||||
import org.mozilla.gecko.*;
|
||||
|
||||
class StringHelper {
|
||||
// Note: DEFAULT_BOOKMARKS_TITLES.length == DEFAULT_BOOKMARKS_URLS.length
|
11
mobile/android/base/tests/TestConstants.java.in
Normal file
11
mobile/android/base/tests/TestConstants.java.in
Normal file
@ -0,0 +1,11 @@
|
||||
#filter substitution
|
||||
/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
|
||||
* 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/. */
|
||||
|
||||
package org.mozilla.gecko;
|
||||
|
||||
public class TestConstants {
|
||||
public static final String ANDROID_PACKAGE_NAME = "@ANDROID_PACKAGE_NAME@";
|
||||
}
|
@ -1,7 +1,6 @@
|
||||
#filter substitution
|
||||
package @ANDROID_PACKAGE_NAME@.tests;
|
||||
package org.mozilla.gecko.tests;
|
||||
|
||||
import @ANDROID_PACKAGE_NAME@.*;
|
||||
import org.mozilla.gecko.*;
|
||||
|
||||
/* Tests related to the about: page:
|
||||
* - check that about: loads from the URL bar
|
@ -1,7 +1,6 @@
|
||||
#filter substitution
|
||||
package @ANDROID_PACKAGE_NAME@.tests;
|
||||
package org.mozilla.gecko.tests;
|
||||
|
||||
import @ANDROID_PACKAGE_NAME@.*;
|
||||
import org.mozilla.gecko.*;
|
||||
import android.view.View;
|
||||
import android.widget.ListAdapter;
|
||||
import android.widget.ListView;
|
@ -1,7 +1,6 @@
|
||||
#filter substitution
|
||||
package @ANDROID_PACKAGE_NAME@.tests;
|
||||
package org.mozilla.gecko.tests;
|
||||
|
||||
import @ANDROID_PACKAGE_NAME@.*;
|
||||
import org.mozilla.gecko.*;
|
||||
import android.util.DisplayMetrics;
|
||||
|
||||
import org.json.JSONArray;
|
@ -1,5 +1,4 @@
|
||||
#filter substitution
|
||||
package @ANDROID_PACKAGE_NAME@.tests;
|
||||
package org.mozilla.gecko.tests;
|
||||
|
||||
public class testAwesomebar extends BaseTest {
|
||||
@Override
|
@ -1,5 +1,4 @@
|
||||
#filter substitution
|
||||
package @ANDROID_PACKAGE_NAME@.tests;
|
||||
package org.mozilla.gecko.tests;
|
||||
|
||||
import com.jayway.android.robotium.solo.Solo;
|
||||
|
||||
@ -7,7 +6,7 @@ import android.widget.ListView;
|
||||
import android.widget.TabWidget;
|
||||
import android.support.v4.view.ViewPager;
|
||||
|
||||
import @ANDROID_PACKAGE_NAME@.*;
|
||||
import org.mozilla.gecko.*;
|
||||
|
||||
/* Tests swiping between tabs on the awesome bar and other basic
|
||||
awesome bar tab selections.
|
@ -1,7 +1,6 @@
|
||||
#filter substitution
|
||||
package @ANDROID_PACKAGE_NAME@.tests;
|
||||
package org.mozilla.gecko.tests;
|
||||
|
||||
import @ANDROID_PACKAGE_NAME@.*;
|
||||
import org.mozilla.gecko.*;
|
||||
|
||||
/**
|
||||
* Basic test for axis locking behaviour.
|
@ -1,7 +1,6 @@
|
||||
#filter substitution
|
||||
package @ANDROID_PACKAGE_NAME@.tests;
|
||||
package org.mozilla.gecko.tests;
|
||||
|
||||
import @ANDROID_PACKAGE_NAME@.*;
|
||||
import org.mozilla.gecko.*;
|
||||
|
||||
import android.view.View;
|
||||
import android.widget.ListView;
|
@ -1,7 +1,6 @@
|
||||
#filter substitution
|
||||
package @ANDROID_PACKAGE_NAME@.tests;
|
||||
package org.mozilla.gecko.tests;
|
||||
|
||||
import @ANDROID_PACKAGE_NAME@.*;
|
||||
import org.mozilla.gecko.*;
|
||||
|
||||
import com.jayway.android.robotium.solo.Condition;
|
||||
|
@ -1,7 +1,6 @@
|
||||
#filter substitution
|
||||
package @ANDROID_PACKAGE_NAME@.tests;
|
||||
package org.mozilla.gecko.tests;
|
||||
|
||||
import @ANDROID_PACKAGE_NAME@.*;
|
||||
import org.mozilla.gecko.*;
|
||||
|
||||
public class testBookmarkKeyword extends AboutHomeTest {
|
||||
|
@ -1,7 +1,6 @@
|
||||
#filter substitution
|
||||
package @ANDROID_PACKAGE_NAME@.tests;
|
||||
package org.mozilla.gecko.tests;
|
||||
|
||||
import @ANDROID_PACKAGE_NAME@.*;
|
||||
import org.mozilla.gecko.*;
|
||||
import android.database.Cursor;
|
||||
|
||||
import android.widget.ListView;
|
@ -1,7 +1,6 @@
|
||||
#filter substitution
|
||||
package @ANDROID_PACKAGE_NAME@.tests;
|
||||
package org.mozilla.gecko.tests;
|
||||
|
||||
import @ANDROID_PACKAGE_NAME@.*;
|
||||
import org.mozilla.gecko.*;
|
||||
|
||||
public class testBookmarksPage extends AboutHomeTest {
|
||||
|
@ -1,5 +1,4 @@
|
||||
#filter substitution
|
||||
package @ANDROID_PACKAGE_NAME@.tests;
|
||||
package org.mozilla.gecko.tests;
|
||||
|
||||
import android.content.ContentValues;
|
||||
import android.content.ContentUris;
|
@ -1,5 +1,4 @@
|
||||
#filter substitution
|
||||
package @ANDROID_PACKAGE_NAME@.tests;
|
||||
package org.mozilla.gecko.tests;
|
||||
|
||||
import android.content.ContentResolver;
|
||||
import android.content.ContentValues;
|
@ -1,7 +1,6 @@
|
||||
#filter substitution
|
||||
package @ANDROID_PACKAGE_NAME@.tests;
|
||||
package org.mozilla.gecko.tests;
|
||||
|
||||
import @ANDROID_PACKAGE_NAME@.*;
|
||||
import org.mozilla.gecko.*;
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.support.v4.app.Fragment;
|
@ -1,5 +1,4 @@
|
||||
#filter substitution
|
||||
package @ANDROID_PACKAGE_NAME@.tests;
|
||||
package org.mozilla.gecko.tests;
|
||||
|
||||
public class testCheck extends PixelTest {
|
||||
private void pause(int length) {
|
@ -1,5 +1,4 @@
|
||||
#filter substitution
|
||||
package @ANDROID_PACKAGE_NAME@.tests;
|
||||
package org.mozilla.gecko.tests;
|
||||
|
||||
public class testCheck2 extends PixelTest {
|
||||
@Override
|
@ -1,7 +1,6 @@
|
||||
#filter substitution
|
||||
package @ANDROID_PACKAGE_NAME@.tests;
|
||||
package org.mozilla.gecko.tests;
|
||||
|
||||
import @ANDROID_PACKAGE_NAME@.*;
|
||||
import org.mozilla.gecko.*;
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class testClearPrivateData extends PixelTest {
|
@ -1,7 +1,6 @@
|
||||
#filter substitution
|
||||
package @ANDROID_PACKAGE_NAME@.tests;
|
||||
package org.mozilla.gecko.tests;
|
||||
|
||||
import @ANDROID_PACKAGE_NAME@.*;
|
||||
import org.mozilla.gecko.*;
|
||||
|
||||
|
||||
public class testDeviceSearchEngine extends JavascriptTest {
|
@ -1,7 +1,6 @@
|
||||
#filter substitution
|
||||
package @ANDROID_PACKAGE_NAME@.tests;
|
||||
package org.mozilla.gecko.tests;
|
||||
|
||||
import @ANDROID_PACKAGE_NAME@.*;
|
||||
import org.mozilla.gecko.*;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
@ -1,7 +1,6 @@
|
||||
#filter substitution
|
||||
package @ANDROID_PACKAGE_NAME@.tests;
|
||||
package org.mozilla.gecko.tests;
|
||||
|
||||
import @ANDROID_PACKAGE_NAME@.*;
|
||||
import org.mozilla.gecko.*;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.SharedPreferences;
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user