Merge mozilla-central to autoland. a=merge

--HG--
extra : rebase_source : d93c4498b3c7872e1539b4f37b8601a804820dea
This commit is contained in:
Cosmin Sabou 2018-11-13 06:29:03 +02:00
Родитель b6884c7920 007b66c1f5
Коммит 791de0dab3
65 изменённых файлов: 716 добавлений и 524 удалений

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

@ -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;
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,19 +1575,14 @@ 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)) {
if (mSpec->indexes().Length() && !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();
}
{
const nsTArray<IndexMetadata>& indexes = mSpec->indexes();
uint32_t idxCount = indexes.Length();
aUpdateInfoArray.SetCapacity(idxCount); // Pretty good estimate
@ -1602,6 +1597,7 @@ IDBObjectStore::GetAddInfo(JSContext* aCx,
return rv;
}
}
}
if (isAutoIncrement && HasValidKeyPath()) {
@ -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,
CodeNode*
BytecodeCompiler::parseStandaloneFunction(MutableHandleFunction fun,
GeneratorKind generatorKind,
FunctionAsyncKind asyncKind,
const Maybe<uint32_t>& parameterListEnd)
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,
CodeNode* parsedFunction = compiler.parseStandaloneFunction(fun, GeneratorKind::NotGenerator,
FunctionAsyncKind::SyncFunction,
parameterListEnd))
{
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,
RootedScope emptyGlobalScope(cx, &cx->global()->emptyGlobalScope());
CodeNode* parsedFunction = compiler.parseStandaloneFunction(fun, GeneratorKind::Generator,
FunctionAsyncKind::SyncFunction,
parameterListEnd))
{
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,
RootedScope emptyGlobalScope(cx, &cx->global()->emptyGlobalScope());
CodeNode* parsedFunction = compiler.parseStandaloneFunction(fun, GeneratorKind::NotGenerator,
FunctionAsyncKind::AsyncFunction,
parameterListEnd))
{
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,
RootedScope emptyGlobalScope(cx, &cx->global()->emptyGlobalScope());
CodeNode* parsedFunction = compiler.parseStandaloneFunction(fun, GeneratorKind::Generator,
FunctionAsyncKind::AsyncFunction,
parameterListEnd))
{
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) {
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>>>) \