зеркало из https://github.com/mozilla/gecko-dev.git
Merge mozilla-central to autoland. a=merge
--HG-- extra : rebase_source : d93c4498b3c7872e1539b4f37b8601a804820dea
This commit is contained in:
Коммит
791de0dab3
|
@ -48,6 +48,10 @@ let whitelist = [
|
|||
{sourceName: /(?:res|gre-resources)\/forms\.css$/i,
|
||||
errorMessage: /Error in parsing value for \u2018-moz-appearance\u2019/iu,
|
||||
isFromDevTools: false},
|
||||
// -moz-user-select: -moz-text is only enabled to user-agent stylesheets.
|
||||
{sourceName: /contenteditable.css$/i,
|
||||
errorMessage: /Error in parsing value for \u2018-moz-user-select\u2019/iu,
|
||||
isFromDevTools: false},
|
||||
// These variables are declared somewhere else, and error when we load the
|
||||
// files directly. They're all marked intermittent because their appearance
|
||||
// in the error console seems to not be consistent.
|
||||
|
|
|
@ -25,6 +25,8 @@ unset MAKECAB
|
|||
# CARGO
|
||||
. "$topsrcdir/browser/config/mozconfigs/common"
|
||||
|
||||
export MOZ_PACKAGE_JSSHELL=1
|
||||
|
||||
# MinGW Stuff
|
||||
ac_add_options --target=i686-w64-mingw32
|
||||
ac_add_options --with-toolchain-prefix=i686-w64-mingw32-
|
||||
|
|
|
@ -25,6 +25,8 @@ unset MAKECAB
|
|||
# CARGO
|
||||
. "$topsrcdir/browser/config/mozconfigs/common"
|
||||
|
||||
export MOZ_PACKAGE_JSSHELL=1
|
||||
|
||||
# MinGW Stuff
|
||||
ac_add_options --target=x86_64-w64-mingw32
|
||||
ac_add_options --with-toolchain-prefix=x86_64-w64-mingw32-
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
This is the PDF.js project output, https://github.com/mozilla/pdf.js
|
||||
|
||||
Current extension version is: 2.1.42
|
||||
Current extension version is: 2.1.52
|
||||
|
||||
Taken from upstream commit: 2194aef0
|
||||
Taken from upstream commit: 4724ebbc
|
||||
|
|
|
@ -785,11 +785,9 @@ class FindEventManager {
|
|||
}
|
||||
|
||||
bind() {
|
||||
var unload = (evt) => {
|
||||
this.contentWindow.addEventListener("unload", (evt) => {
|
||||
this.unbind();
|
||||
this.contentWindow.removeEventListener(evt.type, unload);
|
||||
};
|
||||
this.contentWindow.addEventListener("unload", unload);
|
||||
}, {once: true});
|
||||
|
||||
// We cannot directly attach listeners to for the find events
|
||||
// since the FindBar is in the parent process. Instead we're
|
||||
|
@ -812,6 +810,7 @@ class FindEventManager {
|
|||
|
||||
unbind() {
|
||||
this.winmm.sendAsyncMessage("PDFJS:Parent:removeEventListener");
|
||||
this.winmm.removeMessageListener("PDFJS:Child:handleEvent", this);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -123,8 +123,8 @@ return /******/ (function(modules) { // webpackBootstrap
|
|||
"use strict";
|
||||
|
||||
|
||||
var pdfjsVersion = '2.1.42';
|
||||
var pdfjsBuild = '2194aef0';
|
||||
var pdfjsVersion = '2.1.52';
|
||||
var pdfjsBuild = '4724ebbc';
|
||||
var pdfjsSharedUtil = __w_pdfjs_require__(1);
|
||||
var pdfjsDisplayAPI = __w_pdfjs_require__(7);
|
||||
var pdfjsDisplayTextLayer = __w_pdfjs_require__(19);
|
||||
|
@ -4226,7 +4226,7 @@ function _fetchDocument(worker, source, pdfDataRangeTransport, docId) {
|
|||
}
|
||||
return worker.messageHandler.sendWithPromise('GetDocRequest', {
|
||||
docId,
|
||||
apiVersion: '2.1.42',
|
||||
apiVersion: '2.1.52',
|
||||
source: {
|
||||
data: source.data,
|
||||
url: source.url,
|
||||
|
@ -5540,8 +5540,8 @@ var InternalRenderTask = function InternalRenderTaskClosure() {
|
|||
}();
|
||||
var version, build;
|
||||
{
|
||||
exports.version = version = '2.1.42';
|
||||
exports.build = build = '2194aef0';
|
||||
exports.version = version = '2.1.52';
|
||||
exports.build = build = '4724ebbc';
|
||||
}
|
||||
exports.getDocument = getDocument;
|
||||
exports.LoopbackPort = LoopbackPort;
|
||||
|
|
|
@ -123,8 +123,8 @@ return /******/ (function(modules) { // webpackBootstrap
|
|||
"use strict";
|
||||
|
||||
|
||||
var pdfjsVersion = '2.1.42';
|
||||
var pdfjsBuild = '2194aef0';
|
||||
var pdfjsVersion = '2.1.52';
|
||||
var pdfjsBuild = '4724ebbc';
|
||||
var pdfjsCoreWorker = __w_pdfjs_require__(1);
|
||||
exports.WorkerMessageHandler = pdfjsCoreWorker.WorkerMessageHandler;
|
||||
|
||||
|
@ -326,7 +326,7 @@ var WorkerMessageHandler = {
|
|||
var cancelXHRs = null;
|
||||
var WorkerTasks = [];
|
||||
let apiVersion = docParams.apiVersion;
|
||||
let workerVersion = '2.1.42';
|
||||
let workerVersion = '2.1.52';
|
||||
if (apiVersion !== workerVersion) {
|
||||
throw new Error(`The API version "${apiVersion}" does not match ` + `the Worker version "${workerVersion}".`);
|
||||
}
|
||||
|
|
|
@ -4045,12 +4045,12 @@ Object.defineProperty(exports, "__esModule", {
|
|||
});
|
||||
exports.PDFFindController = exports.FindState = undefined;
|
||||
|
||||
var _ui_utils = __webpack_require__(2);
|
||||
|
||||
var _pdfjsLib = __webpack_require__(3);
|
||||
|
||||
var _pdf_find_utils = __webpack_require__(16);
|
||||
|
||||
var _ui_utils = __webpack_require__(2);
|
||||
|
||||
const FindState = {
|
||||
FOUND: 0,
|
||||
NOT_FOUND: 1,
|
||||
|
@ -4058,6 +4058,8 @@ const FindState = {
|
|||
PENDING: 3
|
||||
};
|
||||
const FIND_TIMEOUT = 250;
|
||||
const MATCH_SCROLL_OFFSET_TOP = -50;
|
||||
const MATCH_SCROLL_OFFSET_LEFT = -400;
|
||||
const CHARACTERS_TO_NORMALIZE = {
|
||||
'\u2018': '\'',
|
||||
'\u2019': '\'',
|
||||
|
@ -4114,18 +4116,24 @@ class PDFFindController {
|
|||
this._firstPageCapability.resolve();
|
||||
}
|
||||
executeCommand(cmd, state) {
|
||||
if (!state) {
|
||||
return;
|
||||
}
|
||||
const pdfDocument = this._pdfDocument;
|
||||
if (this._state === null || this._shouldDirtyMatch(cmd)) {
|
||||
if (this._state === null || this._shouldDirtyMatch(cmd, state)) {
|
||||
this._dirtyMatch = true;
|
||||
}
|
||||
this._state = state;
|
||||
this._updateUIState(FindState.PENDING);
|
||||
if (cmd !== 'findhighlightallchange') {
|
||||
this._updateUIState(FindState.PENDING);
|
||||
}
|
||||
this._firstPageCapability.promise.then(() => {
|
||||
if (!this._pdfDocument || pdfDocument && this._pdfDocument !== pdfDocument) {
|
||||
return;
|
||||
}
|
||||
this._extractText();
|
||||
const findbarClosed = !this._highlightMatches;
|
||||
const pendingTimeout = !!this._findTimeout;
|
||||
if (this._findTimeout) {
|
||||
clearTimeout(this._findTimeout);
|
||||
this._findTimeout = null;
|
||||
|
@ -4142,13 +4150,36 @@ class PDFFindController {
|
|||
if (findbarClosed && this._state.highlightAll) {
|
||||
this._updateAllPages();
|
||||
}
|
||||
} else if (cmd === 'findhighlightallchange') {
|
||||
if (pendingTimeout) {
|
||||
this._nextMatch();
|
||||
} else {
|
||||
this._highlightMatches = true;
|
||||
}
|
||||
this._updateAllPages();
|
||||
} else {
|
||||
this._nextMatch();
|
||||
}
|
||||
});
|
||||
}
|
||||
scrollMatchIntoView({ element = null, pageIndex = -1, matchIndex = -1 }) {
|
||||
if (!this._scrollMatches || !element) {
|
||||
return;
|
||||
} else if (matchIndex === -1 || matchIndex !== this._selected.matchIdx) {
|
||||
return;
|
||||
} else if (pageIndex === -1 || pageIndex !== this._selected.pageIdx) {
|
||||
return;
|
||||
}
|
||||
this._scrollMatches = false;
|
||||
const spot = {
|
||||
top: MATCH_SCROLL_OFFSET_TOP,
|
||||
left: MATCH_SCROLL_OFFSET_LEFT
|
||||
};
|
||||
(0, _ui_utils.scrollIntoView)(element, spot, true);
|
||||
}
|
||||
_reset() {
|
||||
this._highlightMatches = false;
|
||||
this._scrollMatches = false;
|
||||
this._pdfDocument = null;
|
||||
this._pageMatches = [];
|
||||
this._pageMatchesLength = [];
|
||||
|
@ -4180,7 +4211,10 @@ class PDFFindController {
|
|||
}
|
||||
return this._normalizedQuery;
|
||||
}
|
||||
_shouldDirtyMatch(cmd) {
|
||||
_shouldDirtyMatch(cmd, state) {
|
||||
if (state.query !== this._state.query) {
|
||||
return true;
|
||||
}
|
||||
switch (cmd) {
|
||||
case 'findagain':
|
||||
const pageNumber = this._selected.pageIdx + 1;
|
||||
|
@ -4189,6 +4223,8 @@ class PDFFindController {
|
|||
break;
|
||||
}
|
||||
return false;
|
||||
case 'findhighlightallchange':
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -4343,7 +4379,7 @@ class PDFFindController {
|
|||
}
|
||||
}
|
||||
_updatePage(index) {
|
||||
if (this._selected.pageIdx === index) {
|
||||
if (this._scrollMatches && this._selected.pageIdx === index) {
|
||||
this._linkService.page = index + 1;
|
||||
}
|
||||
this._eventBus.dispatch('updatetextlayermatches', {
|
||||
|
@ -4463,6 +4499,7 @@ class PDFFindController {
|
|||
}
|
||||
this._updateUIState(state, this._state.findPrevious);
|
||||
if (this._selected.pageIdx !== -1) {
|
||||
this._scrollMatches = true;
|
||||
this._updatePage(this._selected.pageIdx);
|
||||
}
|
||||
}
|
||||
|
@ -6922,22 +6959,19 @@ class BaseViewer {
|
|||
let pageView = this._pages[this._currentPageNumber - 1];
|
||||
this._scrollIntoView({ pageDiv: pageView.div });
|
||||
}
|
||||
scrollPageIntoView(params) {
|
||||
scrollPageIntoView({ pageNumber, destArray = null, allowNegativeOffset = false }) {
|
||||
if (!this.pdfDocument) {
|
||||
return;
|
||||
}
|
||||
let pageNumber = params.pageNumber || 0;
|
||||
let dest = params.destArray || null;
|
||||
let allowNegativeOffset = params.allowNegativeOffset || false;
|
||||
if (this.isInPresentationMode || !dest) {
|
||||
this._setCurrentPageNumber(pageNumber, true);
|
||||
return;
|
||||
}
|
||||
let pageView = this._pages[pageNumber - 1];
|
||||
const pageView = Number.isInteger(pageNumber) && this._pages[pageNumber - 1];
|
||||
if (!pageView) {
|
||||
console.error(`${this._name}.scrollPageIntoView: Invalid "pageNumber" parameter.`);
|
||||
return;
|
||||
}
|
||||
if (this.isInPresentationMode || !destArray) {
|
||||
this._setCurrentPageNumber(pageNumber, true);
|
||||
return;
|
||||
}
|
||||
let x = 0,
|
||||
y = 0;
|
||||
let width = 0,
|
||||
|
@ -6948,11 +6982,11 @@ class BaseViewer {
|
|||
let pageWidth = (changeOrientation ? pageView.height : pageView.width) / pageView.scale / _ui_utils.CSS_UNITS;
|
||||
let pageHeight = (changeOrientation ? pageView.width : pageView.height) / pageView.scale / _ui_utils.CSS_UNITS;
|
||||
let scale = 0;
|
||||
switch (dest[1].name) {
|
||||
switch (destArray[1].name) {
|
||||
case 'XYZ':
|
||||
x = dest[2];
|
||||
y = dest[3];
|
||||
scale = dest[4];
|
||||
x = destArray[2];
|
||||
y = destArray[3];
|
||||
scale = destArray[4];
|
||||
x = x !== null ? x : 0;
|
||||
y = y !== null ? y : pageHeight;
|
||||
break;
|
||||
|
@ -6962,7 +6996,7 @@ class BaseViewer {
|
|||
break;
|
||||
case 'FitH':
|
||||
case 'FitBH':
|
||||
y = dest[2];
|
||||
y = destArray[2];
|
||||
scale = 'page-width';
|
||||
if (y === null && this._location) {
|
||||
x = this._location.left;
|
||||
|
@ -6971,16 +7005,16 @@ class BaseViewer {
|
|||
break;
|
||||
case 'FitV':
|
||||
case 'FitBV':
|
||||
x = dest[2];
|
||||
x = destArray[2];
|
||||
width = pageWidth;
|
||||
height = pageHeight;
|
||||
scale = 'page-height';
|
||||
break;
|
||||
case 'FitR':
|
||||
x = dest[2];
|
||||
y = dest[3];
|
||||
width = dest[4] - x;
|
||||
height = dest[5] - y;
|
||||
x = destArray[2];
|
||||
y = destArray[3];
|
||||
width = destArray[4] - x;
|
||||
height = destArray[5] - y;
|
||||
let hPadding = this.removePageBorders ? 0 : _ui_utils.SCROLLBAR_PADDING;
|
||||
let vPadding = this.removePageBorders ? 0 : _ui_utils.VERTICAL_PADDING;
|
||||
widthScale = (this.container.clientWidth - hPadding) / width / _ui_utils.CSS_UNITS;
|
||||
|
@ -6988,7 +7022,7 @@ class BaseViewer {
|
|||
scale = Math.min(Math.abs(widthScale), Math.abs(heightScale));
|
||||
break;
|
||||
default:
|
||||
console.error(`${this._name}.scrollPageIntoView: "${dest[1].name}" ` + 'is not a valid destination type.');
|
||||
console.error(`${this._name}.scrollPageIntoView: ` + `"${destArray[1].name}" is not a valid destination type.`);
|
||||
return;
|
||||
}
|
||||
if (scale && scale !== this._currentScale) {
|
||||
|
@ -6996,7 +7030,7 @@ class BaseViewer {
|
|||
} else if (this._currentScale === _ui_utils.UNKNOWN_SCALE) {
|
||||
this.currentScaleValue = _ui_utils.DEFAULT_SCALE_VALUE;
|
||||
}
|
||||
if (scale === 'page-fit' && !dest[4]) {
|
||||
if (scale === 'page-fit' && !destArray[4]) {
|
||||
this._scrollIntoView({
|
||||
pageDiv: pageView.div,
|
||||
pageNumber
|
||||
|
@ -7232,7 +7266,7 @@ class BaseViewer {
|
|||
if (this._currentScaleValue && isNaN(this._currentScaleValue)) {
|
||||
this._setScale(this._currentScaleValue, true);
|
||||
}
|
||||
this.scrollPageIntoView({ pageNumber });
|
||||
this._setCurrentPageNumber(pageNumber, true);
|
||||
this.update();
|
||||
}
|
||||
get spreadMode() {
|
||||
|
@ -7281,7 +7315,7 @@ class BaseViewer {
|
|||
if (!pageNumber) {
|
||||
return;
|
||||
}
|
||||
this.scrollPageIntoView({ pageNumber });
|
||||
this._setCurrentPageNumber(pageNumber, true);
|
||||
this.update();
|
||||
}
|
||||
}
|
||||
|
@ -7854,8 +7888,6 @@ var _ui_utils = __webpack_require__(2);
|
|||
var _pdfjsLib = __webpack_require__(3);
|
||||
|
||||
const EXPAND_DIVS_TIMEOUT = 300;
|
||||
const MATCH_SCROLL_OFFSET_TOP = -50;
|
||||
const MATCH_SCROLL_OFFSET_LEFT = -400;
|
||||
class TextLayerBuilder {
|
||||
constructor({ textLayerDiv, eventBus, pageIndex, viewport, findController = null, enhanceTextSelection = false }) {
|
||||
this.textLayerDiv = textLayerDiv;
|
||||
|
@ -8013,13 +8045,11 @@ class TextLayerBuilder {
|
|||
let end = match.end;
|
||||
let isSelected = isSelectedPage && i === selectedMatchIdx;
|
||||
let highlightSuffix = isSelected ? ' selected' : '';
|
||||
if (findController.selected.matchIdx === i && findController.selected.pageIdx === pageIdx) {
|
||||
const spot = {
|
||||
top: MATCH_SCROLL_OFFSET_TOP,
|
||||
left: MATCH_SCROLL_OFFSET_LEFT
|
||||
};
|
||||
(0, _ui_utils.scrollIntoView)(textDivs[begin.divIdx], spot, true);
|
||||
}
|
||||
findController.scrollMatchIntoView({
|
||||
element: textDivs[begin.divIdx],
|
||||
pageIndex: pageIdx,
|
||||
matchIndex: i
|
||||
});
|
||||
if (!prevEnd || begin.divIdx !== prevEnd.divIdx) {
|
||||
if (prevEnd !== null) {
|
||||
appendTextToDiv(prevEnd.divIdx, prevEnd.offset, infinity.offset);
|
||||
|
|
|
@ -20,7 +20,7 @@ origin:
|
|||
|
||||
# Human-readable identifier for this version/release
|
||||
# Generally "version NNN", "tag SSS", "bookmark SSS"
|
||||
release: version 2.1.42
|
||||
release: version 2.1.52
|
||||
|
||||
# The package's license, where possible using the mnemonic from
|
||||
# https://spdx.org/licenses/
|
||||
|
|
|
@ -69,6 +69,4 @@ For options that accept ``true`` or ``false``, ``=true`` can be left off to get
|
|||
OptionalExtensions=false
|
||||
|
||||
``/ExtractDir=[directory]``
|
||||
Extract the application files to the given directory and exit, without actually running the installer. Of course, this means all other options will be ignored.
|
||||
|
||||
This option is not available for use in .ini files.
|
||||
Extract the application files to the given directory and exit, without actually running the installer. No other options may be supplied along with ``ExtractDir``, and ``ExtractDir`` is not available for use in .ini files.
|
||||
|
|
|
@ -69,7 +69,7 @@
|
|||
ExeCommand="/S /InstallDirectoryName=[INSTALL_DIRECTORY_NAME] /TaskbarShortcut=[TASKBAR_SHORTCUT] /DesktopShortcut=[DESKTOP_SHORTCUT] /StartMenuShortcut=[START_MENU_SHORTCUT] /MaintenanceService=[INSTALL_MAINTENANCE_SERVICE] /RemoveDistributionDir=[REMOTE_DISTRIBUTION_DIR] /PreventRebootRequired=[PREVENT_REBOOT_REQUIRED] /OptionalExtensions=[OPTIONAL_EXTENSIONS] /LaunchedFromMSI" />
|
||||
<CustomAction Id="RunExtractOnly" Return="check" Execute="deferred"
|
||||
HideTarget="no" Impersonate="no" BinaryKey="WrappedExe"
|
||||
ExeCommand="/S /ExtractDir=[EXTRACT_DIR]" />
|
||||
ExeCommand="/ExtractDir=[EXTRACT_DIR]" />
|
||||
|
||||
<!-- When we run the custom actions is kind of arbitrary; this sequencing gets
|
||||
us the least confusing message showing in the MSI progress dialog while
|
||||
|
|
|
@ -1356,19 +1356,14 @@ exports.CSS_PROPERTIES = {
|
|||
],
|
||||
"supports": [],
|
||||
"values": [
|
||||
"-moz-all",
|
||||
"-moz-none",
|
||||
"-moz-text",
|
||||
"all",
|
||||
"auto",
|
||||
"element",
|
||||
"elements",
|
||||
"inherit",
|
||||
"initial",
|
||||
"none",
|
||||
"text",
|
||||
"toggle",
|
||||
"tri-state",
|
||||
"unset"
|
||||
]
|
||||
},
|
||||
|
@ -2752,19 +2747,14 @@ exports.CSS_PROPERTIES = {
|
|||
],
|
||||
"supports": [],
|
||||
"values": [
|
||||
"-moz-all",
|
||||
"-moz-none",
|
||||
"-moz-text",
|
||||
"all",
|
||||
"auto",
|
||||
"element",
|
||||
"elements",
|
||||
"inherit",
|
||||
"initial",
|
||||
"none",
|
||||
"text",
|
||||
"toggle",
|
||||
"tri-state",
|
||||
"unset"
|
||||
]
|
||||
},
|
||||
|
|
|
@ -66,10 +66,14 @@ FetchStreamReader::Create(JSContext* aCx, nsIGlobalObject* aGlobal,
|
|||
|
||||
RefPtr<WeakWorkerRef> workerRef =
|
||||
WeakWorkerRef::Create(workerPrivate, [streamReader]() {
|
||||
// The WorkerPrivate does have a context available, and we could pass
|
||||
// it here to trigger cancellation of the reader, but the author of
|
||||
// this comment chickened out.
|
||||
streamReader->CloseAndRelease(nullptr, NS_ERROR_DOM_INVALID_STATE_ERR);
|
||||
MOZ_ASSERT(streamReader);
|
||||
MOZ_ASSERT(streamReader->mWorkerRef);
|
||||
|
||||
WorkerPrivate* workerPrivate = streamReader->mWorkerRef->GetPrivate();
|
||||
MOZ_ASSERT(workerPrivate);
|
||||
|
||||
streamReader->CloseAndRelease(workerPrivate->GetJSContext(),
|
||||
NS_ERROR_DOM_INVALID_STATE_ERR);
|
||||
});
|
||||
|
||||
if (NS_WARN_IF(!workerRef)) {
|
||||
|
|
|
@ -1575,31 +1575,27 @@ IDBObjectStore::GetAddInfo(JSContext* aCx,
|
|||
}
|
||||
|
||||
// Figure out indexes and the index values to update here.
|
||||
const nsTArray<IndexMetadata>& indexes = mSpec->indexes();
|
||||
|
||||
uint32_t idxCount = indexes.Length();
|
||||
|
||||
if (idxCount) {
|
||||
if (!aValueWrapper.Clone(aCx)) {
|
||||
return NS_ERROR_DOM_DATA_CLONE_ERR;
|
||||
}
|
||||
|
||||
// Update idxCount, the structured clone process may trigger content code
|
||||
// via getters/other which can potentially call CreateIndex/DeleteIndex.
|
||||
idxCount = indexes.Length();
|
||||
if (mSpec->indexes().Length() && !aValueWrapper.Clone(aCx)) {
|
||||
return NS_ERROR_DOM_DATA_CLONE_ERR;
|
||||
}
|
||||
|
||||
aUpdateInfoArray.SetCapacity(idxCount); // Pretty good estimate
|
||||
{
|
||||
const nsTArray<IndexMetadata>& indexes = mSpec->indexes();
|
||||
uint32_t idxCount = indexes.Length();
|
||||
|
||||
for (uint32_t idxIndex = 0; idxIndex < idxCount; idxIndex++) {
|
||||
const IndexMetadata& metadata = indexes[idxIndex];
|
||||
aUpdateInfoArray.SetCapacity(idxCount); // Pretty good estimate
|
||||
|
||||
rv = AppendIndexUpdateInfo(metadata.id(), metadata.keyPath(),
|
||||
metadata.unique(), metadata.multiEntry(),
|
||||
metadata.locale(), aCx, aValueWrapper.Value(),
|
||||
aUpdateInfoArray);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
for (uint32_t idxIndex = 0; idxIndex < idxCount; idxIndex++) {
|
||||
const IndexMetadata& metadata = indexes[idxIndex];
|
||||
|
||||
rv = AppendIndexUpdateInfo(metadata.id(), metadata.keyPath(),
|
||||
metadata.unique(), metadata.multiEntry(),
|
||||
metadata.locale(), aCx, aValueWrapper.Value(),
|
||||
aUpdateInfoArray);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1664,6 +1660,11 @@ IDBObjectStore::AddOrPut(JSContext* aCx,
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
if (!mTransaction->IsOpen()) {
|
||||
aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Check the size limit of the serialized message which mainly consists of
|
||||
// a StructuredCloneBuffer, an encoded object key, and the encoded index keys.
|
||||
// kMaxIDBMsgOverhead covers the minor stuff not included in this calculation
|
||||
|
|
|
@ -83,3 +83,4 @@ skip-if = (os == 'linux') # Bug 1244409
|
|||
[test_sharedWorker_privateBrowsing.html]
|
||||
[test_shutdownCheck.xul]
|
||||
support-files = worker_shutdownCheck.js
|
||||
[test_readableStream_when_closing.html]
|
||||
|
|
|
@ -0,0 +1,66 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for ReadableStream+fetch when the worker is closing</title>
|
||||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?>
|
||||
</head>
|
||||
<body>
|
||||
<script>
|
||||
|
||||
function workerCode() {
|
||||
onmessage = () => {
|
||||
const BIG_BUFFER_SIZE = 1000000;
|
||||
const fibStream = new ReadableStream({
|
||||
start(controller) {},
|
||||
|
||||
pull(controller) {
|
||||
const buffer = new Uint8Array(BIG_BUFFER_SIZE);
|
||||
buffer.fill(42);
|
||||
controller.enqueue(buffer);
|
||||
}
|
||||
});
|
||||
|
||||
const r = new Response(fibStream);
|
||||
|
||||
const p = r.blob();
|
||||
self.postMessage("reading");
|
||||
|
||||
p.then(() => {
|
||||
// really?
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SpecialPowers.pushPrefEnv({"set": [
|
||||
["javascript.options.streams", true],
|
||||
]}).then(() => {
|
||||
const b = new Blob([workerCode+'workerCode();']);
|
||||
const url = URL.createObjectURL(b);
|
||||
const w = new Worker(url);
|
||||
w.onmessage = function(e) {
|
||||
ok(true, 'Worker is reading');
|
||||
|
||||
const wdm = Cc["@mozilla.org/dom/workers/workerdebuggermanager;1"].
|
||||
getService(Ci.nsIWorkerDebuggerManager);
|
||||
wdm.addListener({
|
||||
onUnregister: function (dbg) {
|
||||
if (dbg.url == url) {
|
||||
ok(true, "Debugger with url " + url + " should be unregistered.");
|
||||
wdm.removeListener(this);
|
||||
SimpleTest.finish();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
w.terminate();
|
||||
}
|
||||
w.postMessage("start");
|
||||
});
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -296,7 +296,9 @@ template<class units>
|
|||
bool RectIsInt32Safe(const RectTyped<units>& aRect) {
|
||||
float min = (float)std::numeric_limits<std::int32_t>::min();
|
||||
float max = (float)std::numeric_limits<std::int32_t>::max();
|
||||
return aRect.x > min && aRect.y > min && aRect.XMost() < max && aRect.YMost() < max;
|
||||
return aRect.x > min && aRect.y > min &&
|
||||
aRect.width < max && aRect.height < max &&
|
||||
aRect.XMost() < max && aRect.YMost() < max;
|
||||
}
|
||||
|
||||
template<class units>
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<style class="">
|
||||
* {
|
||||
transform: scalex(10) !important;
|
||||
block-size: calc(-25958*-8px + -23%);
|
||||
}
|
||||
|
||||
@page :left {
|
||||
@page :left {
|
||||
*:link {}
|
||||
}
|
||||
}
|
||||
|
||||
* {
|
||||
box-shadow: green calc(42em - 43357px) 45px, blue -3841px 125px, currentColor 21px 50268px, 168px 2px 50817px 253px orange;
|
||||
-moz-columns: 2 auto ! important;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body class="" style="inline-size:-moz-min-content!important">
|
||||
<p class=""><canvas class="" width="1024">
|
||||
</body>
|
||||
</html>
|
|
@ -169,5 +169,6 @@ load 1467847-1.html
|
|||
load 1468020.html
|
||||
load 1470440.html
|
||||
load 1478035.html
|
||||
load 1490704-1.html
|
||||
load 1501518.html
|
||||
load 1503986-1.html
|
||||
|
|
|
@ -122,10 +122,6 @@ Evaluate(JSContext* cx, AutoVector<JSObject*>& envChain, const ReadOnlyCompileOp
|
|||
* Evaluate the provided UTF-8 data in the scope of the current global of |cx|,
|
||||
* and return the completion value in |rval|. If the data contains invalid
|
||||
* UTF-8, an error is reported.
|
||||
*
|
||||
* The |options.utf8| flag is asserted to be true. At a future time this flag
|
||||
* will be removed and UTF-8-ness of source bytes will be entirely determined
|
||||
* by which compilation function is called.
|
||||
*/
|
||||
extern JS_PUBLIC_API(bool)
|
||||
EvaluateUtf8(JSContext* cx, const ReadOnlyCompileOptions& options,
|
||||
|
@ -136,10 +132,6 @@ EvaluateUtf8(JSContext* cx, const ReadOnlyCompileOptions& options,
|
|||
* the same Unicode code point) in the scope of the current global of |cx|, and
|
||||
* return the completion value in |rval|.
|
||||
*
|
||||
* The |options.utf8| flag is asserted to be false. At a future time this flag
|
||||
* will be removed and UTF-8-ness of source bytes will be entirely determined
|
||||
* by which compilation function is called.
|
||||
*
|
||||
* This function may eventually be removed, such that *only* bytes containing
|
||||
* UTF-8 source text may be directly compiled. Avoid using it if you can.
|
||||
*/
|
||||
|
@ -152,9 +144,6 @@ EvaluateLatin1(JSContext* cx, const ReadOnlyCompileOptions& options,
|
|||
* completion value in |rval|. (The path itself is in the system encoding, not
|
||||
* [necessarily] UTF-8.) If the contents contain any malformed UTF-8, an error
|
||||
* is reported.
|
||||
*
|
||||
* The |options.utf8| flag is asserted to be true. At a future time this flag
|
||||
* will be removed.
|
||||
*/
|
||||
extern JS_PUBLIC_API(bool)
|
||||
EvaluateUtf8Path(JSContext* cx, const ReadOnlyCompileOptions& options,
|
||||
|
@ -171,10 +160,6 @@ Compile(JSContext* cx, const ReadOnlyCompileOptions& options,
|
|||
* Compile the provided UTF-8 data into a script. If the data contains invalid
|
||||
* UTF-8, an error is reported.
|
||||
*
|
||||
* The |options.utf8| flag is asserted to be true. At a future time this flag
|
||||
* will be removed and UTF-8-ness of source bytes will be entirely determined
|
||||
* by which compilation function is called.
|
||||
*
|
||||
* |script| is always set to the compiled script or to null in case of error.
|
||||
*/
|
||||
extern JS_PUBLIC_API(bool)
|
||||
|
@ -185,10 +170,6 @@ CompileUtf8(JSContext* cx, const ReadOnlyCompileOptions& options,
|
|||
* Compile the provided Latin-1 data (i.e. each byte directly corresponds to
|
||||
* the same Unicode code point) into a script.
|
||||
*
|
||||
* The |options.utf8| flag is asserted to be false. At a future time this flag
|
||||
* will be removed and UTF-8-ness of source bytes will be entirely determined
|
||||
* by which compilation function is called.
|
||||
*
|
||||
* This function may eventually be removed, such that *only* bytes containing
|
||||
* UTF-8 source text may be directly compiled. Avoid using it if you can.
|
||||
*
|
||||
|
@ -203,9 +184,6 @@ CompileLatin1(JSContext* cx, const ReadOnlyCompileOptions& options,
|
|||
* contain any malformed UTF-8, an error is reported.
|
||||
*
|
||||
* |script| is always set to the compiled script or to null in case of error.
|
||||
*
|
||||
* The |options.utf8| flag is asserted to be true. At a future time this flag
|
||||
* will be removed.
|
||||
*/
|
||||
extern JS_PUBLIC_API(bool)
|
||||
CompileUtf8File(JSContext* cx, const ReadOnlyCompileOptions& options,
|
||||
|
@ -217,9 +195,6 @@ CompileUtf8File(JSContext* cx, const ReadOnlyCompileOptions& options,
|
|||
* the contents contain any malformed UTF-8, an error is reported.
|
||||
*
|
||||
* |script| is always set to the compiled script or to null in case of error.
|
||||
*
|
||||
* The |options.utf8| flag is asserted to be true. At a future time this flag
|
||||
* will be removed.
|
||||
*/
|
||||
extern JS_PUBLIC_API(bool)
|
||||
CompileUtf8Path(JSContext* cx, const ReadOnlyCompileOptions& options,
|
||||
|
|
|
@ -42,51 +42,13 @@ using JS::SourceBufferHolder;
|
|||
// function bodies.
|
||||
class MOZ_STACK_CLASS BytecodeCompiler
|
||||
{
|
||||
public:
|
||||
// Construct an object passing mandatory arguments.
|
||||
BytecodeCompiler(JSContext* cx,
|
||||
const ReadOnlyCompileOptions& options,
|
||||
SourceBufferHolder& sourceBuffer,
|
||||
HandleScope enclosingScope);
|
||||
|
||||
JSScript* compileGlobalScript(ScopeKind scopeKind);
|
||||
JSScript* compileEvalScript(HandleObject environment, HandleScope enclosingScope);
|
||||
ModuleObject* compileModule();
|
||||
bool compileStandaloneFunction(MutableHandleFunction fun, GeneratorKind generatorKind,
|
||||
FunctionAsyncKind asyncKind,
|
||||
const Maybe<uint32_t>& parameterListEnd);
|
||||
|
||||
ScriptSourceObject* sourceObjectPtr() const;
|
||||
|
||||
private:
|
||||
JSScript* compileScript(HandleObject environment, SharedContext* sc);
|
||||
bool checkLength();
|
||||
bool createScriptSource(const Maybe<uint32_t>& parameterListEnd);
|
||||
bool canLazilyParse();
|
||||
bool createParser(ParseGoal goal);
|
||||
bool createSourceAndParser(ParseGoal goal,
|
||||
const Maybe<uint32_t>& parameterListEnd = Nothing());
|
||||
|
||||
// If toString{Start,End} are not explicitly passed, assume the script's
|
||||
// offsets in the source used to parse it are the same as what should be
|
||||
// used to compute its Function.prototype.toString() value.
|
||||
bool createScript();
|
||||
bool createScript(uint32_t toStringStart, uint32_t toStringEnd);
|
||||
|
||||
using TokenStreamPosition = frontend::TokenStreamPosition<char16_t>;
|
||||
|
||||
bool emplaceEmitter(Maybe<BytecodeEmitter>& emitter, SharedContext* sharedContext);
|
||||
bool handleParseFailure(const Directives& newDirectives, TokenStreamPosition& startPosition);
|
||||
bool deoptimizeArgumentsInEnclosingScripts(JSContext* cx, HandleObject environment);
|
||||
|
||||
protected:
|
||||
AutoKeepAtoms keepAtoms;
|
||||
|
||||
JSContext* cx;
|
||||
const ReadOnlyCompileOptions& options;
|
||||
SourceBufferHolder& sourceBuffer;
|
||||
|
||||
RootedScope enclosingScope;
|
||||
|
||||
RootedScriptSourceObject sourceObject;
|
||||
ScriptSource* scriptSource;
|
||||
|
||||
|
@ -97,6 +59,80 @@ class MOZ_STACK_CLASS BytecodeCompiler
|
|||
Directives directives;
|
||||
|
||||
RootedScript script;
|
||||
|
||||
public:
|
||||
// Construct an object passing mandatory arguments.
|
||||
BytecodeCompiler(JSContext* cx,
|
||||
const ReadOnlyCompileOptions& options,
|
||||
SourceBufferHolder& sourceBuffer);
|
||||
|
||||
ScriptSourceObject* sourceObjectPtr() const {
|
||||
return sourceObject.get();
|
||||
}
|
||||
|
||||
// Call this before calling compile{Global,Eval}Script.
|
||||
MOZ_MUST_USE bool prepareScriptParse() {
|
||||
return createSourceAndParser(ParseGoal::Script) && createCompleteScript();
|
||||
}
|
||||
|
||||
JSScript* compileGlobalScript(ScopeKind scopeKind);
|
||||
JSScript* compileEvalScript(HandleObject environment, HandleScope enclosingScope);
|
||||
|
||||
// Call this before calling compileModule.
|
||||
MOZ_MUST_USE bool prepareModuleParse() {
|
||||
return createSourceAndParser(ParseGoal::Module) && createCompleteScript();
|
||||
}
|
||||
|
||||
ModuleObject* compileModule(HandleScope enclosingScope);
|
||||
|
||||
// Call this before calling parseStandaloneFunction.
|
||||
MOZ_MUST_USE bool prepareStandaloneFunctionParse(const Maybe<uint32_t>& parameterListEnd) {
|
||||
return createSourceAndParser(ParseGoal::Script, parameterListEnd);
|
||||
}
|
||||
|
||||
// Call this before calling compileStandaloneFunction.
|
||||
CodeNode* parseStandaloneFunction(MutableHandleFunction fun, GeneratorKind generatorKind,
|
||||
FunctionAsyncKind asyncKind,
|
||||
const Maybe<uint32_t>& parameterListEnd,
|
||||
HandleScope enclosingScope);
|
||||
|
||||
bool compileStandaloneFunction(CodeNode* parsedFunction, MutableHandleFunction fun);
|
||||
|
||||
private:
|
||||
void assertSourceAndParserCreated() const {
|
||||
MOZ_ASSERT(sourceObject != nullptr);
|
||||
MOZ_ASSERT(scriptSource != nullptr);
|
||||
MOZ_ASSERT(usedNames.isSome());
|
||||
MOZ_ASSERT(parser.isSome());
|
||||
}
|
||||
|
||||
void assertSourceParserAndScriptCreated() const {
|
||||
assertSourceAndParserCreated();
|
||||
MOZ_ASSERT(script != nullptr);
|
||||
}
|
||||
|
||||
JSScript* compileScript(HandleObject environment, SharedContext* sc);
|
||||
bool checkLength();
|
||||
bool createScriptSource(const Maybe<uint32_t>& parameterListEnd);
|
||||
bool canLazilyParse();
|
||||
bool createParser(ParseGoal goal);
|
||||
bool createSourceAndParser(ParseGoal goal,
|
||||
const Maybe<uint32_t>& parameterListEnd = Nothing());
|
||||
|
||||
// This assumes the created script's offsets in the source used to parse it
|
||||
// are the same as are used to compute its Function.prototype.toString()
|
||||
// value.
|
||||
bool createCompleteScript();
|
||||
|
||||
// This uses explicitly-provided toString offsets as the created script's
|
||||
// offsets in the source.
|
||||
bool createScript(uint32_t toStringStart, uint32_t toStringEnd);
|
||||
|
||||
using TokenStreamPosition = frontend::TokenStreamPosition<char16_t>;
|
||||
|
||||
bool emplaceEmitter(Maybe<BytecodeEmitter>& emitter, SharedContext* sharedContext);
|
||||
bool handleParseFailure(const Directives& newDirectives, TokenStreamPosition& startPosition);
|
||||
bool deoptimizeArgumentsInEnclosingScripts(JSContext* cx, HandleObject environment);
|
||||
};
|
||||
|
||||
AutoFrontendTraceLog::AutoFrontendTraceLog(JSContext* cx, const TraceLoggerTextId id,
|
||||
|
@ -153,13 +189,11 @@ AutoFrontendTraceLog::AutoFrontendTraceLog(JSContext* cx, const TraceLoggerTextI
|
|||
|
||||
BytecodeCompiler::BytecodeCompiler(JSContext* cx,
|
||||
const ReadOnlyCompileOptions& options,
|
||||
SourceBufferHolder& sourceBuffer,
|
||||
HandleScope enclosingScope)
|
||||
SourceBufferHolder& sourceBuffer)
|
||||
: keepAtoms(cx),
|
||||
cx(cx),
|
||||
options(options),
|
||||
sourceBuffer(sourceBuffer),
|
||||
enclosingScope(cx, enclosingScope),
|
||||
sourceObject(cx),
|
||||
scriptSource(nullptr),
|
||||
directives(options.strictOption),
|
||||
|
@ -229,9 +263,10 @@ BytecodeCompiler::createParser(ParseGoal goal)
|
|||
usedNames.emplace(cx);
|
||||
|
||||
if (canLazilyParse()) {
|
||||
syntaxParser.emplace(cx, cx->tempLifoAlloc(), options, sourceBuffer.get(),
|
||||
sourceBuffer.length(), /* foldConstants = */ false,
|
||||
*usedNames, nullptr, nullptr, sourceObject, goal);
|
||||
syntaxParser.emplace(cx, cx->tempLifoAlloc(), options,
|
||||
sourceBuffer.get(), sourceBuffer.length(),
|
||||
/* foldConstants = */ false, *usedNames, nullptr, nullptr,
|
||||
sourceObject, goal);
|
||||
if (!syntaxParser->checkOptions()) {
|
||||
return false;
|
||||
}
|
||||
|
@ -253,7 +288,7 @@ BytecodeCompiler::createSourceAndParser(ParseGoal goal,
|
|||
}
|
||||
|
||||
bool
|
||||
BytecodeCompiler::createScript()
|
||||
BytecodeCompiler::createCompleteScript()
|
||||
{
|
||||
return createScript(0, sourceBuffer.length());
|
||||
}
|
||||
|
@ -325,16 +360,10 @@ BytecodeCompiler::deoptimizeArgumentsInEnclosingScripts(JSContext* cx, HandleObj
|
|||
JSScript*
|
||||
BytecodeCompiler::compileScript(HandleObject environment, SharedContext* sc)
|
||||
{
|
||||
if (!createSourceAndParser(ParseGoal::Script)) {
|
||||
return nullptr;
|
||||
}
|
||||
assertSourceParserAndScriptCreated();
|
||||
|
||||
TokenStreamPosition startPosition(keepAtoms, parser->tokenStream);
|
||||
|
||||
if (!createScript()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Maybe<BytecodeEmitter> emitter;
|
||||
if (!emplaceEmitter(emitter, sc)) {
|
||||
return nullptr;
|
||||
|
@ -396,6 +425,11 @@ JSScript*
|
|||
BytecodeCompiler::compileGlobalScript(ScopeKind scopeKind)
|
||||
{
|
||||
GlobalSharedContext globalsc(cx, scopeKind, directives, options.extraWarningsOption);
|
||||
|
||||
if (!prepareScriptParse()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return compileScript(nullptr, &globalsc);
|
||||
}
|
||||
|
||||
|
@ -404,25 +438,24 @@ BytecodeCompiler::compileEvalScript(HandleObject environment, HandleScope enclos
|
|||
{
|
||||
EvalSharedContext evalsc(cx, environment, enclosingScope,
|
||||
directives, options.extraWarningsOption);
|
||||
|
||||
if (!prepareScriptParse()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return compileScript(environment, &evalsc);
|
||||
}
|
||||
|
||||
ModuleObject*
|
||||
BytecodeCompiler::compileModule()
|
||||
BytecodeCompiler::compileModule(HandleScope enclosingScope)
|
||||
{
|
||||
if (!createSourceAndParser(ParseGoal::Module)) {
|
||||
return nullptr;
|
||||
}
|
||||
assertSourceParserAndScriptCreated();
|
||||
|
||||
Rooted<ModuleObject*> module(cx, ModuleObject::create(cx));
|
||||
if (!module) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!createScript()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
module->init(script);
|
||||
|
||||
ModuleBuilder builder(cx, module, parser->anyChars);
|
||||
|
@ -461,21 +494,20 @@ BytecodeCompiler::compileModule()
|
|||
return module;
|
||||
}
|
||||
|
||||
// Compile a standalone JS function, which might appear as the value of an
|
||||
// Parse a standalone JS function, which might appear as the value of an
|
||||
// event handler attribute in an HTML <INPUT> tag, or in a Function()
|
||||
// constructor.
|
||||
bool
|
||||
BytecodeCompiler::compileStandaloneFunction(MutableHandleFunction fun,
|
||||
GeneratorKind generatorKind,
|
||||
FunctionAsyncKind asyncKind,
|
||||
const Maybe<uint32_t>& parameterListEnd)
|
||||
CodeNode*
|
||||
BytecodeCompiler::parseStandaloneFunction(MutableHandleFunction fun,
|
||||
GeneratorKind generatorKind,
|
||||
FunctionAsyncKind asyncKind,
|
||||
const Maybe<uint32_t>& parameterListEnd,
|
||||
HandleScope enclosingScope)
|
||||
{
|
||||
MOZ_ASSERT(fun);
|
||||
MOZ_ASSERT(fun->isTenured());
|
||||
|
||||
if (!createSourceAndParser(ParseGoal::Script, parameterListEnd)) {
|
||||
return false;
|
||||
}
|
||||
assertSourceAndParserCreated();
|
||||
|
||||
TokenStreamPosition startPosition(keepAtoms, parser->tokenStream);
|
||||
|
||||
|
@ -490,11 +522,18 @@ BytecodeCompiler::compileStandaloneFunction(MutableHandleFunction fun,
|
|||
fn = parser->standaloneFunction(fun, enclosingScope, parameterListEnd, generatorKind,
|
||||
asyncKind, directives, &newDirectives);
|
||||
if (!fn && !handleParseFailure(newDirectives, startPosition)) {
|
||||
return false;
|
||||
return nullptr;
|
||||
}
|
||||
} while (!fn);
|
||||
|
||||
FunctionBox* funbox = fn->as<CodeNode>().funbox();
|
||||
return &fn->as<CodeNode>();
|
||||
}
|
||||
|
||||
// Compile a standalone JS function.
|
||||
bool
|
||||
BytecodeCompiler::compileStandaloneFunction(CodeNode* parsedFunction, MutableHandleFunction fun)
|
||||
{
|
||||
FunctionBox* funbox = parsedFunction->funbox();
|
||||
if (funbox->function()->isInterpreted()) {
|
||||
MOZ_ASSERT(fun == funbox->function());
|
||||
|
||||
|
@ -506,9 +545,7 @@ BytecodeCompiler::compileStandaloneFunction(MutableHandleFunction fun,
|
|||
if (!emplaceEmitter(emitter, funbox)) {
|
||||
return false;
|
||||
}
|
||||
if (!emitter->emitFunctionScript(&fn->as<CodeNode>(),
|
||||
BytecodeEmitter::TopLevelFunction::Yes))
|
||||
{
|
||||
if (!emitter->emitFunctionScript(parsedFunction, BytecodeEmitter::TopLevelFunction::Yes)) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
|
@ -517,17 +554,7 @@ BytecodeCompiler::compileStandaloneFunction(MutableHandleFunction fun,
|
|||
}
|
||||
|
||||
// Enqueue an off-thread source compression task after finishing parsing.
|
||||
if (!scriptSource->tryCompressOffThread(cx)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
ScriptSourceObject*
|
||||
BytecodeCompiler::sourceObjectPtr() const
|
||||
{
|
||||
return sourceObject.get();
|
||||
return scriptSource->tryCompressOffThread(cx);
|
||||
}
|
||||
|
||||
ScriptSourceObject*
|
||||
|
@ -646,7 +673,7 @@ frontend::CompileGlobalScript(JSContext* cx, ScopeKind scopeKind,
|
|||
{
|
||||
MOZ_ASSERT(scopeKind == ScopeKind::Global || scopeKind == ScopeKind::NonSyntactic);
|
||||
AutoAssertReportedException assertException(cx);
|
||||
BytecodeCompiler compiler(cx, options, srcBuf, /* enclosingScope = */ nullptr);
|
||||
BytecodeCompiler compiler(cx, options, srcBuf);
|
||||
AutoInitializeSourceObject autoSSO(compiler, sourceObjectOut);
|
||||
JSScript* script = compiler.compileGlobalScript(scopeKind);
|
||||
if (!script) {
|
||||
|
@ -727,7 +754,7 @@ frontend::CompileEvalScript(JSContext* cx, HandleObject environment,
|
|||
ScriptSourceObject** sourceObjectOut)
|
||||
{
|
||||
AutoAssertReportedException assertException(cx);
|
||||
BytecodeCompiler compiler(cx, options, srcBuf, enclosingScope);
|
||||
BytecodeCompiler compiler(cx, options, srcBuf);
|
||||
AutoInitializeSourceObject autoSSO(compiler, sourceObjectOut);
|
||||
JSScript* script = compiler.compileEvalScript(environment, enclosingScope);
|
||||
if (!script) {
|
||||
|
@ -753,10 +780,15 @@ frontend::CompileModule(JSContext* cx, const ReadOnlyCompileOptions& optionsInpu
|
|||
options.setIsRunOnce(true);
|
||||
options.allowHTMLComments = false;
|
||||
|
||||
RootedScope emptyGlobalScope(cx, &cx->global()->emptyGlobalScope());
|
||||
BytecodeCompiler compiler(cx, options, srcBuf, emptyGlobalScope);
|
||||
BytecodeCompiler compiler(cx, options, srcBuf);
|
||||
AutoInitializeSourceObject autoSSO(compiler, sourceObjectOut);
|
||||
ModuleObject* module = compiler.compileModule();
|
||||
|
||||
if (!compiler.prepareModuleParse()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RootedScope emptyGlobalScope(cx, &cx->global()->emptyGlobalScope());
|
||||
ModuleObject* module = compiler.compileModule(emptyGlobalScope);
|
||||
if (!module) {
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -1001,16 +1033,20 @@ frontend::CompileStandaloneFunction(JSContext* cx, MutableHandleFunction fun,
|
|||
{
|
||||
AutoAssertReportedException assertException(cx);
|
||||
|
||||
BytecodeCompiler compiler(cx, options, srcBuf);
|
||||
if (!compiler.prepareStandaloneFunctionParse(parameterListEnd)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
RootedScope scope(cx, enclosingScope);
|
||||
if (!scope) {
|
||||
scope = &cx->global()->emptyGlobalScope();
|
||||
}
|
||||
|
||||
BytecodeCompiler compiler(cx, options, srcBuf, scope);
|
||||
if (!compiler.compileStandaloneFunction(fun, GeneratorKind::NotGenerator,
|
||||
FunctionAsyncKind::SyncFunction,
|
||||
parameterListEnd))
|
||||
{
|
||||
CodeNode* parsedFunction = compiler.parseStandaloneFunction(fun, GeneratorKind::NotGenerator,
|
||||
FunctionAsyncKind::SyncFunction,
|
||||
parameterListEnd, scope);
|
||||
if (!parsedFunction || !compiler.compileStandaloneFunction(parsedFunction, fun)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1026,13 +1062,17 @@ frontend::CompileStandaloneGenerator(JSContext* cx, MutableHandleFunction fun,
|
|||
{
|
||||
AutoAssertReportedException assertException(cx);
|
||||
|
||||
RootedScope emptyGlobalScope(cx, &cx->global()->emptyGlobalScope());
|
||||
BytecodeCompiler compiler(cx, options, srcBuf);
|
||||
if (!compiler.prepareStandaloneFunctionParse(parameterListEnd)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
BytecodeCompiler compiler(cx, options, srcBuf, emptyGlobalScope);
|
||||
if (!compiler.compileStandaloneFunction(fun, GeneratorKind::Generator,
|
||||
FunctionAsyncKind::SyncFunction,
|
||||
parameterListEnd))
|
||||
{
|
||||
RootedScope emptyGlobalScope(cx, &cx->global()->emptyGlobalScope());
|
||||
CodeNode* parsedFunction = compiler.parseStandaloneFunction(fun, GeneratorKind::Generator,
|
||||
FunctionAsyncKind::SyncFunction,
|
||||
parameterListEnd,
|
||||
emptyGlobalScope);
|
||||
if (!parsedFunction || !compiler.compileStandaloneFunction(parsedFunction, fun)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1048,13 +1088,17 @@ frontend::CompileStandaloneAsyncFunction(JSContext* cx, MutableHandleFunction fu
|
|||
{
|
||||
AutoAssertReportedException assertException(cx);
|
||||
|
||||
RootedScope emptyGlobalScope(cx, &cx->global()->emptyGlobalScope());
|
||||
BytecodeCompiler compiler(cx, options, srcBuf);
|
||||
if (!compiler.prepareStandaloneFunctionParse(parameterListEnd)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
BytecodeCompiler compiler(cx, options, srcBuf, emptyGlobalScope);
|
||||
if (!compiler.compileStandaloneFunction(fun, GeneratorKind::NotGenerator,
|
||||
FunctionAsyncKind::AsyncFunction,
|
||||
parameterListEnd))
|
||||
{
|
||||
RootedScope emptyGlobalScope(cx, &cx->global()->emptyGlobalScope());
|
||||
CodeNode* parsedFunction = compiler.parseStandaloneFunction(fun, GeneratorKind::NotGenerator,
|
||||
FunctionAsyncKind::AsyncFunction,
|
||||
parameterListEnd,
|
||||
emptyGlobalScope);
|
||||
if (!parsedFunction || !compiler.compileStandaloneFunction(parsedFunction, fun)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1070,13 +1114,17 @@ frontend::CompileStandaloneAsyncGenerator(JSContext* cx, MutableHandleFunction f
|
|||
{
|
||||
AutoAssertReportedException assertException(cx);
|
||||
|
||||
RootedScope emptyGlobalScope(cx, &cx->global()->emptyGlobalScope());
|
||||
BytecodeCompiler compiler(cx, options, srcBuf);
|
||||
if (!compiler.prepareStandaloneFunctionParse(parameterListEnd)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
BytecodeCompiler compiler(cx, options, srcBuf, emptyGlobalScope);
|
||||
if (!compiler.compileStandaloneFunction(fun, GeneratorKind::Generator,
|
||||
FunctionAsyncKind::AsyncFunction,
|
||||
parameterListEnd))
|
||||
{
|
||||
RootedScope emptyGlobalScope(cx, &cx->global()->emptyGlobalScope());
|
||||
CodeNode* parsedFunction = compiler.parseStandaloneFunction(fun, GeneratorKind::Generator,
|
||||
FunctionAsyncKind::AsyncFunction,
|
||||
parameterListEnd,
|
||||
emptyGlobalScope);
|
||||
if (!parsedFunction || !compiler.compileStandaloneFunction(parsedFunction, fun)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -680,8 +680,8 @@ SourceUnits<Utf8Unit>::assertNextCodePoint(const PeekedCodePoint<Utf8Unit>& peek
|
|||
expectedUnits[1] = 0b1000'0000 | ((c >> 6) & 0b11'1111);
|
||||
expectedUnits[2] = 0b1000'0000 | (c & 0b11'1111);
|
||||
} else {
|
||||
expectedUnits[0] = 0b1110'0000 | (c >> 18);
|
||||
expectedUnits[2] = 0b1000'0000 | ((c >> 12) & 0b11'1111);
|
||||
expectedUnits[0] = 0b1111'0000 | (c >> 18);
|
||||
expectedUnits[1] = 0b1000'0000 | ((c >> 12) & 0b11'1111);
|
||||
expectedUnits[2] = 0b1000'0000 | ((c >> 6) & 0b11'1111);
|
||||
expectedUnits[3] = 0b1000'0000 | (c & 0b11'1111);
|
||||
}
|
||||
|
@ -794,14 +794,17 @@ TokenStreamChars<Utf8Unit, AnyCharsAccess>::notEnoughUnits(Utf8Unit lead,
|
|||
const char actualStr[] = { toHexChar(remaining - 1), '\0' };
|
||||
|
||||
internalEncodingError(remaining, JSMSG_NOT_ENOUGH_CODE_UNITS,
|
||||
leadByteStr, expectedStr, actualStr, remaining == 2 ? " was" : "s were");
|
||||
leadByteStr,
|
||||
expectedStr, required == 2 ? "" : "s",
|
||||
actualStr, remaining == 2 ? " was" : "s were");
|
||||
}
|
||||
|
||||
template<class AnyCharsAccess>
|
||||
MOZ_COLD void
|
||||
TokenStreamChars<Utf8Unit, AnyCharsAccess>::badTrailingUnit(Utf8Unit badUnit,
|
||||
uint8_t unitsObserved)
|
||||
TokenStreamChars<Utf8Unit, AnyCharsAccess>::badTrailingUnit(uint8_t unitsObserved)
|
||||
{
|
||||
Utf8Unit badUnit = this->sourceUnits.addressOfNextCodeUnit()[unitsObserved - 1];
|
||||
|
||||
char badByteStr[5];
|
||||
byteToTerminatedString(badUnit.toUint8(), badByteStr);
|
||||
|
||||
|
@ -829,12 +832,13 @@ TokenStreamChars<Utf8Unit, AnyCharsAccess>::badStructurallyValidCodePoint(uint32
|
|||
char* codePointStr = codePointCharsArray + ArrayLength(codePointCharsArray);
|
||||
*--codePointStr = '\0';
|
||||
|
||||
uint32_t copy = codePoint;
|
||||
while (copy) {
|
||||
// Note that by do-while looping here rather than while-looping, this
|
||||
// writes a '0' when |codePoint == 0|.
|
||||
do {
|
||||
MOZ_ASSERT(codePointCharsArray < codePointStr);
|
||||
*--codePointStr = toHexChar(copy & 0xF);
|
||||
copy >>= 4;
|
||||
}
|
||||
*--codePointStr = toHexChar(codePoint & 0xF);
|
||||
codePoint >>= 4;
|
||||
} while (codePoint);
|
||||
|
||||
MOZ_ASSERT(codePointCharsArray + 2 <= codePointStr);
|
||||
*--codePointStr = 'x';
|
||||
|
@ -856,8 +860,8 @@ TokenStreamChars<Utf8Unit, AnyCharsAccess>::getNonAsciiCodePointDontNormalize(Ut
|
|||
this->notEnoughUnits(lead, remaining, required);
|
||||
};
|
||||
|
||||
auto onBadTrailingUnit = [this, &lead](uint8_t unitsObserved) {
|
||||
this->badTrailingUnit(lead, unitsObserved);
|
||||
auto onBadTrailingUnit = [this](uint8_t unitsObserved) {
|
||||
this->badTrailingUnit(unitsObserved);
|
||||
};
|
||||
|
||||
auto onBadCodePoint = [this](char32_t badCodePoint, uint8_t unitsObserved) {
|
||||
|
@ -977,8 +981,8 @@ TokenStreamChars<Utf8Unit, AnyCharsAccess>::getNonAsciiCodePoint(int32_t unit, i
|
|||
this->notEnoughUnits(lead, remaining, required);
|
||||
};
|
||||
|
||||
auto onBadTrailingUnit = [this, &lead](uint_fast8_t unitsObserved) {
|
||||
this->badTrailingUnit(lead, unitsObserved);
|
||||
auto onBadTrailingUnit = [this](uint_fast8_t unitsObserved) {
|
||||
this->badTrailingUnit(unitsObserved);
|
||||
};
|
||||
|
||||
auto onBadCodePoint = [this](char32_t badCodePoint, uint_fast8_t unitsObserved) {
|
||||
|
|
|
@ -2194,7 +2194,7 @@ class TokenStreamChars<mozilla::Utf8Unit, AnyCharsAccess>
|
|||
* trailing unit was the last of |unitsObserved| units examined from the
|
||||
* current offset.
|
||||
*/
|
||||
MOZ_COLD void badTrailingUnit(mozilla::Utf8Unit badUnit, uint8_t unitsObserved);
|
||||
MOZ_COLD void badTrailingUnit(uint8_t unitsObserved);
|
||||
|
||||
// Helper used for both |badCodePoint| and |notShortestForm| for code units
|
||||
// that have all the requisite high bits set/unset in a manner that *could*
|
||||
|
|
|
@ -370,6 +370,7 @@ function checkMiscPrefixed(opcode, expect_failure) {
|
|||
|
||||
checkMiscPrefixed([0x0a, 0x00], false); // memory.copy, flags=0
|
||||
checkMiscPrefixed([0x0b, 0x00], false); // memory.fill, flags=0
|
||||
checkMiscPrefixed([0x0b, 0x80, 0x00], false); // memory.fill, flags=0 (long encoding)
|
||||
checkMiscPrefixed([0x0f], true); // table.copy+1, which is currently unassigned
|
||||
|
||||
//-----------------------------------------------------------
|
||||
|
|
|
@ -361,7 +361,7 @@ MSG_DEF(JSMSG_FIELDS_NOT_SUPPORTED, 0, JSEXN_SYNTAXERR, "fields are not curre
|
|||
|
||||
// UTF-8 source text encoding errors
|
||||
MSG_DEF(JSMSG_BAD_LEADING_UTF8_UNIT, 1, JSEXN_SYNTAXERR, "{0} byte doesn't begin a valid UTF-8 code point")
|
||||
MSG_DEF(JSMSG_NOT_ENOUGH_CODE_UNITS, 4, JSEXN_SYNTAXERR, "{0} byte in UTF-8 must be followed by {1} bytes, but {2} byte{3} present")
|
||||
MSG_DEF(JSMSG_NOT_ENOUGH_CODE_UNITS, 5, JSEXN_SYNTAXERR, "{0} byte in UTF-8 must be followed by {1} byte{2}, but {3} byte{4} present")
|
||||
MSG_DEF(JSMSG_BAD_TRAILING_UTF8_UNIT, 1, JSEXN_SYNTAXERR, "bad trailing UTF-8 byte {0} doesn't match the pattern 0b10xxxxxx")
|
||||
MSG_DEF(JSMSG_FORBIDDEN_UTF8_CODE_POINT,2,JSEXN_SYNTAXERR, "{0} isn't a valid code point because {1}")
|
||||
MSG_DEF(JSMSG_BAD_CODE_UNITS, 1, JSEXN_NOTE, "the code units comprising this invalid code point were: {0}")
|
||||
|
|
|
@ -886,7 +886,7 @@ js::CreateWasmBuffer(JSContext* cx, const wasm::Limits& memory,
|
|||
MutableHandleArrayBufferObjectMaybeShared buffer)
|
||||
{
|
||||
MOZ_ASSERT(memory.initial % wasm::PageSize == 0);
|
||||
MOZ_RELEASE_ASSERT(wasm::HaveSignalHandlers());
|
||||
MOZ_RELEASE_ASSERT(cx->wasmHaveSignalHandlers);
|
||||
MOZ_RELEASE_ASSERT((memory.initial / wasm::PageSize) <= wasm::MaxMemoryInitialPages);
|
||||
|
||||
// Prevent applications specifying a large max (like UINT32_MAX) from
|
||||
|
@ -932,7 +932,8 @@ js::CreateWasmBuffer(JSContext* cx, const wasm::Limits& memory,
|
|||
ArrayBufferObject::prepareForAsmJS(JSContext* cx, Handle<ArrayBufferObject*> buffer)
|
||||
{
|
||||
MOZ_ASSERT(buffer->byteLength() % wasm::PageSize == 0);
|
||||
MOZ_RELEASE_ASSERT(wasm::HaveSignalHandlers());
|
||||
// Don't assert cx->wasmHaveSignalHandlers because (1) they aren't needed
|
||||
// for asm.js, (2) they are only installed for WebAssembly, not asm.js.
|
||||
|
||||
if (buffer->forInlineTypedObject()) {
|
||||
return false;
|
||||
|
|
|
@ -124,9 +124,6 @@ JSContext::init(ContextKind kind)
|
|||
}
|
||||
#endif
|
||||
|
||||
if (!wasm::EnsureSignalHandlers(this)) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
atomsZoneFreeLists_ = js_new<gc::FreeLists>();
|
||||
if (!atomsZoneFreeLists_) {
|
||||
|
@ -1343,6 +1340,8 @@ JSContext::JSContext(JSRuntime* runtime, const JS::ContextOptions& options)
|
|||
generationalDisabled(0),
|
||||
compactingDisabledCount(0),
|
||||
suppressProfilerSampling(false),
|
||||
wasmTriedToInstallSignalHandlers(false),
|
||||
wasmHaveSignalHandlers(false),
|
||||
tempLifoAlloc_((size_t)TEMP_LIFO_ALLOC_PRIMARY_CHUNK_SIZE),
|
||||
debuggerMutations(0),
|
||||
ionPcScriptCache(nullptr),
|
||||
|
|
|
@ -623,9 +623,10 @@ struct JSContext : public JS::RootingContext,
|
|||
suppressProfilerSampling = false;
|
||||
}
|
||||
|
||||
#if defined(XP_DARWIN)
|
||||
js::wasm::MachExceptionHandler wasmMachExceptionHandler;
|
||||
#endif
|
||||
// Used by wasm::EnsureThreadSignalHandlers(cx) to install thread signal
|
||||
// handlers once per JSContext/thread.
|
||||
bool wasmTriedToInstallSignalHandlers;
|
||||
bool wasmHaveSignalHandlers;
|
||||
|
||||
/* Temporary arena pool used while compiling and decompiling. */
|
||||
static const size_t TEMP_LIFO_ALLOC_PRIMARY_CHUNK_SIZE = 4 * 1024;
|
||||
|
|
|
@ -55,6 +55,7 @@
|
|||
_(WasmStreamEnd, 500) \
|
||||
_(WasmStreamStatus, 500) \
|
||||
_(WasmRuntimeInstances, 500) \
|
||||
_(WasmSignalInstallState, 500) \
|
||||
\
|
||||
_(IcuTimeZoneStateMutex, 600) \
|
||||
_(ThreadId, 600) \
|
||||
|
|
|
@ -48,6 +48,7 @@
|
|||
#include "vm/JSScript.h"
|
||||
#include "vm/TraceLogging.h"
|
||||
#include "vm/TraceLoggingGraph.h"
|
||||
#include "wasm/WasmSignalHandlers.h"
|
||||
|
||||
#include "gc/GC-inl.h"
|
||||
#include "vm/JSContext-inl.h"
|
||||
|
@ -181,6 +182,9 @@ JSRuntime::JSRuntime(JSRuntime* parentRuntime)
|
|||
{
|
||||
JS_COUNT_CTOR(JSRuntime);
|
||||
liveRuntimesCount++;
|
||||
|
||||
// See function comment for why we call this now, not in JS_Init().
|
||||
wasm::EnsureEagerProcessSignalHandlers();
|
||||
}
|
||||
|
||||
JSRuntime::~JSRuntime()
|
||||
|
|
|
@ -29,8 +29,6 @@
|
|||
#include "vm/JSScript.h"
|
||||
#include "vm/SavedFrame.h"
|
||||
#include "wasm/WasmFrameIter.h"
|
||||
#include "wasm/WasmSignalHandlers.h"
|
||||
#include "wasm/WasmTypes.h"
|
||||
|
||||
namespace JS {
|
||||
namespace dbg {
|
||||
|
|
|
@ -11091,10 +11091,6 @@ BaseCompiler::finish()
|
|||
bool
|
||||
js::wasm::BaselineCanCompile()
|
||||
{
|
||||
// On all platforms we require signals for Wasm.
|
||||
// If we made it this far we must have signals.
|
||||
MOZ_RELEASE_ASSERT(wasm::HaveSignalHandlers());
|
||||
|
||||
#if defined(JS_CODEGEN_ARM)
|
||||
// Simplifying assumption: require SDIV and UDIV.
|
||||
//
|
||||
|
|
|
@ -532,8 +532,6 @@ SharedModule
|
|||
wasm::CompileBuffer(const CompileArgs& args, const ShareableBytes& bytecode, UniqueChars* error,
|
||||
UniqueCharsVector* warnings, UniqueLinkData* maybeLinkData)
|
||||
{
|
||||
MOZ_RELEASE_ASSERT(wasm::HaveSignalHandlers());
|
||||
|
||||
Decoder d(bytecode.bytes, 0, error, warnings);
|
||||
|
||||
CompilerEnvironment compilerEnv(args);
|
||||
|
@ -576,8 +574,6 @@ void
|
|||
wasm::CompileTier2(const CompileArgs& args, const Bytes& bytecode, const Module& module,
|
||||
Atomic<bool>* cancelled)
|
||||
{
|
||||
MOZ_RELEASE_ASSERT(wasm::HaveSignalHandlers());
|
||||
|
||||
UniqueChars error;
|
||||
Decoder d(bytecode, 0, &error);
|
||||
|
||||
|
@ -714,8 +710,6 @@ wasm::CompileStreaming(const CompileArgs& args,
|
|||
UniqueChars* error,
|
||||
UniqueCharsVector* warnings)
|
||||
{
|
||||
MOZ_ASSERT(wasm::HaveSignalHandlers());
|
||||
|
||||
CompilerEnvironment compilerEnv(args);
|
||||
Maybe<ModuleEnvironment> env;
|
||||
|
||||
|
|
|
@ -71,7 +71,7 @@ wasm::HasCompilerSupport(JSContext* cx)
|
|||
return false;
|
||||
}
|
||||
|
||||
if (!wasm::HaveSignalHandlers()) {
|
||||
if (!wasm::EnsureFullSignalHandlers(cx)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -1253,6 +1253,8 @@ Module::instantiate(JSContext* cx,
|
|||
HandleObject instanceProto,
|
||||
MutableHandleWasmInstanceObject instance) const
|
||||
{
|
||||
MOZ_RELEASE_ASSERT(metadata().isAsmJS() || cx->wasmHaveSignalHandlers);
|
||||
|
||||
if (!instantiateFunctions(cx, funcImports)) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -2055,8 +2055,8 @@ OpIter<Policy>::readMemOrTableCopy(bool isMem, Value* dst, Value* src, Value* le
|
|||
}
|
||||
}
|
||||
|
||||
uint8_t memOrTableFlags;
|
||||
if (!readFixedU8(&memOrTableFlags)) {
|
||||
uint32_t memOrTableFlags;
|
||||
if (!readVarU32(&memOrTableFlags)) {
|
||||
return fail(isMem ? "unable to read memory flags" : "unable to read table flags");
|
||||
}
|
||||
if (memOrTableFlags != 0) {
|
||||
|
@ -2122,8 +2122,8 @@ OpIter<Policy>::readMemFill(Value* start, Value* val, Value* len)
|
|||
return fail("can't touch memory without memory");
|
||||
}
|
||||
|
||||
uint8_t memoryFlags;
|
||||
if (!readFixedU8(&memoryFlags)) {
|
||||
uint32_t memoryFlags;
|
||||
if (!readVarU32(&memoryFlags)) {
|
||||
return fail("unable to read memory flags");
|
||||
}
|
||||
if (memoryFlags != 0) {
|
||||
|
@ -2174,8 +2174,8 @@ OpIter<Policy>::readMemOrTableInit(bool isMem, uint32_t* segIndex,
|
|||
return false;
|
||||
}
|
||||
|
||||
uint8_t memOrTableFlags;
|
||||
if (!readFixedU8(&memOrTableFlags)) {
|
||||
uint32_t memOrTableFlags;
|
||||
if (!readVarU32(&memOrTableFlags)) {
|
||||
return fail(isMem ? "unable to read memory flags" : "unable to read table flags");
|
||||
}
|
||||
if (memOrTableFlags != 0) {
|
||||
|
|
|
@ -22,9 +22,19 @@
|
|||
#include "mozilla/ScopeExit.h"
|
||||
#include "mozilla/ThreadLocal.h"
|
||||
|
||||
#include "threading/Thread.h"
|
||||
#include "vm/Runtime.h"
|
||||
#include "wasm/WasmInstance.h"
|
||||
|
||||
#if defined(XP_WIN)
|
||||
# include "util/Windows.h"
|
||||
#elif defined(XP_DARWIN)
|
||||
# include <mach/exc.h>
|
||||
# include <mach/mach.h>
|
||||
#else
|
||||
# include <signal.h>
|
||||
#endif
|
||||
|
||||
using namespace js;
|
||||
using namespace js::wasm;
|
||||
|
||||
|
@ -36,13 +46,6 @@ using mozilla::DebugOnly;
|
|||
// CONTEXT struct which is provided to the signal handler.
|
||||
// =============================================================================
|
||||
|
||||
#if defined(XP_WIN)
|
||||
# include "util/Windows.h"
|
||||
#else
|
||||
# include <signal.h>
|
||||
# include <sys/mman.h>
|
||||
#endif
|
||||
|
||||
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
|
||||
# include <sys/ucontext.h> // for ucontext_t, mcontext_t
|
||||
#endif
|
||||
|
@ -343,11 +346,21 @@ struct macos_arm_context {
|
|||
# define FP_sig(p) R01_sig(p)
|
||||
#endif
|
||||
|
||||
static uint8_t**
|
||||
static void
|
||||
SetContextPC(CONTEXT* context, uint8_t* pc)
|
||||
{
|
||||
#ifdef PC_sig
|
||||
*reinterpret_cast<uint8_t**>(&PC_sig(context)) = pc;
|
||||
#else
|
||||
MOZ_CRASH();
|
||||
#endif
|
||||
}
|
||||
|
||||
static uint8_t*
|
||||
ContextToPC(CONTEXT* context)
|
||||
{
|
||||
#ifdef PC_sig
|
||||
return reinterpret_cast<uint8_t**>(&PC_sig(context));
|
||||
return reinterpret_cast<uint8_t*>(PC_sig(context));
|
||||
#else
|
||||
MOZ_CRASH();
|
||||
#endif
|
||||
|
@ -390,7 +403,7 @@ ToRegisterState(CONTEXT* context)
|
|||
{
|
||||
JS::ProfilingFrameIterator::RegisterState state;
|
||||
state.fp = ContextToFP(context);
|
||||
state.pc = *ContextToPC(context);
|
||||
state.pc = ContextToPC(context);
|
||||
state.sp = ContextToSP(context);
|
||||
#if defined(__arm__) || defined(__aarch64__) || defined(__mips__)
|
||||
state.lr = ContextToLR(context);
|
||||
|
@ -434,11 +447,11 @@ struct AutoHandlingTrap
|
|||
};
|
||||
|
||||
static MOZ_MUST_USE bool
|
||||
HandleTrap(CONTEXT* context, JSContext* cx)
|
||||
HandleTrap(CONTEXT* context, JSContext* assertCx = nullptr)
|
||||
{
|
||||
MOZ_ASSERT(sAlreadyHandlingTrap.get());
|
||||
|
||||
uint8_t* pc = *ContextToPC(context);
|
||||
uint8_t* pc = ContextToPC(context);
|
||||
const CodeSegment* codeSegment = LookupCodeSegment(pc);
|
||||
if (!codeSegment || !codeSegment->isModule()) {
|
||||
return false;
|
||||
|
@ -452,19 +465,28 @@ HandleTrap(CONTEXT* context, JSContext* cx)
|
|||
return false;
|
||||
}
|
||||
|
||||
// We have a safe, expected wasm trap. Call startWasmTrap() to store enough
|
||||
// register state at the point of the trap to allow stack unwinding or
|
||||
// resumption, both of which will call finishWasmTrap().
|
||||
// We have a safe, expected wasm trap, so fp is well-defined to be a Frame*.
|
||||
// For the first sanity check, the Trap::IndirectCallBadSig special case is
|
||||
// due to this trap occurring in the indirect call prologue, while fp points
|
||||
// to the caller's Frame which can be in a different Module. In any case,
|
||||
// though, the containing JSContext is the same.
|
||||
Instance* instance = ((Frame*)ContextToFP(context))->tls->instance;
|
||||
MOZ_RELEASE_ASSERT(&instance->code() == &segment.code() || trap == Trap::IndirectCallBadSig);
|
||||
JSContext* cx = instance->realm()->runtimeFromAnyThread()->mainContextFromAnyThread();
|
||||
MOZ_RELEASE_ASSERT(!assertCx || cx == assertCx);
|
||||
|
||||
// JitActivation::startWasmTrap() stores enough register state from the
|
||||
// point of the trap to allow stack unwinding or resumption, both of which
|
||||
// will call finishWasmTrap().
|
||||
jit::JitActivation* activation = cx->activation()->asJit();
|
||||
activation->startWasmTrap(trap, bytecode.offset(), ToRegisterState(context));
|
||||
*ContextToPC(context) = segment.trapCode();
|
||||
SetContextPC(context, segment.trapCode());
|
||||
return true;
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// The following platform specific signal/exception handlers are installed by
|
||||
// wasm::EnsureSignalHandlers() and funnel all potential wasm traps into
|
||||
// HandleTrap() above.
|
||||
// The following platform-specific handlers funnel all signals/exceptions into
|
||||
// the shared HandleTrap() above.
|
||||
// =============================================================================
|
||||
|
||||
#if defined(XP_WIN)
|
||||
|
@ -492,7 +514,9 @@ WasmTrapHandler(LPEXCEPTION_POINTERS exception)
|
|||
}
|
||||
|
||||
#elif defined(XP_DARWIN)
|
||||
# include <mach/exc.h>
|
||||
// On OSX we are forced to use the lower-level Mach exception mechanism instead
|
||||
// of Unix signals because breakpad uses Mach exceptions and would otherwise
|
||||
// report a crash before wasm gets a chance to handle the exception.
|
||||
|
||||
// This definition was generated by mig (the Mach Interface Generator) for the
|
||||
// routine 'exception_raise' (exc.defs).
|
||||
|
@ -519,7 +543,7 @@ struct ExceptionRequest
|
|||
};
|
||||
|
||||
static bool
|
||||
HandleMachException(JSContext* cx, const ExceptionRequest& request)
|
||||
HandleMachException(const ExceptionRequest& request)
|
||||
{
|
||||
// Get the port of the JSContext's thread from the message.
|
||||
mach_port_t cxThread = request.body.thread.name;
|
||||
|
@ -565,7 +589,7 @@ HandleMachException(JSContext* cx, const ExceptionRequest& request)
|
|||
{
|
||||
AutoNoteSingleThreadedRegion anstr;
|
||||
AutoHandlingTrap aht;
|
||||
if (!HandleTrap(&context, cx)) {
|
||||
if (!HandleTrap(&context)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -583,22 +607,18 @@ HandleMachException(JSContext* cx, const ExceptionRequest& request)
|
|||
return true;
|
||||
}
|
||||
|
||||
// Taken from mach_exc in /usr/include/mach/mach_exc.defs.
|
||||
static const mach_msg_id_t sExceptionId = 2405;
|
||||
|
||||
// The choice of id here is arbitrary, the only constraint is that sQuitId != sExceptionId.
|
||||
static const mach_msg_id_t sQuitId = 42;
|
||||
static mach_port_t sMachDebugPort = MACH_PORT_NULL;
|
||||
|
||||
static void
|
||||
MachExceptionHandlerThread(JSContext* cx)
|
||||
MachExceptionHandlerThread()
|
||||
{
|
||||
mach_port_t port = cx->wasmMachExceptionHandler.port();
|
||||
kern_return_t kret;
|
||||
// Taken from mach_exc in /usr/include/mach/mach_exc.defs.
|
||||
static const unsigned EXCEPTION_MSG_ID = 2405;
|
||||
|
||||
while(true) {
|
||||
while (true) {
|
||||
ExceptionRequest request;
|
||||
kret = mach_msg(&request.body.Head, MACH_RCV_MSG, 0, sizeof(request),
|
||||
port, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
|
||||
kern_return_t kret = mach_msg(&request.body.Head, MACH_RCV_MSG, 0, sizeof(request),
|
||||
sMachDebugPort, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
|
||||
|
||||
// If we fail even receiving the message, we can't even send a reply!
|
||||
// Rather than hanging the faulting thread (hanging the browser), crash.
|
||||
|
@ -607,13 +627,7 @@ MachExceptionHandlerThread(JSContext* cx)
|
|||
MOZ_CRASH();
|
||||
}
|
||||
|
||||
// There are only two messages we should be receiving: an exception
|
||||
// message that occurs when the runtime's thread faults and the quit
|
||||
// message sent when the runtime is shutting down.
|
||||
if (request.body.Head.msgh_id == sQuitId) {
|
||||
break;
|
||||
}
|
||||
if (request.body.Head.msgh_id != sExceptionId) {
|
||||
if (request.body.Head.msgh_id != EXCEPTION_MSG_ID) {
|
||||
fprintf(stderr, "Unexpected msg header id %d\n", (int)request.body.Head.msgh_bits);
|
||||
MOZ_CRASH();
|
||||
}
|
||||
|
@ -624,7 +638,7 @@ MachExceptionHandlerThread(JSContext* cx)
|
|||
// of the reply to KERN_FAILURE) which tells the kernel to continue
|
||||
// searching at the process and system level. If this is an asm.js
|
||||
// expected exception, we handle it and return KERN_SUCCESS.
|
||||
bool handled = HandleMachException(cx, request);
|
||||
bool handled = HandleMachException(request);
|
||||
kern_return_t replyCode = handled ? KERN_SUCCESS : KERN_FAILURE;
|
||||
|
||||
// This magic incantation to send a reply back to the kernel was derived
|
||||
|
@ -642,101 +656,6 @@ MachExceptionHandlerThread(JSContext* cx)
|
|||
}
|
||||
}
|
||||
|
||||
MachExceptionHandler::MachExceptionHandler()
|
||||
: installed_(false),
|
||||
thread_(),
|
||||
port_(MACH_PORT_NULL)
|
||||
{}
|
||||
|
||||
void
|
||||
MachExceptionHandler::uninstall()
|
||||
{
|
||||
if (installed_) {
|
||||
thread_port_t thread = mach_thread_self();
|
||||
kern_return_t kret = thread_set_exception_ports(thread,
|
||||
EXC_MASK_BAD_ACCESS | EXC_MASK_BAD_INSTRUCTION,
|
||||
MACH_PORT_NULL,
|
||||
EXCEPTION_DEFAULT | MACH_EXCEPTION_CODES,
|
||||
THREAD_STATE_NONE);
|
||||
mach_port_deallocate(mach_task_self(), thread);
|
||||
if (kret != KERN_SUCCESS) {
|
||||
MOZ_CRASH();
|
||||
}
|
||||
installed_ = false;
|
||||
}
|
||||
if (thread_.joinable()) {
|
||||
// Break the handler thread out of the mach_msg loop.
|
||||
mach_msg_header_t msg;
|
||||
msg.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, 0);
|
||||
msg.msgh_size = sizeof(msg);
|
||||
msg.msgh_remote_port = port_;
|
||||
msg.msgh_local_port = MACH_PORT_NULL;
|
||||
msg.msgh_reserved = 0;
|
||||
msg.msgh_id = sQuitId;
|
||||
kern_return_t kret = mach_msg(&msg, MACH_SEND_MSG, sizeof(msg), 0, MACH_PORT_NULL,
|
||||
MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
|
||||
if (kret != KERN_SUCCESS) {
|
||||
fprintf(stderr, "MachExceptionHandler: failed to send quit message: %d\n", (int)kret);
|
||||
MOZ_CRASH();
|
||||
}
|
||||
|
||||
// Wait for the handler thread to complete before deallocating the port.
|
||||
thread_.join();
|
||||
}
|
||||
if (port_ != MACH_PORT_NULL) {
|
||||
DebugOnly<kern_return_t> kret = mach_port_destroy(mach_task_self(), port_);
|
||||
MOZ_ASSERT(kret == KERN_SUCCESS);
|
||||
port_ = MACH_PORT_NULL;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
MachExceptionHandler::install(JSContext* cx)
|
||||
{
|
||||
MOZ_ASSERT(!installed());
|
||||
kern_return_t kret;
|
||||
mach_port_t thread;
|
||||
|
||||
auto onFailure = mozilla::MakeScopeExit([&] {
|
||||
uninstall();
|
||||
});
|
||||
|
||||
// Get a port which can send and receive data.
|
||||
kret = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &port_);
|
||||
if (kret != KERN_SUCCESS) {
|
||||
return false;
|
||||
}
|
||||
kret = mach_port_insert_right(mach_task_self(), port_, port_, MACH_MSG_TYPE_MAKE_SEND);
|
||||
if (kret != KERN_SUCCESS) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Create a thread to block on reading port_.
|
||||
if (!thread_.init(MachExceptionHandlerThread, cx)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Direct exceptions on this thread to port_ (and thus our handler thread).
|
||||
// Note: we are totally clobbering any existing *thread* exception ports and
|
||||
// not even attempting to forward. Breakpad and gdb both use the *process*
|
||||
// exception ports which are only called if the thread doesn't handle the
|
||||
// exception, so we should be fine.
|
||||
thread = mach_thread_self();
|
||||
kret = thread_set_exception_ports(thread,
|
||||
EXC_MASK_BAD_ACCESS | EXC_MASK_BAD_INSTRUCTION,
|
||||
port_,
|
||||
EXCEPTION_DEFAULT | MACH_EXCEPTION_CODES,
|
||||
THREAD_STATE_NONE);
|
||||
mach_port_deallocate(mach_task_self(), thread);
|
||||
if (kret != KERN_SUCCESS) {
|
||||
return false;
|
||||
}
|
||||
|
||||
installed_ = true;
|
||||
onFailure.release();
|
||||
return true;
|
||||
}
|
||||
|
||||
#else // If not Windows or Mac, assume Unix
|
||||
|
||||
#ifdef __mips__
|
||||
|
@ -794,40 +713,46 @@ WasmTrapHandler(int signum, siginfo_t* info, void* context)
|
|||
extern "C" MFBT_API bool IsSignalHandlingBroken();
|
||||
#endif
|
||||
|
||||
static bool sTriedInstallSignalHandlers = false;
|
||||
static bool sHaveSignalHandlers = false;
|
||||
|
||||
static bool
|
||||
ProcessHasSignalHandlers()
|
||||
struct InstallState
|
||||
{
|
||||
// We assume that there are no races creating the first JSRuntime of the process.
|
||||
if (sTriedInstallSignalHandlers) {
|
||||
return sHaveSignalHandlers;
|
||||
bool tried;
|
||||
bool success;
|
||||
InstallState() : tried(false), success(false) {}
|
||||
};
|
||||
|
||||
static ExclusiveData<InstallState> sEagerInstallState(mutexid::WasmSignalInstallState);
|
||||
|
||||
void
|
||||
wasm::EnsureEagerProcessSignalHandlers()
|
||||
{
|
||||
auto eagerInstallState = sEagerInstallState.lock();
|
||||
if (eagerInstallState->tried) {
|
||||
return;
|
||||
}
|
||||
sTriedInstallSignalHandlers = true;
|
||||
|
||||
eagerInstallState->tried = true;
|
||||
MOZ_RELEASE_ASSERT(eagerInstallState->success == false);
|
||||
|
||||
#if defined (JS_CODEGEN_NONE)
|
||||
// If there is no JIT, then there should be no Wasm signal handlers.
|
||||
return false;
|
||||
return;
|
||||
#endif
|
||||
|
||||
// Signal handlers are currently disabled when recording or replaying.
|
||||
if (mozilla::recordreplay::IsRecordingOrReplaying()) {
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
|
||||
#if defined(ANDROID) && defined(MOZ_LINKER)
|
||||
// Signal handling is broken on some android systems.
|
||||
if (IsSignalHandlingBroken()) {
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Initalize ThreadLocal flag used by WasmTrapHandler
|
||||
sAlreadyHandlingTrap.infallibleInit();
|
||||
|
||||
// Install a SIGSEGV handler to handle safely-out-of-bounds asm.js heap
|
||||
// access and/or unaligned accesses.
|
||||
// Install whatever exception/signal handler is appropriate for the OS.
|
||||
#if defined(XP_WIN)
|
||||
|
||||
# if defined(MOZ_ASAN)
|
||||
|
@ -842,11 +767,13 @@ ProcessHasSignalHandlers()
|
|||
const bool firstHandler = true;
|
||||
# endif
|
||||
if (!AddVectoredExceptionHandler(firstHandler, WasmTrapHandler)) {
|
||||
return false;
|
||||
// Windows has all sorts of random security knobs for disabling things
|
||||
// so make this a dynamic failure that disables wasm, not a MOZ_CRASH().
|
||||
return;
|
||||
}
|
||||
|
||||
#elif defined(XP_DARWIN)
|
||||
// OSX handles seg faults via the Mach exception handler above, so don't
|
||||
// install WasmTrapHandler.
|
||||
// All the Mach setup in EnsureLazyProcessSignalHandlers.
|
||||
#else
|
||||
// SA_NODEFER allows us to reenter the signal handler if we crash while
|
||||
// handling the signal, and fall through to the Breakpad handler by testing
|
||||
|
@ -883,35 +810,96 @@ ProcessHasSignalHandlers()
|
|||
}
|
||||
#endif
|
||||
|
||||
sHaveSignalHandlers = true;
|
||||
eagerInstallState->success = true;
|
||||
}
|
||||
|
||||
static ExclusiveData<InstallState> sLazyInstallState(mutexid::WasmSignalInstallState);
|
||||
|
||||
static bool
|
||||
EnsureLazyProcessSignalHandlers()
|
||||
{
|
||||
auto lazyInstallState = sLazyInstallState.lock();
|
||||
if (lazyInstallState->tried) {
|
||||
return lazyInstallState->success;
|
||||
}
|
||||
|
||||
lazyInstallState->tried = true;
|
||||
MOZ_RELEASE_ASSERT(lazyInstallState->success == false);
|
||||
|
||||
#ifdef XP_DARWIN
|
||||
// Create the port that all JSContext threads will redirect their traps to.
|
||||
kern_return_t kret;
|
||||
kret = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &sMachDebugPort);
|
||||
if (kret != KERN_SUCCESS) {
|
||||
return false;
|
||||
}
|
||||
kret = mach_port_insert_right(mach_task_self(), sMachDebugPort, sMachDebugPort,
|
||||
MACH_MSG_TYPE_MAKE_SEND);
|
||||
if (kret != KERN_SUCCESS) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Create the thread that will wait on and service sMachDebugPort.
|
||||
// It's not useful to destroy this thread on process shutdown so
|
||||
// immediately detach on successful start.
|
||||
Thread handlerThread;
|
||||
if (!handlerThread.init(MachExceptionHandlerThread)) {
|
||||
return false;
|
||||
}
|
||||
handlerThread.detach();
|
||||
#endif
|
||||
|
||||
lazyInstallState->success = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
wasm::EnsureSignalHandlers(JSContext* cx)
|
||||
wasm::EnsureFullSignalHandlers(JSContext* cx)
|
||||
{
|
||||
// Nothing to do if the platform doesn't support it.
|
||||
if (!ProcessHasSignalHandlers()) {
|
||||
return true;
|
||||
if (cx->wasmTriedToInstallSignalHandlers) {
|
||||
return cx->wasmHaveSignalHandlers;
|
||||
}
|
||||
|
||||
#if defined(XP_DARWIN)
|
||||
// On OSX, each JSContext which runs wasm gets its own handler thread.
|
||||
if (!cx->wasmMachExceptionHandler.installed() && !cx->wasmMachExceptionHandler.install(cx)) {
|
||||
cx->wasmTriedToInstallSignalHandlers = true;
|
||||
MOZ_RELEASE_ASSERT(!cx->wasmHaveSignalHandlers);
|
||||
|
||||
{
|
||||
auto eagerInstallState = sEagerInstallState.lock();
|
||||
MOZ_RELEASE_ASSERT(eagerInstallState->tried);
|
||||
if (!eagerInstallState->success) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!EnsureLazyProcessSignalHandlers()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef XP_DARWIN
|
||||
// In addition to the process-wide signal handler setup, OSX needs each
|
||||
// thread configured to send its exceptions to sMachDebugPort. While there
|
||||
// are also task-level (i.e. process-level) exception ports, those are
|
||||
// "claimed" by breakpad and chaining Mach exceptions is dark magic that we
|
||||
// avoid by instead intercepting exceptions at the thread level before they
|
||||
// propagate to the process-level. This works because there are no other
|
||||
// uses of thread-level exception ports.
|
||||
MOZ_RELEASE_ASSERT(sMachDebugPort != MACH_PORT_NULL);
|
||||
thread_port_t thisThread = mach_thread_self();
|
||||
kern_return_t kret = thread_set_exception_ports(thisThread,
|
||||
EXC_MASK_BAD_ACCESS | EXC_MASK_BAD_INSTRUCTION,
|
||||
sMachDebugPort,
|
||||
EXCEPTION_DEFAULT | MACH_EXCEPTION_CODES,
|
||||
THREAD_STATE_NONE);
|
||||
mach_port_deallocate(mach_task_self(), thisThread);
|
||||
if (kret != KERN_SUCCESS) {
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
cx->wasmHaveSignalHandlers = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
wasm::HaveSignalHandlers()
|
||||
{
|
||||
MOZ_ASSERT(sTriedInstallSignalHandlers);
|
||||
return sHaveSignalHandlers;
|
||||
}
|
||||
|
||||
bool
|
||||
wasm::MemoryAccessTraps(const RegisterState& regs, uint8_t* addr, uint32_t numBytes, uint8_t** newPC)
|
||||
{
|
||||
|
|
|
@ -21,12 +21,7 @@
|
|||
|
||||
#include "mozilla/Attributes.h"
|
||||
|
||||
#if defined(XP_DARWIN)
|
||||
# include <mach/mach.h>
|
||||
#endif
|
||||
|
||||
#include "js/ProfilingFrameIterator.h"
|
||||
#include "threading/Thread.h"
|
||||
#include "wasm/WasmProcess.h"
|
||||
|
||||
namespace js {
|
||||
|
@ -34,16 +29,27 @@ namespace wasm {
|
|||
|
||||
typedef JS::ProfilingFrameIterator::RegisterState RegisterState;
|
||||
|
||||
// Ensure the given JSRuntime is set up to use signals. Failure to enable signal
|
||||
// handlers indicates some catastrophic failure and creation of the runtime must
|
||||
// fail.
|
||||
MOZ_MUST_USE bool
|
||||
EnsureSignalHandlers(JSContext* cx);
|
||||
// This function performs the low-overhead signal handler initialization that we
|
||||
// want to do eagerly to ensure a more-deterministic global process state. This
|
||||
// is especially relevant for signal handlers since handler ordering depends on
|
||||
// installation order: the wasm signal handler must run *before* the other crash
|
||||
// handlers (ds/MemoryProtectionExceptionHandler.h and breakpad) and since POSIX
|
||||
// signal handlers work LIFO, this function needs to be called at the end of the
|
||||
// startup process, after the other two handlers have been installed. Currently,
|
||||
// this is achieved by having JSRuntime() call this function. There can be
|
||||
// multiple JSRuntimes per process so this function can thus be called multiple
|
||||
// times, having no effect after the first call.
|
||||
void
|
||||
EnsureEagerProcessSignalHandlers();
|
||||
|
||||
// Return whether signals can be used in this process for asm.js/wasm
|
||||
// out-of-bounds.
|
||||
// Assuming EnsureEagerProcessSignalHandlers() has already been called,
|
||||
// this function performs the full installation of signal handlers which must
|
||||
// be performed per-thread/JSContext. This operation may incur some overhead and
|
||||
// so should be done only when needed to use wasm. Currently, this is done in
|
||||
// wasm::HasCompilerSupport() which is called when deciding whether to expose the
|
||||
// 'WebAssembly' object on the global object.
|
||||
bool
|
||||
HaveSignalHandlers();
|
||||
EnsureFullSignalHandlers(JSContext* cx);
|
||||
|
||||
// Return whether, with the given simulator register state, a memory access to
|
||||
// 'addr' of size 'numBytes' needs to trap and, if so, where the simulator
|
||||
|
@ -56,30 +62,6 @@ MemoryAccessTraps(const RegisterState& regs, uint8_t* addr, uint32_t numBytes, u
|
|||
bool
|
||||
HandleIllegalInstruction(const RegisterState& regs, uint8_t** newPC);
|
||||
|
||||
#if defined(XP_DARWIN)
|
||||
// On OSX we are forced to use the lower-level Mach exception mechanism instead
|
||||
// of Unix signals. Mach exceptions are not handled on the victim's stack but
|
||||
// rather require an extra thread. For simplicity, we create one such thread
|
||||
// per JSContext (upon the first use of wasm in the JSContext). This thread
|
||||
// and related resources are owned by AsmJSMachExceptionHandler which is owned
|
||||
// by JSContext.
|
||||
class MachExceptionHandler
|
||||
{
|
||||
bool installed_;
|
||||
js::Thread thread_;
|
||||
mach_port_t port_;
|
||||
|
||||
void uninstall();
|
||||
|
||||
public:
|
||||
MachExceptionHandler();
|
||||
~MachExceptionHandler() { uninstall(); }
|
||||
mach_port_t port() const { return port_; }
|
||||
bool installed() const { return installed_; }
|
||||
bool install(JSContext* cx);
|
||||
};
|
||||
#endif
|
||||
|
||||
} // namespace wasm
|
||||
} // namespace js
|
||||
|
||||
|
|
|
@ -6290,8 +6290,6 @@ EncodeWake(Encoder& e, AstWake& s)
|
|||
}
|
||||
|
||||
#ifdef ENABLE_WASM_BULKMEM_OPS
|
||||
static const uint8_t DEFAULT_MEM_TABLE_FLAGS = 0;
|
||||
|
||||
static bool
|
||||
EncodeMemOrTableCopy(Encoder& e, AstMemOrTableCopy& s)
|
||||
{
|
||||
|
@ -6299,7 +6297,7 @@ EncodeMemOrTableCopy(Encoder& e, AstMemOrTableCopy& s)
|
|||
EncodeExpr(e, s.src()) &&
|
||||
EncodeExpr(e, s.len()) &&
|
||||
e.writeOp(s.isMem() ? MiscOp::MemCopy : MiscOp::TableCopy) &&
|
||||
e.writeFixedU8(DEFAULT_MEM_TABLE_FLAGS);
|
||||
e.writeVarU32(uint32_t(MemoryTableFlags::Default));
|
||||
}
|
||||
|
||||
static bool
|
||||
|
@ -6316,7 +6314,7 @@ EncodeMemFill(Encoder& e, AstMemFill& s)
|
|||
EncodeExpr(e, s.val()) &&
|
||||
EncodeExpr(e, s.len()) &&
|
||||
e.writeOp(MiscOp::MemFill) &&
|
||||
e.writeFixedU8(DEFAULT_MEM_TABLE_FLAGS);
|
||||
e.writeVarU32(uint32_t(MemoryTableFlags::Default));
|
||||
}
|
||||
|
||||
static bool
|
||||
|
@ -6326,7 +6324,7 @@ EncodeMemOrTableInit(Encoder& e, AstMemOrTableInit& s)
|
|||
EncodeExpr(e, s.src()) &&
|
||||
EncodeExpr(e, s.len()) &&
|
||||
e.writeOp(s.isMem() ? MiscOp::MemInit : MiscOp::TableInit) &&
|
||||
e.writeFixedU8(DEFAULT_MEM_TABLE_FLAGS) &&
|
||||
e.writeVarU32(uint32_t(MemoryTableFlags::Default)) &&
|
||||
e.writeVarU32(s.segIndex());
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -4162,9 +4162,7 @@ nsIFrame::IsSelectable(StyleUserSelect* aSelectStyle) const
|
|||
while (frame) {
|
||||
const nsStyleUIReset* userinterface = frame->StyleUIReset();
|
||||
switch (userinterface->mUserSelect) {
|
||||
case StyleUserSelect::All:
|
||||
case StyleUserSelect::MozAll:
|
||||
{
|
||||
case StyleUserSelect::All: {
|
||||
// override the previous values
|
||||
if (selectStyle != StyleUserSelect::MozText) {
|
||||
selectStyle = userinterface->mUserSelect;
|
||||
|
@ -4188,8 +4186,6 @@ nsIFrame::IsSelectable(StyleUserSelect* aSelectStyle) const
|
|||
if (selectStyle == StyleUserSelect::Auto ||
|
||||
selectStyle == StyleUserSelect::MozText) {
|
||||
selectStyle = StyleUserSelect::Text;
|
||||
} else if (selectStyle == StyleUserSelect::MozAll) {
|
||||
selectStyle = StyleUserSelect::All;
|
||||
}
|
||||
|
||||
// If user tries to select all of a non-editable content,
|
||||
|
@ -4268,8 +4264,6 @@ nsFrame::HandlePress(nsPresContext* aPresContext,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
// When implementing StyleUserSelect::Element, StyleUserSelect::Elements and
|
||||
// StyleUserSelect::Toggle, need to change this logic
|
||||
bool useFrameSelection = (selectStyle == StyleUserSelect::Text);
|
||||
|
||||
// If the mouse is dragged outside the nearest enclosing scrollable area
|
||||
|
|
|
@ -396,6 +396,7 @@ cbindgen-types = [
|
|||
{ gecko = "StylePathCommand", servo = "values::specified::svg_path::PathCommand" },
|
||||
{ gecko = "StyleUnicodeRange", servo = "cssparser::UnicodeRange" },
|
||||
{ gecko = "StyleOverflowWrap", servo = "values::computed::OverflowWrap" },
|
||||
{ gecko = "StyleUserSelect", servo = "values::computed::UserSelect" },
|
||||
]
|
||||
|
||||
mapped-generic-types = [
|
||||
|
|
|
@ -111,6 +111,7 @@ SERIALIZED_PREDEFINED_TYPES = [
|
|||
"Translate",
|
||||
"TimingFunction",
|
||||
"TransformStyle",
|
||||
"UserSelect",
|
||||
"background::BackgroundSize",
|
||||
"basic_shape::ClippingShape",
|
||||
"basic_shape::FloatAreaShape",
|
||||
|
|
|
@ -223,20 +223,6 @@ enum class StyleUserFocus : uint8_t {
|
|||
SelectMenu,
|
||||
};
|
||||
|
||||
// user-select
|
||||
enum class StyleUserSelect : uint8_t {
|
||||
None,
|
||||
Text,
|
||||
Element,
|
||||
Elements,
|
||||
All,
|
||||
Toggle,
|
||||
TriState,
|
||||
Auto, // internal value - please use nsFrame::IsSelectable()
|
||||
MozAll, // force selection of all children, unless an ancestor has NONE set - bug 48096
|
||||
MozText, // Like TEXT, except that it won't get overridden by ancestors having ALL.
|
||||
};
|
||||
|
||||
// user-input
|
||||
enum class StyleUserInput : uint8_t {
|
||||
None,
|
||||
|
|
|
@ -2625,7 +2625,7 @@ var gCSSProperties = {
|
|||
inherited: false,
|
||||
type: CSS_TYPE_LONGHAND,
|
||||
initial_values: [ "auto" ],
|
||||
other_values: [ "none", "text", "element", "elements", "all", "toggle", "tri-state", "-moz-all", "-moz-none" ],
|
||||
other_values: [ "none", "text", "all", "-moz-none" ],
|
||||
invalid_values: []
|
||||
},
|
||||
"background": {
|
||||
|
|
|
@ -110,6 +110,9 @@ const NON_CONTENT_ACCESSIBLE_VALUES = {
|
|||
"-moz-mac-vibrant-titlebar-dark",
|
||||
"-moz-mac-vibrant-titlebar-light",
|
||||
],
|
||||
"-moz-user-select": [
|
||||
"-moz-text",
|
||||
],
|
||||
};
|
||||
|
||||
if (!SpecialPowers.getBoolPref("layout.css.xul-box-display-values.content.enabled")) {
|
||||
|
|
|
@ -53,5 +53,6 @@ include = [
|
|||
"TimingFunction",
|
||||
"PathCommand",
|
||||
"UnicodeRange",
|
||||
"UserSelect",
|
||||
]
|
||||
item_types = ["enums", "structs", "typedefs"]
|
||||
|
|
|
@ -336,6 +336,7 @@ class Longhand(object):
|
|||
"TextEmphasisPosition",
|
||||
"TouchAction",
|
||||
"TransformStyle",
|
||||
"UserSelect",
|
||||
"XSpan",
|
||||
"XTextZoom",
|
||||
"ZIndex",
|
||||
|
|
|
@ -1429,6 +1429,7 @@ impl Clone for ${style_struct.gecko_struct_name} {
|
|||
"SVGWidth": impl_svg_length,
|
||||
"Transform": impl_transform,
|
||||
"TransformOrigin": impl_transform_origin,
|
||||
"UserSelect": impl_simple,
|
||||
"url::UrlOrNone": impl_css_url,
|
||||
}
|
||||
|
||||
|
|
|
@ -31,15 +31,13 @@ ${helpers.single_keyword(
|
|||
spec="https://drafts.csswg.org/css-scrollbars-1/#scrollbar-width"
|
||||
)}
|
||||
|
||||
${helpers.single_keyword(
|
||||
${helpers.predefined_type(
|
||||
"-moz-user-select",
|
||||
"auto text none all element elements toggle tri-state -moz-all -moz-text",
|
||||
"UserSelect",
|
||||
"computed::UserSelect::Auto",
|
||||
products="gecko",
|
||||
alias="-webkit-user-select",
|
||||
gecko_ffi_name="mUserSelect",
|
||||
gecko_enum_prefix="StyleUserSelect",
|
||||
gecko_strip_moz_prefix=False,
|
||||
aliases="-moz-none=none",
|
||||
alias="-webkit-user-select",
|
||||
animation_value_type="discrete",
|
||||
spec="https://drafts.csswg.org/css-ui-4/#propdef-user-select",
|
||||
)}
|
||||
|
|
|
@ -84,7 +84,7 @@ pub use self::transform::{Rotate, Scale, Transform, TransformOperation};
|
|||
pub use self::transform::{TransformOrigin, TransformStyle, Translate};
|
||||
#[cfg(feature = "gecko")]
|
||||
pub use self::ui::CursorImage;
|
||||
pub use self::ui::{ColorOrAuto, Cursor, MozForceBrokenImageIcon};
|
||||
pub use self::ui::{ColorOrAuto, Cursor, MozForceBrokenImageIcon, UserSelect};
|
||||
pub use super::specified::{BorderStyle, TextDecorationLine};
|
||||
pub use super::{Auto, Either, None_};
|
||||
pub use app_units::Au;
|
||||
|
|
|
@ -10,7 +10,7 @@ use crate::values::computed::Number;
|
|||
use crate::values::generics::ui as generics;
|
||||
use crate::values::{Auto, Either};
|
||||
|
||||
pub use crate::values::specified::ui::MozForceBrokenImageIcon;
|
||||
pub use crate::values::specified::ui::{MozForceBrokenImageIcon, UserSelect};
|
||||
|
||||
/// auto | <color>
|
||||
pub type ColorOrAuto = Either<Color, Auto>;
|
||||
|
|
|
@ -52,9 +52,6 @@ fn moz_box_display_values_enabled(context: &ParserContext) -> bool {
|
|||
/// If you change it, make sure to take a look at the
|
||||
/// FrameConstructionDataByDisplay stuff (both the XUL and non-XUL version), and
|
||||
/// ensure it's still correct!
|
||||
///
|
||||
/// Also, when you change this from Gecko you may need to regenerate the
|
||||
/// C++-side bindings (see components/style/cbindgen.toml).
|
||||
#[allow(missing_docs)]
|
||||
#[derive(
|
||||
Clone,
|
||||
|
|
|
@ -82,7 +82,7 @@ pub use self::transform::{Rotate, Scale, Transform};
|
|||
pub use self::transform::{TransformOrigin, TransformStyle, Translate};
|
||||
#[cfg(feature = "gecko")]
|
||||
pub use self::ui::CursorImage;
|
||||
pub use self::ui::{ColorOrAuto, Cursor, MozForceBrokenImageIcon};
|
||||
pub use self::ui::{ColorOrAuto, Cursor, MozForceBrokenImageIcon, UserSelect};
|
||||
pub use super::generics::grid::GridTemplateComponent as GenericGridTemplateComponent;
|
||||
|
||||
#[cfg(feature = "gecko")]
|
||||
|
|
|
@ -140,3 +140,43 @@ impl Parse for ScrollbarColor {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
fn in_ua_sheet(context: &ParserContext) -> bool {
|
||||
use crate::stylesheets::Origin;
|
||||
context.stylesheet_origin == Origin::UserAgent
|
||||
}
|
||||
|
||||
/// The specified value for the `user-select` property.
|
||||
///
|
||||
/// https://drafts.csswg.org/css-ui-4/#propdef-user-select
|
||||
#[allow(missing_docs)]
|
||||
#[derive(
|
||||
Clone,
|
||||
Copy,
|
||||
Debug,
|
||||
Eq,
|
||||
MallocSizeOf,
|
||||
Parse,
|
||||
PartialEq,
|
||||
SpecifiedValueInfo,
|
||||
ToComputedValue,
|
||||
ToCss,
|
||||
)]
|
||||
#[repr(u8)]
|
||||
pub enum UserSelect {
|
||||
Auto,
|
||||
Text,
|
||||
#[parse(aliases = "-moz-none")]
|
||||
None,
|
||||
/// Force selection of all children, unless an ancestor has `none` set.
|
||||
All,
|
||||
/// Like `text`, except that it won't get overridden by ancestors having
|
||||
/// `all`.
|
||||
///
|
||||
/// FIXME(emilio): This only has one use in contenteditable.css, can we find
|
||||
/// a better way to do this?
|
||||
///
|
||||
/// See bug 1181130.
|
||||
#[parse(condition = "in_ua_sheet")]
|
||||
MozText,
|
||||
}
|
||||
|
|
|
@ -575,7 +575,7 @@ linux64-rust-nightly-macos:
|
|||
using: toolchain-script
|
||||
script: repack_rust.py
|
||||
arguments: [
|
||||
'--channel', 'nightly-2018-09-16',
|
||||
'--channel', 'nightly-2018-10-05',
|
||||
'--host', 'x86_64-unknown-linux-gnu',
|
||||
'--target', 'x86_64-unknown-linux-gnu',
|
||||
'--target', 'x86_64-apple-darwin',
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
[key_valid.html]
|
||||
disabled:
|
||||
if debug and not webrender and e10s and (os == "mac") and (version == "OS X 10.10.5") and (processor == "x86_64") and (bits == 64): https://bugzilla.mozilla.org/show_bug.cgi?id=1506417
|
|
@ -0,0 +1,13 @@
|
|||
[compile.any.worker.html]
|
||||
[Invalid code]
|
||||
expected: FAIL
|
||||
|
||||
|
||||
[compile.any.html]
|
||||
[Invalid code]
|
||||
expected: FAIL
|
||||
|
||||
|
||||
[compile.any.js]
|
||||
[Invalid code]
|
||||
expected: FAIL
|
|
@ -62,6 +62,11 @@ test(() => {
|
|||
promise_test(t => {
|
||||
const buffer = new Uint8Array();
|
||||
return promise_rejects(t, new WebAssembly.CompileError(), WebAssembly.compile(buffer));
|
||||
}, "Empty buffer");
|
||||
|
||||
test(() => {
|
||||
const buffer = new Uint8Array(Array.from(emptyModuleBinary).concat([0, 0]));
|
||||
assert_throws(new WebAssembly.CompileError(), () => WebAssembly.compile(buffer));
|
||||
}, "Invalid code");
|
||||
|
||||
promise_test(() => {
|
||||
|
|
|
@ -79,6 +79,11 @@ for (const [name, fn] of instanceTestFactory) {
|
|||
promise_test(t => {
|
||||
const buffer = new Uint8Array();
|
||||
return promise_rejects(t, new WebAssembly.CompileError(), WebAssembly.instantiate(buffer));
|
||||
}, "Empty buffer");
|
||||
|
||||
promise_test(t => {
|
||||
const buffer = new Uint8Array(Array.from(emptyModuleBinary).concat([0, 0]));
|
||||
return promise_rejects(t, new WebAssembly.CompileError(), WebAssembly.instantiate(buffer));
|
||||
}, "Invalid code");
|
||||
|
||||
promise_test(() => {
|
||||
|
|
|
@ -49,6 +49,11 @@ test(() => {
|
|||
assert_throws(new WebAssembly.CompileError(), () => new WebAssembly.Module(buffer));
|
||||
}, "Empty buffer");
|
||||
|
||||
test(() => {
|
||||
const buffer = new Uint8Array(Array.from(emptyModuleBinary).concat([0, 0]));
|
||||
assert_throws(new WebAssembly.CompileError(), () => new WebAssembly.Module(buffer));
|
||||
}, "Invalid code");
|
||||
|
||||
test(() => {
|
||||
const module = new WebAssembly.Module(emptyModuleBinary);
|
||||
assert_equals(Object.getPrototypeOf(module), WebAssembly.Module.prototype);
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
// META: global=window,worker
|
||||
// META: script=/wasm/jsapi/wasm-constants.js
|
||||
// META: script=/wasm/jsapi/wasm-module-builder.js
|
||||
|
||||
let emptyModuleBinary;
|
||||
setup(() => {
|
||||
emptyModuleBinary = new WasmModuleBuilder().toBuffer();
|
||||
});
|
||||
|
||||
for (const method of ["compileStreaming", "instantiateStreaming"]) {
|
||||
promise_test(t => {
|
||||
const buffer = new Uint8Array(Array.from(emptyModuleBinary).concat([0, 0]));
|
||||
const response = new Response(buffer, { headers: { "Content-Type": "application/wasm" } });
|
||||
return promise_rejects(t, new WebAssembly.CompileError(), WebAssembly[method](response));
|
||||
}, `Invalid code: ${method}`);
|
||||
}
|
|
@ -234,7 +234,8 @@ var SafeBrowsing = {
|
|||
this.malwareEnabled = Services.prefs.getBoolPref("browser.safebrowsing.malware.enabled");
|
||||
this.downloadsEnabled = Services.prefs.getBoolPref("browser.safebrowsing.downloads.enabled");
|
||||
this.passwordsEnabled = Services.prefs.getBoolPref("browser.safebrowsing.passwords.enabled");
|
||||
this.trackingEnabled = Services.prefs.getBoolPref("privacy.trackingprotection.enabled") ||
|
||||
this.trackingEnabled = Services.prefs.getBoolPref("toolkit.telemetry.isGeckoViewMode", false) ||
|
||||
Services.prefs.getBoolPref("privacy.trackingprotection.enabled") ||
|
||||
Services.prefs.getBoolPref("privacy.trackingprotection.pbmode.enabled");
|
||||
this.blockedEnabled = Services.prefs.getBoolPref("browser.safebrowsing.blockedURIs.enabled");
|
||||
this.trackingAnnotations = Services.prefs.getBoolPref("privacy.trackingprotection.annotate_channels");
|
||||
|
|
|
@ -58,7 +58,6 @@ xhtml|link {
|
|||
|
||||
.text-list {
|
||||
white-space: pre-line;
|
||||
-moz-user-select: element;
|
||||
}
|
||||
|
||||
row[unsupported="true"] {
|
||||
|
|
|
@ -468,8 +468,10 @@ MaybeInternalJumpTarget(uint8_t* aIpStart, uint8_t* aIpEnd)
|
|||
!strstr(startName, "CTRunGetPositionsPtr")) ||
|
||||
(strstr(startName, "CTRunGetStringIndices") &&
|
||||
!strstr(startName, "CTRunGetStringIndicesPtr")) ||
|
||||
strstr(startName, "CGColorSpaceCreateDeviceGray") ||
|
||||
strstr(startName, "CGColorSpaceCreateDeviceRGB") ||
|
||||
(strstr(startName, "CGColorSpaceCreateDeviceGray") &&
|
||||
!strstr(startName, "CGColorSpaceCreateDeviceGray_block_invoke")) ||
|
||||
(strstr(startName, "CGColorSpaceCreateDeviceRGB") &&
|
||||
!strstr(startName, "CGColorSpaceCreateDeviceRGB_block_invoke")) ||
|
||||
// For these functions, there is a syscall near the beginning which
|
||||
// other system threads might be inside.
|
||||
strstr(startName, "__workq_kernreturn") ||
|
||||
|
|
|
@ -199,6 +199,7 @@ namespace recordreplay {
|
|||
MACRO(mach_vm_allocate, nullptr, Preamble_mach_vm_allocate) \
|
||||
MACRO(mach_vm_deallocate, nullptr, Preamble_mach_vm_deallocate) \
|
||||
MACRO(mach_vm_protect, nullptr, Preamble_mach_vm_protect) \
|
||||
MACRO(rand, RR_ScalarRval) \
|
||||
MACRO(realpath, \
|
||||
RR_SaveRvalHadErrorZero<RR_Compose<RR_CStringRval, \
|
||||
RR_WriteOptionalBufferFixedSize<1, PATH_MAX>>>) \
|
||||
|
|
Загрузка…
Ссылка в новой задаче