зеркало из https://github.com/mozilla/gecko-dev.git
Merge mozilla-central to inbound. a=merge CLOSED TREE
This commit is contained in:
Коммит
f0bb72977e
|
@ -32,6 +32,11 @@ XPCOMUtils.defineLazyGetter(this, "PageMenuChild", () => {
|
|||
return new tmp.PageMenuChild();
|
||||
});
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "ReferrerInfo", () =>
|
||||
Components.Constructor("@mozilla.org/referrer-info;1",
|
||||
"nsIReferrerInfo",
|
||||
"init"));
|
||||
|
||||
const messageListeners = {
|
||||
"ContextMenu:BookmarkFrame": function(aMessage) {
|
||||
let frame = this.getTarget(aMessage).ownerDocument;
|
||||
|
@ -602,6 +607,15 @@ class ContextMenuChild extends ActorChild {
|
|||
|
||||
data.context.targetAsCPOW = targetAsCPOW;
|
||||
|
||||
data.referrerInfo = new ReferrerInfo(
|
||||
referrerPolicy,
|
||||
!context.linkHasNoReferrer,
|
||||
data.documentURIObject);
|
||||
data.frameReferrerInfo = new ReferrerInfo(
|
||||
referrerPolicy,
|
||||
!context.linkHasNoReferrer,
|
||||
referrer ? Services.io.newURI(referrer) : null);
|
||||
|
||||
mainWin.setContextMenuContentData(data);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -314,8 +314,7 @@ function openLinkIn(url, where, params) {
|
|||
var aAllowThirdPartyFixup = params.allowThirdPartyFixup;
|
||||
var aPostData = params.postData;
|
||||
var aCharset = params.charset;
|
||||
var aReferrerInfo = ("referrerInfo" in params)
|
||||
? params.referrerInfo
|
||||
var aReferrerInfo = params.referrerInfo ? params.referrerInfo
|
||||
: new ReferrerInfo(Ci.nsIHttpChannel.REFERRER_POLICY_UNSET, true, null);
|
||||
var aRelatedToCurrent = params.relatedToCurrent;
|
||||
var aAllowInheritPrincipal = !!params.allowInheritPrincipal;
|
||||
|
|
|
@ -50,6 +50,20 @@ var MigrationWizard = { /* exported MigrationWizard */
|
|||
}
|
||||
}
|
||||
|
||||
document.addEventListener("wizardcancel", function() { MigrationWizard.onWizardCancel(); });
|
||||
|
||||
document.getElementById("selectProfile").addEventListener("pageshow", function() { MigrationWizard.onSelectProfilePageShow(); });
|
||||
document.getElementById("importItems").addEventListener("pageshow", function() { MigrationWizard.onImportItemsPageShow(); });
|
||||
document.getElementById("migrating").addEventListener("pageshow", function() { MigrationWizard.onMigratingPageShow(); });
|
||||
document.getElementById("done").addEventListener("pageshow", function() { MigrationWizard.onDonePageShow(); });
|
||||
|
||||
document.getElementById("selectProfile").addEventListener("pagerewound", function() { MigrationWizard.onSelectProfilePageRewound(); });
|
||||
document.getElementById("importItems").addEventListener("pagerewound", function() { MigrationWizard.onImportItemsPageRewound(); });
|
||||
|
||||
document.getElementById("selectProfile").addEventListener("pageadvanced", function() { MigrationWizard.onSelectProfilePageAdvanced(); });
|
||||
document.getElementById("importItems").addEventListener("pageadvanced", function() { MigrationWizard.onImportItemsPageAdvanced(); });
|
||||
document.getElementById("importSource").addEventListener("pageadvanced", function(e) { MigrationWizard.onImportSourcePageAdvanced(e); });
|
||||
|
||||
this.onImportSourcePageShow();
|
||||
},
|
||||
|
||||
|
@ -145,7 +159,7 @@ var MigrationWizard = { /* exported MigrationWizard */
|
|||
}
|
||||
},
|
||||
|
||||
onImportSourcePageAdvanced() {
|
||||
onImportSourcePageAdvanced(event) {
|
||||
var newSource = document.getElementById("importSourceGroup").selectedItem.id;
|
||||
|
||||
if (newSource == "nothing") {
|
||||
|
@ -155,7 +169,7 @@ var MigrationWizard = { /* exported MigrationWizard */
|
|||
Services.telemetry.getHistogramById("FX_MIGRATION_SOURCE_BROWSER")
|
||||
.add(MigrationUtils.getSourceIdForTelemetry("nothing"));
|
||||
document.documentElement.cancel();
|
||||
return false;
|
||||
event.preventDefault();
|
||||
}
|
||||
|
||||
if (!this._migrator || (newSource != this._source)) {
|
||||
|
@ -184,7 +198,6 @@ var MigrationWizard = { /* exported MigrationWizard */
|
|||
else
|
||||
this._selectedProfile = null;
|
||||
}
|
||||
return undefined;
|
||||
},
|
||||
|
||||
// 2 - [Profile Selection]
|
||||
|
|
|
@ -15,15 +15,13 @@
|
|||
onunload="MigrationWizard.uninit()"
|
||||
style="width: 40em;"
|
||||
buttons="accept,cancel"
|
||||
branded="true"
|
||||
onwizardcancel="return MigrationWizard.onWizardCancel();">
|
||||
branded="true">
|
||||
|
||||
<script type="application/javascript" src="chrome://global/content/customElements.js"/>
|
||||
<script type="application/javascript" src="chrome://browser/content/migration/migration.js"/>
|
||||
|
||||
<wizardpage id="importSource" pageid="importSource" next="selectProfile"
|
||||
label="&importSource.title;"
|
||||
onpageadvanced="return MigrationWizard.onImportSourcePageAdvanced();">
|
||||
label="&importSource.title;">
|
||||
#ifdef XP_WIN
|
||||
<description id="importAll" control="importSourceGroup">&importFrom.label;</description>
|
||||
#else
|
||||
|
@ -60,10 +58,7 @@
|
|||
</wizardpage>
|
||||
|
||||
<wizardpage id="selectProfile" pageid="selectProfile" label="&selectProfile.title;"
|
||||
next="importItems"
|
||||
onpageshow="return MigrationWizard.onSelectProfilePageShow();"
|
||||
onpagerewound="return MigrationWizard.onSelectProfilePageRewound();"
|
||||
onpageadvanced="return MigrationWizard.onSelectProfilePageAdvanced();">
|
||||
next="importItems">
|
||||
<description control="profiles">&selectProfile.label;</description>
|
||||
|
||||
<radiogroup id="profiles" align="left"/>
|
||||
|
@ -71,9 +66,6 @@
|
|||
|
||||
<wizardpage id="importItems" pageid="importItems" label="&importItems.title;"
|
||||
next="migrating"
|
||||
onpageshow="return MigrationWizard.onImportItemsPageShow();"
|
||||
onpagerewound="return MigrationWizard.onImportItemsPageRewound();"
|
||||
onpageadvanced="return MigrationWizard.onImportItemsPageAdvanced();"
|
||||
oncommand="MigrationWizard.onImportItemCommand();">
|
||||
<description control="dataSources">&importItems.label;</description>
|
||||
|
||||
|
@ -81,19 +73,16 @@
|
|||
</wizardpage>
|
||||
|
||||
<wizardpage id="migrating" pageid="migrating" label="&migrating.title;"
|
||||
next="done"
|
||||
onpageshow="MigrationWizard.onMigratingPageShow();">
|
||||
next="done">
|
||||
<description control="migratingItems">&migrating.label;</description>
|
||||
|
||||
<vbox id="migratingItems" style="overflow: auto;" align="left" role="group"/>
|
||||
</wizardpage>
|
||||
|
||||
<wizardpage id="done" pageid="done" label="&done.title;"
|
||||
onpageshow="MigrationWizard.onDonePageShow();">
|
||||
<wizardpage id="done" pageid="done" label="&done.title;">
|
||||
<description control="doneItems">&done.label;</description>
|
||||
|
||||
<vbox id="doneItems" style="overflow: auto;" align="left" role="group"/>
|
||||
</wizardpage>
|
||||
|
||||
</wizard>
|
||||
|
||||
|
|
|
@ -1318,7 +1318,10 @@ var UITour = {
|
|||
urlbar.value = SEARCH_STRING;
|
||||
urlbar.select();
|
||||
if (quantumbar) {
|
||||
urlbar.startQuery();
|
||||
urlbar.startQuery({
|
||||
searchString: SEARCH_STRING,
|
||||
allowAutofill: false,
|
||||
});
|
||||
} else {
|
||||
urlbar.controller.startSearch(SEARCH_STRING);
|
||||
}
|
||||
|
|
|
@ -463,14 +463,12 @@ class UrlbarAbstraction {
|
|||
url: urls.length > 0 ? urls[0].textContent : null,
|
||||
typeIcon: typeIconStyle["background-image"],
|
||||
};
|
||||
let actionElement = element.getElementsByClassName("urlbarView-action")[0];
|
||||
let urlElement = element.getElementsByClassName("urlbarView-url")[0];
|
||||
details.element = {
|
||||
action: actionElement,
|
||||
action: element.getElementsByClassName("urlbarView-action")[0],
|
||||
row: element,
|
||||
separator: urlElement || actionElement,
|
||||
separator: element.getElementsByClassName("urlbarView-title-separator")[0],
|
||||
title: element.getElementsByClassName("urlbarView-title")[0],
|
||||
url: urlElement,
|
||||
url: element.getElementsByClassName("urlbarView-url")[0],
|
||||
};
|
||||
if (details.type == UrlbarUtils.RESULT_TYPE.SEARCH) {
|
||||
details.searchParams = {
|
||||
|
|
|
@ -1319,7 +1319,6 @@ menuitem.panel-subview-footer@menuStateActive@,
|
|||
-moz-box-pack: end;
|
||||
margin-inline-start: 10px;
|
||||
margin-inline-end: auto;
|
||||
color: var(--panel-disabled-color);
|
||||
}
|
||||
|
||||
#PanelUI-remotetabs-tabslist > toolbarbutton[itemtype="tab"],
|
||||
|
|
|
@ -47,6 +47,6 @@
|
|||
"patches": [
|
||||
"static-llvm-symbolizer.patch",
|
||||
"find_symbolizer_linux.patch",
|
||||
"rename_gcov_flush_.patch"
|
||||
"rename_gcov_flush.patch"
|
||||
]
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
"patches": [
|
||||
"static-llvm-symbolizer.patch",
|
||||
"find_symbolizer_linux.patch",
|
||||
"rename_gcov_flush_.patch",
|
||||
"rename_gcov_flush.patch",
|
||||
"android-mangling-error.patch"
|
||||
]
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
"ld": "/builds/worker/workspace/build/src/clang/bin/clang",
|
||||
"patches": [
|
||||
"static-llvm-symbolizer.patch",
|
||||
"rename_gcov_flush.patch",
|
||||
"compiler-rt-cross-compile.patch",
|
||||
"compiler-rt-no-codesign.patch"
|
||||
]
|
||||
|
|
|
@ -25,3 +25,16 @@ index 9af64ed332c..bcebe303ff4 100644
|
|||
Builder.CreateCall(GCOVFlush);
|
||||
I->getParent()->splitBasicBlock(I);
|
||||
}
|
||||
diff --git a/clang/lib/Driver/ToolChains/Darwin.cpp b/clang/lib/Driver/ToolChains/Darwin.cpp
|
||||
index e113f9a679..b3a07b18c0 100644
|
||||
--- a/clang/lib/Driver/ToolChains/Darwin.cpp
|
||||
+++ b/clang/lib/Driver/ToolChains/Darwin.cpp
|
||||
@@ -1058,7 +1058,7 @@ void Darwin::addProfileRTLibs(const ArgList &Args,
|
||||
// runtime's functionality.
|
||||
if (hasExportSymbolDirective(Args)) {
|
||||
if (needsGCovInstrumentation(Args)) {
|
||||
- addExportedSymbol(CmdArgs, "___gcov_flush");
|
||||
+ addExportedSymbol(CmdArgs, "___custom_llvm_gcov_flush");
|
||||
addExportedSymbol(CmdArgs, "_flush_fn_list");
|
||||
addExportedSymbol(CmdArgs, "_writeout_fn_list");
|
||||
} else {
|
|
@ -24,6 +24,7 @@ const { remoteClientManager } =
|
|||
|
||||
const {
|
||||
CONNECT_RUNTIME_FAILURE,
|
||||
CONNECT_RUNTIME_NOT_RESPONDING,
|
||||
CONNECT_RUNTIME_START,
|
||||
CONNECT_RUNTIME_SUCCESS,
|
||||
DEBUG_TARGET_PANE,
|
||||
|
@ -52,6 +53,8 @@ const {
|
|||
WATCH_RUNTIME_SUCCESS,
|
||||
} = require("../constants");
|
||||
|
||||
const CONNECTION_TIMING_OUT_DELAY = 3000;
|
||||
|
||||
async function getRuntimeIcon(channel) {
|
||||
return (channel === "release" || channel === "beta" || channel === "aurora")
|
||||
? `chrome://devtools/skin/images/aboutdebugging-firefox-${ channel }.svg`
|
||||
|
@ -69,7 +72,14 @@ function onMultiE10sUpdated() {
|
|||
|
||||
function connectRuntime(id) {
|
||||
return async (dispatch, getState) => {
|
||||
dispatch({ type: CONNECT_RUNTIME_START });
|
||||
dispatch({ type: CONNECT_RUNTIME_START, id });
|
||||
const connectionNotRespondingTimer = setTimeout(() => {
|
||||
// If connecting to the runtime takes time over CONNECTION_TIMING_OUT_DELAY,
|
||||
// we assume the connection prompt is showing on the runtime, show a dialog
|
||||
// to let user know that.
|
||||
dispatch({ type: CONNECT_RUNTIME_NOT_RESPONDING, id });
|
||||
}, CONNECTION_TIMING_OUT_DELAY);
|
||||
|
||||
try {
|
||||
const runtime = findRuntimeById(id, getState().runtimes);
|
||||
const clientWrapper = await createClientForRuntime(runtime);
|
||||
|
@ -135,7 +145,9 @@ function connectRuntime(id) {
|
|||
},
|
||||
});
|
||||
} catch (e) {
|
||||
dispatch({ type: CONNECT_RUNTIME_FAILURE, error: e });
|
||||
dispatch({ type: CONNECT_RUNTIME_FAILURE, id, error: e });
|
||||
} finally {
|
||||
clearTimeout(connectionNotRespondingTimer);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -144,6 +156,9 @@ function createThisFirefoxRuntime() {
|
|||
return (dispatch, getState) => {
|
||||
const thisFirefoxRuntime = {
|
||||
id: RUNTIMES.THIS_FIREFOX,
|
||||
isConnecting: false,
|
||||
isConnectionFailed: false,
|
||||
isConnectionNotResponding: false,
|
||||
isUnknown: false,
|
||||
name: l10n.getString("about-debugging-this-firefox-runtime-name"),
|
||||
type: RUNTIMES.THIS_FIREFOX,
|
||||
|
@ -302,6 +317,9 @@ function updateNetworkRuntimes(locations) {
|
|||
extra: {
|
||||
connectionParameters: { host, port: parseInt(port, 10) },
|
||||
},
|
||||
isConnecting: false,
|
||||
isConnectionFailed: false,
|
||||
isConnectionNotResponding: false,
|
||||
isUnknown: false,
|
||||
name: location,
|
||||
type: RUNTIMES.NETWORK,
|
||||
|
@ -322,6 +340,9 @@ function updateUSBRuntimes(adbRuntimes) {
|
|||
connectionParameters,
|
||||
deviceName: adbRuntime.deviceName,
|
||||
},
|
||||
isConnecting: false,
|
||||
isConnectionFailed: false,
|
||||
isConnectionNotResponding: false,
|
||||
isUnknown: adbRuntime.isUnknown(),
|
||||
name: adbRuntime.shortName,
|
||||
type: RUNTIMES.USB,
|
||||
|
@ -363,12 +384,23 @@ function updateRemoteRuntimes(runtimes, type) {
|
|||
await dispatch(Actions.selectPage(PAGE_TYPES.RUNTIME, RUNTIMES.THIS_FIREFOX));
|
||||
}
|
||||
|
||||
// Retrieve runtimeDetails from existing runtimes.
|
||||
// For existing runtimes, transfer all properties that are not available in the
|
||||
// runtime objects passed to this method:
|
||||
// - runtimeDetails (set by about:debugging after a successful connection)
|
||||
// - isConnecting (set by about:debugging during the connection)
|
||||
// - isConnectionFailed (set by about:debugging if connection was failed)
|
||||
// - isConnectionNotResponding
|
||||
// (set by about:debugging if connection is taking too much time)
|
||||
runtimes.forEach(runtime => {
|
||||
const existingRuntime = findRuntimeById(runtime.id, getState().runtimes);
|
||||
const isConnectionValid = existingRuntime && existingRuntime.runtimeDetails &&
|
||||
!existingRuntime.runtimeDetails.clientWrapper.isClosed();
|
||||
runtime.runtimeDetails = isConnectionValid ? existingRuntime.runtimeDetails : null;
|
||||
runtime.isConnecting = existingRuntime ? existingRuntime.isConnecting : false;
|
||||
runtime.isConnectionFailed =
|
||||
existingRuntime ? existingRuntime.isConnectionFailed : false;
|
||||
runtime.isConnectionNotResponding =
|
||||
existingRuntime ? existingRuntime.isConnectionNotResponding : false;
|
||||
});
|
||||
|
||||
const existingRuntimes = getAllRuntimes(getState().runtimes);
|
||||
|
|
|
@ -163,6 +163,11 @@ p, h1 {
|
|||
color: currentColor;
|
||||
}
|
||||
|
||||
/* Text needs to wrap anywhere */
|
||||
.word-wrap-anywhere {
|
||||
word-wrap: anywhere;
|
||||
}
|
||||
|
||||
/*
|
||||
* Typography
|
||||
*/
|
||||
|
|
|
@ -113,6 +113,9 @@ class Sidebar extends PureComponent {
|
|||
icon,
|
||||
key: keyId,
|
||||
isConnected: runtimeHasDetails,
|
||||
isConnecting: runtime.isConnecting,
|
||||
isConnectionFailed: runtime.isConnectionFailed,
|
||||
isConnectionNotResponding: runtime.isConnectionNotResponding,
|
||||
isSelected,
|
||||
isUnknown: runtime.isUnknown,
|
||||
name,
|
||||
|
|
|
@ -11,8 +11,10 @@ const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
|
|||
const FluentReact = require("devtools/client/shared/vendor/fluent-react");
|
||||
const Localized = createFactory(FluentReact.Localized);
|
||||
|
||||
const Message = createFactory(require("../shared/Message"));
|
||||
const SidebarItem = createFactory(require("./SidebarItem"));
|
||||
const Actions = require("../../actions/index");
|
||||
const { MESSAGE_LEVEL } = require("../../constants");
|
||||
|
||||
/**
|
||||
* This component displays a runtime item of the Sidebar component.
|
||||
|
@ -26,6 +28,9 @@ class SidebarRuntimeItem extends PureComponent {
|
|||
getString: PropTypes.func.isRequired,
|
||||
icon: PropTypes.string.isRequired,
|
||||
isConnected: PropTypes.bool.isRequired,
|
||||
isConnecting: PropTypes.bool.isRequired,
|
||||
isConnectionFailed: PropTypes.bool.isRequired,
|
||||
isConnectionNotResponding: PropTypes.bool.isRequired,
|
||||
isSelected: PropTypes.bool.isRequired,
|
||||
isUnknown: PropTypes.bool.isRequired,
|
||||
name: PropTypes.string.isRequired,
|
||||
|
@ -34,19 +39,74 @@ class SidebarRuntimeItem extends PureComponent {
|
|||
}
|
||||
|
||||
renderConnectButton() {
|
||||
const { isConnecting } = this.props;
|
||||
const localizationId = isConnecting
|
||||
? "about-debugging-sidebar-item-connect-button-connecting"
|
||||
: "about-debugging-sidebar-item-connect-button";
|
||||
return Localized(
|
||||
{
|
||||
id: "about-debugging-sidebar-item-connect-button",
|
||||
id: localizationId,
|
||||
},
|
||||
dom.button(
|
||||
{
|
||||
className: "default-button default-button--micro js-connect-button",
|
||||
disabled: isConnecting,
|
||||
onClick: () => {
|
||||
const { dispatch, runtimeId } = this.props;
|
||||
dispatch(Actions.connectRuntime(runtimeId));
|
||||
},
|
||||
},
|
||||
"Connect"
|
||||
localizationId
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
renderConnectionError() {
|
||||
const { isConnectionFailed } = this.props;
|
||||
|
||||
if (!isConnectionFailed) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const localizationId =
|
||||
"about-debugging-sidebar-item-connect-button-connection-failed";
|
||||
|
||||
return Message(
|
||||
{
|
||||
level: MESSAGE_LEVEL.ERROR,
|
||||
key: "connection-error",
|
||||
className: "qa-connection-error",
|
||||
},
|
||||
Localized(
|
||||
{
|
||||
id: localizationId,
|
||||
},
|
||||
dom.p({ className: "word-wrap-anywhere" }, localizationId)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
renderConnectionNotResponding() {
|
||||
const { isConnectionNotResponding } = this.props;
|
||||
|
||||
if (!isConnectionNotResponding) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const localizationId =
|
||||
"about-debugging-sidebar-item-connect-button-connection-not-responding";
|
||||
|
||||
return Message(
|
||||
{
|
||||
level: MESSAGE_LEVEL.WARNING,
|
||||
key: "connection-not-responding",
|
||||
className: "qa-connection-not-responding",
|
||||
},
|
||||
Localized(
|
||||
{
|
||||
id: localizationId,
|
||||
},
|
||||
dom.p({ className: "word-wrap-anywhere" }, localizationId)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
@ -115,28 +175,33 @@ class SidebarRuntimeItem extends PureComponent {
|
|||
getString("aboutdebugging-sidebar-runtime-connection-status-connected") :
|
||||
getString("aboutdebugging-sidebar-runtime-connection-status-disconnected");
|
||||
|
||||
return SidebarItem(
|
||||
{
|
||||
className: "sidebar-item--tall",
|
||||
isSelected,
|
||||
to: isConnected ? `/runtime/${encodeURIComponent(runtimeId)}` : null,
|
||||
},
|
||||
dom.section(
|
||||
return [
|
||||
SidebarItem(
|
||||
{
|
||||
className: "sidebar-runtime-item__container",
|
||||
className: "sidebar-item--tall",
|
||||
key: "sidebar-item",
|
||||
isSelected,
|
||||
to: isConnected ? `/runtime/${encodeURIComponent(runtimeId)}` : null,
|
||||
},
|
||||
dom.img(
|
||||
dom.section(
|
||||
{
|
||||
className: "sidebar-runtime-item__icon ",
|
||||
src: icon,
|
||||
alt: connectionStatus,
|
||||
title: connectionStatus,
|
||||
}
|
||||
className: "sidebar-runtime-item__container",
|
||||
},
|
||||
dom.img(
|
||||
{
|
||||
className: "sidebar-runtime-item__icon ",
|
||||
src: icon,
|
||||
alt: connectionStatus,
|
||||
title: connectionStatus,
|
||||
}
|
||||
),
|
||||
this.renderName(),
|
||||
!isUnknown && !isConnected ? this.renderConnectButton() : null
|
||||
),
|
||||
this.renderName(),
|
||||
!isUnknown && !isConnected ? this.renderConnectButton() : null
|
||||
)
|
||||
);
|
||||
),
|
||||
this.renderConnectionError(),
|
||||
this.renderConnectionNotResponding(),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@ const actionTypes = {
|
|||
ADB_ADDON_UNINSTALL_FAILURE: "ADB_ADDON_UNINSTALL_FAILURE",
|
||||
ADB_ADDON_STATUS_UPDATED: "ADB_ADDON_STATUS_UPDATED",
|
||||
CONNECT_RUNTIME_FAILURE: "CONNECT_RUNTIME_FAILURE",
|
||||
CONNECT_RUNTIME_NOT_RESPONDING: "CONNECT_RUNTIME_NOT_RESPONDING",
|
||||
CONNECT_RUNTIME_START: "CONNECT_RUNTIME_START",
|
||||
CONNECT_RUNTIME_SUCCESS: "CONNECT_RUNTIME_SUCCESS",
|
||||
DEBUG_TARGET_COLLAPSIBILITY_UPDATED: "DEBUG_TARGET_COLLAPSIBILITY_UPDATED",
|
||||
|
|
|
@ -5,6 +5,9 @@
|
|||
"use strict";
|
||||
|
||||
const {
|
||||
CONNECT_RUNTIME_FAILURE,
|
||||
CONNECT_RUNTIME_NOT_RESPONDING,
|
||||
CONNECT_RUNTIME_START,
|
||||
CONNECT_RUNTIME_SUCCESS,
|
||||
DISCONNECT_RUNTIME_SUCCESS,
|
||||
RUNTIMES,
|
||||
|
@ -72,10 +75,41 @@ function _updateRuntimeById(runtimeId, updatedRuntime, state) {
|
|||
|
||||
function runtimesReducer(state = RuntimesState(), action) {
|
||||
switch (action.type) {
|
||||
case CONNECT_RUNTIME_START: {
|
||||
const { id } = action;
|
||||
const updatedState = {
|
||||
isConnecting: true,
|
||||
isConnectionFailed: false,
|
||||
isConnectionNotResponding: false,
|
||||
};
|
||||
return _updateRuntimeById(id, updatedState, state);
|
||||
}
|
||||
|
||||
case CONNECT_RUNTIME_NOT_RESPONDING: {
|
||||
const { id } = action;
|
||||
return _updateRuntimeById(id, { isConnectionNotResponding: true }, state);
|
||||
}
|
||||
|
||||
case CONNECT_RUNTIME_SUCCESS: {
|
||||
const { id, runtimeDetails, type } = action.runtime;
|
||||
remoteClientManager.setClient(id, type, runtimeDetails.clientWrapper.client);
|
||||
return _updateRuntimeById(id, { runtimeDetails }, state);
|
||||
const updatedState = {
|
||||
isConnecting: false,
|
||||
isConnectionFailed: false,
|
||||
isConnectionNotResponding: false,
|
||||
runtimeDetails,
|
||||
};
|
||||
return _updateRuntimeById(id, updatedState, state);
|
||||
}
|
||||
|
||||
case CONNECT_RUNTIME_FAILURE: {
|
||||
const { id } = action;
|
||||
const updatedState = {
|
||||
isConnecting: false,
|
||||
isConnectionFailed: true,
|
||||
isConnectionNotResponding: false,
|
||||
};
|
||||
return _updateRuntimeById(id, updatedState, state);
|
||||
}
|
||||
|
||||
case DISCONNECT_RUNTIME_SUCCESS: {
|
||||
|
|
|
@ -115,6 +115,17 @@ const runtime = {
|
|||
// unavailable on this-firefox runtime
|
||||
extra: PropTypes.shape(runtimeExtra),
|
||||
|
||||
// this flag will be true when start to connect to the runtime, will be false after
|
||||
// connected or has failures.
|
||||
isConnecting: PropTypes.bool.isRequired,
|
||||
|
||||
// this flag will be true when the connection failed.
|
||||
isConnectionFailed: PropTypes.bool.isRequired,
|
||||
|
||||
// will be true if connecting to runtime is taking time, will be false after connecting
|
||||
// or failing.
|
||||
isConnectionNotResponding: PropTypes.bool.isRequired,
|
||||
|
||||
// unknown runtimes are placeholders for devices where the runtime has not been started
|
||||
// yet. For instance an ADB device connected without a compatible runtime running.
|
||||
isUnknown: PropTypes.bool.isRequired,
|
||||
|
|
|
@ -86,6 +86,7 @@ skip-if = debug || asan || serviceworker_e10s # Frequent intermittent failures,
|
|||
[browser_aboutdebugging_serviceworker_timeout.js]
|
||||
skip-if = debug || asan # Frequent intermittent failures, Bug 1522800
|
||||
[browser_aboutdebugging_serviceworker_unregister.js]
|
||||
[browser_aboutdebugging_sidebar_connection_state.js]
|
||||
[browser_aboutdebugging_sidebar_network_runtimes.js]
|
||||
[browser_aboutdebugging_sidebar_usb_runtime.js]
|
||||
[browser_aboutdebugging_sidebar_usb_runtime_connect.js]
|
||||
|
|
|
@ -0,0 +1,78 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
const RUNTIME_ID = "test-runtime-id";
|
||||
const RUNTIME_NAME = "test runtime name";
|
||||
const RUNTIME_DEVICE_NAME = "test device name";
|
||||
const RUNTIME_SHORT_NAME = "test short name";
|
||||
|
||||
// Test following connection state tests.
|
||||
// * Connect button label and state will change during connecting.
|
||||
// * Show error message if connection failed.
|
||||
// * Show warninng if connection has been taken time.
|
||||
add_task(async function() {
|
||||
const mocks = new Mocks();
|
||||
|
||||
const { document, tab } = await openAboutDebugging();
|
||||
|
||||
mocks.createUSBRuntime(RUNTIME_ID, {
|
||||
name: RUNTIME_NAME,
|
||||
deviceName: RUNTIME_DEVICE_NAME,
|
||||
shortName: RUNTIME_SHORT_NAME,
|
||||
});
|
||||
mocks.emitUSBUpdate();
|
||||
|
||||
info("Wait until the USB sidebar item appears");
|
||||
await waitUntil(() => findSidebarItemByText(RUNTIME_DEVICE_NAME, document));
|
||||
const usbRuntimeSidebarItem = findSidebarItemByText(RUNTIME_DEVICE_NAME, document);
|
||||
const connectButton = usbRuntimeSidebarItem.querySelector(".js-connect-button");
|
||||
|
||||
info("Simulate to happen connection error");
|
||||
mocks.runtimeClientFactoryMock.createClientForRuntime = async (runtime) => {
|
||||
throw new Error("Dummy connection error");
|
||||
};
|
||||
|
||||
info("Check whether the error message displayed after clicking connect button");
|
||||
connectButton.click();
|
||||
await waitUntil(() => document.querySelector(".qa-connection-error"));
|
||||
ok(true, "Error message displays when connection failed");
|
||||
|
||||
info("Simulate to wait for the connection prompt on remote runtime");
|
||||
let resumeConnection;
|
||||
const resumeConnectionPromise = new Promise(r => {
|
||||
resumeConnection = r;
|
||||
});
|
||||
mocks.runtimeClientFactoryMock.createClientForRuntime = async (runtime) => {
|
||||
await resumeConnectionPromise;
|
||||
return mocks._clients[runtime.type][runtime.id];
|
||||
};
|
||||
|
||||
info("Click on the connect button and wait until it disappears");
|
||||
connectButton.click();
|
||||
info("Check whether a warning of connection not responding displays after 3sec");
|
||||
await waitUntil(() => document.querySelector(".qa-connection-not-responding"));
|
||||
ok(document.querySelector(".qa-connection-not-responding"),
|
||||
"A warning of connection not responding displays");
|
||||
ok(connectButton.disabled, "State of the connect button displays");
|
||||
ok(connectButton.textContent.startsWith("Connecting"),
|
||||
"Label of the connect button changes");
|
||||
ok(!document.querySelector(".qa-connection-error"), "Error message disappears");
|
||||
|
||||
info("Unblock the connection and check the message and connect button disappear");
|
||||
resumeConnection();
|
||||
await waitUntil(() => !usbRuntimeSidebarItem.querySelector(".js-connect-button"));
|
||||
ok(!document.querySelector(".qa-connection-error"), "Error disappears");
|
||||
ok(!document.querySelector(".qa-connection-not-responding"), "Warning disappears");
|
||||
|
||||
info("Remove a USB runtime");
|
||||
mocks.removeUSBRuntime(RUNTIME_ID);
|
||||
mocks.emitUSBUpdate();
|
||||
|
||||
info("Wait until the USB sidebar item disappears");
|
||||
await waitUntil(() => !findSidebarItemByText(RUNTIME_DEVICE_NAME, document) &&
|
||||
!findSidebarItemByText(RUNTIME_SHORT_NAME, document));
|
||||
|
||||
await removeTab(tab);
|
||||
});
|
|
@ -93,7 +93,8 @@ function getElements(grip, mode) {
|
|||
attributes,
|
||||
nodeName,
|
||||
isAfterPseudoElement,
|
||||
isBeforePseudoElement
|
||||
isBeforePseudoElement,
|
||||
isMarkerPseudoElement
|
||||
} = grip.preview;
|
||||
const nodeNameElement = span(
|
||||
{
|
||||
|
@ -102,13 +103,16 @@ function getElements(grip, mode) {
|
|||
nodeName
|
||||
);
|
||||
|
||||
if (isAfterPseudoElement || isBeforePseudoElement) {
|
||||
return [
|
||||
span(
|
||||
{ className: "attrName" },
|
||||
`::${isAfterPseudoElement ? "after" : "before"}`
|
||||
)
|
||||
];
|
||||
let pseudoNodeName;
|
||||
if (isAfterPseudoElement) {
|
||||
pseudoNodeName = "after";
|
||||
} else if (isBeforePseudoElement) {
|
||||
pseudoNodeName = "before";
|
||||
} else if (isMarkerPseudoElement) {
|
||||
pseudoNodeName = "marker";
|
||||
}
|
||||
if (pseudoNodeName) {
|
||||
return [span({ className: "attrName" }, `::${pseudoNodeName}`)];
|
||||
}
|
||||
|
||||
if (mode === MODE.TINY) {
|
||||
|
|
|
@ -248,6 +248,19 @@ stubs.set("NodeWithLongStringAttribute", {
|
|||
}
|
||||
});
|
||||
|
||||
stubs.set("MarkerPseudoElement", {
|
||||
type: "object",
|
||||
actor: "server1.conn1.child1/obj26",
|
||||
preview: {
|
||||
kind: "DOMNode",
|
||||
nodeType: 1,
|
||||
nodeName: "_moz_generated_content_marker",
|
||||
attributes: {},
|
||||
attributesLength: 0,
|
||||
isMarkerPseudoElement: true
|
||||
}
|
||||
});
|
||||
|
||||
stubs.set("BeforePseudoElement", {
|
||||
type: "object",
|
||||
actor: "server1.conn1.child1/obj27",
|
||||
|
|
|
@ -465,6 +465,35 @@ describe("ElementNode - Element attribute cropping", () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe("ElementNode - : Marker pseudo element", () => {
|
||||
const stub = stubs.get("MarkerPseudoElement");
|
||||
|
||||
it("selects ElementNode Rep", () => {
|
||||
expect(getRep(stub)).toBe(ElementNode.rep);
|
||||
});
|
||||
|
||||
it("renders with expected text content", () => {
|
||||
const renderedComponent = shallow(
|
||||
ElementNode.rep({
|
||||
object: stub
|
||||
})
|
||||
);
|
||||
|
||||
expect(renderedComponent.text()).toEqual("::marker");
|
||||
});
|
||||
|
||||
it("renders with expected text content in tiny mode", () => {
|
||||
const renderedComponent = shallow(
|
||||
ElementNode.rep({
|
||||
object: stub,
|
||||
mode: MODE.TINY
|
||||
})
|
||||
);
|
||||
|
||||
expect(renderedComponent.text()).toEqual("::marker");
|
||||
});
|
||||
});
|
||||
|
||||
describe("ElementNode - : Before pseudo element", () => {
|
||||
const stub = stubs.get("BeforePseudoElement");
|
||||
|
||||
|
|
|
@ -101,7 +101,7 @@
|
|||
|
||||
.expression-container:hover .expression-container__close-btn,
|
||||
.expression-container__close-btn:focus-within {
|
||||
top: calc(50% - 8px);
|
||||
top: 0;
|
||||
}
|
||||
|
||||
[dir="ltr"] .expression-container__close-btn {
|
||||
|
|
|
@ -428,8 +428,12 @@ HTMLBreadcrumbs.prototype = {
|
|||
*/
|
||||
prettyPrintNodeAsText: function(node) {
|
||||
let text = node.isShadowRoot ? SHADOW_ROOT_TAGNAME : node.displayName;
|
||||
if (node.isPseudoElement) {
|
||||
text = node.isBeforePseudoElement ? "::before" : "::after";
|
||||
if (node.isMarkerPseudoElement) {
|
||||
text = "::marker";
|
||||
} else if (node.isBeforePseudoElement) {
|
||||
text = "::before";
|
||||
} else if (node.isAfterPseudoElement) {
|
||||
text = "::after";
|
||||
}
|
||||
|
||||
if (node.id) {
|
||||
|
@ -472,8 +476,12 @@ HTMLBreadcrumbs.prototype = {
|
|||
pseudosLabel.className = "breadcrumbs-widget-item-pseudo-classes plain";
|
||||
|
||||
let tagText = node.isShadowRoot ? SHADOW_ROOT_TAGNAME : node.displayName;
|
||||
if (node.isPseudoElement) {
|
||||
tagText = node.isBeforePseudoElement ? "::before" : "::after";
|
||||
if (node.isMarkerPseudoElement) {
|
||||
tagText = "::marker";
|
||||
} else if (node.isBeforePseudoElement) {
|
||||
tagText = "::before";
|
||||
} else if (node.isAfterPseudoElement) {
|
||||
tagText = "::after";
|
||||
}
|
||||
let idText = node.id ? ("#" + node.id) : "";
|
||||
let classesText = "";
|
||||
|
|
|
@ -2180,12 +2180,16 @@ MarkupView.prototype = {
|
|||
nextSibling = target.parentNode.container.node;
|
||||
}
|
||||
|
||||
if (nextSibling && nextSibling.isBeforePseudoElement) {
|
||||
nextSibling = target.parentNode.parentNode.children[1].container.node;
|
||||
}
|
||||
if (nextSibling && nextSibling.isAfterPseudoElement) {
|
||||
parent = target.parentNode.container.node.parentNode();
|
||||
nextSibling = null;
|
||||
if (nextSibling) {
|
||||
while (
|
||||
nextSibling.isMarkerPseudoElement || nextSibling.isBeforePseudoElement
|
||||
) {
|
||||
nextSibling = this.getContainer(nextSibling).elt.nextSibling.container.node;
|
||||
}
|
||||
if (nextSibling.isAfterPseudoElement) {
|
||||
parent = target.parentNode.container.node.parentNode();
|
||||
nextSibling = null;
|
||||
}
|
||||
}
|
||||
|
||||
if (parent.nodeType !== nodeConstants.ELEMENT_NODE) {
|
||||
|
|
|
@ -115,6 +115,7 @@ skip-if = (os == 'linux' && bits == 32 && debug) || (os == "win" && processor ==
|
|||
[browser_markup_display_node_02.js]
|
||||
[browser_markup_dragdrop_autoscroll_01.js]
|
||||
[browser_markup_dragdrop_autoscroll_02.js]
|
||||
[browser_markup_dragdrop_before_marker_pseudo.js]
|
||||
[browser_markup_dragdrop_distance.js]
|
||||
[browser_markup_dragdrop_draggable.js]
|
||||
[browser_markup_dragdrop_dragRootNode.js]
|
||||
|
@ -201,6 +202,7 @@ subsuite = clipboard
|
|||
[browser_markup_shadowdom_delete.js]
|
||||
[browser_markup_shadowdom_dynamic.js]
|
||||
[browser_markup_shadowdom_hover.js]
|
||||
[browser_markup_shadowdom_marker_and_before_pseudos.js]
|
||||
[browser_markup_shadowdom_maxchildren.js]
|
||||
[browser_markup_shadowdom_mutations_shadow.js]
|
||||
[browser_markup_shadowdom_navigation.js]
|
||||
|
|
|
@ -14,9 +14,9 @@ add_task(async function() {
|
|||
data:text/html;charset=utf-8,
|
||||
<h1>foo</h1>
|
||||
<span>bar</span>
|
||||
<ul>
|
||||
<li></li>
|
||||
</ul>`);
|
||||
<dl>
|
||||
<dt></dt>
|
||||
</dl>`);
|
||||
const markup = inspector.markup;
|
||||
const doc = markup.doc;
|
||||
const win = doc.defaultView;
|
||||
|
@ -25,7 +25,7 @@ add_task(async function() {
|
|||
const bodyContainer = await getContainerForSelector("body", inspector);
|
||||
const spanContainer = await getContainerForSelector("span", inspector);
|
||||
const headerContainer = await getContainerForSelector("h1", inspector);
|
||||
const listContainer = await getContainerForSelector("ul", inspector);
|
||||
const listContainer = await getContainerForSelector("dl", inspector);
|
||||
|
||||
// Focus on the tree element.
|
||||
rootElt.focus();
|
||||
|
@ -71,7 +71,7 @@ add_task(async function() {
|
|||
"Closed tree item should have aria-expanded unset");
|
||||
|
||||
info("Selecting and expanding list container");
|
||||
await selectNode("ul", inspector);
|
||||
await selectNode("dl", inspector);
|
||||
EventUtils.synthesizeKey("VK_RIGHT", {}, win);
|
||||
await waitForMultipleChildrenUpdates(inspector);
|
||||
|
||||
|
@ -80,7 +80,7 @@ add_task(async function() {
|
|||
"Active descendant should not be set to list container tagLine");
|
||||
is(listContainer.tagLine.getAttribute("aria-expanded"), "true",
|
||||
"Open tree item should have aria-expanded set");
|
||||
const listItemContainer = await getContainerForSelector("li", inspector);
|
||||
const listItemContainer = await getContainerForSelector("dt", inspector);
|
||||
is(listItemContainer.tagLine.getAttribute("aria-level"),
|
||||
TOP_CONTAINER_LEVEL + 1,
|
||||
"Grand child container tagLine should have nested level up to date");
|
||||
|
|
|
@ -0,0 +1,62 @@
|
|||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
// Test drag and dropping a node before a ::marker pseudo.
|
||||
|
||||
const TEST_URL = URL_ROOT + "doc_markup_dragdrop.html";
|
||||
|
||||
add_task(async function() {
|
||||
const {inspector} = await openInspectorForURL(TEST_URL);
|
||||
|
||||
info("Expand #list node");
|
||||
const parentFront = await getNodeFront("#list", inspector);
|
||||
await inspector.markup.expandNode(parentFront.parentNode());
|
||||
await inspector.markup.expandNode(parentFront);
|
||||
await waitForMultipleChildrenUpdates(inspector);
|
||||
|
||||
info("Scroll #list into view");
|
||||
const parentContainer = await getContainerForNodeFront(parentFront, inspector);
|
||||
parentContainer.elt.scrollIntoView(true);
|
||||
|
||||
info("Test placing an element before a ::marker psuedo");
|
||||
await moveElementBeforeMarker("#last-list-child", parentFront, inspector);
|
||||
const childNodes = await getChildrenOf(parentFront, inspector);
|
||||
is(childNodes[0], "_moz_generated_content_marker",
|
||||
"::marker is still the first child of #list");
|
||||
is(childNodes[1], "last-list-child",
|
||||
"#last-list-child is now the second child of #list");
|
||||
is(childNodes[2], "first-list-child",
|
||||
"#first-list-child is now the last child of #list");
|
||||
});
|
||||
|
||||
async function moveElementBeforeMarker(selector, parentFront, inspector) {
|
||||
info(`Placing ${selector} before its parent's ::marker`);
|
||||
|
||||
const container = await getContainerForSelector(selector, inspector);
|
||||
const parentContainer = await getContainerForNodeFront(parentFront, inspector);
|
||||
const offsetY = (parentContainer.tagLine.offsetTop +
|
||||
parentContainer.tagLine.offsetHeight) - container.tagLine.offsetTop;
|
||||
|
||||
const onMutated = inspector.once("markupmutation");
|
||||
const uiUpdate = inspector.once("inspector-updated");
|
||||
|
||||
await simulateNodeDragAndDrop(inspector, selector, 0, offsetY);
|
||||
|
||||
const mutations = await onMutated;
|
||||
await uiUpdate;
|
||||
|
||||
is(mutations.length, 2, "2 mutations were received");
|
||||
}
|
||||
|
||||
async function getChildrenOf(parentFront, {walker}) {
|
||||
const {nodes} = await walker.children(parentFront);
|
||||
return nodes.map(node => {
|
||||
if (node.isMarkerPseudoElement) {
|
||||
return node.displayName;
|
||||
}
|
||||
return node.id;
|
||||
});
|
||||
}
|
|
@ -0,0 +1,112 @@
|
|||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
requestLongerTimeout(1);
|
||||
|
||||
// Test a few static pages using webcomponents with ::marker and ::before
|
||||
// pseudos and check that they are displayed as expected in the markup view.
|
||||
|
||||
const TEST_DATA = [
|
||||
{
|
||||
// Test that ::before on an empty shadow host is displayed when the host
|
||||
// has a ::marker.
|
||||
title: "::before after ::marker, empty node",
|
||||
url: `data:text/html;charset=utf-8,
|
||||
<style>
|
||||
test-component { display: list-item; }
|
||||
test-component::before { content: "before-host" }
|
||||
</style>
|
||||
|
||||
<test-component></test-component>
|
||||
|
||||
<script>
|
||||
'use strict';
|
||||
customElements.define('test-component', class extends HTMLElement {
|
||||
constructor() {
|
||||
super();
|
||||
let shadowRoot = this.attachShadow({mode: "#MODE#"});
|
||||
}
|
||||
});
|
||||
</script>`,
|
||||
tree: `
|
||||
test-component
|
||||
#shadow-root
|
||||
::marker
|
||||
::before`,
|
||||
|
||||
}, {
|
||||
// Test ::before on a shadow host with content is displayed when the host
|
||||
// has a ::marker.
|
||||
title: "::before after ::marker, non-empty node",
|
||||
url: `data:text/html;charset=utf-8,
|
||||
<style>
|
||||
test-component { display: list-item }
|
||||
test-component::before { content: "before-host" }
|
||||
</style>
|
||||
|
||||
<test-component>
|
||||
<div class="light-dom"></div>
|
||||
</test-component>
|
||||
|
||||
<script>
|
||||
"use strict";
|
||||
customElements.define("test-component", class extends HTMLElement {
|
||||
constructor() {
|
||||
super();
|
||||
let shadowRoot = this.attachShadow({mode: "#MODE#"});
|
||||
shadowRoot.innerHTML = "<slot>default content</slot>";
|
||||
}
|
||||
});
|
||||
</script>`,
|
||||
tree: `
|
||||
test-component
|
||||
#shadow-root
|
||||
slot
|
||||
div!slotted
|
||||
::marker
|
||||
::before
|
||||
class="light-dom"`,
|
||||
}, {
|
||||
// Test just ::marker on a shadow host
|
||||
title: "just ::marker, no ::before",
|
||||
url: `data:text/html;charset=utf-8,
|
||||
<style>
|
||||
test-component { display: list-item }
|
||||
</style>
|
||||
|
||||
<test-component></test-component>
|
||||
|
||||
<script>
|
||||
"use strict";
|
||||
customElements.define("test-component", class extends HTMLElement {
|
||||
constructor() {
|
||||
super();
|
||||
let shadowRoot = this.attachShadow({mode: "#MODE#"});
|
||||
}
|
||||
});
|
||||
</script>`,
|
||||
tree: `
|
||||
test-component
|
||||
#shadow-root
|
||||
::marker`,
|
||||
},
|
||||
];
|
||||
|
||||
for (const {url, tree, title} of TEST_DATA) {
|
||||
// Test each configuration in both open and closed modes
|
||||
add_task(async function() {
|
||||
info(`Testing: [${title}] in OPEN mode`);
|
||||
const {inspector, tab} = await openInspectorForURL(url.replace(/#MODE#/g, "open"));
|
||||
await assertMarkupViewAsTree(tree, "test-component", inspector);
|
||||
await removeTab(tab);
|
||||
});
|
||||
add_task(async function() {
|
||||
info(`Testing: [${title}] in CLOSED mode`);
|
||||
const {inspector, tab} = await openInspectorForURL(url.replace(/#MODE#/g, "closed"));
|
||||
await assertMarkupViewAsTree(tree, "test-component", inspector);
|
||||
await removeTab(tab);
|
||||
});
|
||||
}
|
|
@ -25,6 +25,12 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=858038
|
|||
<div slot="slot1" class="slotted2">slot1-2</div>
|
||||
</test-component>
|
||||
|
||||
<ol>
|
||||
<li id="list"><span id="first-list-child"
|
||||
>List item start</span><span id="last-list-child"
|
||||
>List item end</span></li>
|
||||
</ol>
|
||||
|
||||
<script>
|
||||
"use strict";
|
||||
customElements.define("test-component", class extends HTMLElement {
|
||||
|
|
|
@ -16,7 +16,13 @@ function ReadOnlyEditor(container, node) {
|
|||
|
||||
if (node.isPseudoElement) {
|
||||
this.tag.classList.add("theme-fg-color3");
|
||||
this.tag.textContent = node.isBeforePseudoElement ? "::before" : "::after";
|
||||
if (node.isMarkerPseudoElement) {
|
||||
this.tag.textContent = "::marker";
|
||||
} else if (node.isBeforePseudoElement) {
|
||||
this.tag.textContent = "::before";
|
||||
} else if (node.isAfterPseudoElement) {
|
||||
this.tag.textContent = "::after";
|
||||
}
|
||||
} else if (node.nodeType == nodeConstants.DOCUMENT_TYPE_NODE) {
|
||||
this.elt.classList.add("comment", "doctype");
|
||||
this.tag.textContent = node.doctypeString;
|
||||
|
|
|
@ -21,6 +21,7 @@ add_task(async function() {
|
|||
await testBottomLeft(inspector, view);
|
||||
await testParagraph(inspector, view);
|
||||
await testBody(inspector, view);
|
||||
await testList(inspector, view);
|
||||
});
|
||||
|
||||
async function testTopLeft(inspector, view) {
|
||||
|
@ -31,6 +32,7 @@ async function testTopLeft(inspector, view) {
|
|||
firstLineRulesNb: 2,
|
||||
firstLetterRulesNb: 1,
|
||||
selectionRulesNb: 1,
|
||||
markerRulesNb: 0,
|
||||
afterRulesNb: 1,
|
||||
beforeRulesNb: 2,
|
||||
}
|
||||
|
@ -123,6 +125,7 @@ async function testTopRight(inspector, view) {
|
|||
firstLineRulesNb: 1,
|
||||
firstLetterRulesNb: 1,
|
||||
selectionRulesNb: 0,
|
||||
markerRulesNb: 0,
|
||||
beforeRulesNb: 2,
|
||||
afterRulesNb: 1,
|
||||
});
|
||||
|
@ -145,6 +148,7 @@ async function testBottomRight(inspector, view) {
|
|||
firstLineRulesNb: 1,
|
||||
firstLetterRulesNb: 1,
|
||||
selectionRulesNb: 0,
|
||||
markerRulesNb: 0,
|
||||
beforeRulesNb: 3,
|
||||
afterRulesNb: 1,
|
||||
});
|
||||
|
@ -156,6 +160,7 @@ async function testBottomLeft(inspector, view) {
|
|||
firstLineRulesNb: 1,
|
||||
firstLetterRulesNb: 1,
|
||||
selectionRulesNb: 0,
|
||||
markerRulesNb: 0,
|
||||
beforeRulesNb: 2,
|
||||
afterRulesNb: 1,
|
||||
});
|
||||
|
@ -168,6 +173,7 @@ async function testParagraph(inspector, view) {
|
|||
firstLineRulesNb: 1,
|
||||
firstLetterRulesNb: 1,
|
||||
selectionRulesNb: 2,
|
||||
markerRulesNb: 0,
|
||||
beforeRulesNb: 0,
|
||||
afterRulesNb: 0,
|
||||
});
|
||||
|
@ -197,6 +203,20 @@ async function testBody(inspector, view) {
|
|||
is(gutters.length, 0, "There are no gutter headings");
|
||||
}
|
||||
|
||||
async function testList(inspector, view) {
|
||||
await assertPseudoElementRulesNumbers("#list", inspector, view, {
|
||||
elementRulesNb: 4,
|
||||
firstLineRulesNb: 1,
|
||||
firstLetterRulesNb: 1,
|
||||
selectionRulesNb: 0,
|
||||
markerRulesNb: 1,
|
||||
beforeRulesNb: 1,
|
||||
afterRulesNb: 1,
|
||||
});
|
||||
|
||||
assertGutters(view);
|
||||
}
|
||||
|
||||
function convertTextPropsToString(textProps) {
|
||||
return textProps.map(t => t.name + ": " + t.value).join("; ");
|
||||
}
|
||||
|
@ -218,6 +238,8 @@ async function assertPseudoElementRulesNumbers(selector, inspector, view, ruleNb
|
|||
rule.pseudoElement === ":first-letter"),
|
||||
selectionRules: elementStyle.rules.filter(rule =>
|
||||
rule.pseudoElement === ":selection"),
|
||||
markerRules: elementStyle.rules.filter(rule =>
|
||||
rule.pseudoElement === ":marker"),
|
||||
beforeRules: elementStyle.rules.filter(rule =>
|
||||
rule.pseudoElement === ":before"),
|
||||
afterRules: elementStyle.rules.filter(rule =>
|
||||
|
@ -232,6 +254,8 @@ async function assertPseudoElementRulesNumbers(selector, inspector, view, ruleNb
|
|||
selector + " has the correct number of :first-letter rules");
|
||||
is(rules.selectionRules.length, ruleNbs.selectionRulesNb,
|
||||
selector + " has the correct number of :selection rules");
|
||||
is(rules.markerRules.length, ruleNbs.markerRulesNb,
|
||||
selector + " has the correct number of :marker rules");
|
||||
is(rules.beforeRules.length, ruleNbs.beforeRulesNb,
|
||||
selector + " has the correct number of :before rules");
|
||||
is(rules.afterRules.length, ruleNbs.afterRulesNb,
|
||||
|
|
|
@ -26,4 +26,18 @@ add_task(async function() {
|
|||
is(afterElement.tagName, "_moz_generated_content_after",
|
||||
"tag name is correct");
|
||||
await selectNode(afterElement, inspector);
|
||||
|
||||
const listNode = await getNodeFront("#list", inspector);
|
||||
const listChildren = await inspector.markup.walker.children(listNode);
|
||||
|
||||
is(listChildren.nodes.length, 4, "<li> has correct number of children");
|
||||
const markerElement = listChildren.nodes[0];
|
||||
is(markerElement.tagName, "_moz_generated_content_marker",
|
||||
"tag name is correct");
|
||||
await selectNode(markerElement, inspector);
|
||||
|
||||
const listBeforeElement = listChildren.nodes[1];
|
||||
is(listBeforeElement.tagName, "_moz_generated_content_before",
|
||||
"tag name is correct");
|
||||
await selectNode(listBeforeElement, inspector);
|
||||
});
|
||||
|
|
|
@ -106,6 +106,10 @@ p:first-letter {
|
|||
left:0;
|
||||
}
|
||||
|
||||
#list::marker {
|
||||
color: purple;
|
||||
}
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
@ -127,5 +131,9 @@ p:first-letter {
|
|||
<p>Bottom Left<br />Position</p>
|
||||
</div>
|
||||
|
||||
<ol>
|
||||
<li id="list" class="box">List element</li>
|
||||
</ol>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -139,10 +139,15 @@ function getSelectorFromGrip(grip) {
|
|||
nodeName,
|
||||
isAfterPseudoElement,
|
||||
isBeforePseudoElement,
|
||||
isMarkerPseudoElement,
|
||||
} = grip.preview;
|
||||
|
||||
if (isAfterPseudoElement || isBeforePseudoElement) {
|
||||
return `::${isAfterPseudoElement ? "after" : "before"}`;
|
||||
if (isAfterPseudoElement) {
|
||||
return "::after";
|
||||
} else if (isBeforePseudoElement) {
|
||||
return "::before";
|
||||
} else if (isMarkerPseudoElement) {
|
||||
return "::marker";
|
||||
}
|
||||
|
||||
let selector = nodeName;
|
||||
|
@ -200,6 +205,7 @@ function translateNodeFrontToGrip(nodeFront) {
|
|||
attributesLength: attributes.length,
|
||||
isAfterPseudoElement: nodeFront.isAfterPseudoElement,
|
||||
isBeforePseudoElement: nodeFront.isBeforePseudoElement,
|
||||
isMarkerPseudoElement: nodeFront.isMarkerPseudoElement,
|
||||
// All the grid containers are assumed to be in the DOM tree.
|
||||
isConnected: true,
|
||||
// nodeName is already lowerCased in Node grips
|
||||
|
|
|
@ -46,6 +46,16 @@ about-debugging-sidebar-no-devices = No devices discovered
|
|||
# Clicking on the button will attempt to connect to the runtime.
|
||||
about-debugging-sidebar-item-connect-button = Connect
|
||||
|
||||
# Text displayed in buttons found in sidebar items when the runtime is connecting.
|
||||
about-debugging-sidebar-item-connect-button-connecting = Connecting…
|
||||
|
||||
# Text displayed in buttons found in sidebar items when the connection failed.
|
||||
about-debugging-sidebar-item-connect-button-connection-failed = Connection failed
|
||||
|
||||
# Text displayed in connection warning on sidebar item of the runtime when connecting to
|
||||
# the runtime is taking too much time.
|
||||
about-debugging-sidebar-item-connect-button-connection-not-responding = Connection still pending, check for messages on the target browser
|
||||
|
||||
# Temporary text displayed in sidebar items representing remote runtimes after
|
||||
# successfully connecting to them. Temporary UI, do not localize.
|
||||
about-debugging-sidebar-item-connected-label = Connected
|
||||
|
|
|
@ -63,6 +63,10 @@ const SUMMARY_REFERRER_POLICY = L10N.getStr("netmonitor.summary.referrerPolicy")
|
|||
/**
|
||||
* Headers panel component
|
||||
* Lists basic information about the request
|
||||
*
|
||||
* In http/2 all response headers are in small case.
|
||||
* See: https://developer.mozilla.org/en-US/docs/Tools/Network_Monitor/request_details#Headers
|
||||
* RFC: https://tools.ietf.org/html/rfc7540#section-8.1.2
|
||||
*/
|
||||
class HeadersPanel extends Component {
|
||||
static get propTypes() {
|
||||
|
|
|
@ -187,7 +187,6 @@ skip-if = os == 'win' # bug 1391264
|
|||
[browser_net_set-cookie-same-site.js]
|
||||
[browser_net_simple-request-data.js]
|
||||
[browser_net_simple-request-details.js]
|
||||
skip-if = true # Bug 1258809
|
||||
[browser_net_simple-request.js]
|
||||
[browser_net_sort-01.js]
|
||||
[browser_net_sort-02.js]
|
||||
|
|
|
@ -13,14 +13,13 @@ add_task(async function() {
|
|||
const { tab, monitor } = await initNetMonitor(SIMPLE_SJS);
|
||||
info("Starting test... ");
|
||||
|
||||
const { document, store, windowRequire, NetMonitorView } = monitor.panelWin;
|
||||
const { document, store, windowRequire } = monitor.panelWin;
|
||||
const Actions = windowRequire("devtools/client/netmonitor/src/actions/index");
|
||||
const { EVENTS } = windowRequire("devtools/client/netmonitor/src/constants");
|
||||
const { PANELS } = windowRequire("devtools/client/netmonitor/src/constants");
|
||||
const {
|
||||
getSelectedRequest,
|
||||
getSortedRequests,
|
||||
} = windowRequire("devtools/client/netmonitor/src/selectors/index");
|
||||
const Editor = require("devtools/client/shared/sourceeditor/editor");
|
||||
|
||||
store.dispatch(Actions.batchEnable(false));
|
||||
|
||||
|
@ -35,6 +34,8 @@ add_task(async function() {
|
|||
is(!!document.querySelector(".network-details-panel"), false,
|
||||
"The network details panel should still be hidden after first request.");
|
||||
|
||||
const waitForHeaders = waitForDOM(document, ".headers-overview");
|
||||
|
||||
store.dispatch(Actions.toggleNetworkDetails());
|
||||
|
||||
isnot(getSelectedRequest(store.getState()), undefined,
|
||||
|
@ -44,11 +45,13 @@ add_task(async function() {
|
|||
is(!!document.querySelector(".network-details-panel"), true,
|
||||
"The network details panel should not be hidden after toggle button was pressed.");
|
||||
|
||||
testHeadersTab();
|
||||
await waitForHeaders;
|
||||
|
||||
await testHeadersTab();
|
||||
await testCookiesTab();
|
||||
testParamsTab();
|
||||
await testParamsTab();
|
||||
await testResponseTab();
|
||||
testTimingsTab();
|
||||
await testTimingsTab();
|
||||
return teardown(monitor);
|
||||
|
||||
function getSelectedIndex(state) {
|
||||
|
@ -58,215 +61,195 @@ add_task(async function() {
|
|||
return getSortedRequests(state).findIndex(r => r.id === state.requests.selectedId);
|
||||
}
|
||||
|
||||
function testHeadersTab() {
|
||||
const tabEl = document.querySelectorAll("#details-pane tab")[0];
|
||||
const tabpanel = document.querySelectorAll("#details-pane tabpanel")[0];
|
||||
async function testHeadersTab() {
|
||||
const tabEl = document.querySelectorAll(".network-details-panel .tabs-menu a")[0];
|
||||
const tabpanel = document.querySelector(".network-details-panel .tab-panel");
|
||||
|
||||
is(tabEl.getAttribute("selected"), "true",
|
||||
is(tabEl.getAttribute("aria-selected"), "true",
|
||||
"The headers tab in the network details pane should be selected.");
|
||||
|
||||
is(tabpanel.querySelector("#headers-summary-url-value").getAttribute("value"),
|
||||
// Request URL
|
||||
is(tabpanel.querySelectorAll(".tabpanel-summary-value")[0].innerText,
|
||||
SIMPLE_SJS, "The url summary value is incorrect.");
|
||||
is(tabpanel.querySelector("#headers-summary-url-value").getAttribute("tooltiptext"),
|
||||
SIMPLE_SJS, "The url summary tooltiptext is incorrect.");
|
||||
is(tabpanel.querySelector("#headers-summary-method-value").getAttribute("value"),
|
||||
// Request method
|
||||
is(tabpanel.querySelectorAll(".tabpanel-summary-value")[1].innerText,
|
||||
"GET", "The method summary value is incorrect.");
|
||||
is(tabpanel.querySelector("#headers-summary-address-value").getAttribute("value"),
|
||||
// Remote address
|
||||
is(tabpanel.querySelectorAll(".tabpanel-summary-value")[2].innerText,
|
||||
"127.0.0.1:8888", "The remote address summary value is incorrect.");
|
||||
is(tabpanel.querySelector("#headers-summary-status-circle").getAttribute("data-code"),
|
||||
// Status code
|
||||
is(tabpanel.querySelector(".requests-list-status-code").innerText,
|
||||
"200", "The status summary code is incorrect.");
|
||||
is(tabpanel.querySelector("#headers-summary-status-value").getAttribute("value"),
|
||||
"200 Och Aye", "The status summary value is incorrect.");
|
||||
is(tabpanel.querySelector(".status-text").getAttribute("value"),
|
||||
"Och Aye", "The status summary value is incorrect.");
|
||||
// Version
|
||||
is(tabpanel.querySelectorAll(".tabpanel-summary-value")[4].innerText,
|
||||
"HTTP/1.1", "The HTTP version is incorrect.");
|
||||
|
||||
is(tabpanel.querySelectorAll(".variables-view-scope").length, 2,
|
||||
await waitForRequestData(store, ["requestHeaders", "responseHeaders"]);
|
||||
|
||||
is(tabpanel.querySelectorAll(".treeTable tbody .tree-section").length, 2,
|
||||
"There should be 2 header scopes displayed in this tabpanel.");
|
||||
is(tabpanel.querySelectorAll(".variable-or-property").length, 19,
|
||||
"There should be 19 header values displayed in this tabpanel.");
|
||||
|
||||
is(tabpanel.querySelectorAll(".variables-view-empty-notice").length, 0,
|
||||
"The empty notice should not be displayed in this tabpanel.");
|
||||
is(tabpanel.querySelectorAll(":not(.tree-section) > .treeLabelCell").length,
|
||||
23, "There should be 23 header values displayed in this tabpanel.");
|
||||
|
||||
const responseScope = tabpanel.querySelectorAll(".variables-view-scope")[0];
|
||||
const requestScope = tabpanel.querySelectorAll(".variables-view-scope")[1];
|
||||
const headersTable = tabpanel.querySelector(".treeTable tbody");
|
||||
const responseScope = headersTable.querySelectorAll("tr[id^='/Response headers']");
|
||||
const requestScope = headersTable.querySelectorAll("tr[id^='/Request headers']");
|
||||
|
||||
is(responseScope.querySelector(".name").getAttribute("value"),
|
||||
L10N.getStr("responseHeaders") + " (" +
|
||||
L10N.getFormatStr("networkMenu.sizeKB",
|
||||
L10N.numberWithDecimals(330 / 1024, 3)) + ")",
|
||||
ok(headersTable.querySelectorAll(".tree-section .treeLabel")[0].innerHTML
|
||||
.match(new RegExp(L10N.getStr("responseHeaders") + " \\([0-9]+ .+\\)")),
|
||||
"The response headers scope doesn't have the correct title.");
|
||||
|
||||
ok(requestScope.querySelector(".name").getAttribute("value").includes(
|
||||
L10N.getStr("requestHeaders") + " (0"),
|
||||
ok(headersTable.querySelectorAll(".tree-section .treeLabel")[1].innerHTML.includes(
|
||||
L10N.getStr("requestHeaders") + " ("),
|
||||
"The request headers scope doesn't have the correct title.");
|
||||
// Can't test for full request headers title because the size may
|
||||
// vary across platforms ("User-Agent" header differs). We're pretty
|
||||
// sure it's smaller than 1 MB though, so it starts with a 0.
|
||||
|
||||
is(responseScope.querySelectorAll(".variables-view-variable .name")[0]
|
||||
.getAttribute("value"),
|
||||
"Cache-Control", "The first response header name was incorrect.");
|
||||
is(responseScope.querySelectorAll(".variables-view-variable .value")[0]
|
||||
.getAttribute("value"),
|
||||
"\"no-cache, no-store, must-revalidate\"",
|
||||
"The first response header value was incorrect.");
|
||||
is(responseScope.querySelectorAll(".variables-view-variable .name")[1]
|
||||
.getAttribute("value"),
|
||||
"Connection", "The second response header name was incorrect.");
|
||||
is(responseScope.querySelectorAll(".variables-view-variable .value")[1]
|
||||
.getAttribute("value"),
|
||||
"\"close\"", "The second response header value was incorrect.");
|
||||
is(responseScope.querySelectorAll(".variables-view-variable .name")[2]
|
||||
.getAttribute("value"),
|
||||
"Content-Length", "The third response header name was incorrect.");
|
||||
is(responseScope.querySelectorAll(".variables-view-variable .value")[2]
|
||||
.getAttribute("value"),
|
||||
"\"12\"", "The third response header value was incorrect.");
|
||||
is(responseScope.querySelectorAll(".variables-view-variable .name")[3]
|
||||
.getAttribute("value"),
|
||||
"Content-Type", "The fourth response header name was incorrect.");
|
||||
is(responseScope.querySelectorAll(".variables-view-variable .value")[3]
|
||||
.getAttribute("value"),
|
||||
"\"text/plain; charset=utf-8\"", "The fourth response header value was incorrect.");
|
||||
is(responseScope.querySelectorAll(".variables-view-variable .name")[9]
|
||||
.getAttribute("value"),
|
||||
"foo-bar", "The last response header name was incorrect.");
|
||||
is(responseScope.querySelectorAll(".variables-view-variable .value")[9]
|
||||
.getAttribute("value"),
|
||||
"\"baz\"", "The last response header value was incorrect.");
|
||||
const responseHeaders = [
|
||||
{
|
||||
name: "cache-control",
|
||||
value: "no-cache, no-store, must-revalidate",
|
||||
pos: "first",
|
||||
index: 1,
|
||||
},
|
||||
{
|
||||
name: "connection",
|
||||
value: "close",
|
||||
pos: "second",
|
||||
index: 2,
|
||||
},
|
||||
{
|
||||
name: "content-length",
|
||||
value: "12",
|
||||
pos: "third",
|
||||
index: 3,
|
||||
},
|
||||
{
|
||||
name: "content-type",
|
||||
value: "text/plain; charset=utf-8",
|
||||
pos: "fourth",
|
||||
index: 4,
|
||||
},
|
||||
{
|
||||
name: "foo-bar",
|
||||
value: "baz",
|
||||
pos: "seventh",
|
||||
index: 7,
|
||||
},
|
||||
];
|
||||
responseHeaders.forEach((header) => {
|
||||
is(responseScope[header.index].querySelector(".treeLabel").innerHTML,
|
||||
header.name, `The ${header.pos} response header name was incorrect.`);
|
||||
is(responseScope[header.index].querySelector(".objectBox").innerHTML,
|
||||
header.value, `The ${header.pos} response header value was incorrect.`);
|
||||
});
|
||||
|
||||
is(requestScope.querySelectorAll(".variables-view-variable .name")[0]
|
||||
.getAttribute("value"),
|
||||
"Host", "The first request header name was incorrect.");
|
||||
is(requestScope.querySelectorAll(".variables-view-variable .value")[0]
|
||||
.getAttribute("value"),
|
||||
"\"example.com\"", "The first request header value was incorrect.");
|
||||
is(requestScope.querySelectorAll(".variables-view-variable .name")[6]
|
||||
.getAttribute("value"),
|
||||
"Connection", "The ante-penultimate request header name was incorrect.");
|
||||
is(requestScope.querySelectorAll(".variables-view-variable .value")[6]
|
||||
.getAttribute("value"),
|
||||
"\"keep-alive\"", "The ante-penultimate request header value was incorrect.");
|
||||
is(requestScope.querySelectorAll(".variables-view-variable .name")[7]
|
||||
.getAttribute("value"),
|
||||
"Pragma", "The penultimate request header name was incorrect.");
|
||||
is(requestScope.querySelectorAll(".variables-view-variable .value")[7]
|
||||
.getAttribute("value"),
|
||||
"\"no-cache\"", "The penultimate request header value was incorrect.");
|
||||
is(requestScope.querySelectorAll(".variables-view-variable .name")[8]
|
||||
.getAttribute("value"),
|
||||
"Cache-Control", "The last request header name was incorrect.");
|
||||
is(requestScope.querySelectorAll(".variables-view-variable .value")[8]
|
||||
.getAttribute("value"),
|
||||
"\"no-cache\"", "The last request header value was incorrect.");
|
||||
const requestHeaders = [
|
||||
{
|
||||
name: "Cache-Control",
|
||||
value: "no-cache",
|
||||
pos: "fourth",
|
||||
index: 4,
|
||||
},
|
||||
{
|
||||
name: "Connection",
|
||||
value: "keep-alive",
|
||||
pos: "fifth",
|
||||
index: 5,
|
||||
},
|
||||
{
|
||||
name: "Host",
|
||||
value: "example.com",
|
||||
pos: "seventh",
|
||||
index: 7,
|
||||
},
|
||||
{
|
||||
name: "Pragma",
|
||||
value: "no-cache",
|
||||
pos: "eighth",
|
||||
index: 8,
|
||||
},
|
||||
];
|
||||
requestHeaders.forEach((header) => {
|
||||
is(requestScope[header.index].querySelector(".treeLabel").innerHTML,
|
||||
header.name, `The ${header.pos} request header name was incorrect.`);
|
||||
is(requestScope[header.index].querySelector(".objectBox").innerHTML,
|
||||
header.value, `The ${header.pos} request header value was incorrect.`);
|
||||
});
|
||||
}
|
||||
|
||||
async function testCookiesTab() {
|
||||
const onEvent = monitor.panelWin.api.once(EVENTS.TAB_UPDATED);
|
||||
EventUtils.sendMouseEvent({ type: "mousedown" },
|
||||
document.querySelectorAll("#details-pane tab")[1]);
|
||||
await onEvent;
|
||||
const tabpanel = await selectTab(PANELS.COOKIES, 1);
|
||||
|
||||
const tabEl = document.querySelectorAll("#details-pane tab")[1];
|
||||
const tabpanel = document.querySelectorAll("#details-pane tabpanel")[1];
|
||||
|
||||
is(tabEl.getAttribute("selected"), "true",
|
||||
"The cookies tab in the network details pane should be selected.");
|
||||
|
||||
is(tabpanel.querySelectorAll(".variables-view-scope").length, 2,
|
||||
const cookieTable = tabpanel.querySelector(".treeTable tbody");
|
||||
is(cookieTable.querySelectorAll(".tree-section").length, 2,
|
||||
"There should be 2 cookie scopes displayed in this tabpanel.");
|
||||
is(tabpanel.querySelectorAll(".variable-or-property").length, 6,
|
||||
"There should be 6 cookie values displayed in this tabpanel.");
|
||||
// 2 Cookies in response - 1 httpOnly and 1 value for each cookie - total 6
|
||||
is(cookieTable.querySelectorAll("tr[id^='/Response cookies/'").length, 6,
|
||||
"There should be 6 rows displayed in response cookies table");
|
||||
is(cookieTable.querySelectorAll("tr[id^='/Request cookies/'").length, 2,
|
||||
"There should be 2 cookie values displayed in request cookies table.");
|
||||
}
|
||||
|
||||
function testParamsTab() {
|
||||
EventUtils.sendMouseEvent({ type: "mousedown" },
|
||||
document.querySelectorAll("#details-pane tab")[2]);
|
||||
async function testParamsTab() {
|
||||
const tabpanel = await selectTab(PANELS.PARAMS, 2);
|
||||
|
||||
const tabEl = document.querySelectorAll("#details-pane tab")[2];
|
||||
const tabpanel = document.querySelectorAll("#details-pane tabpanel")[2];
|
||||
|
||||
is(tabEl.getAttribute("selected"), "true",
|
||||
"The params tab in the network details pane should be selected.");
|
||||
|
||||
is(tabpanel.querySelectorAll(".variables-view-scope").length, 0,
|
||||
is(tabpanel.querySelectorAll(".panel-container").length, 0,
|
||||
"There should be no param scopes displayed in this tabpanel.");
|
||||
is(tabpanel.querySelectorAll(".variable-or-property").length, 0,
|
||||
"There should be no param values displayed in this tabpanel.");
|
||||
is(tabpanel.querySelectorAll(".variables-view-empty-notice").length, 1,
|
||||
is(tabpanel.querySelectorAll(".empty-notice").length, 1,
|
||||
"The empty notice should be displayed in this tabpanel.");
|
||||
|
||||
is(tabpanel.querySelector("#request-params-box")
|
||||
.hasAttribute("hidden"), false,
|
||||
"The request params box should not be hidden.");
|
||||
is(tabpanel.querySelector("#request-post-data-textarea-box")
|
||||
.hasAttribute("hidden"), true,
|
||||
"The request post data textarea box should be hidden.");
|
||||
}
|
||||
|
||||
async function testResponseTab() {
|
||||
const onEvent = monitor.panelWin.api.once(EVENTS.TAB_UPDATED);
|
||||
EventUtils.sendMouseEvent({ type: "mousedown" },
|
||||
document.querySelectorAll("#details-pane tab")[3]);
|
||||
await onEvent;
|
||||
const tabpanel = await selectTab(PANELS.RESPONSE, 3);
|
||||
await waitForDOM(document, ".treeTable tbody");
|
||||
|
||||
const tabEl = document.querySelectorAll("#details-pane tab")[3];
|
||||
const tabpanel = document.querySelectorAll("#details-pane tabpanel")[3];
|
||||
|
||||
is(tabEl.getAttribute("selected"), "true",
|
||||
"The response tab in the network details pane should be selected.");
|
||||
|
||||
is(tabpanel.querySelector("#response-content-info-header")
|
||||
.hasAttribute("hidden"), true,
|
||||
"The response info header should be hidden.");
|
||||
is(tabpanel.querySelector("#response-content-json-box")
|
||||
.hasAttribute("hidden"), true,
|
||||
"The response content json box should be hidden.");
|
||||
is(tabpanel.querySelector("#response-content-textarea-box")
|
||||
.hasAttribute("hidden"), false,
|
||||
"The response content textarea box should not be hidden.");
|
||||
is(tabpanel.querySelector("#response-content-image-box")
|
||||
.hasAttribute("hidden"), true,
|
||||
"The response content image box should be hidden.");
|
||||
|
||||
const editor = await NetMonitorView.editor("#response-content-textarea");
|
||||
is(editor.getText(), "Hello world!",
|
||||
"The text shown in the source editor is incorrect.");
|
||||
is(editor.getMode(), Editor.modes.text,
|
||||
"The mode active in the source editor is incorrect.");
|
||||
const responseTable = tabpanel.querySelector(".treeTable tbody");
|
||||
is(responseTable.querySelectorAll(".tree-section").length, 1,
|
||||
"There should be 1 response scope displayed in this tabpanel.");
|
||||
is(responseTable.querySelectorAll(".editor-row-container").length, 1,
|
||||
"The response payload tab should be open initially.");
|
||||
}
|
||||
|
||||
function testTimingsTab() {
|
||||
EventUtils.sendMouseEvent({ type: "mousedown" },
|
||||
document.querySelectorAll("#details-pane tab")[4]);
|
||||
async function testTimingsTab() {
|
||||
const tabpanel = await selectTab(PANELS.TIMINGS, 4);
|
||||
|
||||
const tabEl = document.querySelectorAll("#details-pane tab")[4];
|
||||
const tabpanel = document.querySelectorAll("#details-pane tabpanel")[4];
|
||||
const displayFormat = new RegExp(/[0-9]+ ms$/);
|
||||
const propsToVerify = [
|
||||
"blocked",
|
||||
"dns",
|
||||
"connect",
|
||||
"ssl",
|
||||
"send",
|
||||
"wait",
|
||||
"receive",
|
||||
];
|
||||
|
||||
is(tabEl.getAttribute("selected"), "true",
|
||||
"The timings tab in the network details pane should be selected.");
|
||||
// To ensure that test case for a new property is written, otherwise this
|
||||
// test will fail
|
||||
is(tabpanel.querySelectorAll(".tabpanel-summary-container").length,
|
||||
propsToVerify.length,
|
||||
`There should be exactly ${propsToVerify.length} values
|
||||
displayed in this tabpanel`);
|
||||
|
||||
ok(tabpanel.querySelector("#timings-summary-blocked .requests-list-timings-total")
|
||||
.getAttribute("value").match(/[0-9]+/),
|
||||
"The blocked timing info does not appear to be correct.");
|
||||
propsToVerify.forEach((propName) => {
|
||||
ok(tabpanel.querySelector(`#timings-summary-${propName}
|
||||
.requests-list-timings-total`)
|
||||
.innerHTML.match(displayFormat),
|
||||
`The ${propName} timing info does not appear to be correct.`);
|
||||
});
|
||||
}
|
||||
|
||||
ok(tabpanel.querySelector("#timings-summary-dns .requests-list-timings-total")
|
||||
.getAttribute("value").match(/[0-9]+/),
|
||||
"The dns timing info does not appear to be correct.");
|
||||
async function selectTab(tabName, pos) {
|
||||
const tabEl = document.querySelectorAll(".network-details-panel .tabs-menu a")[pos];
|
||||
|
||||
ok(tabpanel.querySelector("#timings-summary-connect .requests-list-timings-total")
|
||||
.getAttribute("value").match(/[0-9]+/),
|
||||
"The connect timing info does not appear to be correct.");
|
||||
const onPanelOpen = waitForDOM(document, `#${tabName}-panel`);
|
||||
EventUtils.sendMouseEvent({ type: "click" }, tabEl);
|
||||
await onPanelOpen;
|
||||
|
||||
ok(tabpanel.querySelector("#timings-summary-send .requests-list-timings-total")
|
||||
.getAttribute("value").match(/[0-9]+/),
|
||||
"The send timing info does not appear to be correct.");
|
||||
is(tabEl.getAttribute("aria-selected"), "true",
|
||||
`The ${tabName} tab in the network details pane should be selected.`);
|
||||
|
||||
ok(tabpanel.querySelector("#timings-summary-wait .requests-list-timings-total")
|
||||
.getAttribute("value").match(/[0-9]+/),
|
||||
"The wait timing info does not appear to be correct.");
|
||||
|
||||
ok(tabpanel.querySelector("#timings-summary-receive .requests-list-timings-total")
|
||||
.getAttribute("value").match(/[0-9]+/),
|
||||
"The receive timing info does not appear to be correct.");
|
||||
return document.querySelector(".network-details-panel .tab-panel");
|
||||
}
|
||||
});
|
||||
|
|
|
@ -6282,14 +6282,23 @@ function getElements(grip, mode) {
|
|||
attributes,
|
||||
nodeName,
|
||||
isAfterPseudoElement,
|
||||
isBeforePseudoElement
|
||||
isBeforePseudoElement,
|
||||
isMarkerPseudoElement
|
||||
} = grip.preview;
|
||||
const nodeNameElement = span({
|
||||
className: "tag-name"
|
||||
}, nodeName);
|
||||
|
||||
if (isAfterPseudoElement || isBeforePseudoElement) {
|
||||
return [span({ className: "attrName" }, `::${isAfterPseudoElement ? "after" : "before"}`)];
|
||||
let pseudoNodeName;
|
||||
if (isAfterPseudoElement) {
|
||||
pseudoNodeName = "after";
|
||||
} else if (isBeforePseudoElement) {
|
||||
pseudoNodeName = "before";
|
||||
} else if (isMarkerPseudoElement) {
|
||||
pseudoNodeName = "marker";
|
||||
}
|
||||
if (pseudoNodeName) {
|
||||
return [span({ className: "attrName" }, `::${pseudoNodeName}`)];
|
||||
}
|
||||
|
||||
if (mode === MODE.TINY) {
|
||||
|
|
|
@ -61,7 +61,7 @@ class ConsoleOutput extends Component {
|
|||
messagesTableData: PropTypes.object.isRequired,
|
||||
messagesRepeat: PropTypes.object.isRequired,
|
||||
warningGroups: PropTypes.object.isRequired,
|
||||
isInWarningGroup: PropTypes.isRequired,
|
||||
isInWarningGroup: PropTypes.func,
|
||||
networkMessagesUpdate: PropTypes.object.isRequired,
|
||||
visibleMessages: PropTypes.array.isRequired,
|
||||
networkMessageActiveTabId: PropTypes.string.isRequired,
|
||||
|
|
|
@ -665,7 +665,7 @@ CssLogic.getSelectors = function(domRule) {
|
|||
*
|
||||
* @returns {Object}
|
||||
* - {DOMNode} node The non-anonymous node
|
||||
* - {string} pseudo One of ':before', ':after', or null.
|
||||
* - {string} pseudo One of ':marker', ':before', ':after', or null.
|
||||
*/
|
||||
CssLogic.getBindingElementAndPseudo = getBindingElementAndPseudo;
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@ const Services = require("Services");
|
|||
const {
|
||||
isAfterPseudoElement,
|
||||
isBeforePseudoElement,
|
||||
isMarkerPseudoElement,
|
||||
isNativeAnonymous,
|
||||
} = require("devtools/shared/layout/utils");
|
||||
const Debugger = require("Debugger");
|
||||
|
@ -389,7 +390,7 @@ class JQueryEventCollector extends MainEventCollector {
|
|||
|
||||
// If jQuery is not on the page, if this is an anonymous node or a pseudo
|
||||
// element we need to return early.
|
||||
if (!jQuery || isNativeAnonymous(node) ||
|
||||
if (!jQuery || isNativeAnonymous(node) || isMarkerPseudoElement(node) ||
|
||||
isBeforePseudoElement(node) || isAfterPseudoElement(node)) {
|
||||
if (checkOnly) {
|
||||
return false;
|
||||
|
|
|
@ -18,6 +18,7 @@ loader.lazyRequireGetter(this, "isAfterPseudoElement", "devtools/shared/layout/u
|
|||
loader.lazyRequireGetter(this, "isAnonymous", "devtools/shared/layout/utils", true);
|
||||
loader.lazyRequireGetter(this, "isBeforePseudoElement", "devtools/shared/layout/utils", true);
|
||||
loader.lazyRequireGetter(this, "isDirectShadowHostChild", "devtools/shared/layout/utils", true);
|
||||
loader.lazyRequireGetter(this, "isMarkerPseudoElement", "devtools/shared/layout/utils", true);
|
||||
loader.lazyRequireGetter(this, "isNativeAnonymous", "devtools/shared/layout/utils", true);
|
||||
loader.lazyRequireGetter(this, "isShadowAnonymous", "devtools/shared/layout/utils", true);
|
||||
loader.lazyRequireGetter(this, "isShadowHost", "devtools/shared/layout/utils", true);
|
||||
|
@ -127,6 +128,7 @@ const NodeActor = protocol.ActorClassWithSpec(nodeSpec, {
|
|||
|
||||
attrs: this.writeAttrs(),
|
||||
customElementLocation: this.getCustomElementLocation(),
|
||||
isMarkerPseudoElement: isMarkerPseudoElement(this.rawNode),
|
||||
isBeforePseudoElement: isBeforePseudoElement(this.rawNode),
|
||||
isAfterPseudoElement: isAfterPseudoElement(this.rawNode),
|
||||
isAnonymous: isAnonymous(this.rawNode),
|
||||
|
@ -186,7 +188,9 @@ const NodeActor = protocol.ActorClassWithSpec(nodeSpec, {
|
|||
get numChildren() {
|
||||
// For pseudo elements, childNodes.length returns 1, but the walker
|
||||
// will return 0.
|
||||
if (isBeforePseudoElement(this.rawNode) || isAfterPseudoElement(this.rawNode)) {
|
||||
if (isMarkerPseudoElement(this.rawNode) ||
|
||||
isBeforePseudoElement(this.rawNode) || isAfterPseudoElement(this.rawNode)
|
||||
) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -60,13 +60,14 @@ function isInXULDocument(el) {
|
|||
|
||||
/**
|
||||
* This DeepTreeWalker filter skips whitespace text nodes and anonymous
|
||||
* content with the exception of ::before and ::after and anonymous content
|
||||
* in XUL document (needed to show all elements in the browser toolbox).
|
||||
* content with the exception of ::marker, ::before, and ::after, plus anonymous
|
||||
* content in XUL document (needed to show all elements in the browser toolbox).
|
||||
*/
|
||||
function standardTreeWalkerFilter(node) {
|
||||
// ::before and ::after are native anonymous content, but we always
|
||||
// ::marker, ::before, and ::after are native anonymous content, but we always
|
||||
// want to show them
|
||||
if (node.nodeName === "_moz_generated_content_before" ||
|
||||
if (node.nodeName === "_moz_generated_content_marker" ||
|
||||
node.nodeName === "_moz_generated_content_before" ||
|
||||
node.nodeName === "_moz_generated_content_after") {
|
||||
return nodeFilterConstants.FILTER_ACCEPT;
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@ loader.lazyRequireGetter(this, "isAfterPseudoElement", "devtools/shared/layout/u
|
|||
loader.lazyRequireGetter(this, "isAnonymous", "devtools/shared/layout/utils", true);
|
||||
loader.lazyRequireGetter(this, "isBeforePseudoElement", "devtools/shared/layout/utils", true);
|
||||
loader.lazyRequireGetter(this, "isDirectShadowHostChild", "devtools/shared/layout/utils", true);
|
||||
loader.lazyRequireGetter(this, "isMarkerPseudoElement", "devtools/shared/layout/utils", true);
|
||||
loader.lazyRequireGetter(this, "isNativeAnonymous", "devtools/shared/layout/utils", true);
|
||||
loader.lazyRequireGetter(this, "isShadowHost", "devtools/shared/layout/utils", true);
|
||||
loader.lazyRequireGetter(this, "isShadowRoot", "devtools/shared/layout/utils", true);
|
||||
|
@ -87,6 +88,7 @@ const PSEUDO_SELECTORS = [
|
|||
[":disabled", 0],
|
||||
[":checked", 1],
|
||||
["::selection", 0],
|
||||
["::marker", 0],
|
||||
];
|
||||
|
||||
const HELPER_SHEET = "data:text/css;charset=utf-8," + encodeURIComponent(`
|
||||
|
@ -536,7 +538,8 @@ var WalkerActor = protocol.ActorClassWithSpec(walkerSpec, {
|
|||
*/
|
||||
inlineTextChild: function({ rawNode }) {
|
||||
// Quick checks to prevent creating a new walker if possible.
|
||||
if (isBeforePseudoElement(rawNode) ||
|
||||
if (isMarkerPseudoElement(rawNode) ||
|
||||
isBeforePseudoElement(rawNode) ||
|
||||
isAfterPseudoElement(rawNode) ||
|
||||
isShadowHost(rawNode) ||
|
||||
rawNode.nodeType != Node.ELEMENT_NODE ||
|
||||
|
@ -865,10 +868,14 @@ var WalkerActor = protocol.ActorClassWithSpec(walkerSpec, {
|
|||
}
|
||||
|
||||
if (shadowHost) {
|
||||
// Use anonymous walkers to fetch ::before / ::after pseudo elements
|
||||
// Use anonymous walkers to fetch ::marker / ::before / ::after pseudo
|
||||
// elements
|
||||
const firstChildWalker = this.getDocumentWalker(node.rawNode);
|
||||
const first = firstChildWalker.firstChild();
|
||||
const hasBefore = first && first.nodeName === "_moz_generated_content_before";
|
||||
const hasMarker = first && first.nodeName === "_moz_generated_content_marker";
|
||||
const maybeBeforeNode = hasMarker ? firstChildWalker.nextSibling() : first;
|
||||
const hasBefore = maybeBeforeNode &&
|
||||
maybeBeforeNode.nodeName === "_moz_generated_content_before";
|
||||
|
||||
const lastChildWalker = this.getDocumentWalker(node.rawNode);
|
||||
const last = lastChildWalker.lastChild();
|
||||
|
@ -877,8 +884,10 @@ var WalkerActor = protocol.ActorClassWithSpec(walkerSpec, {
|
|||
nodes = [
|
||||
// #shadow-root
|
||||
...(hideShadowRoot ? [] : [node.rawNode.openOrClosedShadowRoot]),
|
||||
// ::marker
|
||||
...(hasMarker ? [first] : []),
|
||||
// ::before
|
||||
...(hasBefore ? [first] : []),
|
||||
...(hasBefore ? [maybeBeforeNode] : []),
|
||||
// shadow host direct children
|
||||
...nodes,
|
||||
// native anonymous content for UA widgets
|
||||
|
|
|
@ -93,7 +93,10 @@ WalkerIndex.prototype = {
|
|||
// For each element node, we get the tagname and all attributes names
|
||||
// and values
|
||||
const localName = node.localName;
|
||||
if (localName === "_moz_generated_content_before") {
|
||||
if (localName === "_moz_generated_content_marker") {
|
||||
this._addToIndex("tag", node, "::marker");
|
||||
this._addToIndex("text", node, node.textContent.trim());
|
||||
} else if (localName === "_moz_generated_content_before") {
|
||||
this._addToIndex("tag", node, "::before");
|
||||
this._addToIndex("text", node, node.textContent.trim());
|
||||
} else if (localName === "_moz_generated_content_after") {
|
||||
|
|
|
@ -267,6 +267,9 @@ class NodeFront extends FrontClassWithSpec(nodeSpec) {
|
|||
return this._form.hasEventListeners;
|
||||
}
|
||||
|
||||
get isMarkerPseudoElement() {
|
||||
return this._form.isMarkerPseudoElement;
|
||||
}
|
||||
get isBeforePseudoElement() {
|
||||
return this._form.isBeforePseudoElement;
|
||||
}
|
||||
|
@ -274,7 +277,8 @@ class NodeFront extends FrontClassWithSpec(nodeSpec) {
|
|||
return this._form.isAfterPseudoElement;
|
||||
}
|
||||
get isPseudoElement() {
|
||||
return this.isBeforePseudoElement || this.isAfterPseudoElement;
|
||||
return this.isBeforePseudoElement || this.isAfterPseudoElement ||
|
||||
this.isMarkerPseudoElement;
|
||||
}
|
||||
get isAnonymous() {
|
||||
return this._form.isAnonymous;
|
||||
|
|
|
@ -456,19 +456,22 @@ exports.getCssPath = getCssPath;
|
|||
exports.getXPath = getXPath;
|
||||
|
||||
/**
|
||||
* Given a node, check to see if it is a ::before or ::after element.
|
||||
* Given a node, check to see if it is a ::marker, ::before, or ::after element.
|
||||
* If so, return the node that is accessible from within the document
|
||||
* (the parent of the anonymous node), along with which pseudo element
|
||||
* it was. Otherwise, return the node itself.
|
||||
*
|
||||
* @returns {Object}
|
||||
* - {DOMNode} node The non-anonymous node
|
||||
* - {string} pseudo One of ':before', ':after', or null.
|
||||
* - {string} pseudo One of ':marker', ':before', ':after', or null.
|
||||
*/
|
||||
function getBindingElementAndPseudo(node) {
|
||||
let bindingElement = node;
|
||||
let pseudo = null;
|
||||
if (node.nodeName == "_moz_generated_content_before") {
|
||||
if (node.nodeName == "_moz_generated_content_marker") {
|
||||
bindingElement = node.parentNode;
|
||||
pseudo = ":marker";
|
||||
} else if (node.nodeName == "_moz_generated_content_before") {
|
||||
bindingElement = node.parentNode;
|
||||
pseudo = ":before";
|
||||
} else if (node.nodeName == "_moz_generated_content_after") {
|
||||
|
|
|
@ -638,6 +638,7 @@ exports.isShadowHost = isShadowHost;
|
|||
function isDirectShadowHostChild(node) {
|
||||
// Pseudo elements and native anonymous elements are always part of the anonymous tree.
|
||||
if (
|
||||
isMarkerPseudoElement(node) ||
|
||||
isBeforePseudoElement(node) ||
|
||||
isAfterPseudoElement(node) ||
|
||||
isNativeAnonymous(node)) {
|
||||
|
@ -649,6 +650,17 @@ function isDirectShadowHostChild(node) {
|
|||
}
|
||||
exports.isDirectShadowHostChild = isDirectShadowHostChild;
|
||||
|
||||
/**
|
||||
* Determine whether a node is a ::marker pseudo.
|
||||
*
|
||||
* @param {DOMNode} node
|
||||
* @return {Boolean}
|
||||
*/
|
||||
function isMarkerPseudoElement(node) {
|
||||
return node.nodeName === "_moz_generated_content_marker";
|
||||
}
|
||||
exports.isMarkerPseudoElement = isMarkerPseudoElement;
|
||||
|
||||
/**
|
||||
* Determine whether a node is a ::before pseudo.
|
||||
*
|
||||
|
|
|
@ -62,19 +62,24 @@ void ReleaseDataBuffer_s(const uint8_t* buf, void* user_data) {
|
|||
}
|
||||
|
||||
void DAV1DDecoder::ReleaseDataBuffer(const uint8_t* buf) {
|
||||
// The release callback may be called on a
|
||||
// different thread defined by third party
|
||||
// dav1d execution. Post a task into TaskQueue
|
||||
// to ensure mDecodingBuffers is only ever
|
||||
// accessed on the TaskQueue
|
||||
// The release callback may be called on a different thread defined by the
|
||||
// third party dav1d execution. In that case post a task into TaskQueue to
|
||||
// ensure that mDecodingBuffers is only ever accessed on the TaskQueue.
|
||||
RefPtr<DAV1DDecoder> self = this;
|
||||
nsresult rv = mTaskQueue->Dispatch(
|
||||
NS_NewRunnableFunction("DAV1DDecoder::ReleaseDataBuffer", [self, buf]() {
|
||||
DebugOnly<bool> found = self->mDecodingBuffers.Remove(buf);
|
||||
MOZ_ASSERT(found);
|
||||
}));
|
||||
MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
|
||||
Unused << rv;
|
||||
auto releaseBuffer = [self, buf] {
|
||||
MOZ_ASSERT(self->mTaskQueue->IsCurrentThreadIn());
|
||||
DebugOnly<bool> found = self->mDecodingBuffers.Remove(buf);
|
||||
MOZ_ASSERT(found);
|
||||
};
|
||||
|
||||
if (mTaskQueue->IsCurrentThreadIn()) {
|
||||
releaseBuffer();
|
||||
} else {
|
||||
nsresult rv = mTaskQueue->Dispatch(NS_NewRunnableFunction(
|
||||
"DAV1DDecoder::ReleaseDataBuffer", std::move(releaseBuffer)));
|
||||
MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
|
||||
Unused << rv;
|
||||
}
|
||||
}
|
||||
|
||||
RefPtr<MediaDataDecoder::DecodePromise> DAV1DDecoder::InvokeDecode(
|
||||
|
|
|
@ -403,6 +403,7 @@ class gfxPrefs final {
|
|||
DECL_GFX_PREF(Live, "dom.vr.puppet.submitframe", VRPuppetSubmitFrame, uint32_t, 0);
|
||||
DECL_GFX_PREF(Live, "dom.vr.display.rafMaxDuration", VRDisplayRafMaxDuration, uint32_t, 50);
|
||||
DECL_GFX_PREF(Once, "dom.vr.process.enabled", VRProcessEnabled, bool, false);
|
||||
DECL_GFX_PREF(Once, "dom.vr.process.startup_timeout_ms", VRProcessTimeoutMs, int32_t, 5000);
|
||||
DECL_GFX_PREF(Once, "dom.vr.service.enabled", VRServiceEnabled, bool, true);
|
||||
DECL_GFX_PREF(Live, "dom.w3c_pointer_events.enabled", PointerEventsEnabled, bool, false);
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@ using mozilla::dom::NativeThreadId from "mozilla/dom/TabMessageUtils.h";
|
|||
include "VRMessageUtils.h";
|
||||
|
||||
include GraphicsMessages;
|
||||
include MemoryReportTypes;
|
||||
include protocol PVRGPU;
|
||||
|
||||
include "VRMessageUtils.h";
|
||||
|
@ -27,11 +28,19 @@ parent:
|
|||
async UpdateVar(GfxVarUpdate var);
|
||||
async OpenVRControllerActionPathToVR(nsCString aPath);
|
||||
async OpenVRControllerManifestPathToVR(OpenVRControllerType aType, nsCString aPath);
|
||||
|
||||
async RequestMemoryReport(uint32_t generation,
|
||||
bool anonymize,
|
||||
bool minimizeMemoryUsage,
|
||||
FileDescriptor? DMDFile);
|
||||
child:
|
||||
// Sent when the GPU process has initialized devices. This occurs once, after
|
||||
// Init().
|
||||
async InitComplete();
|
||||
async OpenVRControllerActionPathToParent(nsCString aPath);
|
||||
async OpenVRControllerManifestPathToParent(OpenVRControllerType aType, nsCString aPath);
|
||||
async InitCrashReporter(Shmem shmem, NativeThreadId threadId);
|
||||
async AddMemoryReport(MemoryReport aReport);
|
||||
async FinishMemoryReport(uint32_t aGeneration);
|
||||
};
|
||||
|
||||
} // namespace gfx
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include "mozilla/SystemGroup.h"
|
||||
#include "mozilla/Telemetry.h"
|
||||
#include "mozilla/VsyncDispatcher.h"
|
||||
#include "mozilla/dom/MemoryReportRequest.h"
|
||||
#include "mozilla/ipc/CrashReporterHost.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
@ -66,10 +67,29 @@ class OpenVRControllerManifestManager {
|
|||
|
||||
StaticRefPtr<OpenVRControllerManifestManager> sOpenVRControllerManifestManager;
|
||||
|
||||
VRChild::VRChild(VRProcessParent* aHost) : mHost(aHost) {
|
||||
VRChild::VRChild(VRProcessParent* aHost)
|
||||
: mHost(aHost),
|
||||
mVRReady(false) {
|
||||
MOZ_ASSERT(XRE_IsParentProcess());
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult VRChild::RecvAddMemoryReport(
|
||||
const MemoryReport& aReport) {
|
||||
if (mMemoryReportRequest) {
|
||||
mMemoryReportRequest->RecvReport(aReport);
|
||||
}
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult VRChild::RecvFinishMemoryReport(
|
||||
const uint32_t& aGeneration) {
|
||||
if (mMemoryReportRequest) {
|
||||
mMemoryReportRequest->Finish(aGeneration);
|
||||
mMemoryReportRequest = nullptr;
|
||||
}
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
void VRChild::ActorDestroy(ActorDestroyReason aWhy) {
|
||||
if (aWhy == AbnormalShutdown) {
|
||||
if (mCrashReporter) {
|
||||
|
@ -144,6 +164,14 @@ void VRChild::Init() {
|
|||
gfxVars::AddReceiver(this);
|
||||
}
|
||||
|
||||
bool VRChild::EnsureVRReady() {
|
||||
if (!mVRReady) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult VRChild::RecvOpenVRControllerActionPathToParent(
|
||||
const nsCString& aPath) {
|
||||
sOpenVRControllerManifestManager->SetOpenVRControllerActionPath(aPath);
|
||||
|
@ -157,6 +185,12 @@ mozilla::ipc::IPCResult VRChild::RecvOpenVRControllerManifestPathToParent(
|
|||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult VRChild::RecvInitComplete() {
|
||||
// We synchronously requested VR parameters before this arrived.
|
||||
mVRReady = true;
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult VRChild::RecvInitCrashReporter(
|
||||
Shmem&& aShmem, const NativeThreadId& aThreadId) {
|
||||
mCrashReporter = MakeUnique<ipc::CrashReporterHost>(GeckoProcessType_VR,
|
||||
|
@ -165,6 +199,16 @@ mozilla::ipc::IPCResult VRChild::RecvInitCrashReporter(
|
|||
return IPC_OK();
|
||||
}
|
||||
|
||||
bool VRChild::SendRequestMemoryReport(const uint32_t& aGeneration,
|
||||
const bool& aAnonymize,
|
||||
const bool& aMinimizeMemoryUsage,
|
||||
const Maybe<FileDescriptor>& aDMDFile) {
|
||||
mMemoryReportRequest = MakeUnique<MemoryReportRequestHost>(aGeneration);
|
||||
Unused << PVRChild::SendRequestMemoryReport(aGeneration, aAnonymize,
|
||||
aMinimizeMemoryUsage, aDMDFile);
|
||||
return true;
|
||||
}
|
||||
|
||||
void VRChild::OnVarChanged(const GfxVarUpdate& aVar) { SendUpdateVar(aVar); }
|
||||
|
||||
class DeferredDeleteVRChild : public Runnable {
|
||||
|
|
|
@ -16,12 +16,16 @@ namespace mozilla {
|
|||
namespace ipc {
|
||||
class CrashReporterHost;
|
||||
} // namespace ipc
|
||||
namespace dom {
|
||||
class MemoryReportRequestHost;
|
||||
} // namespace dom
|
||||
namespace gfx {
|
||||
|
||||
class VRProcessParent;
|
||||
class VRChild;
|
||||
|
||||
class VRChild final : public PVRChild, public gfxVarReceiver {
|
||||
typedef mozilla::dom::MemoryReportRequestHost MemoryReportRequestHost;
|
||||
friend class PVRChild;
|
||||
|
||||
public:
|
||||
|
@ -30,7 +34,12 @@ class VRChild final : public PVRChild, public gfxVarReceiver {
|
|||
|
||||
static void Destroy(UniquePtr<VRChild>&& aChild);
|
||||
void Init();
|
||||
bool EnsureVRReady();
|
||||
virtual void OnVarChanged(const GfxVarUpdate& aVar) override;
|
||||
bool SendRequestMemoryReport(const uint32_t& aGeneration,
|
||||
const bool& aAnonymize,
|
||||
const bool& aMinimizeMemoryUsage,
|
||||
const Maybe<ipc::FileDescriptor>& aDMDFile);
|
||||
|
||||
protected:
|
||||
virtual void ActorDestroy(ActorDestroyReason aWhy) override;
|
||||
|
@ -38,12 +47,18 @@ class VRChild final : public PVRChild, public gfxVarReceiver {
|
|||
const nsCString& aPath);
|
||||
mozilla::ipc::IPCResult RecvOpenVRControllerManifestPathToParent(
|
||||
const OpenVRControllerType& aType, const nsCString& aPath);
|
||||
mozilla::ipc::IPCResult RecvInitComplete();
|
||||
mozilla::ipc::IPCResult RecvInitCrashReporter(
|
||||
Shmem&& shmem, const NativeThreadId& aThreadId);
|
||||
|
||||
mozilla::ipc::IPCResult RecvAddMemoryReport(const MemoryReport& aReport);
|
||||
mozilla::ipc::IPCResult RecvFinishMemoryReport(const uint32_t& aGeneration);
|
||||
|
||||
private:
|
||||
VRProcessParent* mHost;
|
||||
UniquePtr<ipc::CrashReporterHost> mCrashReporter;
|
||||
UniquePtr<MemoryReportRequestHost> mMemoryReportRequest;
|
||||
bool mVRReady;
|
||||
};
|
||||
|
||||
} // namespace gfx
|
||||
|
|
|
@ -9,12 +9,14 @@
|
|||
#include "VRManager.h"
|
||||
#include "gfxConfig.h"
|
||||
#include "nsDebugImpl.h"
|
||||
#include "ProcessUtils.h"
|
||||
|
||||
#include "mozilla/gfx/gfxVars.h"
|
||||
#include "mozilla/ipc/CrashReporterClient.h"
|
||||
#include "mozilla/ipc/ProcessChild.h"
|
||||
|
||||
#if defined(XP_WIN)
|
||||
# include <process.h>
|
||||
# include "mozilla/gfx/DeviceManagerDx.h"
|
||||
#endif
|
||||
|
||||
|
@ -39,6 +41,8 @@ IPCResult VRParent::RecvNewGPUVRManager(Endpoint<PVRGPUParent>&& aEndpoint) {
|
|||
IPCResult VRParent::RecvInit(nsTArray<GfxPrefSetting>&& prefs,
|
||||
nsTArray<GfxVarUpdate>&& vars,
|
||||
const DevicePrefs& devicePrefs) {
|
||||
Unused << SendInitComplete();
|
||||
|
||||
const nsTArray<gfxPrefs::Pref*>& globalPrefs = gfxPrefs::all();
|
||||
for (auto& setting : prefs) {
|
||||
gfxPrefs::Pref* pref = globalPrefs[setting.index()];
|
||||
|
@ -93,6 +97,23 @@ mozilla::ipc::IPCResult VRParent::RecvOpenVRControllerManifestPathToVR(
|
|||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult VRParent::RecvRequestMemoryReport(
|
||||
const uint32_t& aGeneration, const bool& aAnonymize,
|
||||
const bool& aMinimizeMemoryUsage, const Maybe<FileDescriptor>& aDMDFile) {
|
||||
MOZ_ASSERT(XRE_IsVRProcess());
|
||||
nsPrintfCString processName("VR (pid %u)", (unsigned)getpid());
|
||||
|
||||
mozilla::dom::MemoryReportRequestClient::Start(
|
||||
aGeneration, aAnonymize, aMinimizeMemoryUsage, aDMDFile, processName,
|
||||
[&](const MemoryReport& aReport) {
|
||||
Unused << SendAddMemoryReport(aReport);
|
||||
},
|
||||
[&](const uint32_t& aGeneration) {
|
||||
return SendFinishMemoryReport(aGeneration);
|
||||
});
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
void VRParent::ActorDestroy(ActorDestroyReason aWhy) {
|
||||
if (AbnormalShutdown == aWhy) {
|
||||
NS_WARNING("Shutting down VR process early due to a crash!");
|
||||
|
@ -161,6 +182,7 @@ bool VRParent::Init(base::ProcessId aParentPid, const char* aParentBuildID,
|
|||
return false;
|
||||
}
|
||||
|
||||
mozilla::ipc::SetThisProcessName("VR Process");
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -46,6 +46,10 @@ class VRParent final : public PVRParent {
|
|||
const nsCString& aPath);
|
||||
mozilla::ipc::IPCResult RecvOpenVRControllerManifestPathToVR(
|
||||
const OpenVRControllerType& aType, const nsCString& aPath);
|
||||
mozilla::ipc::IPCResult RecvRequestMemoryReport(
|
||||
const uint32_t& generation, const bool& anonymize,
|
||||
const bool& minimizeMemoryUsage,
|
||||
const Maybe<ipc::FileDescriptor>& DMDFile);
|
||||
|
||||
private:
|
||||
nsCString mOpenVRControllerAction;
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include "VRChild.h"
|
||||
#include "VRGPUChild.h"
|
||||
#include "VRGPUParent.h"
|
||||
#include "mozilla/MemoryReportingProcess.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace gfx {
|
||||
|
@ -30,7 +31,7 @@ void VRProcessManager::Initialize() {
|
|||
/* static */
|
||||
void VRProcessManager::Shutdown() { sSingleton = nullptr; }
|
||||
|
||||
VRProcessManager::VRProcessManager() : mProcess(nullptr) {
|
||||
VRProcessManager::VRProcessManager() : mProcess(nullptr), mVRChild(nullptr) {
|
||||
MOZ_COUNT_CTOR(VRProcessManager);
|
||||
|
||||
mObserver = new Observer(this);
|
||||
|
@ -79,14 +80,43 @@ void VRProcessManager::DestroyProcess() {
|
|||
|
||||
mProcess->Shutdown();
|
||||
mProcess = nullptr;
|
||||
mVRChild = nullptr;
|
||||
|
||||
CrashReporter::AnnotateCrashReport(CrashReporter::Annotation::VRProcessStatus,
|
||||
NS_LITERAL_CSTRING("Destroyed"));
|
||||
}
|
||||
|
||||
bool VRProcessManager::EnsureVRReady() {
|
||||
if (mProcess && !mProcess->IsConnected()) {
|
||||
if (!mProcess->WaitForLaunch()) {
|
||||
// If this fails, we should have fired OnProcessLaunchComplete and
|
||||
// removed the process.
|
||||
MOZ_ASSERT(!mProcess && !mVRChild);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (mVRChild) {
|
||||
if (mVRChild->EnsureVRReady()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// If the initialization above fails, we likely have a GPU process teardown
|
||||
// waiting in our message queue (or will soon). We need to ensure we don't
|
||||
// restart it later because if we fail here, our callers assume they should
|
||||
// fall back to a combined UI/GPU process. This also ensures our internal
|
||||
// state is consistent (e.g. process token is reset).
|
||||
DisableVRProcess("Failed to initialize VR process");
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void VRProcessManager::OnProcessLaunchComplete(VRProcessParent* aParent) {
|
||||
MOZ_ASSERT(mProcess && mProcess == aParent);
|
||||
|
||||
mVRChild = mProcess->GetActor();
|
||||
|
||||
if (!mProcess->IsConnected()) {
|
||||
DestroyProcess();
|
||||
return;
|
||||
|
@ -166,5 +196,57 @@ void VRProcessManager::OnXPCOMShutdown() {
|
|||
|
||||
VRChild* VRProcessManager::GetVRChild() { return mProcess->GetActor(); }
|
||||
|
||||
class VRMemoryReporter : public MemoryReportingProcess {
|
||||
public:
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(VRMemoryReporter, override)
|
||||
|
||||
bool IsAlive() const override {
|
||||
if (VRProcessManager* vpm = VRProcessManager::Get()) {
|
||||
return !!vpm->GetVRChild();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SendRequestMemoryReport(const uint32_t& aGeneration,
|
||||
const bool& aAnonymize,
|
||||
const bool& aMinimizeMemoryUsage,
|
||||
const Maybe<FileDescriptor>& aDMDFile) override {
|
||||
VRChild* child = GetChild();
|
||||
if (!child) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return child->SendRequestMemoryReport(aGeneration, aAnonymize,
|
||||
aMinimizeMemoryUsage, aDMDFile);
|
||||
}
|
||||
|
||||
int32_t Pid() const override {
|
||||
if (VRChild* child = GetChild()) {
|
||||
return (int32_t)child->OtherPid();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
private:
|
||||
VRChild* GetChild() const {
|
||||
if (VRProcessManager* vpm = VRProcessManager::Get()) {
|
||||
if (VRChild* child = vpm->GetVRChild()) {
|
||||
return child;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
protected:
|
||||
~VRMemoryReporter() = default;
|
||||
};
|
||||
|
||||
RefPtr<MemoryReportingProcess> VRProcessManager::GetProcessMemoryReporter() {
|
||||
if (!EnsureVRReady()) {
|
||||
return nullptr;
|
||||
}
|
||||
return new VRMemoryReporter();
|
||||
}
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace mozilla
|
|
@ -9,6 +9,7 @@
|
|||
#include "VRProcessParent.h"
|
||||
|
||||
namespace mozilla {
|
||||
class MemoryReportingProcess;
|
||||
namespace gfx {
|
||||
|
||||
class VRManagerChild;
|
||||
|
@ -27,10 +28,19 @@ class VRProcessManager final : public VRProcessParent::Listener {
|
|||
|
||||
// If not using a VR process, launch a new VR process asynchronously.
|
||||
void LaunchVRProcess();
|
||||
|
||||
// Ensure that VR-bound methods can be used. If no VR process is being
|
||||
// used, or one is launched and ready, this function returns immediately.
|
||||
// Otherwise it blocks until the VR process has finished launching.
|
||||
bool EnsureVRReady();
|
||||
|
||||
bool CreateGPUBridges(base::ProcessId aOtherProcess,
|
||||
mozilla::ipc::Endpoint<PVRGPUChild>* aOutVRBridge);
|
||||
|
||||
VRChild* GetVRChild();
|
||||
// If a VR process is present, create a MemoryReportingProcess object.
|
||||
// Otherwise, return null.
|
||||
RefPtr<MemoryReportingProcess> GetProcessMemoryReporter();
|
||||
|
||||
virtual void OnProcessLaunchComplete(VRProcessParent* aParent) override;
|
||||
virtual void OnProcessUnexpectedShutdown(VRProcessParent* aParent) override;
|
||||
|
@ -65,6 +75,7 @@ class VRProcessManager final : public VRProcessParent::Listener {
|
|||
|
||||
RefPtr<Observer> mObserver;
|
||||
VRProcessParent* mProcess;
|
||||
VRChild* mVRChild;
|
||||
};
|
||||
|
||||
} // namespace gfx
|
||||
|
|
|
@ -33,6 +33,7 @@ VRProcessParent::VRProcessParent(Listener* aListener)
|
|||
: GeckoChildProcessHost(GeckoProcessType_VR),
|
||||
mTaskFactory(this),
|
||||
mListener(aListener),
|
||||
mLaunchPhase(LaunchPhase::Unlaunched),
|
||||
mChannelClosed(false),
|
||||
mShutdownRequested(false) {
|
||||
MOZ_COUNT_CTOR(VRProcessParent);
|
||||
|
@ -49,19 +50,47 @@ VRProcessParent::~VRProcessParent() {
|
|||
}
|
||||
|
||||
bool VRProcessParent::Launch() {
|
||||
MOZ_ASSERT(mLaunchPhase == LaunchPhase::Unlaunched);
|
||||
MOZ_ASSERT(!mVRChild);
|
||||
mLaunchThread = NS_GetCurrentThread();
|
||||
|
||||
mLaunchPhase = LaunchPhase::Waiting;
|
||||
|
||||
std::vector<std::string> extraArgs;
|
||||
nsCString parentBuildID(mozilla::PlatformBuildID());
|
||||
extraArgs.push_back("-parentBuildID");
|
||||
extraArgs.push_back(parentBuildID.get());
|
||||
|
||||
if (!GeckoChildProcessHost::AsyncLaunch(extraArgs)) {
|
||||
mLaunchPhase = LaunchPhase::Complete;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool VRProcessParent::WaitForLaunch() {
|
||||
if (mLaunchPhase == LaunchPhase::Complete) {
|
||||
return !!mVRChild;
|
||||
}
|
||||
|
||||
int32_t timeoutMs = gfxPrefs::VRProcessTimeoutMs();
|
||||
|
||||
// If one of the following environment variables are set we can effectively
|
||||
// ignore the timeout - as we can guarantee the compositor process will be
|
||||
// terminated
|
||||
if (PR_GetEnv("MOZ_DEBUG_CHILD_PROCESS") ||
|
||||
PR_GetEnv("MOZ_DEBUG_CHILD_PAUSE")) {
|
||||
timeoutMs = 0;
|
||||
}
|
||||
|
||||
// Our caller expects the connection to be finished after we return, so we
|
||||
// immediately set up the IPDL actor and fire callbacks. The IO thread will
|
||||
// still dispatch a notification to the main thread - we'll just ignore it.
|
||||
bool result = GeckoChildProcessHost::WaitUntilConnected(timeoutMs);
|
||||
InitAfterConnect(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
void VRProcessParent::Shutdown() {
|
||||
MOZ_ASSERT(!mShutdownRequested);
|
||||
mListener = nullptr;
|
||||
|
@ -101,6 +130,10 @@ void VRProcessParent::DestroyProcess() {
|
|||
}
|
||||
|
||||
void VRProcessParent::InitAfterConnect(bool aSucceeded) {
|
||||
MOZ_ASSERT(mLaunchPhase == LaunchPhase::Waiting);
|
||||
MOZ_ASSERT(!mVRChild);
|
||||
|
||||
mLaunchPhase = LaunchPhase::Complete;
|
||||
if (aSucceeded) {
|
||||
mVRChild = MakeUnique<VRChild>(this);
|
||||
|
||||
|
@ -157,10 +190,16 @@ void VRProcessParent::OnChannelConnected(int32_t peer_pid) {
|
|||
NS_DispatchToMainThread(runnable);
|
||||
}
|
||||
|
||||
void VRProcessParent::OnChannelConnectedTask() { InitAfterConnect(true); }
|
||||
void VRProcessParent::OnChannelConnectedTask() {
|
||||
if (mLaunchPhase == LaunchPhase::Waiting) {
|
||||
InitAfterConnect(true);
|
||||
}
|
||||
}
|
||||
|
||||
void VRProcessParent::OnChannelErrorTask() {
|
||||
MOZ_ASSERT(false, "VR process channel error.");
|
||||
if (mLaunchPhase == LaunchPhase::Waiting) {
|
||||
InitAfterConnect(false);
|
||||
}
|
||||
}
|
||||
|
||||
void VRProcessParent::OnChannelClosed() {
|
||||
|
|
|
@ -32,6 +32,11 @@ class VRProcessParent final : public mozilla::ipc::GeckoChildProcessHost {
|
|||
explicit VRProcessParent(Listener* aListener);
|
||||
|
||||
bool Launch();
|
||||
// If the process is being launched, block until it has launched and
|
||||
// connected. If a launch task is pending, it will fire immediately.
|
||||
//
|
||||
// Returns true if the process is successfully connected; false otherwise.
|
||||
bool WaitForLaunch();
|
||||
void Shutdown();
|
||||
void DestroyProcess();
|
||||
bool CanShutdown() override { return true; }
|
||||
|
@ -45,6 +50,9 @@ class VRProcessParent final : public mozilla::ipc::GeckoChildProcessHost {
|
|||
|
||||
base::ProcessId OtherPid();
|
||||
VRChild* GetActor() const { return mVRChild.get(); }
|
||||
// Return a unique id for this process, guaranteed not to be shared with any
|
||||
// past or future instance of VRProcessParent.
|
||||
uint64_t GetProcessToken() const;
|
||||
|
||||
private:
|
||||
~VRProcessParent();
|
||||
|
@ -59,6 +67,8 @@ class VRProcessParent final : public mozilla::ipc::GeckoChildProcessHost {
|
|||
nsCOMPtr<nsIThread> mLaunchThread;
|
||||
Listener* mListener;
|
||||
|
||||
enum class LaunchPhase { Unlaunched, Waiting, Complete };
|
||||
LaunchPhase mLaunchPhase;
|
||||
bool mChannelClosed;
|
||||
bool mShutdownRequested;
|
||||
};
|
||||
|
|
|
@ -224,7 +224,7 @@ bool BytecodeEmitter::markSimpleBreakpoint() {
|
|||
bool BytecodeEmitter::emitCheck(JSOp op, ptrdiff_t delta, ptrdiff_t* offset) {
|
||||
*offset = code().length();
|
||||
|
||||
if (!code().growBy(delta)) {
|
||||
if (!code().growByUninitialized(delta)) {
|
||||
ReportOutOfMemory(cx);
|
||||
return false;
|
||||
}
|
||||
|
@ -9193,7 +9193,7 @@ bool BytecodeEmitter::emitTree(
|
|||
|
||||
static bool AllocSrcNote(JSContext* cx, SrcNotesVector& notes,
|
||||
unsigned* index) {
|
||||
if (!notes.growBy(1)) {
|
||||
if (!notes.growByUninitialized(1)) {
|
||||
ReportOutOfMemory(cx);
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
// If the async function's promise is already resolved, any attempt to return
|
||||
// a differerent return value gets ignored.
|
||||
|
||||
let g = newGlobal({newCompartment: true});
|
||||
g.eval(`
|
||||
async function f() {
|
||||
throw "ok";
|
||||
}
|
||||
`);
|
||||
|
||||
let dbg = new Debugger(g);
|
||||
|
||||
let hits = 0;
|
||||
dbg.onEnterFrame = frame => {
|
||||
frame.onPop = () => {
|
||||
hits += 1;
|
||||
|
||||
// Normal functions can override the return value, but async functions
|
||||
// have already resolved their promise, so this return request will get
|
||||
// ignored.
|
||||
return {return: "FAIL"};
|
||||
};
|
||||
};
|
||||
|
||||
g.f().catch(x => {
|
||||
assertEq(hits, 1);
|
||||
assertEq(x, "ok");
|
||||
});
|
|
@ -0,0 +1,28 @@
|
|||
// If the async function's promise is already resolved, any attempt to return
|
||||
// a differerent return value gets ignored.
|
||||
|
||||
let g = newGlobal({newCompartment: true});
|
||||
g.eval(`
|
||||
async function f() {
|
||||
return "ok";
|
||||
}
|
||||
`);
|
||||
|
||||
let dbg = new Debugger(g);
|
||||
|
||||
let hits = 0;
|
||||
dbg.onEnterFrame = frame => {
|
||||
frame.onPop = () => {
|
||||
hits += 1;
|
||||
|
||||
// Normal functions can override the return value, but async functions
|
||||
// have already resolved their promise, so this return request will get
|
||||
// ignored.
|
||||
return {return: "FAIL"};
|
||||
};
|
||||
};
|
||||
|
||||
g.f().then(x => {
|
||||
assertEq(hits, 1);
|
||||
assertEq(x, "ok");
|
||||
});
|
|
@ -442,24 +442,25 @@ static inline bool IsInlinableFallback(ICFallbackStub* icEntry) {
|
|||
#endif
|
||||
|
||||
static inline void* GetStubReturnAddress(JSContext* cx, jsbytecode* pc) {
|
||||
JitRealm* jitRealm = cx->realm()->jitRealm();
|
||||
const BaselineICFallbackCode& code =
|
||||
cx->runtime()->jitRuntime()->baselineICFallbackCode();
|
||||
|
||||
if (IsGetPropPC(pc)) {
|
||||
return jitRealm->bailoutReturnAddr(BailoutReturnStub::GetProp);
|
||||
return code.bailoutReturnAddr(BailoutReturnKind::GetProp);
|
||||
}
|
||||
if (IsSetPropPC(pc)) {
|
||||
return jitRealm->bailoutReturnAddr(BailoutReturnStub::SetProp);
|
||||
return code.bailoutReturnAddr(BailoutReturnKind::SetProp);
|
||||
}
|
||||
if (IsGetElemPC(pc)) {
|
||||
return jitRealm->bailoutReturnAddr(BailoutReturnStub::GetElem);
|
||||
return code.bailoutReturnAddr(BailoutReturnKind::GetElem);
|
||||
}
|
||||
|
||||
// This should be a call op of some kind, now.
|
||||
MOZ_ASSERT(IsCallPC(pc) && !IsSpreadCallPC(pc));
|
||||
if (IsConstructorCallPC(pc)) {
|
||||
return jitRealm->bailoutReturnAddr(BailoutReturnStub::New);
|
||||
return code.bailoutReturnAddr(BailoutReturnKind::New);
|
||||
}
|
||||
return jitRealm->bailoutReturnAddr(BailoutReturnStub::Call);
|
||||
return code.bailoutReturnAddr(BailoutReturnKind::Call);
|
||||
}
|
||||
|
||||
static inline jsbytecode* GetNextNonLoopEntryPc(jsbytecode* pc,
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
#include "vm/Opcodes.h"
|
||||
#include "vm/SelfHosting.h"
|
||||
#include "vm/TypedArrayObject.h"
|
||||
#include "vtune/VTuneWrapper.h"
|
||||
|
||||
#include "builtin/Boolean-inl.h"
|
||||
|
||||
|
@ -54,6 +55,26 @@ using mozilla::DebugOnly;
|
|||
namespace js {
|
||||
namespace jit {
|
||||
|
||||
// Class used to emit all Baseline IC fallback code when initializing the
|
||||
// JitRuntime.
|
||||
class MOZ_RAII FallbackICCodeCompiler final : public ICStubCompilerBase {
|
||||
BaselineICFallbackCode& code;
|
||||
MacroAssembler& masm;
|
||||
|
||||
MOZ_MUST_USE bool emitCall(bool isSpread, bool isConstructing);
|
||||
MOZ_MUST_USE bool emitGetElem(bool hasReceiver);
|
||||
MOZ_MUST_USE bool emitGetProp(bool hasReceiver);
|
||||
|
||||
public:
|
||||
FallbackICCodeCompiler(JSContext* cx, BaselineICFallbackCode& code,
|
||||
MacroAssembler& masm)
|
||||
: ICStubCompilerBase(cx), code(code), masm(masm) {}
|
||||
|
||||
#define DEF_METHOD(kind) MOZ_MUST_USE bool emit_##kind();
|
||||
IC_BASELINE_FALLBACK_CODE_KIND_LIST(DEF_METHOD)
|
||||
#undef DEF_METHOD
|
||||
};
|
||||
|
||||
#ifdef JS_JITSPEW
|
||||
void FallbackICSpew(JSContext* cx, ICFallbackStub* stub, const char* fmt, ...) {
|
||||
if (JitSpewEnabled(JitSpew_BaselineICFallback)) {
|
||||
|
@ -108,14 +129,39 @@ void ICEntry::trace(JSTracer* trc) {
|
|||
}
|
||||
}
|
||||
|
||||
// Allocator for Baseline IC fallback stubs. These stubs use trampoline code
|
||||
// stored in JitRuntime.
|
||||
class MOZ_RAII FallbackStubAllocator {
|
||||
JSContext* cx_;
|
||||
ICStubSpace& stubSpace_;
|
||||
const BaselineICFallbackCode& code_;
|
||||
|
||||
public:
|
||||
FallbackStubAllocator(JSContext* cx, ICStubSpace& stubSpace)
|
||||
: cx_(cx),
|
||||
stubSpace_(stubSpace),
|
||||
code_(cx->runtime()->jitRuntime()->baselineICFallbackCode()) {}
|
||||
|
||||
template <typename T, typename... Args>
|
||||
T* newStub(BaselineICFallbackKind kind, Args&&... args) {
|
||||
TrampolinePtr addr = code_.addr(kind);
|
||||
return ICStub::NewFallback<T>(cx_, &stubSpace_, addr,
|
||||
std::forward<Args>(args)...);
|
||||
}
|
||||
};
|
||||
|
||||
/* static */
|
||||
UniquePtr<ICScript> ICScript::create(JSContext* cx, JSScript* script) {
|
||||
MOZ_ASSERT(cx->realm()->jitRealm());
|
||||
MOZ_ASSERT(jit::IsBaselineEnabled(cx));
|
||||
|
||||
FallbackICStubSpace stubSpace;
|
||||
FallbackStubAllocator alloc(cx, stubSpace);
|
||||
|
||||
js::Vector<ICEntry, 16, SystemAllocPolicy> icEntries;
|
||||
|
||||
using Kind = BaselineICFallbackKind;
|
||||
|
||||
auto addIC = [cx, &icEntries, script](jsbytecode* pc, ICStub* stub) {
|
||||
if (!stub) {
|
||||
MOZ_ASSERT(cx->isExceptionPending());
|
||||
|
@ -133,14 +179,16 @@ UniquePtr<ICScript> ICScript::create(JSContext* cx, JSScript* script) {
|
|||
// Note: we pass a nullptr pc to indicate this is a non-op IC.
|
||||
// See ICEntry::NonOpPCOffset.
|
||||
if (JSFunction* fun = script->functionNonDelazifying()) {
|
||||
ICTypeMonitor_Fallback::Compiler compiler(cx, uint32_t(0));
|
||||
if (!addIC(nullptr, compiler.getStub(&stubSpace))) {
|
||||
ICStub* stub =
|
||||
alloc.newStub<ICTypeMonitor_Fallback>(Kind::TypeMonitor, nullptr, 0);
|
||||
if (!addIC(nullptr, stub)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < fun->nargs(); i++) {
|
||||
ICTypeMonitor_Fallback::Compiler compiler(cx, i + 1);
|
||||
if (!addIC(nullptr, compiler.getStub(&stubSpace))) {
|
||||
ICStub* stub = alloc.newStub<ICTypeMonitor_Fallback>(Kind::TypeMonitor,
|
||||
nullptr, i + 1);
|
||||
if (!addIC(nullptr, stub)) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
@ -166,8 +214,8 @@ UniquePtr<ICScript> ICScript::create(JSContext* cx, JSScript* script) {
|
|||
case JSOP_OR:
|
||||
case JSOP_IFEQ:
|
||||
case JSOP_IFNE: {
|
||||
ICToBool_Fallback::Compiler stubCompiler(cx);
|
||||
if (!addIC(pc, stubCompiler.getStub(&stubSpace))) {
|
||||
ICStub* stub = alloc.newStub<ICToBool_Fallback>(Kind::ToBool);
|
||||
if (!addIC(pc, stub)) {
|
||||
return nullptr;
|
||||
}
|
||||
break;
|
||||
|
@ -176,8 +224,8 @@ UniquePtr<ICScript> ICScript::create(JSContext* cx, JSScript* script) {
|
|||
case JSOP_NEG:
|
||||
case JSOP_INC:
|
||||
case JSOP_DEC: {
|
||||
ICUnaryArith_Fallback::Compiler stubCompiler(cx);
|
||||
if (!addIC(pc, stubCompiler.getStub(&stubSpace))) {
|
||||
ICStub* stub = alloc.newStub<ICUnaryArith_Fallback>(Kind::UnaryArith);
|
||||
if (!addIC(pc, stub)) {
|
||||
return nullptr;
|
||||
}
|
||||
break;
|
||||
|
@ -194,8 +242,8 @@ UniquePtr<ICScript> ICScript::create(JSContext* cx, JSScript* script) {
|
|||
case JSOP_DIV:
|
||||
case JSOP_MOD:
|
||||
case JSOP_POW: {
|
||||
ICBinaryArith_Fallback::Compiler stubCompiler(cx);
|
||||
if (!addIC(pc, stubCompiler.getStub(&stubSpace))) {
|
||||
ICStub* stub = alloc.newStub<ICBinaryArith_Fallback>(Kind::BinaryArith);
|
||||
if (!addIC(pc, stub)) {
|
||||
return nullptr;
|
||||
}
|
||||
break;
|
||||
|
@ -208,15 +256,16 @@ UniquePtr<ICScript> ICScript::create(JSContext* cx, JSScript* script) {
|
|||
case JSOP_GE:
|
||||
case JSOP_STRICTEQ:
|
||||
case JSOP_STRICTNE: {
|
||||
ICCompare_Fallback::Compiler stubCompiler(cx);
|
||||
if (!addIC(pc, stubCompiler.getStub(&stubSpace))) {
|
||||
ICStub* stub = alloc.newStub<ICCompare_Fallback>(Kind::Compare);
|
||||
if (!addIC(pc, stub)) {
|
||||
return nullptr;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case JSOP_LOOPENTRY: {
|
||||
ICWarmUpCounter_Fallback::Compiler stubCompiler(cx);
|
||||
if (!addIC(pc, stubCompiler.getStub(&stubSpace))) {
|
||||
ICStub* stub =
|
||||
alloc.newStub<ICWarmUpCounter_Fallback>(Kind::WarmUpCounter);
|
||||
if (!addIC(pc, stub)) {
|
||||
return nullptr;
|
||||
}
|
||||
break;
|
||||
|
@ -227,16 +276,17 @@ UniquePtr<ICScript> ICScript::create(JSContext* cx, JSScript* script) {
|
|||
if (!group) {
|
||||
return nullptr;
|
||||
}
|
||||
ICNewArray_Fallback::Compiler stubCompiler(cx, group);
|
||||
if (!addIC(pc, stubCompiler.getStub(&stubSpace))) {
|
||||
ICStub* stub =
|
||||
alloc.newStub<ICNewArray_Fallback>(Kind::NewArray, group);
|
||||
if (!addIC(pc, stub)) {
|
||||
return nullptr;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case JSOP_NEWOBJECT:
|
||||
case JSOP_NEWINIT: {
|
||||
ICNewObject_Fallback::Compiler stubCompiler(cx);
|
||||
if (!addIC(pc, stubCompiler.getStub(&stubSpace))) {
|
||||
ICStub* stub = alloc.newStub<ICNewObject_Fallback>(Kind::NewObject);
|
||||
if (!addIC(pc, stub)) {
|
||||
return nullptr;
|
||||
}
|
||||
break;
|
||||
|
@ -247,8 +297,8 @@ UniquePtr<ICScript> ICScript::create(JSContext* cx, JSScript* script) {
|
|||
case JSOP_INITELEM_INC:
|
||||
case JSOP_SETELEM:
|
||||
case JSOP_STRICTSETELEM: {
|
||||
ICSetElem_Fallback::Compiler stubCompiler(cx);
|
||||
if (!addIC(pc, stubCompiler.getStub(&stubSpace))) {
|
||||
ICStub* stub = alloc.newStub<ICSetElem_Fallback>(Kind::SetElem);
|
||||
if (!addIC(pc, stub)) {
|
||||
return nullptr;
|
||||
}
|
||||
break;
|
||||
|
@ -263,8 +313,8 @@ UniquePtr<ICScript> ICScript::create(JSContext* cx, JSScript* script) {
|
|||
case JSOP_STRICTSETNAME:
|
||||
case JSOP_SETGNAME:
|
||||
case JSOP_STRICTSETGNAME: {
|
||||
ICSetProp_Fallback::Compiler compiler(cx);
|
||||
if (!addIC(pc, compiler.getStub(&stubSpace))) {
|
||||
ICStub* stub = alloc.newStub<ICSetProp_Fallback>(Kind::SetProp);
|
||||
if (!addIC(pc, stub)) {
|
||||
return nullptr;
|
||||
}
|
||||
break;
|
||||
|
@ -272,66 +322,78 @@ UniquePtr<ICScript> ICScript::create(JSContext* cx, JSScript* script) {
|
|||
case JSOP_GETPROP:
|
||||
case JSOP_CALLPROP:
|
||||
case JSOP_LENGTH:
|
||||
case JSOP_GETPROP_SUPER:
|
||||
case JSOP_GETBOUNDNAME: {
|
||||
bool hasReceiver = (op == JSOP_GETPROP_SUPER);
|
||||
ICGetProp_Fallback::Compiler compiler(cx, hasReceiver);
|
||||
if (!addIC(pc, compiler.getStub(&stubSpace))) {
|
||||
ICStub* stub = alloc.newStub<ICGetProp_Fallback>(Kind::GetProp);
|
||||
if (!addIC(pc, stub)) {
|
||||
return nullptr;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case JSOP_GETPROP_SUPER: {
|
||||
ICStub* stub = alloc.newStub<ICGetProp_Fallback>(Kind::GetPropSuper);
|
||||
if (!addIC(pc, stub)) {
|
||||
return nullptr;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case JSOP_GETELEM:
|
||||
case JSOP_CALLELEM:
|
||||
case JSOP_CALLELEM: {
|
||||
ICStub* stub = alloc.newStub<ICGetElem_Fallback>(Kind::GetElem);
|
||||
if (!addIC(pc, stub)) {
|
||||
return nullptr;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case JSOP_GETELEM_SUPER: {
|
||||
bool hasReceiver = (op == JSOP_GETELEM_SUPER);
|
||||
ICGetElem_Fallback::Compiler stubCompiler(cx, hasReceiver);
|
||||
if (!addIC(pc, stubCompiler.getStub(&stubSpace))) {
|
||||
ICStub* stub = alloc.newStub<ICGetElem_Fallback>(Kind::GetElemSuper);
|
||||
if (!addIC(pc, stub)) {
|
||||
return nullptr;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case JSOP_IN: {
|
||||
ICIn_Fallback::Compiler stubCompiler(cx);
|
||||
if (!addIC(pc, stubCompiler.getStub(&stubSpace))) {
|
||||
ICStub* stub = alloc.newStub<ICIn_Fallback>(Kind::In);
|
||||
if (!addIC(pc, stub)) {
|
||||
return nullptr;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case JSOP_HASOWN: {
|
||||
ICHasOwn_Fallback::Compiler stubCompiler(cx);
|
||||
if (!addIC(pc, stubCompiler.getStub(&stubSpace))) {
|
||||
ICStub* stub = alloc.newStub<ICHasOwn_Fallback>(Kind::HasOwn);
|
||||
if (!addIC(pc, stub)) {
|
||||
return nullptr;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case JSOP_GETNAME:
|
||||
case JSOP_GETGNAME: {
|
||||
ICGetName_Fallback::Compiler stubCompiler(cx);
|
||||
if (!addIC(pc, stubCompiler.getStub(&stubSpace))) {
|
||||
ICStub* stub = alloc.newStub<ICGetName_Fallback>(Kind::GetName);
|
||||
if (!addIC(pc, stub)) {
|
||||
return nullptr;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case JSOP_BINDNAME:
|
||||
case JSOP_BINDGNAME: {
|
||||
ICBindName_Fallback::Compiler stubCompiler(cx);
|
||||
if (!addIC(pc, stubCompiler.getStub(&stubSpace))) {
|
||||
ICStub* stub = alloc.newStub<ICBindName_Fallback>(Kind::BindName);
|
||||
if (!addIC(pc, stub)) {
|
||||
return nullptr;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case JSOP_GETALIASEDVAR:
|
||||
case JSOP_GETIMPORT: {
|
||||
ICTypeMonitor_Fallback::Compiler compiler(cx, nullptr);
|
||||
if (!addIC(pc, compiler.getStub(&stubSpace))) {
|
||||
ICStub* stub =
|
||||
alloc.newStub<ICTypeMonitor_Fallback>(Kind::TypeMonitor, nullptr);
|
||||
if (!addIC(pc, stub)) {
|
||||
return nullptr;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case JSOP_GETINTRINSIC: {
|
||||
ICGetIntrinsic_Fallback::Compiler stubCompiler(cx);
|
||||
if (!addIC(pc, stubCompiler.getStub(&stubSpace))) {
|
||||
ICStub* stub =
|
||||
alloc.newStub<ICGetIntrinsic_Fallback>(Kind::GetIntrinsic);
|
||||
if (!addIC(pc, stub)) {
|
||||
return nullptr;
|
||||
}
|
||||
break;
|
||||
|
@ -339,54 +401,60 @@ UniquePtr<ICScript> ICScript::create(JSContext* cx, JSScript* script) {
|
|||
case JSOP_CALL:
|
||||
case JSOP_CALL_IGNORES_RV:
|
||||
case JSOP_CALLITER:
|
||||
case JSOP_SUPERCALL:
|
||||
case JSOP_FUNCALL:
|
||||
case JSOP_FUNAPPLY:
|
||||
case JSOP_NEW:
|
||||
case JSOP_EVAL:
|
||||
case JSOP_STRICTEVAL: {
|
||||
bool construct = JSOp(*pc) == JSOP_NEW || JSOp(*pc) == JSOP_SUPERCALL;
|
||||
ICCall_Fallback::Compiler stubCompiler(cx,
|
||||
/* isConstructing = */ construct,
|
||||
/* isSpread = */ false);
|
||||
if (!addIC(pc, stubCompiler.getStub(&stubSpace))) {
|
||||
ICStub* stub = alloc.newStub<ICCall_Fallback>(Kind::Call);
|
||||
if (!addIC(pc, stub)) {
|
||||
return nullptr;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case JSOP_SUPERCALL:
|
||||
case JSOP_NEW: {
|
||||
ICStub* stub = alloc.newStub<ICCall_Fallback>(Kind::CallConstructing);
|
||||
if (!addIC(pc, stub)) {
|
||||
return nullptr;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case JSOP_SPREADCALL:
|
||||
case JSOP_SPREADSUPERCALL:
|
||||
case JSOP_SPREADNEW:
|
||||
case JSOP_SPREADEVAL:
|
||||
case JSOP_STRICTSPREADEVAL: {
|
||||
bool construct =
|
||||
JSOp(*pc) == JSOP_SPREADNEW || JSOp(*pc) == JSOP_SPREADSUPERCALL;
|
||||
ICCall_Fallback::Compiler stubCompiler(cx,
|
||||
/* isConstructing = */ construct,
|
||||
/* isSpread = */ true);
|
||||
if (!addIC(pc, stubCompiler.getStub(&stubSpace))) {
|
||||
ICStub* stub = alloc.newStub<ICCall_Fallback>(Kind::SpreadCall);
|
||||
if (!addIC(pc, stub)) {
|
||||
return nullptr;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case JSOP_SPREADSUPERCALL:
|
||||
case JSOP_SPREADNEW: {
|
||||
ICStub* stub =
|
||||
alloc.newStub<ICCall_Fallback>(Kind::SpreadCallConstructing);
|
||||
if (!addIC(pc, stub)) {
|
||||
return nullptr;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case JSOP_INSTANCEOF: {
|
||||
ICInstanceOf_Fallback::Compiler stubCompiler(cx);
|
||||
if (!addIC(pc, stubCompiler.getStub(&stubSpace))) {
|
||||
ICStub* stub = alloc.newStub<ICInstanceOf_Fallback>(Kind::InstanceOf);
|
||||
if (!addIC(pc, stub)) {
|
||||
return nullptr;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case JSOP_TYPEOF:
|
||||
case JSOP_TYPEOFEXPR: {
|
||||
ICTypeOf_Fallback::Compiler stubCompiler(cx);
|
||||
if (!addIC(pc, stubCompiler.getStub(&stubSpace))) {
|
||||
ICStub* stub = alloc.newStub<ICTypeOf_Fallback>(Kind::TypeOf);
|
||||
if (!addIC(pc, stub)) {
|
||||
return nullptr;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case JSOP_ITER: {
|
||||
ICGetIterator_Fallback::Compiler compiler(cx);
|
||||
if (!addIC(pc, compiler.getStub(&stubSpace))) {
|
||||
ICStub* stub = alloc.newStub<ICGetIterator_Fallback>(Kind::GetIterator);
|
||||
if (!addIC(pc, stub)) {
|
||||
return nullptr;
|
||||
}
|
||||
break;
|
||||
|
@ -398,8 +466,9 @@ UniquePtr<ICScript> ICScript::create(JSContext* cx, JSScript* script) {
|
|||
if (!templateObject) {
|
||||
return nullptr;
|
||||
}
|
||||
ICRest_Fallback::Compiler compiler(cx, templateObject);
|
||||
if (!addIC(pc, compiler.getStub(&stubSpace))) {
|
||||
ICStub* stub =
|
||||
alloc.newStub<ICRest_Fallback>(Kind::Rest, templateObject);
|
||||
if (!addIC(pc, stub)) {
|
||||
return nullptr;
|
||||
}
|
||||
break;
|
||||
|
@ -504,11 +573,6 @@ bool ICStub::makesGCCalls() const {
|
|||
}
|
||||
}
|
||||
|
||||
void ICStub::traceCode(JSTracer* trc, const char* name) {
|
||||
JitCode* stubJitCode = jitCode();
|
||||
TraceManuallyBarrieredEdge(trc, &stubJitCode, name);
|
||||
}
|
||||
|
||||
void ICStub::updateCode(JitCode* code) {
|
||||
// Write barrier on the old code.
|
||||
JitCode::writeBarrierPre(jitCode());
|
||||
|
@ -517,7 +581,11 @@ void ICStub::updateCode(JitCode* code) {
|
|||
|
||||
/* static */
|
||||
void ICStub::trace(JSTracer* trc) {
|
||||
traceCode(trc, "shared-stub-jitcode");
|
||||
// Fallback stubs use runtime-wide trampoline code we don't need to trace.
|
||||
if (!usesTrampolineCode()) {
|
||||
JitCode* stubJitCode = jitCode();
|
||||
TraceManuallyBarrieredEdge(trc, &stubJitCode, "baseline-ic-stub-code");
|
||||
}
|
||||
|
||||
// If the stub is a monitored fallback stub, then trace the monitor ICs
|
||||
// hanging off of that stub. We don't need to worry about the regular
|
||||
|
@ -781,8 +849,7 @@ bool DoWarmUpCounterFallbackOSR(JSContext* cx, BaselineFrame* frame,
|
|||
return true;
|
||||
}
|
||||
|
||||
bool ICWarmUpCounter_Fallback::Compiler::generateStubCode(
|
||||
MacroAssembler& masm) {
|
||||
bool FallbackICCodeCompiler::emit_WarmUpCounter() {
|
||||
// Push a stub frame so that we can perform a non-tail call.
|
||||
enterStubFrame(masm, R1.scratchReg());
|
||||
|
||||
|
@ -1005,12 +1072,14 @@ bool ICMonitoredFallbackStub::initMonitoringChain(JSContext* cx,
|
|||
JSScript* script) {
|
||||
MOZ_ASSERT(fallbackMonitorStub_ == nullptr);
|
||||
|
||||
ICTypeMonitor_Fallback::Compiler compiler(cx, this);
|
||||
ICStubSpace* space = script->icScript()->fallbackStubSpace();
|
||||
ICTypeMonitor_Fallback* stub = compiler.getStub(space);
|
||||
FallbackStubAllocator alloc(cx, *space);
|
||||
auto* stub = alloc.newStub<ICTypeMonitor_Fallback>(
|
||||
BaselineICFallbackKind::TypeMonitor, this);
|
||||
if (!stub) {
|
||||
return false;
|
||||
}
|
||||
|
||||
fallbackMonitorStub_ = stub;
|
||||
return true;
|
||||
}
|
||||
|
@ -1030,8 +1099,9 @@ bool ICMonitoredFallbackStub::addMonitorStubForValue(JSContext* cx,
|
|||
bool ICUpdatedStub::initUpdatingChain(JSContext* cx, ICStubSpace* space) {
|
||||
MOZ_ASSERT(firstUpdateStub_ == nullptr);
|
||||
|
||||
ICTypeUpdate_Fallback::Compiler compiler(cx);
|
||||
ICTypeUpdate_Fallback* stub = compiler.getStub(space);
|
||||
FallbackStubAllocator alloc(cx, *space);
|
||||
auto* stub =
|
||||
alloc.newStub<ICTypeUpdate_Fallback>(BaselineICFallbackKind::TypeUpdate);
|
||||
if (!stub) {
|
||||
return false;
|
||||
}
|
||||
|
@ -1049,6 +1119,17 @@ ICStubSpace* ICStubCompiler::StubSpaceForStub(bool makesGCCalls,
|
|||
return script->zone()->jitZone()->optimizedStubSpace();
|
||||
}
|
||||
|
||||
static void InitMacroAssemblerForICStub(StackMacroAssembler& masm) {
|
||||
#ifndef JS_USE_LINK_REGISTER
|
||||
// The first value contains the return addres,
|
||||
// which we pull into ICTailCallReg for tail calls.
|
||||
masm.adjustFrame(sizeof(intptr_t));
|
||||
#endif
|
||||
#ifdef JS_CODEGEN_ARM
|
||||
masm.setSecondScratchReg(BaselineSecondScratchReg);
|
||||
#endif
|
||||
}
|
||||
|
||||
JitCode* ICStubCompiler::getStubCode() {
|
||||
JitRealm* realm = cx->realm()->jitRealm();
|
||||
|
||||
|
@ -1062,14 +1143,7 @@ JitCode* ICStubCompiler::getStubCode() {
|
|||
// Compile new stubcode.
|
||||
JitContext jctx(cx, nullptr);
|
||||
StackMacroAssembler masm;
|
||||
#ifndef JS_USE_LINK_REGISTER
|
||||
// The first value contains the return addres,
|
||||
// which we pull into ICTailCallReg for tail calls.
|
||||
masm.adjustFrame(sizeof(intptr_t));
|
||||
#endif
|
||||
#ifdef JS_CODEGEN_ARM
|
||||
masm.setSecondScratchReg(BaselineSecondScratchReg);
|
||||
#endif
|
||||
InitMacroAssemblerForICStub(masm);
|
||||
|
||||
if (!generateStubCode(masm)) {
|
||||
return nullptr;
|
||||
|
@ -1085,10 +1159,6 @@ JitCode* ICStubCompiler::getStubCode() {
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
// After generating code, run postGenerateStubCode(). We must not fail
|
||||
// after this point.
|
||||
postGenerateStubCode(masm, newStubCode);
|
||||
|
||||
MOZ_ASSERT(entersStubFrame_ == ICStub::NonCacheIRStubMakesGCCalls(kind));
|
||||
MOZ_ASSERT(!inStubFrame_);
|
||||
|
||||
|
@ -1099,8 +1169,8 @@ JitCode* ICStubCompiler::getStubCode() {
|
|||
return newStubCode;
|
||||
}
|
||||
|
||||
bool ICStubCompiler::tailCallVMInternal(MacroAssembler& masm,
|
||||
TailCallVMFunctionId id) {
|
||||
bool ICStubCompilerBase::tailCallVMInternal(MacroAssembler& masm,
|
||||
TailCallVMFunctionId id) {
|
||||
TrampolinePtr code = cx->runtime()->jitRuntime()->getVMWrapper(id);
|
||||
const VMFunctionData& fun = GetVMFunction(id);
|
||||
MOZ_ASSERT(fun.expectTailCall == TailCall);
|
||||
|
@ -1109,7 +1179,7 @@ bool ICStubCompiler::tailCallVMInternal(MacroAssembler& masm,
|
|||
return true;
|
||||
}
|
||||
|
||||
bool ICStubCompiler::callVMInternal(MacroAssembler& masm, VMFunctionId id) {
|
||||
bool ICStubCompilerBase::callVMInternal(MacroAssembler& masm, VMFunctionId id) {
|
||||
MOZ_ASSERT(inStubFrame_);
|
||||
|
||||
TrampolinePtr code = cx->runtime()->jitRuntime()->getVMWrapper(id);
|
||||
|
@ -1120,18 +1190,19 @@ bool ICStubCompiler::callVMInternal(MacroAssembler& masm, VMFunctionId id) {
|
|||
}
|
||||
|
||||
template <typename Fn, Fn fn>
|
||||
bool ICStubCompiler::callVM(MacroAssembler& masm) {
|
||||
bool ICStubCompilerBase::callVM(MacroAssembler& masm) {
|
||||
VMFunctionId id = VMFunctionToId<Fn, fn>::id;
|
||||
return callVMInternal(masm, id);
|
||||
}
|
||||
|
||||
template <typename Fn, Fn fn>
|
||||
bool ICStubCompiler::tailCallVM(MacroAssembler& masm) {
|
||||
bool ICStubCompilerBase::tailCallVM(MacroAssembler& masm) {
|
||||
TailCallVMFunctionId id = TailCallVMFunctionToId<Fn, fn>::id;
|
||||
return tailCallVMInternal(masm, id);
|
||||
}
|
||||
|
||||
void ICStubCompiler::enterStubFrame(MacroAssembler& masm, Register scratch) {
|
||||
void ICStubCompilerBase::enterStubFrame(MacroAssembler& masm,
|
||||
Register scratch) {
|
||||
EmitBaselineEnterStubFrame(masm, scratch);
|
||||
#ifdef DEBUG
|
||||
framePushedAtEnterStubFrame_ = masm.framePushed();
|
||||
|
@ -1145,7 +1216,7 @@ void ICStubCompiler::enterStubFrame(MacroAssembler& masm, Register scratch) {
|
|||
#endif
|
||||
}
|
||||
|
||||
void ICStubCompiler::assumeStubFrame() {
|
||||
void ICStubCompilerBase::assumeStubFrame() {
|
||||
MOZ_ASSERT(!inStubFrame_);
|
||||
inStubFrame_ = true;
|
||||
|
||||
|
@ -1158,7 +1229,8 @@ void ICStubCompiler::assumeStubFrame() {
|
|||
#endif
|
||||
}
|
||||
|
||||
void ICStubCompiler::leaveStubFrame(MacroAssembler& masm, bool calledIntoIon) {
|
||||
void ICStubCompilerBase::leaveStubFrame(MacroAssembler& masm,
|
||||
bool calledIntoIon) {
|
||||
MOZ_ASSERT(entersStubFrame_ && inStubFrame_);
|
||||
inStubFrame_ = false;
|
||||
|
||||
|
@ -1171,7 +1243,8 @@ void ICStubCompiler::leaveStubFrame(MacroAssembler& masm, bool calledIntoIon) {
|
|||
EmitBaselineLeaveStubFrame(masm, calledIntoIon);
|
||||
}
|
||||
|
||||
void ICStubCompiler::pushStubPayload(MacroAssembler& masm, Register scratch) {
|
||||
void ICStubCompilerBase::pushStubPayload(MacroAssembler& masm,
|
||||
Register scratch) {
|
||||
if (inStubFrame_) {
|
||||
masm.loadPtr(Address(BaselineFrameReg, 0), scratch);
|
||||
masm.pushBaselineFramePtr(scratch, scratch);
|
||||
|
@ -1180,7 +1253,8 @@ void ICStubCompiler::pushStubPayload(MacroAssembler& masm, Register scratch) {
|
|||
}
|
||||
}
|
||||
|
||||
void ICStubCompiler::PushStubPayload(MacroAssembler& masm, Register scratch) {
|
||||
void ICStubCompilerBase::PushStubPayload(MacroAssembler& masm,
|
||||
Register scratch) {
|
||||
pushStubPayload(masm, scratch);
|
||||
masm.adjustFrame(sizeof(intptr_t));
|
||||
}
|
||||
|
@ -1427,7 +1501,7 @@ bool DoTypeMonitorFallback(JSContext* cx, BaselineFrame* frame,
|
|||
return stub->addMonitorStubForValue(cx, frame, types, value);
|
||||
}
|
||||
|
||||
bool ICTypeMonitor_Fallback::Compiler::generateStubCode(MacroAssembler& masm) {
|
||||
bool FallbackICCodeCompiler::emit_TypeMonitor() {
|
||||
MOZ_ASSERT(R0 == JSReturnOperand);
|
||||
|
||||
// Restore the tail call register.
|
||||
|
@ -1766,7 +1840,7 @@ bool DoTypeUpdateFallback(JSContext* cx, BaselineFrame* frame,
|
|||
return true;
|
||||
}
|
||||
|
||||
bool ICTypeUpdate_Fallback::Compiler::generateStubCode(MacroAssembler& masm) {
|
||||
bool FallbackICCodeCompiler::emit_TypeUpdate() {
|
||||
// Just store false into R1.scratchReg() and return.
|
||||
masm.move32(Imm32(0), R1.scratchReg());
|
||||
EmitReturnFromIC(masm);
|
||||
|
@ -1892,7 +1966,7 @@ bool DoToBoolFallback(JSContext* cx, BaselineFrame* frame,
|
|||
return true;
|
||||
}
|
||||
|
||||
bool ICToBool_Fallback::Compiler::generateStubCode(MacroAssembler& masm) {
|
||||
bool FallbackICCodeCompiler::emit_ToBool() {
|
||||
MOZ_ASSERT(R0 == JSReturnOperand);
|
||||
|
||||
// Restore the tail call register.
|
||||
|
@ -2106,14 +2180,14 @@ bool DoGetElemSuperFallback(JSContext* cx, BaselineFrame* frame,
|
|||
return true;
|
||||
}
|
||||
|
||||
bool ICGetElem_Fallback::Compiler::generateStubCode(MacroAssembler& masm) {
|
||||
bool FallbackICCodeCompiler::emitGetElem(bool hasReceiver) {
|
||||
MOZ_ASSERT(R0 == JSReturnOperand);
|
||||
|
||||
// Restore the tail call register.
|
||||
EmitRestoreTailCallReg(masm);
|
||||
|
||||
// Super property getters use a |this| that differs from base object
|
||||
if (hasReceiver_) {
|
||||
if (hasReceiver) {
|
||||
// State: receiver in R0, index in R1, obj on the stack
|
||||
|
||||
// Ensure stack is fully synced for the expression decompiler.
|
||||
|
@ -2157,7 +2231,13 @@ bool ICGetElem_Fallback::Compiler::generateStubCode(MacroAssembler& masm) {
|
|||
// Ion inlined frames. The return address pushed onto reconstructed stack
|
||||
// will point here.
|
||||
assumeStubFrame();
|
||||
bailoutReturnOffset_.bind(masm.currentOffset());
|
||||
if (hasReceiver) {
|
||||
code.initBailoutReturnOffset(BailoutReturnKind::GetElemSuper,
|
||||
masm.currentOffset());
|
||||
} else {
|
||||
code.initBailoutReturnOffset(BailoutReturnKind::GetElem,
|
||||
masm.currentOffset());
|
||||
}
|
||||
|
||||
leaveStubFrame(masm, true);
|
||||
|
||||
|
@ -2175,12 +2255,12 @@ bool ICGetElem_Fallback::Compiler::generateStubCode(MacroAssembler& masm) {
|
|||
return true;
|
||||
}
|
||||
|
||||
void ICGetElem_Fallback::Compiler::postGenerateStubCode(MacroAssembler& masm,
|
||||
Handle<JitCode*> code) {
|
||||
BailoutReturnStub kind = hasReceiver_ ? BailoutReturnStub::GetElemSuper
|
||||
: BailoutReturnStub::GetElem;
|
||||
void* address = code->raw() + bailoutReturnOffset_.offset();
|
||||
cx->realm()->jitRealm()->initBailoutReturnAddr(address, getKey(), kind);
|
||||
bool FallbackICCodeCompiler::emit_GetElem() {
|
||||
return emitGetElem(/* hasReceiver = */ false);
|
||||
}
|
||||
|
||||
bool FallbackICCodeCompiler::emit_GetElemSuper() {
|
||||
return emitGetElem(/* hasReceiver = */ true);
|
||||
}
|
||||
|
||||
static void SetUpdateStubData(ICCacheIR_Updated* stub,
|
||||
|
@ -2326,7 +2406,7 @@ bool DoSetElemFallback(JSContext* cx, BaselineFrame* frame,
|
|||
return true;
|
||||
}
|
||||
|
||||
bool ICSetElem_Fallback::Compiler::generateStubCode(MacroAssembler& masm) {
|
||||
bool FallbackICCodeCompiler::emit_SetElem() {
|
||||
MOZ_ASSERT(R0 == JSReturnOperand);
|
||||
|
||||
EmitRestoreTailCallReg(masm);
|
||||
|
@ -2467,7 +2547,7 @@ bool DoInFallback(JSContext* cx, BaselineFrame* frame, ICIn_Fallback* stub,
|
|||
return true;
|
||||
}
|
||||
|
||||
bool ICIn_Fallback::Compiler::generateStubCode(MacroAssembler& masm) {
|
||||
bool FallbackICCodeCompiler::emit_In() {
|
||||
EmitRestoreTailCallReg(masm);
|
||||
|
||||
// Sync for the decompiler.
|
||||
|
@ -2509,7 +2589,7 @@ bool DoHasOwnFallback(JSContext* cx, BaselineFrame* frame,
|
|||
return true;
|
||||
}
|
||||
|
||||
bool ICHasOwn_Fallback::Compiler::generateStubCode(MacroAssembler& masm) {
|
||||
bool FallbackICCodeCompiler::emit_HasOwn() {
|
||||
EmitRestoreTailCallReg(masm);
|
||||
|
||||
// Sync for the decompiler.
|
||||
|
@ -2572,7 +2652,7 @@ bool DoGetNameFallback(JSContext* cx, BaselineFrame* frame,
|
|||
return true;
|
||||
}
|
||||
|
||||
bool ICGetName_Fallback::Compiler::generateStubCode(MacroAssembler& masm) {
|
||||
bool FallbackICCodeCompiler::emit_GetName() {
|
||||
MOZ_ASSERT(R0 == JSReturnOperand);
|
||||
|
||||
EmitRestoreTailCallReg(masm);
|
||||
|
@ -2616,7 +2696,7 @@ bool DoBindNameFallback(JSContext* cx, BaselineFrame* frame,
|
|||
return true;
|
||||
}
|
||||
|
||||
bool ICBindName_Fallback::Compiler::generateStubCode(MacroAssembler& masm) {
|
||||
bool FallbackICCodeCompiler::emit_BindName() {
|
||||
MOZ_ASSERT(R0 == JSReturnOperand);
|
||||
|
||||
EmitRestoreTailCallReg(masm);
|
||||
|
@ -2662,7 +2742,7 @@ bool DoGetIntrinsicFallback(JSContext* cx, BaselineFrame* frame,
|
|||
return true;
|
||||
}
|
||||
|
||||
bool ICGetIntrinsic_Fallback::Compiler::generateStubCode(MacroAssembler& masm) {
|
||||
bool FallbackICCodeCompiler::emit_GetIntrinsic() {
|
||||
EmitRestoreTailCallReg(masm);
|
||||
|
||||
masm.push(ICStubReg);
|
||||
|
@ -2837,13 +2917,13 @@ bool DoGetPropSuperFallback(JSContext* cx, BaselineFrame* frame,
|
|||
return true;
|
||||
}
|
||||
|
||||
bool ICGetProp_Fallback::Compiler::generateStubCode(MacroAssembler& masm) {
|
||||
bool FallbackICCodeCompiler::emitGetProp(bool hasReceiver) {
|
||||
MOZ_ASSERT(R0 == JSReturnOperand);
|
||||
|
||||
EmitRestoreTailCallReg(masm);
|
||||
|
||||
// Super property getters use a |this| that differs from base object
|
||||
if (hasReceiver_) {
|
||||
if (hasReceiver) {
|
||||
// Push arguments.
|
||||
masm.pushValue(R0);
|
||||
masm.pushValue(R1);
|
||||
|
@ -2875,7 +2955,13 @@ bool ICGetProp_Fallback::Compiler::generateStubCode(MacroAssembler& masm) {
|
|||
// Ion inlined frames. The return address pushed onto reconstructed stack
|
||||
// will point here.
|
||||
assumeStubFrame();
|
||||
bailoutReturnOffset_.bind(masm.currentOffset());
|
||||
if (hasReceiver) {
|
||||
code.initBailoutReturnOffset(BailoutReturnKind::GetPropSuper,
|
||||
masm.currentOffset());
|
||||
} else {
|
||||
code.initBailoutReturnOffset(BailoutReturnKind::GetProp,
|
||||
masm.currentOffset());
|
||||
}
|
||||
|
||||
leaveStubFrame(masm, true);
|
||||
|
||||
|
@ -2893,12 +2979,12 @@ bool ICGetProp_Fallback::Compiler::generateStubCode(MacroAssembler& masm) {
|
|||
return true;
|
||||
}
|
||||
|
||||
void ICGetProp_Fallback::Compiler::postGenerateStubCode(MacroAssembler& masm,
|
||||
Handle<JitCode*> code) {
|
||||
BailoutReturnStub kind = hasReceiver_ ? BailoutReturnStub::GetPropSuper
|
||||
: BailoutReturnStub::GetProp;
|
||||
void* address = code->raw() + bailoutReturnOffset_.offset();
|
||||
cx->realm()->jitRealm()->initBailoutReturnAddr(address, getKey(), kind);
|
||||
bool FallbackICCodeCompiler::emit_GetProp() {
|
||||
return emitGetProp(/* hasReceiver = */ false);
|
||||
}
|
||||
|
||||
bool FallbackICCodeCompiler::emit_GetPropSuper() {
|
||||
return emitGetProp(/* hasReceiver = */ true);
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -3045,7 +3131,7 @@ bool DoSetPropFallback(JSContext* cx, BaselineFrame* frame,
|
|||
return true;
|
||||
}
|
||||
|
||||
bool ICSetProp_Fallback::Compiler::generateStubCode(MacroAssembler& masm) {
|
||||
bool FallbackICCodeCompiler::emit_SetProp() {
|
||||
MOZ_ASSERT(R0 == JSReturnOperand);
|
||||
|
||||
EmitRestoreTailCallReg(masm);
|
||||
|
@ -3079,7 +3165,8 @@ bool ICSetProp_Fallback::Compiler::generateStubCode(MacroAssembler& masm) {
|
|||
// Ion inlined frames. The return address pushed onto reconstructed stack
|
||||
// will point here.
|
||||
assumeStubFrame();
|
||||
bailoutReturnOffset_.bind(masm.currentOffset());
|
||||
code.initBailoutReturnOffset(BailoutReturnKind::SetProp,
|
||||
masm.currentOffset());
|
||||
|
||||
leaveStubFrame(masm, true);
|
||||
EmitReturnFromIC(masm);
|
||||
|
@ -3087,13 +3174,6 @@ bool ICSetProp_Fallback::Compiler::generateStubCode(MacroAssembler& masm) {
|
|||
return true;
|
||||
}
|
||||
|
||||
void ICSetProp_Fallback::Compiler::postGenerateStubCode(MacroAssembler& masm,
|
||||
Handle<JitCode*> code) {
|
||||
BailoutReturnStub kind = BailoutReturnStub::SetProp;
|
||||
void* address = code->raw() + bailoutReturnOffset_.offset();
|
||||
cx->realm()->jitRealm()->initBailoutReturnAddr(address, getKey(), kind);
|
||||
}
|
||||
|
||||
//
|
||||
// Call_Fallback
|
||||
//
|
||||
|
@ -3886,7 +3966,7 @@ bool DoSpreadCallFallback(JSContext* cx, BaselineFrame* frame,
|
|||
return true;
|
||||
}
|
||||
|
||||
void ICCallStubCompiler::pushCallArguments(MacroAssembler& masm,
|
||||
void ICStubCompilerBase::pushCallArguments(MacroAssembler& masm,
|
||||
AllocatableGeneralRegisterSet regs,
|
||||
Register argcReg, bool isJitCall,
|
||||
bool isConstructing) {
|
||||
|
@ -4195,7 +4275,7 @@ void ICCallStubCompiler::pushArrayArguments(
|
|||
masm.bind(©Done);
|
||||
}
|
||||
|
||||
bool ICCall_Fallback::Compiler::generateStubCode(MacroAssembler& masm) {
|
||||
bool FallbackICCodeCompiler::emitCall(bool isSpread, bool isConstructing) {
|
||||
MOZ_ASSERT(R0 == JSReturnOperand);
|
||||
|
||||
// Values are on the stack left-to-right. Calling convention wants them
|
||||
|
@ -4204,7 +4284,7 @@ bool ICCall_Fallback::Compiler::generateStubCode(MacroAssembler& masm) {
|
|||
|
||||
AllocatableGeneralRegisterSet regs(availableGeneralRegs(0));
|
||||
|
||||
if (MOZ_UNLIKELY(isSpread_)) {
|
||||
if (MOZ_UNLIKELY(isSpread)) {
|
||||
// Push a stub frame so that we can perform a non-tail call.
|
||||
enterStubFrame(masm, R1.scratchReg());
|
||||
|
||||
|
@ -4213,22 +4293,26 @@ bool ICCall_Fallback::Compiler::generateStubCode(MacroAssembler& masm) {
|
|||
// calling enterStubFrame.
|
||||
|
||||
// newTarget
|
||||
if (isConstructing_) {
|
||||
uint32_t valueOffset = 0;
|
||||
if (isConstructing) {
|
||||
masm.pushValue(Address(BaselineFrameReg, STUB_FRAME_SIZE));
|
||||
valueOffset++;
|
||||
}
|
||||
|
||||
// array
|
||||
uint32_t valueOffset = isConstructing_;
|
||||
masm.pushValue(Address(BaselineFrameReg,
|
||||
valueOffset++ * sizeof(Value) + STUB_FRAME_SIZE));
|
||||
valueOffset * sizeof(Value) + STUB_FRAME_SIZE));
|
||||
valueOffset++;
|
||||
|
||||
// this
|
||||
masm.pushValue(Address(BaselineFrameReg,
|
||||
valueOffset++ * sizeof(Value) + STUB_FRAME_SIZE));
|
||||
valueOffset * sizeof(Value) + STUB_FRAME_SIZE));
|
||||
valueOffset++;
|
||||
|
||||
// callee
|
||||
masm.pushValue(Address(BaselineFrameReg,
|
||||
valueOffset++ * sizeof(Value) + STUB_FRAME_SIZE));
|
||||
valueOffset * sizeof(Value) + STUB_FRAME_SIZE));
|
||||
valueOffset++;
|
||||
|
||||
masm.push(masm.getStackPointer());
|
||||
masm.push(ICStubReg);
|
||||
|
@ -4255,7 +4339,7 @@ bool ICCall_Fallback::Compiler::generateStubCode(MacroAssembler& masm) {
|
|||
regs.take(R0.scratchReg()); // argc.
|
||||
|
||||
pushCallArguments(masm, regs, R0.scratchReg(), /* isJitCall = */ false,
|
||||
isConstructing_);
|
||||
isConstructing);
|
||||
|
||||
masm.push(masm.getStackPointer());
|
||||
masm.push(R0.scratchReg());
|
||||
|
@ -4276,7 +4360,14 @@ bool ICCall_Fallback::Compiler::generateStubCode(MacroAssembler& masm) {
|
|||
// Ion inlined frames. The return address pushed onto reconstructed stack
|
||||
// will point here.
|
||||
assumeStubFrame();
|
||||
bailoutReturnOffset_.bind(masm.currentOffset());
|
||||
|
||||
MOZ_ASSERT(!isSpread);
|
||||
|
||||
if (isConstructing) {
|
||||
code.initBailoutReturnOffset(BailoutReturnKind::New, masm.currentOffset());
|
||||
} else {
|
||||
code.initBailoutReturnOffset(BailoutReturnKind::Call, masm.currentOffset());
|
||||
}
|
||||
|
||||
// Load passed-in ThisV into R1 just in case it's needed. Need to do this
|
||||
// before we leave the stub frame since that info will be lost.
|
||||
|
@ -4287,7 +4378,7 @@ bool ICCall_Fallback::Compiler::generateStubCode(MacroAssembler& masm) {
|
|||
|
||||
// If this is a |constructing| call, if the callee returns a non-object, we
|
||||
// replace it with the |this| object passed in.
|
||||
if (isConstructing_) {
|
||||
if (isConstructing) {
|
||||
MOZ_ASSERT(JSReturnOperand == R0);
|
||||
Label skipThisReplace;
|
||||
|
||||
|
@ -4315,16 +4406,20 @@ bool ICCall_Fallback::Compiler::generateStubCode(MacroAssembler& masm) {
|
|||
return true;
|
||||
}
|
||||
|
||||
void ICCall_Fallback::Compiler::postGenerateStubCode(MacroAssembler& masm,
|
||||
Handle<JitCode*> code) {
|
||||
if (MOZ_UNLIKELY(isSpread_)) {
|
||||
return;
|
||||
}
|
||||
bool FallbackICCodeCompiler::emit_Call() {
|
||||
return emitCall(/* isSpread = */ false, /* isConstructing = */ false);
|
||||
}
|
||||
|
||||
void* address = code->raw() + bailoutReturnOffset_.offset();
|
||||
BailoutReturnStub kind =
|
||||
isConstructing_ ? BailoutReturnStub::New : BailoutReturnStub::Call;
|
||||
cx->realm()->jitRealm()->initBailoutReturnAddr(address, getKey(), kind);
|
||||
bool FallbackICCodeCompiler::emit_CallConstructing() {
|
||||
return emitCall(/* isSpread = */ false, /* isConstructing = */ true);
|
||||
}
|
||||
|
||||
bool FallbackICCodeCompiler::emit_SpreadCall() {
|
||||
return emitCall(/* isSpread = */ true, /* isConstructing = */ false);
|
||||
}
|
||||
|
||||
bool FallbackICCodeCompiler::emit_SpreadCallConstructing() {
|
||||
return emitCall(/* isSpread = */ true, /* isConstructing = */ true);
|
||||
}
|
||||
|
||||
bool ICCallScriptedCompiler::generateStubCode(MacroAssembler& masm) {
|
||||
|
@ -5281,7 +5376,7 @@ bool DoGetIteratorFallback(JSContext* cx, BaselineFrame* frame,
|
|||
return true;
|
||||
}
|
||||
|
||||
bool ICGetIterator_Fallback::Compiler::generateStubCode(MacroAssembler& masm) {
|
||||
bool FallbackICCodeCompiler::emit_GetIterator() {
|
||||
EmitRestoreTailCallReg(masm);
|
||||
|
||||
// Sync stack for the decompiler.
|
||||
|
@ -5339,7 +5434,7 @@ bool DoInstanceOfFallback(JSContext* cx, BaselineFrame* frame,
|
|||
return true;
|
||||
}
|
||||
|
||||
bool ICInstanceOf_Fallback::Compiler::generateStubCode(MacroAssembler& masm) {
|
||||
bool FallbackICCodeCompiler::emit_InstanceOf() {
|
||||
EmitRestoreTailCallReg(masm);
|
||||
|
||||
// Sync stack for the decompiler.
|
||||
|
@ -5375,7 +5470,7 @@ bool DoTypeOfFallback(JSContext* cx, BaselineFrame* frame,
|
|||
return true;
|
||||
}
|
||||
|
||||
bool ICTypeOf_Fallback::Compiler::generateStubCode(MacroAssembler& masm) {
|
||||
bool FallbackICCodeCompiler::emit_TypeOf() {
|
||||
EmitRestoreTailCallReg(masm);
|
||||
|
||||
masm.pushValue(R0);
|
||||
|
@ -5464,7 +5559,7 @@ bool DoRestFallback(JSContext* cx, BaselineFrame* frame, ICRest_Fallback* stub,
|
|||
return true;
|
||||
}
|
||||
|
||||
bool ICRest_Fallback::Compiler::generateStubCode(MacroAssembler& masm) {
|
||||
bool FallbackICCodeCompiler::emit_Rest() {
|
||||
EmitRestoreTailCallReg(masm);
|
||||
|
||||
masm.push(ICStubReg);
|
||||
|
@ -5531,7 +5626,7 @@ bool DoUnaryArithFallback(JSContext* cx, BaselineFrame* frame,
|
|||
return true;
|
||||
}
|
||||
|
||||
bool ICUnaryArith_Fallback::Compiler::generateStubCode(MacroAssembler& masm) {
|
||||
bool FallbackICCodeCompiler::emit_UnaryArith() {
|
||||
MOZ_ASSERT(R0 == JSReturnOperand);
|
||||
|
||||
// Restore the tail call register.
|
||||
|
@ -5655,7 +5750,7 @@ bool DoBinaryArithFallback(JSContext* cx, BaselineFrame* frame,
|
|||
return true;
|
||||
}
|
||||
|
||||
bool ICBinaryArith_Fallback::Compiler::generateStubCode(MacroAssembler& masm) {
|
||||
bool FallbackICCodeCompiler::emit_BinaryArith() {
|
||||
MOZ_ASSERT(R0 == JSReturnOperand);
|
||||
|
||||
// Restore the tail call register.
|
||||
|
@ -5752,7 +5847,7 @@ bool DoCompareFallback(JSContext* cx, BaselineFrame* frame,
|
|||
return true;
|
||||
}
|
||||
|
||||
bool ICCompare_Fallback::Compiler::generateStubCode(MacroAssembler& masm) {
|
||||
bool FallbackICCodeCompiler::emit_Compare() {
|
||||
MOZ_ASSERT(R0 == JSReturnOperand);
|
||||
|
||||
// Restore the tail call register.
|
||||
|
@ -5813,7 +5908,7 @@ bool DoNewArrayFallback(JSContext* cx, BaselineFrame* frame,
|
|||
return true;
|
||||
}
|
||||
|
||||
bool ICNewArray_Fallback::Compiler::generateStubCode(MacroAssembler& masm) {
|
||||
bool FallbackICCodeCompiler::emit_NewArray() {
|
||||
EmitRestoreTailCallReg(masm);
|
||||
|
||||
masm.push(R0.scratchReg()); // length
|
||||
|
@ -5868,7 +5963,7 @@ bool DoNewObjectFallback(JSContext* cx, BaselineFrame* frame,
|
|||
return true;
|
||||
}
|
||||
|
||||
bool ICNewObject_Fallback::Compiler::generateStubCode(MacroAssembler& masm) {
|
||||
bool FallbackICCodeCompiler::emit_NewObject() {
|
||||
EmitRestoreTailCallReg(masm);
|
||||
|
||||
masm.push(ICStubReg); // stub.
|
||||
|
@ -5879,5 +5974,42 @@ bool ICNewObject_Fallback::Compiler::generateStubCode(MacroAssembler& masm) {
|
|||
return tailCallVM<Fn, DoNewObjectFallback>(masm);
|
||||
}
|
||||
|
||||
bool JitRuntime::generateBaselineICFallbackCode(JSContext* cx) {
|
||||
StackMacroAssembler masm;
|
||||
|
||||
BaselineICFallbackCode& fallbackCode = baselineICFallbackCode_.ref();
|
||||
FallbackICCodeCompiler compiler(cx, fallbackCode, masm);
|
||||
|
||||
JitSpew(JitSpew_Codegen, "# Emitting Baseline IC fallback code");
|
||||
|
||||
#define EMIT_CODE(kind) \
|
||||
{ \
|
||||
uint32_t offset = startTrampolineCode(masm); \
|
||||
InitMacroAssemblerForICStub(masm); \
|
||||
if (!compiler.emit_##kind()) { \
|
||||
return false; \
|
||||
} \
|
||||
fallbackCode.initOffset(BaselineICFallbackKind::kind, offset); \
|
||||
}
|
||||
IC_BASELINE_FALLBACK_CODE_KIND_LIST(EMIT_CODE)
|
||||
#undef EMIT_CODE
|
||||
|
||||
Linker linker(masm, "BaselineICFallback");
|
||||
JitCode* code = linker.newCode(cx, CodeKind::Other);
|
||||
if (!code) {
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef JS_ION_PERF
|
||||
writePerfSpewerJitCodeProfile(code, "BaselineICFallback");
|
||||
#endif
|
||||
#ifdef MOZ_VTUNE
|
||||
vtune::MarkStub(code, "BaselineICFallback");
|
||||
#endif
|
||||
|
||||
fallbackCode.initCode(code);
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace jit
|
||||
} // namespace js
|
||||
|
|
|
@ -503,7 +503,6 @@ class ICStub {
|
|||
Updated = 0x4
|
||||
};
|
||||
|
||||
void traceCode(JSTracer* trc, const char* name);
|
||||
void updateCode(JitCode* stubCode);
|
||||
void trace(JSTracer* trc);
|
||||
|
||||
|
@ -520,6 +519,16 @@ class ICStub {
|
|||
return result;
|
||||
}
|
||||
|
||||
template <typename T, typename... Args>
|
||||
static T* NewFallback(JSContext* cx, ICStubSpace* space, TrampolinePtr code,
|
||||
Args&&... args) {
|
||||
T* result = space->allocate<T>(code, std::forward<Args>(args)...);
|
||||
if (MOZ_UNLIKELY(!result)) {
|
||||
ReportOutOfMemory(cx);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
protected:
|
||||
// The raw jitcode to call for this stub.
|
||||
uint8_t* stubCode_;
|
||||
|
@ -537,8 +546,8 @@ class ICStub {
|
|||
Trait trait_ : 3;
|
||||
Kind kind_ : 13;
|
||||
|
||||
inline ICStub(Kind kind, JitCode* stubCode)
|
||||
: stubCode_(stubCode->raw()),
|
||||
inline ICStub(Kind kind, uint8_t* stubCode)
|
||||
: stubCode_(stubCode),
|
||||
next_(nullptr),
|
||||
extra_(0),
|
||||
trait_(Regular),
|
||||
|
@ -546,14 +555,22 @@ class ICStub {
|
|||
MOZ_ASSERT(stubCode != nullptr);
|
||||
}
|
||||
|
||||
inline ICStub(Kind kind, Trait trait, JitCode* stubCode)
|
||||
: stubCode_(stubCode->raw()),
|
||||
inline ICStub(Kind kind, JitCode* stubCode) : ICStub(kind, stubCode->raw()) {
|
||||
MOZ_ASSERT(stubCode != nullptr);
|
||||
}
|
||||
|
||||
inline ICStub(Kind kind, Trait trait, uint8_t* stubCode)
|
||||
: stubCode_(stubCode),
|
||||
next_(nullptr),
|
||||
extra_(0),
|
||||
trait_(trait),
|
||||
kind_(kind) {
|
||||
MOZ_ASSERT(stubCode != nullptr);
|
||||
}
|
||||
inline ICStub(Kind kind, Trait trait, JitCode* stubCode)
|
||||
: ICStub(kind, trait, stubCode->raw()) {
|
||||
MOZ_ASSERT(stubCode != nullptr);
|
||||
}
|
||||
|
||||
inline Trait trait() const {
|
||||
// Workaround for MSVC reading trait_ as signed value.
|
||||
|
@ -640,7 +657,15 @@ class ICStub {
|
|||
|
||||
inline ICStub** addressOfNext() { return &next_; }
|
||||
|
||||
inline JitCode* jitCode() { return JitCode::FromExecutable(stubCode_); }
|
||||
bool usesTrampolineCode() const {
|
||||
// All fallback code is stored in a single JitCode instance, so we can't
|
||||
// call JitCode::FromExecutable on the raw pointer.
|
||||
return isFallback() || isTypeMonitor_Fallback() || isTypeUpdate_Fallback();
|
||||
}
|
||||
JitCode* jitCode() {
|
||||
MOZ_ASSERT(!usesTrampolineCode());
|
||||
return JitCode::FromExecutable(stubCode_);
|
||||
}
|
||||
|
||||
inline uint8_t* rawStubCode() const { return stubCode_; }
|
||||
|
||||
|
@ -705,15 +730,15 @@ class ICFallbackStub : public ICStub {
|
|||
// last stub's "next_" field.
|
||||
ICStub** lastStubPtrAddr_;
|
||||
|
||||
ICFallbackStub(Kind kind, JitCode* stubCode)
|
||||
: ICStub(kind, ICStub::Fallback, stubCode),
|
||||
ICFallbackStub(Kind kind, TrampolinePtr stubCode)
|
||||
: ICStub(kind, ICStub::Fallback, stubCode.value),
|
||||
icEntry_(nullptr),
|
||||
state_(),
|
||||
enteredCount_(0),
|
||||
lastStubPtrAddr_(nullptr) {}
|
||||
|
||||
ICFallbackStub(Kind kind, Trait trait, JitCode* stubCode)
|
||||
: ICStub(kind, trait, stubCode),
|
||||
ICFallbackStub(Kind kind, Trait trait, TrampolinePtr stubCode)
|
||||
: ICStub(kind, trait, stubCode.value),
|
||||
icEntry_(nullptr),
|
||||
state_(),
|
||||
enteredCount_(0),
|
||||
|
@ -954,41 +979,21 @@ class ICCacheIR_Updated : public ICUpdatedStub,
|
|||
};
|
||||
|
||||
// Base class for stubcode compilers.
|
||||
class ICStubCompiler {
|
||||
// Prevent GC in the middle of stub compilation.
|
||||
js::gc::AutoSuppressGC suppressGC;
|
||||
|
||||
class ICStubCompilerBase {
|
||||
protected:
|
||||
JSContext* cx;
|
||||
ICStub::Kind kind;
|
||||
bool inStubFrame_;
|
||||
bool inStubFrame_ = false;
|
||||
|
||||
#ifdef DEBUG
|
||||
bool entersStubFrame_;
|
||||
uint32_t framePushedAtEnterStubFrame_;
|
||||
bool entersStubFrame_ = false;
|
||||
uint32_t framePushedAtEnterStubFrame_ = 0;
|
||||
#endif
|
||||
|
||||
// By default the stubcode key is just the kind.
|
||||
virtual int32_t getKey() const { return static_cast<int32_t>(kind); }
|
||||
explicit ICStubCompilerBase(JSContext* cx) : cx(cx) {}
|
||||
|
||||
virtual MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm) = 0;
|
||||
virtual void postGenerateStubCode(MacroAssembler& masm,
|
||||
Handle<JitCode*> genCode) {}
|
||||
|
||||
JitCode* getStubCode();
|
||||
|
||||
ICStubCompiler(JSContext* cx, ICStub::Kind kind)
|
||||
: suppressGC(cx),
|
||||
cx(cx),
|
||||
kind(kind),
|
||||
inStubFrame_(false)
|
||||
#ifdef DEBUG
|
||||
,
|
||||
entersStubFrame_(false),
|
||||
framePushedAtEnterStubFrame_(0)
|
||||
#endif
|
||||
{
|
||||
}
|
||||
void pushCallArguments(MacroAssembler& masm,
|
||||
AllocatableGeneralRegisterSet regs, Register argcReg,
|
||||
bool isJitCall, bool isConstructing = false);
|
||||
|
||||
// Push a payload specialized per compiler needed to execute stubs.
|
||||
void PushStubPayload(MacroAssembler& masm, Register scratch);
|
||||
|
@ -1056,6 +1061,24 @@ class ICStubCompiler {
|
|||
|
||||
return regs;
|
||||
}
|
||||
};
|
||||
|
||||
class ICStubCompiler : public ICStubCompilerBase {
|
||||
// Prevent GC in the middle of stub compilation.
|
||||
js::gc::AutoSuppressGC suppressGC;
|
||||
|
||||
protected:
|
||||
ICStub::Kind kind;
|
||||
|
||||
// By default the stubcode key is just the kind.
|
||||
virtual int32_t getKey() const { return static_cast<int32_t>(kind); }
|
||||
|
||||
virtual MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm) = 0;
|
||||
|
||||
JitCode* getStubCode();
|
||||
|
||||
ICStubCompiler(JSContext* cx, ICStub::Kind kind)
|
||||
: ICStubCompilerBase(cx), suppressGC(cx), kind(kind) {}
|
||||
|
||||
protected:
|
||||
template <typename T, typename... Args>
|
||||
|
@ -1080,23 +1103,8 @@ class ICStubCompiler {
|
|||
class ICWarmUpCounter_Fallback : public ICFallbackStub {
|
||||
friend class ICStubSpace;
|
||||
|
||||
explicit ICWarmUpCounter_Fallback(JitCode* stubCode)
|
||||
explicit ICWarmUpCounter_Fallback(TrampolinePtr stubCode)
|
||||
: ICFallbackStub(ICStub::WarmUpCounter_Fallback, stubCode) {}
|
||||
|
||||
public:
|
||||
// Compiler for this stub kind.
|
||||
class Compiler : public ICStubCompiler {
|
||||
protected:
|
||||
MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm) override;
|
||||
|
||||
public:
|
||||
explicit Compiler(JSContext* cx)
|
||||
: ICStubCompiler(cx, ICStub::WarmUpCounter_Fallback) {}
|
||||
|
||||
ICWarmUpCounter_Fallback* getStub(ICStubSpace* space) override {
|
||||
return newStub<ICWarmUpCounter_Fallback>(space, getStubCode());
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
// Monitored fallback stubs - as the name implies.
|
||||
|
@ -1106,7 +1114,7 @@ class ICMonitoredFallbackStub : public ICFallbackStub {
|
|||
// getFallbackMonitorStub if needed.
|
||||
ICTypeMonitor_Fallback* fallbackMonitorStub_;
|
||||
|
||||
ICMonitoredFallbackStub(Kind kind, JitCode* stubCode)
|
||||
ICMonitoredFallbackStub(Kind kind, TrampolinePtr stubCode)
|
||||
: ICFallbackStub(kind, ICStub::MonitoredFallback, stubCode),
|
||||
fallbackMonitorStub_(nullptr) {}
|
||||
|
||||
|
@ -1251,10 +1259,10 @@ class ICTypeMonitor_Fallback : public ICStub {
|
|||
|
||||
static const uint32_t BYTECODE_INDEX = (1 << 23) - 1;
|
||||
|
||||
ICTypeMonitor_Fallback(JitCode* stubCode,
|
||||
ICTypeMonitor_Fallback(TrampolinePtr stubCode,
|
||||
ICMonitoredFallbackStub* mainFallbackStub,
|
||||
uint32_t argumentIndex)
|
||||
: ICStub(ICStub::TypeMonitor_Fallback, stubCode),
|
||||
uint32_t argumentIndex = BYTECODE_INDEX)
|
||||
: ICStub(ICStub::TypeMonitor_Fallback, stubCode.value),
|
||||
mainFallbackStub_(mainFallbackStub),
|
||||
firstMonitorStub_(thisFromCtor()),
|
||||
lastMonitorStubPtrAddr_(nullptr),
|
||||
|
@ -1348,31 +1356,6 @@ class ICTypeMonitor_Fallback : public ICStub {
|
|||
HandleValue val);
|
||||
|
||||
void resetMonitorStubChain(Zone* zone);
|
||||
|
||||
// Compiler for this stub kind.
|
||||
class Compiler : public ICStubCompiler {
|
||||
ICMonitoredFallbackStub* mainFallbackStub_;
|
||||
uint32_t argumentIndex_;
|
||||
|
||||
protected:
|
||||
MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm) override;
|
||||
|
||||
public:
|
||||
Compiler(JSContext* cx, ICMonitoredFallbackStub* mainFallbackStub)
|
||||
: ICStubCompiler(cx, ICStub::TypeMonitor_Fallback),
|
||||
mainFallbackStub_(mainFallbackStub),
|
||||
argumentIndex_(BYTECODE_INDEX) {}
|
||||
|
||||
Compiler(JSContext* cx, uint32_t argumentIndex)
|
||||
: ICStubCompiler(cx, ICStub::TypeMonitor_Fallback),
|
||||
mainFallbackStub_(nullptr),
|
||||
argumentIndex_(argumentIndex) {}
|
||||
|
||||
ICTypeMonitor_Fallback* getStub(ICStubSpace* space) override {
|
||||
return newStub<ICTypeMonitor_Fallback>(space, getStubCode(),
|
||||
mainFallbackStub_, argumentIndex_);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
class ICTypeMonitor_PrimitiveSet : public TypeCheckPrimitiveSetStub {
|
||||
|
@ -1494,23 +1477,8 @@ class ICTypeMonitor_AnyValue : public ICStub {
|
|||
class ICTypeUpdate_Fallback : public ICStub {
|
||||
friend class ICStubSpace;
|
||||
|
||||
explicit ICTypeUpdate_Fallback(JitCode* stubCode)
|
||||
: ICStub(ICStub::TypeUpdate_Fallback, stubCode) {}
|
||||
|
||||
public:
|
||||
// Compiler for this stub kind.
|
||||
class Compiler : public ICStubCompiler {
|
||||
protected:
|
||||
MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm) override;
|
||||
|
||||
public:
|
||||
explicit Compiler(JSContext* cx)
|
||||
: ICStubCompiler(cx, ICStub::TypeUpdate_Fallback) {}
|
||||
|
||||
ICTypeUpdate_Fallback* getStub(ICStubSpace* space) override {
|
||||
return newStub<ICTypeUpdate_Fallback>(space, getStubCode());
|
||||
}
|
||||
};
|
||||
explicit ICTypeUpdate_Fallback(TrampolinePtr stubCode)
|
||||
: ICStub(ICStub::TypeUpdate_Fallback, stubCode.value) {}
|
||||
};
|
||||
|
||||
class ICTypeUpdate_PrimitiveSet : public TypeCheckPrimitiveSetStub {
|
||||
|
@ -1633,25 +1601,11 @@ class ICTypeUpdate_AnyValue : public ICStub {
|
|||
class ICToBool_Fallback : public ICFallbackStub {
|
||||
friend class ICStubSpace;
|
||||
|
||||
explicit ICToBool_Fallback(JitCode* stubCode)
|
||||
explicit ICToBool_Fallback(TrampolinePtr stubCode)
|
||||
: ICFallbackStub(ICStub::ToBool_Fallback, stubCode) {}
|
||||
|
||||
public:
|
||||
static const uint32_t MAX_OPTIMIZED_STUBS = 8;
|
||||
|
||||
// Compiler for this stub kind.
|
||||
class Compiler : public ICStubCompiler {
|
||||
protected:
|
||||
MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm) override;
|
||||
|
||||
public:
|
||||
explicit Compiler(JSContext* cx)
|
||||
: ICStubCompiler(cx, ICStub::ToBool_Fallback) {}
|
||||
|
||||
ICStub* getStub(ICStubSpace* space) override {
|
||||
return newStub<ICToBool_Fallback>(space, getStubCode());
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
// GetElem
|
||||
|
@ -1661,7 +1615,7 @@ class ICToBool_Fallback : public ICFallbackStub {
|
|||
class ICGetElem_Fallback : public ICMonitoredFallbackStub {
|
||||
friend class ICStubSpace;
|
||||
|
||||
explicit ICGetElem_Fallback(JitCode* stubCode)
|
||||
explicit ICGetElem_Fallback(TrampolinePtr stubCode)
|
||||
: ICMonitoredFallbackStub(ICStub::GetElem_Fallback, stubCode) {}
|
||||
|
||||
static const uint16_t EXTRA_NEGATIVE_INDEX = 0x1;
|
||||
|
@ -1673,30 +1627,6 @@ class ICGetElem_Fallback : public ICMonitoredFallbackStub {
|
|||
|
||||
void setSawNonIntegerIndex() { extra_ |= SAW_NON_INTEGER_INDEX_BIT; }
|
||||
bool sawNonIntegerIndex() const { return extra_ & SAW_NON_INTEGER_INDEX_BIT; }
|
||||
|
||||
// Compiler for this stub kind.
|
||||
class Compiler : public ICStubCompiler {
|
||||
protected:
|
||||
CodeOffset bailoutReturnOffset_;
|
||||
bool hasReceiver_;
|
||||
MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm) override;
|
||||
void postGenerateStubCode(MacroAssembler& masm,
|
||||
Handle<JitCode*> code) override;
|
||||
|
||||
virtual int32_t getKey() const override {
|
||||
return static_cast<int32_t>(kind) |
|
||||
(static_cast<int32_t>(hasReceiver_) << 16);
|
||||
}
|
||||
|
||||
public:
|
||||
explicit Compiler(JSContext* cx, bool hasReceiver = false)
|
||||
: ICStubCompiler(cx, ICStub::GetElem_Fallback),
|
||||
hasReceiver_(hasReceiver) {}
|
||||
|
||||
ICStub* getStub(ICStubSpace* space) override {
|
||||
return newStub<ICGetElem_Fallback>(space, getStubCode());
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
// SetElem
|
||||
|
@ -1706,7 +1636,7 @@ class ICGetElem_Fallback : public ICMonitoredFallbackStub {
|
|||
class ICSetElem_Fallback : public ICFallbackStub {
|
||||
friend class ICStubSpace;
|
||||
|
||||
explicit ICSetElem_Fallback(JitCode* stubCode)
|
||||
explicit ICSetElem_Fallback(TrampolinePtr stubCode)
|
||||
: ICFallbackStub(ICStub::SetElem_Fallback, stubCode) {}
|
||||
|
||||
static const size_t HasDenseAddFlag = 0x1;
|
||||
|
@ -1718,20 +1648,6 @@ class ICSetElem_Fallback : public ICFallbackStub {
|
|||
|
||||
void noteHasTypedArrayOOB() { extra_ |= HasTypedArrayOOBFlag; }
|
||||
bool hasTypedArrayOOB() const { return extra_ & HasTypedArrayOOBFlag; }
|
||||
|
||||
// Compiler for this stub kind.
|
||||
class Compiler : public ICStubCompiler {
|
||||
protected:
|
||||
MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm) override;
|
||||
|
||||
public:
|
||||
explicit Compiler(JSContext* cx)
|
||||
: ICStubCompiler(cx, ICStub::SetElem_Fallback) {}
|
||||
|
||||
ICStub* getStub(ICStubSpace* space) override {
|
||||
return newStub<ICSetElem_Fallback>(space, getStubCode());
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
// In
|
||||
|
@ -1739,22 +1655,8 @@ class ICSetElem_Fallback : public ICFallbackStub {
|
|||
class ICIn_Fallback : public ICFallbackStub {
|
||||
friend class ICStubSpace;
|
||||
|
||||
explicit ICIn_Fallback(JitCode* stubCode)
|
||||
explicit ICIn_Fallback(TrampolinePtr stubCode)
|
||||
: ICFallbackStub(ICStub::In_Fallback, stubCode) {}
|
||||
|
||||
public:
|
||||
class Compiler : public ICStubCompiler {
|
||||
protected:
|
||||
MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm) override;
|
||||
|
||||
public:
|
||||
explicit Compiler(JSContext* cx)
|
||||
: ICStubCompiler(cx, ICStub::In_Fallback) {}
|
||||
|
||||
ICStub* getStub(ICStubSpace* space) override {
|
||||
return newStub<ICIn_Fallback>(space, getStubCode());
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
// HasOwn
|
||||
|
@ -1762,22 +1664,8 @@ class ICIn_Fallback : public ICFallbackStub {
|
|||
class ICHasOwn_Fallback : public ICFallbackStub {
|
||||
friend class ICStubSpace;
|
||||
|
||||
explicit ICHasOwn_Fallback(JitCode* stubCode)
|
||||
explicit ICHasOwn_Fallback(TrampolinePtr stubCode)
|
||||
: ICFallbackStub(ICStub::HasOwn_Fallback, stubCode) {}
|
||||
|
||||
public:
|
||||
class Compiler : public ICStubCompiler {
|
||||
protected:
|
||||
MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm) override;
|
||||
|
||||
public:
|
||||
explicit Compiler(JSContext* cx)
|
||||
: ICStubCompiler(cx, ICStub::HasOwn_Fallback) {}
|
||||
|
||||
ICStub* getStub(ICStubSpace* space) override {
|
||||
return newStub<ICHasOwn_Fallback>(space, getStubCode());
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
// GetName
|
||||
|
@ -1786,22 +1674,8 @@ class ICHasOwn_Fallback : public ICFallbackStub {
|
|||
class ICGetName_Fallback : public ICMonitoredFallbackStub {
|
||||
friend class ICStubSpace;
|
||||
|
||||
explicit ICGetName_Fallback(JitCode* stubCode)
|
||||
explicit ICGetName_Fallback(TrampolinePtr stubCode)
|
||||
: ICMonitoredFallbackStub(ICStub::GetName_Fallback, stubCode) {}
|
||||
|
||||
public:
|
||||
class Compiler : public ICStubCompiler {
|
||||
protected:
|
||||
MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm) override;
|
||||
|
||||
public:
|
||||
explicit Compiler(JSContext* cx)
|
||||
: ICStubCompiler(cx, ICStub::GetName_Fallback) {}
|
||||
|
||||
ICStub* getStub(ICStubSpace* space) override {
|
||||
return newStub<ICGetName_Fallback>(space, getStubCode());
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
// BindName
|
||||
|
@ -1809,22 +1683,8 @@ class ICGetName_Fallback : public ICMonitoredFallbackStub {
|
|||
class ICBindName_Fallback : public ICFallbackStub {
|
||||
friend class ICStubSpace;
|
||||
|
||||
explicit ICBindName_Fallback(JitCode* stubCode)
|
||||
explicit ICBindName_Fallback(TrampolinePtr stubCode)
|
||||
: ICFallbackStub(ICStub::BindName_Fallback, stubCode) {}
|
||||
|
||||
public:
|
||||
class Compiler : public ICStubCompiler {
|
||||
protected:
|
||||
MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm) override;
|
||||
|
||||
public:
|
||||
explicit Compiler(JSContext* cx)
|
||||
: ICStubCompiler(cx, ICStub::BindName_Fallback) {}
|
||||
|
||||
ICStub* getStub(ICStubSpace* space) override {
|
||||
return newStub<ICBindName_Fallback>(space, getStubCode());
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
// GetIntrinsic
|
||||
|
@ -1832,22 +1692,8 @@ class ICBindName_Fallback : public ICFallbackStub {
|
|||
class ICGetIntrinsic_Fallback : public ICMonitoredFallbackStub {
|
||||
friend class ICStubSpace;
|
||||
|
||||
explicit ICGetIntrinsic_Fallback(JitCode* stubCode)
|
||||
explicit ICGetIntrinsic_Fallback(TrampolinePtr stubCode)
|
||||
: ICMonitoredFallbackStub(ICStub::GetIntrinsic_Fallback, stubCode) {}
|
||||
|
||||
public:
|
||||
class Compiler : public ICStubCompiler {
|
||||
protected:
|
||||
MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm) override;
|
||||
|
||||
public:
|
||||
explicit Compiler(JSContext* cx)
|
||||
: ICStubCompiler(cx, ICStub::GetIntrinsic_Fallback) {}
|
||||
|
||||
ICStub* getStub(ICStubSpace* space) override {
|
||||
return newStub<ICGetIntrinsic_Fallback>(space, getStubCode());
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
// GetProp
|
||||
|
@ -1857,7 +1703,7 @@ class ICGetIntrinsic_Fallback : public ICMonitoredFallbackStub {
|
|||
class ICGetProp_Fallback : public ICMonitoredFallbackStub {
|
||||
friend class ICStubSpace;
|
||||
|
||||
explicit ICGetProp_Fallback(JitCode* stubCode)
|
||||
explicit ICGetProp_Fallback(TrampolinePtr stubCode)
|
||||
: ICMonitoredFallbackStub(ICStub::GetProp_Fallback, stubCode) {}
|
||||
|
||||
public:
|
||||
|
@ -1867,29 +1713,6 @@ class ICGetProp_Fallback : public ICMonitoredFallbackStub {
|
|||
bool hasAccessedGetter() const {
|
||||
return extra_ & (1u << ACCESSED_GETTER_BIT);
|
||||
}
|
||||
|
||||
class Compiler : public ICStubCompiler {
|
||||
protected:
|
||||
CodeOffset bailoutReturnOffset_;
|
||||
bool hasReceiver_;
|
||||
MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm) override;
|
||||
void postGenerateStubCode(MacroAssembler& masm,
|
||||
Handle<JitCode*> code) override;
|
||||
|
||||
virtual int32_t getKey() const override {
|
||||
return static_cast<int32_t>(kind) |
|
||||
(static_cast<int32_t>(hasReceiver_) << 16);
|
||||
}
|
||||
|
||||
public:
|
||||
explicit Compiler(JSContext* cx, bool hasReceiver = false)
|
||||
: ICStubCompiler(cx, ICStub::GetProp_Fallback),
|
||||
hasReceiver_(hasReceiver) {}
|
||||
|
||||
ICStub* getStub(ICStubSpace* space) override {
|
||||
return newStub<ICGetProp_Fallback>(space, getStubCode());
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
// SetProp
|
||||
|
@ -1901,25 +1724,8 @@ class ICGetProp_Fallback : public ICMonitoredFallbackStub {
|
|||
class ICSetProp_Fallback : public ICFallbackStub {
|
||||
friend class ICStubSpace;
|
||||
|
||||
explicit ICSetProp_Fallback(JitCode* stubCode)
|
||||
explicit ICSetProp_Fallback(TrampolinePtr stubCode)
|
||||
: ICFallbackStub(ICStub::SetProp_Fallback, stubCode) {}
|
||||
|
||||
public:
|
||||
class Compiler : public ICStubCompiler {
|
||||
protected:
|
||||
CodeOffset bailoutReturnOffset_;
|
||||
MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm) override;
|
||||
void postGenerateStubCode(MacroAssembler& masm,
|
||||
Handle<JitCode*> code) override;
|
||||
|
||||
public:
|
||||
explicit Compiler(JSContext* cx)
|
||||
: ICStubCompiler(cx, ICStub::SetProp_Fallback) {}
|
||||
|
||||
ICStub* getStub(ICStubSpace* space) override {
|
||||
return newStub<ICSetProp_Fallback>(space, getStubCode());
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
// Call
|
||||
|
@ -1939,9 +1745,6 @@ class ICCallStubCompiler : public ICStubCompiler {
|
|||
|
||||
enum FunApplyThing { FunApply_MagicArgs, FunApply_Array };
|
||||
|
||||
void pushCallArguments(MacroAssembler& masm,
|
||||
AllocatableGeneralRegisterSet regs, Register argcReg,
|
||||
bool isJitCall, bool isConstructing = false);
|
||||
void pushSpreadCallArguments(MacroAssembler& masm,
|
||||
AllocatableGeneralRegisterSet regs,
|
||||
Register argcReg, bool isJitCall,
|
||||
|
@ -1964,7 +1767,7 @@ class ICCall_Fallback : public ICMonitoredFallbackStub {
|
|||
static const uint32_t MAX_OPTIMIZED_STUBS = 16;
|
||||
|
||||
private:
|
||||
explicit ICCall_Fallback(JitCode* stubCode)
|
||||
explicit ICCall_Fallback(TrampolinePtr stubCode)
|
||||
: ICMonitoredFallbackStub(ICStub::Call_Fallback, stubCode) {}
|
||||
|
||||
public:
|
||||
|
@ -1973,33 +1776,6 @@ class ICCall_Fallback : public ICMonitoredFallbackStub {
|
|||
// Return hasStub(Call_AnyNative) after Call_AnyNative stub is added.
|
||||
return false;
|
||||
}
|
||||
|
||||
// Compiler for this stub kind.
|
||||
class Compiler : public ICCallStubCompiler {
|
||||
protected:
|
||||
bool isConstructing_;
|
||||
bool isSpread_;
|
||||
CodeOffset bailoutReturnOffset_;
|
||||
MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm) override;
|
||||
void postGenerateStubCode(MacroAssembler& masm,
|
||||
Handle<JitCode*> code) override;
|
||||
|
||||
virtual int32_t getKey() const override {
|
||||
return static_cast<int32_t>(kind) |
|
||||
(static_cast<int32_t>(isSpread_) << 16) |
|
||||
(static_cast<int32_t>(isConstructing_) << 17);
|
||||
}
|
||||
|
||||
public:
|
||||
Compiler(JSContext* cx, bool isConstructing, bool isSpread)
|
||||
: ICCallStubCompiler(cx, ICStub::Call_Fallback),
|
||||
isConstructing_(isConstructing),
|
||||
isSpread_(isSpread) {}
|
||||
|
||||
ICStub* getStub(ICStubSpace* space) override {
|
||||
return newStub<ICCall_Fallback>(space, getStubCode());
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
class ICCall_Scripted : public ICMonitoredStub {
|
||||
|
@ -2421,22 +2197,8 @@ class ICCall_ConstStringSplit : public ICMonitoredStub {
|
|||
class ICGetIterator_Fallback : public ICFallbackStub {
|
||||
friend class ICStubSpace;
|
||||
|
||||
explicit ICGetIterator_Fallback(JitCode* stubCode)
|
||||
explicit ICGetIterator_Fallback(TrampolinePtr stubCode)
|
||||
: ICFallbackStub(ICStub::GetIterator_Fallback, stubCode) {}
|
||||
|
||||
public:
|
||||
class Compiler : public ICStubCompiler {
|
||||
protected:
|
||||
MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm) override;
|
||||
|
||||
public:
|
||||
explicit Compiler(JSContext* cx)
|
||||
: ICStubCompiler(cx, ICStub::GetIterator_Fallback) {}
|
||||
|
||||
ICStub* getStub(ICStubSpace* space) override {
|
||||
return newStub<ICGetIterator_Fallback>(space, getStubCode());
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
// InstanceOf
|
||||
|
@ -2444,22 +2206,8 @@ class ICGetIterator_Fallback : public ICFallbackStub {
|
|||
class ICInstanceOf_Fallback : public ICFallbackStub {
|
||||
friend class ICStubSpace;
|
||||
|
||||
explicit ICInstanceOf_Fallback(JitCode* stubCode)
|
||||
explicit ICInstanceOf_Fallback(TrampolinePtr stubCode)
|
||||
: ICFallbackStub(ICStub::InstanceOf_Fallback, stubCode) {}
|
||||
|
||||
public:
|
||||
class Compiler : public ICStubCompiler {
|
||||
protected:
|
||||
MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm) override;
|
||||
|
||||
public:
|
||||
explicit Compiler(JSContext* cx)
|
||||
: ICStubCompiler(cx, ICStub::InstanceOf_Fallback) {}
|
||||
|
||||
ICStub* getStub(ICStubSpace* space) override {
|
||||
return newStub<ICInstanceOf_Fallback>(space, getStubCode());
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
// TypeOf
|
||||
|
@ -2468,24 +2216,11 @@ class ICInstanceOf_Fallback : public ICFallbackStub {
|
|||
class ICTypeOf_Fallback : public ICFallbackStub {
|
||||
friend class ICStubSpace;
|
||||
|
||||
explicit ICTypeOf_Fallback(JitCode* stubCode)
|
||||
explicit ICTypeOf_Fallback(TrampolinePtr stubCode)
|
||||
: ICFallbackStub(ICStub::TypeOf_Fallback, stubCode) {}
|
||||
|
||||
public:
|
||||
static const uint32_t MAX_OPTIMIZED_STUBS = 6;
|
||||
|
||||
class Compiler : public ICStubCompiler {
|
||||
protected:
|
||||
MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm) override;
|
||||
|
||||
public:
|
||||
explicit Compiler(JSContext* cx)
|
||||
: ICStubCompiler(cx, ICStub::TypeOf_Fallback) {}
|
||||
|
||||
ICStub* getStub(ICStubSpace* space) override {
|
||||
return newStub<ICTypeOf_Fallback>(space, getStubCode());
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
class ICRest_Fallback : public ICFallbackStub {
|
||||
|
@ -2493,7 +2228,7 @@ class ICRest_Fallback : public ICFallbackStub {
|
|||
|
||||
GCPtrArrayObject templateObject_;
|
||||
|
||||
ICRest_Fallback(JitCode* stubCode, ArrayObject* templateObject)
|
||||
ICRest_Fallback(TrampolinePtr stubCode, ArrayObject* templateObject)
|
||||
: ICFallbackStub(ICStub::Rest_Fallback, stubCode),
|
||||
templateObject_(templateObject) {}
|
||||
|
||||
|
@ -2501,21 +2236,6 @@ class ICRest_Fallback : public ICFallbackStub {
|
|||
static const uint32_t MAX_OPTIMIZED_STUBS = 8;
|
||||
|
||||
GCPtrArrayObject& templateObject() { return templateObject_; }
|
||||
|
||||
class Compiler : public ICStubCompiler {
|
||||
protected:
|
||||
RootedArrayObject templateObject;
|
||||
MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm) override;
|
||||
|
||||
public:
|
||||
Compiler(JSContext* cx, ArrayObject* templateObject)
|
||||
: ICStubCompiler(cx, ICStub::Rest_Fallback),
|
||||
templateObject(cx, templateObject) {}
|
||||
|
||||
ICStub* getStub(ICStubSpace* space) override {
|
||||
return newStub<ICRest_Fallback>(space, getStubCode(), templateObject);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
// UnaryArith
|
||||
|
@ -2527,7 +2247,7 @@ class ICRest_Fallback : public ICFallbackStub {
|
|||
class ICUnaryArith_Fallback : public ICFallbackStub {
|
||||
friend class ICStubSpace;
|
||||
|
||||
explicit ICUnaryArith_Fallback(JitCode* stubCode)
|
||||
explicit ICUnaryArith_Fallback(TrampolinePtr stubCode)
|
||||
: ICFallbackStub(UnaryArith_Fallback, stubCode) {
|
||||
extra_ = 0;
|
||||
}
|
||||
|
@ -2535,20 +2255,6 @@ class ICUnaryArith_Fallback : public ICFallbackStub {
|
|||
public:
|
||||
bool sawDoubleResult() { return extra_; }
|
||||
void setSawDoubleResult() { extra_ = 1; }
|
||||
|
||||
// Compiler for this stub kind.
|
||||
class Compiler : public ICStubCompiler {
|
||||
protected:
|
||||
MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm) override;
|
||||
|
||||
public:
|
||||
explicit Compiler(JSContext* cx)
|
||||
: ICStubCompiler(cx, ICStub::UnaryArith_Fallback) {}
|
||||
|
||||
ICStub* getStub(ICStubSpace* space) override {
|
||||
return newStub<ICUnaryArith_Fallback>(space, getStubCode());
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
// Compare
|
||||
|
@ -2564,23 +2270,8 @@ class ICUnaryArith_Fallback : public ICFallbackStub {
|
|||
class ICCompare_Fallback : public ICFallbackStub {
|
||||
friend class ICStubSpace;
|
||||
|
||||
explicit ICCompare_Fallback(JitCode* stubCode)
|
||||
explicit ICCompare_Fallback(TrampolinePtr stubCode)
|
||||
: ICFallbackStub(ICStub::Compare_Fallback, stubCode) {}
|
||||
|
||||
public:
|
||||
// Compiler for this stub kind.
|
||||
class Compiler : public ICStubCompiler {
|
||||
protected:
|
||||
MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm) override;
|
||||
|
||||
public:
|
||||
explicit Compiler(JSContext* cx)
|
||||
: ICStubCompiler(cx, ICStub::Compare_Fallback) {}
|
||||
|
||||
ICStub* getStub(ICStubSpace* space) override {
|
||||
return newStub<ICCompare_Fallback>(space, getStubCode());
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
// BinaryArith
|
||||
|
@ -2591,7 +2282,7 @@ class ICCompare_Fallback : public ICFallbackStub {
|
|||
class ICBinaryArith_Fallback : public ICFallbackStub {
|
||||
friend class ICStubSpace;
|
||||
|
||||
explicit ICBinaryArith_Fallback(JitCode* stubCode)
|
||||
explicit ICBinaryArith_Fallback(TrampolinePtr stubCode)
|
||||
: ICFallbackStub(BinaryArith_Fallback, stubCode) {
|
||||
extra_ = 0;
|
||||
}
|
||||
|
@ -2603,20 +2294,6 @@ class ICBinaryArith_Fallback : public ICFallbackStub {
|
|||
|
||||
bool sawDoubleResult() const { return extra_ & SAW_DOUBLE_RESULT_BIT; }
|
||||
void setSawDoubleResult() { extra_ |= SAW_DOUBLE_RESULT_BIT; }
|
||||
|
||||
// Compiler for this stub kind.
|
||||
class Compiler : public ICStubCompiler {
|
||||
protected:
|
||||
MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm) override;
|
||||
|
||||
public:
|
||||
explicit Compiler(JSContext* cx)
|
||||
: ICStubCompiler(cx, ICStub::BinaryArith_Fallback) {}
|
||||
|
||||
ICStub* getStub(ICStubSpace* space) override {
|
||||
return newStub<ICBinaryArith_Fallback>(space, getStubCode());
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
// JSOP_NEWARRAY
|
||||
|
@ -2630,26 +2307,12 @@ class ICNewArray_Fallback : public ICFallbackStub {
|
|||
// template object itself is not.
|
||||
GCPtrObjectGroup templateGroup_;
|
||||
|
||||
ICNewArray_Fallback(JitCode* stubCode, ObjectGroup* templateGroup)
|
||||
ICNewArray_Fallback(TrampolinePtr stubCode, ObjectGroup* templateGroup)
|
||||
: ICFallbackStub(ICStub::NewArray_Fallback, stubCode),
|
||||
templateObject_(nullptr),
|
||||
templateGroup_(templateGroup) {}
|
||||
|
||||
public:
|
||||
class Compiler : public ICStubCompiler {
|
||||
RootedObjectGroup templateGroup;
|
||||
MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm) override;
|
||||
|
||||
public:
|
||||
Compiler(JSContext* cx, ObjectGroup* templateGroup)
|
||||
: ICStubCompiler(cx, ICStub::NewArray_Fallback),
|
||||
templateGroup(cx, templateGroup) {}
|
||||
|
||||
ICStub* getStub(ICStubSpace* space) override {
|
||||
return newStub<ICNewArray_Fallback>(space, getStubCode(), templateGroup);
|
||||
}
|
||||
};
|
||||
|
||||
GCPtrObject& templateObject() { return templateObject_; }
|
||||
|
||||
void setTemplateObject(JSObject* obj) {
|
||||
|
@ -2672,23 +2335,11 @@ class ICNewObject_Fallback : public ICFallbackStub {
|
|||
|
||||
GCPtrObject templateObject_;
|
||||
|
||||
explicit ICNewObject_Fallback(JitCode* stubCode)
|
||||
explicit ICNewObject_Fallback(TrampolinePtr stubCode)
|
||||
: ICFallbackStub(ICStub::NewObject_Fallback, stubCode),
|
||||
templateObject_(nullptr) {}
|
||||
|
||||
public:
|
||||
class Compiler : public ICStubCompiler {
|
||||
MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm) override;
|
||||
|
||||
public:
|
||||
explicit Compiler(JSContext* cx)
|
||||
: ICStubCompiler(cx, ICStub::NewObject_Fallback) {}
|
||||
|
||||
ICStub* getStub(ICStubSpace* space) override {
|
||||
return newStub<ICNewObject_Fallback>(space, getStubCode());
|
||||
}
|
||||
};
|
||||
|
||||
GCPtrObject& templateObject() { return templateObject_; }
|
||||
|
||||
void setTemplateObject(JSObject* obj) { templateObject_ = obj; }
|
||||
|
|
|
@ -10,7 +10,8 @@
|
|||
namespace js {
|
||||
namespace jit {
|
||||
|
||||
// List of IC stub kinds that can only run in Baseline.
|
||||
// List of Baseline IC stub kinds. The stub kind determines the structure of the
|
||||
// ICStub data.
|
||||
#define IC_BASELINE_STUB_KIND_LIST(_) \
|
||||
_(WarmUpCounter_Fallback) \
|
||||
\
|
||||
|
@ -60,7 +61,6 @@ namespace jit {
|
|||
_(GetIterator_Fallback) \
|
||||
\
|
||||
_(InstanceOf_Fallback) \
|
||||
_(InstanceOf_Function) \
|
||||
\
|
||||
_(TypeOf_Fallback) \
|
||||
\
|
||||
|
@ -76,6 +76,41 @@ namespace jit {
|
|||
_(CacheIR_Monitored) \
|
||||
_(CacheIR_Updated)
|
||||
|
||||
// List of fallback trampolines. Each of these fallback trampolines exists as
|
||||
// part of the JitRuntime. Note that some fallback stubs in previous list may
|
||||
// have multiple trampolines in this list. For example, Call_Fallback has
|
||||
// constructing/spread variants here with different calling conventions needing
|
||||
// different trampolines.
|
||||
#define IC_BASELINE_FALLBACK_CODE_KIND_LIST(_) \
|
||||
_(WarmUpCounter) \
|
||||
_(TypeMonitor) \
|
||||
_(TypeUpdate) \
|
||||
_(NewArray) \
|
||||
_(NewObject) \
|
||||
_(ToBool) \
|
||||
_(UnaryArith) \
|
||||
_(Call) \
|
||||
_(CallConstructing) \
|
||||
_(SpreadCall) \
|
||||
_(SpreadCallConstructing) \
|
||||
_(GetElem) \
|
||||
_(GetElemSuper) \
|
||||
_(SetElem) \
|
||||
_(In) \
|
||||
_(HasOwn) \
|
||||
_(GetName) \
|
||||
_(BindName) \
|
||||
_(GetIntrinsic) \
|
||||
_(SetProp) \
|
||||
_(GetIterator) \
|
||||
_(InstanceOf) \
|
||||
_(TypeOf) \
|
||||
_(Rest) \
|
||||
_(BinaryArith) \
|
||||
_(Compare) \
|
||||
_(GetProp) \
|
||||
_(GetPropSuper)
|
||||
|
||||
} // namespace jit
|
||||
} // namespace js
|
||||
|
||||
|
|
|
@ -200,6 +200,23 @@ bool JitRuntime::initialize(JSContext* cx) {
|
|||
|
||||
JitContext jctx(cx, nullptr);
|
||||
|
||||
if (!generateTrampolines(cx)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!generateBaselineICFallbackCode(cx)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
jitcodeGlobalTable_ = cx->new_<JitcodeGlobalTable>();
|
||||
if (!jitcodeGlobalTable_) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool JitRuntime::generateTrampolines(JSContext* cx) {
|
||||
StackMacroAssembler masm;
|
||||
|
||||
Label bailoutTail;
|
||||
|
@ -305,11 +322,6 @@ bool JitRuntime::initialize(JSContext* cx) {
|
|||
vtune::MarkStub(trampolineCode_, "Trampolines");
|
||||
#endif
|
||||
|
||||
jitcodeGlobalTable_ = cx->new_<JitcodeGlobalTable>();
|
||||
if (!jitcodeGlobalTable_) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -561,14 +573,6 @@ void JitRealm::sweep(JS::Realm* realm) {
|
|||
|
||||
stubCodes_->sweep();
|
||||
|
||||
// If the sweep removed a bailout Fallback stub, nullptr the corresponding
|
||||
// return addr.
|
||||
for (auto& it : bailoutReturnStubInfo_) {
|
||||
if (!stubCodes_->lookup(it.key)) {
|
||||
it = BailoutReturnStubInfo();
|
||||
}
|
||||
}
|
||||
|
||||
for (ReadBarrieredJitCode& stub : stubs_) {
|
||||
if (stub && IsAboutToBeFinalized(&stub)) {
|
||||
stub.set(nullptr);
|
||||
|
|
|
@ -9,11 +9,13 @@
|
|||
|
||||
#include "mozilla/Array.h"
|
||||
#include "mozilla/DebugOnly.h"
|
||||
#include "mozilla/EnumeratedArray.h"
|
||||
#include "mozilla/MemoryReporting.h"
|
||||
|
||||
#include <utility>
|
||||
|
||||
#include "builtin/TypedObject.h"
|
||||
#include "jit/BaselineICList.h"
|
||||
#include "jit/CompileInfo.h"
|
||||
#include "jit/ICStubSpace.h"
|
||||
#include "jit/IonCode.h"
|
||||
|
@ -62,6 +64,60 @@ struct EnterJitData {
|
|||
bool constructing;
|
||||
};
|
||||
|
||||
enum class BaselineICFallbackKind {
|
||||
#define DEF_ENUM_KIND(kind) kind,
|
||||
IC_BASELINE_FALLBACK_CODE_KIND_LIST(DEF_ENUM_KIND)
|
||||
#undef DEF_ENUM_KIND
|
||||
Count
|
||||
};
|
||||
|
||||
enum class BailoutReturnKind {
|
||||
GetProp,
|
||||
GetPropSuper,
|
||||
SetProp,
|
||||
GetElem,
|
||||
GetElemSuper,
|
||||
Call,
|
||||
New,
|
||||
Count
|
||||
};
|
||||
|
||||
// Class storing code and offsets for all Baseline IC fallback trampolines. This
|
||||
// is stored in JitRuntime and generated when creating the JitRuntime.
|
||||
class BaselineICFallbackCode {
|
||||
JitCode* code_ = nullptr;
|
||||
using OffsetArray =
|
||||
mozilla::EnumeratedArray<BaselineICFallbackKind,
|
||||
BaselineICFallbackKind::Count, uint32_t>;
|
||||
OffsetArray offsets_ = {};
|
||||
|
||||
// Keep track of offset into various baseline stubs' code at return
|
||||
// point from called script.
|
||||
using BailoutReturnArray =
|
||||
mozilla::EnumeratedArray<BailoutReturnKind, BailoutReturnKind::Count,
|
||||
uint32_t>;
|
||||
BailoutReturnArray bailoutReturnOffsets_ = {};
|
||||
|
||||
public:
|
||||
BaselineICFallbackCode() = default;
|
||||
BaselineICFallbackCode(const BaselineICFallbackCode&) = delete;
|
||||
void operator=(const BaselineICFallbackCode&) = delete;
|
||||
|
||||
void initOffset(BaselineICFallbackKind kind, uint32_t offset) {
|
||||
offsets_[kind] = offset;
|
||||
}
|
||||
void initCode(JitCode* code) { code_ = code; }
|
||||
void initBailoutReturnOffset(BailoutReturnKind kind, uint32_t offset) {
|
||||
bailoutReturnOffsets_[kind] = offset;
|
||||
}
|
||||
TrampolinePtr addr(BaselineICFallbackKind kind) const {
|
||||
return TrampolinePtr(code_->raw() + offsets_[kind]);
|
||||
}
|
||||
uint8_t* bailoutReturnAddr(BailoutReturnKind kind) const {
|
||||
return code_->raw() + bailoutReturnOffsets_[kind];
|
||||
}
|
||||
};
|
||||
|
||||
typedef void (*EnterJitCode)(void* code, unsigned argc, Value* argv,
|
||||
InterpreterFrame* fp, CalleeToken calleeToken,
|
||||
JSObject* envChain, size_t numStackValues,
|
||||
|
@ -155,6 +211,8 @@ class JitRuntime {
|
|||
// trampolineCode_.
|
||||
VMWrapperOffsets tailCallFunctionWrapperOffsets_;
|
||||
|
||||
MainThreadData<BaselineICFallbackCode> baselineICFallbackCode_;
|
||||
|
||||
// Global table of jitcode native address => bytecode address mappings.
|
||||
UnprotectedData<JitcodeGlobalTable*> jitcodeGlobalTable_;
|
||||
|
||||
|
@ -181,6 +239,9 @@ class JitRuntime {
|
|||
MainThreadData<uint64_t> disambiguationId_;
|
||||
|
||||
private:
|
||||
bool generateTrampolines(JSContext* cx);
|
||||
bool generateBaselineICFallbackCode(JSContext* cx);
|
||||
|
||||
void generateLazyLinkStub(MacroAssembler& masm);
|
||||
void generateInterpreterStub(MacroAssembler& masm);
|
||||
void generateDoubleToInt32ValueStub(MacroAssembler& masm);
|
||||
|
@ -242,6 +303,10 @@ class JitRuntime {
|
|||
|
||||
ExecutableAllocator& execAlloc() { return execAlloc_.ref(); }
|
||||
|
||||
const BaselineICFallbackCode& baselineICFallbackCode() const {
|
||||
return baselineICFallbackCode_.ref();
|
||||
}
|
||||
|
||||
IonCompilationId nextCompilationId() {
|
||||
return IonCompilationId(nextCompilationId_++);
|
||||
}
|
||||
|
@ -471,17 +536,6 @@ class JitZone {
|
|||
void purgeIonCacheIRStubInfo() { ionCacheIRStubInfoSet_.clearAndCompact(); }
|
||||
};
|
||||
|
||||
enum class BailoutReturnStub {
|
||||
GetProp,
|
||||
GetPropSuper,
|
||||
SetProp,
|
||||
GetElem,
|
||||
GetElemSuper,
|
||||
Call,
|
||||
New,
|
||||
Count
|
||||
};
|
||||
|
||||
class JitRealm {
|
||||
friend class JitActivation;
|
||||
|
||||
|
@ -491,20 +545,6 @@ class JitRealm {
|
|||
ZoneAllocPolicy, IcStubCodeMapGCPolicy<uint32_t>>;
|
||||
ICStubCodeMap* stubCodes_;
|
||||
|
||||
// Keep track of offset into various baseline stubs' code at return
|
||||
// point from called script.
|
||||
struct BailoutReturnStubInfo {
|
||||
void* addr;
|
||||
uint32_t key;
|
||||
|
||||
BailoutReturnStubInfo() : addr(nullptr), key(0) {}
|
||||
BailoutReturnStubInfo(void* addr_, uint32_t key_)
|
||||
: addr(addr_), key(key_) {}
|
||||
};
|
||||
mozilla::EnumeratedArray<BailoutReturnStub, BailoutReturnStub::Count,
|
||||
BailoutReturnStubInfo>
|
||||
bailoutReturnStubInfo_;
|
||||
|
||||
// The JitRealm stores stubs to concatenate strings inline and perform RegExp
|
||||
// calls inline. These bake in zone and realm specific pointers and can't be
|
||||
// stored in JitRuntime. They also are dependent on the value of
|
||||
|
@ -557,14 +597,6 @@ class JitRealm {
|
|||
}
|
||||
return true;
|
||||
}
|
||||
void initBailoutReturnAddr(void* addr, uint32_t key, BailoutReturnStub kind) {
|
||||
MOZ_ASSERT(bailoutReturnStubInfo_[kind].addr == nullptr);
|
||||
bailoutReturnStubInfo_[kind] = BailoutReturnStubInfo{addr, key};
|
||||
}
|
||||
void* bailoutReturnAddr(BailoutReturnStub kind) {
|
||||
MOZ_ASSERT(bailoutReturnStubInfo_[kind].addr);
|
||||
return bailoutReturnStubInfo_[kind].addr;
|
||||
}
|
||||
|
||||
JitRealm();
|
||||
~JitRealm();
|
||||
|
|
|
@ -1645,11 +1645,13 @@ static void AdjustGeneratorResumptionValue(JSContext* cx,
|
|||
cx, &genObj->as<AsyncFunctionGeneratorObject>());
|
||||
|
||||
// 1. `return <value>` fulfills and returns the async function's promise.
|
||||
JSObject* promise = AsyncFunctionResolve(
|
||||
cx, asyncGenObj, vp, AsyncFunctionResolveKind::Fulfill);
|
||||
if (!promise) {
|
||||
getAndClearExceptionThenThrow();
|
||||
return;
|
||||
Rooted<PromiseObject*> promise(cx, asyncGenObj->promise());
|
||||
if (promise->state() == JS::PromiseState::Pending) {
|
||||
if (!AsyncFunctionResolve(cx, asyncGenObj, vp,
|
||||
AsyncFunctionResolveKind::Fulfill)) {
|
||||
getAndClearExceptionThenThrow();
|
||||
return;
|
||||
}
|
||||
}
|
||||
vp.setObject(*promise);
|
||||
|
||||
|
|
|
@ -1065,19 +1065,19 @@ WasmToken WasmTokenStream::next() {
|
|||
if (consume(u"const")) {
|
||||
return WasmToken(WasmToken::Const, ValType::F32, begin, cur_);
|
||||
}
|
||||
if (consume(u"convert_s/i32")) {
|
||||
if (consume(u"convert_i32_s") || consume(u"convert_s/i32")) {
|
||||
return WasmToken(WasmToken::ConversionOpcode, Op::F32ConvertSI32,
|
||||
begin, cur_);
|
||||
}
|
||||
if (consume(u"convert_u/i32")) {
|
||||
if (consume(u"convert_i32_u") || consume(u"convert_u/i32")) {
|
||||
return WasmToken(WasmToken::ConversionOpcode, Op::F32ConvertUI32,
|
||||
begin, cur_);
|
||||
}
|
||||
if (consume(u"convert_s/i64")) {
|
||||
if (consume(u"convert_i64_s") || consume(u"convert_s/i64")) {
|
||||
return WasmToken(WasmToken::ConversionOpcode, Op::F32ConvertSI64,
|
||||
begin, cur_);
|
||||
}
|
||||
if (consume(u"convert_u/i64")) {
|
||||
if (consume(u"convert_i64_u") || consume(u"convert_u/i64")) {
|
||||
return WasmToken(WasmToken::ConversionOpcode, Op::F32ConvertUI64,
|
||||
begin, cur_);
|
||||
}
|
||||
|
@ -1087,7 +1087,7 @@ WasmToken WasmTokenStream::next() {
|
|||
}
|
||||
break;
|
||||
case 'd':
|
||||
if (consume(u"demote/f64")) {
|
||||
if (consume(u"demote_f64") || consume(u"demote/f64")) {
|
||||
return WasmToken(WasmToken::ConversionOpcode, Op::F32DemoteF64,
|
||||
begin, cur_);
|
||||
}
|
||||
|
@ -1159,7 +1159,7 @@ WasmToken WasmTokenStream::next() {
|
|||
}
|
||||
break;
|
||||
case 'r':
|
||||
if (consume(u"reinterpret/i32")) {
|
||||
if (consume(u"reinterpret_i32") || consume(u"reinterpret/i32")) {
|
||||
return WasmToken(WasmToken::ConversionOpcode,
|
||||
Op::F32ReinterpretI32, begin, cur_);
|
||||
}
|
||||
|
@ -1209,19 +1209,19 @@ WasmToken WasmTokenStream::next() {
|
|||
if (consume(u"const")) {
|
||||
return WasmToken(WasmToken::Const, ValType::F64, begin, cur_);
|
||||
}
|
||||
if (consume(u"convert_s/i32")) {
|
||||
if (consume(u"convert_i32_s") || consume(u"convert_s/i32")) {
|
||||
return WasmToken(WasmToken::ConversionOpcode, Op::F64ConvertSI32,
|
||||
begin, cur_);
|
||||
}
|
||||
if (consume(u"convert_u/i32")) {
|
||||
if (consume(u"convert_i32_u") || consume(u"convert_u/i32")) {
|
||||
return WasmToken(WasmToken::ConversionOpcode, Op::F64ConvertUI32,
|
||||
begin, cur_);
|
||||
}
|
||||
if (consume(u"convert_s/i64")) {
|
||||
if (consume(u"convert_i64_s") || consume(u"convert_s/i64")) {
|
||||
return WasmToken(WasmToken::ConversionOpcode, Op::F64ConvertSI64,
|
||||
begin, cur_);
|
||||
}
|
||||
if (consume(u"convert_u/i64")) {
|
||||
if (consume(u"convert_i64_u") || consume(u"convert_u/i64")) {
|
||||
return WasmToken(WasmToken::ConversionOpcode, Op::F64ConvertUI64,
|
||||
begin, cur_);
|
||||
}
|
||||
|
@ -1299,13 +1299,13 @@ WasmToken WasmTokenStream::next() {
|
|||
}
|
||||
break;
|
||||
case 'p':
|
||||
if (consume(u"promote/f32")) {
|
||||
if (consume(u"promote_f32") || consume(u"promote/f32")) {
|
||||
return WasmToken(WasmToken::ConversionOpcode, Op::F64PromoteF32,
|
||||
begin, cur_);
|
||||
}
|
||||
break;
|
||||
case 'r':
|
||||
if (consume(u"reinterpret/i64")) {
|
||||
if (consume(u"reinterpret_i64") || consume(u"reinterpret/i64")) {
|
||||
return WasmToken(WasmToken::UnaryOpcode, Op::F64ReinterpretI64,
|
||||
begin, cur_);
|
||||
}
|
||||
|
@ -1377,11 +1377,11 @@ WasmToken WasmTokenStream::next() {
|
|||
cur_);
|
||||
}
|
||||
if (consume(u"atomic.")) {
|
||||
if (consume(u"rmw8_u.add")) {
|
||||
if (consume(u"rmw8.add_u") || consume(u"rmw8_u.add")) {
|
||||
return WasmToken(WasmToken::AtomicRMW, ThreadOp::I32AtomicAdd8U,
|
||||
begin, cur_);
|
||||
}
|
||||
if (consume(u"rmw16_u.add")) {
|
||||
if (consume(u"rmw16.add_u") || consume(u"rmw16_u.add")) {
|
||||
return WasmToken(WasmToken::AtomicRMW,
|
||||
ThreadOp::I32AtomicAdd16U, begin, cur_);
|
||||
}
|
||||
|
@ -1389,11 +1389,11 @@ WasmToken WasmTokenStream::next() {
|
|||
return WasmToken(WasmToken::AtomicRMW, ThreadOp::I32AtomicAdd,
|
||||
begin, cur_);
|
||||
}
|
||||
if (consume(u"rmw8_u.and")) {
|
||||
if (consume(u"rmw8.and_u") || consume(u"rmw8_u.and")) {
|
||||
return WasmToken(WasmToken::AtomicRMW, ThreadOp::I32AtomicAnd8U,
|
||||
begin, cur_);
|
||||
}
|
||||
if (consume(u"rmw16_u.and")) {
|
||||
if (consume(u"rmw16.and_u") || consume(u"rmw16_u.and")) {
|
||||
return WasmToken(WasmToken::AtomicRMW,
|
||||
ThreadOp::I32AtomicAnd16U, begin, cur_);
|
||||
}
|
||||
|
@ -1401,11 +1401,11 @@ WasmToken WasmTokenStream::next() {
|
|||
return WasmToken(WasmToken::AtomicRMW, ThreadOp::I32AtomicAnd,
|
||||
begin, cur_);
|
||||
}
|
||||
if (consume(u"rmw8_u.cmpxchg")) {
|
||||
if (consume(u"rmw8.cmpxchg_u") || consume(u"rmw8_u.cmpxchg")) {
|
||||
return WasmToken(WasmToken::AtomicCmpXchg,
|
||||
ThreadOp::I32AtomicCmpXchg8U, begin, cur_);
|
||||
}
|
||||
if (consume(u"rmw16_u.cmpxchg")) {
|
||||
if (consume(u"rmw16.cmpxchg_u") || consume(u"rmw16_u.cmpxchg")) {
|
||||
return WasmToken(WasmToken::AtomicCmpXchg,
|
||||
ThreadOp::I32AtomicCmpXchg16U, begin, cur_);
|
||||
}
|
||||
|
@ -1425,11 +1425,11 @@ WasmToken WasmTokenStream::next() {
|
|||
return WasmToken(WasmToken::AtomicLoad, ThreadOp::I32AtomicLoad,
|
||||
begin, cur_);
|
||||
}
|
||||
if (consume(u"rmw8_u.or")) {
|
||||
if (consume(u"rmw8.or_u") || consume(u"rmw8_u.or")) {
|
||||
return WasmToken(WasmToken::AtomicRMW, ThreadOp::I32AtomicOr8U,
|
||||
begin, cur_);
|
||||
}
|
||||
if (consume(u"rmw16_u.or")) {
|
||||
if (consume(u"rmw16.or_u") || consume(u"rmw16_u.or")) {
|
||||
return WasmToken(WasmToken::AtomicRMW, ThreadOp::I32AtomicOr16U,
|
||||
begin, cur_);
|
||||
}
|
||||
|
@ -1449,11 +1449,11 @@ WasmToken WasmTokenStream::next() {
|
|||
return WasmToken(WasmToken::AtomicStore,
|
||||
ThreadOp::I32AtomicStore, begin, cur_);
|
||||
}
|
||||
if (consume(u"rmw8_u.sub")) {
|
||||
if (consume(u"rmw8.sub_u") || consume(u"rmw8_u.sub")) {
|
||||
return WasmToken(WasmToken::AtomicRMW, ThreadOp::I32AtomicSub8U,
|
||||
begin, cur_);
|
||||
}
|
||||
if (consume(u"rmw16_u.sub")) {
|
||||
if (consume(u"rmw16.sub_u") || consume(u"rmw16_u.sub")) {
|
||||
return WasmToken(WasmToken::AtomicRMW,
|
||||
ThreadOp::I32AtomicSub16U, begin, cur_);
|
||||
}
|
||||
|
@ -1461,11 +1461,11 @@ WasmToken WasmTokenStream::next() {
|
|||
return WasmToken(WasmToken::AtomicRMW, ThreadOp::I32AtomicSub,
|
||||
begin, cur_);
|
||||
}
|
||||
if (consume(u"rmw8_u.xor")) {
|
||||
if (consume(u"rmw8.xor_u") || consume(u"rmw8_u.xor")) {
|
||||
return WasmToken(WasmToken::AtomicRMW, ThreadOp::I32AtomicXor8U,
|
||||
begin, cur_);
|
||||
}
|
||||
if (consume(u"rmw16_u.xor")) {
|
||||
if (consume(u"rmw16.xor_u") || consume(u"rmw16_u.xor")) {
|
||||
return WasmToken(WasmToken::AtomicRMW,
|
||||
ThreadOp::I32AtomicXor16U, begin, cur_);
|
||||
}
|
||||
|
@ -1473,11 +1473,11 @@ WasmToken WasmTokenStream::next() {
|
|||
return WasmToken(WasmToken::AtomicRMW, ThreadOp::I32AtomicXor,
|
||||
begin, cur_);
|
||||
}
|
||||
if (consume(u"rmw8_u.xchg")) {
|
||||
if (consume(u"rmw8.xchg_u") || consume(u"rmw8_u.xchg")) {
|
||||
return WasmToken(WasmToken::AtomicRMW,
|
||||
ThreadOp::I32AtomicXchg8U, begin, cur_);
|
||||
}
|
||||
if (consume(u"rmw16_u.xchg")) {
|
||||
if (consume(u"rmw16.xchg_u") || consume(u"rmw16_u.xchg")) {
|
||||
return WasmToken(WasmToken::AtomicRMW,
|
||||
ThreadOp::I32AtomicXchg16U, begin, cur_);
|
||||
}
|
||||
|
@ -1607,7 +1607,7 @@ WasmToken WasmTokenStream::next() {
|
|||
}
|
||||
break;
|
||||
case 'r':
|
||||
if (consume(u"reinterpret/f32")) {
|
||||
if (consume(u"reinterpret_f32") || consume(u"reinterpret/f32")) {
|
||||
return WasmToken(WasmToken::UnaryOpcode, Op::I32ReinterpretF32,
|
||||
begin, cur_);
|
||||
}
|
||||
|
@ -1659,41 +1659,41 @@ WasmToken WasmTokenStream::next() {
|
|||
}
|
||||
break;
|
||||
case 't':
|
||||
if (consume(u"trunc_s/f32")) {
|
||||
if (consume(u"trunc_f32_s") || consume(u"trunc_s/f32")) {
|
||||
return WasmToken(WasmToken::ConversionOpcode, Op::I32TruncSF32,
|
||||
begin, cur_);
|
||||
}
|
||||
if (consume(u"trunc_s/f64")) {
|
||||
if (consume(u"trunc_f64_s") || consume(u"trunc_s/f64")) {
|
||||
return WasmToken(WasmToken::ConversionOpcode, Op::I32TruncSF64,
|
||||
begin, cur_);
|
||||
}
|
||||
if (consume(u"trunc_u/f32")) {
|
||||
if (consume(u"trunc_f32_u") || consume(u"trunc_u/f32")) {
|
||||
return WasmToken(WasmToken::ConversionOpcode, Op::I32TruncUF32,
|
||||
begin, cur_);
|
||||
}
|
||||
if (consume(u"trunc_u/f64")) {
|
||||
if (consume(u"trunc_f64_u") || consume(u"trunc_u/f64")) {
|
||||
return WasmToken(WasmToken::ConversionOpcode, Op::I32TruncUF64,
|
||||
begin, cur_);
|
||||
}
|
||||
if (consume(u"trunc_s:sat/f32")) {
|
||||
if (consume(u"trunc_sat_f32_s") || consume(u"trunc_s:sat/f32")) {
|
||||
return WasmToken(WasmToken::ExtraConversionOpcode,
|
||||
MiscOp::I32TruncSSatF32, begin, cur_);
|
||||
}
|
||||
if (consume(u"trunc_s:sat/f64")) {
|
||||
if (consume(u"trunc_sat_f64_s") || consume(u"trunc_s:sat/f64")) {
|
||||
return WasmToken(WasmToken::ExtraConversionOpcode,
|
||||
MiscOp::I32TruncSSatF64, begin, cur_);
|
||||
}
|
||||
if (consume(u"trunc_u:sat/f32")) {
|
||||
if (consume(u"trunc_sat_f32_u") || consume(u"trunc_u:sat/f32")) {
|
||||
return WasmToken(WasmToken::ExtraConversionOpcode,
|
||||
MiscOp::I32TruncUSatF32, begin, cur_);
|
||||
}
|
||||
if (consume(u"trunc_u:sat/f64")) {
|
||||
if (consume(u"trunc_sat_f64_u") || consume(u"trunc_u:sat/f64")) {
|
||||
return WasmToken(WasmToken::ExtraConversionOpcode,
|
||||
MiscOp::I32TruncUSatF64, begin, cur_);
|
||||
}
|
||||
break;
|
||||
case 'w':
|
||||
if (consume(u"wrap/i64")) {
|
||||
if (consume(u"wrap_i64") || consume(u"wrap/i64")) {
|
||||
return WasmToken(WasmToken::ConversionOpcode, Op::I32WrapI64,
|
||||
begin, cur_);
|
||||
}
|
||||
|
@ -1723,15 +1723,15 @@ WasmToken WasmTokenStream::next() {
|
|||
cur_);
|
||||
}
|
||||
if (consume(u"atomic.")) {
|
||||
if (consume(u"rmw8_u.add")) {
|
||||
if (consume(u"rmw8.add_u") || consume(u"rmw8_u.add")) {
|
||||
return WasmToken(WasmToken::AtomicRMW, ThreadOp::I64AtomicAdd8U,
|
||||
begin, cur_);
|
||||
}
|
||||
if (consume(u"rmw16_u.add")) {
|
||||
if (consume(u"rmw16.add_u") || consume(u"rmw16_u.add")) {
|
||||
return WasmToken(WasmToken::AtomicRMW,
|
||||
ThreadOp::I64AtomicAdd16U, begin, cur_);
|
||||
}
|
||||
if (consume(u"rmw32_u.add")) {
|
||||
if (consume(u"rmw32.add_u") || consume(u"rmw32_u.add")) {
|
||||
return WasmToken(WasmToken::AtomicRMW,
|
||||
ThreadOp::I64AtomicAdd32U, begin, cur_);
|
||||
}
|
||||
|
@ -1739,15 +1739,15 @@ WasmToken WasmTokenStream::next() {
|
|||
return WasmToken(WasmToken::AtomicRMW, ThreadOp::I64AtomicAdd,
|
||||
begin, cur_);
|
||||
}
|
||||
if (consume(u"rmw8_u.and")) {
|
||||
if (consume(u"rmw8.and_u") || consume(u"rmw8_u.and")) {
|
||||
return WasmToken(WasmToken::AtomicRMW, ThreadOp::I64AtomicAnd8U,
|
||||
begin, cur_);
|
||||
}
|
||||
if (consume(u"rmw16_u.and")) {
|
||||
if (consume(u"rmw16.and_u") || consume(u"rmw16_u.and")) {
|
||||
return WasmToken(WasmToken::AtomicRMW,
|
||||
ThreadOp::I64AtomicAnd16U, begin, cur_);
|
||||
}
|
||||
if (consume(u"rmw32_u.and")) {
|
||||
if (consume(u"rmw32.and_u") || consume(u"rmw32_u.and")) {
|
||||
return WasmToken(WasmToken::AtomicRMW,
|
||||
ThreadOp::I64AtomicAnd32U, begin, cur_);
|
||||
}
|
||||
|
@ -1755,15 +1755,15 @@ WasmToken WasmTokenStream::next() {
|
|||
return WasmToken(WasmToken::AtomicRMW, ThreadOp::I64AtomicAnd,
|
||||
begin, cur_);
|
||||
}
|
||||
if (consume(u"rmw8_u.cmpxchg")) {
|
||||
if (consume(u"rmw8.cmpxchg_u") || consume(u"rmw8_u.cmpxchg")) {
|
||||
return WasmToken(WasmToken::AtomicCmpXchg,
|
||||
ThreadOp::I64AtomicCmpXchg8U, begin, cur_);
|
||||
}
|
||||
if (consume(u"rmw16_u.cmpxchg")) {
|
||||
if (consume(u"rmw16.cmpxchg_u") || consume(u"rmw16_u.cmpxchg")) {
|
||||
return WasmToken(WasmToken::AtomicCmpXchg,
|
||||
ThreadOp::I64AtomicCmpXchg16U, begin, cur_);
|
||||
}
|
||||
if (consume(u"rmw32_u.cmpxchg")) {
|
||||
if (consume(u"rmw32.cmpxchg_u") || consume(u"rmw32_u.cmpxchg")) {
|
||||
return WasmToken(WasmToken::AtomicCmpXchg,
|
||||
ThreadOp::I64AtomicCmpXchg32U, begin, cur_);
|
||||
}
|
||||
|
@ -1787,15 +1787,15 @@ WasmToken WasmTokenStream::next() {
|
|||
return WasmToken(WasmToken::AtomicLoad, ThreadOp::I64AtomicLoad,
|
||||
begin, cur_);
|
||||
}
|
||||
if (consume(u"rmw8_u.or")) {
|
||||
if (consume(u"rmw8.or_u") || consume(u"rmw8_u.or")) {
|
||||
return WasmToken(WasmToken::AtomicRMW, ThreadOp::I64AtomicOr8U,
|
||||
begin, cur_);
|
||||
}
|
||||
if (consume(u"rmw16_u.or")) {
|
||||
if (consume(u"rmw16.or_u") || consume(u"rmw16_u.or")) {
|
||||
return WasmToken(WasmToken::AtomicRMW, ThreadOp::I64AtomicOr16U,
|
||||
begin, cur_);
|
||||
}
|
||||
if (consume(u"rmw32_u.or")) {
|
||||
if (consume(u"rmw32.or_u") || consume(u"rmw32_u.or")) {
|
||||
return WasmToken(WasmToken::AtomicRMW, ThreadOp::I64AtomicOr32U,
|
||||
begin, cur_);
|
||||
}
|
||||
|
@ -1819,15 +1819,15 @@ WasmToken WasmTokenStream::next() {
|
|||
return WasmToken(WasmToken::AtomicStore,
|
||||
ThreadOp::I64AtomicStore, begin, cur_);
|
||||
}
|
||||
if (consume(u"rmw8_u.sub")) {
|
||||
if (consume(u"rmw8.sub_u") || consume(u"rmw8_u.sub")) {
|
||||
return WasmToken(WasmToken::AtomicRMW, ThreadOp::I64AtomicSub8U,
|
||||
begin, cur_);
|
||||
}
|
||||
if (consume(u"rmw16_u.sub")) {
|
||||
if (consume(u"rmw16.sub_u") || consume(u"rmw16_u.sub")) {
|
||||
return WasmToken(WasmToken::AtomicRMW,
|
||||
ThreadOp::I64AtomicSub16U, begin, cur_);
|
||||
}
|
||||
if (consume(u"rmw32_u.sub")) {
|
||||
if (consume(u"rmw32.sub_u") || consume(u"rmw32_u.sub")) {
|
||||
return WasmToken(WasmToken::AtomicRMW,
|
||||
ThreadOp::I64AtomicSub32U, begin, cur_);
|
||||
}
|
||||
|
@ -1835,15 +1835,15 @@ WasmToken WasmTokenStream::next() {
|
|||
return WasmToken(WasmToken::AtomicRMW, ThreadOp::I64AtomicSub,
|
||||
begin, cur_);
|
||||
}
|
||||
if (consume(u"rmw8_u.xor")) {
|
||||
if (consume(u"rmw8.xor_u") || consume(u"rmw8_u.xor")) {
|
||||
return WasmToken(WasmToken::AtomicRMW, ThreadOp::I64AtomicXor8U,
|
||||
begin, cur_);
|
||||
}
|
||||
if (consume(u"rmw16_u.xor")) {
|
||||
if (consume(u"rmw16.xor_u") || consume(u"rmw16_u.xor")) {
|
||||
return WasmToken(WasmToken::AtomicRMW,
|
||||
ThreadOp::I64AtomicXor16U, begin, cur_);
|
||||
}
|
||||
if (consume(u"rmw32_u.xor")) {
|
||||
if (consume(u"rmw32.xor_u") || consume(u"rmw32_u.xor")) {
|
||||
return WasmToken(WasmToken::AtomicRMW,
|
||||
ThreadOp::I64AtomicXor32U, begin, cur_);
|
||||
}
|
||||
|
@ -1851,15 +1851,15 @@ WasmToken WasmTokenStream::next() {
|
|||
return WasmToken(WasmToken::AtomicRMW, ThreadOp::I64AtomicXor,
|
||||
begin, cur_);
|
||||
}
|
||||
if (consume(u"rmw8_u.xchg")) {
|
||||
if (consume(u"rmw8.xchg_u") || consume(u"rmw8_u.xchg")) {
|
||||
return WasmToken(WasmToken::AtomicRMW,
|
||||
ThreadOp::I64AtomicXchg8U, begin, cur_);
|
||||
}
|
||||
if (consume(u"rmw16_u.xchg")) {
|
||||
if (consume(u"rmw16.xchg_u") || consume(u"rmw16_u.xchg")) {
|
||||
return WasmToken(WasmToken::AtomicRMW,
|
||||
ThreadOp::I64AtomicXchg16U, begin, cur_);
|
||||
}
|
||||
if (consume(u"rmw32_u.xchg")) {
|
||||
if (consume(u"rmw32.xchg_u") || consume(u"rmw32_u.xchg")) {
|
||||
return WasmToken(WasmToken::AtomicRMW,
|
||||
ThreadOp::I64AtomicXchg32U, begin, cur_);
|
||||
}
|
||||
|
@ -1902,11 +1902,11 @@ WasmToken WasmTokenStream::next() {
|
|||
return WasmToken(WasmToken::ComparisonOpcode, Op::I64Eq, begin,
|
||||
cur_);
|
||||
}
|
||||
if (consume(u"extend_s/i32")) {
|
||||
if (consume(u"extend_i32_s") || consume(u"extend_s/i32")) {
|
||||
return WasmToken(WasmToken::ConversionOpcode, Op::I64ExtendSI32,
|
||||
begin, cur_);
|
||||
}
|
||||
if (consume(u"extend_u/i32")) {
|
||||
if (consume(u"extend_i32_u") || consume(u"extend_u/i32")) {
|
||||
return WasmToken(WasmToken::ConversionOpcode, Op::I64ExtendUI32,
|
||||
begin, cur_);
|
||||
}
|
||||
|
@ -2007,7 +2007,7 @@ WasmToken WasmTokenStream::next() {
|
|||
}
|
||||
break;
|
||||
case 'r':
|
||||
if (consume(u"reinterpret/f64")) {
|
||||
if (consume(u"reinterpret_f64") || consume(u"reinterpret/f64")) {
|
||||
return WasmToken(WasmToken::UnaryOpcode, Op::I64ReinterpretF64,
|
||||
begin, cur_);
|
||||
}
|
||||
|
@ -2062,35 +2062,35 @@ WasmToken WasmTokenStream::next() {
|
|||
}
|
||||
break;
|
||||
case 't':
|
||||
if (consume(u"trunc_s/f32")) {
|
||||
if (consume(u"trunc_f32_s") || consume(u"trunc_s/f32")) {
|
||||
return WasmToken(WasmToken::ConversionOpcode, Op::I64TruncSF32,
|
||||
begin, cur_);
|
||||
}
|
||||
if (consume(u"trunc_s/f64")) {
|
||||
if (consume(u"trunc_f64_s") || consume(u"trunc_s/f64")) {
|
||||
return WasmToken(WasmToken::ConversionOpcode, Op::I64TruncSF64,
|
||||
begin, cur_);
|
||||
}
|
||||
if (consume(u"trunc_u/f32")) {
|
||||
if (consume(u"trunc_f32_u") || consume(u"trunc_u/f32")) {
|
||||
return WasmToken(WasmToken::ConversionOpcode, Op::I64TruncUF32,
|
||||
begin, cur_);
|
||||
}
|
||||
if (consume(u"trunc_u/f64")) {
|
||||
if (consume(u"trunc_f64_u") || consume(u"trunc_u/f64")) {
|
||||
return WasmToken(WasmToken::ConversionOpcode, Op::I64TruncUF64,
|
||||
begin, cur_);
|
||||
}
|
||||
if (consume(u"trunc_s:sat/f32")) {
|
||||
if (consume(u"trunc_sat_f32_s") || consume(u"trunc_s:sat/f32")) {
|
||||
return WasmToken(WasmToken::ExtraConversionOpcode,
|
||||
MiscOp::I64TruncSSatF32, begin, cur_);
|
||||
}
|
||||
if (consume(u"trunc_s:sat/f64")) {
|
||||
if (consume(u"trunc_sat_f64_s") || consume(u"trunc_s:sat/f64")) {
|
||||
return WasmToken(WasmToken::ExtraConversionOpcode,
|
||||
MiscOp::I64TruncSSatF64, begin, cur_);
|
||||
}
|
||||
if (consume(u"trunc_u:sat/f32")) {
|
||||
if (consume(u"trunc_sat_f32_u") || consume(u"trunc_u:sat/f32")) {
|
||||
return WasmToken(WasmToken::ExtraConversionOpcode,
|
||||
MiscOp::I64TruncUSatF32, begin, cur_);
|
||||
}
|
||||
if (consume(u"trunc_u:sat/f64")) {
|
||||
if (consume(u"trunc_sat_f64_u") || consume(u"trunc_u:sat/f64")) {
|
||||
return WasmToken(WasmToken::ExtraConversionOpcode,
|
||||
MiscOp::I64TruncUSatF64, begin, cur_);
|
||||
}
|
||||
|
@ -2125,6 +2125,9 @@ WasmToken WasmTokenStream::next() {
|
|||
if (consume(u".set")) {
|
||||
return WasmToken(WasmToken::SetLocal, begin, cur_);
|
||||
}
|
||||
if (consume(u".tee")) {
|
||||
return WasmToken(WasmToken::TeeLocal, begin, cur_);
|
||||
}
|
||||
return WasmToken(WasmToken::Local, begin, cur_);
|
||||
}
|
||||
if (consume(u"loop")) {
|
||||
|
|
|
@ -409,6 +409,13 @@ function runTest() {
|
|||
// (TEST 18) Test passing valid url() source strings to the FontFace
|
||||
// constructor.
|
||||
var p = Promise.resolve();
|
||||
|
||||
// The sub-test is very fragile on Android platform, see Bug 1455824,
|
||||
// especially Comment 34.
|
||||
if (navigator.appVersion.includes("Android")) {
|
||||
return p;
|
||||
}
|
||||
|
||||
sourceWindows.forEach(function({ win, what }) {
|
||||
p = p.then(function() {
|
||||
var srcTests = Promise.resolve();
|
||||
|
|
|
@ -21,6 +21,14 @@
|
|||
</switch>
|
||||
</switch>
|
||||
</svg>
|
||||
<svg>
|
||||
<switch>
|
||||
<mask>
|
||||
<text id="g">Vendredi</text>
|
||||
</mask>
|
||||
<a></a>
|
||||
</switch>
|
||||
</svg>
|
||||
</body>
|
||||
<script>
|
||||
function go() {
|
||||
|
@ -30,5 +38,6 @@ function go() {
|
|||
d.getComputedTextLength();
|
||||
e.getComputedTextLength();
|
||||
f.getComputedTextLength();
|
||||
g.getComputedTextLength();
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -139,20 +139,23 @@ nsIFrame* nsSVGSwitchFrame::GetFrameForPoint(const gfxPoint& aPoint) {
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
static bool shouldReflowSVGTextFrameInside(nsIFrame* aFrame) {
|
||||
return aFrame->IsFrameOfType(nsIFrame::eSVG | nsIFrame::eSVGContainer) ||
|
||||
aFrame->IsSVGForeignObjectFrame() ||
|
||||
!aFrame->IsFrameOfType(nsIFrame::eSVG);
|
||||
}
|
||||
|
||||
void nsSVGSwitchFrame::AlwaysReflowSVGTextFrameDoForOneKid(nsIFrame* aKid) {
|
||||
if (!NS_SUBTREE_DIRTY(aKid)) {
|
||||
return;
|
||||
}
|
||||
|
||||
LayoutFrameType type = aKid->Type();
|
||||
if (type == LayoutFrameType::SVGText) {
|
||||
if (aKid->IsSVGTextFrame()) {
|
||||
MOZ_ASSERT(!aKid->HasAnyStateBits(NS_FRAME_IS_NONDISPLAY),
|
||||
"A non-display SVGTextFrame directly contained in a display "
|
||||
"container?");
|
||||
static_cast<SVGTextFrame*>(aKid)->ReflowSVG();
|
||||
} else if (aKid->IsFrameOfType(nsIFrame::eSVG | nsIFrame::eSVGContainer) ||
|
||||
type == LayoutFrameType::SVGForeignObject ||
|
||||
!aKid->IsFrameOfType(nsIFrame::eSVG)) {
|
||||
} else if (shouldReflowSVGTextFrameInside(aKid)) {
|
||||
if (!aKid->HasAnyStateBits(NS_FRAME_IS_NONDISPLAY)) {
|
||||
for (nsIFrame* kid : aKid->PrincipalChildList()) {
|
||||
AlwaysReflowSVGTextFrameDoForOneKid(kid);
|
||||
|
@ -222,6 +225,10 @@ void nsSVGSwitchFrame::ReflowSVG() {
|
|||
// nsLayoutUtils::UnionChildOverflow since SVG frame's all use the same
|
||||
// frame list, and we're iterating over that list now anyway.
|
||||
ConsiderChildOverflow(overflowRects, child);
|
||||
} else if (child && shouldReflowSVGTextFrameInside(child)) {
|
||||
MOZ_ASSERT(child->HasAnyStateBits(NS_FRAME_IS_NONDISPLAY),
|
||||
"Check for this explicitly in the |if|, then");
|
||||
ReflowSVGNonDisplayText(child);
|
||||
}
|
||||
|
||||
if (isFirstReflow) {
|
||||
|
|
|
@ -2696,7 +2696,7 @@ pref("csp.overrule_about_uris_without_csp_whitelist", false);
|
|||
pref("csp.skip_about_page_has_csp_assert", false);
|
||||
// assertion flag will be set to false after fixing Bug 1473549
|
||||
pref("security.allow_eval_with_system_principal", false);
|
||||
pref("security.uris_using_eval_with_system_principal", "autocomplete.xml,redux.js,react-redux.js,content-task.js,content-task.js,tree.xml,dialog.xml,preferencesbindings.js,wizard.xml,lodash.js,jszip.js,sinon-7.2.7.js,ajv-4.1.1.js,updates.js,setup,jsol.js,parent_utils.js,chrometask_chromescript");
|
||||
pref("security.uris_using_eval_with_system_principal", "autocomplete.xml,redux.js,react-redux.js,content-task.js,content-task.js,tree.xml,dialog.xml,preferencesbindings.js,lodash.js,jszip.js,sinon-7.2.7.js,ajv-4.1.1.js,updates.js,setup,jsol.js,parent_utils.js,chrometask_chromescript");
|
||||
#endif
|
||||
|
||||
// Default Content Security Policy to apply to signed contents.
|
||||
|
|
|
@ -673,7 +673,7 @@ class BaseBootstrapper(object):
|
|||
print('Your version of Rust (%s) is new enough.' % version)
|
||||
rustup = self.which('rustup', cargo_bin)
|
||||
if rustup:
|
||||
self.ensure_rust_targets(rustup)
|
||||
self.ensure_rust_targets(rustup, version)
|
||||
return
|
||||
|
||||
if version:
|
||||
|
@ -697,7 +697,7 @@ class BaseBootstrapper(object):
|
|||
print('Will try to install Rust.')
|
||||
self.install_rust()
|
||||
|
||||
def ensure_rust_targets(self, rustup):
|
||||
def ensure_rust_targets(self, rustup, rust_version):
|
||||
"""Make sure appropriate cross target libraries are installed."""
|
||||
target_list = subprocess.check_output([rustup, 'target', 'list'])
|
||||
targets = [line.split()[0] for line in target_list.splitlines()
|
||||
|
@ -712,7 +712,11 @@ class BaseBootstrapper(object):
|
|||
|
||||
if 'mobile_android' in self.application:
|
||||
# Let's add the most common targets.
|
||||
android_targets = ('thumbv7neon-linux-androideabi',
|
||||
if LooseVersion(rust_version) < '1.33':
|
||||
arm_target = 'armv7-linux-androideabi'
|
||||
else:
|
||||
arm_target = 'thumbv7neon-linux-androideabi'
|
||||
android_targets = (arm_target,
|
||||
'aarch64-linux-android',
|
||||
'i686-linux-android',
|
||||
'x86_64-linux-android', )
|
||||
|
|
|
@ -1,4 +1,9 @@
|
|||
job-defaults:
|
||||
# Run only on try and code-review tasks
|
||||
# to avoid running clang tools on the whole codebase
|
||||
run-on-projects:
|
||||
- try
|
||||
|
||||
platform: linux64/opt
|
||||
attributes:
|
||||
code-review: true
|
||||
|
|
|
@ -17,7 +17,6 @@ page_timeout = 30000
|
|||
gecko_profile_interval = 1
|
||||
gecko_profile_entries = 2000000
|
||||
alert_on = fcp, loadtime
|
||||
screen_capture=true
|
||||
|
||||
[raptor-tp6-ebay-mitm-404-recordings-202-firefox]
|
||||
apps = firefox
|
||||
|
|
|
@ -55,11 +55,12 @@ var NormandyApi = {
|
|||
},
|
||||
|
||||
absolutify(url) {
|
||||
const apiBase = prefs.getCharPref("api_url");
|
||||
const server = new URL(apiBase).origin;
|
||||
if (url.startsWith("http")) {
|
||||
return url;
|
||||
} else if (url.startsWith("/")) {
|
||||
}
|
||||
const apiBase = prefs.getCharPref("api_url");
|
||||
const server = new URL(apiBase).origin;
|
||||
if (url.startsWith("/")) {
|
||||
return server + url;
|
||||
}
|
||||
throw new Error("Can't use relative urls");
|
||||
|
@ -87,50 +88,65 @@ var NormandyApi = {
|
|||
const rawText = await objectsResponse.text();
|
||||
const objectsWithSigs = JSON.parse(rawText);
|
||||
|
||||
const verifiedObjects = [];
|
||||
return Promise.all(
|
||||
objectsWithSigs.map(async (item) => {
|
||||
// Check that the rawtext (the object and the signature)
|
||||
// includes the CanonicalJSON version of the object. This isn't
|
||||
// strictly needed, but it is a great benefit for debugging
|
||||
// signature problems.
|
||||
const object = item[type];
|
||||
const serialized = CanonicalJSON.stringify(object);
|
||||
if (!rawText.includes(serialized)) {
|
||||
log.debug(rawText, serialized);
|
||||
throw new NormandyApi.InvalidSignatureError(
|
||||
`Canonical ${type} serialization does not match!`);
|
||||
}
|
||||
// Verify content signature using cryptography (will throw if fails).
|
||||
await this.verifyObjectSignature(serialized, item.signature, type);
|
||||
return object;
|
||||
})
|
||||
);
|
||||
},
|
||||
|
||||
for (const objectWithSig of objectsWithSigs) {
|
||||
const {signature, x5u} = objectWithSig.signature;
|
||||
const object = objectWithSig[type];
|
||||
/**
|
||||
* Verify content signature, by serializing the specified `object` as
|
||||
* canonical JSON, and using the Normandy signer verifier to check that
|
||||
* it matches the signature specified in `signaturePayload`.
|
||||
*
|
||||
* @param {object|String} data The object (or string) to be checked
|
||||
* @param {object} signaturePayload The signature information
|
||||
* @param {String} signaturePayload.x5u The certificate chain URL
|
||||
* @param {String} signaturePayload.signature base64 signature bytes
|
||||
* @param {String} type The object type (eg. `"recipe"`, `"action"`)
|
||||
*
|
||||
* @throws {NormandyApi.InvalidSignatureError} if signature is invalid.
|
||||
*/
|
||||
async verifyObjectSignature(data, signaturePayload, type) {
|
||||
const { signature, x5u } = signaturePayload;
|
||||
const certChainResponse = await this.get(this.absolutify(x5u));
|
||||
const certChain = await certChainResponse.text();
|
||||
const builtSignature = `p384ecdsa=${signature}`;
|
||||
|
||||
const serialized = CanonicalJSON.stringify(object);
|
||||
// Check that the rawtext (the object and the signature)
|
||||
// includes the CanonicalJSON version of the object. This isn't
|
||||
// strictly needed, but it is a great benefit for debugging
|
||||
// signature problems.
|
||||
if (!rawText.includes(serialized)) {
|
||||
log.debug(rawText, serialized);
|
||||
throw new NormandyApi.InvalidSignatureError(
|
||||
`Canonical ${type} serialization does not match!`);
|
||||
}
|
||||
const serialized = typeof data == "string" ? data : CanonicalJSON.stringify(data);
|
||||
|
||||
const certChainResponse = await this.get(this.absolutify(x5u));
|
||||
const certChain = await certChainResponse.text();
|
||||
const builtSignature = `p384ecdsa=${signature}`;
|
||||
const verifier = Cc["@mozilla.org/security/contentsignatureverifier;1"]
|
||||
.createInstance(Ci.nsIContentSignatureVerifier);
|
||||
|
||||
const verifier = Cc["@mozilla.org/security/contentsignatureverifier;1"]
|
||||
.createInstance(Ci.nsIContentSignatureVerifier);
|
||||
|
||||
let valid;
|
||||
try {
|
||||
valid = verifier.verifyContentSignature(
|
||||
serialized,
|
||||
builtSignature,
|
||||
certChain,
|
||||
"normandy.content-signature.mozilla.org"
|
||||
);
|
||||
} catch (err) {
|
||||
throw new NormandyApi.InvalidSignatureError(`${type} signature validation failed: ${err}`);
|
||||
}
|
||||
|
||||
if (!valid) {
|
||||
throw new NormandyApi.InvalidSignatureError(`${type} signature is not valid`);
|
||||
}
|
||||
|
||||
verifiedObjects.push(object);
|
||||
let valid;
|
||||
try {
|
||||
valid = verifier.verifyContentSignature(
|
||||
serialized,
|
||||
builtSignature,
|
||||
certChain,
|
||||
"normandy.content-signature.mozilla.org"
|
||||
);
|
||||
} catch (err) {
|
||||
throw new NormandyApi.InvalidSignatureError(`${type} signature validation failed: ${err}`);
|
||||
}
|
||||
|
||||
return verifiedObjects;
|
||||
if (!valid) {
|
||||
throw new NormandyApi.InvalidSignatureError(`${type} signature is not valid`);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
|
|
|
@ -50,7 +50,7 @@ const PREFS_TO_WATCH = [
|
|||
|
||||
XPCOMUtils.defineLazyGetter(this, "gRemoteSettingsClient", () => {
|
||||
return RemoteSettings(REMOTE_SETTINGS_COLLECTION, {
|
||||
filterFunc: async recipe => (await RecipeRunner.checkFilter(recipe)) ? recipe : null,
|
||||
filterFunc: async entry => (await RecipeRunner.checkFilter(entry.recipe)) ? entry : null,
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -215,7 +215,15 @@ var RecipeRunner = {
|
|||
try {
|
||||
recipesToRun = await this.loadRecipes();
|
||||
} catch (e) {
|
||||
// The legacy call to `Normandy.fetchRecipes()` can throw.
|
||||
// Either we failed at fetching the recipes from server (legacy),
|
||||
// or the recipes signature verification failed.
|
||||
let status = Uptake.RUNNER_SERVER_ERROR;
|
||||
if (/NetworkError/.test(e)) {
|
||||
status = Uptake.RUNNER_NETWORK_ERROR;
|
||||
} else if (e instanceof NormandyApi.InvalidSignatureError) {
|
||||
status = Uptake.RUNNER_INVALID_SIGNATURE;
|
||||
}
|
||||
await Uptake.reportRunner(status);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -242,10 +250,17 @@ var RecipeRunner = {
|
|||
*/
|
||||
async loadRecipes() {
|
||||
// If RemoteSettings is enabled, we read the list of recipes from there.
|
||||
// The JEXL filtering is done via the provided callback.
|
||||
// The JEXL filtering is done via the provided callback (see `gRemoteSettingsClient`).
|
||||
if (await FeatureGate.isEnabled("normandy-remote-settings")) {
|
||||
return gRemoteSettingsClient.get();
|
||||
// First, fetch recipes whose JEXL filters match.
|
||||
const entries = await gRemoteSettingsClient.get();
|
||||
// Then, verify the signature of each recipe. It will throw if invalid.
|
||||
return Promise.all(entries.map(async ( { recipe, signature } ) => {
|
||||
await NormandyApi.verifyObjectSignature(recipe, signature, "recipe");
|
||||
return recipe;
|
||||
}));
|
||||
}
|
||||
|
||||
// Obtain the recipes from the Normandy server (legacy).
|
||||
let recipes;
|
||||
try {
|
||||
|
@ -257,14 +272,6 @@ var RecipeRunner = {
|
|||
} catch (e) {
|
||||
const apiUrl = Services.prefs.getCharPref(API_URL_PREF);
|
||||
log.error(`Could not fetch recipes from ${apiUrl}: "${e}"`);
|
||||
|
||||
let status = Uptake.RUNNER_SERVER_ERROR;
|
||||
if (/NetworkError/.test(e)) {
|
||||
status = Uptake.RUNNER_NETWORK_ERROR;
|
||||
} else if (e instanceof NormandyApi.InvalidSignatureError) {
|
||||
status = Uptake.RUNNER_INVALID_SIGNATURE;
|
||||
}
|
||||
await Uptake.reportRunner(status);
|
||||
throw e;
|
||||
}
|
||||
// Evaluate recipe filters
|
||||
|
|
|
@ -205,33 +205,42 @@ decorate_task(
|
|||
["features.normandy-remote-settings.enabled", true],
|
||||
],
|
||||
}),
|
||||
withStub(NormandyApi, "verifyObjectSignature"),
|
||||
withStub(ActionsManager.prototype, "runRecipe"),
|
||||
withStub(ActionsManager.prototype, "fetchRemoteActions"),
|
||||
withStub(ActionsManager.prototype, "finalize"),
|
||||
withStub(Uptake, "reportRecipe"),
|
||||
async function testReadFromRemoteSettings(
|
||||
verifyObjectSignatureStub,
|
||||
runRecipeStub,
|
||||
fetchRemoteActionsStub,
|
||||
finalizeStub,
|
||||
reportRecipeStub,
|
||||
) {
|
||||
const matchRecipe = { id: "match", action: "matchAction", filter_expression: "true", _status: "synced", enabled: true };
|
||||
const noMatchRecipe = { id: "noMatch", action: "noMatchAction", filter_expression: "false", _status: "synced", enabled: true };
|
||||
const missingRecipe = { id: "missing", action: "missingAction", filter_expression: "true", _status: "synced", enabled: true };
|
||||
const matchRecipe = { name: "match", action: "matchAction", filter_expression: "true" };
|
||||
const noMatchRecipe = { name: "noMatch", action: "noMatchAction", filter_expression: "false" };
|
||||
const missingRecipe = { name: "missing", action: "missingAction", filter_expression: "true" };
|
||||
|
||||
const rsCollection = await RecipeRunner._remoteSettingsClientForTesting.openCollection();
|
||||
await rsCollection.create(matchRecipe, { synced: true });
|
||||
await rsCollection.create(noMatchRecipe, { synced: true });
|
||||
await rsCollection.create(missingRecipe, { synced: true });
|
||||
await rsCollection.clear();
|
||||
const fakeSig = { signature: "abc" };
|
||||
await rsCollection.create({ id: "match", recipe: matchRecipe, signature: fakeSig }, { synced: true });
|
||||
await rsCollection.create({ id: "noMatch", recipe: noMatchRecipe, signature: fakeSig }, { synced: true });
|
||||
await rsCollection.create({ id: "missing", recipe: missingRecipe, signature: fakeSig }, { synced: true });
|
||||
await rsCollection.db.saveLastModified(42);
|
||||
rsCollection.db.close();
|
||||
|
||||
await RecipeRunner.run();
|
||||
|
||||
Assert.deepEqual(
|
||||
verifyObjectSignatureStub.args,
|
||||
[[matchRecipe, fakeSig, "recipe"], [missingRecipe, fakeSig, "recipe"]],
|
||||
"recipes with matching filters should have their signature verified",
|
||||
);
|
||||
Assert.deepEqual(
|
||||
runRecipeStub.args,
|
||||
[[matchRecipe], [missingRecipe]],
|
||||
"recipe with matching filters should be executed",
|
||||
"recipes with matching filters should be executed",
|
||||
);
|
||||
Assert.deepEqual(
|
||||
reportRecipeStub.args,
|
||||
|
@ -241,6 +250,42 @@ decorate_task(
|
|||
}
|
||||
);
|
||||
|
||||
decorate_task(
|
||||
withPrefEnv({
|
||||
set: [
|
||||
["features.normandy-remote-settings.enabled", true],
|
||||
],
|
||||
}),
|
||||
withStub(ActionsManager.prototype, "runRecipe"),
|
||||
withStub(NormandyApi, "get"),
|
||||
withStub(Uptake, "reportRunner"),
|
||||
async function testBadSignatureFromRemoteSettings(
|
||||
runRecipeStub,
|
||||
normandyGetStub,
|
||||
reportRunnerStub,
|
||||
) {
|
||||
normandyGetStub.resolves({ async text() { return "---CERT x5u----"; } });
|
||||
|
||||
const matchRecipe = { name: "badSig", action: "matchAction", filter_expression: "true" };
|
||||
|
||||
const rsCollection = await RecipeRunner._remoteSettingsClientForTesting.openCollection();
|
||||
await rsCollection.clear();
|
||||
const badSig = { x5u: "http://localhost/x5u", signature: "abc" };
|
||||
await rsCollection.create({ id: "badSig", recipe: matchRecipe, signature: badSig }, { synced: true });
|
||||
await rsCollection.db.saveLastModified(42);
|
||||
rsCollection.db.close();
|
||||
|
||||
await RecipeRunner.run();
|
||||
|
||||
ok(!runRecipeStub.called, "no recipe is executed");
|
||||
Assert.deepEqual(
|
||||
reportRunnerStub.args,
|
||||
[[Uptake.RUNNER_INVALID_SIGNATURE]],
|
||||
"RecipeRunner should report uptake telemetry",
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
decorate_task(
|
||||
withMockNormandyApi,
|
||||
async function testRunFetchFail(mockApi) {
|
||||
|
|
|
@ -41,7 +41,6 @@ skip-if = (os == 'linux' && debug) #Bug 1199778
|
|||
[test_classifier_match.html]
|
||||
[test_classifier_worker.html]
|
||||
[test_classify_by_default.html]
|
||||
skip-if = (os == 'android') #Bug 1538662
|
||||
[test_classify_ping.html]
|
||||
skip-if = (verify && debug && (os == 'win' || os == 'mac'))
|
||||
[test_classify_track.html]
|
||||
|
|
|
@ -14,9 +14,6 @@
|
|||
</div>
|
||||
<pre id="test">
|
||||
|
||||
<iframe id="testFrame1"></iframe>
|
||||
<iframe id="testFrame2"></iframe>
|
||||
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
// To add a request to test, add the request in trackerFrame.html
|
||||
|
@ -44,8 +41,9 @@ function setup() {
|
|||
});
|
||||
}
|
||||
|
||||
function loadTestFrame(withcookie, frameId) {
|
||||
function loadTestWindow(withcookie) {
|
||||
return new Promise(resolve => {
|
||||
let win;
|
||||
let query = withcookie ? "with-cookie" : "without-cookie";
|
||||
fetch(trackerFrame + "?callback=" + query, {
|
||||
credentials: "include",
|
||||
|
@ -57,12 +55,12 @@ function loadTestFrame(withcookie, frameId) {
|
|||
(withcookie ? "with" : "without") + " cookie";
|
||||
ok(trackers_found.includes(tracker), description);
|
||||
}
|
||||
win.close();
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
|
||||
let frame = document.getElementById(frameId);
|
||||
frame.src = "trackerFrame.html";
|
||||
win = window.open("trackerFrame.html");
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -77,13 +75,13 @@ async function runTests() {
|
|||
|
||||
await setup();
|
||||
|
||||
await loadTestFrame(true, "testFrame1");
|
||||
await loadTestWindow(true);
|
||||
|
||||
await SpecialPowers.pushPrefEnv({set: [
|
||||
[ "privacy.trackingprotection.annotate_channels", true],
|
||||
]});
|
||||
|
||||
await loadTestFrame(false, "testFrame2");
|
||||
await loadTestWindow(false);
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
|
|
@ -444,18 +444,7 @@
|
|||
event.initEvent(aType, true, true);
|
||||
|
||||
// handle dom event handlers
|
||||
var noCancel = aTarget.dispatchEvent(event);
|
||||
|
||||
// handle any xml attribute event handlers
|
||||
var handler = aTarget.getAttribute("on"+aType);
|
||||
if (handler != "") {
|
||||
var fn = new Function("event", handler);
|
||||
var returned = fn.apply(aTarget, [event]);
|
||||
if (returned == false)
|
||||
noCancel = false;
|
||||
}
|
||||
|
||||
return noCancel;
|
||||
return aTarget.dispatchEvent(event);
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
|
|
@ -308,6 +308,30 @@ var gUpdates = {
|
|||
this._cacheButtonStrings("extra1");
|
||||
this._cacheButtonStrings("extra2");
|
||||
|
||||
document.addEventListener("wizardfinish", function() { gUpdates.onWizardFinish(); });
|
||||
document.addEventListener("wizardcancel", function() { gUpdates.onWizardCancel(); });
|
||||
document.addEventListener("wizardnext", function() { gUpdates.onWizardNext(); });
|
||||
|
||||
document.getElementById("checking").addEventListener("pageshow", function() { gCheckingPage.onPageShow(); });
|
||||
document.getElementById("noupdatesfound").addEventListener("pageshow", function() { gNoUpdatesPage.onPageShow(); });
|
||||
document.getElementById("manualUpdate").addEventListener("pageshow", function() { gManualUpdatePage.onPageShow(); });
|
||||
document.getElementById("unsupported").addEventListener("pageshow", function() { gUnsupportedPage.onPageShow(); });
|
||||
document.getElementById("updatesfoundbasic").addEventListener("pageshow", function() { gUpdatesFoundBasicPage.onPageShow(); });
|
||||
document.getElementById("downloading").addEventListener("pageshow", function() { gDownloadingPage.onPageShow(); });
|
||||
document.getElementById("errors").addEventListener("pageshow", function() { gErrorsPage.onPageShow(); });
|
||||
document.getElementById("errorextra").addEventListener("pageshow", function() { gErrorExtraPage.onPageShow(); });
|
||||
document.getElementById("errorpatching").addEventListener("pageshow", function() { gErrorPatchingPage.onPageShow(); });
|
||||
document.getElementById("finished").addEventListener("pageshow", function() { gFinishedPage.onPageShow(); });
|
||||
document.getElementById("finishedBackground").addEventListener("pageshow", function() { gFinishedPage.onPageShowBackground(); });
|
||||
|
||||
document.getElementById("updatesfoundbasic").addEventListener("extra1", function() { gUpdatesFoundBasicPage.onExtra1(); });
|
||||
document.getElementById("downloading").addEventListener("extra1", function() { gDownloadingPage.onHide(); });
|
||||
document.getElementById("finished").addEventListener("extra1", function() { gFinishedPage.onExtra1(); });
|
||||
document.getElementById("finishedBackground").addEventListener("extra1", function() { gFinishedPage.onExtra1(); });
|
||||
|
||||
document.getElementById("updatesfoundbasic").addEventListener("extra2", function() { gUpdatesFoundBasicPage.onExtra2(); });
|
||||
document.getElementById("finishedBackground").addEventListener("extra2", function() { gFinishedPage.onExtra2(); });
|
||||
|
||||
// Advance to the Start page.
|
||||
this.getStartPageID(function(startPageID) {
|
||||
LOG("gUpdates", "onLoad - setting current page to startpage " + startPageID);
|
||||
|
|
|
@ -24,9 +24,6 @@
|
|||
title="&updateWizard.title;"
|
||||
windowtype="Update:Wizard"
|
||||
style="width: auto; height: auto"
|
||||
onwizardfinish="gUpdates.onWizardFinish();"
|
||||
onwizardcancel="gUpdates.onWizardCancel();"
|
||||
onwizardnext="gUpdates.onWizardNext();"
|
||||
onload="gUpdates.onLoad();"
|
||||
onunload="gUpdates.onUnload();">
|
||||
|
||||
|
@ -47,7 +44,7 @@
|
|||
<wizardpage id="dummy" pageid="dummy" firstpage="true"/>
|
||||
|
||||
<wizardpage id="checking" pageid="checking" next="noupdatesfound"
|
||||
object="gCheckingPage" onpageshow="gCheckingPage.onPageShow();">
|
||||
object="gCheckingPage">
|
||||
<updateheader label="&checking.title;"/>
|
||||
<vbox class="update-content" flex="1">
|
||||
<label>&updateCheck.label;</label>
|
||||
|
@ -57,7 +54,7 @@
|
|||
</wizardpage>
|
||||
|
||||
<wizardpage id="noupdatesfound" pageid="noupdatesfound"
|
||||
object="gNoUpdatesPage" onpageshow="gNoUpdatesPage.onPageShow();">
|
||||
object="gNoUpdatesPage">
|
||||
<updateheader label="&noupdatesfound.title;"/>
|
||||
<vbox class="update-content" flex="1">
|
||||
<label id="noUpdatesAutoEnabled" hidden="true">&noupdatesautoenabled.intro;</label>
|
||||
|
@ -65,8 +62,7 @@
|
|||
</vbox>
|
||||
</wizardpage>
|
||||
|
||||
<wizardpage id="manualUpdate" pageid="manualUpdate" object="gManualUpdatePage"
|
||||
onpageshow="gManualUpdatePage.onPageShow();">
|
||||
<wizardpage id="manualUpdate" pageid="manualUpdate" object="gManualUpdatePage">
|
||||
<updateheader label="&manualUpdate.title;"/>
|
||||
<vbox class="update-content" flex="1">
|
||||
<label id="manualUpdateDesc">&manualUpdate.desc;</label>
|
||||
|
@ -82,8 +78,7 @@
|
|||
</wizardpage>
|
||||
|
||||
<wizardpage id="unsupported" pageid="unsupported"
|
||||
object="gUnsupportedPage"
|
||||
onpageshow="gUnsupportedPage.onPageShow();">
|
||||
object="gUnsupportedPage">
|
||||
<updateheader label="&unsupported.title;"/>
|
||||
<vbox class="update-content" flex="1">
|
||||
<description flex="1">&unsupported.label;
|
||||
|
@ -95,10 +90,7 @@
|
|||
</wizardpage>
|
||||
|
||||
<wizardpage id="updatesfoundbasic" pageid="updatesfoundbasic"
|
||||
object="gUpdatesFoundBasicPage" next="downloading"
|
||||
onpageshow="gUpdatesFoundBasicPage.onPageShow();"
|
||||
onextra1="gUpdatesFoundBasicPage.onExtra1();"
|
||||
onextra2="gUpdatesFoundBasicPage.onExtra2();">
|
||||
object="gUpdatesFoundBasicPage" next="downloading">
|
||||
<updateheader id="updatesFoundBasicHeader" label=""/>
|
||||
<vbox class="update-content" flex="1">
|
||||
<label id="updatesFoundInto"/>
|
||||
|
@ -117,8 +109,7 @@
|
|||
</wizardpage>
|
||||
|
||||
<wizardpage id="downloading" pageid="downloading"
|
||||
object="gDownloadingPage" onextra1="gDownloadingPage.onHide();"
|
||||
onpageshow="gDownloadingPage.onPageShow();">
|
||||
object="gDownloadingPage">
|
||||
<updateheader label="&downloadPage.title;"/>
|
||||
<vbox class="update-content" flex="1">
|
||||
<hbox id="downloadStatusProgress">
|
||||
|
@ -138,8 +129,7 @@
|
|||
</vbox>
|
||||
</wizardpage>
|
||||
|
||||
<wizardpage id="errors" pageid="errors" object="gErrorsPage"
|
||||
onpageshow="gErrorsPage.onPageShow();">
|
||||
<wizardpage id="errors" pageid="errors" object="gErrorsPage">
|
||||
<updateheader label="&error.title;"/>
|
||||
<vbox class="update-content" flex="1">
|
||||
<label id="errorIntro">&error.label;</label>
|
||||
|
@ -155,8 +145,7 @@
|
|||
</wizardpage>
|
||||
|
||||
<wizardpage id="errorextra" pageid="errorextra"
|
||||
object="gErrorExtraPage"
|
||||
onpageshow="gErrorExtraPage.onPageShow();">
|
||||
object="gErrorExtraPage">
|
||||
<updateheader label="&error.title;"/>
|
||||
<vbox class="update-content" flex="1">
|
||||
<label id="bgErrorLabel">&genericBackgroundError.label;</label>
|
||||
|
@ -168,17 +157,14 @@
|
|||
</wizardpage>
|
||||
|
||||
<wizardpage id="errorpatching" pageid="errorpatching" next="downloading"
|
||||
object="gErrorPatchingPage"
|
||||
onpageshow="gErrorPatchingPage.onPageShow();">
|
||||
object="gErrorPatchingPage">
|
||||
<updateheader label="&error.title;"/>
|
||||
<vbox class="update-content" flex="1">
|
||||
<label>&errorpatching.intro;</label>
|
||||
</vbox>
|
||||
</wizardpage>
|
||||
|
||||
<wizardpage id="finished" pageid="finished" object="gFinishedPage"
|
||||
onpageshow="gFinishedPage.onPageShow();"
|
||||
onextra1="gFinishedPage.onExtra1()">
|
||||
<wizardpage id="finished" pageid="finished" object="gFinishedPage">
|
||||
<updateheader label="&finishedPage.title;"/>
|
||||
<vbox class="update-content" flex="1">
|
||||
<label>&finishedPage.text;</label>
|
||||
|
@ -186,9 +172,7 @@
|
|||
</wizardpage>
|
||||
|
||||
<wizardpage id="finishedBackground" pageid="finishedBackground"
|
||||
object="gFinishedPage" onextra1="gFinishedPage.onExtra1()"
|
||||
onextra2="gFinishedPage.onExtra2()"
|
||||
onpageshow="gFinishedPage.onPageShowBackground();">
|
||||
object="gFinishedPage">
|
||||
<updateheader label="&finishedPage.title;"/>
|
||||
<vbox class="update-content" flex="1">
|
||||
<label>&finishedBackgroundPage.text;</label>
|
||||
|
|
|
@ -31,6 +31,9 @@ function initWizard() {
|
|||
|
||||
// Initialize the profile location display.
|
||||
gProfileDisplay = document.getElementById("profileDisplay").firstChild;
|
||||
document.addEventListener("wizardfinish", onFinish);
|
||||
document.getElementById("explanation").addEventListener("pageshow", enableNextButton);
|
||||
document.getElementById("createProfile").addEventListener("pageshow", initSecondWizardPage);
|
||||
setDisplayToDefaultFolder();
|
||||
} catch (e) {
|
||||
window.close();
|
||||
|
@ -169,7 +172,7 @@ function enableNextButton() {
|
|||
document.documentElement.canAdvance = true;
|
||||
}
|
||||
|
||||
function onFinish() {
|
||||
function onFinish(event) {
|
||||
var profileName = document.getElementById("profileName").value;
|
||||
var profile;
|
||||
|
||||
|
@ -184,7 +187,8 @@ function onFinish() {
|
|||
Services.prompt.alert(window, profileCreationFailedTitle,
|
||||
profileCreationFailed + "\n" + e);
|
||||
|
||||
return false;
|
||||
event.preventDefault();
|
||||
return;
|
||||
}
|
||||
|
||||
// window.opener is false if the Create Profile Wizard was opened from the
|
||||
|
@ -199,7 +203,4 @@ function onFinish() {
|
|||
var dialogParams = window.arguments[0].QueryInterface(I.nsIDialogParamBlock);
|
||||
dialogParams.objects.insertElementAt(profileLock, 0);
|
||||
}
|
||||
|
||||
// Exit the wizard.
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
xmlns:html="http://www.w3.org/1999/xhtml"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
onwizardfinish="return onFinish();"
|
||||
onload="initWizard();"
|
||||
style="&window.size;">
|
||||
<script type="application/javascript"
|
||||
|
@ -28,7 +27,7 @@
|
|||
|
||||
<script type="application/javascript" src="chrome://mozapps/content/profile/createProfileWizard.js"/>
|
||||
|
||||
<wizardpage id="explanation" onpageshow="enableNextButton();">
|
||||
<wizardpage id="explanation">
|
||||
<description>&profileCreationExplanation_1.text;</description>
|
||||
<description>&profileCreationExplanation_2.text;</description>
|
||||
<description>&profileCreationExplanation_3.text;</description>
|
||||
|
@ -44,7 +43,7 @@
|
|||
#endif
|
||||
</wizardpage>
|
||||
|
||||
<wizardpage id="createProfile" onpageshow="initSecondWizardPage();">
|
||||
<wizardpage id="createProfile">
|
||||
<description>&profileCreationIntro.text;</description>
|
||||
|
||||
<label accesskey="&profilePrompt.accesskey;" control="ProfileName">&profilePrompt.label;</label>
|
||||
|
|
|
@ -134,6 +134,7 @@ clang_checkers:
|
|||
- name: readability-misleading-indentation
|
||||
- name: readability-non-const-parameter
|
||||
- name: readability-redundant-control-flow
|
||||
- name: readability-redundant-preprocessor
|
||||
- name: readability-redundant-smartptr-get
|
||||
- name: readability-redundant-string-cstr
|
||||
- name: readability-redundant-string-init
|
||||
|
|
|
@ -33,7 +33,7 @@ using namespace mozilla;
|
|||
// Linux, to avoid naming clashes in builds which mix GCC and LLVM. So, when we
|
||||
// are building with LLVM exclusively, we need to use __custom_llvm_gcov_flush
|
||||
// instead.
|
||||
#if defined(XP_LINUX) && defined(__clang__)
|
||||
#if !defined(XP_WIN) && defined(__clang__)
|
||||
# define __gcov_flush __custom_llvm_gcov_flush
|
||||
#endif
|
||||
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#endif
|
||||
#include "nsNetCID.h"
|
||||
#include "nsThread.h"
|
||||
#include "VRProcessManager.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/MemoryReportingProcess.h"
|
||||
#include "mozilla/PodOperations.h"
|
||||
|
@ -1814,6 +1815,12 @@ nsresult nsMemoryReporterManager::StartGettingReports() {
|
|||
}
|
||||
}
|
||||
|
||||
if (gfx::VRProcessManager* vr = gfx::VRProcessManager::Get()) {
|
||||
if (RefPtr<MemoryReportingProcess> proc = vr->GetProcessMemoryReporter()) {
|
||||
s->mChildrenPending.AppendElement(proc.forget());
|
||||
}
|
||||
}
|
||||
|
||||
if (!mIsRegistrationBlocked && net::gIOService) {
|
||||
if (RefPtr<MemoryReportingProcess> proc =
|
||||
net::gIOService->GetSocketProcessMemoryReporter()) {
|
||||
|
|
|
@ -67,7 +67,7 @@ Classes = [
|
|||
'type': 'nsMemoryReporterManager',
|
||||
'headers': ['/xpcom/base/nsMemoryReporterManager.h'],
|
||||
'init_method': 'Init',
|
||||
'processes': ProcessSelector.ALLOW_IN_GPU_AND_SOCKET_PROCESS,
|
||||
'processes': ProcessSelector.ALLOW_IN_GPU_VR_AND_SOCKET_PROCESS,
|
||||
},
|
||||
{
|
||||
'cid': '{7b4eeb20-d781-11d4-8a83-0010a4e0c9ca}',
|
||||
|
|
|
@ -26,7 +26,7 @@ if CONFIG['OS_ARCH'] == 'GNU':
|
|||
'xptcstubs_gcc_x86_unix.cpp'
|
||||
]
|
||||
|
||||
if CONFIG['OS_ARCH'] in ('Linux', 'Bitrig', 'DragonFly', 'FreeBSD', 'NetBSD', 'OpenBSD') or \
|
||||
if CONFIG['OS_ARCH'] in ('Linux', 'Bitrig', 'DragonFly', 'FreeBSD', 'NetBSD', 'OpenBSD', 'SunOS') or \
|
||||
CONFIG['OS_ARCH'].startswith('GNU_'):
|
||||
if CONFIG['CPU_ARCH'] == 'x86_64':
|
||||
SOURCES += [
|
||||
|
@ -49,41 +49,6 @@ if CONFIG['OS_ARCH'] in ('Linux', 'FreeBSD'):
|
|||
'xptcstubs_ipf64.cpp'
|
||||
]
|
||||
|
||||
if CONFIG['OS_ARCH'] == 'SunOS' and CONFIG['INTEL_ARCHITECTURE']:
|
||||
if CONFIG['CPU_ARCH'] == 'x86_64':
|
||||
if CONFIG['CC_TYPE'] in ('clang', 'gcc'):
|
||||
SOURCES += [
|
||||
'xptcinvoke_asm_x86_64_unix.S',
|
||||
'xptcinvoke_x86_64_unix.cpp',
|
||||
'xptcstubs_x86_64_linux.cpp'
|
||||
]
|
||||
else:
|
||||
GENERATED_FILES = [
|
||||
'xptcstubsdef_asm.solx86',
|
||||
]
|
||||
ASFLAGS += ['-xarch=amd64']
|
||||
SOURCES += [
|
||||
'xptcinvoke_x86_64_solaris.cpp',
|
||||
'xptcstubs_asm_x86_64_solaris_SUNW.s',
|
||||
'xptcstubs_x86_64_solaris.cpp',
|
||||
]
|
||||
else:
|
||||
if CONFIG['CC_TYPE'] in ('clang', 'gcc'):
|
||||
SOURCES += [
|
||||
'xptcinvoke_gcc_x86_unix.cpp',
|
||||
'xptcstubs_gcc_x86_unix.cpp'
|
||||
]
|
||||
else:
|
||||
GENERATED_FILES = [
|
||||
'xptcstubsdef_asm.solx86',
|
||||
]
|
||||
SOURCES += [
|
||||
'xptcinvoke_asm_x86_solaris_SUNW.s',
|
||||
'xptcinvoke_x86_solaris.cpp',
|
||||
'xptcstubs_asm_x86_solaris_SUNW.s',
|
||||
'xptcstubs_x86_solaris.cpp'
|
||||
]
|
||||
|
||||
if CONFIG['CPU_ARCH'] == 'Alpha':
|
||||
if CONFIG['OS_ARCH'] in ('Linux', 'FreeBSD', 'NetBSD'):
|
||||
SOURCES += [
|
||||
|
@ -240,7 +205,7 @@ if CONFIG['OS_ARCH'] == 'OpenBSD' and CONFIG['CPU_ARCH'] == 'sparc':
|
|||
'xptcstubs_sparc_openbsd.cpp',
|
||||
]
|
||||
|
||||
if CONFIG['OS_ARCH'] in ('OpenBSD', 'FreeBSD', 'Linux') and CONFIG['CPU_ARCH'] == 'sparc64':
|
||||
if CONFIG['OS_ARCH'] in ('OpenBSD', 'FreeBSD', 'Linux', 'SunOS') and CONFIG['CPU_ARCH'] == 'sparc64':
|
||||
SOURCES += [
|
||||
'xptcinvoke_asm_sparc64_openbsd.s',
|
||||
'xptcinvoke_sparc64_openbsd.cpp',
|
||||
|
@ -248,35 +213,6 @@ if CONFIG['OS_ARCH'] in ('OpenBSD', 'FreeBSD', 'Linux') and CONFIG['CPU_ARCH'] =
|
|||
'xptcstubs_sparc64_openbsd.cpp',
|
||||
]
|
||||
|
||||
if CONFIG['OS_ARCH'] == 'SunOS' and not CONFIG['INTEL_ARCHITECTURE']:
|
||||
if CONFIG['HAVE_64BIT_BUILD']:
|
||||
ASFLAGS += ['-xarch=v9']
|
||||
SOURCES += [
|
||||
'xptcinvoke_sparcv9_solaris.cpp',
|
||||
'xptcstubs_sparcv9_solaris.cpp',
|
||||
]
|
||||
else:
|
||||
SOURCES += [
|
||||
'xptcinvoke_sparc_solaris.cpp',
|
||||
'xptcstubs_sparc_solaris.cpp',
|
||||
]
|
||||
if CONFIG['CC_TYPE'] in ('clang', 'gcc'):
|
||||
SOURCES += [
|
||||
'xptcinvoke_asm_sparc_solaris_GCC3.s',
|
||||
'xptcstubs_asm_sparc_solaris.s',
|
||||
]
|
||||
else:
|
||||
if CONFIG['HAVE_64BIT_BUILD']:
|
||||
SOURCES += [
|
||||
'xptcinvoke_asm_sparcv9_solaris_SUNW.s',
|
||||
'xptcstubs_asm_sparcv9_solaris.s',
|
||||
]
|
||||
else:
|
||||
SOURCES += [
|
||||
'xptcinvoke_asm_sparc_solaris_SUNW.s',
|
||||
'xptcstubs_asm_sparc_solaris.s',
|
||||
]
|
||||
|
||||
if CONFIG['OS_ARCH'] == 'Linux':
|
||||
if CONFIG['CPU_ARCH'] == 's390':
|
||||
SOURCES += [
|
||||
|
|
|
@ -1,52 +0,0 @@
|
|||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* 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/. */
|
||||
|
||||
/*
|
||||
* Platform specific code to invoke XPCOM methods on native objects for
|
||||
* solaris/sparc with gcc 3 ABI.
|
||||
*/
|
||||
.global NS_InvokeByIndex
|
||||
/*
|
||||
* NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
|
||||
* uint32_t paramCount, nsXPTCVariant* params);
|
||||
*/
|
||||
NS_InvokeByIndex:
|
||||
save %sp,-(64 + 32),%sp ! room for the register window and
|
||||
! struct pointer, rounded up to 0 % 32
|
||||
mov %i2,%o0 ! paramCount
|
||||
call invoke_count_words ! returns the required stack size in %o0
|
||||
mov %i3,%o1 ! params
|
||||
|
||||
sll %o0,2,%l0 ! number of bytes
|
||||
sub %sp,%l0,%sp ! create the additional stack space
|
||||
|
||||
mov %sp,%o0 ! pointer for copied args
|
||||
add %o0,72,%o0 ! step past the register window, the
|
||||
! struct result pointer and the 'this' slot
|
||||
mov %i2,%o1 ! paramCount
|
||||
call invoke_copy_to_stack
|
||||
mov %i3,%o2 ! params
|
||||
!
|
||||
! calculate the target address from the vtable
|
||||
!
|
||||
ld [%i0],%l1 ! *that --> vTable
|
||||
sll %i1,2,%i1 ! multiply index by 4
|
||||
add %i1,%l1,%l1 ! l1 now points to vTable entry
|
||||
ld [%l1],%l0 ! target address
|
||||
|
||||
.L5: ld [%sp + 88],%o5
|
||||
.L4: ld [%sp + 84],%o4
|
||||
.L3: ld [%sp + 80],%o3
|
||||
.L2: ld [%sp + 76],%o2
|
||||
.L1: ld [%sp + 72],%o1
|
||||
.L0:
|
||||
jmpl %l0,%o7 ! call the routine
|
||||
! always have a 'this', from the incoming 'that'
|
||||
mov %i0,%o0
|
||||
|
||||
mov %o0,%i0 ! propagate return value
|
||||
ret
|
||||
restore
|
|
@ -1,56 +0,0 @@
|
|||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* 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/. */
|
||||
|
||||
/* Platform specific code to invoke XPCOM methods on native objects */
|
||||
|
||||
.global NS_InvokeByIndex
|
||||
.type NS_InvokeByIndex, #function
|
||||
/*
|
||||
NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
|
||||
uint32_t paramCount, nsXPTCVariant* params);
|
||||
|
||||
*/
|
||||
NS_InvokeByIndex:
|
||||
save %sp,-(64 + 32),%sp ! room for the register window and
|
||||
! struct pointer, rounded up to 0 % 32
|
||||
sll %i2,3,%l0 ! assume the worst case
|
||||
! paramCount * 2 * 4 bytes
|
||||
cmp %l0, 0 ! are there any args? If not,
|
||||
be .invoke ! no need to copy args to stack
|
||||
|
||||
sub %sp,%l0,%sp ! create the additional stack space
|
||||
add %sp,72,%o0 ! step past the register window, the
|
||||
! struct result pointer and the 'this' slot
|
||||
mov %i2,%o1 ! paramCount
|
||||
call invoke_copy_to_stack
|
||||
mov %i3,%o2 ! params
|
||||
|
||||
!
|
||||
! load arguments from stack into the outgoing registers
|
||||
!
|
||||
ld [%sp + 72],%o1
|
||||
ld [%sp + 76],%o2
|
||||
ld [%sp + 80],%o3
|
||||
ld [%sp + 84],%o4
|
||||
ld [%sp + 88],%o5
|
||||
|
||||
!
|
||||
! calculate the target address from the vtable
|
||||
!
|
||||
.invoke:
|
||||
sll %i1,2,%l0 ! index *= 4
|
||||
add %l0,8,%l0 ! there are 2 extra entries in the vTable
|
||||
ld [%i0],%l1 ! *that --> address of vtable
|
||||
ld [%l0 + %l1],%l0 ! that->vtable[index * 4 + 8] --> address
|
||||
|
||||
jmpl %l0,%o7 ! call the routine
|
||||
mov %i0,%o0 ! move 'this' pointer to out register
|
||||
|
||||
mov %o0,%i0 ! propagate return value
|
||||
ret
|
||||
restore
|
||||
|
||||
.size NS_InvokeByIndex, .-NS_InvokeByIndex
|
|
@ -1,85 +0,0 @@
|
|||
/* -*- Mode: asm; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* 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/. */
|
||||
|
||||
/*
|
||||
Platform specific code to invoke XPCOM methods on native objects
|
||||
for sparcv9 Solaris.
|
||||
|
||||
See the SPARC Compliance Definition (SCD) Chapter 3
|
||||
for more information about what is going on here, including
|
||||
the use of BIAS (0x7ff).
|
||||
The SCD is available from http://www.sparc.com/.
|
||||
*/
|
||||
|
||||
.global NS_InvokeByIndex
|
||||
.type NS_InvokeByIndex, #function
|
||||
|
||||
/*
|
||||
NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
|
||||
uint32_t paramCount, nsXPTCVariant* params);
|
||||
|
||||
*/
|
||||
NS_InvokeByIndex:
|
||||
save %sp,-(128 + 64),%sp ! room for the register window and
|
||||
! struct pointer, rounded up to 0 % 64
|
||||
sll %i2,4,%l0 ! assume the worst case
|
||||
! paramCount * 2 * 8 bytes
|
||||
cmp %l0, 0 ! are there any args? If not,
|
||||
be .invoke ! no need to copy args to stack
|
||||
|
||||
sub %sp,%l0,%sp ! create the additional stack space
|
||||
add %sp,0x7ff+136,%o0 ! step past the register window, the
|
||||
! struct result pointer and the 'this' slot
|
||||
mov %i2,%o1 ! paramCount
|
||||
call invoke_copy_to_stack
|
||||
mov %i3,%o2 ! params
|
||||
|
||||
!
|
||||
! load arguments from stack into the outgoing registers
|
||||
! BIAS is 0x7ff (2047)
|
||||
!
|
||||
|
||||
! load the %o1..5 64bit (extended word) output registers registers
|
||||
ldx [%sp + 0x7ff + 136],%o1 ! %i1
|
||||
ldx [%sp + 0x7ff + 144],%o2 ! %i2
|
||||
ldx [%sp + 0x7ff + 152],%o3 ! %i3
|
||||
ldx [%sp + 0x7ff + 160],%o4 ! %i4
|
||||
ldx [%sp + 0x7ff + 168],%o5 ! %i5
|
||||
|
||||
! load the even number double registers starting with %d2
|
||||
ldd [%sp + 0x7ff + 136],%d2
|
||||
ldd [%sp + 0x7ff + 144],%d4
|
||||
ldd [%sp + 0x7ff + 152],%d6
|
||||
ldd [%sp + 0x7ff + 160],%d8
|
||||
ldd [%sp + 0x7ff + 168],%d10
|
||||
ldd [%sp + 0x7ff + 176],%d12
|
||||
ldd [%sp + 0x7ff + 184],%d14
|
||||
ldd [%sp + 0x7ff + 192],%d16
|
||||
ldd [%sp + 0x7ff + 200],%d18
|
||||
ldd [%sp + 0x7ff + 208],%d20
|
||||
ldd [%sp + 0x7ff + 216],%d22
|
||||
ldd [%sp + 0x7ff + 224],%d24
|
||||
ldd [%sp + 0x7ff + 232],%d26
|
||||
ldd [%sp + 0x7ff + 240],%d28
|
||||
ldd [%sp + 0x7ff + 248],%d30
|
||||
|
||||
!
|
||||
! calculate the target address from the vtable
|
||||
!
|
||||
.invoke:
|
||||
sll %i1,3,%l0 ! index *= 8
|
||||
add %l0,16,%l0 ! there are 2 extra entries in the vTable (16bytes)
|
||||
ldx [%i0],%l1 ! *that --> address of vtable
|
||||
ldx [%l0 + %l1],%l0 ! that->vtable[index * 8 + 16] --> address
|
||||
|
||||
jmpl %l0,%o7 ! call the routine
|
||||
mov %i0,%o0 ! move 'this' pointer to out register
|
||||
|
||||
mov %o0,%i0 ! propagate return value
|
||||
ret
|
||||
restore
|
||||
|
||||
.size NS_InvokeByIndex, .-NS_InvokeByIndex
|
|
@ -1,55 +0,0 @@
|
|||
.globl NS_InvokeByIndex
|
||||
.type NS_InvokeByIndex, @function
|
||||
NS_InvokeByIndex:
|
||||
push %ebp
|
||||
movl %esp,%ebp
|
||||
push %ebx
|
||||
call .CG0.66
|
||||
.CG0.66:
|
||||
pop %ebx
|
||||
addl $_GLOBAL_OFFSET_TABLE_+0x1,%ebx
|
||||
push 20(%ebp)
|
||||
push 16(%ebp)
|
||||
push 12(%ebp)
|
||||
push 8(%ebp)
|
||||
/ INLINE: invoke_by_index
|
||||
|
||||
|
||||
|
||||
pushl %ebx
|
||||
pushl %esi
|
||||
movl %esp, %ebx
|
||||
|
||||
pushl 0x14(%ebp)
|
||||
pushl 0x10(%ebp)
|
||||
call invoke_count_words
|
||||
mov %ebx, %esp
|
||||
|
||||
sall $0x2 , %eax
|
||||
subl %eax, %esp
|
||||
movl %esp, %esi
|
||||
|
||||
pushl %esp
|
||||
pushl 0x14(%ebp)
|
||||
pushl 0x10(%ebp)
|
||||
call invoke_copy_to_stack
|
||||
movl %esi, %esp
|
||||
|
||||
movl 0x8(%ebp), %ecx
|
||||
pushl %ecx
|
||||
movl (%ecx), %edx
|
||||
movl 0xc(%ebp), %eax
|
||||
movl 0x8(%edx, %eax, 4), %edx
|
||||
|
||||
call *%edx
|
||||
mov %ebx, %esp
|
||||
popl %esi
|
||||
popl %ebx
|
||||
/ INLINE_END
|
||||
addl $16,%esp
|
||||
pop %ebx
|
||||
movl %ebp,%esp
|
||||
pop %ebp
|
||||
ret
|
||||
.size NS_InvokeByIndex, . - NS_InvokeByIndex
|
||||
|
|
@ -30,9 +30,9 @@ invoke_copy_to_stack(uint64_t* d, uint32_t paramCount, nsXPTCVariant* s)
|
|||
{
|
||||
if (regCount < 5) regCount++;
|
||||
|
||||
if (l_s->IsPtrData())
|
||||
if (l_s->IsIndirect())
|
||||
{
|
||||
*l_d = (uint64_t)l_s->ptr;
|
||||
*l_d = (uint64_t) &l_s->val;
|
||||
continue;
|
||||
}
|
||||
switch (l_s->type)
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче