merge mozilla-central to mozilla-inbound. r=merge a=merge

This commit is contained in:
Sebastian Hengst 2017-08-05 12:00:50 +02:00
Родитель f257cde65c 39ccebaf18
Коммит 75303aec29
148 изменённых файлов: 2219 добавлений и 2573 удалений

Просмотреть файл

@ -1134,6 +1134,7 @@ toolbarpaletteitem[place="palette"] > #downloads-button[indicator] > #downloads-
-moz-image-region: auto;
}
%ifdef MOZ_PHOTON_ANIMATIONS
%ifdef MOZ_WIDGET_COCOA
/* On Mac, use the properties "-moz-window-transform" and "-moz-window-opacity"
@ -1144,6 +1145,61 @@ toolbarpaletteitem[place="palette"] > #downloads-button[indicator] > #downloads-
lot faster. In fact, Gecko no longer triggers shadow shape recomputations
for repaints.
These properties are not implemented on other platforms. */
#BMB_bookmarksPopup:not([animate="false"]) {
-moz-window-opacity: 0;
-moz-window-transform: translateY(-70px);
transition-property: -moz-window-transform, -moz-window-opacity;
transition-duration: 0.18s, 0.18s;
transition-timing-function:
var(--animation-easing-function), ease-out;
}
#BMB_bookmarksPopup[side="bottom"]:not([animate="false"]) {
-moz-window-transform: translateY(70px);
}
#BMB_bookmarksPopup[side][animate="open"] {
-moz-window-opacity: 1.0;
transition-duration: 0.18s, 0.18s;
-moz-window-transform: none;
transition-timing-function:
var(--animation-easing-function), ease-in-out;
}
#BMB_bookmarksPopup[animate="cancel"] {
-moz-window-transform: none;
}
%elifndef MOZ_WIDGET_GTK
#BMB_bookmarksPopup:not([animate="false"]) {
opacity: 0;
transform: translateY(-70px);
transition-property: transform, opacity;
transition-duration: 0.18s, 0.18s;
transition-timing-function:
var(--animation-easing-function), ease-out;
}
#BMB_bookmarksPopup[side="bottom"]:not([animate="false"]) {
transform: translateY(70px);
}
#BMB_bookmarksPopup[side][animate="open"] {
opacity: 1.0;
transition-duration: 0.18s, 0.18s;
transform: none;
transition-timing-function:
var(--animation-easing-function), ease-in-out;
}
#BMB_bookmarksPopup[animate="cancel"] {
transform: none;
}
%endif
%else
%ifdef MOZ_WIDGET_COCOA
#BMB_bookmarksPopup {
-moz-window-transform: scale(.4);
-moz-window-opacity: 0;
@ -1220,6 +1276,7 @@ toolbarpaletteitem[place="palette"] > #downloads-button[indicator] > #downloads-
transform-origin: calc(100% - 20px) bottom;
}
%endif
%endif
/* Customize mode */
%ifndef MOZ_PHOTON_THEME

Просмотреть файл

@ -1452,6 +1452,11 @@ var gBrowserInit = {
gIdentityHandler.refreshIdentityBlock();
});
// Get the service so that it initializes and registers listeners for new
// tab pages in order to be ready for any early-loading about:newtab pages,
// e.g., start/home page, command line / startup uris to load, sessionstore
gAboutNewTabService.QueryInterface(Ci.nsISupports);
let uriToLoad = this._getUriToLoad();
if (uriToLoad && uriToLoad != "about:blank") {
if (uriToLoad instanceof Ci.nsIArray) {

Просмотреть файл

@ -188,7 +188,7 @@ CustomizeMode.prototype = {
win.gBrowser.setTabTitle(gTab);
win.gBrowser.setIcon(gTab,
"chrome://browser/skin/customizableui/customizeFavicon.ico");
"chrome://browser/skin/customize.svg");
gTab.addEventListener("TabClose", unregisterGlobalTab);

Просмотреть файл

@ -19,13 +19,13 @@ const kSmallWidth = 400;
function bookmarksMenuPanelShown() {
return new Promise(resolve => {
let bookmarksMenuPopup = document.getElementById("BMB_bookmarksPopup");
let onTransitionEnd = (e) => {
let onPopupShown = (e) => {
if (e.target == bookmarksMenuPopup) {
bookmarksMenuPopup.removeEventListener("transitionend", onTransitionEnd);
bookmarksMenuPopup.removeEventListener("popupshown", onPopupShown);
resolve();
}
}
bookmarksMenuPopup.addEventListener("transitionend", onTransitionEnd);
bookmarksMenuPopup.addEventListener("popupshown", onPopupShown);
});
}

Просмотреть файл

@ -10,8 +10,8 @@ const {utils: Cu, interfaces: Ci} = Components;
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/Services.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "Preferences",
"resource://gre/modules/Preferences.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "AboutNewTab",
"resource:///modules/AboutNewTab.jsm");
const LOCAL_NEWTAB_URL = "chrome://browser/content/newtab/newTab.xhtml";
@ -19,12 +19,18 @@ const ACTIVITY_STREAM_URL = "resource://activity-stream/data/content/activity-st
const ABOUT_URL = "about:newtab";
const IS_MAIN_PROCESS = Services.appinfo.processType === Services.appinfo.PROCESS_TYPE_DEFAULT;
// Pref that tells if activity stream is enabled
const PREF_ACTIVITY_STREAM_ENABLED = "browser.newtabpage.activity-stream.enabled";
function AboutNewTabService() {
Preferences.observe(PREF_ACTIVITY_STREAM_ENABLED, this._handleToggleEvent.bind(this));
this.toggleActivityStream(Services.prefs.getBoolPref(PREF_ACTIVITY_STREAM_ENABLED));
Services.obs.addObserver(this, "quit-application-granted");
Services.prefs.addObserver(PREF_ACTIVITY_STREAM_ENABLED, this);
this.toggleActivityStream();
if (IS_MAIN_PROCESS) {
AboutNewTab.init();
}
}
/*
@ -68,14 +74,28 @@ AboutNewTabService.prototype = {
_overridden: false,
classID: Components.ID("{dfcd2adc-7867-4d3a-ba70-17501f208142}"),
QueryInterface: XPCOMUtils.generateQI([Ci.nsIAboutNewTabService]),
QueryInterface: XPCOMUtils.generateQI([
Ci.nsIAboutNewTabService,
Ci.nsIObserver
]),
_xpcom_categories: [{
service: true
}],
_handleToggleEvent(stateEnabled) {
if (this.toggleActivityStream(stateEnabled)) {
Services.obs.notifyObservers(null, "newtab-url-changed", ABOUT_URL);
observe(subject, topic, data) {
switch (topic) {
case "nsPref:changed":
if (this.toggleActivityStream()) {
Services.obs.notifyObservers(null, "newtab-url-changed", ABOUT_URL);
}
break;
case "quit-application-granted":
Services.obs.removeObserver(this, "quit-application-granted");
Services.prefs.removeObserver(PREF_ACTIVITY_STREAM_ENABLED, this);
if (IS_MAIN_PROCESS) {
AboutNewTab.uninit();
}
break;
}
},
@ -93,7 +113,8 @@ AboutNewTabService.prototype = {
* @param {Boolean} stateEnabled activity stream enabled state to set to
* @param {Boolean} forceState force state change
*/
toggleActivityStream(stateEnabled, forceState = false) {
toggleActivityStream(stateEnabled = Services.prefs.getBoolPref(PREF_ACTIVITY_STREAM_ENABLED),
forceState = false) {
if (!forceState && (this.overridden || stateEnabled === this.activityStreamEnabled)) {
// exit there is no change of state
@ -158,7 +179,7 @@ AboutNewTabService.prototype = {
resetNewTabURL() {
this._overridden = false;
this._newTabURL = ABOUT_URL;
this.toggleActivityStream(Services.prefs.getBoolPref(PREF_ACTIVITY_STREAM_ENABLED), true);
this.toggleActivityStream(undefined, true);
Services.obs.notifyObservers(null, "newtab-url-changed", this._newTabURL);
}
};

Просмотреть файл

@ -25,7 +25,7 @@ XPCOMUtils.defineLazyModuleGetter(this, "SafeBrowsing",
// lazy module getters
/* global AboutHome:false, AboutNewTab:false, AddonManager:false, AppMenuNotifications:false,
/* global AboutHome:false, AddonManager:false, AppMenuNotifications:false,
AsyncPrefs: false, AsyncShutdown:false, AutoCompletePopup:false, BookmarkHTMLUtils:false,
BookmarkJSONUtils:false, BrowserUITelemetry:false, BrowserUsageTelemetry:false,
ContentClick:false, ContentPrefServiceParent:false, ContentSearch:false,
@ -54,7 +54,6 @@ let initializedModules = {};
[
["AboutHome", "resource:///modules/AboutHome.jsm", "init"],
["AboutNewTab", "resource:///modules/AboutNewTab.jsm"],
["AddonManager", "resource://gre/modules/AddonManager.jsm"],
["AppMenuNotifications", "resource://gre/modules/AppMenuNotifications.jsm"],
["AsyncPrefs", "resource://gre/modules/AsyncPrefs.jsm"],
@ -969,7 +968,6 @@ BrowserGlue.prototype = {
DirectoryLinksProvider.init();
NewTabUtils.init();
NewTabUtils.links.addProvider(DirectoryLinksProvider);
AboutNewTab.init();
PageActions.init();
@ -1030,7 +1028,6 @@ BrowserGlue.prototype = {
BrowserUsageTelemetry.uninit();
PageThumbs.uninit();
AboutNewTab.uninit();
NewTabUtils.uninit();
AutoCompletePopup.uninit();
DateTimePickerHelper.uninit();

Просмотреть файл

@ -605,7 +605,7 @@
]]></handler>
<handler event="transitionend"><![CDATA[
if (event.originalTarget.getAttribute("anonid") == "container" &&
event.propertyName == "transform") {
(event.propertyName == "transform" || event.propertyName == "-moz-window-transform")) {
this.style.removeProperty("pointer-events");
}
]]></handler>

Просмотреть файл

@ -133,6 +133,13 @@ this.ActivityStreamMessageChannel = class ActivityStreamMessageChannel {
this.channel.addMessageListener("RemotePage:Load", this.onNewTabLoad);
this.channel.addMessageListener("RemotePage:Unload", this.onNewTabUnload);
this.channel.addMessageListener(this.incomingMessageName, this.onMessage);
// Some pages might have already loaded, so we won't get the usual message
for (const {loaded, portID} of this.channel.messagePorts) {
if (loaded) {
this.onNewTabLoad({target: {portID}});
}
}
}
/**

2
browser/extensions/e10srollout/bootstrap.js поставляемый
Просмотреть файл

@ -21,7 +21,7 @@ const TEST_THRESHOLD = {
// If a user qualifies for the e10s-multi experiement, this is how many
// content processes to use and whether to allow addons for the experiment.
const MULTI_EXPERIMENT = {
"beta": { buckets: { 1: .5, 4: 1, }, // 1 process: 50%, 4 processes: 50%
"beta": { buckets: { 4: 1, }, // 4 processes: 100%
// When on the "beta" channel, getAddonsDisqualifyForMulti
// will return true if any addon installed is not a web extension.

Просмотреть файл

@ -10,7 +10,7 @@
<Description about="urn:mozilla:install-manifest">
<em:id>e10srollout@mozilla.org</em:id>
<em:version>2.1</em:version>
<em:version>2.15</em:version>
<em:type>2</em:type>
<em:bootstrap>true</em:bootstrap>
<em:multiprocessCompatible>true</em:multiprocessCompatible>

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 1.1 KiB

Просмотреть файл

@ -357,7 +357,7 @@ photonpanelmultiview panelview {
}
photonpanelmultiview .panel-subview-body {
margin: 4px 0;
padding: 6px 0;
}
/* END photonpanelview adjustments */
@ -1222,10 +1222,11 @@ panelview:not([mainView]) .subviewbutton.panel-subview-footer > .toolbarbutton-t
content: url(chrome://browser/skin/back-12.svg);
fill: GrayText;
float: right;
transform: translateY(1px);
}
.PanelUI-subView .subviewbutton-nav:-moz-locale-dir(ltr)::after {
transform: scaleX(-1);
transform: scaleX(-1) translateY(1px);
}
.subviewbutton[shortcut]::after,
@ -1408,7 +1409,7 @@ menuitem.subviewbutton@menuStateActive@,
}
.subviewbutton.panel-subview-footer {
margin: 4px -4px -4px;
margin: 0;
background-color: var(--arrowpanel-dimmed);
border-top: 1px solid var(--panel-separator-color);
border-radius: 0;
@ -1501,8 +1502,8 @@ menuitem.panel-subview-footer@menuStateActive@,
border-inline-start: 1px solid var(--panel-separator-color);
border-top: none;
margin: 0;
margin-inline-start: 4px;
margin-inline-end: 5px;
margin-inline-start: 6px;
margin-inline-end: 7px;
}
.subviewbutton > .menu-accel-container {

Просмотреть файл

@ -31,7 +31,6 @@
* skin/classic/browser/controlcenter/tracking-protection.svg (../shared/controlcenter/tracking-protection.svg)
skin/classic/browser/controlcenter/warning-gray.svg (../shared/controlcenter/warning-gray.svg)
skin/classic/browser/controlcenter/warning-yellow.svg (../shared/controlcenter/warning-yellow.svg)
skin/classic/browser/customizableui/customizeFavicon.ico (../shared/customizableui/customizeFavicon.ico)
skin/classic/browser/customizableui/menuPanel-customizeFinish.png (../shared/customizableui/menuPanel-customizeFinish.png)
skin/classic/browser/customizableui/menuPanel-customizeFinish@2x.png (../shared/customizableui/menuPanel-customizeFinish@2x.png)
#ifdef MOZ_PHOTON_THEME

Просмотреть файл

@ -8,7 +8,7 @@ this.EXPORTED_SYMBOLS = ["Tabs"];
const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
const CUST_TAB = "chrome://browser/skin/customizableui/customizeFavicon.ico";
const CUST_TAB = "chrome://browser/skin/customize.svg";
const PREFS_TAB = "chrome://browser/skin/settings.svg";
const DEFAULT_FAVICON_TAB = `data:text/html,<meta charset="utf-8">
<title>No favicon</title>`;

Просмотреть файл

@ -16,12 +16,15 @@ support-files =
code_binary_search.map
code_binary_search_absolute.js
code_binary_search_absolute.map
code_bundle_cross_domain.js
code_bundle_cross_domain.js.map
code_bundle_no_race.js
code_bundle_no_race.js.map
code_bundle_reload_1.js
code_bundle_reload_1.js.map
code_bundle_reload_2.js
code_bundle_reload_2.js.map
code_cross_domain.js
code_inline_bundle.js
code_inline_original.js
code_math.js
@ -59,6 +62,7 @@ skip-if = debug # Bug 1282269
[browser_new_activation_workflow.js]
[browser_source_map-01.js]
[browser_source_map-absolute.js]
[browser_source_map-cross-domain.js]
[browser_source_map-inline.js]
[browser_source_map-no-race.js]
[browser_source_map-reload.js]

Просмотреть файл

@ -0,0 +1,39 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
// Test that the source map service can fetch a source map from a
// different domain.
"use strict";
const JS_URL = URL_ROOT + "code_bundle_cross_domain.js";
const PAGE_URL = `data:text/html,
<!doctype html>
<html>
<head>
<meta charset="utf-8"/>
<title>Empty test page to test cross domain source map</title>
</head>
<body>
<script src="${JS_URL}"></script>
</body>
</html>`;
const ORIGINAL_URL = "webpack:///code_cross_domain.js";
const GENERATED_LINE = 82;
const ORIGINAL_LINE = 12;
add_task(function* () {
const toolbox = yield openNewTabAndToolbox(PAGE_URL, "webconsole");
const service = toolbox.sourceMapURLService;
info(`checking original location for ${JS_URL}:${GENERATED_LINE}`);
let newLoc = yield service.originalPositionFor(JS_URL, GENERATED_LINE);
is(newLoc.sourceUrl, ORIGINAL_URL, "check mapped URL");
is(newLoc.line, ORIGINAL_LINE, "check mapped line number");
});

Просмотреть файл

@ -0,0 +1,93 @@
/******/ (function(modules) { // webpackBootstrap
/******/ // The module cache
/******/ var installedModules = {};
/******/
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/
/******/ // Check if module is in cache
/******/ if(installedModules[moduleId]) {
/******/ return installedModules[moduleId].exports;
/******/ }
/******/ // Create a new module (and put it into the cache)
/******/ var module = installedModules[moduleId] = {
/******/ i: moduleId,
/******/ l: false,
/******/ exports: {}
/******/ };
/******/
/******/ // Execute the module function
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/
/******/ // Flag the module as loaded
/******/ module.l = true;
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/
/******/
/******/ // expose the modules object (__webpack_modules__)
/******/ __webpack_require__.m = modules;
/******/
/******/ // expose the module cache
/******/ __webpack_require__.c = installedModules;
/******/
/******/ // define getter function for harmony exports
/******/ __webpack_require__.d = function(exports, name, getter) {
/******/ if(!__webpack_require__.o(exports, name)) {
/******/ Object.defineProperty(exports, name, {
/******/ configurable: false,
/******/ enumerable: true,
/******/ get: getter
/******/ });
/******/ }
/******/ };
/******/
/******/ // getDefaultExport function for compatibility with non-harmony modules
/******/ __webpack_require__.n = function(module) {
/******/ var getter = module && module.__esModule ?
/******/ function getDefault() { return module['default']; } :
/******/ function getModuleExports() { return module; };
/******/ __webpack_require__.d(getter, 'a', getter);
/******/ return getter;
/******/ };
/******/
/******/ // Object.prototype.hasOwnProperty.call
/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
/******/
/******/ // __webpack_public_path__
/******/ __webpack_require__.p = "";
/******/
/******/ // Load entry module and return exports
/******/ return __webpack_require__(__webpack_require__.s = 0);
/******/ })
/************************************************************************/
/******/ ([
/* 0 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
// Original source code for the cross-domain source map test.
// The generated file was made with
// webpack --devtool source-map code_cross_domain.js code_bundle_cross_domain.js
// ... and then edited to replace the generated sourceMappingURL.
function f() {
console.log("anything will do");
}
f();
// Avoid script GC.
window.f = f;
/***/ })
/******/ ]);
//# sourceMappingURL=http://test2.mochi.test:8888/browser/devtools/client/framework/test/code_bundle_cross_domain.js.map

Просмотреть файл

@ -0,0 +1 @@
{"version":3,"sources":["webpack:///webpack/bootstrap 7b928b82bd207211f478","webpack:///./code_cross_domain.js"],"names":[],"mappings":";AAAA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;;AAGA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,aAAK;AACL;AACA;;AAEA;AACA;AACA;AACA,mCAA2B,0BAA0B,EAAE;AACvD,yCAAiC,eAAe;AAChD;AACA;AACA;;AAEA;AACA,8DAAsD,+DAA+D;;AAErH;AACA;;AAEA;AACA;;;;;;;;AC7DA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;;AAEA;;AAEA;AACA","file":"code_bundle_cross_domain.js","sourcesContent":[" \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, {\n \t\t\t\tconfigurable: false,\n \t\t\t\tenumerable: true,\n \t\t\t\tget: getter\n \t\t\t});\n \t\t}\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = 0);\n\n\n\n// WEBPACK FOOTER //\n// webpack/bootstrap 7b928b82bd207211f478","/* Any copyright is dedicated to the Public Domain.\n http://creativecommons.org/publicdomain/zero/1.0/ */\n\n// Original source code for the cross-domain source map test.\n// The generated file was made with\n// webpack --devtool source-map code_cross_domain.js code_bundle_cross_domain.js\n// ... and then edited to replace the generated sourceMappingURL.\n\n\"use strict\";\n\nfunction f() {\n console.log(\"anything will do\");\n}\n\nf();\n\n// Avoid script GC.\nwindow.f = f;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./code_cross_domain.js\n// module id = 0\n// module chunks = 0"],"sourceRoot":""}

Просмотреть файл

@ -0,0 +1,19 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
// Original source code for the cross-domain source map test.
// The generated file was made with
// webpack --devtool source-map code_cross_domain.js code_bundle_cross_domain.js
// ... and then the bundle was edited to replace the generated
// sourceMappingURL.
"use strict";
function f() {
console.log("anything will do");
}
f();
// Avoid script GC.
window.f = f;

Просмотреть файл

@ -551,7 +551,12 @@ Toolbox.prototype = {
get: (target, name) => {
if (name === "getOriginalURLs") {
return (urlInfo) => {
return target.getOriginalURLs(urlInfo).catch(console.error);
return target.getOriginalURLs(urlInfo)
.catch(text => {
let message = L10N.getFormatStr("toolbox.sourceMapFailure",
text, urlInfo.url, urlInfo.sourceMapURL);
this.target.logErrorInPage(message, "source map");
});
};
}
return target[name];

Просмотреть файл

@ -177,3 +177,10 @@ toolbox.closebutton.tooltip=Close Developer Tools
# LOCALIZATION NOTE (toolbox.allToolsButton.tooltip): This is the tooltip for the
# "all tools" button displayed when some tools are hidden by overflow of the toolbar.
toolbox.allToolsButton.tooltip=Select another tool
# LOCALIZATION NOTE (toolbox.sourceMapFailure): This is shown in the web console
# when there is a failure to fetch or parse a source map.
# The text of the error: %1$S
# The URL that caused DevTools to try to fetch a source map: %2$S
# The URL of the source map itself: %3$S
toolbox.sourceMapFailure=Source map error: %1$S\nResource URL: %2$S\nSource Map URL: %3$S

Просмотреть файл

@ -148,7 +148,7 @@ a {
display: flex;
}
.message-body > * {
.message-body {
white-space: pre-wrap;
word-wrap: break-word;
}

Просмотреть файл

@ -38,7 +38,7 @@ var styleSheets = [
// on the right CSS strategy FIXME.
// It would also be nice to include them using @import.
styleSheets.forEach(url => {
loadSheet(this, url, "author");
loadSheet(window, url, "author");
});
// Localization API used by React components

Просмотреть файл

@ -267,7 +267,6 @@ stubPreparedMessages.set("console.assert(false, {message: 'foobar'})", new Conso
"columnNumber": 27,
"filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-console-api.html",
"functionName": "triggerPacket",
"language": 2,
"lineNumber": 1
}
],
@ -666,21 +665,18 @@ stubPreparedMessages.set("console.trace()", new ConsoleMessage({
"columnNumber": 3,
"filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-console-api.html",
"functionName": "testStacktraceFiltering",
"language": 2,
"lineNumber": 3
},
{
"columnNumber": 3,
"filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-console-api.html",
"functionName": "foo",
"language": 2,
"lineNumber": 6
},
{
"columnNumber": 1,
"filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-console-api.html",
"functionName": "triggerPacket",
"language": 2,
"lineNumber": 9
}
],
@ -1462,7 +1458,6 @@ stubPackets.set("console.assert(false, {message: 'foobar'})", {
"columnNumber": 27,
"filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-console-api.html",
"functionName": "triggerPacket",
"language": 2,
"lineNumber": 1
}
],
@ -1841,21 +1836,18 @@ stubPackets.set("console.trace()", {
"columnNumber": 3,
"filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-console-api.html",
"functionName": "testStacktraceFiltering",
"language": 2,
"lineNumber": 3
},
{
"columnNumber": 3,
"filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-console-api.html",
"functionName": "foo",
"language": 2,
"lineNumber": 6
},
{
"columnNumber": 1,
"filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-console-api.html",
"functionName": "triggerPacket",
"language": 2,
"lineNumber": 9
}
],

Просмотреть файл

@ -15,6 +15,10 @@ support-files =
test-location-styleeditor-link-2.css
test-location-styleeditor-link.html
test-network-request.html
test-sourcemap-error-01.html
test-sourcemap-error-02.html
test-sourcemap-error-01.js
test-sourcemap-error-02.js
test-stacktrace-location-debugger-link.html
!/devtools/client/framework/test/shared-head.js
@ -48,7 +52,9 @@ skip-if = (os == 'linux' && bits == 32 && debug) # bug 1328915, disable linux32
[browser_webconsole_object_inspector.js]
[browser_webconsole_observer_notifications.js]
[browser_webconsole_shows_reqs_in_netmonitor.js]
[browser_webconsole_sourcemap_error.js]
[browser_webconsole_stacktrace_location_debugger_link.js]
[browser_webconsole_stacktrace_location_scratchpad_link.js]
[browser_webconsole_string.js]
[browser_webconsole_timestamps.js]
[browser_webconsole_warn_about_replaced_api.js]

Просмотреть файл

@ -32,7 +32,7 @@ add_task(async function task() {
}]
});
await loadDocument(currentTab.linkedBrowser, TEST_PATH);
await loadDocument(TEST_PATH);
info("Document loaded.");
await onMessageAdded;

Просмотреть файл

@ -27,7 +27,7 @@ add_task(async function task() {
let toolbox = gDevTools.getToolbox(target);
const documentUrl = TEST_PATH + TEST_FILE;
await loadDocument(currentTab.linkedBrowser, documentUrl);
await loadDocument(documentUrl);
info("Document loaded.");
await testNetmonitorLink(toolbox, hud, documentUrl);

Просмотреть файл

@ -21,10 +21,9 @@ registerCleanupFunction(() => {
add_task(async function () {
const toolbox = await openNewTabAndToolbox(TEST_URI, "netmonitor");
const currentTab = gBrowser.selectedTab;
info("Network panel is open.");
await loadDocument(currentTab.linkedBrowser, TEST_PATH);
await loadDocument(TEST_PATH);
info("Document loaded.");
// Test that the request appears in the network panel.

Просмотреть файл

@ -0,0 +1,22 @@
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim: set ft=javascript 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 that a missing source map is reported.
const BASE = "http://example.com/browser/devtools/client/webconsole/new-console-output/test/mochitest/";
add_task(async function () {
for (let test of ["test-sourcemap-error-01.html", "test-sourcemap-error-02.html"]) {
const hud = await openNewTabAndConsole(BASE + test);
const node = await waitFor(() => findMessage(hud, "here"));
ok(node, "logged text is displayed in web console");
const node2 = await waitFor(() => findMessage(hud, "Source map error"));
ok(node2, "source map error is displayed in web console");
}
});

Просмотреть файл

@ -0,0 +1,54 @@
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
const TEST_URI_REPLACED =
"data:text/html;charset=utf8,<script>console = {log: () => ''}</script>";
const TEST_URI_NOT_REPLACED =
"data:text/html;charset=utf8,<script>console.log('foo')</script>";
add_task(async function () {
await SpecialPowers.pushPrefEnv({"set": [
["devtools.webconsole.persistlog", true]
]});
let hud = await openNewTabAndConsole(TEST_URI_NOT_REPLACED);
await testWarningNotPresent(hud);
await closeToolbox();
await loadDocument(TEST_URI_REPLACED);
let toolbox = await openToolboxForTab(gBrowser.selectedTab, "webconsole");
hud = toolbox.getCurrentPanel().hud;
await testWarningPresent(hud);
});
async function testWarningNotPresent(hud) {
ok(!findMessage(hud, "logging API"), "no warning displayed");
// Bug 862024: make sure the warning doesn't show after page reload.
info("wait for the page to refresh and make sure the warning still isn't there");
await refreshTab();
await waitFor(() => {
// We need to wait for 3 messages because there are two logs, plus the
// navigation message since messages are persisted
return findMessages(hud, "foo").length === 3;
});
ok(!findMessage(hud, "logging API"), "no warning displayed");
}
async function testWarningPresent(hud) {
info("wait for the warning to show");
await waitFor(() => findMessage(hud, "logging API"));
info("reload the test page and wait for the warning to show");
await refreshTab();
await waitFor(() => {
return findMessages(hud, "logging API").length === 2;
});
}

Просмотреть файл

@ -179,7 +179,7 @@ function hideContextMenu(hud) {
return onPopupHidden;
}
function loadDocument(browser, url) {
function loadDocument(url, browser = gBrowser.selectedBrowser) {
return new Promise(resolve => {
browser.addEventListener("load", resolve, {capture: true, once: true});
BrowserTestUtils.loadURI(gBrowser.selectedBrowser, url);

Просмотреть файл

@ -0,0 +1,13 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Test that a missing source map is reported to the console</title>
<!-- Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ -->
<script type="text/javascript" src="test-sourcemap-error-01.js"></script>
</head>
<body>
<p>Web Console test for source map failure.</p>
</body>
</html>

Просмотреть файл

@ -0,0 +1,7 @@
"use strict";
window.qqz = function () {
console.log("here");
};
window.qqz();
/* eslint-disable spaced-comment */
//# sourceMappingURL=no-such-file.js.map

Просмотреть файл

@ -0,0 +1,13 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Test that an invalid source map URL is reported to the console</title>
<!-- Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ -->
<script type="text/javascript" src="test-sourcemap-error-02.js"></script>
</head>
<body>
<p>Web Console test for source map failure.</p>
</body>
</html>

Просмотреть файл

@ -0,0 +1,7 @@
"use strict";
window.qqz = function () {
console.log("here");
};
window.qqz();
/* eslint-disable spaced-comment */
//# sourceMappingURL=data:invalid

Просмотреть файл

@ -139,7 +139,8 @@ NewWebConsoleFrame.prototype = {
},
logWarningAboutReplacedAPI() {
this.owner.target.logErrorInPage(l10n.getStr("ConsoleAPIDisabled"),
"ConsoleAPIDisabled");
},
handleNetworkEventUpdate() {

Просмотреть файл

@ -37,28 +37,24 @@ add_task(function* () {
columnNumber: 3,
filename: TEST_URI,
functionName: "window.foobar585956c",
language: 2,
lineNumber: 9
},
{
columnNumber: 10,
filename: TEST_URI,
functionName: "foobar585956b",
language: 2,
lineNumber: 14
},
{
columnNumber: 10,
filename: TEST_URI,
functionName: "foobar585956a",
language: 2,
lineNumber: 18
},
{
columnNumber: 1,
filename: TEST_URI,
functionName: "",
language: 2,
lineNumber: 21
}
];

Просмотреть файл

@ -46,7 +46,6 @@ add_task(function* runTest() {
columnNumber: 3,
filename: TEST_URI,
functionName: "inner",
language: 2,
lineNumber: 9
},
{
@ -54,7 +53,6 @@ add_task(function* runTest() {
columnNumber: 3,
filename: TEST_URI,
functionName: "time1",
language: 2,
lineNumber: 13,
},
{
@ -62,7 +60,6 @@ add_task(function* runTest() {
columnNumber: 1,
filename: TEST_URI,
functionName: "",
language: 2,
lineNumber: 18,
}
];

Просмотреть файл

@ -267,9 +267,9 @@ WebConsoleConnectionProxy.prototype = {
this.dispatchMessagesAdd(messages);
} else {
this.webConsoleFrame.displayCachedMessages(messages);
if (!this._hasNativeConsoleAPI) {
this.webConsoleFrame.logWarningAboutReplacedAPI();
}
}
if (!this._hasNativeConsoleAPI) {
this.webConsoleFrame.logWarningAboutReplacedAPI();
}
this.connected = true;

Просмотреть файл

@ -160,6 +160,11 @@ XPCOMUtils.defineLazyGetter(this, "KeyShortcuts", function () {
function DevToolsStartup() {}
DevToolsStartup.prototype = {
/**
* Flag that indicates if the developer toggle was already added to customizableUI.
*/
developerToggleCreated: false,
handle: function (cmdLine) {
let consoleFlag = cmdLine.handleFlag("jsconsole", false);
let debuggerFlag = cmdLine.handleFlag("jsdebugger", false);
@ -206,15 +211,19 @@ DevToolsStartup.prototype = {
* We do that to prevent loading any DevTools module until the user intent to use them.
*/
hookWindow(window) {
// Key Shortcuts need to be added on all the created windows.
this.hookKeyShortcuts(window);
// All the other hooks are only necessary if the tools aren't loaded yet.
if (this.initialized) {
return;
if (!this.developerToggleCreated) {
this.hookDeveloperToggle();
this.developerToggleCreated = true;
}
this.hookWebDeveloperMenu(window);
this.hookDeveloperToggle(window);
// The developer menu hook only needs to be added if devtools have not been
// initialized yet.
if (!this.initialized) {
this.hookWebDeveloperMenu(window);
}
},
/**
@ -233,7 +242,7 @@ DevToolsStartup.prototype = {
* devtools/client/framework/browser-menu to create the items for real,
* initDevTools, from onViewShowing is also calling browser-menu.
*/
hookDeveloperToggle(window) {
hookDeveloperToggle() {
let id = "developer-button";
let widget = CustomizableUI.getWidget(id);
if (widget && widget.provider == CustomizableUI.PROVIDER_API) {

Просмотреть файл

@ -80,13 +80,18 @@ NodeIsInTraversalRange(nsINode* aNode, bool aIsPreMode,
NS_WARNING_ASSERTION(indx != -1, "bad indx");
if (!aIsPreMode) {
++indx;
// Post mode: start < node <= end.
return nsContentUtils::ComparePoints(aStartContainer, aStartOffset,
parent, indx + 1) < 0 &&
nsContentUtils::ComparePoints(aEndContainer, aEndOffset,
parent, indx + 1) >= 0;
}
// Pre mode: start <= node < end.
return nsContentUtils::ComparePoints(aStartContainer, aStartOffset,
parent, indx) <= 0 &&
nsContentUtils::ComparePoints(aEndContainer, aEndOffset,
parent, indx) >= 0;
parent, indx) > 0;
}

Просмотреть файл

@ -277,6 +277,8 @@
#endif // MOZ_WEBRTC
#include "nsIURIClassifier.h"
#include "mozilla/DocumentStyleRootIterator.h"
#include "mozilla/ServoRestyleManager.h"
using namespace mozilla;
using namespace mozilla::dom;
@ -1350,6 +1352,7 @@ nsIDocument::nsIDocument()
mFrameRequestCallbacksScheduled(false),
mIsTopLevelContentDocument(false),
mIsContentDocument(false),
mMightHaveStaleServoData(false),
mIsScopedStyleEnabled(eScopedStyle_Unknown),
mCompatMode(eCompatibility_FullStandards),
mReadyState(ReadyState::READYSTATE_UNINITIALIZED),
@ -3907,6 +3910,9 @@ nsDocument::CreateShell(nsPresContext* aContext, nsViewManager* aViewManager,
FillStyleSet(aStyleSet);
// Ensure we start with no stale data in the tree.
ClearStaleServoDataFromDocument();
RefPtr<PresShell> shell = new PresShell;
shell->Init(this, aContext, aViewManager, aStyleSet);
@ -4026,6 +4032,18 @@ nsDocument::DeleteShell()
mPresShell = nullptr;
UpdateFrameRequestCallbackSchedulingState(oldShell);
mStyleSetFilled = false;
// Record that the tree might have stale Servo element data in it
// that would need to be cleared if we ever get a new pres shell
// or if we call ServoStyleSet style resolving functions on
// elements in the document. Most of the time this lazy clearing
// of Servo element data saves us work, since it's not often that a
// document gets a new pres shell after its old one is destroyed.
// In those cases we rely on the data being cleared in UnbindFromTree
// and save this additional traversal.
if (IsStyledByServo()) {
mMightHaveStaleServoData = true;
}
}
static void
@ -12686,7 +12704,7 @@ nsIDocument::InlineScriptAllowedByCSP()
nsresult rv = csp->GetAllowsInline(nsIContentPolicy::TYPE_SCRIPT,
EmptyString(), // aNonce
true, // aParserCreated
EmptyString(), // FIXME get script sample (bug 1314567)
nullptr, // FIXME get script sample (bug 1314567)
0, // aLineNumber
&allowsInlineScript);
NS_ENSURE_SUCCESS(rv, true);
@ -13549,3 +13567,17 @@ nsIDocument::IsScopedStyleEnabled()
}
return mIsScopedStyleEnabled == eScopedStyle_Enabled;
}
void
nsIDocument::ClearStaleServoDataFromDocument()
{
if (!mMightHaveStaleServoData) {
return;
}
DocumentStyleRootIterator iter(this);
while (Element* root = iter.GetNextStyleRoot()) {
ServoRestyleManager::ClearServoDataFromSubtree(root);
}
mMightHaveStaleServoData = false;
}

Просмотреть файл

@ -812,6 +812,10 @@ nsFrameMessageManager::ReleaseCachedProcesses()
NS_IMETHODIMP
nsFrameMessageManager::Dump(const nsAString& aStr)
{
if (!nsContentUtils::DOMWindowDumpEnabled()) {
return NS_OK;
}
#ifdef ANDROID
__android_log_print(ANDROID_LOG_INFO, "Gecko", "%s", NS_ConvertUTF16toUTF8(aStr).get());
#endif

Просмотреть файл

@ -860,6 +860,11 @@ public:
return GetBFCacheEntry() ? nullptr : mPresShell;
}
bool HasShellOrBFCacheEntry() const
{
return mPresShell || mBFCacheEntry;
}
// Instead using this method, what you probably want is
// RemoveFromBFCacheSync() as we do in MessagePort and BroadcastChannel.
void DisallowBFCaching()
@ -1701,6 +1706,18 @@ public:
mIsContentDocument = aIsContentDocument;
}
/**
* Checks if this document has no pres shell, and if so, clears any Servo
* element data stored on Elements in the document.
*/
void ClearStaleServoDataFromDocument();
/**
* Returns true if there may be Servo element data on Elements in the document
* that were created for a pres shell that no longer exists.
*/
bool MightHaveStaleServoData() const { return mMightHaveStaleServoData; }
/**
* Create an element with the specified name, prefix and namespace ID.
* Returns null if element name parsing failed.
@ -3285,6 +3302,10 @@ protected:
bool mIsContentDocument : 1;
// True if there may be Servo element data on Elements in the document that
// were created for a pres shell that no longer exists.
bool mMightHaveStaleServoData : 1;
// Whether <style scoped> support is enabled in this document.
enum { eScopedStyle_Unknown, eScopedStyle_Disabled, eScopedStyle_Enabled };
unsigned int mIsScopedStyleEnabled : 2;

Просмотреть файл

@ -14,7 +14,6 @@
#include "mozilla/dom/BindingUtils.h"
#include "mozilla/dom/DOMException.h"
#include "mozilla/dom/ScriptSettings.h"
#include "nsIProgrammingLanguage.h"
#include "nsPIDOMWindow.h"
#include "nsServiceManagerUtils.h"
#include "nsThreadUtils.h"
@ -318,18 +317,6 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(JSStackFrame)
NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_INTERFACE_MAP_END
NS_IMETHODIMP JSStackFrame::GetLanguage(uint32_t* aLanguage)
{
*aLanguage = nsIProgrammingLanguage::JAVASCRIPT;
return NS_OK;
}
NS_IMETHODIMP JSStackFrame::GetLanguageName(nsACString& aLanguageName)
{
aLanguageName.AssignLiteral("JavaScript");
return NS_OK;
}
// Helper method to get the value of a stack property, if it's not already
// cached. This will make sure we skip the cache if the access is happening
// over Xrays.

Просмотреть файл

@ -2879,13 +2879,13 @@ GetFontStyleForServo(Element* aElement, const nsAString& aFont,
if (aElement && aElement->IsInUncomposedDoc()) {
// Inherit from the canvas element.
aPresShell->FlushPendingNotifications(FlushType::Style);
// We need to use ResolveTransientServoStyle, which involves traversal,
// instead of ResolveServoStyle() because we need up-to-date style even if
// We need to use ResolveStyleLazily, which involves traversal,
// instead of ResolvestyleFor() because we need up-to-date style even if
// the canvas element is display:none.
parentStyle =
styleSet->ResolveTransientServoStyle(aElement,
CSSPseudoElementType::NotPseudo,
nullptr);
styleSet->ResolveStyleLazily(aElement,
CSSPseudoElementType::NotPseudo,
nullptr);
} else {
RefPtr<RawServoDeclarationBlock> declarations =
CreateFontDeclarationForServo(NS_LITERAL_STRING("10px sans-serif"),

Просмотреть файл

@ -37,7 +37,6 @@
#include "nsIDOMWindowUtils.h"
#include "nsIInterfaceRequestorUtils.h"
#include "nsILoadContext.h"
#include "nsIProgrammingLanguage.h"
#include "nsISensitiveInfoHiddenURI.h"
#include "nsIServiceManager.h"
#include "nsISupportsPrimitives.h"
@ -1151,7 +1150,6 @@ StackFrameToStackEntry(JSContext* aCx, nsIStackFrame* aStackFrame,
aStackEntry.mAsyncCause.Construct(cause);
}
aStackEntry.mLanguage = nsIProgrammingLanguage::JAVASCRIPT;
return NS_OK;
}

Просмотреть файл

@ -46,6 +46,7 @@
#include "nsIDOMEventListener.h"
#include "nsIScriptGlobalObject.h"
#include "nsISupports.h"
#include "nsISupportsPrimitives.h"
#include "nsIXPConnect.h"
#include "nsJSUtils.h"
#include "nsNameSpaceManager.h"
@ -876,12 +877,16 @@ EventListenerManager::SetEventHandler(nsIAtom* aName,
scriptSample.AppendLiteral(" attribute on ");
scriptSample.Append(tagName);
scriptSample.AppendLiteral(" element");
nsCOMPtr<nsISupportsString> sampleIString(do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID));
if (sampleIString) {
sampleIString->SetData(scriptSample);
}
bool allowsInlineScript = true;
rv = csp->GetAllowsInline(nsIContentPolicy::TYPE_SCRIPT,
EmptyString(), // aNonce
true, // aParserCreated (true because attribute event handler)
scriptSample,
sampleIString,
0, // aLineNumber
&allowsInlineScript);
NS_ENSURE_SUCCESS(rv, rv);

Просмотреть файл

@ -3033,7 +3033,15 @@ IsOrHasAncestorWithDisplayNone(Element* aElement, nsIPresShell* aPresShell)
RefPtr<nsStyleContext> sc;
for (auto* element : Reversed(elementsToCheck)) {
if (sc) {
sc = styleSet->ResolveStyleFor(element, sc, LazyComputeBehavior::Assert);
if (styleSet->IsGecko()) {
sc = styleSet->ResolveStyleFor(element, sc,
LazyComputeBehavior::Assert);
} else {
// Call ResolveStyleLazily to protect against stale element data in
// the tree when styled by Servo.
sc = styleSet->AsServo()->ResolveStyleLazily(
element, CSSPseudoElementType::NotPseudo, nullptr);
}
} else {
sc = nsComputedDOMStyle::GetStyleContextNoFlush(element,
nullptr, aPresShell);

Просмотреть файл

@ -81,7 +81,7 @@ interface nsITabParent : nsISupports
/**
* Notify APZ to start autoscrolling.
* (aAnchorX, aAnchorY) are the coordinates of the autoscroll anchor,
* in LayoutDevice coordinates relative to the screen. aScrollId and
* in CSS coordinates relative to the screen. aScrollId and
* aPresShellId identify the scroll frame that content chose to scroll.
*/
void startApzAutoscroll(in float aAnchorX, in float aAnchorY,

Просмотреть файл

@ -11,6 +11,7 @@ interface nsIDocShell;
interface nsIDOMDocument;
interface nsIEventTarget;
interface nsIPrincipal;
interface nsIScriptElement;
interface nsIURI;
/**
@ -138,7 +139,8 @@ interface nsIContentSecurityPolicy : nsISerializable
* @param aContentPolicyType Either TYPE_SCRIPT or TYPE_STYLESHEET
* @param aNonce The nonce string to check against the policy
* @param aParserCreated If the script element was created by the HTML Parser
* @param aContent The content of the inline resource to hash
* @param aElementOrContent The script element of the inline resource to hash
* or the content of the psuedo-script to compare to hash
* (and compare to the hashes listed in the policy)
* @param aLineNumber The line number of the inline resource
* (used for reporting)
@ -149,7 +151,7 @@ interface nsIContentSecurityPolicy : nsISerializable
boolean getAllowsInline(in nsContentPolicyType aContentPolicyType,
in AString aNonce,
in boolean aParserCreated,
in AString aContent,
in nsISupports aElementOrContent,
in unsigned long aLineNumber);
/**

Просмотреть файл

@ -3283,7 +3283,8 @@ TabParent::StartApzAutoscroll(float aAnchorX, float aAnchorY,
// The anchor coordinates that are passed in are relative to the origin
// of the screen, but we are sending them to APZ which only knows about
// coordinates relative to the widget, so convert them accordingly.
LayoutDeviceIntPoint anchor = RoundedToInt(LayoutDevicePoint{aAnchorX, aAnchorY});
CSSPoint anchorCss{aAnchorX, aAnchorY};
LayoutDeviceIntPoint anchor = RoundedToInt(anchorCss * widget->GetDefaultScale());
anchor -= widget->WidgetToScreenOffset();
widget->StartAsyncAutoscroll(

Просмотреть файл

@ -182,7 +182,7 @@ nsresult nsJSThunk::EvaluateScript(nsIChannel *aChannel,
rv = csp->GetAllowsInline(nsIContentPolicy::TYPE_SCRIPT,
EmptyString(), // aNonce
true, // aParserCreated
EmptyString(), // aContent
nullptr, // aContent
0, // aLineNumber
&allowsInlineScript);

Просмотреть файл

@ -1110,13 +1110,9 @@ CSPAllowsInlineScript(nsIScriptElement* aElement, nsIDocument* aDocument)
scriptContent->GetAttr(kNameSpaceID_None, nsGkAtoms::nonce, nonce);
bool parserCreated = aElement->GetParserCreated() != mozilla::dom::NOT_FROM_PARSER;
// query the scripttext
nsAutoString scriptText;
aElement->GetScriptText(scriptText);
bool allowInlineScript = false;
rv = csp->GetAllowsInline(nsIContentPolicy::TYPE_SCRIPT,
nonce, parserCreated, scriptText,
nonce, parserCreated, aElement,
aElement->GetScriptLineNumber(),
&allowInlineScript);
return allowInlineScript;

Просмотреть файл

@ -26,6 +26,7 @@
#include "nsIObserver.h"
#include "nsIObserverService.h"
#include "nsIStringStream.h"
#include "nsISupportsPrimitives.h"
#include "nsIUploadChannel.h"
#include "nsIScriptError.h"
#include "nsIWebNavigation.h"
@ -505,7 +506,7 @@ NS_IMETHODIMP
nsCSPContext::GetAllowsInline(nsContentPolicyType aContentType,
const nsAString& aNonce,
bool aParserCreated,
const nsAString& aContent,
nsISupports* aElementOrContent,
uint32_t aLineNumber,
bool* outAllowsInline)
{
@ -520,12 +521,36 @@ nsCSPContext::GetAllowsInline(nsContentPolicyType aContentType,
return NS_OK;
}
nsAutoString content(EmptyString());
// always iterate all policies, otherwise we might not send out all reports
for (uint32_t i = 0; i < mPolicies.Length(); i++) {
bool allowed =
mPolicies[i]->allows(aContentType, CSP_UNSAFE_INLINE, EmptyString(), aParserCreated) ||
mPolicies[i]->allows(aContentType, CSP_NONCE, aNonce, aParserCreated) ||
mPolicies[i]->allows(aContentType, CSP_HASH, aContent, aParserCreated);
mPolicies[i]->allows(aContentType, CSP_NONCE, aNonce, aParserCreated);
// If the inlined script or style is allowed by either unsafe-inline or the
// nonce, go ahead and shortcut this loop so we can avoid allocating
// unecessary strings
if (allowed) {
continue;
}
// Check the content length to ensure the content is not allocated more than
// once. Even though we are in a for loop, it is probable that there is only one
// policy, so this check may be unnecessary.
if (content.Length() == 0) {
// postpone the allocation until absolutely necessary.
nsCOMPtr<nsISupportsString> stringContent = do_QueryInterface(aElementOrContent);
nsCOMPtr<nsIScriptElement> element = do_QueryInterface(aElementOrContent);
if (stringContent) {
Unused << stringContent->GetData(content);
} else if (element) {
element->GetScriptText(content);
}
}
allowed = mPolicies[i]->allows(aContentType, CSP_HASH, content, aParserCreated);
if (!allowed) {
// policy is violoated: deny the load unless policy is report only and
@ -537,7 +562,7 @@ nsCSPContext::GetAllowsInline(nsContentPolicyType aContentType,
mPolicies[i]->getDirectiveStringForContentType(aContentType, violatedDirective);
reportInlineViolation(aContentType,
aNonce,
aContent,
content,
violatedDirective,
i,
aLineNumber);

Просмотреть файл

@ -107,6 +107,9 @@ function run_test() {
":" + REPORT_SERVER_PORT +
"/foo/self");
let content = Cc["@mozilla.org/supports-string;1"].
createInstance(Ci.nsISupportsString);
content.data = "";
// test that inline script violations cause a report.
makeTest(0, {"blocked-uri": "self"}, false,
function(csp) {
@ -114,7 +117,7 @@ function run_test() {
inlineOK = csp.getAllowsInline(Ci.nsIContentPolicy.TYPE_SCRIPT,
"", // aNonce
false, // aParserCreated
"", // aContent
content, // aContent
0); // aLineNumber
// this is not a report only policy, so it better block inline scripts
@ -158,10 +161,13 @@ function run_test() {
makeTest(3, {"blocked-uri": "self"}, true,
function(csp) {
let inlineOK = true;
let content = Cc["@mozilla.org/supports-string;1"].
createInstance(Ci.nsISupportsString);
content.data = "";
inlineOK = csp.getAllowsInline(Ci.nsIContentPolicy.TYPE_SCRIPT,
"", // aNonce
false, // aParserCreated
"", // aContent
content, // aContent
0); // aLineNumber
// this is a report only policy, so it better allow inline scripts

Просмотреть файл

@ -267,10 +267,10 @@ async function startTraceTest(browser) {
dump("Observer attached\n");
gLevel = "trace";
gArgs = [
{columnNumber: 9, filename: TEST_URI, functionName: "window.foobar585956c", language: 2, lineNumber: 6},
{columnNumber: 16, filename: TEST_URI, functionName: "foobar585956b", language: 2, lineNumber: 11},
{columnNumber: 16, filename: TEST_URI, functionName: "foobar585956a", language: 2, lineNumber: 15},
{columnNumber: 1, filename: TEST_URI, functionName: "onclick", language: 2, lineNumber: 1}
{columnNumber: 9, filename: TEST_URI, functionName: "window.foobar585956c", lineNumber: 6},
{columnNumber: 16, filename: TEST_URI, functionName: "foobar585956b", lineNumber: 11},
{columnNumber: 16, filename: TEST_URI, functionName: "foobar585956a", lineNumber: 15},
{columnNumber: 1, filename: TEST_URI, functionName: "onclick", lineNumber: 1}
];
});

Просмотреть файл

@ -85,7 +85,6 @@ dictionary ConsoleStackEntry {
unsigned long lineNumber = 0;
unsigned long columnNumber = 0;
DOMString functionName = "";
unsigned long language = 0;
DOMString? asyncCause;
};

Просмотреть файл

@ -352,12 +352,16 @@ struct BaseRect {
T Area() const { return width * height; }
// Helper methods for computing the extents
T X() const { return x; }
T Y() const { return y; }
T Width() const { return width; }
T Height() const { return height; }
T XMost() const { return x + width; }
T YMost() const { return y + height; }
MOZ_ALWAYS_INLINE T X() const { return x; }
MOZ_ALWAYS_INLINE T Y() const { return y; }
MOZ_ALWAYS_INLINE T Width() const { return width; }
MOZ_ALWAYS_INLINE T Height() const { return height; }
MOZ_ALWAYS_INLINE T XMost() const { return x + width; }
MOZ_ALWAYS_INLINE T YMost() const { return y + height; }
// Set width and height. SizeTo() sets them together.
MOZ_ALWAYS_INLINE void SetWidth(T aWidth) { width = aWidth; }
MOZ_ALWAYS_INLINE void SetHeight(T aHeight) { height = aHeight; }
// Get the coordinate of the edge on the given side.
T Edge(mozilla::Side aSide) const
@ -390,6 +394,10 @@ struct BaseRect {
MOZ_ASSERT(aYMost >= y);
height = aYMost - y;
}
void Swap() {
std::swap(x, y);
std::swap(width, height);
}
// Round the rectangle edges to integer coordinates, such that the rounded
// rectangle has the same set of pixel centers as the original rectangle.

Просмотреть файл

@ -21,7 +21,7 @@ TestConstructors()
// Make sure the rectangle was properly initialized
EXPECT_TRUE(rect1.x == 10 && rect1.y == 20 &&
rect1.width == 30 && rect1.height == 40) <<
rect1.Width() == 30 && rect1.Height() == 40) <<
"[1] Make sure the rectangle was properly initialized with constructor";
// Create a second rect using the copy constructor
@ -29,7 +29,7 @@ TestConstructors()
// Make sure the rectangle was properly initialized
EXPECT_TRUE(rect2.x == rect1.x && rect2.y == rect2.y &&
rect2.width == rect2.width && rect2.height == rect2.height) <<
rect2.Width() == rect2.Width() && rect2.Height() == rect2.Height()) <<
"[2] Make sure the rectangle was properly initialized with copy constructor";
@ -73,7 +73,7 @@ TestContainment()
//
// Basic test of a point in the middle of the rect
EXPECT_FALSE(!rect1.Contains(rect1.x + rect1.width/2, rect1.y + rect1.height/2)) <<
EXPECT_FALSE(!rect1.Contains(rect1.x + rect1.Width()/2, rect1.y + rect1.Height()/2)) <<
"[1] Basic test of a point in the middle of the rect";
// Test against a point at the left/top edges
@ -149,10 +149,10 @@ TestIntersects()
rect2.x++;
// Test against a rect that's outside of rect1 on the left
rect2.x -= rect2.width;
rect2.x -= rect2.Width();
EXPECT_FALSE(rect1.Intersects(rect2)) <<
"[5] Test against a rect that's outside of rect1 on the left";
rect2.x += rect2.width;
rect2.x += rect2.Width();
// Test against a rect that overlaps the top edge of rect1
rect2.y--;
@ -161,10 +161,10 @@ TestIntersects()
rect2.y++;
// Test against a rect that's outside of rect1 on the top
rect2.y -= rect2.height;
rect2.y -= rect2.Height();
EXPECT_FALSE(rect1.Intersects(rect2)) <<
"[7] Test against a rect that's outside of rect1 on the top";
rect2.y += rect2.height;
rect2.y += rect2.Height();
// Test against a rect that overlaps the right edge of rect1
rect2.x++;
@ -173,10 +173,10 @@ TestIntersects()
rect2.x--;
// Test against a rect that's outside of rect1 on the right
rect2.x += rect2.width;
rect2.x += rect2.Width();
EXPECT_FALSE(rect1.Intersects(rect2)) <<
"[9] Test against a rect that's outside of rect1 on the right";
rect2.x -= rect2.width;
rect2.x -= rect2.Width();
// Test against a rect that overlaps the bottom edge of rect1
rect2.y++;
@ -185,10 +185,10 @@ TestIntersects()
rect2.y--;
// Test against a rect that's outside of rect1 on the bottom
rect2.y += rect2.height;
rect2.y += rect2.Height();
EXPECT_FALSE(rect1.Intersects(rect2)) <<
"[11] Test against a rect that's outside of rect1 on the bottom";
rect2.y -= rect2.height;
rect2.y -= rect2.Height();
return true;
}
@ -215,72 +215,72 @@ TestIntersection()
// Test against a rect that overlaps the left edge of rect1
rect2.x--;
EXPECT_FALSE(!dest.IntersectRect(rect1, rect2) ||
!(dest.IsEqualInterior(RectType(rect1.x, rect1.y, rect1.width - 1, rect1.height)))) <<
!(dest.IsEqualInterior(RectType(rect1.x, rect1.y, rect1.Width() - 1, rect1.Height())))) <<
"[3] Test against a rect that overlaps the left edge of rect1";
rect2.x++;
// Test against a rect that's outside of rect1 on the left
rect2.x -= rect2.width;
rect2.x -= rect2.Width();
EXPECT_FALSE(dest.IntersectRect(rect1, rect2)) <<
"[4] Test against a rect that's outside of rect1 on the left";
// Make sure an empty rect is returned
EXPECT_FALSE(!dest.IsEmpty()) <<
"[4] Make sure an empty rect is returned";
EXPECT_TRUE(dest.IsFinite()) << "[4b] Should be finite";
rect2.x += rect2.width;
rect2.x += rect2.Width();
// Test against a rect that overlaps the top edge of rect1
rect2.y--;
EXPECT_FALSE(!dest.IntersectRect(rect1, rect2) ||
!(dest.IsEqualInterior(RectType(rect1.x, rect1.y, rect1.width, rect1.height - 1)))) <<
!(dest.IsEqualInterior(RectType(rect1.x, rect1.y, rect1.Width(), rect1.Height() - 1)))) <<
"[5] Test against a rect that overlaps the top edge of rect1";
EXPECT_TRUE(dest.IsFinite()) << "[5b] Should be finite";
rect2.y++;
// Test against a rect that's outside of rect1 on the top
rect2.y -= rect2.height;
rect2.y -= rect2.Height();
EXPECT_FALSE(dest.IntersectRect(rect1, rect2)) <<
"[6] Test against a rect that's outside of rect1 on the top";
// Make sure an empty rect is returned
EXPECT_FALSE(!dest.IsEmpty()) <<
"[6] Make sure an empty rect is returned";
EXPECT_TRUE(dest.IsFinite()) << "[6b] Should be finite";
rect2.y += rect2.height;
rect2.y += rect2.Height();
// Test against a rect that overlaps the right edge of rect1
rect2.x++;
EXPECT_FALSE(!dest.IntersectRect(rect1, rect2) ||
!(dest.IsEqualInterior(RectType(rect1.x + 1, rect1.y, rect1.width - 1, rect1.height)))) <<
!(dest.IsEqualInterior(RectType(rect1.x + 1, rect1.y, rect1.Width() - 1, rect1.Height())))) <<
"[7] Test against a rect that overlaps the right edge of rect1";
rect2.x--;
// Test against a rect that's outside of rect1 on the right
rect2.x += rect2.width;
rect2.x += rect2.Width();
EXPECT_FALSE(dest.IntersectRect(rect1, rect2)) <<
"[8] Test against a rect that's outside of rect1 on the right";
// Make sure an empty rect is returned
EXPECT_FALSE(!dest.IsEmpty()) <<
"[8] Make sure an empty rect is returned";
EXPECT_TRUE(dest.IsFinite()) << "[8b] Should be finite";
rect2.x -= rect2.width;
rect2.x -= rect2.Width();
// Test against a rect that overlaps the bottom edge of rect1
rect2.y++;
EXPECT_FALSE(!dest.IntersectRect(rect1, rect2) ||
!(dest.IsEqualInterior(RectType(rect1.x, rect1.y + 1, rect1.width, rect1.height - 1)))) <<
!(dest.IsEqualInterior(RectType(rect1.x, rect1.y + 1, rect1.Width(), rect1.Height() - 1)))) <<
"[9] Test against a rect that overlaps the bottom edge of rect1";
EXPECT_TRUE(dest.IsFinite()) << "[9b] Should be finite";
rect2.y--;
// Test against a rect that's outside of rect1 on the bottom
rect2.y += rect2.height;
rect2.y += rect2.Height();
EXPECT_FALSE(dest.IntersectRect(rect1, rect2)) <<
"[10] Test against a rect that's outside of rect1 on the bottom";
// Make sure an empty rect is returned
EXPECT_FALSE(!dest.IsEmpty()) <<
"[10] Make sure an empty rect is returned";
EXPECT_TRUE(dest.IsFinite()) << "[10b] Should be finite";
rect2.y -= rect2.height;
rect2.y -= rect2.Height();
// Test against a rect with zero width or height
rect1.SetRect(100, 100, 100, 100);
@ -412,12 +412,40 @@ TestBug1135677()
dest = rect1.Intersect(rect2);
EXPECT_TRUE(dest.x == 1073741820 && dest.y == 1073741820 &&
dest.width == 14400 && dest.height == 77640) <<
dest.Width() == 14400 && dest.Height() == 77640) <<
"[1] Operation should not overflow internally.";
return true;
}
template <class RectType>
static bool
TestSetWH()
{
RectType rect(1, 2, 3, 4);
EXPECT_TRUE(rect.X() == 1 && rect.Y() == 2 && rect.Width() == 3 && rect.Height() == 4);
rect.SetWidth(13);
EXPECT_TRUE(rect.X() == 1 && rect.Y() == 2 && rect.Width() == 13 && rect.Height() == 4);
rect.SetHeight(14);
EXPECT_TRUE(rect.X() == 1 && rect.Y() == 2 && rect.Width() == 13 && rect.Height() == 14);
rect.SizeTo(23, 24);
EXPECT_TRUE(rect.X() == 1 && rect.Y() == 2 && rect.Width() == 23 && rect.Height() == 24);
return true;
}
template <class RectType>
static bool
TestSwap()
{
RectType rect(1, 2, 3, 4);
EXPECT_TRUE(rect.X() == 1 && rect.Y() == 2 && rect.Width() == 3 && rect.Height() == 4);
rect.Swap();
EXPECT_TRUE(rect.X() == 2 && rect.Y() == 1 && rect.Width() == 4 && rect.Height() == 3);
return true;
}
TEST(Gfx, nsRect) {
TestConstructors<nsRect>();
TestEqualityOperator<nsRect>();
@ -426,6 +454,8 @@ TEST(Gfx, nsRect) {
TestIntersection<nsRect>();
TestUnion<nsRect>();
TestBug1135677<nsRect>();
TestSetWH<nsRect>();
TestSwap<nsRect>();
}
TEST(Gfx, nsIntRect) {
@ -436,6 +466,8 @@ TEST(Gfx, nsIntRect) {
TestIntersection<nsIntRect>();
TestUnion<nsIntRect>();
TestBug1135677<nsIntRect>();
TestSetWH<nsIntRect>();
TestSwap<nsIntRect>();
}
TEST(Gfx, gfxRect) {
@ -447,4 +479,6 @@ TEST(Gfx, gfxRect) {
TestUnion<gfxRect>();
TestBug1135677<gfxRect>();
TestFiniteGfx();
TestSetWH<gfxRect>();
TestSwap<gfxRect>();
}

Просмотреть файл

@ -758,6 +758,7 @@ BytecodeEmitter::EmitterScope::searchInEnclosingScope(JSAtom* name, Scope* scope
case ScopeKind::NonSyntactic:
return NameLocation::Dynamic();
case ScopeKind::WasmInstance:
case ScopeKind::WasmFunction:
MOZ_CRASH("No direct eval inside wasm functions");
}
@ -1458,6 +1459,7 @@ BytecodeEmitter::EmitterScope::leave(BytecodeEmitter* bce, bool nonLocal)
case ScopeKind::Module:
break;
case ScopeKind::WasmInstance:
case ScopeKind::WasmFunction:
MOZ_CRASH("No wasm function scopes in JS");
}

Просмотреть файл

@ -1285,9 +1285,14 @@ ModuleScope::Data::trace(JSTracer* trc)
TraceBindingNames(trc, names, length);
}
void
WasmInstanceScope::Data::trace(JSTracer* trc)
{
TraceNullableEdge(trc, &instance, "wasm instance");
TraceBindingNames(trc, names, length);
}
void
WasmFunctionScope::Data::trace(JSTracer* trc)
{
TraceNullableEdge(trc, &instance, "wasm function");
TraceBindingNames(trc, names, length);
}
void
@ -1323,6 +1328,9 @@ Scope::traceChildren(JSTracer* trc)
break;
case ScopeKind::With:
break;
case ScopeKind::WasmInstance:
reinterpret_cast<WasmInstanceScope::Data*>(data_)->trace(trc);
break;
case ScopeKind::WasmFunction:
reinterpret_cast<WasmFunctionScope::Data*>(data_)->trace(trc);
break;
@ -1392,9 +1400,16 @@ js::GCMarker::eagerlyMarkChildren(Scope* scope)
case ScopeKind::With:
break;
case ScopeKind::WasmInstance: {
WasmInstanceScope::Data* data = reinterpret_cast<WasmInstanceScope::Data*>(scope->data_);
traverseEdge(scope, static_cast<JSObject*>(data->instance));
names = data->names;
length = data->length;
break;
}
case ScopeKind::WasmFunction: {
WasmFunctionScope::Data* data = reinterpret_cast<WasmFunctionScope::Data*>(scope->data_);
traverseEdge(scope, static_cast<JSObject*>(data->instance));
names = data->names;
length = data->length;
break;

Просмотреть файл

@ -0,0 +1,95 @@
// |jit-test| test-also-wasm-baseline
// Tests that wasm module scripts has inspectable globals and memory.
load(libdir + "wasm.js");
load(libdir + 'eqArrayHelper.js');
function monitorGlobalValues(wast, lib, expected) {
function setupFrame(frame) {
var globals = {};
framesGlobals.push(globals);
// Environment with globals follow function scope enviroment
var globalEnv = frame.environment.parent;
globalEnv.names().forEach(n => {
globals[n] = [globalEnv.getVariable(n)];
});
frame.onStep = function () {
var globalEnv = frame.environment.parent;
globalEnv.names().forEach(n => {
var prevValues = globals[n];
if (!prevValues)
globals[n] = prevValues = [void 0];
var value = globalEnv.getVariable(n);
if (prevValues[prevValues.length - 1] !== value)
prevValues.push(value);
});
}
}
var framesGlobals = [];
wasmRunWithDebugger(wast, lib,
function ({dbg}) {
dbg.onEnterFrame = function(frame) {
if (frame.type == "wasmcall")
setupFrame(frame);
}
},
function ({error}) {
assertEq(error, undefined);
}
);
assertEq(framesGlobals.length, expected.length);
for (var i = 0; i < framesGlobals.length; i++) {
var frameGlobals = framesGlobals[i];
var expectedGlobals = expected[i];
var globalsNames = Object.keys(frameGlobals);
assertEq(globalsNames.length, Object.keys(expectedGlobals).length);
globalsNames.forEach(n => {
if (typeof expectedGlobals[n][0] === "function") {
// expectedGlobals are assert functions
expectedGlobals[n].forEach((assertFn, i) => {
assertFn(frameGlobals[n][i]);
});
return;
}
assertEqArray(frameGlobals[n], expectedGlobals[n]);
});
}
}
monitorGlobalValues(
'(module (func (export "test") (nop)))',
undefined,
[{}]
);
monitorGlobalValues(
'(module (memory (export "memory") 1 1) (func (export "test") (nop) (nop)))',
undefined,
[{
memory0: [
function (actual) {
var bufferProp = actual.proto.getOwnPropertyDescriptor("buffer");
assertEq(!!bufferProp, true, "wasm memory buffer property");
var buffer = bufferProp.get.call(actual).return;
var bufferLengthProp = buffer.proto.getOwnPropertyDescriptor("byteLength");
var bufferLength = bufferLengthProp.get.call(buffer).return;
assertEq(bufferLength, 65536, "wasm memory size");
}
]
}]
);
monitorGlobalValues(
'(module\
(global i32 (i32.const 1))(global i64 (i64.const 2))(global f32 (f32.const 3.5))(global f64 (f64.const 42.25))\
(func (export "test") (nop)))',
undefined,
[{global0: [1], global1: [2], global2: [3.5], global3: [42.25]}]
);
monitorGlobalValues(
'(module (global (mut i32) (i32.const 1))(global (mut i64) (i64.const 2))\
(global (mut f32) (f32.const 3.5))(global (mut f64) (f64.const 42.25))\
(func (export "test")\
(i32.const 2)(set_global 0)(i64.const 1)(set_global 1)\
(f32.const 42.25)(set_global 2)(f64.const 3.5)(set_global 3)))',
undefined,
[{global0: [1, 2], global1: [2, 1], global2: [3.5, 42.25], global3: [42.25, 3.5]}]
)

Просмотреть файл

@ -0,0 +1,45 @@
// |jit-test| test-also-wasm-baseline
// Tests that JS can be evaluated on wasm module scripts frames.
load(libdir + "wasm.js");
wasmRunWithDebugger(
'(module (memory 1 1)\
(global (mut f64) (f64.const 0.5))\
(global f32 (f32.const 3.5))\
(func (param i32) (local f64) (f64.const 1.0) (tee_local 1) (set_global 0) (nop))\
(export "test" 0)\
(data (i32.const 0) "Abc\\x2A"))',
undefined,
function ({dbg}) {
dbg.onEnterFrame = function (frame) {
if (frame.type != 'wasmcall') return;
var memoryContent = frame.eval('new DataView(memory0.buffer).getUint8(3)').return;
assertEq(memoryContent, 42, 'valid memory content is expected (0x2A)');
var global1AndParamSum = frame.eval('global1 + var0').return;
assertEq(global1AndParamSum, 3.5);
var stepNumber = 0;
frame.onStep = function () {
switch (stepNumber) {
case 1: // after i64.const 1.0
assertEq(frame.eval('global0').return, 0.5);
assertEq(frame.eval('var1').return, 0.0);
break;
case 2: // after tee_local $var1
assertEq(frame.eval('var1').return, 1.0);
break;
case 3: // after set_global $global0
assertEq(frame.eval('global0').return, 1.0);
break;
}
stepNumber++;
};
};
},
function ({error}) {
assertEq(error, undefined);
}
);

Просмотреть файл

@ -244,3 +244,20 @@ testInitExpr('f64', 13.37, 0.1989, x => +x);
setJitCompilerOption('wasm.test-mode', 0);
}
// Custom NaN.
{
let dv = new DataView(new ArrayBuffer(8));
module = wasmEvalText(`(module
(global $g f64 (f64.const -nan:0xe7ffff1591120))
(global $h f32 (f32.const -nan:0x651234))
(export "nan64" (global $g))(export "nan32" (global $h))
)`, {}).exports;
dv.setFloat64(0, module.nan64, true);
assertEq(dv.getUint32(4, true), 0x7ff80000);
assertEq(dv.getUint32(0, true), 0x00000000);
dv.setFloat32(0, module.nan32, true);
assertEq(dv.getUint32(0, true), 0x7fc00000);
}

Просмотреть файл

@ -790,6 +790,7 @@ js::XDRScript(XDRState<mode>* xdr, HandleScope scriptEnclosingScope,
return false;
break;
case ScopeKind::Module:
case ScopeKind::WasmInstance:
MOZ_CRASH("NYI");
break;
case ScopeKind::WasmFunction:

Просмотреть файл

@ -8170,11 +8170,10 @@ DebuggerFrame::getArguments(JSContext *cx, HandleDebuggerFrame frame,
*/
static bool
EvaluateInEnv(JSContext* cx, Handle<Env*> env, AbstractFramePtr frame,
jsbytecode* pc, mozilla::Range<const char16_t> chars, const char* filename,
mozilla::Range<const char16_t> chars, const char* filename,
unsigned lineno, MutableHandleValue rval)
{
assertSameCompartment(cx, env, frame);
MOZ_ASSERT_IF(frame, pc);
CompileOptions options(cx);
options.setIsRunOnce(true)
@ -8182,8 +8181,8 @@ EvaluateInEnv(JSContext* cx, Handle<Env*> env, AbstractFramePtr frame,
.setFileAndLine(filename, lineno)
.setCanLazilyParse(false)
.setIntroductionType("debugger eval")
.maybeMakeStrictMode(frame ? frame.script()->strict() : false);
RootedScript callerScript(cx, frame ? frame.script() : nullptr);
.maybeMakeStrictMode(frame && frame.hasScript() ? frame.script()->strict() : false);
RootedScript callerScript(cx, frame && frame.hasScript() ? frame.script() : nullptr);
SourceBufferHolder srcBuf(chars.begin().get(), chars.length(), SourceBufferHolder::NoOwnership);
RootedScript script(cx);
@ -8298,9 +8297,8 @@ DebuggerGenericEval(JSContext* cx, const mozilla::Range<const char16_t> chars,
LeaveDebuggeeNoExecute nnx(cx);
RootedValue rval(cx);
AbstractFramePtr frame = iter ? iter->abstractFramePtr() : NullFramePtr();
jsbytecode* pc = iter ? iter->pc() : nullptr;
bool ok = EvaluateInEnv(cx, env, frame, pc, chars,
bool ok = EvaluateInEnv(cx, env, frame, chars,
options.filename() ? options.filename() : "debugger eval code",
options.lineno(), &rval);
Debugger::resultToCompletion(cx, ok, rval, &status, value);
@ -8314,8 +8312,6 @@ DebuggerFrame::eval(JSContext* cx, HandleDebuggerFrame frame, mozilla::Range<con
MutableHandleValue value)
{
MOZ_ASSERT(frame->isLive());
if (!requireScriptReferent(cx, frame))
return false;
Debugger* dbg = frame->owner();

Просмотреть файл

@ -636,13 +636,46 @@ ModuleEnvironmentObject::newEnumerate(JSContext* cx, HandleObject obj, AutoIdVec
/*****************************************************************************/
const Class WasmInstanceEnvironmentObject::class_ = {
"WasmInstance",
JSCLASS_IS_ANONYMOUS | JSCLASS_HAS_RESERVED_SLOTS(WasmInstanceEnvironmentObject::RESERVED_SLOTS)
};
/* static */ WasmInstanceEnvironmentObject*
WasmInstanceEnvironmentObject::createHollowForDebug(JSContext* cx, Handle<WasmInstanceScope*> scope)
{
RootedObjectGroup group(cx, ObjectGroup::defaultNewGroup(cx, &class_, TaggedProto(nullptr)));
if (!group)
return nullptr;
RootedShape shape(cx, scope->getEmptyEnvironmentShape(cx));
if (!shape)
return nullptr;
gc::AllocKind kind = gc::GetGCObjectKind(shape->numFixedSlots());
MOZ_ASSERT(CanBeFinalizedInBackground(kind, &class_));
kind = gc::GetBackgroundAllocKind(kind);
JSObject* obj;
JS_TRY_VAR_OR_RETURN_NULL(cx, obj, NativeObject::create(cx, kind, gc::DefaultHeap, shape, group));
Rooted<WasmInstanceEnvironmentObject*> callobj(cx, &obj->as<WasmInstanceEnvironmentObject>());
callobj->initEnclosingEnvironment(&cx->global()->lexicalEnvironment());
callobj->initReservedSlot(SCOPE_SLOT, PrivateGCThingValue(scope));
return callobj;
}
/*****************************************************************************/
const Class WasmFunctionCallObject::class_ = {
"WasmCall",
JSCLASS_IS_ANONYMOUS | JSCLASS_HAS_RESERVED_SLOTS(WasmFunctionCallObject::RESERVED_SLOTS)
};
/* static */ WasmFunctionCallObject*
WasmFunctionCallObject::createHollowForDebug(JSContext* cx, Handle<WasmFunctionScope*> scope)
WasmFunctionCallObject::createHollowForDebug(JSContext* cx, HandleObject enclosing,
Handle<WasmFunctionScope*> scope)
{
RootedObjectGroup group(cx, ObjectGroup::defaultNewGroup(cx, &class_, TaggedProto(nullptr)));
if (!group)
@ -660,7 +693,7 @@ WasmFunctionCallObject::createHollowForDebug(JSContext* cx, Handle<WasmFunctionS
JS_TRY_VAR_OR_RETURN_NULL(cx, obj, NativeObject::create(cx, kind, gc::DefaultHeap, shape, group));
Rooted<WasmFunctionCallObject*> callobj(cx, &obj->as<WasmFunctionCallObject>());
callobj->initEnclosingEnvironment(&cx->global()->lexicalEnvironment());
callobj->initEnclosingEnvironment(enclosing);
callobj->initReservedSlot(SCOPE_SLOT, PrivateGCThingValue(scope));
return callobj;
@ -1673,6 +1706,38 @@ class DebugEnvironmentProxyHandler : public BaseProxyHandler
return true;
}
if (env->is<WasmInstanceEnvironmentObject>()) {
RootedScope scope(cx, getEnvironmentScope(*env));
MOZ_ASSERT(scope->is<WasmInstanceScope>());
uint32_t index = 0;
for (BindingIter bi(scope); bi; bi++) {
if (JSID_IS_ATOM(id, bi.name()))
break;
MOZ_ASSERT(!bi.isLast());
index++;
}
Rooted<WasmInstanceScope*> instanceScope(cx, &scope->as<WasmInstanceScope>());
wasm::Instance& instance = instanceScope->instance()->instance();
if (action == GET) {
if (instanceScope->memoriesStart() <= index && index < instanceScope->globalsStart()) {
MOZ_ASSERT(instanceScope->memoriesStart() + 1 == instanceScope->globalsStart());
vp.set(ObjectValue(*instance.memory()));
}
if (instanceScope->globalsStart() <= index) {
MOZ_ASSERT(index < instanceScope->namesCount());
if (!instance.debug().getGlobal(instance, index - instanceScope->globalsStart(), vp)) {
ReportOutOfMemory(cx);
return false;
}
}
*accessResult = ACCESS_UNALIASED;
} else { // if (action == SET)
// TODO
}
return true;
}
/* The rest of the internal scopes do not have unaliased vars. */
MOZ_ASSERT(!IsSyntacticEnvironment(env) ||
env->is<WithEnvironmentObject>());
@ -1707,6 +1772,8 @@ class DebugEnvironmentProxyHandler : public BaseProxyHandler
return &env.as<LexicalEnvironmentObject>().scope();
if (env.is<VarEnvironmentObject>())
return &env.as<VarEnvironmentObject>().scope();
if (env.is<WasmInstanceEnvironmentObject>())
return &env.as<WasmInstanceEnvironmentObject>().scope();
if (env.is<WasmFunctionCallObject>())
return &env.as<WasmFunctionCallObject>().scope();
return nullptr;
@ -2311,6 +2378,7 @@ DebugEnvironmentProxy::isForDeclarative() const
return e.is<CallObject>() ||
e.is<VarEnvironmentObject>() ||
e.is<ModuleEnvironmentObject>() ||
e.is<WasmInstanceEnvironmentObject>() ||
e.is<WasmFunctionCallObject>() ||
e.is<LexicalEnvironmentObject>();
}
@ -2957,6 +3025,7 @@ GetDebugEnvironmentForMissing(JSContext* cx, const EnvironmentIter& ei)
MOZ_ASSERT(!ei.hasSyntacticEnvironment() &&
(ei.scope().is<FunctionScope>() ||
ei.scope().is<LexicalScope>() ||
ei.scope().is<WasmInstanceScope>() ||
ei.scope().is<WasmFunctionScope>() ||
ei.scope().is<VarScope>()));
@ -3000,10 +3069,20 @@ GetDebugEnvironmentForMissing(JSContext* cx, const EnvironmentIter& ei)
if (!env)
return nullptr;
debugEnv = DebugEnvironmentProxy::create(cx, *env, enclosingDebug);
} else if (ei.scope().is<WasmInstanceScope>()) {
Rooted<WasmInstanceScope*> wasmInstanceScope(cx, &ei.scope().as<WasmInstanceScope>());
Rooted<WasmInstanceEnvironmentObject*> env(cx,
WasmInstanceEnvironmentObject::createHollowForDebug(cx, wasmInstanceScope));
if (!env)
return nullptr;
debugEnv = DebugEnvironmentProxy::create(cx, *env, enclosingDebug);
} else if (ei.scope().is<WasmFunctionScope>()) {
Rooted<WasmFunctionScope*> wasmFunctionScope(cx, &ei.scope().as<WasmFunctionScope>());
Rooted<WasmFunctionCallObject*> callobj(cx, WasmFunctionCallObject::createHollowForDebug(cx, wasmFunctionScope));
RootedObject enclosing(cx, &enclosingDebug->as<DebugEnvironmentProxy>().environment());
Rooted<WasmFunctionCallObject*> callobj(cx,
WasmFunctionCallObject::createHollowForDebug(cx, enclosing, wasmFunctionScope));
if (!callobj)
return nullptr;
@ -3053,6 +3132,7 @@ GetDebugEnvironment(JSContext* cx, const EnvironmentIter& ei)
if (ei.scope().is<FunctionScope>() ||
ei.scope().is<LexicalScope>() ||
ei.scope().is<WasmInstanceScope>() ||
ei.scope().is<WasmFunctionScope>() ||
ei.scope().is<VarScope>())
{

Просмотреть файл

@ -427,6 +427,28 @@ typedef Rooted<ModuleEnvironmentObject*> RootedModuleEnvironmentObject;
typedef Handle<ModuleEnvironmentObject*> HandleModuleEnvironmentObject;
typedef MutableHandle<ModuleEnvironmentObject*> MutableHandleModuleEnvironmentObject;
class WasmInstanceEnvironmentObject : public EnvironmentObject
{
// Currently WasmInstanceScopes do not use their scopes in a
// meaningful way. However, it is an invariant of DebugEnvironments that
// environments kept in those maps have live scopes, thus this strong
// reference.
static const uint32_t SCOPE_SLOT = 1;
public:
static const Class class_;
static const uint32_t RESERVED_SLOTS = 2;
static WasmInstanceEnvironmentObject* createHollowForDebug(JSContext* cx,
Handle<WasmInstanceScope*> scope);
WasmInstanceScope& scope() const {
Value v = getReservedSlot(SCOPE_SLOT);
MOZ_ASSERT(v.isPrivateGCThing());
return *static_cast<WasmInstanceScope*>(v.toGCThing());
}
};
class WasmFunctionCallObject : public EnvironmentObject
{
// Currently WasmFunctionCallObjects do not use their scopes in a
@ -440,7 +462,7 @@ class WasmFunctionCallObject : public EnvironmentObject
static const uint32_t RESERVED_SLOTS = 2;
static WasmFunctionCallObject* createHollowForDebug(JSContext* cx,
static WasmFunctionCallObject* createHollowForDebug(JSContext* cx, HandleObject enclosing,
Handle<WasmFunctionScope*> scope);
WasmFunctionScope& scope() const {
Value v = getReservedSlot(SCOPE_SLOT);
@ -1015,6 +1037,7 @@ JSObject::is<js::EnvironmentObject>() const
return is<js::CallObject>() ||
is<js::VarEnvironmentObject>() ||
is<js::ModuleEnvironmentObject>() ||
is<js::WasmInstanceEnvironmentObject>() ||
is<js::WasmFunctionCallObject>() ||
is<js::LexicalEnvironmentObject>() ||
is<js::WithEnvironmentObject>() ||

Просмотреть файл

@ -1071,6 +1071,7 @@ PopEnvironment(JSContext* cx, EnvironmentIter& ei)
case ScopeKind::NonSyntactic:
case ScopeKind::Module:
break;
case ScopeKind::WasmInstance:
case ScopeKind::WasmFunction:
MOZ_CRASH("wasm is not interpreted");
break;

Просмотреть файл

@ -77,6 +77,8 @@ js::ScopeKindString(ScopeKind kind)
return "non-syntactic";
case ScopeKind::Module:
return "module";
case ScopeKind::WasmInstance:
return "wasm instance";
case ScopeKind::WasmFunction:
return "wasm function";
}
@ -427,6 +429,7 @@ Scope::clone(JSContext* cx, HandleScope scope, HandleScope enclosing)
break;
case ScopeKind::Module:
case ScopeKind::WasmInstance:
MOZ_CRASH("NYI");
break;
@ -514,6 +517,9 @@ LexicalScope::nextFrameSlot(Scope* scope)
return 0;
case ScopeKind::Module:
return si.scope()->as<ModuleScope>().nextFrameSlot();
case ScopeKind::WasmInstance:
// TODO return si.scope()->as<WasmInstanceScope>().nextFrameSlot();
return 0;
case ScopeKind::WasmFunction:
// TODO return si.scope()->as<WasmFunctionScope>().nextFrameSlot();
return 0;
@ -1235,16 +1241,16 @@ ModuleScope::script() const
return module()->script();
}
// TODO Check what Debugger behavior should be when it evaluates a
// var declaration.
static const uint32_t WasmFunctionEnvShapeFlags =
static const uint32_t WasmInstanceEnvShapeFlags =
BaseShape::NOT_EXTENSIBLE | BaseShape::DELEGATE;
template <size_t ArrayLength>
static JSAtom*
GenerateWasmVariableName(JSContext* cx, uint32_t index)
GenerateWasmName(JSContext* cx, const char (&prefix)[ArrayLength], uint32_t index)
{
StringBuffer sb(cx);
if (!sb.append("var"))
if (!sb.append(prefix))
return nullptr;
if (!NumberValueToStringBuffer(cx, Int32Value(index), sb))
return nullptr;
@ -1252,45 +1258,109 @@ GenerateWasmVariableName(JSContext* cx, uint32_t index)
return sb.finishAtom();
}
/* static */ WasmFunctionScope*
WasmFunctionScope::create(JSContext* cx, WasmInstanceObject* instance, uint32_t funcIndex)
/* static */ WasmInstanceScope*
WasmInstanceScope::create(JSContext* cx, WasmInstanceObject* instance)
{
// WasmFunctionScope::Data has GCManagedDeletePolicy because it contains a
// WasmInstanceScope::Data has GCManagedDeletePolicy because it contains a
// GCPtr. Destruction of |data| below may trigger calls into the GC.
Rooted<WasmFunctionScope*> wasmFunctionScope(cx);
Rooted<WasmInstanceScope*> wasmInstanceScope(cx);
{
// TODO pull the local variable names from the wasm function definition.
wasm::ValTypeVector locals;
size_t argsLength;
if (!instance->instance().debug().debugGetLocalTypes(funcIndex, &locals, &argsLength))
return nullptr;
uint32_t namesCount = locals.length();
size_t namesCount = 0;
if (instance->instance().memory()) {
namesCount++;
}
size_t globalsStart = namesCount;
size_t globalsCount = instance->instance().metadata().globals.length();
namesCount += globalsCount;
Rooted<UniquePtr<Data>> data(cx, NewEmptyScopeData<WasmFunctionScope>(cx, namesCount));
Rooted<UniquePtr<Data>> data(cx, NewEmptyScopeData<WasmInstanceScope>(cx, namesCount));
if (!data)
return nullptr;
Rooted<Scope*> enclosingScope(cx, &cx->global()->emptyGlobalScope());
data->instance.init(instance);
data->funcIndex = funcIndex;
data->length = namesCount;
for (size_t i = 0; i < namesCount; i++) {
RootedAtom name(cx, GenerateWasmVariableName(cx, i));
size_t nameIndex = 0;
if (instance->instance().memory()) {
RootedAtom name(cx, GenerateWasmName(cx, "memory", /* index = */ 0));
if (!name)
return nullptr;
data->names[i] = BindingName(name, false);
data->names[nameIndex] = BindingName(name, false);
nameIndex++;
}
for (size_t i = 0; i < globalsCount; i++) {
RootedAtom name(cx, GenerateWasmName(cx, "global", i));
if (!name)
return nullptr;
data->names[nameIndex] = BindingName(name, false);
nameIndex++;
}
MOZ_ASSERT(nameIndex == namesCount);
Scope* scope = Scope::create(cx, ScopeKind::WasmFunction, enclosingScope, /* envShape = */ nullptr);
data->instance.init(instance);
data->memoriesStart = 0;
data->globalsStart = globalsStart;
data->length = namesCount;
Rooted<Scope*> enclosingScope(cx, &cx->global()->emptyGlobalScope());
Scope* scope = Scope::create(cx, ScopeKind::WasmInstance, enclosingScope, /* envShape = */ nullptr);
if (!scope)
return nullptr;
wasmFunctionScope = &scope->as<WasmFunctionScope>();
wasmFunctionScope->initData(Move(data.get()));
wasmInstanceScope = &scope->as<WasmInstanceScope>();
wasmInstanceScope->initData(Move(data.get()));
}
return wasmInstanceScope;
}
/* static */ Shape*
WasmInstanceScope::getEmptyEnvironmentShape(JSContext* cx)
{
const Class* cls = &WasmInstanceEnvironmentObject::class_;
return EmptyEnvironmentShape(cx, cls, JSSLOT_FREE(cls), WasmInstanceEnvShapeFlags);
}
// TODO Check what Debugger behavior should be when it evaluates a
// var declaration.
static const uint32_t WasmFunctionEnvShapeFlags =
BaseShape::NOT_EXTENSIBLE | BaseShape::DELEGATE;
/* static */ WasmFunctionScope*
WasmFunctionScope::create(JSContext* cx, HandleScope enclosing, uint32_t funcIndex)
{
MOZ_ASSERT(enclosing->is<WasmInstanceScope>());
Rooted<WasmFunctionScope*> wasmFunctionScope(cx);
Rooted<WasmInstanceObject*> instance(cx, enclosing->as<WasmInstanceScope>().instance());
// TODO pull the local variable names from the wasm function definition.
wasm::ValTypeVector locals;
size_t argsLength;
if (!instance->instance().debug().debugGetLocalTypes(funcIndex, &locals, &argsLength))
return nullptr;
uint32_t namesCount = locals.length();
Rooted<UniquePtr<Data>> data(cx, NewEmptyScopeData<WasmFunctionScope>(cx, namesCount));
if (!data)
return nullptr;
data->funcIndex = funcIndex;
data->length = namesCount;
for (size_t i = 0; i < namesCount; i++) {
RootedAtom name(cx, GenerateWasmName(cx, "var", i));
if (!name)
return nullptr;
data->names[i] = BindingName(name, false);
}
Scope* scope = Scope::create(cx, ScopeKind::WasmFunction, enclosing, /* envShape = */ nullptr);
if (!scope)
return nullptr;
wasmFunctionScope = &scope->as<WasmFunctionScope>();
wasmFunctionScope->initData(Move(data.get()));
return wasmFunctionScope;
}
@ -1352,6 +1422,9 @@ BindingIter::BindingIter(Scope* scope)
case ScopeKind::Module:
init(scope->as<ModuleScope>().data());
break;
case ScopeKind::WasmInstance:
init(scope->as<WasmInstanceScope>().data());
break;
case ScopeKind::WasmFunction:
init(scope->as<WasmFunctionScope>().data());
break;
@ -1485,6 +1558,22 @@ BindingIter::init(ModuleScope::Data& data)
data.names, data.length);
}
void
BindingIter::init(WasmInstanceScope::Data& data)
{
// imports - [0, 0)
// positional formals - [0, 0)
// other formals - [0, 0)
// top-level funcs - [0, 0)
// vars - [0, data.length)
// lets - [data.length, data.length)
// consts - [data.length, data.length)
init(0, 0, 0, 0, data.length, data.length,
CanHaveFrameSlots | CanHaveEnvironmentSlots,
UINT32_MAX, UINT32_MAX,
data.names, data.length);
}
void
BindingIter::init(WasmFunctionScope::Data& data)
{

Просмотреть файл

@ -73,6 +73,9 @@ enum class ScopeKind : uint8_t
// ModuleScope
Module,
// WasmInstanceScope
WasmInstance,
// WasmFunctionScope
WasmFunction
};
@ -949,21 +952,19 @@ class ModuleScope : public Scope
static Shape* getEmptyEnvironmentShape(JSContext* cx);
};
// Scope corresponding to the wasm function. A WasmFunctionScope is used by
// Debugger only, and not for wasm execution.
//
class WasmFunctionScope : public Scope
class WasmInstanceScope : public Scope
{
friend class BindingIter;
friend class Scope;
static const ScopeKind classScopeKind_ = ScopeKind::WasmFunction;
static const ScopeKind classScopeKind_ = ScopeKind::WasmInstance;
public:
struct Data
{
uint32_t memoriesStart;
uint32_t globalsStart;
uint32_t length;
uint32_t nextFrameSlot;
uint32_t funcIndex;
// The wasm instance of the scope.
GCPtr<WasmInstanceObject*> instance;
@ -973,7 +974,7 @@ class WasmFunctionScope : public Scope
void trace(JSTracer* trc);
};
static WasmFunctionScope* create(JSContext* cx, WasmInstanceObject* instance, uint32_t funcIndex);
static WasmInstanceScope* create(JSContext* cx, WasmInstanceObject* instance);
static size_t sizeOfData(uint32_t length) {
return sizeof(Data) + (length ? length - 1 : 0) * sizeof(BindingName);
@ -993,6 +994,58 @@ class WasmFunctionScope : public Scope
return data().instance;
}
uint32_t memoriesStart() const {
return data().memoriesStart;
}
uint32_t globalsStart() const {
return data().globalsStart;
}
uint32_t namesCount() const {
return data().length;
}
static Shape* getEmptyEnvironmentShape(JSContext* cx);
};
// Scope corresponding to the wasm function. A WasmFunctionScope is used by
// Debugger only, and not for wasm execution.
//
class WasmFunctionScope : public Scope
{
friend class BindingIter;
friend class Scope;
static const ScopeKind classScopeKind_ = ScopeKind::WasmFunction;
public:
struct Data
{
uint32_t length;
uint32_t nextFrameSlot;
uint32_t funcIndex;
BindingName names[1];
void trace(JSTracer* trc);
};
static WasmFunctionScope* create(JSContext* cx, HandleScope enclosing, uint32_t funcIndex);
static size_t sizeOfData(uint32_t length) {
return sizeof(Data) + (length ? length - 1 : 0) * sizeof(BindingName);
}
private:
Data& data() {
return *reinterpret_cast<Data*>(data_);
}
const Data& data() const {
return *reinterpret_cast<Data*>(data_);
}
public:
uint32_t funcIndex() const {
return data().funcIndex;
}
@ -1109,6 +1162,7 @@ class BindingIter
void init(GlobalScope::Data& data);
void init(EvalScope::Data& data, bool strict);
void init(ModuleScope::Data& data);
void init(WasmInstanceScope::Data& data);
void init(WasmFunctionScope::Data& data);
bool hasFormalParameterExprs() const {

Просмотреть файл

@ -45,14 +45,15 @@ InterpreterFrame::initExecuteFrame(JSContext* cx, HandleScript script,
RootedValue newTarget(cx, newTargetValue);
if (script->isDirectEvalInFunction()) {
FrameIter iter(cx);
MOZ_ASSERT(!iter.isWasm());
if (newTarget.isNull() &&
iter.hasScript() &&
iter.script()->bodyScope()->hasOnChain(ScopeKind::Function))
{
newTarget = iter.newTarget();
}
} else if (evalInFramePrev) {
if (newTarget.isNull() &&
evalInFramePrev.hasScript() &&
evalInFramePrev.script()->bodyScope()->hasOnChain(ScopeKind::Function))
{
newTarget = evalInFramePrev.newTarget();
@ -159,6 +160,10 @@ AssertScopeMatchesEnvironment(Scope* scope, JSObject* originalEnv)
env = &env->as<ModuleEnvironmentObject>().enclosingEnvironment();
break;
case ScopeKind::WasmInstance:
env = &env->as<WasmInstanceEnvironmentObject>().enclosingEnvironment();
break;
case ScopeKind::WasmFunction:
env = &env->as<WasmFunctionCallObject>().enclosingEnvironment();
break;
@ -1188,7 +1193,6 @@ FrameIter::environmentChain(JSContext* cx) const
{
switch (data_.state_) {
case DONE:
case WASM:
break;
case JIT:
if (data_.jitFrames_.isIonScripted()) {
@ -1198,6 +1202,8 @@ FrameIter::environmentChain(JSContext* cx) const
return data_.jitFrames_.baselineFrame()->environmentChain();
case INTERP:
return interpFrame()->environmentChain();
case WASM:
return data_.wasmFrames_.debugFrame()->environmentChain();
}
MOZ_CRASH("Unexpected state");
}

Просмотреть файл

@ -26,6 +26,7 @@
#include "vm/Debugger.h"
#include "vm/StringBuffer.h"
#include "wasm/WasmBinaryToText.h"
#include "wasm/WasmInstance.h"
#include "wasm/WasmValidate.h"
using namespace js;
@ -549,6 +550,61 @@ DebugState::debugGetResultType(uint32_t funcIndex)
return metadata().debugFuncReturnTypes[funcIndex];
}
bool
DebugState::getGlobal(Instance& instance, uint32_t globalIndex, MutableHandleValue vp)
{
const GlobalDesc& global = metadata().globals[globalIndex];
if (global.isConstant()) {
Val value = global.constantValue();
switch (value.type()) {
case ValType::I32:
vp.set(Int32Value(value.i32()));
break;
case ValType::I64:
// Just display as a Number; it's ok if we lose some precision
vp.set(NumberValue((double)value.i64()));
break;
case ValType::F32:
vp.set(NumberValue(JS::CanonicalizeNaN(value.f32())));
break;
case ValType::F64:
vp.set(NumberValue(JS::CanonicalizeNaN(value.f64())));
break;
default:
MOZ_CRASH("Global constant type");
}
return true;
}
uint8_t* globalData = instance.globalSegment().globalData();
void* dataPtr = globalData + global.offset();
switch (global.type()) {
case ValType::I32: {
vp.set(Int32Value(*static_cast<int32_t*>(dataPtr)));
break;
}
case ValType::I64: {
// Just display as a Number; it's ok if we lose some precision
vp.set(NumberValue((double)*static_cast<int64_t*>(dataPtr)));
break;
}
case ValType::F32: {
vp.set(NumberValue(JS::CanonicalizeNaN(*static_cast<float*>(dataPtr))));
break;
}
case ValType::F64: {
vp.set(NumberValue(JS::CanonicalizeNaN(*static_cast<double*>(dataPtr))));
break;
}
default:
MOZ_CRASH("Global variable type");
break;
}
return true;
}
JSString*
DebugState::debugDisplayURL(JSContext* cx) const
{

Просмотреть файл

@ -143,6 +143,7 @@ class DebugState
bool debugGetLocalTypes(uint32_t funcIndex, ValTypeVector* locals, size_t* argsLength);
ExprType debugGetResultType(uint32_t funcIndex);
bool getGlobal(Instance& instance, uint32_t globalIndex, MutableHandleValue vp);
// Debug URL helpers.

Просмотреть файл

@ -523,6 +523,12 @@ Instance::trace(JSTracer* trc)
TraceEdge(trc, &object_, "wasm instance object");
}
WasmMemoryObject*
Instance::memory() const
{
return memory_;
}
SharedMem<uint8_t*>
Instance::memoryBase() const
{

Просмотреть файл

@ -116,6 +116,7 @@ class Instance
bool isAsmJS() const { return metadata().isAsmJS(); }
const SharedTableVector& tables() const { return tables_; }
SharedMem<uint8_t*> memoryBase() const;
WasmMemoryObject* memory() const;
size_t memoryLength() const;
size_t memoryMappedSize() const;
bool memoryAccessInGuardRegion(uint8_t* addr, unsigned numBytes) const;

Просмотреть файл

@ -1035,6 +1035,7 @@ WasmInstanceObject::create(JSContext* cx,
obj->setReservedSlot(EXPORTS_SLOT, PrivateValue(exports.release()));
obj->setReservedSlot(SCOPES_SLOT, PrivateValue(scopes.release()));
obj->setReservedSlot(INSTANCE_SCOPE_SLOT, UndefinedValue());
MOZ_ASSERT(obj->isNewborn());
MOZ_ASSERT(obj->isTenured(), "assumed by WasmTableObject write barriers");
@ -1213,6 +1214,21 @@ WasmInstanceObject::getExportedFunctionCodeRange(HandleFunction fun, Tier tier)
return instance().metadata(tier).codeRanges[funcExport.codeRangeIndex()];
}
/* static */ WasmInstanceScope*
WasmInstanceObject::getScope(JSContext* cx, HandleWasmInstanceObject instanceObj)
{
if (!instanceObj->getReservedSlot(INSTANCE_SCOPE_SLOT).isUndefined())
return (WasmInstanceScope*)instanceObj->getReservedSlot(INSTANCE_SCOPE_SLOT).toGCThing();
Rooted<WasmInstanceScope*> instanceScope(cx, WasmInstanceScope::create(cx, instanceObj));
if (!instanceScope)
return nullptr;
instanceObj->setReservedSlot(INSTANCE_SCOPE_SLOT, PrivateGCThingValue(instanceScope));
return instanceScope;
}
/* static */ WasmFunctionScope*
WasmInstanceObject::getFunctionScope(JSContext* cx, HandleWasmInstanceObject instanceObj,
uint32_t funcIndex)
@ -1220,7 +1236,11 @@ WasmInstanceObject::getFunctionScope(JSContext* cx, HandleWasmInstanceObject ins
if (ScopeMap::Ptr p = instanceObj->scopes().lookup(funcIndex))
return p->value();
Rooted<WasmFunctionScope*> funcScope(cx, WasmFunctionScope::create(cx, instanceObj, funcIndex));
Rooted<WasmInstanceScope*> instanceScope(cx, WasmInstanceObject::getScope(cx, instanceObj));
if (!instanceScope)
return nullptr;
Rooted<WasmFunctionScope*> funcScope(cx, WasmFunctionScope::create(cx, instanceScope, funcIndex));
if (!funcScope)
return nullptr;

Просмотреть файл

@ -27,6 +27,7 @@ namespace js {
class TypedArrayObject;
class WasmFunctionScope;
class WasmInstanceScope;
namespace wasm {
@ -147,6 +148,7 @@ class WasmInstanceObject : public NativeObject
static const unsigned EXPORTS_OBJ_SLOT = 1;
static const unsigned EXPORTS_SLOT = 2;
static const unsigned SCOPES_SLOT = 3;
static const unsigned INSTANCE_SCOPE_SLOT = 4;
static const ClassOps classOps_;
static bool exportsGetterImpl(JSContext* cx, const CallArgs& args);
static bool exportsGetter(JSContext* cx, unsigned argc, Value* vp);
@ -174,7 +176,7 @@ class WasmInstanceObject : public NativeObject
ScopeMap& scopes() const;
public:
static const unsigned RESERVED_SLOTS = 4;
static const unsigned RESERVED_SLOTS = 5;
static const Class class_;
static const JSPropertySpec properties[];
static const JSFunctionSpec methods[];
@ -202,6 +204,7 @@ class WasmInstanceObject : public NativeObject
const wasm::CodeRange& getExportedFunctionCodeRange(HandleFunction fun, wasm::Tier tier);
static WasmInstanceScope* getScope(JSContext* cx, HandleWasmInstanceObject instanceObj);
static WasmFunctionScope* getFunctionScope(JSContext* cx,
HandleWasmInstanceObject instanceObj,
uint32_t funcIndex);

Просмотреть файл

@ -852,7 +852,7 @@ GetGlobalExport(JSContext* cx, const GlobalDescVector& globals, uint32_t globalI
jsval.set(ObjectValue(*obj));
return true;
}
jsval.set(DoubleValue(double(f)));
jsval.set(DoubleValue(JS::CanonicalizeNaN(double(f))));
return true;
}
case ValType::F64: {
@ -864,7 +864,7 @@ GetGlobalExport(JSContext* cx, const GlobalDescVector& globals, uint32_t globalI
jsval.set(ObjectValue(*obj));
return true;
}
jsval.set(DoubleValue(d));
jsval.set(DoubleValue(JS::CanonicalizeNaN(d)));
return true;
}
default: {

Просмотреть файл

@ -86,6 +86,10 @@ static LazyLogModule gJSCLLog("JSComponentLoader");
static bool
Dump(JSContext* cx, unsigned argc, Value* vp)
{
if (!nsContentUtils::DOMWindowDumpEnabled()) {
return true;
}
CallArgs args = CallArgsFromVp(argc, vp);
if (args.length() == 0)

Просмотреть файл

@ -114,6 +114,10 @@ xpc::NewSandboxConstructor()
static bool
SandboxDump(JSContext* cx, unsigned argc, Value* vp)
{
if (!nsContentUtils::DOMWindowDumpEnabled()) {
return true;
}
CallArgs args = CallArgsFromVp(argc, vp);
if (args.length() == 0)

Просмотреть файл

@ -33,6 +33,7 @@ fuzzy-if(webrender,1,27) == compound-1a.html compound-1-ref.html
== translate-1d.html translate-1-ref.html
== translate-1e.html translate-1-ref.html
== translate-2a.html translate-2-ref.html
== translate-3.html translate-3-ref.html
# rotate: Several rotations of the same object should be idempotent. These
# tests are currently disabled because of subpixel (< 0.00001 gfx units)
# rounding errors.

Просмотреть файл

@ -0,0 +1,8 @@
<!DOCTYPE html>
<style>
div {
width: 100px; height: 100px;
background: green;
}
</style>
<div></div>

Просмотреть файл

@ -0,0 +1,18 @@
<!DOCTYPE html>
<style>
div {
width: 100px; height: 100px;
}
#outer {
background: green;
overflow: hidden;
}
#inner {
background: red;
transform: translateX(calc(100px));
}
</style>
<div id="outer">
<div id="inner">
</div>
</div>

Просмотреть файл

@ -539,7 +539,8 @@ SERVO_BINDING_FUNC(Servo_ResolveStyleLazily, ServoStyleContextStrong,
mozilla::CSSPseudoElementType pseudo_type,
mozilla::StyleRuleInclusion rule_inclusion,
const mozilla::ServoElementSnapshotTable* snapshots,
RawServoStyleSetBorrowed set)
RawServoStyleSetBorrowed set,
bool ignore_existing_styles)
// Reparents style to the new parents.
SERVO_BINDING_FUNC(Servo_ReparentStyle, ServoStyleContextStrong,

Просмотреть файл

@ -5,6 +5,7 @@
#include "mozilla/ServoStyleContext.h"
#include "nsCSSAnonBoxes.h"
#include "nsStyleConsts.h"
#include "nsStyleStruct.h"
#include "nsPresContext.h"
@ -31,4 +32,24 @@ ServoStyleContext::ServoStyleContext(
// producing the ServoComputedData.
}
ServoStyleContext*
ServoStyleContext::GetCachedInheritingAnonBoxStyle(nsIAtom* aAnonBox) const
{
MOZ_ASSERT(nsCSSAnonBoxes::IsInheritingAnonBox(aAnonBox));
// See the reasoning in SetCachedInheritingAnonBoxStyle to understand why we
// can't use the cache in this case.
if (IsInheritingAnonBox()) {
return nullptr;
}
auto* current = mNextInheritingAnonBoxStyle.get();
while (current && current->GetPseudo() != aAnonBox) {
current = current->mNextInheritingAnonBoxStyle.get();
}
return current;
}
} // namespace mozilla

Просмотреть файл

@ -34,6 +34,28 @@ public:
return ComputedData()->visited_style.mPtr;
}
ServoStyleContext* GetCachedInheritingAnonBoxStyle(nsIAtom* aAnonBox) const;
void SetCachedInheritedAnonBoxStyle(nsIAtom* aAnonBox,
ServoStyleContext& aStyle)
{
MOZ_ASSERT(!GetCachedInheritingAnonBoxStyle(aAnonBox));
MOZ_ASSERT(!aStyle.mNextInheritingAnonBoxStyle);
// NOTE(emilio): Since we use it to cache inheriting anon boxes in a linked
// list, we can't use that cache if the style we're inheriting from is an
// inheriting anon box itself, since otherwise our parent would mistakenly
// think that the style we're caching inherits from it.
//
// See the documentation of mNextInheritingAnonBoxStyle.
if (IsInheritingAnonBox()) {
return;
}
mNextInheritingAnonBoxStyle.swap(aStyle.mNextInheritingAnonBoxStyle);
mNextInheritingAnonBoxStyle = &aStyle;
}
/**
* Makes this context match |aOther| in terms of which style structs have
* been resolved.
@ -43,6 +65,13 @@ public:
private:
nsPresContext* mPresContext;
ServoComputedData mSource;
// A linked-list cache of inheriting anon boxes inheriting from this style _if
// the style isn't an inheriting anon-box_.
//
// Otherwise it represents the next entry in the cache of the parent style
// context.
RefPtr<ServoStyleContext> mNextInheritingAnonBoxStyle;
};
} // namespace mozilla

Просмотреть файл

@ -191,13 +191,51 @@ ServoStyleSet::ResolveStyleFor(Element* aElement,
RefPtr<ServoStyleContext> computedValues;
if (aMayCompute == LazyComputeBehavior::Allow) {
PreTraverseSync();
return ResolveStyleLazily(
return ResolveStyleLazilyInternal(
aElement, CSSPseudoElementType::NotPseudo, nullptr, aParentContext);
}
return ResolveServoStyle(aElement, ServoTraversalFlags::Empty);
}
/**
* Clears any stale Servo element data that might existing in the specified
* element's document. Upon destruction, asserts that the element and all
* its ancestors still have no element data, if the document has no pres shell.
*/
class MOZ_STACK_CLASS AutoClearStaleData
{
public:
explicit AutoClearStaleData(Element* aElement)
#ifdef DEBUG
: mElement(aElement)
#endif
{
aElement->OwnerDoc()->ClearStaleServoDataFromDocument();
}
~AutoClearStaleData()
{
#ifdef DEBUG
// Assert that the element and its ancestors are all unstyled, if the
// document has no pres shell.
if (mElement->OwnerDoc()->HasShellOrBFCacheEntry()) {
// We must check whether we're in the bfcache because its presence
// means we have a "hidden" pres shell with up-to-date data in the
// tree.
return;
}
for (Element* e = mElement; e; e = e->GetParentElement()) {
MOZ_ASSERT(!e->HasServoData(), "expected element to be unstyled");
}
#endif
}
private:
#ifdef DEBUG
Element* mElement;
#endif
};
const ServoElementSnapshotTable&
ServoStyleSet::Snapshots()
@ -352,6 +390,32 @@ ServoStyleSet::PrepareAndTraverseSubtree(
return postTraversalRequired;
}
static inline already_AddRefed<ServoStyleContext>
ResolveStyleForTextOrFirstLetterContinuation(
RawServoStyleSetBorrowed aStyleSet,
ServoStyleContext& aParent,
nsIAtom* aAnonBox)
{
MOZ_ASSERT(aAnonBox == nsCSSAnonBoxes::mozText ||
aAnonBox == nsCSSAnonBoxes::firstLetterContinuation);
auto inheritTarget = aAnonBox == nsCSSAnonBoxes::mozText
? InheritTarget::Text
: InheritTarget::FirstLetterContinuation;
RefPtr<ServoStyleContext> style =
aParent.GetCachedInheritingAnonBoxStyle(aAnonBox);
if (!style) {
style = Servo_ComputedValues_Inherit(aStyleSet,
aAnonBox,
&aParent,
inheritTarget).Consume();
MOZ_ASSERT(style);
aParent.SetCachedInheritedAnonBoxStyle(aAnonBox, *style);
}
return style.forget();
}
already_AddRefed<ServoStyleContext>
ServoStyleSet::ResolveStyleForText(nsIContent* aTextNode,
ServoStyleContext* aParentContext)
@ -360,29 +424,17 @@ ServoStyleSet::ResolveStyleForText(nsIContent* aTextNode,
MOZ_ASSERT(aTextNode->GetParent());
MOZ_ASSERT(aParentContext);
// Gecko expects text node style contexts to be like elements that match no
// rules: inherit the inherit structs, reset the reset structs. This is cheap
// enough to do on the main thread, which means that the parallel style system
// can avoid worrying about text nodes.
RefPtr<ServoStyleContext> computedValues =
Servo_ComputedValues_Inherit(mRawSet.get(),
nsCSSAnonBoxes::mozText,
aParentContext,
InheritTarget::Text).Consume();
return computedValues.forget();
return ResolveStyleForTextOrFirstLetterContinuation(
mRawSet.get(), *aParentContext, nsCSSAnonBoxes::mozText);
}
already_AddRefed<ServoStyleContext>
ServoStyleSet::ResolveStyleForFirstLetterContinuation(ServoStyleContext* aParentContext)
{
RefPtr<ServoStyleContext> computedValues =
Servo_ComputedValues_Inherit(mRawSet.get(),
nsCSSAnonBoxes::firstLetterContinuation,
aParentContext,
InheritTarget::FirstLetterContinuation)
.Consume();
MOZ_ASSERT(computedValues);
return computedValues.forget();
MOZ_ASSERT(aParentContext);
return ResolveStyleForTextOrFirstLetterContinuation(
mRawSet.get(), *aParentContext, nsCSSAnonBoxes::firstLetterContinuation);
}
already_AddRefed<ServoStyleContext>
@ -439,25 +491,33 @@ ServoStyleSet::ResolvePseudoElementStyle(Element* aOriginatingElement,
}
already_AddRefed<ServoStyleContext>
ServoStyleSet::ResolveTransientStyle(Element* aElement,
CSSPseudoElementType aPseudoType,
nsIAtom* aPseudoTag,
StyleRuleInclusion aRuleInclusion)
ServoStyleSet::ResolveStyleLazily(Element* aElement,
CSSPseudoElementType aPseudoType,
nsIAtom* aPseudoTag,
StyleRuleInclusion aRuleInclusion)
{
RefPtr<ServoStyleContext> result =
ResolveTransientServoStyle(aElement, aPseudoType, aPseudoTag, aRuleInclusion);
return result.forget();
}
// Lazy style computation avoids storing any new data in the tree.
// If the tree has stale data in it, then the AutoClearStaleData below
// will ensure it's cleared so we don't use it. But if the document is
// in the bfcache, then we will have valid, usable data in the tree,
// but we don't want to use it. Instead we want to pretend as if the
// document has no pres shell and no styles.
//
// If we don't do this, then we can very easily mix styles from different
// style sets in the tree. For example, calling getComputedStyle on an
// element in a display:none iframe (which has no pres shell) will use the
// caller's style set for any styling. If we allowed this to re-use any
// existing styles in the DOM, then we would do selector matching on the
// undisplayed element with the caller's style set's rules, but inherit from
// values that were computed with the style set from the target element's
// hidden-by-the-bfcache-entry pres shell.
bool ignoreExistingStyles = aElement->OwnerDoc()->GetBFCacheEntry();
already_AddRefed<ServoStyleContext>
ServoStyleSet::ResolveTransientServoStyle(
Element* aElement,
CSSPseudoElementType aPseudoType,
nsIAtom* aPseudoTag,
StyleRuleInclusion aRuleInclusion)
{
AutoClearStaleData guard(aElement);
PreTraverseSync();
return ResolveStyleLazily(aElement, aPseudoType, aPseudoTag, nullptr, aRuleInclusion);
return ResolveStyleLazilyInternal(aElement, aPseudoType, aPseudoTag,
nullptr, aRuleInclusion,
ignoreExistingStyles);
}
already_AddRefed<ServoStyleContext>
@ -466,24 +526,28 @@ ServoStyleSet::ResolveInheritingAnonymousBoxStyle(nsIAtom* aPseudoTag,
{
MOZ_ASSERT(nsCSSAnonBoxes::IsAnonBox(aPseudoTag) &&
!nsCSSAnonBoxes::IsNonInheritingAnonBox(aPseudoTag));
MOZ_ASSERT_IF(aParentContext, !StylistNeedsUpdate());
UpdateStylistIfNeeded();
RefPtr<ServoStyleContext> computedValues =
Servo_ComputedValues_GetForAnonymousBox(aParentContext,
aPseudoTag,
mRawSet.get()).Consume();
#ifdef DEBUG
if (!computedValues) {
nsString pseudo;
aPseudoTag->ToString(pseudo);
NS_ERROR(nsPrintfCString("stylo: could not get anon-box: %s",
NS_ConvertUTF16toUTF8(pseudo).get()).get());
MOZ_CRASH();
}
#endif
RefPtr<ServoStyleContext> style = nullptr;
return computedValues.forget();
if (aParentContext) {
style = aParentContext->GetCachedInheritingAnonBoxStyle(aPseudoTag);
}
if (!style) {
style =
Servo_ComputedValues_GetForAnonymousBox(aParentContext,
aPseudoTag,
mRawSet.get()).Consume();
MOZ_ASSERT(style);
if (aParentContext) {
aParentContext->SetCachedInheritedAnonBoxStyle(aPseudoTag, *style);
}
}
return style.forget();
}
already_AddRefed<ServoStyleContext>
@ -920,6 +984,12 @@ ServoStyleSet::GetComputedKeyframeValuesFor(
Element* aElement,
const ServoStyleContext* aContext)
{
// Servo_GetComputedKeyframeValues below won't handle ignoring existing
// element data for bfcached documents. (See comment in ResolveStyleLazily
// about these bfcache issues.)
MOZ_RELEASE_ASSERT(!aElement->OwnerDoc()->GetBFCacheEntry());
AutoClearStaleData guard(aElement);
nsTArray<ComputedKeyframeValues> result(aKeyframes.Length());
// Construct each nsTArray<PropertyStyleAnimationValuePair> here.
@ -940,6 +1010,12 @@ ServoStyleSet::GetAnimationValues(
const ServoStyleContext* aStyleContext,
nsTArray<RefPtr<RawServoAnimationValue>>& aAnimationValues)
{
// Servo_GetAnimationValues below won't handle ignoring existing element
// data for bfcached documents. (See comment in ResolveStyleLazily
// about these bfcache issues.)
MOZ_RELEASE_ASSERT(!aElement->OwnerDoc()->GetBFCacheEntry());
AutoClearStaleData guard(aElement);
Servo_GetAnimationValues(aDeclarations,
aElement,
aStyleContext,
@ -956,6 +1032,14 @@ ServoStyleSet::GetBaseContextForElement(
CSSPseudoElementType aPseudoType,
const ServoStyleContext* aStyle)
{
// Servo_StyleSet_GetBaseComputedValuesForElement below won't handle ignoring
// existing element data for bfcached documents. (See comment in
// ResolveStyleLazily about these bfcache issues.)
MOZ_RELEASE_ASSERT(!aElement->OwnerDoc()->GetBFCacheEntry(),
"GetBaseContextForElement does not support documents in the "
"bfcache");
AutoClearStaleData guard(aElement);
return Servo_StyleSet_GetBaseComputedValuesForElement(mRawSet.get(),
aElement,
aStyle,
@ -969,6 +1053,12 @@ ServoStyleSet::ComputeAnimationValue(
RawServoDeclarationBlock* aDeclarations,
const ServoStyleContext* aContext)
{
// Servo_AnimationValue_Compute below won't handle ignoring existing element
// data for bfcached documents. (See comment in ResolveStyleLazily about
// these bfcache issues.)
MOZ_RELEASE_ASSERT(!aElement->OwnerDoc()->GetBFCacheEntry());
AutoClearStaleData guard(aElement);
return Servo_AnimationValue_Compute(aElement,
aDeclarations,
aContext,
@ -1068,11 +1158,12 @@ ServoStyleSet::ClearNonInheritingStyleContexts()
}
already_AddRefed<ServoStyleContext>
ServoStyleSet::ResolveStyleLazily(Element* aElement,
CSSPseudoElementType aPseudoType,
nsIAtom* aPseudoTag,
const ServoStyleContext* aParentContext,
StyleRuleInclusion aRuleInclusion)
ServoStyleSet::ResolveStyleLazilyInternal(Element* aElement,
CSSPseudoElementType aPseudoType,
nsIAtom* aPseudoTag,
const ServoStyleContext* aParentContext,
StyleRuleInclusion aRuleInclusion,
bool aIgnoreExistingStyles)
{
mPresContext->EffectCompositor()->PreTraverse(aElement, aPseudoType);
MOZ_ASSERT(!StylistNeedsUpdate());
@ -1109,7 +1200,8 @@ ServoStyleSet::ResolveStyleLazily(Element* aElement,
pseudoTypeForStyleResolution,
aRuleInclusion,
&Snapshots(),
mRawSet.get()).Consume();
mRawSet.get(),
aIgnoreExistingStyles).Consume();
if (mPresContext->EffectCompositor()->PreTraverse(aElement, aPseudoType)) {
computedValues =
@ -1117,7 +1209,8 @@ ServoStyleSet::ResolveStyleLazily(Element* aElement,
pseudoTypeForStyleResolution,
aRuleInclusion,
&Snapshots(),
mRawSet.get()).Consume();
mRawSet.get(),
aIgnoreExistingStyles).Consume();
}
if (aPseudoType == CSSPseudoElementType::NotPseudo) {

Просмотреть файл

@ -174,24 +174,15 @@ public:
dom::Element* aPseudoElement);
// Resolves style for a (possibly-pseudo) Element without assuming that the
// style has been resolved, and without worrying about setting the style
// context up to live in the style context tree (a null parent is used).
// |aPeudoTag| and |aPseudoType| must match.
// style has been resolved. If the element was unstyled and a new style
// context was resolved, it is not stored in the DOM. (That is, the element
// remains unstyled.) |aPeudoTag| and |aPseudoType| must match.
already_AddRefed<ServoStyleContext>
ResolveTransientStyle(dom::Element* aElement,
CSSPseudoElementType aPseudoType,
nsIAtom* aPseudoTag,
StyleRuleInclusion aRules =
StyleRuleInclusion::All);
// Similar to ResolveTransientStyle() but doesn't update the context state
// Unlike ResolveServoStyle() this function calls PreTraverseSync().
already_AddRefed<ServoStyleContext>
ResolveTransientServoStyle(dom::Element* aElement,
CSSPseudoElementType aPseudoType,
nsIAtom* aPseudoTag,
StyleRuleInclusion aRules =
StyleRuleInclusion::All);
ResolveStyleLazily(dom::Element* aElement,
CSSPseudoElementType aPseudoType,
nsIAtom* aPseudoTag,
StyleRuleInclusion aRules =
StyleRuleInclusion::All);
// Get a style context for an anonymous box. aPseudoTag is the pseudo-tag to
// use and must be non-null. It must be an anon box, and must be one that
@ -554,12 +545,13 @@ private:
void UpdateStylist();
already_AddRefed<ServoStyleContext>
ResolveStyleLazily(dom::Element* aElement,
CSSPseudoElementType aPseudoType,
nsIAtom* aPseudoTag,
const ServoStyleContext* aParentContext,
StyleRuleInclusion aRules =
StyleRuleInclusion::All);
ResolveStyleLazilyInternal(dom::Element* aElement,
CSSPseudoElementType aPseudoType,
nsIAtom* aPseudoTag,
const ServoStyleContext* aParentContext,
StyleRuleInclusion aRules =
StyleRuleInclusion::All,
bool aIgnoreExistingStyles = false);
void RunPostTraversalTasks();

Просмотреть файл

@ -0,0 +1,27 @@
<!DOCTYPE html>
<html class="reftest-wait">
<style>
textarea {
min-height: 100px;
}
</style>
<div>
<iframe src="about:blank"></iframe>
</div>
<script>
let div = document.querySelector('div');
let iframe = document.querySelector('iframe');
iframe.onload = function() {
let doc = iframe.contentDocument;
let e = doc.createElement('textarea');
doc.body.appendChild(e);
setTimeout(function() {
getComputedStyle(e).minHeight;
div.style.display = 'none';
setTimeout(function() {
getComputedStyle(e).minHeight;
document.documentElement.className = "";
}, 0);
}, 0);
};
</script>

Просмотреть файл

@ -0,0 +1,31 @@
<!DOCTYPE html>
<html class="reftest-wait">
<style>
textarea {
min-height: 100px;
}
</style>
<div>
<iframe src="about:blank"></iframe>
</div>
<script>
let div = document.querySelector('div');
let iframe = document.querySelector('iframe');
iframe.onload = function() {
let doc = iframe.contentDocument;
let e = doc.createElement('textarea');
doc.body.appendChild(e);
setTimeout(function() {
var cs = getComputedStyle(e);
cs.minHeight;
div.style.display = 'none';
setTimeout(function() {
div.style.display = 'block';
setTimeout(function() {
cs.minHeight;
document.documentElement.className = "";
}, 0);
}, 0);
}, 0);
};
</script>

Просмотреть файл

@ -196,3 +196,5 @@ load link-transition-before.html
load long-url-list-stack-overflow.html
load 1383981.html
load 1383981-2.html
load 1384824-1.html
load 1384824-2.html

Просмотреть файл

@ -59,6 +59,22 @@ public:
false;
}
#ifdef DEBUG
// NOTE(emilio): DEBUG only because this does a pretty slow linear search. Try
// to use IsNonInheritingAnonBox if you know the atom is an anon box already
// or, even better, nothing like this.
static bool IsInheritingAnonBox(nsIAtom* aPseudo)
{
return
#define CSS_ANON_BOX(_name, _value) _name == aPseudo ||
#define CSS_NON_INHERITING_ANON_BOX(_name, _value) /* nothing */
#include "nsCSSAnonBoxList.h"
#undef CSS_NON_INHERITING_ANON_BOX
#undef CSS_ANON_BOX
false;
}
#endif
// Get the NonInheriting type for a given pseudo tag. The pseudo tag must
// test true for IsNonInheritingAnonBox.
static NonInheriting NonInheritingTypeForPseudoTag(nsIAtom* aPseudo);

Просмотреть файл

@ -873,7 +873,7 @@ nsCSSValue::GetCalcValue() const
nsStyleCoord::CalcValue result;
if (rootValue.GetUnit() == eCSSUnit_Pixel) {
result.mLength = rootValue.GetFloatValue();
result.mLength = rootValue.GetPixelLength();
result.mPercent = 0.0f;
result.mHasPercent = false;
} else {
@ -890,7 +890,7 @@ nsCSSValue::GetCalcValue() const
"The first value should be eCSSUnit_Pixel");
MOZ_ASSERT(percent.GetUnit() == eCSSUnit_Percent,
"The first value should be eCSSUnit_Percent");
result.mLength = length.GetFloatValue();
result.mLength = length.GetPixelLength();
result.mPercent = percent.GetPercentValue();
result.mHasPercent = true;
}

Просмотреть файл

@ -588,6 +588,15 @@ nsComputedDOMStyle::DoGetStyleContextNoFlush(Element* aElement,
return nullptr;
}
// We do this check to avoid having to add too much special casing of
// Servo functions we call to explicitly ignore any element data in
// the tree. (See comment in ServoStyleSet::ResolveStyleLazily.)
MOZ_RELEASE_ASSERT((aStyleType == eAll && aAnimationFlag == eWithAnimation) ||
!aElement->OwnerDoc()->GetBFCacheEntry(),
"nsComputedDOMStyle doesn't support getting styles without "
"document rules or without animation for documents in the "
"bfcache");
auto pseudoType = CSSPseudoElementType::NotPseudo;
if (aPseudo) {
pseudoType = nsCSSPseudoElements::
@ -657,7 +666,7 @@ nsComputedDOMStyle::DoGetStyleContextNoFlush(Element* aElement,
? StyleRuleInclusion::DefaultOnly
: StyleRuleInclusion::All;
RefPtr<ServoStyleContext> result =
servoSet->ResolveTransientStyle(aElement, pseudoType, aPseudo, rules);
servoSet->ResolveStyleLazily(aElement, pseudoType, aPseudo, rules);
if (aAnimationFlag == eWithAnimation) {
return result.forget();
}

Просмотреть файл

@ -94,11 +94,18 @@ public:
mBits >> NS_STYLE_CONTEXT_TYPE_SHIFT);
}
bool IsAnonBox() const {
return
GetPseudoType() == mozilla::CSSPseudoElementType::InheritingAnonBox ||
GetPseudoType() == mozilla::CSSPseudoElementType::NonInheritingAnonBox;
bool IsInheritingAnonBox() const {
return GetPseudoType() == mozilla::CSSPseudoElementType::InheritingAnonBox;
}
bool IsNonInheritingAnonBox() const {
return GetPseudoType() == mozilla::CSSPseudoElementType::NonInheritingAnonBox;
}
bool IsAnonBox() const {
return IsInheritingAnonBox() || IsNonInheritingAnonBox();
}
bool IsPseudoElement() const { return mPseudoTag && !IsAnonBox(); }

Просмотреть файл

@ -125,6 +125,14 @@ class nsStyleSet final
return ResolveStyleFor(aElement, aParentContext);
}
already_AddRefed<mozilla::GeckoStyleContext>
ResolveCleanStyleFor(mozilla::dom::Element* aElement,
mozilla::GeckoStyleContext* aParentContext,
mozilla::LazyComputeBehavior)
{
return ResolveStyleFor(aElement, aParentContext);
}
already_AddRefed<mozilla::GeckoStyleContext>
ResolveStyleFor(mozilla::dom::Element* aElement,
mozilla::GeckoStyleContext* aParentContext,

Просмотреть файл

@ -15,6 +15,7 @@
#include "nsIContentPolicy.h"
#include "nsIContentSecurityPolicy.h"
#include "nsIURI.h"
#include "nsISupportsPrimitives.h"
#include "nsPrintfCString.h"
#include <cctype>
@ -849,11 +850,16 @@ nsStyleUtil::CSPAllowsInlineStyle(nsIContent* aContent,
aContent->GetAttr(kNameSpaceID_None, nsGkAtoms::nonce, nonce);
}
nsCOMPtr<nsISupportsString> styleText(do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID));
if (styleText) {
styleText->SetData(aStyleText);
}
bool allowInlineStyle = true;
rv = csp->GetAllowsInline(nsIContentPolicy::TYPE_STYLESHEET,
nonce,
false, // aParserCreated only applies to scripts
aStyleText, aLineNumber,
styleText, aLineNumber,
&allowInlineStyle);
NS_ENSURE_SUCCESS(rv, false);

Просмотреть файл

@ -46,8 +46,6 @@ to mochitest command.
## Need Gecko change
* test_specified_value_serialization.html `-webkit-radial-gradient`: bug 1380259 [1]
## Unknown / Unsure
## Ignore

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше