зеркало из https://github.com/mozilla/gecko-dev.git
Merge mozilla-inbound to mozilla-central. a=merge
This commit is contained in:
Коммит
91a9c110e2
|
@ -3,6 +3,7 @@
|
|||
TOOLTOOL_DIR=${TOOLTOOL_DIR:-$topsrcdir}
|
||||
|
||||
ac_add_options --disable-sandbox
|
||||
ac_add_options --disable-warnings-as-errors
|
||||
ac_add_options --enable-coverage
|
||||
|
||||
export CFLAGS="-coverage"
|
||||
|
|
|
@ -6,6 +6,7 @@ MOZ_AUTOMATION_L10N_CHECK=0
|
|||
ac_add_options --enable-optimize
|
||||
ac_add_options --enable-debug
|
||||
ac_add_options --disable-sandbox
|
||||
ac_add_options --disable-warnings-as-errors
|
||||
ac_add_options --enable-coverage
|
||||
|
||||
# Needed to enable breakpad in application.ini
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
This is the PDF.js project output, https://github.com/mozilla/pdf.js
|
||||
|
||||
Current extension version is: 2.0.625
|
||||
Current extension version is: 2.0.641
|
||||
|
||||
Taken from upstream commit: e8b50883
|
||||
Taken from upstream commit: 6fa2c779
|
||||
|
|
|
@ -123,8 +123,8 @@ return /******/ (function(modules) { // webpackBootstrap
|
|||
"use strict";
|
||||
|
||||
|
||||
var pdfjsVersion = '2.0.625';
|
||||
var pdfjsBuild = 'e8b50883';
|
||||
var pdfjsVersion = '2.0.641';
|
||||
var pdfjsBuild = '6fa2c779';
|
||||
var pdfjsSharedUtil = __w_pdfjs_require__(1);
|
||||
var pdfjsDisplayAPI = __w_pdfjs_require__(6);
|
||||
var pdfjsDisplayTextLayer = __w_pdfjs_require__(18);
|
||||
|
@ -4223,7 +4223,7 @@ function _fetchDocument(worker, source, pdfDataRangeTransport, docId) {
|
|||
}
|
||||
return worker.messageHandler.sendWithPromise('GetDocRequest', {
|
||||
docId,
|
||||
apiVersion: '2.0.625',
|
||||
apiVersion: '2.0.641',
|
||||
source: {
|
||||
data: source.data,
|
||||
url: source.url,
|
||||
|
@ -4530,6 +4530,7 @@ var PDFPageProxy = function PDFPageProxyClosure() {
|
|||
argsArray: [],
|
||||
lastChunk: false
|
||||
};
|
||||
this._stats.time('Page Request');
|
||||
this.transport.messageHandler.send('RenderPageRequest', {
|
||||
pageIndex: this.pageIndex,
|
||||
intent: renderingIntent
|
||||
|
@ -5562,8 +5563,8 @@ var InternalRenderTask = function InternalRenderTaskClosure() {
|
|||
}();
|
||||
var version, build;
|
||||
{
|
||||
exports.version = version = '2.0.625';
|
||||
exports.build = build = 'e8b50883';
|
||||
exports.version = version = '2.0.641';
|
||||
exports.build = build = '6fa2c779';
|
||||
}
|
||||
exports.getDocument = getDocument;
|
||||
exports.LoopbackPort = LoopbackPort;
|
||||
|
|
|
@ -123,8 +123,8 @@ return /******/ (function(modules) { // webpackBootstrap
|
|||
"use strict";
|
||||
|
||||
|
||||
var pdfjsVersion = '2.0.625';
|
||||
var pdfjsBuild = 'e8b50883';
|
||||
var pdfjsVersion = '2.0.641';
|
||||
var pdfjsBuild = '6fa2c779';
|
||||
var pdfjsCoreWorker = __w_pdfjs_require__(1);
|
||||
exports.WorkerMessageHandler = pdfjsCoreWorker.WorkerMessageHandler;
|
||||
|
||||
|
@ -327,7 +327,7 @@ var WorkerMessageHandler = {
|
|||
var cancelXHRs = null;
|
||||
var WorkerTasks = [];
|
||||
let apiVersion = docParams.apiVersion;
|
||||
let workerVersion = '2.0.625';
|
||||
let workerVersion = '2.0.641';
|
||||
if (apiVersion !== workerVersion) {
|
||||
throw new Error(`The API version "${apiVersion}" does not match ` + `the Worker version "${workerVersion}".`);
|
||||
}
|
||||
|
@ -11387,6 +11387,46 @@ var Jbig2Image = function Jbig2ImageClosure() {
|
|||
}
|
||||
return visitor.buffer;
|
||||
}
|
||||
function parseJbig2(data) {
|
||||
let position = 0,
|
||||
end = data.length;
|
||||
if (data[position] !== 0x97 || data[position + 1] !== 0x4A || data[position + 2] !== 0x42 || data[position + 3] !== 0x32 || data[position + 4] !== 0x0D || data[position + 5] !== 0x0A || data[position + 6] !== 0x1A || data[position + 7] !== 0x0A) {
|
||||
throw new Jbig2Error('parseJbig2 - invalid header.');
|
||||
}
|
||||
let header = Object.create(null);
|
||||
position += 8;
|
||||
const flags = data[position++];
|
||||
header.randomAccess = !(flags & 1);
|
||||
if (!(flags & 2)) {
|
||||
header.numberOfPages = (0, _util.readUint32)(data, position);
|
||||
position += 4;
|
||||
}
|
||||
let segments = readSegments(header, data, position, end);
|
||||
let visitor = new SimpleSegmentVisitor();
|
||||
processSegments(segments, visitor);
|
||||
const { width, height } = visitor.currentPageInfo;
|
||||
const bitPacked = visitor.buffer;
|
||||
let imgData = new Uint8ClampedArray(width * height);
|
||||
let q = 0,
|
||||
k = 0;
|
||||
for (let i = 0; i < height; i++) {
|
||||
let mask = 0,
|
||||
buffer;
|
||||
for (let j = 0; j < width; j++) {
|
||||
if (!mask) {
|
||||
mask = 128;
|
||||
buffer = bitPacked[k++];
|
||||
}
|
||||
imgData[q++] = buffer & mask ? 0 : 255;
|
||||
mask >>= 1;
|
||||
}
|
||||
}
|
||||
return {
|
||||
imgData,
|
||||
width,
|
||||
height
|
||||
};
|
||||
}
|
||||
function SimpleSegmentVisitor() {}
|
||||
SimpleSegmentVisitor.prototype = {
|
||||
onPageInformation: function SimpleSegmentVisitor_onPageInformation(info) {
|
||||
|
@ -11986,8 +12026,14 @@ var Jbig2Image = function Jbig2ImageClosure() {
|
|||
}
|
||||
function Jbig2Image() {}
|
||||
Jbig2Image.prototype = {
|
||||
parseChunks: function Jbig2Image_parseChunks(chunks) {
|
||||
parseChunks(chunks) {
|
||||
return parseJbig2Chunks(chunks);
|
||||
},
|
||||
parse(data) {
|
||||
const { imgData, width, height } = parseJbig2(data);
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
return imgData;
|
||||
}
|
||||
};
|
||||
return Jbig2Image;
|
||||
|
@ -12381,7 +12427,10 @@ let JpegStream = function JpegStreamClosure() {
|
|||
if (this.eof) {
|
||||
return;
|
||||
}
|
||||
let jpegImage = new _jpg.JpegImage();
|
||||
let jpegOptions = {
|
||||
decodeTransform: undefined,
|
||||
colorTransform: undefined
|
||||
};
|
||||
let decodeArr = this.dict.getArray('Decode', 'D');
|
||||
if (this.forceRGB && Array.isArray(decodeArr)) {
|
||||
let bitsPerComponent = this.dict.get('BitsPerComponent') || 8;
|
||||
|
@ -12397,15 +12446,16 @@ let JpegStream = function JpegStreamClosure() {
|
|||
}
|
||||
}
|
||||
if (transformNeeded) {
|
||||
jpegImage.decodeTransform = transform;
|
||||
jpegOptions.decodeTransform = transform;
|
||||
}
|
||||
}
|
||||
if ((0, _primitives.isDict)(this.params)) {
|
||||
let colorTransform = this.params.get('ColorTransform');
|
||||
if (Number.isInteger(colorTransform)) {
|
||||
jpegImage.colorTransform = colorTransform;
|
||||
jpegOptions.colorTransform = colorTransform;
|
||||
}
|
||||
}
|
||||
const jpegImage = new _jpg.JpegImage(jpegOptions);
|
||||
jpegImage.parse(this.bytes);
|
||||
let data = jpegImage.getData(this.drawWidth, this.drawHeight, this.forceRGB);
|
||||
this.buffer = data;
|
||||
|
@ -12471,9 +12521,9 @@ var JpegImage = function JpegImageClosure() {
|
|||
var dctSin6 = 3784;
|
||||
var dctSqrt2 = 5793;
|
||||
var dctSqrt1d2 = 2896;
|
||||
function JpegImage() {
|
||||
this.decodeTransform = null;
|
||||
this.colorTransform = -1;
|
||||
function JpegImage({ decodeTransform = null, colorTransform = -1 } = {}) {
|
||||
this._decodeTransform = decodeTransform;
|
||||
this._colorTransform = colorTransform;
|
||||
}
|
||||
function buildHuffmanTable(codeLengths, values) {
|
||||
var k = 0,
|
||||
|
@ -13276,7 +13326,7 @@ var JpegImage = function JpegImageClosure() {
|
|||
}
|
||||
}
|
||||
}
|
||||
var transform = this.decodeTransform;
|
||||
const transform = this._decodeTransform;
|
||||
if (transform) {
|
||||
for (i = 0; i < dataLength;) {
|
||||
for (j = 0, k = 0; j < numComponents; j++, i++, k += 2) {
|
||||
|
@ -13291,12 +13341,12 @@ var JpegImage = function JpegImageClosure() {
|
|||
return !!this.adobe.transformCode;
|
||||
}
|
||||
if (this.numComponents === 3) {
|
||||
if (this.colorTransform === 0) {
|
||||
if (this._colorTransform === 0) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (this.colorTransform === 1) {
|
||||
if (this._colorTransform === 1) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -21484,11 +21534,13 @@ var EvaluatorPreprocessor = function EvaluatorPreprocessorClosure() {
|
|||
t['nul'] = null;
|
||||
t['null'] = null;
|
||||
});
|
||||
const MAX_INVALID_PATH_OPS = 20;
|
||||
function EvaluatorPreprocessor(stream, xref, stateManager) {
|
||||
this.opMap = getOPMap();
|
||||
this.parser = new _parser.Parser(new _parser.Lexer(stream, this.opMap), false, xref);
|
||||
this.stateManager = stateManager;
|
||||
this.nonProcessedArgs = [];
|
||||
this._numInvalidPathOPS = 0;
|
||||
}
|
||||
EvaluatorPreprocessor.prototype = {
|
||||
get savedStatesDepth() {
|
||||
|
@ -21502,7 +21554,7 @@ var EvaluatorPreprocessor = function EvaluatorPreprocessorClosure() {
|
|||
var cmd = obj.cmd;
|
||||
var opSpec = this.opMap[cmd];
|
||||
if (!opSpec) {
|
||||
(0, _util.warn)('Unknown command "' + cmd + '"');
|
||||
(0, _util.warn)(`Unknown command "${cmd}".`);
|
||||
continue;
|
||||
}
|
||||
var fn = opSpec.id;
|
||||
|
@ -21524,14 +21576,18 @@ var EvaluatorPreprocessor = function EvaluatorPreprocessorClosure() {
|
|||
}
|
||||
}
|
||||
if (argsLength < numArgs) {
|
||||
(0, _util.warn)('Skipping command ' + fn + ': expected ' + numArgs + ' args, but received ' + argsLength + ' args.');
|
||||
const partialMsg = `command ${cmd}: expected ${numArgs} args, ` + `but received ${argsLength} args.`;
|
||||
if (fn >= _util.OPS.moveTo && fn <= _util.OPS.endPath && ++this._numInvalidPathOPS > MAX_INVALID_PATH_OPS) {
|
||||
throw new _util.FormatError(`Invalid ${partialMsg}`);
|
||||
}
|
||||
(0, _util.warn)(`Skipping ${partialMsg}`);
|
||||
if (args !== null) {
|
||||
args.length = 0;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
} else if (argsLength > numArgs) {
|
||||
(0, _util.info)('Command ' + fn + ': expected [0,' + numArgs + '] args, but received ' + argsLength + ' args.');
|
||||
(0, _util.info)(`Command ${cmd}: expected [0, ${numArgs}] args, ` + `but received ${argsLength} args.`);
|
||||
}
|
||||
this.preprocessCommand(fn, args);
|
||||
operation.fn = fn;
|
||||
|
|
|
@ -319,6 +319,7 @@ var _view_history = __webpack_require__(31);
|
|||
|
||||
const DEFAULT_SCALE_DELTA = 1.1;
|
||||
const DISABLE_AUTO_FETCH_LOADING_BAR_TIMEOUT = 5000;
|
||||
const FORCE_PAGES_LOADED_TIMEOUT = 10000;
|
||||
const DefaultExternalServices = {
|
||||
updateFindControlState(data) {},
|
||||
initPassiveLoading(callbacks) {},
|
||||
|
@ -959,8 +960,7 @@ let PDFViewerApplication = {
|
|||
hash: null
|
||||
};
|
||||
let storePromise = store.getMultiple({
|
||||
exists: false,
|
||||
page: '1',
|
||||
page: null,
|
||||
zoom: _ui_utils.DEFAULT_SCALE_VALUE,
|
||||
scrollLeft: '0',
|
||||
scrollTop: '0',
|
||||
|
@ -970,13 +970,14 @@ let PDFViewerApplication = {
|
|||
spreadMode: null
|
||||
}).catch(() => {});
|
||||
Promise.all([storePromise, pageModePromise]).then(([values = {}, pageMode]) => {
|
||||
let hash = _app_options.AppOptions.get('defaultZoomValue') ? 'zoom=' + _app_options.AppOptions.get('defaultZoomValue') : null;
|
||||
const zoom = _app_options.AppOptions.get('defaultZoomValue');
|
||||
let hash = zoom ? `zoom=${zoom}` : null;
|
||||
let rotation = null;
|
||||
let sidebarView = _app_options.AppOptions.get('sidebarViewOnLoad');
|
||||
let scrollMode = _app_options.AppOptions.get('scrollModeOnLoad');
|
||||
let spreadMode = _app_options.AppOptions.get('spreadModeOnLoad');
|
||||
if (values.exists && _app_options.AppOptions.get('showPreviousViewOnLoad')) {
|
||||
hash = 'page=' + values.page + '&zoom=' + (_app_options.AppOptions.get('defaultZoomValue') || values.zoom) + ',' + values.scrollLeft + ',' + values.scrollTop;
|
||||
if (values.page && _app_options.AppOptions.get('showPreviousViewOnLoad')) {
|
||||
hash = 'page=' + values.page + '&zoom=' + (zoom || values.zoom) + ',' + values.scrollLeft + ',' + values.scrollTop;
|
||||
rotation = parseInt(values.rotation, 10);
|
||||
sidebarView = sidebarView || values.sidebarView | 0;
|
||||
if (values.scrollMode !== null) {
|
||||
|
@ -1008,7 +1009,9 @@ let PDFViewerApplication = {
|
|||
if (!this.isViewerEmbedded) {
|
||||
pdfViewer.focus();
|
||||
}
|
||||
return pagesPromise;
|
||||
return Promise.race([pagesPromise, new Promise(resolve => {
|
||||
setTimeout(resolve, FORCE_PAGES_LOADED_TIMEOUT);
|
||||
})]);
|
||||
}).then(() => {
|
||||
if (!initialParams.bookmark && !initialParams.hash) {
|
||||
return;
|
||||
|
@ -1482,7 +1485,6 @@ function webViewerUpdateViewarea(evt) {
|
|||
store = PDFViewerApplication.store;
|
||||
if (store && PDFViewerApplication.isInitialViewSet) {
|
||||
store.setMultiple({
|
||||
'exists': true,
|
||||
'page': location.pageNumber,
|
||||
'zoom': location.scale,
|
||||
'scrollLeft': location.left,
|
||||
|
@ -1941,7 +1943,7 @@ exports.PDFPrintServiceFactory = PDFPrintServiceFactory;
|
|||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.moveToEndOfArray = exports.waitOnEventOrTimeout = exports.WaitOnType = exports.animationStarted = exports.normalizeWheelEventDelta = exports.binarySearchFirstItem = exports.watchScroll = exports.scrollIntoView = exports.getOutputScale = exports.approximateFraction = exports.getPageSizeInches = exports.roundToDivide = exports.getVisibleElements = exports.backtrackBeforeAllVisibleElements = exports.parseQueryString = exports.noContextMenuHandler = exports.getPDFFileNameFromURL = exports.ProgressBar = exports.EventBus = exports.NullL10n = exports.TextLayerMode = exports.RendererType = exports.PresentationModeState = exports.cloneObj = exports.isPortraitOrientation = exports.isValidRotation = exports.VERTICAL_PADDING = exports.SCROLLBAR_PADDING = exports.MAX_AUTO_SCALE = exports.UNKNOWN_SCALE = exports.MAX_SCALE = exports.MIN_SCALE = exports.DEFAULT_SCALE = exports.DEFAULT_SCALE_VALUE = exports.CSS_UNITS = undefined;
|
||||
exports.moveToEndOfArray = exports.waitOnEventOrTimeout = exports.WaitOnType = exports.animationStarted = exports.normalizeWheelEventDelta = exports.binarySearchFirstItem = exports.watchScroll = exports.scrollIntoView = exports.getOutputScale = exports.approximateFraction = exports.getPageSizeInches = exports.roundToDivide = exports.getVisibleElements = exports.backtrackBeforeAllVisibleElements = exports.parseQueryString = exports.noContextMenuHandler = exports.getPDFFileNameFromURL = exports.ProgressBar = exports.EventBus = exports.NullL10n = exports.TextLayerMode = exports.RendererType = exports.PresentationModeState = exports.isPortraitOrientation = exports.isValidRotation = exports.VERTICAL_PADDING = exports.SCROLLBAR_PADDING = exports.MAX_AUTO_SCALE = exports.UNKNOWN_SCALE = exports.MAX_SCALE = exports.MIN_SCALE = exports.DEFAULT_SCALE = exports.DEFAULT_SCALE_VALUE = exports.CSS_UNITS = undefined;
|
||||
|
||||
var _pdfjsLib = __webpack_require__(3);
|
||||
|
||||
|
@ -2293,15 +2295,6 @@ function isValidRotation(angle) {
|
|||
function isPortraitOrientation(size) {
|
||||
return size.width <= size.height;
|
||||
}
|
||||
function cloneObj(obj) {
|
||||
let result = Object.create(null);
|
||||
for (let i in obj) {
|
||||
if (Object.prototype.hasOwnProperty.call(obj, i)) {
|
||||
result[i] = obj[i];
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
const WaitOnType = {
|
||||
EVENT: 'event',
|
||||
TIMEOUT: 'timeout'
|
||||
|
@ -2452,7 +2445,6 @@ exports.SCROLLBAR_PADDING = SCROLLBAR_PADDING;
|
|||
exports.VERTICAL_PADDING = VERTICAL_PADDING;
|
||||
exports.isValidRotation = isValidRotation;
|
||||
exports.isPortraitOrientation = isPortraitOrientation;
|
||||
exports.cloneObj = cloneObj;
|
||||
exports.PresentationModeState = PresentationModeState;
|
||||
exports.RendererType = RendererType;
|
||||
exports.TextLayerMode = TextLayerMode;
|
||||
|
@ -3850,7 +3842,7 @@ class PDFDocumentProperties {
|
|||
if (fileSize === this.fieldData['fileSize']) {
|
||||
return;
|
||||
}
|
||||
let data = (0, _ui_utils.cloneObj)(this.fieldData);
|
||||
let data = Object.assign(Object.create(null), this.fieldData);
|
||||
data['fileSize'] = fileSize;
|
||||
freezeFieldData(data);
|
||||
this._updateUI();
|
||||
|
@ -4723,7 +4715,7 @@ class PDFHistory {
|
|||
}
|
||||
let position = this._position;
|
||||
if (temporary) {
|
||||
position = (0, _ui_utils.cloneObj)(this._position);
|
||||
position = Object.assign(Object.create(null), this._position);
|
||||
position.temporary = true;
|
||||
}
|
||||
if (!this._destination) {
|
||||
|
@ -8484,11 +8476,12 @@ class ViewHistory {
|
|||
let database = JSON.parse(databaseStr || '{}');
|
||||
if (!('files' in database)) {
|
||||
database.files = [];
|
||||
} else {
|
||||
while (database.files.length >= this.cacheSize) {
|
||||
database.files.shift();
|
||||
}
|
||||
}
|
||||
if (database.files.length >= this.cacheSize) {
|
||||
database.files.shift();
|
||||
}
|
||||
let index;
|
||||
let index = -1;
|
||||
for (let i = 0, length = database.files.length; i < length; i++) {
|
||||
let branch = database.files[i];
|
||||
if (branch.fingerprint === this.fingerprint) {
|
||||
|
@ -8496,7 +8489,7 @@ class ViewHistory {
|
|||
break;
|
||||
}
|
||||
}
|
||||
if (typeof index !== 'number') {
|
||||
if (index === -1) {
|
||||
index = database.files.push({ fingerprint: this.fingerprint }) - 1;
|
||||
}
|
||||
this.file = database.files[index];
|
||||
|
@ -8903,10 +8896,6 @@ exports.FirefoxCom = FirefoxCom;
|
|||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.BasePreferences = undefined;
|
||||
|
||||
var _ui_utils = __webpack_require__(2);
|
||||
|
||||
let defaultPreferences = null;
|
||||
function getDefaultPreferences() {
|
||||
if (!defaultPreferences) {
|
||||
|
@ -8948,7 +8937,7 @@ class BasePreferences {
|
|||
enumerable: true,
|
||||
configurable: false
|
||||
});
|
||||
this.prefs = (0, _ui_utils.cloneObj)(defaults);
|
||||
this.prefs = Object.assign(Object.create(null), defaults);
|
||||
return this._readFromStorage(defaults);
|
||||
}).then(prefObj => {
|
||||
if (prefObj) {
|
||||
|
@ -8964,7 +8953,7 @@ class BasePreferences {
|
|||
}
|
||||
reset() {
|
||||
return this._initializedPromise.then(() => {
|
||||
this.prefs = (0, _ui_utils.cloneObj)(this.defaults);
|
||||
this.prefs = Object.assign(Object.create(null), this.defaults);
|
||||
return this._writeToStorage(this.defaults);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -267,8 +267,8 @@ class RemoteAutomation(Automation):
|
|||
app, moz_env=env, extra_args=args, url=url)
|
||||
|
||||
# Setting timeout at 1 hour since on a remote device this takes much longer.
|
||||
# Temporarily increased to 90 minutes because no more chunks can be created.
|
||||
self.timeout = 5400
|
||||
# Temporarily increased to 110 minutes because no more chunks can be created.
|
||||
self.timeout = 6600
|
||||
|
||||
# Used to buffer log messages until we meet a line break
|
||||
self.logBuffer = ""
|
||||
|
|
|
@ -645,7 +645,7 @@ static_assert(sizeof(FragmentOrElement::nsDOMSlots) <= MaxDOMSlotSizeAllowed,
|
|||
"DOM slots cannot be grown without consideration");
|
||||
|
||||
void
|
||||
nsIContent::nsExtendedContentSlots::Unlink()
|
||||
nsIContent::nsExtendedContentSlots::UnlinkExtendedSlots()
|
||||
{
|
||||
mBindingParent = nullptr;
|
||||
mXBLInsertionPoint = nullptr;
|
||||
|
@ -654,7 +654,7 @@ nsIContent::nsExtendedContentSlots::Unlink()
|
|||
}
|
||||
|
||||
void
|
||||
nsIContent::nsExtendedContentSlots::Traverse(nsCycleCollectionTraversalCallback& aCb)
|
||||
nsIContent::nsExtendedContentSlots::TraverseExtendedSlots(nsCycleCollectionTraversalCallback& aCb)
|
||||
{
|
||||
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(aCb, "mExtendedSlots->mBindingParent");
|
||||
aCb.NoteXPCOMChild(NS_ISUPPORTS_CAST(nsIContent*, mBindingParent));
|
||||
|
@ -679,10 +679,13 @@ FragmentOrElement::nsDOMSlots::nsDOMSlots()
|
|||
: nsIContent::nsContentSlots(),
|
||||
mDataset(nullptr)
|
||||
{
|
||||
MOZ_COUNT_CTOR(nsDOMSlots);
|
||||
}
|
||||
|
||||
FragmentOrElement::nsDOMSlots::~nsDOMSlots()
|
||||
{
|
||||
MOZ_COUNT_DTOR(nsDOMSlots);
|
||||
|
||||
if (mAttributeMap) {
|
||||
mAttributeMap->DropReference();
|
||||
}
|
||||
|
@ -723,8 +726,8 @@ size_t
|
|||
FragmentOrElement::nsDOMSlots::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
|
||||
{
|
||||
size_t n = aMallocSizeOf(this);
|
||||
if (mExtendedSlots) {
|
||||
n += aMallocSizeOf(mExtendedSlots.get());
|
||||
if (OwnsExtendedSlots()) {
|
||||
n += aMallocSizeOf(GetExtendedContentSlots());
|
||||
}
|
||||
|
||||
if (mAttributeMap) {
|
||||
|
@ -758,9 +761,9 @@ FragmentOrElement::nsExtendedDOMSlots::~nsExtendedDOMSlots()
|
|||
}
|
||||
|
||||
void
|
||||
FragmentOrElement::nsExtendedDOMSlots::Unlink()
|
||||
FragmentOrElement::nsExtendedDOMSlots::UnlinkExtendedSlots()
|
||||
{
|
||||
nsIContent::nsExtendedContentSlots::Unlink();
|
||||
nsIContent::nsExtendedContentSlots::UnlinkExtendedSlots();
|
||||
|
||||
// Don't clear mXBLBinding, it'll be done in
|
||||
// BindingManager::RemovedFromDocument from FragmentOrElement::Unlink.
|
||||
|
@ -780,9 +783,9 @@ FragmentOrElement::nsExtendedDOMSlots::Unlink()
|
|||
}
|
||||
|
||||
void
|
||||
FragmentOrElement::nsExtendedDOMSlots::Traverse(nsCycleCollectionTraversalCallback& aCb)
|
||||
FragmentOrElement::nsExtendedDOMSlots::TraverseExtendedSlots(nsCycleCollectionTraversalCallback& aCb)
|
||||
{
|
||||
nsIContent::nsExtendedContentSlots::Traverse(aCb);
|
||||
nsIContent::nsExtendedContentSlots::TraverseExtendedSlots(aCb);
|
||||
|
||||
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(aCb, "mExtendedSlots->mSMILOverrideStyle");
|
||||
aCb.NoteXPCOMChild(mSMILOverrideStyle.get());
|
||||
|
|
|
@ -171,14 +171,14 @@ public:
|
|||
* accessed through the DOM.
|
||||
*/
|
||||
|
||||
class nsExtendedDOMSlots final : public nsIContent::nsExtendedContentSlots
|
||||
class nsExtendedDOMSlots : public nsIContent::nsExtendedContentSlots
|
||||
{
|
||||
public:
|
||||
nsExtendedDOMSlots();
|
||||
~nsExtendedDOMSlots() final;
|
||||
~nsExtendedDOMSlots();
|
||||
|
||||
void Traverse(nsCycleCollectionTraversalCallback&) final;
|
||||
void Unlink() final;
|
||||
void TraverseExtendedSlots(nsCycleCollectionTraversalCallback&) final;
|
||||
void UnlinkExtendedSlots() final;
|
||||
|
||||
/**
|
||||
* SMIL Overridde style rules (for SMIL animation of CSS properties)
|
||||
|
@ -223,11 +223,11 @@ public:
|
|||
|
||||
};
|
||||
|
||||
class nsDOMSlots final : public nsIContent::nsContentSlots
|
||||
class nsDOMSlots : public nsIContent::nsContentSlots
|
||||
{
|
||||
public:
|
||||
nsDOMSlots();
|
||||
~nsDOMSlots() final;
|
||||
~nsDOMSlots();
|
||||
|
||||
void Traverse(nsCycleCollectionTraversalCallback&) final;
|
||||
void Unlink() final;
|
||||
|
@ -263,6 +263,29 @@ public:
|
|||
RefPtr<nsDOMTokenList> mClassList;
|
||||
};
|
||||
|
||||
/**
|
||||
* In case ExtendedDOMSlots is needed before normal DOMSlots, an instance of
|
||||
* FatSlots class, which combines those two slot types, is created.
|
||||
* This way we can avoid extra allocation for ExtendedDOMSlots.
|
||||
* FatSlots is useful for example when creating Custom Elements.
|
||||
*/
|
||||
class FatSlots final : public nsDOMSlots, public nsExtendedDOMSlots
|
||||
{
|
||||
public:
|
||||
FatSlots()
|
||||
: nsDOMSlots()
|
||||
, nsExtendedDOMSlots()
|
||||
{
|
||||
MOZ_COUNT_CTOR(FatSlots);
|
||||
SetExtendedContentSlots(this, false);
|
||||
}
|
||||
|
||||
~FatSlots() final
|
||||
{
|
||||
MOZ_COUNT_DTOR(FatSlots);
|
||||
}
|
||||
};
|
||||
|
||||
protected:
|
||||
void GetMarkup(bool aIncludeSelf, nsAString& aMarkup);
|
||||
void SetInnerHTMLInternal(const nsAString& aInnerHTML, ErrorResult& aError);
|
||||
|
@ -290,7 +313,18 @@ protected:
|
|||
|
||||
nsExtendedDOMSlots* ExtendedDOMSlots()
|
||||
{
|
||||
return static_cast<nsExtendedDOMSlots*>(ExtendedContentSlots());
|
||||
nsContentSlots* slots = GetExistingContentSlots();
|
||||
if (!slots) {
|
||||
FatSlots* fatSlots = new FatSlots();
|
||||
mSlots = fatSlots;
|
||||
return fatSlots;
|
||||
}
|
||||
|
||||
if (!slots->GetExtendedContentSlots()) {
|
||||
slots->SetExtendedContentSlots(CreateExtendedSlots(), true);
|
||||
}
|
||||
|
||||
return static_cast<nsExtendedDOMSlots*>(slots->GetExtendedContentSlots());
|
||||
}
|
||||
|
||||
const nsExtendedDOMSlots* GetExistingExtendedDOMSlots() const
|
||||
|
|
|
@ -791,8 +791,8 @@ protected:
|
|||
nsExtendedContentSlots();
|
||||
virtual ~nsExtendedContentSlots();
|
||||
|
||||
virtual void Traverse(nsCycleCollectionTraversalCallback&);
|
||||
virtual void Unlink();
|
||||
virtual void TraverseExtendedSlots(nsCycleCollectionTraversalCallback&);
|
||||
virtual void UnlinkExtendedSlots();
|
||||
|
||||
/**
|
||||
* The nearest enclosing content node with a binding that created us.
|
||||
|
@ -821,11 +821,24 @@ protected:
|
|||
class nsContentSlots : public nsINode::nsSlots
|
||||
{
|
||||
public:
|
||||
nsContentSlots()
|
||||
: nsINode::nsSlots()
|
||||
, mExtendedSlots(0)
|
||||
{
|
||||
}
|
||||
|
||||
~nsContentSlots()
|
||||
{
|
||||
if (!(mExtendedSlots & sNonOwningExtendedSlotsFlag)) {
|
||||
delete GetExtendedContentSlots();
|
||||
}
|
||||
}
|
||||
|
||||
void Traverse(nsCycleCollectionTraversalCallback& aCb) override
|
||||
{
|
||||
nsINode::nsSlots::Traverse(aCb);
|
||||
if (mExtendedSlots) {
|
||||
mExtendedSlots->Traverse(aCb);
|
||||
GetExtendedContentSlots()->TraverseExtendedSlots(aCb);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -833,11 +846,33 @@ protected:
|
|||
{
|
||||
nsINode::nsSlots::Unlink();
|
||||
if (mExtendedSlots) {
|
||||
mExtendedSlots->Unlink();
|
||||
GetExtendedContentSlots()->UnlinkExtendedSlots();
|
||||
}
|
||||
}
|
||||
|
||||
mozilla::UniquePtr<nsExtendedContentSlots> mExtendedSlots;
|
||||
void SetExtendedContentSlots(nsExtendedContentSlots* aSlots, bool aOwning)
|
||||
{
|
||||
mExtendedSlots = reinterpret_cast<uintptr_t>(aSlots);
|
||||
if (!aOwning) {
|
||||
mExtendedSlots |= sNonOwningExtendedSlotsFlag;
|
||||
}
|
||||
}
|
||||
|
||||
bool OwnsExtendedSlots() const
|
||||
{
|
||||
return !(mExtendedSlots & sNonOwningExtendedSlotsFlag);
|
||||
}
|
||||
|
||||
nsExtendedContentSlots* GetExtendedContentSlots() const
|
||||
{
|
||||
return reinterpret_cast<nsExtendedContentSlots*>(
|
||||
mExtendedSlots & ~sNonOwningExtendedSlotsFlag);
|
||||
}
|
||||
|
||||
private:
|
||||
static const uintptr_t sNonOwningExtendedSlotsFlag = 1u;
|
||||
|
||||
uintptr_t mExtendedSlots;
|
||||
};
|
||||
|
||||
// Override from nsINode
|
||||
|
@ -869,22 +904,22 @@ protected:
|
|||
const nsExtendedContentSlots* GetExistingExtendedContentSlots() const
|
||||
{
|
||||
const nsContentSlots* slots = GetExistingContentSlots();
|
||||
return slots ? slots->mExtendedSlots.get() : nullptr;
|
||||
return slots ? slots->GetExtendedContentSlots() : nullptr;
|
||||
}
|
||||
|
||||
nsExtendedContentSlots* GetExistingExtendedContentSlots()
|
||||
{
|
||||
nsContentSlots* slots = GetExistingContentSlots();
|
||||
return slots ? slots->mExtendedSlots.get() : nullptr;
|
||||
return slots ? slots->GetExtendedContentSlots() : nullptr;
|
||||
}
|
||||
|
||||
nsExtendedContentSlots* ExtendedContentSlots()
|
||||
{
|
||||
nsContentSlots* slots = ContentSlots();
|
||||
if (!slots->mExtendedSlots) {
|
||||
slots->mExtendedSlots.reset(CreateExtendedSlots());
|
||||
if (!slots->GetExtendedContentSlots()) {
|
||||
slots->SetExtendedContentSlots(CreateExtendedSlots(), true);
|
||||
}
|
||||
return slots->mExtendedSlots.get();
|
||||
return slots->GetExtendedContentSlots();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -66,6 +66,10 @@ WebCryptoThreadPool::DispatchInternal(nsIRunnable* aRunnable)
|
|||
{
|
||||
MutexAutoLock lock(mMutex);
|
||||
|
||||
if (mShutdown) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
if (!mPool) {
|
||||
NS_ENSURE_TRUE(EnsureNSSInitializedChromeOrContent(), NS_ERROR_FAILURE);
|
||||
|
||||
|
@ -85,10 +89,21 @@ void
|
|||
WebCryptoThreadPool::Shutdown()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread(), "Wrong thread!");
|
||||
MutexAutoLock lock(mMutex);
|
||||
|
||||
if (mPool) {
|
||||
mPool->Shutdown();
|
||||
// Limit the scope of locking to avoid deadlocking if DispatchInternal ends
|
||||
// up getting called during shutdown event processing.
|
||||
nsCOMPtr<nsIThreadPool> pool;
|
||||
{
|
||||
MutexAutoLock lock(mMutex);
|
||||
if (mShutdown) {
|
||||
return;
|
||||
}
|
||||
pool = mPool;
|
||||
mShutdown = true;
|
||||
}
|
||||
|
||||
if (pool) {
|
||||
pool->Shutdown();
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
|
||||
|
|
|
@ -29,6 +29,7 @@ private:
|
|||
WebCryptoThreadPool()
|
||||
: mMutex("WebCryptoThreadPool::mMutex")
|
||||
, mPool(nullptr)
|
||||
, mShutdown(false)
|
||||
{ }
|
||||
virtual ~WebCryptoThreadPool()
|
||||
{ }
|
||||
|
@ -48,6 +49,7 @@ private:
|
|||
|
||||
mozilla::Mutex mMutex;
|
||||
nsCOMPtr<nsIThreadPool> mPool;
|
||||
bool mShutdown;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
|
|
|
@ -429,6 +429,7 @@ UnregisterSensorObserver(SensorType aSensor, ISensorObserver *aObserver) {
|
|||
AssertMainThread();
|
||||
|
||||
if (!gSensorObservers) {
|
||||
HAL_ERR("Un-registering a sensor when none have been registered");
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -18,7 +18,6 @@ namespace hal {
|
|||
* If you add or change any here, do the same in GeckoHalDefines.java.
|
||||
*/
|
||||
enum SensorType {
|
||||
SENSOR_UNKNOWN = -1,
|
||||
SENSOR_ORIENTATION = 0,
|
||||
SENSOR_ACCELERATION = 1,
|
||||
SENSOR_PROXIMITY = 2,
|
||||
|
@ -51,7 +50,7 @@ namespace IPC {
|
|||
struct ParamTraits<mozilla::hal::SensorType>:
|
||||
public ContiguousEnumSerializer<
|
||||
mozilla::hal::SensorType,
|
||||
mozilla::hal::SENSOR_UNKNOWN,
|
||||
mozilla::hal::SENSOR_ORIENTATION,
|
||||
mozilla::hal::NUM_SENSOR_TYPE> {
|
||||
};
|
||||
} // namespace IPC
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include "mozilla/dom/network/Types.h"
|
||||
#include "mozilla/dom/ScreenOrientation.h"
|
||||
#include "mozilla/fallback/FallbackScreenConfiguration.h"
|
||||
#include "mozilla/EnumeratedRange.h"
|
||||
#include "mozilla/Observer.h"
|
||||
#include "mozilla/Unused.h"
|
||||
#include "nsAutoPtr.h"
|
||||
|
@ -232,9 +233,8 @@ public:
|
|||
hal::UnregisterBatteryObserver(this);
|
||||
hal::UnregisterNetworkObserver(this);
|
||||
hal::UnregisterScreenConfigurationObserver(this);
|
||||
for (int32_t sensor = SENSOR_UNKNOWN + 1;
|
||||
sensor < NUM_SENSOR_TYPE; ++sensor) {
|
||||
hal::UnregisterSensorObserver(SensorType(sensor), this);
|
||||
for (auto sensor : MakeEnumeratedRange(NUM_SENSOR_TYPE)) {
|
||||
hal::UnregisterSensorObserver(sensor, this);
|
||||
}
|
||||
hal::UnregisterWakeLockObserver(this);
|
||||
}
|
||||
|
|
|
@ -2816,6 +2816,11 @@ imgLoader::GetMimeTypeFromContent(const char* aContents,
|
|||
!memcmp(aContents, "\000\000\002\000", 4))) {
|
||||
aContentType.AssignLiteral(IMAGE_ICO);
|
||||
|
||||
// WebPs always begin with RIFF, a 32-bit length, and WEBP.
|
||||
} else if (aLength >= 12 && !memcmp(aContents, "RIFF", 4) &&
|
||||
!memcmp(aContents + 8, "WEBP", 4)) {
|
||||
aContentType.AssignLiteral(IMAGE_WEBP);
|
||||
|
||||
} else {
|
||||
/* none of the above? I give up */
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
#include "imgIRequest.h"
|
||||
|
||||
#include "mozilla/IntegerPrintfMacros.h"
|
||||
#include "mozilla/Telemetry.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::image;
|
||||
|
@ -940,6 +941,7 @@ imgRequest::OnStopRequest(nsIRequest* aRequest,
|
|||
struct mimetype_closure
|
||||
{
|
||||
nsACString* newType;
|
||||
uint32_t segmentSize;
|
||||
};
|
||||
|
||||
/* prototype for these defined below */
|
||||
|
@ -986,11 +988,49 @@ PrepareForNewPart(nsIRequest* aRequest, nsIInputStream* aInStr, uint32_t aCount,
|
|||
if (aInStr) {
|
||||
mimetype_closure closure;
|
||||
closure.newType = &result.mContentType;
|
||||
closure.segmentSize = 0;
|
||||
|
||||
// Look at the first few bytes and see if we can tell what the data is from
|
||||
// that since servers tend to lie. :(
|
||||
uint32_t out;
|
||||
aInStr->ReadSegments(sniff_mimetype_callback, &closure, aCount, &out);
|
||||
|
||||
// We don't support WebP but we are getting reports of Firefox being served
|
||||
// WebP content in the wild. In particular this appears to be a problem on
|
||||
// Fennec where content authors assume Android implies WebP support. The
|
||||
// telemetry below is intended to get a sense of how prevalent this is.
|
||||
//
|
||||
// From the Google WebP FAQ example and the Modernizr library, websites may
|
||||
// supply a tiny WebP image to probe for feature support using scripts. The
|
||||
// probes are implemented as data URIs thus we should have all the content
|
||||
// upfront. We don't want to consider a probe as having observed WebP since
|
||||
// in theory the client should do the right thing when we fail to decode it.
|
||||
// See https://developers.google.com/speed/webp/faq for details.
|
||||
bool webp = result.mContentType.EqualsLiteral(IMAGE_WEBP);
|
||||
bool webpProbe = false;
|
||||
if (webp) {
|
||||
// The probes from the example/library are all < 90 bytes. Round it up
|
||||
// just in case.
|
||||
const uint32_t kMaxProbeSize = 100;
|
||||
if (closure.segmentSize < kMaxProbeSize &&
|
||||
NS_FAILED(aURI->SchemeIs("data", &webpProbe))) {
|
||||
webpProbe = false;
|
||||
}
|
||||
|
||||
if (webpProbe) {
|
||||
Telemetry::ScalarSet(Telemetry::ScalarID::IMAGES_WEBP_PROBE_OBSERVED,
|
||||
true);
|
||||
} else {
|
||||
Telemetry::ScalarSet(Telemetry::ScalarID::IMAGES_WEBP_CONTENT_OBSERVED,
|
||||
true);
|
||||
}
|
||||
}
|
||||
|
||||
if (!webpProbe) {
|
||||
Telemetry::ScalarAdd(Telemetry::ScalarID::IMAGES_WEBP_CONTENT_FREQUENCY,
|
||||
webp ? NS_LITERAL_STRING("webp") :
|
||||
NS_LITERAL_STRING("other"), 1);
|
||||
}
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIChannel> chan(do_QueryInterface(aRequest));
|
||||
|
@ -1241,6 +1281,7 @@ sniff_mimetype_callback(nsIInputStream* in,
|
|||
|
||||
NS_ASSERTION(closure, "closure is null!");
|
||||
|
||||
closure->segmentSize = count;
|
||||
if (count > 0) {
|
||||
imgLoader::GetMimeTypeFromContent(fromRawSegment, count, *closure->newType);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,84 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include "Common.h"
|
||||
#include "imgLoader.h"
|
||||
#include "nsMimeTypes.h"
|
||||
#include "nsString.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::image;
|
||||
|
||||
static void
|
||||
CheckMimeType(const char* aContents, size_t aLength, const char* aExpected)
|
||||
{
|
||||
nsAutoCString detected;
|
||||
nsresult rv = imgLoader::GetMimeTypeFromContent(aContents, aLength, detected);
|
||||
if (aExpected) {
|
||||
ASSERT_TRUE(NS_SUCCEEDED(rv));
|
||||
EXPECT_TRUE(detected.EqualsASCII(aExpected));
|
||||
} else {
|
||||
ASSERT_TRUE(NS_FAILED(rv));
|
||||
EXPECT_TRUE(detected.IsEmpty());
|
||||
}
|
||||
}
|
||||
|
||||
class ImageLoader : public ::testing::Test
|
||||
{
|
||||
protected:
|
||||
AutoInitializeImageLib mInit;
|
||||
};
|
||||
|
||||
TEST_F(ImageLoader, DetectGIF)
|
||||
{
|
||||
const char buffer[] = "GIF87a";
|
||||
CheckMimeType(buffer, sizeof(buffer), IMAGE_GIF);
|
||||
}
|
||||
|
||||
TEST_F(ImageLoader, DetectPNG)
|
||||
{
|
||||
const char buffer[] = "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A";
|
||||
CheckMimeType(buffer, sizeof(buffer), IMAGE_PNG);
|
||||
}
|
||||
|
||||
TEST_F(ImageLoader, DetectJPEG)
|
||||
{
|
||||
const char buffer[] = "\xFF\xD8\xFF";
|
||||
CheckMimeType(buffer, sizeof(buffer), IMAGE_JPEG);
|
||||
}
|
||||
|
||||
TEST_F(ImageLoader, DetectART)
|
||||
{
|
||||
const char buffer[] = "\x4A\x47\xFF\xFF\x00";
|
||||
CheckMimeType(buffer, sizeof(buffer), IMAGE_ART);
|
||||
}
|
||||
|
||||
TEST_F(ImageLoader, DetectBMP)
|
||||
{
|
||||
const char buffer[] = "BM";
|
||||
CheckMimeType(buffer, sizeof(buffer), IMAGE_BMP);
|
||||
}
|
||||
|
||||
TEST_F(ImageLoader, DetectICO)
|
||||
{
|
||||
const char buffer[] = "\x00\x00\x01\x00";
|
||||
CheckMimeType(buffer, sizeof(buffer), IMAGE_ICO);
|
||||
}
|
||||
|
||||
TEST_F(ImageLoader, DetectWebP)
|
||||
{
|
||||
const char buffer[] = "RIFF\xFF\xFF\xFF\xFFWEBPVP8L";
|
||||
CheckMimeType(buffer, sizeof(buffer), IMAGE_WEBP);
|
||||
}
|
||||
|
||||
TEST_F(ImageLoader, DetectNone)
|
||||
{
|
||||
const char buffer[] = "abcdefghijklmnop";
|
||||
CheckMimeType(buffer, sizeof(buffer), nullptr);
|
||||
}
|
||||
|
|
@ -15,6 +15,7 @@ UNIFIED_SOURCES = [
|
|||
'TestDecoders.cpp',
|
||||
'TestDecodeToSurface.cpp',
|
||||
'TestDeinterlacingFilter.cpp',
|
||||
'TestLoader.cpp',
|
||||
'TestMetadata.cpp',
|
||||
'TestRemoveFrameRectFilter.cpp',
|
||||
'TestSourceBuffer.cpp',
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
|
||||
#include "js/AllocPolicy.h"
|
||||
#include "js/UbiNodeBreadthFirst.h"
|
||||
#include "js/UniquePtr.h"
|
||||
#include "js/Vector.h"
|
||||
|
||||
namespace JS {
|
||||
|
@ -28,7 +29,7 @@ struct JS_PUBLIC_API(BackEdge)
|
|||
EdgeName name_;
|
||||
|
||||
public:
|
||||
using Ptr = mozilla::UniquePtr<BackEdge, JS::DeletePolicy<BackEdge>>;
|
||||
using Ptr = js::UniquePtr<BackEdge>;
|
||||
|
||||
BackEdge() : predecessor_(), name_(nullptr) { }
|
||||
|
||||
|
@ -147,7 +148,7 @@ struct JS_PUBLIC_API(ShortestPaths)
|
|||
"saw it.");
|
||||
|
||||
if (ptr->value().length() < shortestPaths.maxNumPaths_) {
|
||||
BackEdge::Ptr thisBackEdge(js_new<BackEdge>());
|
||||
auto thisBackEdge = js::MakeUnique<BackEdge>();
|
||||
if (!thisBackEdge || !thisBackEdge->init(origin, edge))
|
||||
return false;
|
||||
ptr->value().infallibleAppend(std::move(thisBackEdge));
|
||||
|
|
|
@ -306,11 +306,10 @@ MapIteratorObject::objectMoved(JSObject* obj, JSObject* old)
|
|||
}
|
||||
|
||||
AutoEnterOOMUnsafeRegion oomUnsafe;
|
||||
auto newRange = iter->zone()->pod_malloc<ValueMap::Range>();
|
||||
auto newRange = iter->zone()->new_<ValueMap::Range>(*range);
|
||||
if (!newRange)
|
||||
oomUnsafe.crash("MapIteratorObject failed to allocate Range data while tenuring.");
|
||||
|
||||
new (newRange) ValueMap::Range(*range);
|
||||
range->~Range();
|
||||
iter->setReservedSlot(MapIteratorObject::RangeSlot, PrivateValue(newRange));
|
||||
return sizeof(ValueMap::Range);
|
||||
|
@ -1161,11 +1160,10 @@ SetIteratorObject::objectMoved(JSObject* obj, JSObject* old)
|
|||
}
|
||||
|
||||
AutoEnterOOMUnsafeRegion oomUnsafe;
|
||||
auto newRange = iter->zone()->pod_malloc<ValueSet::Range>();
|
||||
auto newRange = iter->zone()->new_<ValueSet::Range>(*range);
|
||||
if (!newRange)
|
||||
oomUnsafe.crash("SetIteratorObject failed to allocate Range data while tenuring.");
|
||||
|
||||
new (newRange) ValueSet::Range(*range);
|
||||
range->~Range();
|
||||
iter->setReservedSlot(SetIteratorObject::RangeSlot, PrivateValue(newRange));
|
||||
return sizeof(ValueSet::Range);
|
||||
|
|
|
@ -28,6 +28,8 @@
|
|||
# define getpid _getpid
|
||||
#endif
|
||||
|
||||
#include "js/Utility.h"
|
||||
#include "util/Text.h"
|
||||
#include "vm/Probes.h"
|
||||
|
||||
#include "vm/JSContext-inl.h"
|
||||
|
@ -188,27 +190,21 @@ JS_DumpProfile(const char* outfile, const char* profileName)
|
|||
|
||||
#ifdef MOZ_PROFILING
|
||||
|
||||
struct RequiredStringArg {
|
||||
JSContext* mCx;
|
||||
char* mBytes;
|
||||
RequiredStringArg(JSContext* cx, const CallArgs& args, size_t argi, const char* caller)
|
||||
: mCx(cx), mBytes(nullptr)
|
||||
{
|
||||
if (args.length() <= argi) {
|
||||
JS_ReportErrorASCII(cx, "%s: not enough arguments", caller);
|
||||
} else if (!args[argi].isString()) {
|
||||
JS_ReportErrorASCII(cx, "%s: invalid arguments (string expected)", caller);
|
||||
} else {
|
||||
mBytes = JS_EncodeString(cx, args[argi].toString());
|
||||
}
|
||||
static UniqueChars
|
||||
RequiredStringArg(JSContext* cx, const CallArgs& args, size_t argi, const char* caller)
|
||||
{
|
||||
if (args.length() <= argi) {
|
||||
JS_ReportErrorASCII(cx, "%s: not enough arguments", caller);
|
||||
return nullptr;
|
||||
}
|
||||
operator void*() {
|
||||
return (void*) mBytes;
|
||||
|
||||
if (!args[argi].isString()) {
|
||||
JS_ReportErrorASCII(cx, "%s: invalid arguments (string expected)", caller);
|
||||
return nullptr;
|
||||
}
|
||||
~RequiredStringArg() {
|
||||
js_free(mBytes);
|
||||
}
|
||||
};
|
||||
|
||||
return UniqueChars(JS_EncodeString(cx, args[argi].toString()));
|
||||
}
|
||||
|
||||
static bool
|
||||
StartProfiling(JSContext* cx, unsigned argc, Value* vp)
|
||||
|
@ -219,12 +215,12 @@ StartProfiling(JSContext* cx, unsigned argc, Value* vp)
|
|||
return true;
|
||||
}
|
||||
|
||||
RequiredStringArg profileName(cx, args, 0, "startProfiling");
|
||||
UniqueChars profileName = RequiredStringArg(cx, args, 0, "startProfiling");
|
||||
if (!profileName)
|
||||
return false;
|
||||
|
||||
if (args.length() == 1) {
|
||||
args.rval().setBoolean(JS_StartProfiling(profileName.mBytes, getpid()));
|
||||
args.rval().setBoolean(JS_StartProfiling(profileName.get(), getpid()));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -233,7 +229,7 @@ StartProfiling(JSContext* cx, unsigned argc, Value* vp)
|
|||
return false;
|
||||
}
|
||||
pid_t pid = static_cast<pid_t>(args[1].toInt32());
|
||||
args.rval().setBoolean(JS_StartProfiling(profileName.mBytes, pid));
|
||||
args.rval().setBoolean(JS_StartProfiling(profileName.get(), pid));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -246,10 +242,10 @@ StopProfiling(JSContext* cx, unsigned argc, Value* vp)
|
|||
return true;
|
||||
}
|
||||
|
||||
RequiredStringArg profileName(cx, args, 0, "stopProfiling");
|
||||
UniqueChars profileName = RequiredStringArg(cx, args, 0, "stopProfiling");
|
||||
if (!profileName)
|
||||
return false;
|
||||
args.rval().setBoolean(JS_StopProfiling(profileName.mBytes));
|
||||
args.rval().setBoolean(JS_StopProfiling(profileName.get()));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -262,10 +258,10 @@ PauseProfilers(JSContext* cx, unsigned argc, Value* vp)
|
|||
return true;
|
||||
}
|
||||
|
||||
RequiredStringArg profileName(cx, args, 0, "pauseProfiling");
|
||||
UniqueChars profileName = RequiredStringArg(cx, args, 0, "pauseProfiling");
|
||||
if (!profileName)
|
||||
return false;
|
||||
args.rval().setBoolean(JS_PauseProfilers(profileName.mBytes));
|
||||
args.rval().setBoolean(JS_PauseProfilers(profileName.get()));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -278,10 +274,10 @@ ResumeProfilers(JSContext* cx, unsigned argc, Value* vp)
|
|||
return true;
|
||||
}
|
||||
|
||||
RequiredStringArg profileName(cx, args, 0, "resumeProfiling");
|
||||
UniqueChars profileName = RequiredStringArg(cx, args, 0, "resumeProfiling");
|
||||
if (!profileName)
|
||||
return false;
|
||||
args.rval().setBoolean(JS_ResumeProfilers(profileName.mBytes));
|
||||
args.rval().setBoolean(JS_ResumeProfilers(profileName.get()));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -294,18 +290,18 @@ DumpProfile(JSContext* cx, unsigned argc, Value* vp)
|
|||
if (args.length() == 0) {
|
||||
ret = JS_DumpProfile(nullptr, nullptr);
|
||||
} else {
|
||||
RequiredStringArg filename(cx, args, 0, "dumpProfile");
|
||||
UniqueChars filename = RequiredStringArg(cx, args, 0, "dumpProfile");
|
||||
if (!filename)
|
||||
return false;
|
||||
|
||||
if (args.length() == 1) {
|
||||
ret = JS_DumpProfile(filename.mBytes, nullptr);
|
||||
ret = JS_DumpProfile(filename.get(), nullptr);
|
||||
} else {
|
||||
RequiredStringArg profileName(cx, args, 1, "dumpProfile");
|
||||
UniqueChars profileName = RequiredStringArg(cx, args, 1, "dumpProfile");
|
||||
if (!profileName)
|
||||
return false;
|
||||
|
||||
ret = JS_DumpProfile(filename.mBytes, profileName.mBytes);
|
||||
ret = JS_DumpProfile(filename.get(), profileName.get());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -367,11 +363,11 @@ DumpCallgrind(JSContext* cx, unsigned argc, Value* vp)
|
|||
return true;
|
||||
}
|
||||
|
||||
RequiredStringArg outFile(cx, args, 0, "dumpCallgrind");
|
||||
UniqueChars outFile = RequiredStringArg(cx, args, 0, "dumpCallgrind");
|
||||
if (!outFile)
|
||||
return false;
|
||||
|
||||
args.rval().setBoolean(js_DumpCallgrind(outFile.mBytes));
|
||||
args.rval().setBoolean(js_DumpCallgrind(outFile.get()));
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
@ -547,10 +543,9 @@ bool js_StartPerf()
|
|||
flags = "--call-graph";
|
||||
}
|
||||
|
||||
UniqueChars flags2((char*)js_malloc(strlen(flags) + 1));
|
||||
UniqueChars flags2 = DuplicateString(flags);
|
||||
if (!flags2)
|
||||
return false;
|
||||
strcpy(flags2.get(), flags);
|
||||
|
||||
// Split |flags2| on spaces.
|
||||
char* toksave;
|
||||
|
|
|
@ -192,12 +192,7 @@ class MOZ_NON_PARAM InlineCharBuffer
|
|||
MOZ_ASSERT(heapStorage, "heap storage was not allocated for non-inline string");
|
||||
|
||||
heapStorage.get()[length] = '\0'; // Null-terminate
|
||||
JSString* res = NewStringDontDeflate<CanGC>(cx, heapStorage.get(), length);
|
||||
if (!res)
|
||||
return nullptr;
|
||||
|
||||
mozilla::Unused << heapStorage.release();
|
||||
return res;
|
||||
return NewStringDontDeflate<CanGC>(cx, std::move(heapStorage), length);
|
||||
}
|
||||
|
||||
JSString* toString(JSContext* cx, size_t length)
|
||||
|
@ -214,12 +209,7 @@ class MOZ_NON_PARAM InlineCharBuffer
|
|||
MOZ_ASSERT(heapStorage, "heap storage was not allocated for non-inline string");
|
||||
|
||||
heapStorage.get()[length] = '\0'; // Null-terminate
|
||||
JSString* res = NewString<CanGC>(cx, heapStorage.get(), length);
|
||||
if (!res)
|
||||
return nullptr;
|
||||
|
||||
mozilla::Unused << heapStorage.release();
|
||||
return res;
|
||||
return NewString<CanGC>(cx, std::move(heapStorage), length);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -3558,7 +3548,7 @@ js::str_fromCodePoint(JSContext* cx, unsigned argc, Value* vp)
|
|||
// Step 3.
|
||||
static_assert(ARGS_LENGTH_MAX < std::numeric_limits<decltype(args.length())>::max() / 2,
|
||||
"|args.length() * 2 + 1| does not overflow");
|
||||
char16_t* elements = cx->pod_malloc<char16_t>(args.length() * 2 + 1);
|
||||
auto elements = cx->make_pod_array<char16_t>(args.length() * 2 + 1);
|
||||
if (!elements)
|
||||
return false;
|
||||
|
||||
|
@ -3567,22 +3557,18 @@ js::str_fromCodePoint(JSContext* cx, unsigned argc, Value* vp)
|
|||
for (unsigned nextIndex = 0; nextIndex < args.length(); nextIndex++) {
|
||||
// Steps 5.a-d.
|
||||
uint32_t codePoint;
|
||||
if (!ToCodePoint(cx, args[nextIndex], &codePoint)) {
|
||||
js_free(elements);
|
||||
if (!ToCodePoint(cx, args[nextIndex], &codePoint))
|
||||
return false;
|
||||
}
|
||||
|
||||
// Step 5.e.
|
||||
unicode::UTF16Encode(codePoint, elements, &length);
|
||||
unicode::UTF16Encode(codePoint, elements.get(), &length);
|
||||
}
|
||||
elements[length] = 0;
|
||||
|
||||
// Step 6.
|
||||
JSString* str = NewString<CanGC>(cx, elements, length);
|
||||
if (!str) {
|
||||
js_free(elements);
|
||||
JSString* str = NewString<CanGC>(cx, std::move(elements), length);
|
||||
if (!str)
|
||||
return false;
|
||||
}
|
||||
|
||||
args.rval().setString(str);
|
||||
return true;
|
||||
|
|
|
@ -1438,7 +1438,7 @@ NewExternalString(JSContext* cx, unsigned argc, Value* vp)
|
|||
RootedString str(cx, args[0].toString());
|
||||
size_t len = str->length();
|
||||
|
||||
UniqueTwoByteChars buf(cx->pod_malloc<char16_t>(len));
|
||||
auto buf = cx->make_pod_array<char16_t>(len);
|
||||
if (!buf)
|
||||
return false;
|
||||
|
||||
|
@ -1467,7 +1467,7 @@ NewMaybeExternalString(JSContext* cx, unsigned argc, Value* vp)
|
|||
RootedString str(cx, args[0].toString());
|
||||
size_t len = str->length();
|
||||
|
||||
UniqueTwoByteChars buf(cx->pod_malloc<char16_t>(len));
|
||||
auto buf = cx->make_pod_array<char16_t>(len);
|
||||
if (!buf)
|
||||
return false;
|
||||
|
||||
|
@ -2435,13 +2435,9 @@ ReadGeckoProfilingStack(JSContext* cx, unsigned argc, Value* vp)
|
|||
if (!JS_DefineProperty(cx, inlineFrameInfo, "kind", frameKind, propAttrs))
|
||||
return false;
|
||||
|
||||
size_t length = strlen(inlineFrame.label.get());
|
||||
auto* label = reinterpret_cast<Latin1Char*>(inlineFrame.label.release());
|
||||
frameLabel = NewString<CanGC>(cx, label, length);
|
||||
if (!frameLabel) {
|
||||
js_free(label);
|
||||
frameLabel = NewLatin1StringZ(cx, std::move(inlineFrame.label));
|
||||
if (!frameLabel)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!JS_DefineProperty(cx, inlineFrameInfo, "label", frameLabel, propAttrs))
|
||||
return false;
|
||||
|
@ -2927,7 +2923,7 @@ class CloneBufferObject : public NativeObject {
|
|||
return false;
|
||||
|
||||
size_t size = data->Size();
|
||||
UniqueChars buffer(static_cast<char*>(js_malloc(size)));
|
||||
UniqueChars buffer(js_pod_malloc<char>(size));
|
||||
if (!buffer) {
|
||||
ReportOutOfMemory(cx);
|
||||
return false;
|
||||
|
@ -2957,7 +2953,7 @@ class CloneBufferObject : public NativeObject {
|
|||
return false;
|
||||
|
||||
size_t size = data->Size();
|
||||
UniqueChars buffer(static_cast<char*>(js_malloc(size)));
|
||||
UniqueChars buffer(js_pod_malloc<char>(size));
|
||||
if (!buffer) {
|
||||
ReportOutOfMemory(cx);
|
||||
return false;
|
||||
|
@ -3645,10 +3641,10 @@ FindPath(JSContext* cx, unsigned argc, Value* vp)
|
|||
|
||||
heaptools::EdgeName edgeName = std::move(edges[i]);
|
||||
|
||||
RootedString edgeStr(cx, NewString<CanGC>(cx, edgeName.get(), js_strlen(edgeName.get())));
|
||||
size_t edgeNameLength = js_strlen(edgeName.get());
|
||||
RootedString edgeStr(cx, NewString<CanGC>(cx, std::move(edgeName), edgeNameLength));
|
||||
if (!edgeStr)
|
||||
return false;
|
||||
mozilla::Unused << edgeName.release(); // edgeStr acquired ownership
|
||||
|
||||
if (!JS_DefineProperty(cx, obj, "edge", edgeStr, JSPROP_ENUMERATE))
|
||||
return false;
|
||||
|
@ -4347,18 +4343,16 @@ GetLcovInfo(JSContext* cx, unsigned argc, Value* vp)
|
|||
}
|
||||
|
||||
size_t length = 0;
|
||||
char* content = nullptr;
|
||||
UniqueChars content;
|
||||
{
|
||||
AutoRealm ar(cx, global);
|
||||
content = js::GetCodeCoverageSummary(cx, &length);
|
||||
content.reset(js::GetCodeCoverageSummary(cx, &length));
|
||||
}
|
||||
|
||||
if (!content)
|
||||
return false;
|
||||
|
||||
JSString* str = JS_NewStringCopyN(cx, content, length);
|
||||
js_free(content);
|
||||
|
||||
JSString* str = JS_NewStringCopyN(cx, content.get(), length);
|
||||
if (!str)
|
||||
return false;
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include "mozilla/MemoryReporting.h"
|
||||
#include "mozilla/Sprintf.h"
|
||||
#include "mozilla/TextUtils.h"
|
||||
#include "mozilla/Unused.h"
|
||||
#include "mozilla/Vector.h"
|
||||
#include "mozilla/WrappingOperations.h"
|
||||
|
||||
|
@ -7699,7 +7700,7 @@ CData::Create(JSContext* cx,
|
|||
|
||||
// attach the buffer. since it might not be 2-byte aligned, we need to
|
||||
// allocate an aligned space for it and store it there. :(
|
||||
char** buffer = cx->new_<char*>();
|
||||
UniquePtr<char*, JS::FreePolicy> buffer(cx->new_<char*>());
|
||||
if (!buffer)
|
||||
return nullptr;
|
||||
|
||||
|
@ -7713,7 +7714,6 @@ CData::Create(JSContext* cx,
|
|||
if (!data) {
|
||||
// Report a catchable allocation error.
|
||||
JS_ReportAllocationOverflow(cx);
|
||||
js_free(buffer);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -7723,8 +7723,8 @@ CData::Create(JSContext* cx,
|
|||
memcpy(data, source, size);
|
||||
}
|
||||
|
||||
*buffer = data;
|
||||
JS_SetReservedSlot(dataObj, SLOT_DATA, PrivateValue(buffer));
|
||||
*buffer.get() = data;
|
||||
JS_SetReservedSlot(dataObj, SLOT_DATA, PrivateValue(buffer.release()));
|
||||
|
||||
// If this is an array, wrap it in a proxy so we can intercept element
|
||||
// gets/sets.
|
||||
|
@ -8014,16 +8014,15 @@ ReadStringCommon(JSContext* cx, InflateUTF8Method inflateUTF8, unsigned argc,
|
|||
size_t length = strnlen(bytes, maxLength);
|
||||
|
||||
// Determine the length.
|
||||
char16_t* dst = inflateUTF8(cx, JS::UTF8Chars(bytes, length), &length).get();
|
||||
UniqueTwoByteChars dst(inflateUTF8(cx, JS::UTF8Chars(bytes, length), &length).get());
|
||||
if (!dst)
|
||||
return false;
|
||||
|
||||
result = JS_NewUCString(cx, dst, length);
|
||||
if (!result) {
|
||||
js_free(dst);
|
||||
result = JS_NewUCString(cx, dst.get(), length);
|
||||
if (!result)
|
||||
return false;
|
||||
}
|
||||
|
||||
mozilla::Unused << dst.release();
|
||||
break;
|
||||
}
|
||||
case TYPE_int16_t:
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include "jit/mips64/Simulator-mips64.h"
|
||||
#include "jit/Recover.h"
|
||||
#include "jit/RematerializedFrame.h"
|
||||
#include "js/Utility.h"
|
||||
#include "vm/ArgumentsObject.h"
|
||||
#include "vm/Debugger.h"
|
||||
#include "vm/TraceLogging.h"
|
||||
|
@ -118,7 +119,7 @@ struct BaselineStackBuilder
|
|||
MOZ_MUST_USE bool init() {
|
||||
MOZ_ASSERT(!buffer_);
|
||||
MOZ_ASSERT(bufferUsed_ == 0);
|
||||
buffer_ = reinterpret_cast<uint8_t*>(js_calloc(bufferTotal_));
|
||||
buffer_ = js_pod_calloc<uint8_t>(bufferTotal_);
|
||||
if (!buffer_)
|
||||
return false;
|
||||
bufferAvail_ = bufferTotal_ - HeaderSize();
|
||||
|
@ -148,7 +149,7 @@ struct BaselineStackBuilder
|
|||
if (bufferTotal_ & mozilla::tl::MulOverflowMask<2>::value)
|
||||
return false;
|
||||
size_t newSize = bufferTotal_ * 2;
|
||||
uint8_t* newBuffer = reinterpret_cast<uint8_t*>(js_calloc(newSize));
|
||||
uint8_t* newBuffer = js_pod_calloc<uint8_t>(newSize);
|
||||
if (!newBuffer)
|
||||
return false;
|
||||
memcpy((newBuffer + newSize) - bufferUsed_, header_->copyStackBottom, bufferUsed_);
|
||||
|
@ -1236,20 +1237,19 @@ InitFromBailout(JSContext* cx, size_t frameNo,
|
|||
if (filename == nullptr)
|
||||
filename = "<unknown>";
|
||||
unsigned len = strlen(filename) + 200;
|
||||
char* buf = js_pod_malloc<char>(len);
|
||||
UniqueChars buf(js_pod_malloc<char>(len));
|
||||
if (buf == nullptr) {
|
||||
ReportOutOfMemory(cx);
|
||||
return false;
|
||||
}
|
||||
snprintf(buf, len, "%s %s %s on line %u of %s:%u",
|
||||
snprintf(buf.get(), len, "%s %s %s on line %u of %s:%u",
|
||||
BailoutKindString(bailoutKind),
|
||||
resumeAfter ? "after" : "at",
|
||||
CodeName[op],
|
||||
PCToLineNumber(script, pc),
|
||||
filename,
|
||||
script->lineno());
|
||||
cx->runtime()->geckoProfiler().markEvent(buf);
|
||||
js_free(buf);
|
||||
cx->runtime()->geckoProfiler().markEvent(buf.get());
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
|
@ -5384,7 +5384,7 @@ CodeGenerator::maybeCreateScriptCounts()
|
|||
if (!script)
|
||||
return nullptr;
|
||||
|
||||
UniquePtr<IonScriptCounts> counts(js_new<IonScriptCounts>());
|
||||
auto counts = MakeUnique<IonScriptCounts>();
|
||||
if (!counts || !counts->init(graph.numBlocks()))
|
||||
return nullptr;
|
||||
|
||||
|
@ -5405,7 +5405,7 @@ CodeGenerator::maybeCreateScriptCounts()
|
|||
if (block->entryResumePoint()->caller()) {
|
||||
// Get the filename and line number of the inner script.
|
||||
JSScript* innerScript = block->info().script();
|
||||
description = (char*) js_calloc(200);
|
||||
description = js_pod_calloc<char>(200);
|
||||
if (description) {
|
||||
snprintf(description, 200, "%s:%u",
|
||||
innerScript->filename(), innerScript->lineno());
|
||||
|
|
|
@ -1872,16 +1872,14 @@ GenerateCode(MIRGenerator* mir, LIRGraph* lir)
|
|||
TraceLoggerThread* logger = TraceLoggerForCurrentThread();
|
||||
AutoTraceLog log(logger, TraceLogger_GenerateCode);
|
||||
|
||||
CodeGenerator* codegen = js_new<CodeGenerator>(mir, lir);
|
||||
auto codegen = MakeUnique<CodeGenerator>(mir, lir);
|
||||
if (!codegen)
|
||||
return nullptr;
|
||||
|
||||
if (!codegen->generate()) {
|
||||
js_delete(codegen);
|
||||
if (!codegen->generate())
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return codegen;
|
||||
return codegen.release();
|
||||
}
|
||||
|
||||
CodeGenerator*
|
||||
|
|
|
@ -1413,7 +1413,7 @@ GetPcScript(JSContext* cx, JSScript** scriptRes, jsbytecode** pcRes)
|
|||
|
||||
// Lazily initialize the cache. The allocation may safely fail and will not GC.
|
||||
if (MOZ_UNLIKELY(cx->ionPcScriptCache == nullptr)) {
|
||||
cx->ionPcScriptCache = (PcScriptCache*)js_malloc(sizeof(struct PcScriptCache));
|
||||
cx->ionPcScriptCache = js_pod_malloc<PcScriptCache>();
|
||||
if (cx->ionPcScriptCache)
|
||||
cx->ionPcScriptCache->clear(cx->runtime()->gc.gcNumber());
|
||||
}
|
||||
|
|
|
@ -73,10 +73,7 @@ RematerializedFrame::New(JSContext* cx, uint8_t* top, InlineFrameIterator& iter,
|
|||
if (extraSlots > 0)
|
||||
extraSlots -= 1;
|
||||
|
||||
size_t numBytes = sizeof(RematerializedFrame) + (extraSlots * sizeof(Value));
|
||||
MOZ_ASSERT(numBytes >= sizeof(RematerializedFrame));
|
||||
|
||||
void* buf = cx->pod_calloc<uint8_t>(numBytes);
|
||||
RematerializedFrame* buf = cx->pod_calloc_with_extra<RematerializedFrame, Value>(extraSlots);
|
||||
if (!buf)
|
||||
return nullptr;
|
||||
|
||||
|
|
|
@ -38,6 +38,8 @@
|
|||
#include "jit/arm/Assembler-arm.h"
|
||||
#include "jit/arm/disasm/Constants-arm.h"
|
||||
#include "jit/AtomicOperations.h"
|
||||
#include "js/UniquePtr.h"
|
||||
#include "js/Utility.h"
|
||||
#include "threading/LockGuard.h"
|
||||
#include "vm/Runtime.h"
|
||||
#include "vm/SharedMem.h"
|
||||
|
@ -414,14 +416,12 @@ int64_t Simulator::StopSimAt = -1L;
|
|||
Simulator*
|
||||
Simulator::Create(JSContext* cx)
|
||||
{
|
||||
Simulator* sim = js_new<Simulator>(cx);
|
||||
auto sim = MakeUnique<Simulator>(cx);
|
||||
if (!sim)
|
||||
return nullptr;
|
||||
|
||||
if (!sim->init()) {
|
||||
js_delete(sim);
|
||||
if (!sim->init())
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
char* stopAtStr = getenv("ARM_SIM_STOP_AT");
|
||||
int64_t stopAt;
|
||||
|
@ -430,7 +430,7 @@ Simulator::Create(JSContext* cx)
|
|||
Simulator::StopSimAt = stopAt;
|
||||
}
|
||||
|
||||
return sim;
|
||||
return sim.release();
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -620,7 +620,7 @@ ArmDebugger::redoBreakpoints()
|
|||
static char*
|
||||
ReadLine(const char* prompt)
|
||||
{
|
||||
char* result = nullptr;
|
||||
UniqueChars result;
|
||||
char line_buf[256];
|
||||
int offset = 0;
|
||||
bool keep_going = true;
|
||||
|
@ -629,8 +629,6 @@ ReadLine(const char* prompt)
|
|||
while (keep_going) {
|
||||
if (fgets(line_buf, sizeof(line_buf), stdin) == nullptr) {
|
||||
// fgets got an error. Just give up.
|
||||
if (result)
|
||||
js_delete(result);
|
||||
return nullptr;
|
||||
}
|
||||
int len = strlen(line_buf);
|
||||
|
@ -642,29 +640,28 @@ ReadLine(const char* prompt)
|
|||
if (!result) {
|
||||
// Allocate the initial result and make room for the terminating
|
||||
// '\0'.
|
||||
result = (char*)js_malloc(len + 1);
|
||||
result.reset(js_pod_malloc<char>(len + 1));
|
||||
if (!result)
|
||||
return nullptr;
|
||||
} else {
|
||||
// Allocate a new result with enough room for the new addition.
|
||||
int new_len = offset + len + 1;
|
||||
char* new_result = (char*)js_malloc(new_len);
|
||||
char* new_result = js_pod_malloc<char>(new_len);
|
||||
if (!new_result)
|
||||
return nullptr;
|
||||
// Copy the existing input into the new array and set the new
|
||||
// array as the result.
|
||||
memcpy(new_result, result, offset * sizeof(char));
|
||||
js_free(result);
|
||||
result = new_result;
|
||||
memcpy(new_result, result.get(), offset * sizeof(char));
|
||||
result.reset(new_result);
|
||||
}
|
||||
// Copy the newly read line into the result.
|
||||
memcpy(result + offset, line_buf, len * sizeof(char));
|
||||
memcpy(result.get() + offset, line_buf, len * sizeof(char));
|
||||
offset += len;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(result);
|
||||
result[offset] = '\0';
|
||||
return result;
|
||||
return result.release();
|
||||
}
|
||||
|
||||
|
||||
|
@ -1199,7 +1196,7 @@ Simulator::init()
|
|||
{
|
||||
// Allocate 2MB for the stack. Note that we will only use 1MB, see below.
|
||||
static const size_t stackSize = 2 * 1024*1024;
|
||||
stack_ = reinterpret_cast<char*>(js_malloc(stackSize));
|
||||
stack_ = js_pod_malloc<char>(stackSize);
|
||||
if (!stack_)
|
||||
return false;
|
||||
|
||||
|
@ -1257,7 +1254,7 @@ class Redirection
|
|||
}
|
||||
|
||||
AutoEnterOOMUnsafeRegion oomUnsafe;
|
||||
Redirection* redir = (Redirection*)js_malloc(sizeof(Redirection));
|
||||
Redirection* redir = js_pod_malloc<Redirection>();
|
||||
if (!redir)
|
||||
oomUnsafe.crash("Simulator redirection");
|
||||
new(redir) Redirection(nativeFunction, type);
|
||||
|
|
|
@ -136,7 +136,7 @@ class IdentifierToken : public ValueToken<char*> {
|
|||
public:
|
||||
explicit IdentifierToken(const char* name) {
|
||||
size_t size = strlen(name) + 1;
|
||||
value_ = (char*)js_malloc(size);
|
||||
value_ = js_pod_malloc<char>(size);
|
||||
strncpy(value_, name, size);
|
||||
}
|
||||
virtual ~IdentifierToken() { js_free(value_); }
|
||||
|
@ -244,7 +244,7 @@ class UnknownToken : public Token {
|
|||
public:
|
||||
explicit UnknownToken(const char* arg) {
|
||||
size_t size = strlen(arg) + 1;
|
||||
unknown_ = (char*)js_malloc(size);
|
||||
unknown_ = js_pod_malloc<char>(size);
|
||||
strncpy(unknown_, arg, size);
|
||||
}
|
||||
virtual ~UnknownToken() { js_free(unknown_); }
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include "jit/arm64/vixl/Debugger-vixl.h"
|
||||
#include "jit/arm64/vixl/Simulator-vixl.h"
|
||||
#include "jit/IonTypes.h"
|
||||
#include "js/UniquePtr.h"
|
||||
#include "js/Utility.h"
|
||||
#include "threading/LockGuard.h"
|
||||
#include "vm/Runtime.h"
|
||||
|
@ -124,7 +125,7 @@ void Simulator::init(Decoder* decoder, FILE* stream) {
|
|||
ResetState();
|
||||
|
||||
// Allocate and set up the simulator stack.
|
||||
stack_ = (byte*)js_malloc(stack_size_);
|
||||
stack_ = js_pod_malloc<byte>(stack_size_);
|
||||
if (!stack_) {
|
||||
oom_ = true;
|
||||
return;
|
||||
|
@ -168,19 +169,17 @@ Simulator* Simulator::Create(JSContext* cx) {
|
|||
// FIXME: This just leaks the Decoder object for now, which is probably OK.
|
||||
// FIXME: We should free it at some point.
|
||||
// FIXME: Note that it can't be stored in the SimulatorRuntime due to lifetime conflicts.
|
||||
Simulator *sim;
|
||||
js::UniquePtr<Simulator> sim;
|
||||
if (getenv("USE_DEBUGGER") != nullptr)
|
||||
sim = js_new<Debugger>(cx, decoder, stdout);
|
||||
sim.reset(js_new<Debugger>(cx, decoder, stdout));
|
||||
else
|
||||
sim = js_new<Simulator>(cx, decoder, stdout);
|
||||
sim.reset(js_new<Simulator>(cx, decoder, stdout));
|
||||
|
||||
// Check if Simulator:init ran out of memory.
|
||||
if (sim && sim->oom()) {
|
||||
js_delete(sim);
|
||||
if (sim && sim->oom())
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return sim;
|
||||
return sim.release();
|
||||
}
|
||||
|
||||
|
||||
|
@ -392,7 +391,7 @@ class Redirection
|
|||
}
|
||||
|
||||
js::AutoEnterOOMUnsafeRegion oomUnsafe;
|
||||
Redirection* redir = (Redirection*)js_malloc(sizeof(Redirection));
|
||||
Redirection* redir = js_pod_malloc<Redirection>();
|
||||
if (!redir)
|
||||
oomUnsafe.crash("Simulator redirection");
|
||||
new(redir) Redirection(nativeFunction, type);
|
||||
|
|
|
@ -37,6 +37,8 @@
|
|||
|
||||
#include "jit/AtomicOperations.h"
|
||||
#include "jit/mips32/Assembler-mips32.h"
|
||||
#include "js/UniquePtr.h"
|
||||
#include "js/Utility.h"
|
||||
#include "vm/Runtime.h"
|
||||
#include "wasm/WasmInstance.h"
|
||||
#include "wasm/WasmSignalHandlers.h"
|
||||
|
@ -523,14 +525,12 @@ int Simulator::StopSimAt = -1;
|
|||
Simulator*
|
||||
Simulator::Create(JSContext* cx)
|
||||
{
|
||||
Simulator* sim = js_new<Simulator>();
|
||||
auto sim = MakeUnique<Simulator>();
|
||||
if (!sim)
|
||||
return nullptr;
|
||||
|
||||
if (!sim->init()) {
|
||||
js_delete(sim);
|
||||
if (!sim->init())
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
char* stopAtStr = getenv("MIPS_SIM_STOP_AT");
|
||||
int64_t stopAt;
|
||||
|
@ -539,7 +539,7 @@ Simulator::Create(JSContext* cx)
|
|||
Simulator::StopSimAt = stopAt;
|
||||
}
|
||||
|
||||
return sim;
|
||||
return sim.release();
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -749,7 +749,7 @@ MipsDebugger::printAllRegsIncludingFPU()
|
|||
static char*
|
||||
ReadLine(const char* prompt)
|
||||
{
|
||||
char* result = nullptr;
|
||||
UniqueChars result;
|
||||
char lineBuf[256];
|
||||
int offset = 0;
|
||||
bool keepGoing = true;
|
||||
|
@ -758,8 +758,6 @@ ReadLine(const char* prompt)
|
|||
while (keepGoing) {
|
||||
if (fgets(lineBuf, sizeof(lineBuf), stdin) == nullptr) {
|
||||
// fgets got an error. Just give up.
|
||||
if (result)
|
||||
js_delete(result);
|
||||
return nullptr;
|
||||
}
|
||||
int len = strlen(lineBuf);
|
||||
|
@ -770,29 +768,28 @@ ReadLine(const char* prompt)
|
|||
}
|
||||
if (!result) {
|
||||
// Allocate the initial result and make room for the terminating '\0'
|
||||
result = (char*)js_malloc(len + 1);
|
||||
result.reset(js_pod_malloc<char>(len + 1));
|
||||
if (!result)
|
||||
return nullptr;
|
||||
} else {
|
||||
// Allocate a new result with enough room for the new addition.
|
||||
int new_len = offset + len + 1;
|
||||
char* new_result = (char*)js_malloc(new_len);
|
||||
char* new_result = js_pod_malloc<char>(new_len);
|
||||
if (!new_result)
|
||||
return nullptr;
|
||||
// Copy the existing input into the new array and set the new
|
||||
// array as the result.
|
||||
memcpy(new_result, result, offset * sizeof(char));
|
||||
js_free(result);
|
||||
result = new_result;
|
||||
memcpy(new_result, result.get(), offset * sizeof(char));
|
||||
result.reset(new_result);
|
||||
}
|
||||
// Copy the newly read line into the result.
|
||||
memcpy(result + offset, lineBuf, len * sizeof(char));
|
||||
memcpy(result.get() + offset, lineBuf, len * sizeof(char));
|
||||
offset += len;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(result);
|
||||
result[offset] = '\0';
|
||||
return result;
|
||||
return result.release();
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -1288,7 +1285,7 @@ Simulator::init()
|
|||
{
|
||||
// Allocate 2MB for the stack. Note that we will only use 1MB, see below.
|
||||
static const size_t stackSize = 2 * 1024 * 1024;
|
||||
stack_ = static_cast<char*>(js_malloc(stackSize));
|
||||
stack_ = js_pod_malloc<char>(stackSize);
|
||||
if (!stack_)
|
||||
return false;
|
||||
|
||||
|
@ -1347,7 +1344,7 @@ class Redirection
|
|||
}
|
||||
|
||||
AutoEnterOOMUnsafeRegion oomUnsafe;
|
||||
Redirection* redir = (Redirection*)js_malloc(sizeof(Redirection));
|
||||
Redirection* redir = js_pod_malloc<Redirection>();
|
||||
if (!redir) {
|
||||
oomUnsafe.crash("Simulator redirection");
|
||||
}
|
||||
|
|
|
@ -40,6 +40,8 @@
|
|||
|
||||
#include "jit/AtomicOperations.h"
|
||||
#include "jit/mips64/Assembler-mips64.h"
|
||||
#include "js/UniquePtr.h"
|
||||
#include "js/Utility.h"
|
||||
#include "threading/LockGuard.h"
|
||||
#include "vm/Runtime.h"
|
||||
#include "wasm/WasmInstance.h"
|
||||
|
@ -558,14 +560,12 @@ int64_t Simulator::StopSimAt = -1;
|
|||
Simulator *
|
||||
Simulator::Create(JSContext* cx)
|
||||
{
|
||||
Simulator* sim = js_new<Simulator>();
|
||||
auto sim = MakeUnique<Simulator>();
|
||||
if (!sim)
|
||||
return nullptr;
|
||||
|
||||
if (!sim->init()) {
|
||||
js_delete(sim);
|
||||
if (!sim->init())
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
int64_t stopAt;
|
||||
char* stopAtStr = getenv("MIPS_SIM_STOP_AT");
|
||||
|
@ -574,7 +574,7 @@ Simulator::Create(JSContext* cx)
|
|||
Simulator::StopSimAt = stopAt;
|
||||
}
|
||||
|
||||
return sim;
|
||||
return sim.release();
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -767,7 +767,7 @@ MipsDebugger::printAllRegsIncludingFPU()
|
|||
static char*
|
||||
ReadLine(const char* prompt)
|
||||
{
|
||||
char* result = nullptr;
|
||||
UniqueChars result;
|
||||
char lineBuf[256];
|
||||
int offset = 0;
|
||||
bool keepGoing = true;
|
||||
|
@ -776,8 +776,6 @@ ReadLine(const char* prompt)
|
|||
while (keepGoing) {
|
||||
if (fgets(lineBuf, sizeof(lineBuf), stdin) == nullptr) {
|
||||
// fgets got an error. Just give up.
|
||||
if (result)
|
||||
js_delete(result);
|
||||
return nullptr;
|
||||
}
|
||||
int len = strlen(lineBuf);
|
||||
|
@ -788,29 +786,28 @@ ReadLine(const char* prompt)
|
|||
}
|
||||
if (!result) {
|
||||
// Allocate the initial result and make room for the terminating '\0'
|
||||
result = (char*)js_malloc(len + 1);
|
||||
result.reset(js_pod_malloc<char>(len + 1));
|
||||
if (!result)
|
||||
return nullptr;
|
||||
} else {
|
||||
// Allocate a new result with enough room for the new addition.
|
||||
int new_len = offset + len + 1;
|
||||
char* new_result = (char*)js_malloc(new_len);
|
||||
char* new_result = js_pod_malloc<char>(new_len);
|
||||
if (!new_result)
|
||||
return nullptr;
|
||||
// Copy the existing input into the new array and set the new
|
||||
// array as the result.
|
||||
memcpy(new_result, result, offset * sizeof(char));
|
||||
js_free(result);
|
||||
result = new_result;
|
||||
memcpy(new_result, result.get(), offset * sizeof(char));
|
||||
result.reset(new_result);
|
||||
}
|
||||
// Copy the newly read line into the result.
|
||||
memcpy(result + offset, lineBuf, len * sizeof(char));
|
||||
memcpy(result.get() + offset, lineBuf, len * sizeof(char));
|
||||
offset += len;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(result);
|
||||
result[offset] = '\0';
|
||||
return result;
|
||||
return result.release();
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -1296,7 +1293,7 @@ Simulator::init()
|
|||
{
|
||||
// Allocate 2MB for the stack. Note that we will only use 1MB, see below.
|
||||
static const size_t stackSize = 2 * 1024 * 1024;
|
||||
stack_ = static_cast<char*>(js_malloc(stackSize));
|
||||
stack_ = js_pod_malloc<char>(stackSize);
|
||||
if (!stack_)
|
||||
return false;
|
||||
|
||||
|
@ -1355,7 +1352,7 @@ class Redirection
|
|||
}
|
||||
|
||||
AutoEnterOOMUnsafeRegion oomUnsafe;
|
||||
Redirection* redir = (Redirection*)js_malloc(sizeof(Redirection));
|
||||
Redirection* redir = js_pod_malloc<Redirection>();
|
||||
if (!redir) {
|
||||
oomUnsafe.crash("Simulator redirection");
|
||||
}
|
||||
|
|
|
@ -237,7 +237,7 @@ DisassemblerSpew::Node*
|
|||
DisassemblerSpew::add(const Label* key, uint32_t value)
|
||||
{
|
||||
MOZ_ASSERT(!lookup(key));
|
||||
Node* node = (Node*)js_malloc(sizeof(Node));
|
||||
Node* node = js_pod_malloc<Node>();
|
||||
if (node) {
|
||||
node->key = key;
|
||||
node->value = value;
|
||||
|
|
|
@ -4361,7 +4361,7 @@ JS_BufferIsCompilableUnit(JSContext* cx, HandleObject obj, const char* utf8, siz
|
|||
|
||||
cx->clearPendingException();
|
||||
|
||||
UniquePtr<char16_t> chars
|
||||
UniqueTwoByteChars chars
|
||||
{ JS::UTF8CharsToNewTwoByteCharsZ(cx, JS::UTF8Chars(utf8, length), &length).get() };
|
||||
if (!chars)
|
||||
return true;
|
||||
|
@ -5812,7 +5812,7 @@ JS_NewLatin1String(JSContext* cx, JS::Latin1Char* chars, size_t length)
|
|||
{
|
||||
AssertHeapIsIdle();
|
||||
CHECK_REQUEST(cx);
|
||||
return NewString<CanGC>(cx, chars, length);
|
||||
return NewString(cx, chars, length);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSString*)
|
||||
|
@ -5820,7 +5820,7 @@ JS_NewUCString(JSContext* cx, char16_t* chars, size_t length)
|
|||
{
|
||||
AssertHeapIsIdle();
|
||||
CHECK_REQUEST(cx);
|
||||
return NewString<CanGC>(cx, chars, length);
|
||||
return NewString(cx, chars, length);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSString*)
|
||||
|
@ -5828,7 +5828,7 @@ JS_NewUCStringDontDeflate(JSContext* cx, char16_t* chars, size_t length)
|
|||
{
|
||||
AssertHeapIsIdle();
|
||||
CHECK_REQUEST(cx);
|
||||
return NewStringDontDeflate<CanGC>(cx, chars, length);
|
||||
return NewStringDontDeflate(cx, chars, length);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSString*)
|
||||
|
|
|
@ -374,7 +374,7 @@ namespace JS {
|
|||
* Example use:
|
||||
*
|
||||
* size_t length = 512;
|
||||
* char16_t* chars = static_cast<char16_t*>(js_malloc(sizeof(char16_t) * length));
|
||||
* char16_t* chars = js_pod_malloc<char16_t>(length);
|
||||
* JS::SourceBufferHolder srcBuf(chars, length, JS::SourceBufferHolder::GiveOwnership);
|
||||
* JS::Compile(cx, options, srcBuf);
|
||||
*/
|
||||
|
|
|
@ -86,7 +86,7 @@ ComputeAccurateDecimalInteger(JSContext* cx, const CharT* start, const CharT* en
|
|||
double* dp)
|
||||
{
|
||||
size_t length = end - start;
|
||||
UniqueChars cstr(cx->pod_malloc<char>(length + 1));
|
||||
auto cstr = cx->make_pod_array<char>(length + 1);
|
||||
if (!cstr)
|
||||
return false;
|
||||
|
||||
|
|
|
@ -773,20 +773,11 @@ ReportSysError(JSContext* cx, const char* prefix)
|
|||
if (!errstr)
|
||||
errstr = "unknown error";
|
||||
|
||||
size_t nbytes = strlen(prefix) + strlen(errstr) + 3;
|
||||
char* final = (char*) js_malloc(nbytes);
|
||||
if (!final) {
|
||||
JS_ReportOutOfMemory(cx);
|
||||
return;
|
||||
}
|
||||
|
||||
snprintf(final, nbytes, "%s: %s", prefix, errstr);
|
||||
/*
|
||||
* Use Latin1 variant here because the encoding of the return value of
|
||||
* strerror_s and strerror_r function can be non-UTF-8.
|
||||
*/
|
||||
JS_ReportErrorLatin1(cx, "%s", final);
|
||||
js_free(final);
|
||||
JS_ReportErrorLatin1(cx, "%s: %s", prefix, errstr);
|
||||
}
|
||||
|
||||
static bool
|
||||
|
|
|
@ -884,7 +884,7 @@ InitModuleLoader(JSContext* cx)
|
|||
// the module loader for the current compartment.
|
||||
|
||||
uint32_t srcLen = moduleloader::GetRawScriptsSize();
|
||||
UniqueChars src(cx->pod_malloc<char>(srcLen));
|
||||
auto src = cx->make_pod_array<char>(srcLen);
|
||||
if (!src || !DecompressString(moduleloader::compressedSources, moduleloader::GetCompressedSize(),
|
||||
reinterpret_cast<unsigned char*>(src.get()), srcLen))
|
||||
{
|
||||
|
@ -2128,7 +2128,7 @@ js::shell::FileAsString(JSContext* cx, JS::HandleString pathnameStr)
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
UniqueChars buf(static_cast<char*>(js_malloc(len + 1)));
|
||||
UniqueChars buf(js_pod_malloc<char>(len + 1));
|
||||
if (!buf)
|
||||
return nullptr;
|
||||
|
||||
|
@ -3562,25 +3562,22 @@ EnsureGeckoProfilingStackInstalled(JSContext* cx, ShellContext* sc)
|
|||
struct WorkerInput
|
||||
{
|
||||
JSRuntime* parentRuntime;
|
||||
char16_t* chars;
|
||||
UniqueTwoByteChars chars;
|
||||
size_t length;
|
||||
|
||||
WorkerInput(JSRuntime* parentRuntime, char16_t* chars, size_t length)
|
||||
: parentRuntime(parentRuntime), chars(chars), length(length)
|
||||
WorkerInput(JSRuntime* parentRuntime, UniqueTwoByteChars chars, size_t length)
|
||||
: parentRuntime(parentRuntime), chars(std::move(chars)), length(length)
|
||||
{}
|
||||
|
||||
~WorkerInput() {
|
||||
js_free(chars);
|
||||
}
|
||||
~WorkerInput() = default;
|
||||
};
|
||||
|
||||
static void SetWorkerContextOptions(JSContext* cx);
|
||||
static bool ShellBuildId(JS::BuildIdCharVector* buildId);
|
||||
|
||||
static void
|
||||
WorkerMain(void* arg)
|
||||
WorkerMain(WorkerInput* input)
|
||||
{
|
||||
WorkerInput* input = (WorkerInput*) arg;
|
||||
MOZ_ASSERT(input->parentRuntime);
|
||||
|
||||
JSContext* cx = JS_NewContext(8L * 1024L * 1024L, 2L * 1024L * 1024L, input->parentRuntime);
|
||||
|
@ -3635,7 +3632,7 @@ WorkerMain(void* arg)
|
|||
|
||||
AutoReportException are(cx);
|
||||
RootedScript script(cx);
|
||||
if (!JS::Compile(cx, options, input->chars, input->length, &script))
|
||||
if (!JS::Compile(cx, options, input->chars.get(), input->length, &script))
|
||||
break;
|
||||
RootedValue result(cx);
|
||||
JS_ExecuteScript(cx, script, &result);
|
||||
|
@ -3694,15 +3691,16 @@ EvalInWorker(JSContext* cx, unsigned argc, Value* vp)
|
|||
|
||||
JSLinearString* str = &args[0].toString()->asLinear();
|
||||
|
||||
char16_t* chars = (char16_t*) js_malloc(str->length() * sizeof(char16_t));
|
||||
UniqueTwoByteChars chars(js_pod_malloc<char16_t>(str->length()));
|
||||
if (!chars) {
|
||||
ReportOutOfMemory(cx);
|
||||
return false;
|
||||
}
|
||||
|
||||
CopyChars(chars, *str);
|
||||
CopyChars(chars.get(), *str);
|
||||
|
||||
WorkerInput* input = js_new<WorkerInput>(JS_GetParentRuntime(cx), chars, str->length());
|
||||
WorkerInput* input = js_new<WorkerInput>(JS_GetParentRuntime(cx), std::move(chars),
|
||||
str->length());
|
||||
if (!input) {
|
||||
ReportOutOfMemory(cx);
|
||||
return false;
|
||||
|
@ -5029,7 +5027,7 @@ EscapeForShell(JSContext* cx, AutoCStringVector& argv)
|
|||
newLen++;
|
||||
}
|
||||
|
||||
UniqueChars escaped(cx->pod_malloc<char>(newLen));
|
||||
auto escaped = cx->make_pod_array<char>(newLen);
|
||||
if (!escaped)
|
||||
return false;
|
||||
|
||||
|
|
|
@ -0,0 +1,60 @@
|
|||
// ToNumber(value) is executed for OOB writes when using a direct assignment.
|
||||
function plainSet() {
|
||||
var callCount = 0;
|
||||
var value = {
|
||||
valueOf() {
|
||||
callCount++;
|
||||
return 1;
|
||||
}
|
||||
};
|
||||
|
||||
var N = 100;
|
||||
var ta = new Int32Array(0);
|
||||
for (var i = 0; i < N; ++i)
|
||||
ta[0] = value
|
||||
|
||||
assertEq(callCount, N);
|
||||
}
|
||||
for (var i = 0; i < 2; ++i) plainSet();
|
||||
|
||||
// ToNumber(value) is executed for OOB writes when using Reflect.set(...).
|
||||
function reflectSet() {
|
||||
var callCount = 0;
|
||||
var value = {
|
||||
valueOf() {
|
||||
callCount++;
|
||||
return 1;
|
||||
}
|
||||
};
|
||||
|
||||
var N = 100;
|
||||
var ta = new Int32Array(0);
|
||||
for (var i = 0; i < N; ++i)
|
||||
assertEq(Reflect.set(ta, 0, value), false);
|
||||
|
||||
assertEq(callCount, N);
|
||||
}
|
||||
for (var i = 0; i < 2; ++i) reflectSet();
|
||||
|
||||
// ToNumber(value) is not executed for OOB writes when using Reflect.defineProperty(...).
|
||||
function defineProp() {
|
||||
var callCount = 0;
|
||||
var value = {
|
||||
valueOf() {
|
||||
callCount++;
|
||||
return 1;
|
||||
}
|
||||
};
|
||||
var desc = {value, writable: true, enumerable: true, configurable: false};
|
||||
|
||||
var N = 100;
|
||||
var ta = new Int32Array(0);
|
||||
for (var i = 0; i < N; ++i)
|
||||
assertEq(Reflect.defineProperty(ta, 0, desc), false);
|
||||
|
||||
assertEq(callCount, 0);
|
||||
}
|
||||
for (var i = 0; i < 2; ++i) defineProp();
|
||||
|
||||
if (typeof reportCompare === "function")
|
||||
reportCompare(true, true);
|
|
@ -307,7 +307,7 @@ js_dtobasestr(DtoaState* state, int base, double dinput)
|
|||
MOZ_ASSERT(base >= 2 && base <= 36);
|
||||
|
||||
dval(d) = dinput;
|
||||
buffer = (char*) js_malloc(DTOBASESTR_BUFFER_SIZE);
|
||||
buffer = js_pod_malloc<char>(DTOBASESTR_BUFFER_SIZE);
|
||||
if (!buffer)
|
||||
return nullptr;
|
||||
p = buffer;
|
||||
|
|
|
@ -84,7 +84,7 @@ FinishStringFlat(JSContext* cx, StringBuffer& sb, Buffer& cb)
|
|||
if (!buf)
|
||||
return nullptr;
|
||||
|
||||
JSFlatString* str = NewStringDontDeflate<CanGC>(cx, buf.get(), len);
|
||||
JSFlatString* str = NewStringDontDeflate<CanGC>(cx, std::move(buf), len);
|
||||
if (!str)
|
||||
return nullptr;
|
||||
|
||||
|
@ -94,7 +94,6 @@ FinishStringFlat(JSContext* cx, StringBuffer& sb, Buffer& cb)
|
|||
*/
|
||||
cx->updateMallocCounter(sizeof(CharT) * len);
|
||||
|
||||
mozilla::Unused << buf.release();
|
||||
return str;
|
||||
}
|
||||
|
||||
|
|
|
@ -216,7 +216,7 @@ BigInt::toString(JSContext* cx, BigInt* x, uint8_t radix)
|
|||
MOZ_ASSERT(2 <= radix && radix <= 36);
|
||||
// We need two extra chars for '\0' and potentially '-'.
|
||||
size_t strSize = mpz_sizeinbase(x->num_, 10) + 2;
|
||||
UniqueChars str(static_cast<char*>(js_malloc(strSize)));
|
||||
UniqueChars str(js_pod_malloc<char>(strSize));
|
||||
if (!str) {
|
||||
ReportOutOfMemory(cx);
|
||||
return nullptr;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: set ts=8 sts=4 et sw=4 tw=99:
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
|
@ -95,7 +95,7 @@ const char * const js::CodeName[] = {
|
|||
/************************************************************************/
|
||||
|
||||
static bool
|
||||
DecompileArgumentFromStack(JSContext* cx, int formalIndex, char** res);
|
||||
DecompileArgumentFromStack(JSContext* cx, int formalIndex, UniqueChars* res);
|
||||
|
||||
size_t
|
||||
js::GetVariableBytecodeLength(jsbytecode* pc)
|
||||
|
@ -1652,7 +1652,7 @@ struct ExpressionDecompiler
|
|||
bool quote(JSString* s, uint32_t quote);
|
||||
bool write(const char* s);
|
||||
bool write(JSString* str);
|
||||
bool getOutput(char** out);
|
||||
UniqueChars getOutput();
|
||||
#if defined(DEBUG) || defined(JS_JITSPEW)
|
||||
void setStackDump() {
|
||||
isStackDump = true;
|
||||
|
@ -1725,17 +1725,14 @@ ExpressionDecompiler::decompilePC(jsbytecode* pc, uint8_t defIndex)
|
|||
#endif /* DEBUG */
|
||||
)
|
||||
{
|
||||
char* result;
|
||||
UniqueChars result;
|
||||
if (!DecompileArgumentFromStack(cx, slot, &result))
|
||||
return false;
|
||||
|
||||
// Note that decompiling the argument in the parent frame might
|
||||
// not succeed.
|
||||
if (result) {
|
||||
bool ok = write(result);
|
||||
js_free(result);
|
||||
return ok;
|
||||
}
|
||||
if (result)
|
||||
return write(result.get());
|
||||
}
|
||||
|
||||
JSAtom* atom = getArg(slot);
|
||||
|
@ -2160,16 +2157,16 @@ ExpressionDecompiler::getArg(unsigned slot)
|
|||
MOZ_CRASH("No binding");
|
||||
}
|
||||
|
||||
bool
|
||||
ExpressionDecompiler::getOutput(char** res)
|
||||
UniqueChars
|
||||
ExpressionDecompiler::getOutput()
|
||||
{
|
||||
ptrdiff_t len = sprinter.stringEnd() - sprinter.stringAt(0);
|
||||
*res = cx->pod_malloc<char>(len + 1);
|
||||
if (!*res)
|
||||
return false;
|
||||
js_memcpy(*res, sprinter.stringAt(0), len);
|
||||
(*res)[len] = 0;
|
||||
return true;
|
||||
auto res = cx->make_pod_array<char>(len + 1);
|
||||
if (!res)
|
||||
return nullptr;
|
||||
js_memcpy(res.get(), sprinter.stringAt(0), len);
|
||||
res[len] = 0;
|
||||
return res;
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
@ -2187,13 +2184,11 @@ DecompileAtPCForStackDump(JSContext* cx, HandleScript script,
|
|||
if (!ed.decompilePC(offsetAndDefIndex))
|
||||
return false;
|
||||
|
||||
char* result;
|
||||
if (!ed.getOutput(&result))
|
||||
UniqueChars result = ed.getOutput();
|
||||
if (!result)
|
||||
return false;
|
||||
|
||||
bool ok = sp->put(result);
|
||||
js_free(result);
|
||||
return ok;
|
||||
return sp->put(result.get());
|
||||
}
|
||||
#endif /* defined(DEBUG) || defined(JS_JITSPEW) */
|
||||
|
||||
|
@ -2260,7 +2255,8 @@ FindStartPC(JSContext* cx, const FrameIter& iter, int spindex, int skipStackHits
|
|||
}
|
||||
|
||||
static bool
|
||||
DecompileExpressionFromStack(JSContext* cx, int spindex, int skipStackHits, HandleValue v, char** res)
|
||||
DecompileExpressionFromStack(JSContext* cx, int spindex, int skipStackHits, HandleValue v,
|
||||
UniqueChars* res)
|
||||
{
|
||||
MOZ_ASSERT(spindex < 0 ||
|
||||
spindex == JSDVG_IGNORE_STACK ||
|
||||
|
@ -2303,7 +2299,8 @@ DecompileExpressionFromStack(JSContext* cx, int spindex, int skipStackHits, Hand
|
|||
if (!ed.decompilePC(valuepc, defIndex))
|
||||
return false;
|
||||
|
||||
return ed.getOutput(res);
|
||||
*res = ed.getOutput();
|
||||
return *res != nullptr;
|
||||
}
|
||||
|
||||
UniqueChars
|
||||
|
@ -2312,14 +2309,11 @@ js::DecompileValueGenerator(JSContext* cx, int spindex, HandleValue v,
|
|||
{
|
||||
RootedString fallback(cx, fallbackArg);
|
||||
{
|
||||
char* result;
|
||||
UniqueChars result;
|
||||
if (!DecompileExpressionFromStack(cx, spindex, skipStackHits, v, &result))
|
||||
return nullptr;
|
||||
if (result) {
|
||||
if (strcmp(result, "(intermediate value)"))
|
||||
return UniqueChars(result);
|
||||
js_free(result);
|
||||
}
|
||||
if (result && strcmp(result.get(), "(intermediate value)"))
|
||||
return result;
|
||||
}
|
||||
if (!fallback) {
|
||||
if (v.isUndefined())
|
||||
|
@ -2333,7 +2327,7 @@ js::DecompileValueGenerator(JSContext* cx, int spindex, HandleValue v,
|
|||
}
|
||||
|
||||
static bool
|
||||
DecompileArgumentFromStack(JSContext* cx, int formalIndex, char** res)
|
||||
DecompileArgumentFromStack(JSContext* cx, int formalIndex, UniqueChars* res)
|
||||
{
|
||||
MOZ_ASSERT(formalIndex >= 0);
|
||||
|
||||
|
@ -2398,21 +2392,19 @@ DecompileArgumentFromStack(JSContext* cx, int formalIndex, char** res)
|
|||
if (!ed.decompilePCForStackOperand(current, formalStackIndex))
|
||||
return false;
|
||||
|
||||
return ed.getOutput(res);
|
||||
*res = ed.getOutput();
|
||||
return *res != nullptr;
|
||||
}
|
||||
|
||||
UniqueChars
|
||||
js::DecompileArgument(JSContext* cx, int formalIndex, HandleValue v)
|
||||
{
|
||||
{
|
||||
char* result;
|
||||
UniqueChars result;
|
||||
if (!DecompileArgumentFromStack(cx, formalIndex, &result))
|
||||
return nullptr;
|
||||
if (result) {
|
||||
if (strcmp(result, "(intermediate value)"))
|
||||
return UniqueChars(result);
|
||||
js_free(result);
|
||||
}
|
||||
if (result && strcmp(result.get(), "(intermediate value)"))
|
||||
return result;
|
||||
}
|
||||
if (v.isUndefined())
|
||||
return DuplicateString(cx, js_undefined_str); // Prevent users from seeing "(void 0)"
|
||||
|
@ -2755,11 +2747,10 @@ GetPCCountJSON(JSContext* cx, const ScriptAndCounts& sac, StringBuffer& buf)
|
|||
// defIndex passed here is not used.
|
||||
if (!ed.decompilePC(pc, /* defIndex = */ 0))
|
||||
return false;
|
||||
char* text;
|
||||
if (!ed.getOutput(&text))
|
||||
UniqueChars text = ed.getOutput();
|
||||
if (!text)
|
||||
return false;
|
||||
JSString* str = JS_NewStringCopyZ(cx, text);
|
||||
js_free(text);
|
||||
JSString* str = NewLatin1StringZ(cx, std::move(text));
|
||||
if (!AppendJSONProperty(buf, "text"))
|
||||
return false;
|
||||
if (!str || !(str = StringToSource(cx, str)))
|
||||
|
|
|
@ -17,7 +17,7 @@ RuntimeCaches::createMathCache(JSContext* cx)
|
|||
{
|
||||
MOZ_ASSERT(!mathCache_);
|
||||
|
||||
UniquePtr<MathCache> newMathCache(js_new<MathCache>());
|
||||
auto newMathCache = MakeUnique<MathCache>();
|
||||
if (!newMathCache) {
|
||||
ReportOutOfMemory(cx);
|
||||
return nullptr;
|
||||
|
|
|
@ -131,22 +131,14 @@ CopyStringPure(JSContext* cx, JSString* str)
|
|||
if (!copiedChars)
|
||||
return nullptr;
|
||||
|
||||
auto* rawCopiedChars = copiedChars.release();
|
||||
auto* result = NewString<CanGC>(cx, rawCopiedChars, len);
|
||||
if (!result)
|
||||
js_free(rawCopiedChars);
|
||||
return result;
|
||||
return NewString<CanGC>(cx, std::move(copiedChars), len);
|
||||
}
|
||||
|
||||
UniqueTwoByteChars copiedChars = str->asRope().copyTwoByteCharsZ(cx);
|
||||
if (!copiedChars)
|
||||
return nullptr;
|
||||
|
||||
auto* rawCopiedChars = copiedChars.release();
|
||||
auto* result = NewStringDontDeflate<CanGC>(cx, rawCopiedChars, len);
|
||||
if (!result)
|
||||
js_free(rawCopiedChars);
|
||||
return result;
|
||||
return NewStringDontDeflate<CanGC>(cx, std::move(copiedChars), len);
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
|
@ -455,11 +455,7 @@ ParseTask::finish(JSContext* cx)
|
|||
return true;
|
||||
}
|
||||
|
||||
ParseTask::~ParseTask()
|
||||
{
|
||||
for (size_t i = 0; i < errors.length(); i++)
|
||||
js_delete(errors[i]);
|
||||
}
|
||||
ParseTask::~ParseTask() = default;
|
||||
|
||||
void
|
||||
ParseTask::trace(JSTracer* trc)
|
||||
|
@ -2059,11 +2055,12 @@ JSContext::addPendingCompileError(js::CompileError** error)
|
|||
auto errorPtr = make_unique<js::CompileError>();
|
||||
if (!errorPtr)
|
||||
return false;
|
||||
if (!helperThread()->parseTask()->errors.append(errorPtr.get())) {
|
||||
ParseTask* parseTask = helperThread()->parseTask();
|
||||
if (!parseTask->errors.append(std::move(errorPtr))) {
|
||||
ReportOutOfMemory(this);
|
||||
return false;
|
||||
}
|
||||
*error = errorPtr.release();
|
||||
*error = parseTask->errors.back().get();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -692,7 +692,7 @@ struct ParseTask : public mozilla::LinkedListElement<ParseTask>, public JS::OffT
|
|||
|
||||
// Any errors or warnings produced during compilation. These are reported
|
||||
// when finishing the script.
|
||||
Vector<CompileError*, 0, SystemAllocPolicy> errors;
|
||||
Vector<UniquePtr<CompileError>, 0, SystemAllocPolicy> errors;
|
||||
bool overRecursed;
|
||||
bool outOfMemory;
|
||||
|
||||
|
|
|
@ -745,6 +745,7 @@ js::XDRAtom(XDRState<mode>* xdr, MutableHandleAtom atomp)
|
|||
*/
|
||||
char16_t* chars;
|
||||
char16_t stackChars[256];
|
||||
UniqueTwoByteChars heapChars;
|
||||
if (length <= ArrayLength(stackChars)) {
|
||||
chars = stackChars;
|
||||
} else {
|
||||
|
@ -753,15 +754,15 @@ js::XDRAtom(XDRState<mode>* xdr, MutableHandleAtom atomp)
|
|||
* most allocations here will be bigger than tempLifoAlloc's default
|
||||
* chunk size.
|
||||
*/
|
||||
chars = cx->pod_malloc<char16_t>(length);
|
||||
if (!chars)
|
||||
heapChars.reset(cx->pod_malloc<char16_t>(length));
|
||||
if (!heapChars)
|
||||
return xdr->fail(JS::TranscodeResult_Throw);
|
||||
|
||||
chars = heapChars.get();
|
||||
}
|
||||
|
||||
MOZ_TRY(xdr->codeChars(chars, length));
|
||||
atom = AtomizeChars(cx, chars, length);
|
||||
if (chars != stackChars)
|
||||
js_free(chars);
|
||||
#endif /* !MOZ_LITTLE_ENDIAN */
|
||||
}
|
||||
|
||||
|
|
|
@ -2137,7 +2137,7 @@ ScriptSource::performXDR(XDRState<mode>* xdr)
|
|||
|
||||
size_t byteLen = compressedLength ? compressedLength : (len * sizeof(char16_t));
|
||||
if (mode == XDR_DECODE) {
|
||||
UniqueChars bytes(xdr->cx()->template pod_malloc<char>(Max<size_t>(byteLen, 1)));
|
||||
auto bytes = xdr->cx()->template make_pod_array<char>(Max<size_t>(byteLen, 1));
|
||||
if (!bytes)
|
||||
return xdr->fail(JS::TranscodeResult_Throw);
|
||||
MOZ_TRY(xdr->codeBytes(bytes.get(), byteLen));
|
||||
|
|
|
@ -1938,13 +1938,31 @@ DefineNonexistentProperty(JSContext* cx, HandleNativeObject obj, HandleId id,
|
|||
return result.fail(JSMSG_CANT_DEFINE_PAST_ARRAY_LENGTH);
|
||||
}
|
||||
} else if (obj->is<TypedArrayObject>()) {
|
||||
// 9.4.5.3 step 3. Indexed properties of typed arrays are special.
|
||||
// 9.4.5.5 step 2. Indexed properties of typed arrays are special.
|
||||
uint64_t index;
|
||||
if (IsTypedArrayIndex(id, &index)) {
|
||||
// ES2019 draft rev e7dc63fb5d1c26beada9ffc12dc78aa6548f1fb5
|
||||
// 9.4.5.9 IntegerIndexedElementSet
|
||||
|
||||
// This method is only called for non-existent properties, which
|
||||
// means any absent indexed property must be out of range.
|
||||
MOZ_ASSERT(index >= obj->as<TypedArrayObject>().length());
|
||||
|
||||
// Steps 1-2 are enforced by the caller.
|
||||
|
||||
// Step 3.
|
||||
// We still need to call ToNumber, because of its possible side
|
||||
// effects.
|
||||
double d;
|
||||
if (!ToNumber(cx, v, &d))
|
||||
return false;
|
||||
|
||||
// Steps 4-5.
|
||||
// ToNumber may have detached the array buffer.
|
||||
if (obj->as<TypedArrayObject>().hasDetachedBuffer())
|
||||
return result.failSoft(JSMSG_TYPED_ARRAY_DETACHED);
|
||||
|
||||
// Steps 6-9.
|
||||
// We (wrongly) ignore out of range defines.
|
||||
return result.failSoft(JSMSG_BAD_INDEX);
|
||||
}
|
||||
|
@ -2645,10 +2663,19 @@ SetDenseOrTypedArrayElement(JSContext* cx, HandleNativeObject obj, uint32_t inde
|
|||
ObjectOpResult& result)
|
||||
{
|
||||
if (obj->is<TypedArrayObject>()) {
|
||||
// ES2019 draft rev e7dc63fb5d1c26beada9ffc12dc78aa6548f1fb5
|
||||
// 9.4.5.9 IntegerIndexedElementSet
|
||||
|
||||
// Steps 1-2 are enforced by the caller.
|
||||
|
||||
// Step 3.
|
||||
double d;
|
||||
if (!ToNumber(cx, v, &d))
|
||||
return false;
|
||||
|
||||
// Steps 6-7 don't apply for existing typed array elements.
|
||||
|
||||
// Steps 8-16.
|
||||
// Silently do nothing for out-of-bounds sets, for consistency with
|
||||
// current behavior. (ES6 currently says to throw for this in
|
||||
// strict mode code, so we may eventually need to change.)
|
||||
|
@ -2658,6 +2685,7 @@ SetDenseOrTypedArrayElement(JSContext* cx, HandleNativeObject obj, uint32_t inde
|
|||
return result.succeed();
|
||||
}
|
||||
|
||||
// Steps 4-5.
|
||||
// A previously existing typed array element can only be out-of-bounds
|
||||
// if the above ToNumber call detached the typed array's buffer.
|
||||
MOZ_ASSERT(obj->as<TypedArrayObject>().hasDetachedBuffer());
|
||||
|
|
|
@ -1252,14 +1252,13 @@ ObjectGroup::newPlainObject(JSContext* cx, IdValuePair* properties, size_t nprop
|
|||
group->setPreliminaryObjects(preliminaryObjects);
|
||||
preliminaryObjects->registerNewObject(obj);
|
||||
|
||||
UniquePtr<jsid[], JS::FreePolicy> ids(group->zone()->pod_calloc<jsid>(nproperties));
|
||||
auto ids = group->zone()->make_zeroed_pod_array<jsid>(nproperties);
|
||||
if (!ids) {
|
||||
ReportOutOfMemory(cx);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
UniquePtr<TypeSet::Type[], JS::FreePolicy> types(
|
||||
group->zone()->pod_calloc<TypeSet::Type>(nproperties));
|
||||
auto types = group->zone()->make_zeroed_pod_array<TypeSet::Type>(nproperties);
|
||||
if (!types) {
|
||||
ReportOutOfMemory(cx);
|
||||
return nullptr;
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include "jsutil.h"
|
||||
|
||||
#include "ds/LifoAlloc.h"
|
||||
#include "util/Text.h"
|
||||
#include "util/Windows.h"
|
||||
#include "vm/JSContext.h"
|
||||
|
||||
|
@ -124,7 +125,7 @@ bool
|
|||
Sprinter::init()
|
||||
{
|
||||
MOZ_ASSERT(!initialized);
|
||||
base = (char*) js_malloc(DefaultSize);
|
||||
base = js_pod_malloc<char>(DefaultSize);
|
||||
if (!base) {
|
||||
reportOutOfMemory();
|
||||
return false;
|
||||
|
@ -447,13 +448,11 @@ Fprinter::put(const char* s, size_t len)
|
|||
}
|
||||
#ifdef XP_WIN32
|
||||
if ((file_ == stderr) && (IsDebuggerPresent())) {
|
||||
UniqueChars buf(static_cast<char*>(js_malloc(len + 1)));
|
||||
UniqueChars buf = DuplicateString(s, len);
|
||||
if (!buf) {
|
||||
reportOutOfMemory();
|
||||
return false;
|
||||
}
|
||||
PodCopy(buf.get(), s, len);
|
||||
buf[len] = '\0';
|
||||
OutputDebugStringA(buf.get());
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -322,7 +322,7 @@ JSRuntime::destroyRuntime()
|
|||
|
||||
js_delete(defaultFreeOp_.ref());
|
||||
|
||||
js_free(defaultLocale);
|
||||
defaultLocale = nullptr;
|
||||
js_delete(jitRuntime_.ref());
|
||||
|
||||
#ifdef DEBUG
|
||||
|
@ -532,27 +532,25 @@ JSRuntime::setDefaultLocale(const char* locale)
|
|||
if (!locale)
|
||||
return false;
|
||||
|
||||
char* newLocale = DuplicateString(mainContextFromOwnThread(), locale).release();
|
||||
UniqueChars newLocale = DuplicateString(mainContextFromOwnThread(), locale);
|
||||
if (!newLocale)
|
||||
return false;
|
||||
|
||||
resetDefaultLocale();
|
||||
defaultLocale = newLocale;
|
||||
defaultLocale.ref() = std::move(newLocale);
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
JSRuntime::resetDefaultLocale()
|
||||
{
|
||||
js_free(defaultLocale);
|
||||
defaultLocale = nullptr;
|
||||
}
|
||||
|
||||
const char*
|
||||
JSRuntime::getDefaultLocale()
|
||||
{
|
||||
if (defaultLocale)
|
||||
return defaultLocale;
|
||||
if (defaultLocale.ref())
|
||||
return defaultLocale.ref().get();
|
||||
|
||||
const char* locale = setlocale(LC_ALL, nullptr);
|
||||
|
||||
|
@ -560,18 +558,18 @@ JSRuntime::getDefaultLocale()
|
|||
if (!locale || !strcmp(locale, "C"))
|
||||
locale = "und";
|
||||
|
||||
char* lang = DuplicateString(mainContextFromOwnThread(), locale).release();
|
||||
UniqueChars lang = DuplicateString(mainContextFromOwnThread(), locale);
|
||||
if (!lang)
|
||||
return nullptr;
|
||||
|
||||
char* p;
|
||||
if ((p = strchr(lang, '.')))
|
||||
if ((p = strchr(lang.get(), '.')))
|
||||
*p = '\0';
|
||||
while ((p = strchr(lang, '_')))
|
||||
while ((p = strchr(lang.get(), '_')))
|
||||
*p = '-';
|
||||
|
||||
defaultLocale = lang;
|
||||
return defaultLocale;
|
||||
defaultLocale.ref() = std::move(lang);
|
||||
return defaultLocale.ref().get();
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
# include "js/Proxy.h" // For AutoEnterPolicy
|
||||
#endif
|
||||
#include "js/UniquePtr.h"
|
||||
#include "js/Utility.h"
|
||||
#include "js/Vector.h"
|
||||
#include "threading/Thread.h"
|
||||
#include "vm/Caches.h"
|
||||
|
@ -528,7 +529,7 @@ struct JSRuntime : public js::MallocProvider<JSRuntime>
|
|||
js::MainThreadData<const JSLocaleCallbacks*> localeCallbacks;
|
||||
|
||||
/* Default locale for Internationalization API */
|
||||
js::MainThreadData<char*> defaultLocale;
|
||||
js::MainThreadData<js::UniqueChars> defaultLocale;
|
||||
|
||||
/* If true, new scripts must be created with PC counter information. */
|
||||
js::MainThreadOrIonCompileData<bool> profilingScripts;
|
||||
|
|
|
@ -2955,7 +2955,7 @@ JSRuntime::initSelfHosting(JSContext* cx)
|
|||
|
||||
const unsigned char* compressed = compressedSources;
|
||||
uint32_t compressedLen = GetCompressedSize();
|
||||
UniqueChars src(selfHostingGlobal_->zone()->pod_malloc<char>(srcLen));
|
||||
auto src = selfHostingGlobal_->zone()->make_pod_array<char>(srcLen);
|
||||
if (!src || !DecompressString(compressed, compressedLen,
|
||||
reinterpret_cast<unsigned char*>(src.get()), srcLen))
|
||||
{
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include "gc/Policy.h"
|
||||
#include "gc/PublicIterators.h"
|
||||
#include "js/HashTable.h"
|
||||
#include "js/UniquePtr.h"
|
||||
#include "util/Text.h"
|
||||
#include "vm/JSAtom.h"
|
||||
#include "vm/JSContext.h"
|
||||
|
@ -1628,15 +1629,13 @@ ShapeHasher::match(const Key k, const Lookup& l)
|
|||
static KidsHash*
|
||||
HashChildren(Shape* kid1, Shape* kid2)
|
||||
{
|
||||
KidsHash* hash = js_new<KidsHash>();
|
||||
if (!hash || !hash->init(2)) {
|
||||
js_delete(hash);
|
||||
auto hash = MakeUnique<KidsHash>();
|
||||
if (!hash || !hash->init(2))
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
hash->putNewInfallible(StackShape(kid1), kid1);
|
||||
hash->putNewInfallible(StackShape(kid2), kid2);
|
||||
return hash;
|
||||
return hash.release();
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include "builtin/String.h"
|
||||
|
||||
#include "js/HashTable.h"
|
||||
#include "js/UniquePtr.h"
|
||||
#include "js/Utility.h"
|
||||
|
||||
#include "threading/ExclusiveData.h"
|
||||
|
@ -239,7 +240,7 @@ class SharedImmutableStringsCache
|
|||
public:
|
||||
mutable size_t refcount;
|
||||
|
||||
using Ptr = mozilla::UniquePtr<StringBox, JS::DeletePolicy<StringBox>>;
|
||||
using Ptr = js::UniquePtr<StringBox>;
|
||||
|
||||
StringBox(OwnedChars&& chars, size_t length)
|
||||
: chars_(std::move(chars))
|
||||
|
@ -250,7 +251,7 @@ class SharedImmutableStringsCache
|
|||
}
|
||||
|
||||
static Ptr Create(OwnedChars&& chars, size_t length) {
|
||||
return Ptr(js_new<StringBox>(std::move(chars), length));
|
||||
return js::MakeUnique<StringBox>(std::move(chars), length);
|
||||
}
|
||||
|
||||
StringBox(const StringBox&) = delete;
|
||||
|
|
|
@ -41,6 +41,8 @@ using mozilla::Unused;
|
|||
|
||||
using JS::AutoCheckCannotGC;
|
||||
|
||||
using UniqueLatin1Chars = UniquePtr<Latin1Char[], JS::FreePolicy>;
|
||||
|
||||
size_t
|
||||
JSString::sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf)
|
||||
{
|
||||
|
@ -279,7 +281,7 @@ AllocChars(JSString* str, size_t length, CharT** chars, size_t* capacity)
|
|||
return *chars != nullptr;
|
||||
}
|
||||
|
||||
UniquePtr<Latin1Char[], JS::FreePolicy>
|
||||
UniqueLatin1Chars
|
||||
JSRope::copyLatin1CharsZ(JSContext* maybecx) const
|
||||
{
|
||||
return copyCharsInternal<Latin1Char>(maybecx, true);
|
||||
|
@ -291,7 +293,7 @@ JSRope::copyTwoByteCharsZ(JSContext* maybecx) const
|
|||
return copyCharsInternal<char16_t>(maybecx, true);
|
||||
}
|
||||
|
||||
UniquePtr<Latin1Char[], JS::FreePolicy>
|
||||
UniqueLatin1Chars
|
||||
JSRope::copyLatin1Chars(JSContext* maybecx) const
|
||||
{
|
||||
return copyCharsInternal<Latin1Char>(maybecx, false);
|
||||
|
@ -782,22 +784,21 @@ JSFlatString*
|
|||
JSDependentString::undependInternal(JSContext* cx)
|
||||
{
|
||||
size_t n = length();
|
||||
CharT* s = cx->pod_malloc<CharT>(n + 1);
|
||||
auto s = cx->make_pod_array<CharT>(n + 1);
|
||||
if (!s)
|
||||
return nullptr;
|
||||
|
||||
if (!isTenured()) {
|
||||
if (!cx->runtime()->gc.nursery().registerMallocedBuffer(s)) {
|
||||
js_free(s);
|
||||
if (!cx->runtime()->gc.nursery().registerMallocedBuffer(s.get())) {
|
||||
ReportOutOfMemory(cx);
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
AutoCheckCannotGC nogc;
|
||||
PodCopy(s, nonInlineChars<CharT>(nogc), n);
|
||||
PodCopy(s.get(), nonInlineChars<CharT>(nogc), n);
|
||||
s[n] = '\0';
|
||||
setNonInlineChars<CharT>(s);
|
||||
setNonInlineChars<CharT>(s.release());
|
||||
|
||||
/*
|
||||
* Transform *this into an undepended string so 'base' will remain rooted
|
||||
|
@ -1358,13 +1359,12 @@ JSExternalString::ensureFlat(JSContext* cx)
|
|||
MOZ_ASSERT(hasTwoByteChars());
|
||||
|
||||
size_t n = length();
|
||||
char16_t* s = cx->pod_malloc<char16_t>(n + 1);
|
||||
auto s = cx->make_pod_array<char16_t>(n + 1);
|
||||
if (!s)
|
||||
return nullptr;
|
||||
|
||||
if (!isTenured()) {
|
||||
if (!cx->runtime()->gc.nursery().registerMallocedBuffer(s)) {
|
||||
js_free(s);
|
||||
if (!cx->runtime()->gc.nursery().registerMallocedBuffer(s.get())) {
|
||||
ReportOutOfMemory(cx);
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -1373,7 +1373,7 @@ JSExternalString::ensureFlat(JSContext* cx)
|
|||
// Copy the chars before finalizing the string.
|
||||
{
|
||||
AutoCheckCannotGC nogc;
|
||||
PodCopy(s, nonInlineChars<char16_t>(nogc), n);
|
||||
PodCopy(s.get(), nonInlineChars<char16_t>(nogc), n);
|
||||
s[n] = '\0';
|
||||
}
|
||||
|
||||
|
@ -1383,7 +1383,7 @@ JSExternalString::ensureFlat(JSContext* cx)
|
|||
// Transform the string into a non-external, flat string. Note that the
|
||||
// resulting string will still be in an AllocKind::EXTERNAL_STRING arena,
|
||||
// but will no longer be an external string.
|
||||
setNonInlineChars<char16_t>(s);
|
||||
setNonInlineChars<char16_t>(s.release());
|
||||
d.u1.flags = INIT_FLAT_FLAGS;
|
||||
|
||||
return &this->asFlat();
|
||||
|
@ -1506,7 +1506,7 @@ NewStringDeflated(JSContext* cx, const char16_t* s, size_t n)
|
|||
if (JSInlineString::lengthFits<Latin1Char>(n))
|
||||
return NewInlineStringDeflated<allowGC>(cx, mozilla::Range<const char16_t>(s, n));
|
||||
|
||||
UniquePtr<Latin1Char[], JS::FreePolicy> news(cx->pod_malloc<Latin1Char>(n + 1));
|
||||
auto news = cx->make_pod_array<Latin1Char>(n + 1);
|
||||
if (!news)
|
||||
return nullptr;
|
||||
|
||||
|
@ -1531,7 +1531,7 @@ NewStringDeflated(JSContext* cx, const Latin1Char* s, size_t n)
|
|||
MOZ_CRASH("Shouldn't be called for Latin1 chars");
|
||||
}
|
||||
|
||||
template <AllowGC allowGC, typename CharT>
|
||||
template <typename CharT>
|
||||
JSFlatString*
|
||||
js::NewStringDontDeflate(JSContext* cx, CharT* chars, size_t length)
|
||||
{
|
||||
|
@ -1544,7 +1544,7 @@ js::NewStringDontDeflate(JSContext* cx, CharT* chars, size_t length)
|
|||
|
||||
if (JSInlineString::lengthFits<CharT>(length)) {
|
||||
JSInlineString* str =
|
||||
NewInlineString<allowGC>(cx, mozilla::Range<const CharT>(chars, length));
|
||||
NewInlineString<CanGC>(cx, mozilla::Range<const CharT>(chars, length));
|
||||
if (!str)
|
||||
return nullptr;
|
||||
|
||||
|
@ -1552,27 +1552,21 @@ js::NewStringDontDeflate(JSContext* cx, CharT* chars, size_t length)
|
|||
return str;
|
||||
}
|
||||
|
||||
return JSFlatString::new_<allowGC>(cx, chars, length);
|
||||
return JSFlatString::new_<CanGC>(cx, chars, length);
|
||||
}
|
||||
|
||||
template JSFlatString*
|
||||
js::NewStringDontDeflate<CanGC>(JSContext* cx, char16_t* chars, size_t length);
|
||||
js::NewStringDontDeflate(JSContext* cx, char16_t* chars, size_t length);
|
||||
|
||||
template JSFlatString*
|
||||
js::NewStringDontDeflate<NoGC>(JSContext* cx, char16_t* chars, size_t length);
|
||||
js::NewStringDontDeflate(JSContext* cx, Latin1Char* chars, size_t length);
|
||||
|
||||
template JSFlatString*
|
||||
js::NewStringDontDeflate<CanGC>(JSContext* cx, Latin1Char* chars, size_t length);
|
||||
|
||||
template JSFlatString*
|
||||
js::NewStringDontDeflate<NoGC>(JSContext* cx, Latin1Char* chars, size_t length);
|
||||
|
||||
template <AllowGC allowGC, typename CharT>
|
||||
template <typename CharT>
|
||||
JSFlatString*
|
||||
js::NewString(JSContext* cx, CharT* chars, size_t length)
|
||||
{
|
||||
if (IsSame<CharT, char16_t>::value && CanStoreCharsAsLatin1(chars, length)) {
|
||||
JSFlatString* s = NewStringDeflated<allowGC>(cx, chars, length);
|
||||
JSFlatString* s = NewStringDeflated<CanGC>(cx, chars, length);
|
||||
if (!s)
|
||||
return nullptr;
|
||||
|
||||
|
@ -1581,20 +1575,66 @@ js::NewString(JSContext* cx, CharT* chars, size_t length)
|
|||
return s;
|
||||
}
|
||||
|
||||
return NewStringDontDeflate<allowGC>(cx, chars, length);
|
||||
return NewStringDontDeflate(cx, chars, length);
|
||||
}
|
||||
|
||||
template JSFlatString*
|
||||
js::NewString<CanGC>(JSContext* cx, char16_t* chars, size_t length);
|
||||
js::NewString(JSContext* cx, char16_t* chars, size_t length);
|
||||
|
||||
template JSFlatString*
|
||||
js::NewString<NoGC>(JSContext* cx, char16_t* chars, size_t length);
|
||||
js::NewString(JSContext* cx, Latin1Char* chars, size_t length);
|
||||
|
||||
template <AllowGC allowGC, typename CharT>
|
||||
JSFlatString*
|
||||
js::NewStringDontDeflate(JSContext* cx, UniquePtr<CharT[], JS::FreePolicy> chars, size_t length)
|
||||
{
|
||||
if (JSFlatString* str = TryEmptyOrStaticString(cx, chars.get(), length))
|
||||
return str;
|
||||
|
||||
if (JSInlineString::lengthFits<CharT>(length))
|
||||
return NewInlineString<allowGC>(cx, mozilla::Range<const CharT>(chars.get(), length));
|
||||
|
||||
JSFlatString* str = JSFlatString::new_<allowGC>(cx, chars.get(), length);
|
||||
if (!str)
|
||||
return nullptr;
|
||||
|
||||
mozilla::Unused << chars.release();
|
||||
return str;
|
||||
}
|
||||
|
||||
template JSFlatString*
|
||||
js::NewString<CanGC>(JSContext* cx, Latin1Char* chars, size_t length);
|
||||
js::NewStringDontDeflate<CanGC>(JSContext* cx, UniqueTwoByteChars chars, size_t length);
|
||||
|
||||
template JSFlatString*
|
||||
js::NewString<NoGC>(JSContext* cx, Latin1Char* chars, size_t length);
|
||||
js::NewStringDontDeflate<NoGC>(JSContext* cx, UniqueTwoByteChars chars, size_t length);
|
||||
|
||||
template JSFlatString*
|
||||
js::NewStringDontDeflate<CanGC>(JSContext* cx, UniqueLatin1Chars chars, size_t length);
|
||||
|
||||
template JSFlatString*
|
||||
js::NewStringDontDeflate<NoGC>(JSContext* cx, UniqueLatin1Chars chars, size_t length);
|
||||
|
||||
template <AllowGC allowGC, typename CharT>
|
||||
JSFlatString*
|
||||
js::NewString(JSContext* cx, UniquePtr<CharT[], JS::FreePolicy> chars, size_t length)
|
||||
{
|
||||
if (IsSame<CharT, char16_t>::value && CanStoreCharsAsLatin1(chars.get(), length))
|
||||
return NewStringDeflated<allowGC>(cx, chars.get(), length);
|
||||
|
||||
return NewStringDontDeflate<allowGC>(cx, std::move(chars), length);
|
||||
}
|
||||
|
||||
template JSFlatString*
|
||||
js::NewString<CanGC>(JSContext* cx, UniqueTwoByteChars chars, size_t length);
|
||||
|
||||
template JSFlatString*
|
||||
js::NewString<NoGC>(JSContext* cx, UniqueTwoByteChars chars, size_t length);
|
||||
|
||||
template JSFlatString*
|
||||
js::NewString<CanGC>(JSContext* cx, UniqueLatin1Chars chars, size_t length);
|
||||
|
||||
template JSFlatString*
|
||||
js::NewString<NoGC>(JSContext* cx, UniqueLatin1Chars chars, size_t length);
|
||||
|
||||
namespace js {
|
||||
|
||||
|
@ -1608,7 +1648,7 @@ NewStringCopyNDontDeflate(JSContext* cx, const CharT* s, size_t n)
|
|||
if (JSInlineString::lengthFits<CharT>(n))
|
||||
return NewInlineString<allowGC>(cx, mozilla::Range<const CharT>(s, n));
|
||||
|
||||
UniquePtr<CharT[], JS::FreePolicy> news(cx->pod_malloc<CharT>(n + 1));
|
||||
auto news = cx->make_pod_array<CharT>(n + 1);
|
||||
if (!news) {
|
||||
if (!allowGC)
|
||||
cx->recoverFromOutOfMemory();
|
||||
|
@ -1641,12 +1681,9 @@ NewStringCopyNDontDeflate<NoGC>(JSContext* cx, const Latin1Char* s, size_t n);
|
|||
JSFlatString*
|
||||
NewLatin1StringZ(JSContext* cx, UniqueChars chars)
|
||||
{
|
||||
JSFlatString* str = NewString<CanGC>(cx, (Latin1Char*)chars.get(), strlen(chars.get()));
|
||||
if (!str)
|
||||
return nullptr;
|
||||
|
||||
mozilla::Unused << chars.release();
|
||||
return str;
|
||||
size_t length = strlen(chars.get());
|
||||
UniqueLatin1Chars latin1(reinterpret_cast<Latin1Char*>(chars.release()));
|
||||
return NewString<CanGC>(cx, std::move(latin1), length);
|
||||
}
|
||||
|
||||
template <AllowGC allowGC, typename CharT>
|
||||
|
@ -1681,26 +1718,20 @@ NewStringCopyUTF8N(JSContext* cx, const JS::UTF8Chars utf8)
|
|||
|
||||
size_t length;
|
||||
if (encoding == JS::SmallestEncoding::Latin1) {
|
||||
Latin1Char* latin1 = UTF8CharsToNewLatin1CharsZ(cx, utf8, &length).get();
|
||||
UniqueLatin1Chars latin1(UTF8CharsToNewLatin1CharsZ(cx, utf8, &length).get());
|
||||
if (!latin1)
|
||||
return nullptr;
|
||||
|
||||
JSFlatString* result = NewString<allowGC>(cx, latin1, length);
|
||||
if (!result)
|
||||
js_free((void*)latin1);
|
||||
return result;
|
||||
return NewString<allowGC>(cx, std::move(latin1), length);
|
||||
}
|
||||
|
||||
MOZ_ASSERT(encoding == JS::SmallestEncoding::UTF16);
|
||||
|
||||
char16_t* utf16 = UTF8CharsToNewTwoByteCharsZ(cx, utf8, &length).get();
|
||||
UniqueTwoByteChars utf16(UTF8CharsToNewTwoByteCharsZ(cx, utf8, &length).get());
|
||||
if (!utf16)
|
||||
return nullptr;
|
||||
|
||||
JSFlatString* result = NewString<allowGC>(cx, utf16, length);
|
||||
if (!result)
|
||||
js_free((void*)utf16);
|
||||
return result;
|
||||
return NewString<allowGC>(cx, std::move(utf16), length);
|
||||
}
|
||||
|
||||
template JSFlatString*
|
||||
|
|
|
@ -1444,15 +1444,25 @@ StringToNewUTF8CharsZ(JSContext* maybecx, JSString& str)
|
|||
}
|
||||
|
||||
/* GC-allocate a string descriptor for the given malloc-allocated chars. */
|
||||
template <js::AllowGC allowGC, typename CharT>
|
||||
template <typename CharT>
|
||||
extern JSFlatString*
|
||||
NewString(JSContext* cx, CharT* chars, size_t length);
|
||||
|
||||
/* Like NewString, but doesn't try to deflate to Latin1. */
|
||||
template <js::AllowGC allowGC, typename CharT>
|
||||
template <typename CharT>
|
||||
extern JSFlatString*
|
||||
NewStringDontDeflate(JSContext* cx, CharT* chars, size_t length);
|
||||
|
||||
/* GC-allocate a string descriptor for the given malloc-allocated chars. */
|
||||
template <js::AllowGC allowGC, typename CharT>
|
||||
extern JSFlatString*
|
||||
NewString(JSContext* cx, UniquePtr<CharT[], JS::FreePolicy> chars, size_t length);
|
||||
|
||||
/* Like NewString, but doesn't try to deflate to Latin1. */
|
||||
template <js::AllowGC allowGC, typename CharT>
|
||||
extern JSFlatString*
|
||||
NewStringDontDeflate(JSContext* cx, UniquePtr<CharT[], JS::FreePolicy> chars, size_t length);
|
||||
|
||||
extern JSLinearString*
|
||||
NewDependentString(JSContext* cx, JSString* base, size_t start, size_t length);
|
||||
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#include "mozilla/EndianUtils.h"
|
||||
#include "mozilla/FloatingPoint.h"
|
||||
#include "mozilla/RangedPtr.h"
|
||||
#include "mozilla/Unused.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <utility>
|
||||
|
@ -1187,7 +1188,7 @@ JSStructuredCloneWriter::writeBigInt(uint32_t tag, BigInt* bi)
|
|||
return false;
|
||||
uint32_t lengthAndSign = length | (static_cast<uint32_t>(signBit) << 31);
|
||||
|
||||
js::UniquePtr<uint8_t> buf(static_cast<uint8_t*>(js_malloc(length)));
|
||||
js::UniquePtr<uint8_t> buf(js_pod_malloc<uint8_t>(length));
|
||||
if (!buf)
|
||||
return false;
|
||||
|
||||
|
@ -1905,31 +1906,16 @@ JSStructuredCloneReader::checkDouble(double d)
|
|||
return true;
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
template <typename CharT>
|
||||
class Chars {
|
||||
JSContext* cx;
|
||||
CharT* p;
|
||||
public:
|
||||
explicit Chars(JSContext* cx) : cx(cx), p(nullptr) {}
|
||||
~Chars() { js_free(p); }
|
||||
|
||||
bool allocate(size_t len) {
|
||||
MOZ_ASSERT(!p);
|
||||
// We're going to null-terminate!
|
||||
p = cx->pod_malloc<CharT>(len + 1);
|
||||
if (p) {
|
||||
p[len] = CharT(0);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
CharT* get() { return p; }
|
||||
void forget() { p = nullptr; }
|
||||
};
|
||||
|
||||
} // anonymous namespace
|
||||
static UniquePtr<CharT[], JS::FreePolicy>
|
||||
AllocateChars(JSContext* cx, size_t len)
|
||||
{
|
||||
// We're going to null-terminate!
|
||||
auto p = cx->make_pod_array<CharT>(len + 1);
|
||||
if (p)
|
||||
p[len] = CharT(0);
|
||||
return p;
|
||||
}
|
||||
|
||||
template <typename CharT>
|
||||
JSString*
|
||||
|
@ -1940,13 +1926,10 @@ JSStructuredCloneReader::readStringImpl(uint32_t nchars)
|
|||
"string length");
|
||||
return nullptr;
|
||||
}
|
||||
Chars<CharT> chars(context());
|
||||
if (!chars.allocate(nchars) || !in.readChars(chars.get(), nchars))
|
||||
UniquePtr<CharT[], JS::FreePolicy> chars = AllocateChars<CharT>(context(), nchars);
|
||||
if (!chars || !in.readChars(chars.get(), nchars))
|
||||
return nullptr;
|
||||
JSString* str = NewString<CanGC>(context(), chars.get(), nchars);
|
||||
if (str)
|
||||
chars.forget();
|
||||
return str;
|
||||
return NewString<CanGC>(context(), std::move(chars), nchars);
|
||||
}
|
||||
|
||||
JSString*
|
||||
|
@ -1967,7 +1950,7 @@ JSStructuredCloneReader::readBigInt(uint32_t data)
|
|||
if (nbytes == 0)
|
||||
return BigInt::create(context());
|
||||
|
||||
UniquePtr<uint8_t> buf(static_cast<uint8_t*>(js_malloc(nbytes)));
|
||||
UniquePtr<uint8_t> buf(js_pod_malloc<uint8_t>(nbytes));
|
||||
if (!buf)
|
||||
return nullptr;
|
||||
if (!in.readBytes(buf.get(), nbytes))
|
||||
|
|
|
@ -54,8 +54,6 @@ TraceLoggerGraphState* traceLoggerGraphState = nullptr;
|
|||
static js::UniqueChars
|
||||
MOZ_FORMAT_PRINTF(1, 2)
|
||||
AllocTraceLogFilename(const char* pattern, ...) {
|
||||
js::UniqueChars filename;
|
||||
|
||||
va_list ap;
|
||||
|
||||
static const char* outdir = getenv("TLDIR") ? getenv("TLDIR") : DEFAULT_TRACE_LOG_DIR;
|
||||
|
@ -77,7 +75,7 @@ AllocTraceLogFilename(const char* pattern, ...) {
|
|||
|
||||
len++; // For the terminating NUL.
|
||||
|
||||
filename.reset((char*) js_malloc(len));
|
||||
js::UniqueChars filename(js_pod_malloc<char>(len));
|
||||
if (!filename)
|
||||
return nullptr;
|
||||
char* rest = filename.get() + sprintf(filename.get(), "%s/", outdir);
|
||||
|
|
|
@ -170,7 +170,7 @@ class ContinuousSpace {
|
|||
bool init() {
|
||||
capacity_ = 64;
|
||||
size_ = 0;
|
||||
data_ = (T*) js_malloc(capacity_ * sizeof(T));
|
||||
data_ = js_pod_malloc<T>(capacity_);
|
||||
if (!data_)
|
||||
return false;
|
||||
|
||||
|
@ -230,7 +230,7 @@ class ContinuousSpace {
|
|||
uint32_t nCapacity = capacity_ * 2;
|
||||
nCapacity = (nCapacity < maxSize()) ? nCapacity : maxSize();
|
||||
|
||||
T* entries = (T*) js_realloc(data_, nCapacity * sizeof(T));
|
||||
T* entries = js_pod_realloc<T>(data_, capacity_, nCapacity);
|
||||
if (!entries)
|
||||
return false;
|
||||
|
||||
|
|
|
@ -351,7 +351,7 @@ IsTypedArrayIndex(jsid id, uint64_t* indexp)
|
|||
if (JSID_IS_INT(id)) {
|
||||
int32_t i = JSID_TO_INT(id);
|
||||
MOZ_ASSERT(i >= 0);
|
||||
*indexp = (double)i;
|
||||
*indexp = static_cast<uint64_t>(i);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -333,14 +333,14 @@ template JS::Zone* TracerConcrete<JSString>::zone() const;
|
|||
template<typename Referent>
|
||||
UniquePtr<EdgeRange>
|
||||
TracerConcrete<Referent>::edges(JSContext* cx, bool wantNames) const {
|
||||
UniquePtr<SimpleEdgeRange, JS::DeletePolicy<SimpleEdgeRange>> range(js_new<SimpleEdgeRange>());
|
||||
auto range = js::MakeUnique<SimpleEdgeRange>();
|
||||
if (!range)
|
||||
return nullptr;
|
||||
|
||||
if (!range->init(cx->runtime(), ptr, JS::MapTypeToTraceKind<Referent>::kind, wantNames))
|
||||
return nullptr;
|
||||
|
||||
return UniquePtr<EdgeRange>(range.release());
|
||||
return range;
|
||||
}
|
||||
|
||||
template UniquePtr<EdgeRange> TracerConcrete<JSScript>::edges(JSContext* cx, bool wantNames) const;
|
||||
|
@ -556,7 +556,7 @@ const char16_t Concrete<RootList>::concreteTypeName[] = u"JS::ubi::RootList";
|
|||
UniquePtr<EdgeRange>
|
||||
Concrete<RootList>::edges(JSContext* cx, bool wantNames) const {
|
||||
MOZ_ASSERT_IF(wantNames, get().wantNames);
|
||||
return UniquePtr<EdgeRange>(js_new<PreComputedEdgeRange>(get().edges));
|
||||
return js::MakeUnique<PreComputedEdgeRange>(get().edges);
|
||||
}
|
||||
|
||||
} // namespace ubi
|
||||
|
|
|
@ -438,7 +438,7 @@ ByObjectClass::makeCount()
|
|||
if (!otherCount)
|
||||
return nullptr;
|
||||
|
||||
UniquePtr<Count> count(js_new<Count>(*this, otherCount));
|
||||
auto count = js::MakeUnique<Count>(*this, otherCount);
|
||||
if (!count || !count->init())
|
||||
return nullptr;
|
||||
|
||||
|
@ -532,7 +532,7 @@ class ByUbinodeType : public CountType {
|
|||
CountBasePtr
|
||||
ByUbinodeType::makeCount()
|
||||
{
|
||||
UniquePtr<Count> count(js_new<Count>(*this));
|
||||
auto count = js::MakeUnique<Count>(*this);
|
||||
if (!count || !count->init())
|
||||
return nullptr;
|
||||
|
||||
|
@ -679,7 +679,7 @@ ByAllocationStack::makeCount()
|
|||
if (!noStackCount)
|
||||
return nullptr;
|
||||
|
||||
UniquePtr<Count> count(js_new<Count>(*this, noStackCount));
|
||||
auto count = js::MakeUnique<Count>(*this, noStackCount);
|
||||
if (!count || !count->init())
|
||||
return nullptr;
|
||||
return CountBasePtr(count.release());
|
||||
|
@ -855,7 +855,7 @@ ByFilename::makeCount()
|
|||
if (!noFilenameCount)
|
||||
return nullptr;
|
||||
|
||||
UniquePtr<Count> count(js_new<Count>(*this, std::move(thenCount), std::move(noFilenameCount)));
|
||||
auto count = js::MakeUnique<Count>(*this, std::move(thenCount), std::move(noFilenameCount));
|
||||
if (!count || !count->init())
|
||||
return nullptr;
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@ namespace ubi {
|
|||
JS_PUBLIC_API(BackEdge::Ptr)
|
||||
BackEdge::clone() const
|
||||
{
|
||||
BackEdge::Ptr clone(js_new<BackEdge>());
|
||||
auto clone = js::MakeUnique<BackEdge>();
|
||||
if (!clone)
|
||||
return nullptr;
|
||||
|
||||
|
|
|
@ -211,7 +211,7 @@ Module::startTier2(const CompileArgs& args)
|
|||
// ~Tier2GeneratorTaskImpl() to call notifyCompilationListeners() if it
|
||||
// hasn't been already.
|
||||
|
||||
UniqueTier2GeneratorTask task(js_new<Tier2GeneratorTaskImpl>(*this, args));
|
||||
auto task = MakeUnique<Tier2GeneratorTaskImpl>(*this, args);
|
||||
if (!task)
|
||||
return;
|
||||
|
||||
|
|
|
@ -320,6 +320,9 @@ NS_NewScrollbarFrame (nsIPresShell* aPresShell, ComputedStyle* aStyle);
|
|||
nsIFrame*
|
||||
NS_NewScrollbarButtonFrame (nsIPresShell* aPresShell, ComputedStyle* aStyle);
|
||||
|
||||
nsIFrame*
|
||||
NS_NewImageFrameForContentProperty(nsIPresShell*, ComputedStyle*);
|
||||
|
||||
|
||||
#ifdef NOISY_FINDFRAME
|
||||
static int32_t FFWC_totalCount=0;
|
||||
|
@ -5625,6 +5628,17 @@ ShouldSuppressFrameInNonOpenDetails(const HTMLDetailsElement* aDetails,
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
ShouldCreateImageFrameForContent(ComputedStyle& aStyle)
|
||||
{
|
||||
auto& content = *aStyle.StyleContent();
|
||||
if (content.ContentCount() != 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return content.ContentAt(0).GetType() == eStyleContentType_Image;
|
||||
}
|
||||
|
||||
void
|
||||
nsCSSFrameConstructor::AddFrameConstructionItemsInternal(nsFrameConstructorState& aState,
|
||||
nsIContent* aContent,
|
||||
|
@ -5789,6 +5803,14 @@ nsCSSFrameConstructor::AddFrameConstructionItemsInternal(nsFrameConstructorState
|
|||
computedStyle);
|
||||
}
|
||||
|
||||
// Check for 'content: <image-url>' on the element (which makes us ignore
|
||||
// 'display' values other than 'none' or 'contents').
|
||||
if (!data && ShouldCreateImageFrameForContent(*computedStyle)) {
|
||||
static const FrameConstructionData sImgData =
|
||||
SIMPLE_FCDATA(NS_NewImageFrameForContentProperty);
|
||||
data = &sImgData;
|
||||
}
|
||||
|
||||
// Now check for XUL display types
|
||||
if (!data) {
|
||||
data = FindXULDisplayData(display, element, computedStyle);
|
||||
|
@ -8598,7 +8620,8 @@ nsCSSFrameConstructor::CreateContinuingFrame(nsPresContext* aPresContext,
|
|||
newFrame = NS_NewFirstLetterFrame(shell, computedStyle);
|
||||
newFrame->Init(content, aParentFrame, aFrame);
|
||||
} else if (LayoutFrameType::Image == frameType) {
|
||||
newFrame = NS_NewImageFrame(shell, computedStyle);
|
||||
auto* imageFrame = static_cast<nsImageFrame*>(aFrame);
|
||||
newFrame = imageFrame->CreateContinuingFrame(shell, computedStyle);
|
||||
newFrame->Init(content, aParentFrame, aFrame);
|
||||
} else if (LayoutFrameType::ImageControl == frameType) {
|
||||
newFrame = NS_NewImageControlFrame(shell, computedStyle);
|
||||
|
|
|
@ -148,11 +148,7 @@ public:
|
|||
{
|
||||
}
|
||||
|
||||
virtual ~RefreshDriverTimer()
|
||||
{
|
||||
MOZ_ASSERT(mContentRefreshDrivers.Length() == 0, "Should have removed all content refresh drivers from here by now!");
|
||||
MOZ_ASSERT(mRootRefreshDrivers.Length() == 0, "Should have removed all root refresh drivers from here by now!");
|
||||
}
|
||||
NS_INLINE_DECL_REFCOUNTING(RefreshDriverTimer)
|
||||
|
||||
virtual void AddRefreshDriver(nsRefreshDriver* aDriver)
|
||||
{
|
||||
|
@ -259,6 +255,12 @@ public:
|
|||
}
|
||||
|
||||
protected:
|
||||
virtual ~RefreshDriverTimer()
|
||||
{
|
||||
MOZ_ASSERT(mContentRefreshDrivers.Length() == 0, "Should have removed all content refresh drivers from here by now!");
|
||||
MOZ_ASSERT(mRootRefreshDrivers.Length() == 0, "Should have removed all root refresh drivers from here by now!");
|
||||
}
|
||||
|
||||
virtual void StartTimer() = 0;
|
||||
virtual void StopTimer() = 0;
|
||||
virtual void ScheduleNextTick(TimeStamp aNowTime) = 0;
|
||||
|
@ -336,10 +338,11 @@ protected:
|
|||
nsTArray<RefPtr<nsRefreshDriver>> mRootRefreshDrivers;
|
||||
|
||||
// useful callback for nsITimer-based derived classes, here
|
||||
// bacause of c++ protected shenanigans
|
||||
// because of c++ protected shenanigans
|
||||
static void TimerTick(nsITimer* aTimer, void* aClosure)
|
||||
{
|
||||
RefreshDriverTimer *timer = static_cast<RefreshDriverTimer*>(aClosure);
|
||||
RefPtr<RefreshDriverTimer> timer =
|
||||
static_cast<RefreshDriverTimer*>(aClosure);
|
||||
timer->Tick();
|
||||
}
|
||||
};
|
||||
|
@ -471,9 +474,7 @@ public:
|
|||
private:
|
||||
// Since VsyncObservers are refCounted, but the RefreshDriverTimer are
|
||||
// explicitly shutdown. We create an inner class that has the VsyncObserver
|
||||
// and is shutdown when the RefreshDriverTimer is deleted. The alternative is
|
||||
// to (a) make all RefreshDriverTimer RefCounted or (b) use different
|
||||
// VsyncObserver types.
|
||||
// and is shutdown when the RefreshDriverTimer is deleted.
|
||||
class RefreshDriverVsyncObserver final : public VsyncObserver
|
||||
{
|
||||
public:
|
||||
|
@ -537,6 +538,9 @@ private:
|
|||
|
||||
bool NotifyVsync(TimeStamp aVsyncTimestamp) override
|
||||
{
|
||||
// IMPORTANT: All paths through this method MUST hold a strong ref on
|
||||
// |this| for the duration of the TickRefreshDriver callback.
|
||||
|
||||
if (!NS_IsMainThread()) {
|
||||
MOZ_ASSERT(XRE_IsParentProcess());
|
||||
// Compress vsync notifications such that only 1 may run at a time
|
||||
|
@ -571,6 +575,7 @@ private:
|
|||
return true;
|
||||
}
|
||||
|
||||
RefPtr<RefreshDriverVsyncObserver> kungFuDeathGrip(this);
|
||||
TickRefreshDriver(aVsyncTimestamp);
|
||||
}
|
||||
|
||||
|
@ -670,7 +675,9 @@ private:
|
|||
// the scheduled TickRefreshDriver() runs. Check mVsyncRefreshDriverTimer
|
||||
// before use.
|
||||
if (mVsyncRefreshDriverTimer) {
|
||||
mVsyncRefreshDriverTimer->RunRefreshDrivers(aVsyncTimestamp);
|
||||
RefPtr<VsyncRefreshDriverTimer> timer = mVsyncRefreshDriverTimer;
|
||||
timer->RunRefreshDrivers(aVsyncTimestamp);
|
||||
// Note: mVsyncRefreshDriverTimer might be null now.
|
||||
}
|
||||
|
||||
if (!XRE_IsParentProcess()) {
|
||||
|
@ -952,7 +959,8 @@ protected:
|
|||
|
||||
static void TimerTickOne(nsITimer* aTimer, void* aClosure)
|
||||
{
|
||||
InactiveRefreshDriverTimer *timer = static_cast<InactiveRefreshDriverTimer*>(aClosure);
|
||||
RefPtr<InactiveRefreshDriverTimer> timer =
|
||||
static_cast<InactiveRefreshDriverTimer*>(aClosure);
|
||||
timer->TickOne();
|
||||
}
|
||||
|
||||
|
@ -963,8 +971,8 @@ protected:
|
|||
|
||||
} // namespace mozilla
|
||||
|
||||
static RefreshDriverTimer* sRegularRateTimer;
|
||||
static InactiveRefreshDriverTimer* sThrottledRateTimer;
|
||||
static StaticRefPtr<RefreshDriverTimer> sRegularRateTimer;
|
||||
static StaticRefPtr<InactiveRefreshDriverTimer> sThrottledRateTimer;
|
||||
|
||||
static void
|
||||
CreateContentVsyncRefreshTimer(void*)
|
||||
|
@ -1038,9 +1046,6 @@ GetFirstFrameDelay(imgIRequest* req)
|
|||
nsRefreshDriver::Shutdown()
|
||||
{
|
||||
// clean up our timers
|
||||
delete sRegularRateTimer;
|
||||
delete sThrottledRateTimer;
|
||||
|
||||
sRegularRateTimer = nullptr;
|
||||
sThrottledRateTimer = nullptr;
|
||||
}
|
||||
|
@ -2288,16 +2293,15 @@ nsRefreshDriver::PVsyncActorCreated(VsyncChild* aVsyncChild)
|
|||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(!XRE_IsParentProcess());
|
||||
auto* vsyncRefreshDriverTimer =
|
||||
new VsyncRefreshDriverTimer(aVsyncChild);
|
||||
RefPtr<RefreshDriverTimer> vsyncRefreshDriverTimer =
|
||||
new VsyncRefreshDriverTimer(aVsyncChild);
|
||||
|
||||
// If we are using software timer, swap current timer to
|
||||
// VsyncRefreshDriverTimer.
|
||||
if (sRegularRateTimer) {
|
||||
sRegularRateTimer->SwapRefreshDrivers(vsyncRefreshDriverTimer);
|
||||
delete sRegularRateTimer;
|
||||
}
|
||||
sRegularRateTimer = vsyncRefreshDriverTimer;
|
||||
sRegularRateTimer = vsyncRefreshDriverTimer.forget();
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -130,15 +130,31 @@ inline bool HaveFixedSize(const ReflowInput& aReflowInput)
|
|||
nsIFrame*
|
||||
NS_NewImageFrame(nsIPresShell* aPresShell, ComputedStyle* aStyle)
|
||||
{
|
||||
return new (aPresShell) nsImageFrame(aStyle);
|
||||
return new (aPresShell) nsImageFrame(aStyle, nsImageFrame::Kind::ImageElement);
|
||||
}
|
||||
|
||||
nsIFrame*
|
||||
NS_NewImageFrameForContentProperty(nsIPresShell* aPresShell,
|
||||
ComputedStyle* aStyle)
|
||||
{
|
||||
return new (aPresShell) nsImageFrame(
|
||||
aStyle, nsImageFrame::Kind::NonGeneratedContentProperty);
|
||||
}
|
||||
|
||||
nsImageFrame*
|
||||
nsImageFrame::CreateContinuingFrame(nsIPresShell* aPresShell,
|
||||
ComputedStyle* aStyle) const
|
||||
{
|
||||
return new (aPresShell) nsImageFrame(aStyle, mKind);
|
||||
}
|
||||
|
||||
NS_IMPL_FRAMEARENA_HELPERS(nsImageFrame)
|
||||
|
||||
nsImageFrame::nsImageFrame(ComputedStyle* aStyle, ClassID aID)
|
||||
nsImageFrame::nsImageFrame(ComputedStyle* aStyle, ClassID aID, Kind aKind)
|
||||
: nsAtomicContainerFrame(aStyle, aID)
|
||||
, mComputedSize(0, 0)
|
||||
, mIntrinsicRatio(0, 0)
|
||||
, mKind(aKind)
|
||||
, mDisplayingIcon(false)
|
||||
, mFirstFrameComplete(false)
|
||||
, mReflowCallbackPosted(false)
|
||||
|
@ -203,20 +219,25 @@ nsImageFrame::DestroyFrom(nsIFrame* aDestructRoot, PostDestroyData& aPostDestroy
|
|||
// a DOM listener.
|
||||
DisconnectMap();
|
||||
|
||||
// set the frame to null so we don't send messages to a dead object.
|
||||
if (mListener) {
|
||||
MOZ_ASSERT(mListener);
|
||||
|
||||
if (mKind == Kind::ImageElement) {
|
||||
MOZ_ASSERT(!mContentURLRequest);
|
||||
nsCOMPtr<nsIImageLoadingContent> imageLoader = do_QueryInterface(mContent);
|
||||
if (imageLoader) {
|
||||
// Notify our image loading content that we are going away so it can
|
||||
// deregister with our refresh driver.
|
||||
imageLoader->FrameDestroyed(this);
|
||||
MOZ_ASSERT(imageLoader);
|
||||
|
||||
imageLoader->RemoveNativeObserver(mListener);
|
||||
// Notify our image loading content that we are going away so it can
|
||||
// deregister with our refresh driver.
|
||||
imageLoader->FrameDestroyed(this);
|
||||
imageLoader->RemoveNativeObserver(mListener);
|
||||
} else {
|
||||
if (mContentURLRequest) {
|
||||
mContentURLRequest->Cancel(NS_BINDING_ABORTED);
|
||||
}
|
||||
|
||||
mListener->SetFrame(nullptr);
|
||||
}
|
||||
|
||||
// set the frame to null so we don't send messages to a dead object.
|
||||
mListener->SetFrame(nullptr);
|
||||
mListener = nullptr;
|
||||
|
||||
// If we were displaying an icon, take ourselves off the list
|
||||
|
@ -254,11 +275,27 @@ nsImageFrame::DidSetComputedStyle(ComputedStyle* aOldComputedStyle)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsImageFrame::Init(nsIContent* aContent,
|
||||
nsContainerFrame* aParent,
|
||||
nsIFrame* aPrevInFlow)
|
||||
static bool
|
||||
SizeIsAvailable(imgIRequest* aRequest)
|
||||
{
|
||||
if (!aRequest) {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t imageStatus = 0;
|
||||
nsresult rv = aRequest->GetImageStatus(&imageStatus);
|
||||
return NS_SUCCEEDED(rv) && (imageStatus & imgIRequest::STATUS_SIZE_AVAILABLE);
|
||||
}
|
||||
|
||||
void
|
||||
nsImageFrame::Init(nsIContent* aContent,
|
||||
nsContainerFrame* aParent,
|
||||
nsIFrame* aPrevInFlow)
|
||||
{
|
||||
MOZ_ASSERT_IF(aPrevInFlow,
|
||||
aPrevInFlow->Type() == LayoutFrameType::Image &&
|
||||
static_cast<nsImageFrame*>(aPrevInFlow)->mKind == mKind);
|
||||
|
||||
nsAtomicContainerFrame::Init(aContent, aParent, aPrevInFlow);
|
||||
|
||||
mListener = new nsImageListener(this);
|
||||
|
@ -266,17 +303,27 @@ nsImageFrame::Init(nsIContent* aContent,
|
|||
if (!gIconLoad)
|
||||
LoadIcons(PresContext());
|
||||
|
||||
nsCOMPtr<nsIImageLoadingContent> imageLoader = do_QueryInterface(aContent);
|
||||
if (!imageLoader) {
|
||||
MOZ_CRASH("Why do we have an nsImageFrame here at all?");
|
||||
if (mKind == Kind::ImageElement) {
|
||||
nsCOMPtr<nsIImageLoadingContent> imageLoader = do_QueryInterface(aContent);
|
||||
MOZ_ASSERT(imageLoader);
|
||||
imageLoader->AddNativeObserver(mListener);
|
||||
// We have a PresContext now, so we need to notify the image content node
|
||||
// that it can register images.
|
||||
imageLoader->FrameCreated(this);
|
||||
} else {
|
||||
if (auto* proxy = StyleContent()->ContentAt(0).GetImage()) {
|
||||
proxy->Clone(mListener,
|
||||
mContent->OwnerDoc(),
|
||||
getter_AddRefs(mContentURLRequest));
|
||||
// Make sure we get the intrinsic size and such ASAP if available.
|
||||
if (SizeIsAvailable(mContentURLRequest)) {
|
||||
nsCOMPtr<imgIContainer> image;
|
||||
mContentURLRequest->GetImage(getter_AddRefs(image));
|
||||
OnSizeAvailable(mContentURLRequest, image);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
imageLoader->AddNativeObserver(mListener);
|
||||
|
||||
// We have a PresContext now, so we need to notify the image content node that
|
||||
// it can register images.
|
||||
imageLoader->FrameCreated(this);
|
||||
|
||||
// Give image loads associated with an image frame a small priority boost.
|
||||
if (nsCOMPtr<imgIRequest> currentRequest = GetCurrentRequest()) {
|
||||
uint32_t categoryToBoostPriority = imgIRequest::CATEGORY_FRAME_INIT;
|
||||
|
@ -330,7 +377,9 @@ nsImageFrame::UpdateIntrinsicSize(imgIContainer* aImage)
|
|||
// Set intrinsic size to match aImage's reported intrinsic width & height.
|
||||
nsSize intrinsicSize;
|
||||
if (NS_SUCCEEDED(aImage->GetIntrinsicSize(&intrinsicSize))) {
|
||||
ScaleIntrinsicSizeForDensity(*mContent, intrinsicSize);
|
||||
if (mKind == Kind::ImageElement) {
|
||||
ScaleIntrinsicSizeForDensity(*mContent, intrinsicSize);
|
||||
}
|
||||
// If the image has no intrinsic width, intrinsicSize.width will be -1, and
|
||||
// we can leave mIntrinsicSize.width at its default value of eStyleUnit_None.
|
||||
// Otherwise we use intrinsicSize.width. Height works the same way.
|
||||
|
@ -408,8 +457,13 @@ bool
|
|||
nsImageFrame::IsPendingLoad(imgIRequest* aRequest) const
|
||||
{
|
||||
// Default to pending load in case of errors
|
||||
if (mKind == Kind::NonGeneratedContentProperty) {
|
||||
MOZ_ASSERT(aRequest == mContentURLRequest);
|
||||
return false;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIImageLoadingContent> imageLoader(do_QueryInterface(mContent));
|
||||
NS_ASSERTION(imageLoader, "No image loading content?");
|
||||
MOZ_ASSERT(imageLoader);
|
||||
|
||||
int32_t requestType = nsIImageLoadingContent::UNKNOWN_REQUEST;
|
||||
imageLoader->GetRequestType(aRequest, &requestType);
|
||||
|
@ -550,22 +604,12 @@ nsImageFrame::Notify(imgIRequest* aRequest,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
static bool
|
||||
SizeIsAvailable(imgIRequest* aRequest)
|
||||
{
|
||||
if (!aRequest)
|
||||
return false;
|
||||
|
||||
uint32_t imageStatus = 0;
|
||||
nsresult rv = aRequest->GetImageStatus(&imageStatus);
|
||||
|
||||
return NS_SUCCEEDED(rv) && (imageStatus & imgIRequest::STATUS_SIZE_AVAILABLE);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsImageFrame::OnSizeAvailable(imgIRequest* aRequest, imgIContainer* aImage)
|
||||
{
|
||||
if (!aImage) return NS_ERROR_INVALID_ARG;
|
||||
if (!aImage) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
/* Get requested animation policy from the pres context:
|
||||
* normal = 0
|
||||
|
@ -598,9 +642,13 @@ nsImageFrame::OnSizeAvailable(imgIRequest* aRequest, imgIContainer* aImage)
|
|||
intrinsicSizeChanged = true;
|
||||
}
|
||||
|
||||
if (!GotInitialReflow()) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
MarkNeedsDisplayItemRebuild();
|
||||
|
||||
if (intrinsicSizeChanged && GotInitialReflow()) {
|
||||
if (intrinsicSizeChanged) {
|
||||
// Now we need to reflow if we have an unconstrained size and have
|
||||
// already gotten the initial reflow
|
||||
if (!(mState & IMAGE_SIZECONSTRAINED)) {
|
||||
|
@ -821,46 +869,56 @@ nsImageFrame::EnsureIntrinsicSizeAndRatio()
|
|||
{
|
||||
// If mIntrinsicSize.width and height are 0, then we need to update from the
|
||||
// image container.
|
||||
if (mIntrinsicSize.width.GetUnit() == eStyleUnit_Coord &&
|
||||
mIntrinsicSize.width.GetCoordValue() == 0 &&
|
||||
mIntrinsicSize.height.GetUnit() == eStyleUnit_Coord &&
|
||||
mIntrinsicSize.height.GetCoordValue() == 0) {
|
||||
if (mIntrinsicSize.width.GetUnit() != eStyleUnit_Coord ||
|
||||
mIntrinsicSize.width.GetCoordValue() != 0 ||
|
||||
mIntrinsicSize.height.GetUnit() != eStyleUnit_Coord ||
|
||||
mIntrinsicSize.height.GetCoordValue() != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (mImage) {
|
||||
UpdateIntrinsicSize(mImage);
|
||||
UpdateIntrinsicRatio(mImage);
|
||||
} else {
|
||||
// image request is null or image size not known, probably an
|
||||
// invalid image specified
|
||||
if (!(GetStateBits() & NS_FRAME_GENERATED_CONTENT)) {
|
||||
bool imageInvalid = false;
|
||||
if (mImage) {
|
||||
UpdateIntrinsicSize(mImage);
|
||||
UpdateIntrinsicRatio(mImage);
|
||||
return;
|
||||
}
|
||||
|
||||
// check for broken images. valid null images (eg. img src="") are
|
||||
// not considered broken because they have no image requests
|
||||
if (nsCOMPtr<imgIRequest> currentRequest = GetCurrentRequest()) {
|
||||
uint32_t imageStatus;
|
||||
imageInvalid =
|
||||
NS_SUCCEEDED(currentRequest->GetImageStatus(&imageStatus)) &&
|
||||
(imageStatus & imgIRequest::STATUS_ERROR);
|
||||
} else if (nsCOMPtr<nsIImageLoadingContent> loader = do_QueryInterface(mContent)) {
|
||||
// check if images are user-disabled (or blocked for other
|
||||
// reasons)
|
||||
int16_t imageBlockingStatus;
|
||||
loader->GetImageBlockingStatus(&imageBlockingStatus);
|
||||
imageInvalid = imageBlockingStatus != nsIContentPolicy::ACCEPT;
|
||||
}
|
||||
// NOTE(emilio, https://github.com/w3c/csswg-drafts/issues/2832): WebKit
|
||||
// and Blink behave differently here for content: url(..), for now adapt to
|
||||
// Blink's behavior.
|
||||
const bool mayDisplayBrokenIcon = IsForNonGeneratedImageElement();
|
||||
if (!mayDisplayBrokenIcon) {
|
||||
return;
|
||||
}
|
||||
// image request is null or image size not known, probably an
|
||||
// invalid image specified
|
||||
bool imageInvalid = false;
|
||||
|
||||
// invalid image specified. make the image big enough for the "broken" icon
|
||||
if (imageInvalid) {
|
||||
nscoord edgeLengthToUse =
|
||||
nsPresContext::CSSPixelsToAppUnits(
|
||||
ICON_SIZE + (2 * (ICON_PADDING + ALT_BORDER_WIDTH)));
|
||||
mIntrinsicSize.width.SetCoordValue(edgeLengthToUse);
|
||||
mIntrinsicSize.height.SetCoordValue(edgeLengthToUse);
|
||||
mIntrinsicRatio.SizeTo(1, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
// check for broken images. valid null images (eg. img src="") are
|
||||
// not considered broken because they have no image requests
|
||||
if (nsCOMPtr<imgIRequest> currentRequest = GetCurrentRequest()) {
|
||||
uint32_t imageStatus;
|
||||
imageInvalid =
|
||||
NS_SUCCEEDED(currentRequest->GetImageStatus(&imageStatus)) &&
|
||||
(imageStatus & imgIRequest::STATUS_ERROR);
|
||||
} else {
|
||||
MOZ_ASSERT(mKind == Kind::ImageElement);
|
||||
|
||||
nsCOMPtr<nsIImageLoadingContent> loader = do_QueryInterface(mContent);
|
||||
MOZ_ASSERT(loader);
|
||||
// check if images are user-disabled (or blocked for other reasons)
|
||||
int16_t imageBlockingStatus;
|
||||
loader->GetImageBlockingStatus(&imageBlockingStatus);
|
||||
imageInvalid = imageBlockingStatus != nsIContentPolicy::ACCEPT;
|
||||
}
|
||||
|
||||
// invalid image specified. make the image big enough for the "broken" icon
|
||||
if (imageInvalid) {
|
||||
nscoord edgeLengthToUse =
|
||||
nsPresContext::CSSPixelsToAppUnits(
|
||||
ICON_SIZE + (2 * (ICON_PADDING + ALT_BORDER_WIDTH)));
|
||||
mIntrinsicSize.width.SetCoordValue(edgeLengthToUse);
|
||||
mIntrinsicSize.height.SetCoordValue(edgeLengthToUse);
|
||||
mIntrinsicRatio.SizeTo(1, 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1461,14 +1519,11 @@ nsImageFrame::DisplayAltFeedback(gfxContext& aRenderingContext,
|
|||
|
||||
// If there's still room, display the alt-text
|
||||
if (!inner.IsEmpty()) {
|
||||
nsIContent* content = GetContent();
|
||||
if (content) {
|
||||
nsAutoString altText;
|
||||
nsCSSFrameConstructor::GetAlternateTextFor(content->AsElement(),
|
||||
content->NodeInfo()->NameAtom(),
|
||||
altText);
|
||||
DisplayAltText(PresContext(), aRenderingContext, altText, inner);
|
||||
}
|
||||
nsAutoString altText;
|
||||
nsCSSFrameConstructor::GetAlternateTextFor(mContent->AsElement(),
|
||||
mContent->NodeInfo()->NameAtom(),
|
||||
altText);
|
||||
DisplayAltText(PresContext(), aRenderingContext, altText, inner);
|
||||
}
|
||||
|
||||
aRenderingContext.Restore();
|
||||
|
@ -1780,14 +1835,17 @@ nsImageFrame::PaintImage(gfxContext& aRenderingContext, nsPoint aPt,
|
|||
already_AddRefed<imgIRequest>
|
||||
nsImageFrame::GetCurrentRequest() const
|
||||
{
|
||||
nsCOMPtr<imgIRequest> request;
|
||||
if (mKind == Kind::NonGeneratedContentProperty) {
|
||||
return do_AddRef(mContentURLRequest);
|
||||
}
|
||||
|
||||
MOZ_ASSERT(!mContentURLRequest);
|
||||
|
||||
nsCOMPtr<imgIRequest> request;
|
||||
nsCOMPtr<nsIImageLoadingContent> imageLoader = do_QueryInterface(mContent);
|
||||
MOZ_ASSERT(imageLoader);
|
||||
|
||||
imageLoader->GetRequest(nsIImageLoadingContent::CURRENT_REQUEST,
|
||||
getter_AddRefs(request));
|
||||
|
||||
return request.forget();
|
||||
}
|
||||
|
||||
|
@ -2118,15 +2176,11 @@ void
|
|||
nsImageFrame::OnVisibilityChange(Visibility aNewVisibility,
|
||||
const Maybe<OnNonvisible>& aNonvisibleAction)
|
||||
{
|
||||
nsCOMPtr<nsIImageLoadingContent> imageLoader = do_QueryInterface(mContent);
|
||||
if (!imageLoader) {
|
||||
MOZ_ASSERT_UNREACHABLE("Should have an nsIImageLoadingContent");
|
||||
nsAtomicContainerFrame::OnVisibilityChange(aNewVisibility, aNonvisibleAction);
|
||||
return;
|
||||
if (mKind == Kind::ImageElement) {
|
||||
nsCOMPtr<nsIImageLoadingContent> imageLoader = do_QueryInterface(mContent);
|
||||
imageLoader->OnVisibilityChange(aNewVisibility, aNonvisibleAction);
|
||||
}
|
||||
|
||||
imageLoader->OnVisibilityChange(aNewVisibility, aNonvisibleAction);
|
||||
|
||||
if (aNewVisibility == Visibility::APPROXIMATELY_VISIBLE) {
|
||||
MaybeDecodeForPredictedSize();
|
||||
}
|
||||
|
|
|
@ -180,13 +180,42 @@ public:
|
|||
virtual bool ReflowFinished() override;
|
||||
virtual void ReflowCallbackCanceled() override;
|
||||
|
||||
// The kind of image frame we are.
|
||||
enum class Kind : uint8_t
|
||||
{
|
||||
// For an nsImageLoadingContent, including generated ::before and ::after
|
||||
// content, which are an nsGenConImageContent.
|
||||
ImageElement,
|
||||
// For css 'content: url(..)' on other elements.
|
||||
NonGeneratedContentProperty,
|
||||
};
|
||||
|
||||
// Whether this frame is for a non-generated image element, that is, one that
|
||||
// isn't a ::before / ::after.
|
||||
bool IsForNonGeneratedImageElement() const
|
||||
{
|
||||
return mKind == Kind::ImageElement &&
|
||||
!HasAnyStateBits(NS_FRAME_GENERATED_CONTENT);
|
||||
}
|
||||
|
||||
// Creates a suitable continuing frame for this frame.
|
||||
nsImageFrame* CreateContinuingFrame(nsIPresShell*, ComputedStyle*) const;
|
||||
|
||||
private:
|
||||
friend nsIFrame* NS_NewImageFrame(nsIPresShell*, ComputedStyle*);
|
||||
explicit nsImageFrame(ComputedStyle* aStyle)
|
||||
: nsImageFrame(aStyle, kClassID) {}
|
||||
friend nsIFrame* NS_NewImageFrameForContentProperty(nsIPresShell*, ComputedStyle*);
|
||||
|
||||
nsImageFrame(ComputedStyle* aStyle, Kind aKind)
|
||||
: nsImageFrame(aStyle, kClassID, aKind)
|
||||
{ }
|
||||
|
||||
nsImageFrame(ComputedStyle*, ClassID, Kind);
|
||||
|
||||
protected:
|
||||
nsImageFrame(ComputedStyle* aStyle, ClassID aID);
|
||||
nsImageFrame(ComputedStyle* aStyle, ClassID aID)
|
||||
: nsImageFrame(aStyle, aID, Kind::ImageElement)
|
||||
{ }
|
||||
|
||||
virtual ~nsImageFrame();
|
||||
|
||||
void EnsureIntrinsicSizeAndRatio();
|
||||
|
@ -338,12 +367,16 @@ private:
|
|||
|
||||
RefPtr<nsImageListener> mListener;
|
||||
|
||||
// An image request created for content: url(..).
|
||||
RefPtr<imgRequestProxy> mContentURLRequest;
|
||||
|
||||
nsCOMPtr<imgIContainer> mImage;
|
||||
nsCOMPtr<imgIContainer> mPrevImage;
|
||||
nsSize mComputedSize;
|
||||
mozilla::IntrinsicSize mIntrinsicSize;
|
||||
nsSize mIntrinsicRatio;
|
||||
|
||||
const Kind mKind;
|
||||
bool mDisplayingIcon;
|
||||
bool mFirstFrameComplete;
|
||||
bool mReflowCallbackPosted;
|
||||
|
|
|
@ -114,6 +114,7 @@
|
|||
#define IMAGE_MNG "video/x-mng"
|
||||
#define IMAGE_JNG "image/x-jng"
|
||||
#define IMAGE_SVG_XML "image/svg+xml"
|
||||
#define IMAGE_WEBP "image/webp"
|
||||
|
||||
#define MESSAGE_EXTERNAL_BODY "message/external-body"
|
||||
#define MESSAGE_NEWS "message/news"
|
||||
|
|
|
@ -1099,7 +1099,8 @@ nsHttpTransaction::Close(nsresult reason)
|
|||
if ((reason == NS_ERROR_NET_RESET ||
|
||||
reason == NS_OK ||
|
||||
reason == psm::GetXPCOMFromNSSError(SSL_ERROR_DOWNGRADE_WITH_EARLY_DATA)) &&
|
||||
(!(mCaps & NS_HTTP_STICKY_CONNECTION) || (mCaps & NS_HTTP_CONNECTION_RESTARTABLE))) {
|
||||
(!(mCaps & NS_HTTP_STICKY_CONNECTION) || (mCaps & NS_HTTP_CONNECTION_RESTARTABLE) ||
|
||||
(mEarlyDataDisposition == EARLY_425))) {
|
||||
|
||||
if (mForceRestart && NS_SUCCEEDED(Restart())) {
|
||||
if (mResponseHead) {
|
||||
|
|
|
@ -1 +1 @@
|
|||
93cbd336eaca
|
||||
c84a61acb17d
|
||||
|
|
|
@ -10,4 +10,3 @@
|
|||
*/
|
||||
|
||||
#error "Do not include this header file."
|
||||
|
||||
|
|
|
@ -37,6 +37,50 @@ TEST_P(TlsConnectGeneric, ServerAuthRsaChain) {
|
|||
EXPECT_EQ(2UL, chain_length);
|
||||
}
|
||||
|
||||
TEST_P(TlsConnectTls12Plus, ServerAuthRsaPss) {
|
||||
static const SSLSignatureScheme kSignatureSchemePss[] = {
|
||||
ssl_sig_rsa_pss_pss_sha256};
|
||||
|
||||
Reset(TlsAgent::kServerRsaPss);
|
||||
client_->SetSignatureSchemes(kSignatureSchemePss,
|
||||
PR_ARRAY_SIZE(kSignatureSchemePss));
|
||||
server_->SetSignatureSchemes(kSignatureSchemePss,
|
||||
PR_ARRAY_SIZE(kSignatureSchemePss));
|
||||
Connect();
|
||||
CheckKeys(ssl_kea_ecdh, ssl_grp_ec_curve25519, ssl_auth_rsa_pss,
|
||||
ssl_sig_rsa_pss_pss_sha256);
|
||||
}
|
||||
|
||||
// PSS doesn't work with TLS 1.0 or 1.1 because we can't signal it.
|
||||
TEST_P(TlsConnectPre12, ServerAuthRsaPssFails) {
|
||||
static const SSLSignatureScheme kSignatureSchemePss[] = {
|
||||
ssl_sig_rsa_pss_pss_sha256};
|
||||
|
||||
Reset(TlsAgent::kServerRsaPss);
|
||||
client_->SetSignatureSchemes(kSignatureSchemePss,
|
||||
PR_ARRAY_SIZE(kSignatureSchemePss));
|
||||
server_->SetSignatureSchemes(kSignatureSchemePss,
|
||||
PR_ARRAY_SIZE(kSignatureSchemePss));
|
||||
ConnectExpectAlert(server_, kTlsAlertHandshakeFailure);
|
||||
server_->CheckErrorCode(SSL_ERROR_NO_CYPHER_OVERLAP);
|
||||
client_->CheckErrorCode(SSL_ERROR_NO_CYPHER_OVERLAP);
|
||||
}
|
||||
|
||||
// Check that a PSS certificate with no parameters works.
|
||||
TEST_P(TlsConnectTls12Plus, ServerAuthRsaPssNoParameters) {
|
||||
static const SSLSignatureScheme kSignatureSchemePss[] = {
|
||||
ssl_sig_rsa_pss_pss_sha256};
|
||||
|
||||
Reset("rsa_pss_noparam");
|
||||
client_->SetSignatureSchemes(kSignatureSchemePss,
|
||||
PR_ARRAY_SIZE(kSignatureSchemePss));
|
||||
server_->SetSignatureSchemes(kSignatureSchemePss,
|
||||
PR_ARRAY_SIZE(kSignatureSchemePss));
|
||||
Connect();
|
||||
CheckKeys(ssl_kea_ecdh, ssl_grp_ec_curve25519, ssl_auth_rsa_pss,
|
||||
ssl_sig_rsa_pss_pss_sha256);
|
||||
}
|
||||
|
||||
TEST_P(TlsConnectGeneric, ServerAuthRsaPssChain) {
|
||||
Reset("rsa_pss_chain");
|
||||
Connect();
|
||||
|
@ -218,13 +262,13 @@ TEST_P(TlsConnectTls12, ClientAuthNoSigAlgsFallback) {
|
|||
CheckSigScheme(capture_cert_verify, 0, server_, ssl_sig_rsa_pkcs1_sha1, 1024);
|
||||
}
|
||||
|
||||
static const SSLSignatureScheme SignatureSchemeEcdsaSha384[] = {
|
||||
static const SSLSignatureScheme kSignatureSchemeEcdsaSha384[] = {
|
||||
ssl_sig_ecdsa_secp384r1_sha384};
|
||||
static const SSLSignatureScheme SignatureSchemeEcdsaSha256[] = {
|
||||
static const SSLSignatureScheme kSignatureSchemeEcdsaSha256[] = {
|
||||
ssl_sig_ecdsa_secp256r1_sha256};
|
||||
static const SSLSignatureScheme SignatureSchemeRsaSha384[] = {
|
||||
static const SSLSignatureScheme kSignatureSchemeRsaSha384[] = {
|
||||
ssl_sig_rsa_pkcs1_sha384};
|
||||
static const SSLSignatureScheme SignatureSchemeRsaSha256[] = {
|
||||
static const SSLSignatureScheme kSignatureSchemeRsaSha256[] = {
|
||||
ssl_sig_rsa_pkcs1_sha256};
|
||||
|
||||
static SSLNamedGroup NamedGroupForEcdsa384(uint16_t version) {
|
||||
|
@ -241,10 +285,10 @@ static SSLNamedGroup NamedGroupForEcdsa384(uint16_t version) {
|
|||
// for TLS 1.1 and 1.0, where they should be ignored.
|
||||
TEST_P(TlsConnectGeneric, SignatureAlgorithmServerAuth) {
|
||||
Reset(TlsAgent::kServerEcdsa384);
|
||||
client_->SetSignatureSchemes(SignatureSchemeEcdsaSha384,
|
||||
PR_ARRAY_SIZE(SignatureSchemeEcdsaSha384));
|
||||
server_->SetSignatureSchemes(SignatureSchemeEcdsaSha384,
|
||||
PR_ARRAY_SIZE(SignatureSchemeEcdsaSha384));
|
||||
client_->SetSignatureSchemes(kSignatureSchemeEcdsaSha384,
|
||||
PR_ARRAY_SIZE(kSignatureSchemeEcdsaSha384));
|
||||
server_->SetSignatureSchemes(kSignatureSchemeEcdsaSha384,
|
||||
PR_ARRAY_SIZE(kSignatureSchemeEcdsaSha384));
|
||||
Connect();
|
||||
CheckKeys(ssl_kea_ecdh, NamedGroupForEcdsa384(version_), ssl_auth_ecdsa,
|
||||
ssl_sig_ecdsa_secp384r1_sha384);
|
||||
|
@ -273,8 +317,8 @@ TEST_P(TlsConnectGeneric, SignatureAlgorithmClientOnly) {
|
|||
// Defaults on the client include the provided option.
|
||||
TEST_P(TlsConnectGeneric, SignatureAlgorithmServerOnly) {
|
||||
Reset(TlsAgent::kServerEcdsa384);
|
||||
server_->SetSignatureSchemes(SignatureSchemeEcdsaSha384,
|
||||
PR_ARRAY_SIZE(SignatureSchemeEcdsaSha384));
|
||||
server_->SetSignatureSchemes(kSignatureSchemeEcdsaSha384,
|
||||
PR_ARRAY_SIZE(kSignatureSchemeEcdsaSha384));
|
||||
Connect();
|
||||
CheckKeys(ssl_kea_ecdh, NamedGroupForEcdsa384(version_), ssl_auth_ecdsa,
|
||||
ssl_sig_ecdsa_secp384r1_sha384);
|
||||
|
@ -283,16 +327,16 @@ TEST_P(TlsConnectGeneric, SignatureAlgorithmServerOnly) {
|
|||
// In TLS 1.2, curve and hash aren't bound together.
|
||||
TEST_P(TlsConnectTls12, SignatureSchemeCurveMismatch) {
|
||||
Reset(TlsAgent::kServerEcdsa256);
|
||||
client_->SetSignatureSchemes(SignatureSchemeEcdsaSha384,
|
||||
PR_ARRAY_SIZE(SignatureSchemeEcdsaSha384));
|
||||
client_->SetSignatureSchemes(kSignatureSchemeEcdsaSha384,
|
||||
PR_ARRAY_SIZE(kSignatureSchemeEcdsaSha384));
|
||||
Connect();
|
||||
}
|
||||
|
||||
// In TLS 1.3, curve and hash are coupled.
|
||||
TEST_P(TlsConnectTls13, SignatureSchemeCurveMismatch) {
|
||||
Reset(TlsAgent::kServerEcdsa256);
|
||||
client_->SetSignatureSchemes(SignatureSchemeEcdsaSha384,
|
||||
PR_ARRAY_SIZE(SignatureSchemeEcdsaSha384));
|
||||
client_->SetSignatureSchemes(kSignatureSchemeEcdsaSha384,
|
||||
PR_ARRAY_SIZE(kSignatureSchemeEcdsaSha384));
|
||||
ConnectExpectAlert(server_, kTlsAlertHandshakeFailure);
|
||||
server_->CheckErrorCode(SSL_ERROR_UNSUPPORTED_SIGNATURE_ALGORITHM);
|
||||
client_->CheckErrorCode(SSL_ERROR_NO_CYPHER_OVERLAP);
|
||||
|
@ -301,16 +345,16 @@ TEST_P(TlsConnectTls13, SignatureSchemeCurveMismatch) {
|
|||
// Configuring a P-256 cert with only SHA-384 signatures is OK in TLS 1.2.
|
||||
TEST_P(TlsConnectTls12, SignatureSchemeBadConfig) {
|
||||
Reset(TlsAgent::kServerEcdsa256); // P-256 cert can't be used.
|
||||
server_->SetSignatureSchemes(SignatureSchemeEcdsaSha384,
|
||||
PR_ARRAY_SIZE(SignatureSchemeEcdsaSha384));
|
||||
server_->SetSignatureSchemes(kSignatureSchemeEcdsaSha384,
|
||||
PR_ARRAY_SIZE(kSignatureSchemeEcdsaSha384));
|
||||
Connect();
|
||||
}
|
||||
|
||||
// A P-256 certificate in TLS 1.3 needs a SHA-256 signature scheme.
|
||||
TEST_P(TlsConnectTls13, SignatureSchemeBadConfig) {
|
||||
Reset(TlsAgent::kServerEcdsa256); // P-256 cert can't be used.
|
||||
server_->SetSignatureSchemes(SignatureSchemeEcdsaSha384,
|
||||
PR_ARRAY_SIZE(SignatureSchemeEcdsaSha384));
|
||||
server_->SetSignatureSchemes(kSignatureSchemeEcdsaSha384,
|
||||
PR_ARRAY_SIZE(kSignatureSchemeEcdsaSha384));
|
||||
ConnectExpectAlert(server_, kTlsAlertHandshakeFailure);
|
||||
server_->CheckErrorCode(SSL_ERROR_UNSUPPORTED_SIGNATURE_ALGORITHM);
|
||||
client_->CheckErrorCode(SSL_ERROR_NO_CYPHER_OVERLAP);
|
||||
|
@ -319,10 +363,10 @@ TEST_P(TlsConnectTls13, SignatureSchemeBadConfig) {
|
|||
// Where there is no overlap on signature schemes, we still connect successfully
|
||||
// if we aren't going to use a signature.
|
||||
TEST_P(TlsConnectGenericPre13, SignatureAlgorithmNoOverlapStaticRsa) {
|
||||
client_->SetSignatureSchemes(SignatureSchemeRsaSha384,
|
||||
PR_ARRAY_SIZE(SignatureSchemeRsaSha384));
|
||||
server_->SetSignatureSchemes(SignatureSchemeRsaSha256,
|
||||
PR_ARRAY_SIZE(SignatureSchemeRsaSha256));
|
||||
client_->SetSignatureSchemes(kSignatureSchemeRsaSha384,
|
||||
PR_ARRAY_SIZE(kSignatureSchemeRsaSha384));
|
||||
server_->SetSignatureSchemes(kSignatureSchemeRsaSha256,
|
||||
PR_ARRAY_SIZE(kSignatureSchemeRsaSha256));
|
||||
EnableOnlyStaticRsaCiphers();
|
||||
Connect();
|
||||
CheckKeys(ssl_kea_rsa, ssl_auth_rsa_decrypt);
|
||||
|
@ -330,10 +374,10 @@ TEST_P(TlsConnectGenericPre13, SignatureAlgorithmNoOverlapStaticRsa) {
|
|||
|
||||
TEST_P(TlsConnectTls12Plus, SignatureAlgorithmNoOverlapEcdsa) {
|
||||
Reset(TlsAgent::kServerEcdsa256);
|
||||
client_->SetSignatureSchemes(SignatureSchemeEcdsaSha384,
|
||||
PR_ARRAY_SIZE(SignatureSchemeEcdsaSha384));
|
||||
server_->SetSignatureSchemes(SignatureSchemeEcdsaSha256,
|
||||
PR_ARRAY_SIZE(SignatureSchemeEcdsaSha256));
|
||||
client_->SetSignatureSchemes(kSignatureSchemeEcdsaSha384,
|
||||
PR_ARRAY_SIZE(kSignatureSchemeEcdsaSha384));
|
||||
server_->SetSignatureSchemes(kSignatureSchemeEcdsaSha256,
|
||||
PR_ARRAY_SIZE(kSignatureSchemeEcdsaSha256));
|
||||
ConnectExpectAlert(server_, kTlsAlertHandshakeFailure);
|
||||
client_->CheckErrorCode(SSL_ERROR_NO_CYPHER_OVERLAP);
|
||||
server_->CheckErrorCode(SSL_ERROR_UNSUPPORTED_SIGNATURE_ALGORITHM);
|
||||
|
@ -342,10 +386,10 @@ TEST_P(TlsConnectTls12Plus, SignatureAlgorithmNoOverlapEcdsa) {
|
|||
// Pre 1.2, a mismatch on signature algorithms shouldn't affect anything.
|
||||
TEST_P(TlsConnectPre12, SignatureAlgorithmNoOverlapEcdsa) {
|
||||
Reset(TlsAgent::kServerEcdsa256);
|
||||
client_->SetSignatureSchemes(SignatureSchemeEcdsaSha384,
|
||||
PR_ARRAY_SIZE(SignatureSchemeEcdsaSha384));
|
||||
server_->SetSignatureSchemes(SignatureSchemeEcdsaSha256,
|
||||
PR_ARRAY_SIZE(SignatureSchemeEcdsaSha256));
|
||||
client_->SetSignatureSchemes(kSignatureSchemeEcdsaSha384,
|
||||
PR_ARRAY_SIZE(kSignatureSchemeEcdsaSha384));
|
||||
server_->SetSignatureSchemes(kSignatureSchemeEcdsaSha256,
|
||||
PR_ARRAY_SIZE(kSignatureSchemeEcdsaSha256));
|
||||
Connect();
|
||||
}
|
||||
|
||||
|
@ -411,8 +455,8 @@ TEST_P(TlsConnectTls13, InconsistentSignatureSchemeAlert) {
|
|||
}
|
||||
|
||||
TEST_P(TlsConnectTls12Plus, RequestClientAuthWithSha384) {
|
||||
server_->SetSignatureSchemes(SignatureSchemeRsaSha384,
|
||||
PR_ARRAY_SIZE(SignatureSchemeRsaSha384));
|
||||
server_->SetSignatureSchemes(kSignatureSchemeRsaSha384,
|
||||
PR_ARRAY_SIZE(kSignatureSchemeRsaSha384));
|
||||
server_->RequestClientAuth(false);
|
||||
Connect();
|
||||
}
|
||||
|
@ -754,15 +798,15 @@ TEST_F(TlsAgentStreamTestServer, ConfigureCertRsaPkcs1SignAndKEX) {
|
|||
PRFileDesc* ssl_fd = agent_->ssl_fd();
|
||||
EXPECT_TRUE(SSLInt_HasCertWithAuthType(ssl_fd, ssl_auth_rsa_decrypt));
|
||||
EXPECT_TRUE(SSLInt_HasCertWithAuthType(ssl_fd, ssl_auth_rsa_sign));
|
||||
EXPECT_TRUE(SSLInt_HasCertWithAuthType(ssl_fd, ssl_auth_rsa_pss));
|
||||
EXPECT_FALSE(SSLInt_HasCertWithAuthType(ssl_fd, ssl_auth_rsa_pss));
|
||||
|
||||
// Configuring for only rsa_sign, rsa_pss, or rsa_decrypt should work.
|
||||
// Configuring for only rsa_sign or rsa_decrypt should work.
|
||||
EXPECT_TRUE(agent_->ConfigServerCert(TlsAgent::kServerRsa, false,
|
||||
&ServerCertDataRsaPkcs1Decrypt));
|
||||
EXPECT_TRUE(agent_->ConfigServerCert(TlsAgent::kServerRsa, false,
|
||||
&ServerCertDataRsaPkcs1Sign));
|
||||
EXPECT_TRUE(agent_->ConfigServerCert(TlsAgent::kServerRsa, false,
|
||||
&ServerCertDataRsaPss));
|
||||
EXPECT_FALSE(agent_->ConfigServerCert(TlsAgent::kServerRsa, false,
|
||||
&ServerCertDataRsaPss));
|
||||
}
|
||||
|
||||
// Test RSA cert with usage=[signature].
|
||||
|
@ -772,17 +816,17 @@ TEST_F(TlsAgentStreamTestServer, ConfigureCertRsaPkcs1Sign) {
|
|||
PRFileDesc* ssl_fd = agent_->ssl_fd();
|
||||
EXPECT_FALSE(SSLInt_HasCertWithAuthType(ssl_fd, ssl_auth_rsa_decrypt));
|
||||
EXPECT_TRUE(SSLInt_HasCertWithAuthType(ssl_fd, ssl_auth_rsa_sign));
|
||||
EXPECT_TRUE(SSLInt_HasCertWithAuthType(ssl_fd, ssl_auth_rsa_pss));
|
||||
EXPECT_FALSE(SSLInt_HasCertWithAuthType(ssl_fd, ssl_auth_rsa_pss));
|
||||
|
||||
// Configuring for only rsa_decrypt should fail.
|
||||
EXPECT_FALSE(agent_->ConfigServerCert(TlsAgent::kServerRsaSign, false,
|
||||
&ServerCertDataRsaPkcs1Decrypt));
|
||||
|
||||
// Configuring for only rsa_sign or rsa_pss should work.
|
||||
// Configuring for only rsa_sign should work.
|
||||
EXPECT_TRUE(agent_->ConfigServerCert(TlsAgent::kServerRsaSign, false,
|
||||
&ServerCertDataRsaPkcs1Sign));
|
||||
EXPECT_TRUE(agent_->ConfigServerCert(TlsAgent::kServerRsaSign, false,
|
||||
&ServerCertDataRsaPss));
|
||||
EXPECT_FALSE(agent_->ConfigServerCert(TlsAgent::kServerRsaSign, false,
|
||||
&ServerCertDataRsaPss));
|
||||
}
|
||||
|
||||
// Test RSA cert with usage=[encipherment].
|
||||
|
|
|
@ -84,6 +84,18 @@ class TlsCipherSuiteTestBase : public TlsConnectTestBase {
|
|||
Reset(TlsAgent::kRsa2048);
|
||||
auth_type_ = ssl_auth_rsa_sign;
|
||||
break;
|
||||
case ssl_sig_rsa_pss_pss_sha256:
|
||||
Reset(TlsAgent::kServerRsaPss);
|
||||
auth_type_ = ssl_auth_rsa_pss;
|
||||
break;
|
||||
case ssl_sig_rsa_pss_pss_sha384:
|
||||
Reset("rsa_pss384");
|
||||
auth_type_ = ssl_auth_rsa_pss;
|
||||
break;
|
||||
case ssl_sig_rsa_pss_pss_sha512:
|
||||
Reset("rsa_pss512");
|
||||
auth_type_ = ssl_auth_rsa_pss;
|
||||
break;
|
||||
case ssl_sig_ecdsa_secp256r1_sha256:
|
||||
Reset(TlsAgent::kServerEcdsa256);
|
||||
auth_type_ = ssl_auth_ecdsa;
|
||||
|
@ -310,14 +322,13 @@ static const auto kDummyNamedGroupParams = ::testing::Values(ssl_grp_none);
|
|||
static const auto kDummySignatureSchemesParams =
|
||||
::testing::Values(ssl_sig_none);
|
||||
|
||||
#ifndef NSS_DISABLE_TLS_1_3
|
||||
static SSLSignatureScheme kSignatureSchemesParamsArr[] = {
|
||||
ssl_sig_rsa_pkcs1_sha256, ssl_sig_rsa_pkcs1_sha384,
|
||||
ssl_sig_rsa_pkcs1_sha512, ssl_sig_ecdsa_secp256r1_sha256,
|
||||
ssl_sig_ecdsa_secp384r1_sha384, ssl_sig_rsa_pss_rsae_sha256,
|
||||
ssl_sig_rsa_pss_rsae_sha384, ssl_sig_rsa_pss_rsae_sha512,
|
||||
};
|
||||
#endif
|
||||
ssl_sig_rsa_pss_pss_sha256, ssl_sig_rsa_pss_pss_sha384,
|
||||
ssl_sig_rsa_pss_pss_sha512};
|
||||
|
||||
INSTANTIATE_CIPHER_TEST_P(RC4, Stream, V10ToV12, kDummyNamedGroupParams,
|
||||
kDummySignatureSchemesParams,
|
||||
|
@ -372,6 +383,14 @@ INSTANTIATE_CIPHER_TEST_P(
|
|||
TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, TLS_ECDH_RSA_WITH_AES_256_CBC_SHA,
|
||||
TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
|
||||
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA);
|
||||
INSTANTIATE_CIPHER_TEST_P(
|
||||
TLS12SigSchemes, All, V12, ::testing::ValuesIn(kFasterDHEGroups),
|
||||
::testing::ValuesIn(kSignatureSchemesParamsArr),
|
||||
TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, TLS_RSA_WITH_AES_256_CBC_SHA256,
|
||||
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,
|
||||
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, TLS_DHE_RSA_WITH_AES_128_CBC_SHA256,
|
||||
TLS_RSA_WITH_AES_128_CBC_SHA256, TLS_DHE_DSS_WITH_AES_128_CBC_SHA256,
|
||||
TLS_DHE_DSS_WITH_AES_256_CBC_SHA256);
|
||||
#ifndef NSS_DISABLE_TLS_1_3
|
||||
INSTANTIATE_CIPHER_TEST_P(TLS13, All, V13,
|
||||
::testing::ValuesIn(kFasterDHEGroups),
|
||||
|
|
|
@ -583,6 +583,7 @@ void TlsAgent::CheckAuthType(SSLAuthType auth,
|
|||
// switch statement because default label is different.
|
||||
switch (auth) {
|
||||
case ssl_auth_rsa_sign:
|
||||
case ssl_auth_rsa_pss:
|
||||
EXPECT_EQ(ssl_auth_rsa_decrypt, csinfo_.authAlgorithm)
|
||||
<< "authAlgorithm for RSA is always decrypt";
|
||||
break;
|
||||
|
|
|
@ -765,6 +765,9 @@ ssl_HasCert(const sslSocket *ss, SSLAuthType authType)
|
|||
}
|
||||
return PR_TRUE;
|
||||
}
|
||||
if (authType == ssl_auth_rsa_sign) {
|
||||
return ssl_HasCert(ss, ssl_auth_rsa_pss);
|
||||
}
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
|
@ -1120,6 +1123,8 @@ ssl3_SignHashes(sslSocket *ss, SSL3Hashes *hash, SECKEYPrivateKey *key,
|
|||
|
||||
if (ss->sec.isServer) {
|
||||
ss->sec.signatureScheme = ss->ssl3.hs.signatureScheme;
|
||||
ss->sec.authType =
|
||||
ssl_SignatureSchemeToAuthType(ss->ssl3.hs.signatureScheme);
|
||||
}
|
||||
PRINT_BUF(60, (NULL, "signed hashes", (unsigned char *)buf->data, buf->len));
|
||||
done:
|
||||
|
@ -1255,6 +1260,7 @@ ssl3_VerifySignedHashes(sslSocket *ss, SSLSignatureScheme scheme, SSL3Hashes *ha
|
|||
}
|
||||
if (!ss->sec.isServer) {
|
||||
ss->sec.signatureScheme = scheme;
|
||||
ss->sec.authType = ssl_SignatureSchemeToAuthType(scheme);
|
||||
}
|
||||
|
||||
loser:
|
||||
|
@ -4002,8 +4008,8 @@ ssl_SignatureSchemeToHashType(SSLSignatureScheme scheme)
|
|||
return ssl_hash_none;
|
||||
}
|
||||
|
||||
KeyType
|
||||
ssl_SignatureSchemeToKeyType(SSLSignatureScheme scheme)
|
||||
static PRBool
|
||||
ssl_SignatureSchemeMatchesSpkiOid(SSLSignatureScheme scheme, SECOidTag spkiOid)
|
||||
{
|
||||
switch (scheme) {
|
||||
case ssl_sig_rsa_pkcs1_sha256:
|
||||
|
@ -4013,133 +4019,243 @@ ssl_SignatureSchemeToKeyType(SSLSignatureScheme scheme)
|
|||
case ssl_sig_rsa_pss_rsae_sha256:
|
||||
case ssl_sig_rsa_pss_rsae_sha384:
|
||||
case ssl_sig_rsa_pss_rsae_sha512:
|
||||
case ssl_sig_rsa_pkcs1_sha1md5:
|
||||
return (spkiOid == SEC_OID_X500_RSA_ENCRYPTION) ||
|
||||
(spkiOid == SEC_OID_PKCS1_RSA_ENCRYPTION);
|
||||
case ssl_sig_rsa_pss_pss_sha256:
|
||||
case ssl_sig_rsa_pss_pss_sha384:
|
||||
case ssl_sig_rsa_pss_pss_sha512:
|
||||
case ssl_sig_rsa_pkcs1_sha1md5:
|
||||
return rsaKey;
|
||||
return spkiOid == SEC_OID_PKCS1_RSA_PSS_SIGNATURE;
|
||||
case ssl_sig_ecdsa_secp256r1_sha256:
|
||||
case ssl_sig_ecdsa_secp384r1_sha384:
|
||||
case ssl_sig_ecdsa_secp521r1_sha512:
|
||||
case ssl_sig_ecdsa_sha1:
|
||||
return ecKey;
|
||||
return spkiOid == SEC_OID_ANSIX962_EC_PUBLIC_KEY;
|
||||
case ssl_sig_dsa_sha256:
|
||||
case ssl_sig_dsa_sha384:
|
||||
case ssl_sig_dsa_sha512:
|
||||
case ssl_sig_dsa_sha1:
|
||||
return dsaKey;
|
||||
return spkiOid == SEC_OID_ANSIX9_DSA_SIGNATURE;
|
||||
case ssl_sig_none:
|
||||
case ssl_sig_ed25519:
|
||||
case ssl_sig_ed448:
|
||||
break;
|
||||
}
|
||||
PORT_Assert(0);
|
||||
return nullKey;
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
static SSLNamedGroup
|
||||
ssl_NamedGroupForSignatureScheme(SSLSignatureScheme scheme)
|
||||
{
|
||||
switch (scheme) {
|
||||
case ssl_sig_ecdsa_secp256r1_sha256:
|
||||
return ssl_grp_ec_secp256r1;
|
||||
case ssl_sig_ecdsa_secp384r1_sha384:
|
||||
return ssl_grp_ec_secp384r1;
|
||||
case ssl_sig_ecdsa_secp521r1_sha512:
|
||||
return ssl_grp_ec_secp521r1;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
PORT_Assert(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Validate that the signature scheme works for the given key.
|
||||
* If |allowSha1| is set, we allow the use of SHA-1.
|
||||
* If |matchGroup| is set, we also check that the group and hash match. */
|
||||
/* Validate that the signature scheme works for the given key type. */
|
||||
static PRBool
|
||||
ssl_SignatureSchemeValidForKey(PRBool allowSha1, PRBool matchGroup,
|
||||
KeyType keyType,
|
||||
const sslNamedGroupDef *ecGroup,
|
||||
SSLSignatureScheme scheme)
|
||||
ssl_SignatureSchemeValid(SSLSignatureScheme scheme, SECOidTag spkiOid,
|
||||
PRBool isTls13)
|
||||
{
|
||||
if (!ssl_IsSupportedSignatureScheme(scheme)) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
if (keyType != ssl_SignatureSchemeToKeyType(scheme)) {
|
||||
if (!ssl_SignatureSchemeMatchesSpkiOid(scheme, spkiOid)) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
if (!allowSha1 && ssl_SignatureSchemeToHashType(scheme) == ssl_hash_sha1) {
|
||||
return PR_FALSE;
|
||||
if (isTls13) {
|
||||
if (ssl_SignatureSchemeToHashType(scheme) == ssl_hash_sha1) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
/* With TLS 1.3, EC keys should have been selected based on calling
|
||||
* ssl_SignatureSchemeFromSpki(), reject them otherwise. */
|
||||
return spkiOid != SEC_OID_ANSIX962_EC_PUBLIC_KEY;
|
||||
}
|
||||
if (keyType != ecKey) {
|
||||
return PR_TRUE;
|
||||
}
|
||||
if (!ecGroup) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
/* If |allowSha1| is present and the scheme is ssl_sig_ecdsa_sha1, it's OK.
|
||||
* This scheme isn't bound to a specific group. */
|
||||
if (allowSha1 && (scheme == ssl_sig_ecdsa_sha1)) {
|
||||
return PR_TRUE;
|
||||
}
|
||||
if (!matchGroup) {
|
||||
return PR_TRUE;
|
||||
}
|
||||
return ecGroup->name == ssl_NamedGroupForSignatureScheme(scheme);
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
/* ssl3_CheckSignatureSchemeConsistency checks that the signature
|
||||
* algorithm identifier in |sigAndHash| is consistent with the public key in
|
||||
* |cert|. It also checks the hash algorithm against the configured signature
|
||||
* algorithms. If all the tests pass, SECSuccess is returned. Otherwise,
|
||||
* PORT_SetError is called and SECFailure is returned. */
|
||||
SECStatus
|
||||
ssl_CheckSignatureSchemeConsistency(
|
||||
sslSocket *ss, SSLSignatureScheme scheme, CERTCertificate *cert)
|
||||
static SECStatus
|
||||
ssl_SignatureSchemeFromPssSpki(CERTSubjectPublicKeyInfo *spki,
|
||||
SSLSignatureScheme *scheme)
|
||||
{
|
||||
unsigned int i;
|
||||
const sslNamedGroupDef *group = NULL;
|
||||
SECKEYPublicKey *key;
|
||||
KeyType keyType;
|
||||
PRBool isTLS13 = ss->version == SSL_LIBRARY_VERSION_TLS_1_3;
|
||||
SECKEYRSAPSSParams pssParam = { 0 };
|
||||
PORTCheapArenaPool arena;
|
||||
SECStatus rv;
|
||||
|
||||
key = CERT_ExtractPublicKey(cert);
|
||||
if (key == NULL) {
|
||||
ssl_MapLowLevelError(SSL_ERROR_EXTRACT_PUBLIC_KEY_FAILURE);
|
||||
/* The key doesn't have parameters, boo. */
|
||||
if (!spki->algorithm.parameters.len) {
|
||||
*scheme = ssl_sig_none;
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
PORT_InitCheapArena(&arena, DER_DEFAULT_CHUNKSIZE);
|
||||
rv = SEC_QuickDERDecodeItem(&arena.arena, &pssParam,
|
||||
SEC_ASN1_GET(SECKEY_RSAPSSParamsTemplate),
|
||||
&spki->algorithm.parameters);
|
||||
if (rv != SECSuccess) {
|
||||
goto loser;
|
||||
}
|
||||
/* Not having hashAlg means SHA-1 and we don't accept that. */
|
||||
if (!pssParam.hashAlg) {
|
||||
goto loser;
|
||||
}
|
||||
switch (SECOID_GetAlgorithmTag(pssParam.hashAlg)) {
|
||||
case SEC_OID_SHA256:
|
||||
*scheme = ssl_sig_rsa_pss_pss_sha256;
|
||||
break;
|
||||
case SEC_OID_SHA384:
|
||||
*scheme = ssl_sig_rsa_pss_pss_sha384;
|
||||
break;
|
||||
case SEC_OID_SHA512:
|
||||
*scheme = ssl_sig_rsa_pss_pss_sha512;
|
||||
break;
|
||||
default:
|
||||
goto loser;
|
||||
}
|
||||
|
||||
PORT_DestroyCheapArena(&arena);
|
||||
return SECSuccess;
|
||||
|
||||
loser:
|
||||
PORT_DestroyCheapArena(&arena);
|
||||
PORT_SetError(SSL_ERROR_BAD_CERTIFICATE);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
static SECStatus
|
||||
ssl_SignatureSchemeFromEcSpki(CERTSubjectPublicKeyInfo *spki,
|
||||
SSLSignatureScheme *scheme)
|
||||
{
|
||||
const sslNamedGroupDef *group;
|
||||
SECKEYPublicKey *key;
|
||||
|
||||
key = SECKEY_ExtractPublicKey(spki);
|
||||
if (!key) {
|
||||
PORT_SetError(SSL_ERROR_BAD_CERTIFICATE);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
keyType = SECKEY_GetPublicKeyType(key);
|
||||
if (keyType == ecKey) {
|
||||
group = ssl_ECPubKey2NamedGroup(key);
|
||||
}
|
||||
group = ssl_ECPubKey2NamedGroup(key);
|
||||
SECKEY_DestroyPublicKey(key);
|
||||
if (!group) {
|
||||
PORT_SetError(SSL_ERROR_BAD_CERTIFICATE);
|
||||
return SECFailure;
|
||||
}
|
||||
switch (group->name) {
|
||||
case ssl_grp_ec_secp256r1:
|
||||
*scheme = ssl_sig_ecdsa_secp256r1_sha256;
|
||||
return SECSuccess;
|
||||
case ssl_grp_ec_secp384r1:
|
||||
*scheme = ssl_sig_ecdsa_secp384r1_sha384;
|
||||
return SECSuccess;
|
||||
case ssl_grp_ec_secp521r1:
|
||||
*scheme = ssl_sig_ecdsa_secp521r1_sha512;
|
||||
return SECSuccess;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
PORT_SetError(SSL_ERROR_BAD_CERTIFICATE);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
/* Newer signature schemes are designed so that a single SPKI can be used with
|
||||
* that scheme. This determines that scheme from the SPKI. If the SPKI doesn't
|
||||
* have a single scheme, |*scheme| is set to ssl_sig_none. */
|
||||
static SECStatus
|
||||
ssl_SignatureSchemeFromSpki(CERTSubjectPublicKeyInfo *spki,
|
||||
PRBool isTls13, SSLSignatureScheme *scheme)
|
||||
{
|
||||
SECOidTag spkiOid = SECOID_GetAlgorithmTag(&spki->algorithm);
|
||||
|
||||
if (spkiOid == SEC_OID_PKCS1_RSA_PSS_SIGNATURE) {
|
||||
return ssl_SignatureSchemeFromPssSpki(spki, scheme);
|
||||
}
|
||||
|
||||
/* Only do this lookup for TLS 1.3, where the scheme can be determined from
|
||||
* the SPKI alone because the ECDSA key size determines the hash. Earlier
|
||||
* TLS versions allow the same EC key to be used with different hashes. */
|
||||
if (isTls13 && spkiOid == SEC_OID_ANSIX962_EC_PUBLIC_KEY) {
|
||||
return ssl_SignatureSchemeFromEcSpki(spki, scheme);
|
||||
}
|
||||
|
||||
*scheme = ssl_sig_none;
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
static PRBool
|
||||
ssl_SignatureSchemeEnabled(sslSocket *ss, SSLSignatureScheme scheme)
|
||||
{
|
||||
unsigned int i;
|
||||
for (i = 0; i < ss->ssl3.signatureSchemeCount; ++i) {
|
||||
if (scheme == ss->ssl3.signatureSchemes[i]) {
|
||||
return PR_TRUE;
|
||||
}
|
||||
}
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
static PRBool
|
||||
ssl_SignatureKeyMatchesSpkiOid(const ssl3KEADef *keaDef, SECOidTag spkiOid)
|
||||
{
|
||||
switch (spkiOid) {
|
||||
case SEC_OID_X500_RSA_ENCRYPTION:
|
||||
case SEC_OID_PKCS1_RSA_ENCRYPTION:
|
||||
case SEC_OID_PKCS1_RSA_PSS_SIGNATURE:
|
||||
return keaDef->signKeyType == rsaKey;
|
||||
case SEC_OID_ANSIX9_DSA_SIGNATURE:
|
||||
return keaDef->signKeyType == dsaKey;
|
||||
case SEC_OID_ANSIX962_EC_PUBLIC_KEY:
|
||||
return keaDef->signKeyType == ecKey;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
/* ssl3_CheckSignatureSchemeConsistency checks that the signature algorithm
|
||||
* identifier in |scheme| is consistent with the public key in |cert|. It also
|
||||
* checks the hash algorithm against the configured signature algorithms. If
|
||||
* all the tests pass, SECSuccess is returned. Otherwise, PORT_SetError is
|
||||
* called and SECFailure is returned. */
|
||||
SECStatus
|
||||
ssl_CheckSignatureSchemeConsistency(sslSocket *ss, SSLSignatureScheme scheme,
|
||||
CERTCertificate *cert)
|
||||
{
|
||||
SSLSignatureScheme spkiScheme;
|
||||
PRBool isTLS13 = ss->version == SSL_LIBRARY_VERSION_TLS_1_3;
|
||||
SECOidTag spkiOid;
|
||||
SECStatus rv;
|
||||
|
||||
rv = ssl_SignatureSchemeFromSpki(&cert->subjectPublicKeyInfo, isTLS13,
|
||||
&spkiScheme);
|
||||
if (rv != SECSuccess) {
|
||||
return SECFailure;
|
||||
}
|
||||
if (spkiScheme != ssl_sig_none) {
|
||||
/* The SPKI in the certificate can only be used for a single scheme. */
|
||||
if (spkiScheme != scheme ||
|
||||
!ssl_SignatureSchemeEnabled(ss, scheme)) {
|
||||
PORT_SetError(SSL_ERROR_INCORRECT_SIGNATURE_ALGORITHM);
|
||||
return SECFailure;
|
||||
}
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
spkiOid = SECOID_GetAlgorithmTag(&cert->subjectPublicKeyInfo.algorithm);
|
||||
|
||||
/* If we're a client, check that the signature algorithm matches the signing
|
||||
* key type of the cipher suite. */
|
||||
if (!isTLS13 &&
|
||||
!ss->sec.isServer &&
|
||||
ss->ssl3.hs.kea_def->signKeyType != keyType) {
|
||||
PORT_SetError(SSL_ERROR_INCORRECT_SIGNATURE_ALGORITHM);
|
||||
return SECFailure;
|
||||
if (!isTLS13 && !ss->sec.isServer) {
|
||||
if (!ssl_SignatureKeyMatchesSpkiOid(ss->ssl3.hs.kea_def, spkiOid)) {
|
||||
PORT_SetError(SSL_ERROR_INCORRECT_SIGNATURE_ALGORITHM);
|
||||
return SECFailure;
|
||||
}
|
||||
}
|
||||
|
||||
/* Verify that the signature scheme matches the signing key. */
|
||||
if (!ssl_SignatureSchemeValidForKey(!isTLS13 /* allowSha1 */,
|
||||
isTLS13 /* matchGroup */,
|
||||
keyType, group, scheme)) {
|
||||
if (!ssl_SignatureSchemeValid(scheme, spkiOid, isTLS13)) {
|
||||
PORT_SetError(SSL_ERROR_INCORRECT_SIGNATURE_ALGORITHM);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
for (i = 0; i < ss->ssl3.signatureSchemeCount; ++i) {
|
||||
if (scheme == ss->ssl3.signatureSchemes[i]) {
|
||||
return SECSuccess;
|
||||
}
|
||||
if (!ssl_SignatureSchemeEnabled(ss, scheme)) {
|
||||
PORT_SetError(SSL_ERROR_UNSUPPORTED_SIGNATURE_ALGORITHM);
|
||||
return SECFailure;
|
||||
}
|
||||
PORT_SetError(SSL_ERROR_UNSUPPORTED_SIGNATURE_ALGORITHM);
|
||||
return SECFailure;
|
||||
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
PRBool
|
||||
|
@ -4153,6 +4269,9 @@ ssl_IsSupportedSignatureScheme(SSLSignatureScheme scheme)
|
|||
case ssl_sig_rsa_pss_rsae_sha256:
|
||||
case ssl_sig_rsa_pss_rsae_sha384:
|
||||
case ssl_sig_rsa_pss_rsae_sha512:
|
||||
case ssl_sig_rsa_pss_pss_sha256:
|
||||
case ssl_sig_rsa_pss_pss_sha384:
|
||||
case ssl_sig_rsa_pss_pss_sha512:
|
||||
case ssl_sig_ecdsa_secp256r1_sha256:
|
||||
case ssl_sig_ecdsa_secp384r1_sha384:
|
||||
case ssl_sig_ecdsa_secp521r1_sha512:
|
||||
|
@ -4164,9 +4283,6 @@ ssl_IsSupportedSignatureScheme(SSLSignatureScheme scheme)
|
|||
return PR_TRUE;
|
||||
|
||||
case ssl_sig_rsa_pkcs1_sha1md5:
|
||||
case ssl_sig_rsa_pss_pss_sha256:
|
||||
case ssl_sig_rsa_pss_pss_sha384:
|
||||
case ssl_sig_rsa_pss_pss_sha512:
|
||||
case ssl_sig_none:
|
||||
case ssl_sig_ed25519:
|
||||
case ssl_sig_ed448:
|
||||
|
@ -4182,6 +4298,9 @@ ssl_IsRsaPssSignatureScheme(SSLSignatureScheme scheme)
|
|||
case ssl_sig_rsa_pss_rsae_sha256:
|
||||
case ssl_sig_rsa_pss_rsae_sha384:
|
||||
case ssl_sig_rsa_pss_rsae_sha512:
|
||||
case ssl_sig_rsa_pss_pss_sha256:
|
||||
case ssl_sig_rsa_pss_pss_sha384:
|
||||
case ssl_sig_rsa_pss_pss_sha512:
|
||||
return PR_TRUE;
|
||||
|
||||
default:
|
||||
|
@ -4190,6 +4309,41 @@ ssl_IsRsaPssSignatureScheme(SSLSignatureScheme scheme)
|
|||
return PR_FALSE;
|
||||
}
|
||||
|
||||
SSLAuthType
|
||||
ssl_SignatureSchemeToAuthType(SSLSignatureScheme scheme)
|
||||
{
|
||||
switch (scheme) {
|
||||
case ssl_sig_rsa_pkcs1_sha1:
|
||||
case ssl_sig_rsa_pkcs1_sha1md5:
|
||||
case ssl_sig_rsa_pkcs1_sha256:
|
||||
case ssl_sig_rsa_pkcs1_sha384:
|
||||
case ssl_sig_rsa_pkcs1_sha512:
|
||||
/* We report based on the key type for PSS signatures. */
|
||||
case ssl_sig_rsa_pss_rsae_sha256:
|
||||
case ssl_sig_rsa_pss_rsae_sha384:
|
||||
case ssl_sig_rsa_pss_rsae_sha512:
|
||||
return ssl_auth_rsa_sign;
|
||||
case ssl_sig_rsa_pss_pss_sha256:
|
||||
case ssl_sig_rsa_pss_pss_sha384:
|
||||
case ssl_sig_rsa_pss_pss_sha512:
|
||||
return ssl_auth_rsa_pss;
|
||||
case ssl_sig_ecdsa_secp256r1_sha256:
|
||||
case ssl_sig_ecdsa_secp384r1_sha384:
|
||||
case ssl_sig_ecdsa_secp521r1_sha512:
|
||||
case ssl_sig_ecdsa_sha1:
|
||||
return ssl_auth_ecdsa;
|
||||
case ssl_sig_dsa_sha1:
|
||||
case ssl_sig_dsa_sha256:
|
||||
case ssl_sig_dsa_sha384:
|
||||
case ssl_sig_dsa_sha512:
|
||||
return ssl_auth_dsa;
|
||||
|
||||
default:
|
||||
PORT_Assert(0);
|
||||
}
|
||||
return ssl_auth_null;
|
||||
}
|
||||
|
||||
/* ssl_ConsumeSignatureScheme reads a SSLSignatureScheme (formerly
|
||||
* SignatureAndHashAlgorithm) structure from |b| and puts the resulting value
|
||||
* into |out|. |b| and |length| are updated accordingly.
|
||||
|
@ -5394,6 +5548,7 @@ ssl3_GetWrappingKey(sslSocket *ss,
|
|||
switch (authType) {
|
||||
case ssl_auth_rsa_decrypt:
|
||||
case ssl_auth_rsa_sign: /* bad: see Bug 1248320 */
|
||||
case ssl_auth_rsa_pss:
|
||||
asymWrapMechanism = CKM_RSA_PKCS;
|
||||
rv = PK11_PubWrapSymKey(asymWrapMechanism, svrPubKey,
|
||||
unwrappedWrappingKey, &wrappedKey);
|
||||
|
@ -5843,20 +5998,59 @@ ssl3_SendClientKeyExchange(sslSocket *ss)
|
|||
return rv; /* err code already set. */
|
||||
}
|
||||
|
||||
/* Used by ssl_PickSignatureScheme(). */
|
||||
static PRBool
|
||||
ssl_CanUseSignatureScheme(SSLSignatureScheme scheme,
|
||||
const SSLSignatureScheme *peerSchemes,
|
||||
unsigned int peerSchemeCount,
|
||||
PRBool requireSha1,
|
||||
PRBool slotDoesPss)
|
||||
{
|
||||
SSLHashType hashType;
|
||||
SECOidTag hashOID;
|
||||
PRUint32 policy;
|
||||
unsigned int i;
|
||||
|
||||
/* Skip RSA-PSS schemes when the certificate's private key slot does
|
||||
* not support this signature mechanism. */
|
||||
if (ssl_IsRsaPssSignatureScheme(scheme) && !slotDoesPss) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
hashType = ssl_SignatureSchemeToHashType(scheme);
|
||||
if (requireSha1 && (hashType != ssl_hash_sha1)) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
hashOID = ssl3_HashTypeToOID(hashType);
|
||||
if ((NSS_GetAlgorithmPolicy(hashOID, &policy) == SECSuccess) &&
|
||||
!(policy & NSS_USE_ALG_IN_SSL_KX)) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
for (i = 0; i < peerSchemeCount; i++) {
|
||||
if (peerSchemes[i] == scheme) {
|
||||
return PR_TRUE;
|
||||
}
|
||||
}
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
SECStatus
|
||||
ssl_PickSignatureScheme(sslSocket *ss,
|
||||
CERTCertificate *cert,
|
||||
SECKEYPublicKey *pubKey,
|
||||
SECKEYPrivateKey *privKey,
|
||||
const SSLSignatureScheme *peerSchemes,
|
||||
unsigned int peerSchemeCount,
|
||||
PRBool requireSha1)
|
||||
{
|
||||
unsigned int i, j;
|
||||
const sslNamedGroupDef *group = NULL;
|
||||
KeyType keyType;
|
||||
unsigned int i;
|
||||
PK11SlotInfo *slot;
|
||||
PRBool slotDoesPss;
|
||||
PRBool isTLS13 = ss->version >= SSL_LIBRARY_VERSION_TLS_1_3;
|
||||
SECStatus rv;
|
||||
SSLSignatureScheme scheme;
|
||||
SECOidTag spkiOid;
|
||||
|
||||
/* We can't require SHA-1 in TLS 1.3. */
|
||||
PORT_Assert(!(requireSha1 && isTLS13));
|
||||
|
@ -5874,47 +6068,35 @@ ssl_PickSignatureScheme(sslSocket *ss,
|
|||
slotDoesPss = PK11_DoesMechanism(slot, auth_alg_defs[ssl_auth_rsa_pss]);
|
||||
PK11_FreeSlot(slot);
|
||||
|
||||
keyType = SECKEY_GetPublicKeyType(pubKey);
|
||||
if (keyType == ecKey) {
|
||||
group = ssl_ECPubKey2NamedGroup(pubKey);
|
||||
/* If the certificate SPKI indicates a single scheme, don't search. */
|
||||
rv = ssl_SignatureSchemeFromSpki(&cert->subjectPublicKeyInfo,
|
||||
isTLS13, &scheme);
|
||||
if (rv != SECSuccess) {
|
||||
return SECFailure;
|
||||
}
|
||||
if (scheme != ssl_sig_none) {
|
||||
if (!ssl_SignatureSchemeEnabled(ss, scheme) ||
|
||||
!ssl_CanUseSignatureScheme(scheme, peerSchemes, peerSchemeCount,
|
||||
requireSha1, slotDoesPss)) {
|
||||
PORT_SetError(SSL_ERROR_UNSUPPORTED_SIGNATURE_ALGORITHM);
|
||||
return SECFailure;
|
||||
}
|
||||
ss->ssl3.hs.signatureScheme = scheme;
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
/* Here we look for the first local preference that the client has
|
||||
* indicated support for in their signature_algorithms extension. */
|
||||
spkiOid = SECOID_GetAlgorithmTag(&cert->subjectPublicKeyInfo.algorithm);
|
||||
|
||||
/* Now we have to search based on the key type. Go through our preferred
|
||||
* schemes in order and find the first that can be used. */
|
||||
for (i = 0; i < ss->ssl3.signatureSchemeCount; ++i) {
|
||||
SSLHashType hashType;
|
||||
SECOidTag hashOID;
|
||||
SSLSignatureScheme preferred = ss->ssl3.signatureSchemes[i];
|
||||
PRUint32 policy;
|
||||
scheme = ss->ssl3.signatureSchemes[i];
|
||||
|
||||
if (!ssl_SignatureSchemeValidForKey(!isTLS13 /* allowSha1 */,
|
||||
isTLS13 /* matchGroup */,
|
||||
keyType, group, preferred)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Skip RSA-PSS schemes when the certificate's private key slot does
|
||||
* not support this signature mechanism. */
|
||||
if (ssl_IsRsaPssSignatureScheme(preferred) && !slotDoesPss) {
|
||||
continue;
|
||||
}
|
||||
|
||||
hashType = ssl_SignatureSchemeToHashType(preferred);
|
||||
if (requireSha1 && (hashType != ssl_hash_sha1)) {
|
||||
continue;
|
||||
}
|
||||
hashOID = ssl3_HashTypeToOID(hashType);
|
||||
if ((NSS_GetAlgorithmPolicy(hashOID, &policy) == SECSuccess) &&
|
||||
!(policy & NSS_USE_ALG_IN_SSL_KX)) {
|
||||
/* we ignore hashes we don't support */
|
||||
continue;
|
||||
}
|
||||
|
||||
for (j = 0; j < peerSchemeCount; j++) {
|
||||
if (peerSchemes[j] == preferred) {
|
||||
ss->ssl3.hs.signatureScheme = preferred;
|
||||
return SECSuccess;
|
||||
}
|
||||
if (ssl_SignatureSchemeValid(scheme, spkiOid, isTLS13) &&
|
||||
ssl_CanUseSignatureScheme(scheme, peerSchemes, peerSchemeCount,
|
||||
requireSha1, slotDoesPss)) {
|
||||
ss->ssl3.hs.signatureScheme = scheme;
|
||||
return SECSuccess;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5956,17 +6138,19 @@ ssl_PickFallbackSignatureScheme(sslSocket *ss, SECKEYPublicKey *pubKey)
|
|||
static SECStatus
|
||||
ssl3_PickServerSignatureScheme(sslSocket *ss)
|
||||
{
|
||||
sslKeyPair *keyPair = ss->sec.serverCert->serverKeyPair;
|
||||
const sslServerCert *cert = ss->sec.serverCert;
|
||||
PRBool isTLS12 = ss->version >= SSL_LIBRARY_VERSION_TLS_1_2;
|
||||
|
||||
if (!isTLS12 || !ssl3_ExtensionNegotiated(ss, ssl_signature_algorithms_xtn)) {
|
||||
/* If the client didn't provide any signature_algorithms extension then
|
||||
* we can assume that they support SHA-1: RFC5246, Section 7.4.1.4.1. */
|
||||
return ssl_PickFallbackSignatureScheme(ss, keyPair->pubKey);
|
||||
return ssl_PickFallbackSignatureScheme(ss, cert->serverKeyPair->pubKey);
|
||||
}
|
||||
|
||||
/* Sets error code, if needed. */
|
||||
return ssl_PickSignatureScheme(ss, keyPair->pubKey, keyPair->privKey,
|
||||
return ssl_PickSignatureScheme(ss, cert->serverCert,
|
||||
cert->serverKeyPair->pubKey,
|
||||
cert->serverKeyPair->privKey,
|
||||
ss->xtnData.sigSchemes,
|
||||
ss->xtnData.numSigSchemes,
|
||||
PR_FALSE /* requireSha1 */);
|
||||
|
@ -5977,11 +6161,10 @@ ssl_PickClientSignatureScheme(sslSocket *ss, const SSLSignatureScheme *schemes,
|
|||
unsigned int numSchemes)
|
||||
{
|
||||
SECKEYPrivateKey *privKey = ss->ssl3.clientPrivateKey;
|
||||
SECKEYPublicKey *pubKey;
|
||||
SECStatus rv;
|
||||
|
||||
PRBool isTLS13 = (PRBool)ss->version >= SSL_LIBRARY_VERSION_TLS_1_3;
|
||||
pubKey = CERT_ExtractPublicKey(ss->ssl3.clientCertificate);
|
||||
SECKEYPublicKey *pubKey = CERT_ExtractPublicKey(ss->ssl3.clientCertificate);
|
||||
|
||||
PORT_Assert(pubKey);
|
||||
|
||||
if (!isTLS13 && numSchemes == 0) {
|
||||
|
@ -6004,7 +6187,8 @@ ssl_PickClientSignatureScheme(sslSocket *ss, const SSLSignatureScheme *schemes,
|
|||
* older, DSA key size is at most 1024 bits and the hash function must
|
||||
* be SHA-1.
|
||||
*/
|
||||
rv = ssl_PickSignatureScheme(ss, pubKey, privKey, schemes, numSchemes,
|
||||
rv = ssl_PickSignatureScheme(ss, ss->ssl3.clientCertificate,
|
||||
pubKey, privKey, schemes, numSchemes,
|
||||
PR_TRUE /* requireSha1 */);
|
||||
if (rv == SECSuccess) {
|
||||
SECKEY_DestroyPublicKey(pubKey);
|
||||
|
@ -6013,7 +6197,8 @@ ssl_PickClientSignatureScheme(sslSocket *ss, const SSLSignatureScheme *schemes,
|
|||
/* If this fails, that's because the peer doesn't advertise SHA-1,
|
||||
* so fall back to the full negotiation. */
|
||||
}
|
||||
rv = ssl_PickSignatureScheme(ss, pubKey, privKey, schemes, numSchemes,
|
||||
rv = ssl_PickSignatureScheme(ss, ss->ssl3.clientCertificate,
|
||||
pubKey, privKey, schemes, numSchemes,
|
||||
PR_FALSE /* requireSha1 */);
|
||||
SECKEY_DestroyPublicKey(pubKey);
|
||||
return rv;
|
||||
|
@ -7845,6 +8030,7 @@ ssl3_SelectServerCert(sslSocket *ss)
|
|||
{
|
||||
const ssl3KEADef *kea_def = ss->ssl3.hs.kea_def;
|
||||
PRCList *cursor;
|
||||
SECStatus rv;
|
||||
|
||||
/* If the client didn't include the supported groups extension, assume just
|
||||
* P-256 support and disable all the other ECDHE groups. This also affects
|
||||
|
@ -7870,24 +8056,40 @@ ssl3_SelectServerCert(sslSocket *ss)
|
|||
cursor != &ss->serverCerts;
|
||||
cursor = PR_NEXT_LINK(cursor)) {
|
||||
sslServerCert *cert = (sslServerCert *)cursor;
|
||||
if (!SSL_CERT_IS(cert, kea_def->authKeyType)) {
|
||||
continue;
|
||||
}
|
||||
if (SSL_CERT_IS_EC(cert) &&
|
||||
!ssl_NamedGroupEnabled(ss, cert->namedCurve)) {
|
||||
continue;
|
||||
if (kea_def->authKeyType == ssl_auth_rsa_sign) {
|
||||
/* We consider PSS certificates here as well for TLS 1.2. */
|
||||
if (!SSL_CERT_IS(cert, ssl_auth_rsa_sign) &&
|
||||
(!SSL_CERT_IS(cert, ssl_auth_rsa_pss) ||
|
||||
ss->version < SSL_LIBRARY_VERSION_TLS_1_2)) {
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
if (!SSL_CERT_IS(cert, kea_def->authKeyType)) {
|
||||
continue;
|
||||
}
|
||||
if (SSL_CERT_IS_EC(cert) &&
|
||||
!ssl_NamedGroupEnabled(ss, cert->namedCurve)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/* Found one. */
|
||||
ss->sec.serverCert = cert;
|
||||
ss->sec.authType = kea_def->authKeyType;
|
||||
ss->sec.authKeyBits = cert->serverKeyBits;
|
||||
|
||||
/* Don't pick a signature scheme if we aren't going to use it. */
|
||||
if (kea_def->signKeyType == nullKey) {
|
||||
ss->sec.authType = kea_def->authKeyType;
|
||||
return SECSuccess;
|
||||
}
|
||||
return ssl3_PickServerSignatureScheme(ss);
|
||||
|
||||
rv = ssl3_PickServerSignatureScheme(ss);
|
||||
if (rv != SECSuccess) {
|
||||
return SECFailure;
|
||||
}
|
||||
ss->sec.authType =
|
||||
ssl_SignatureSchemeToAuthType(ss->ssl3.hs.signatureScheme);
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
PORT_SetError(SSL_ERROR_NO_CYPHER_OVERLAP);
|
||||
|
|
|
@ -436,8 +436,6 @@ ssl_GetCertificateAuthTypes(CERTCertificate *cert, SSLAuthType targetAuthType)
|
|||
case SEC_OID_PKCS1_RSA_ENCRYPTION:
|
||||
if (cert->keyUsage & KU_DIGITAL_SIGNATURE) {
|
||||
authTypes |= 1 << ssl_auth_rsa_sign;
|
||||
/* This certificate is RSA, assume that it's also PSS. */
|
||||
authTypes |= 1 << ssl_auth_rsa_pss;
|
||||
}
|
||||
|
||||
if (cert->keyUsage & KU_KEY_ENCIPHERMENT) {
|
||||
|
|
|
@ -1640,6 +1640,7 @@ SECStatus ssl3_FillInCachedSID(sslSocket *ss, sslSessionID *sid,
|
|||
const ssl3CipherSuiteDef *ssl_LookupCipherSuiteDef(ssl3CipherSuite suite);
|
||||
SECStatus ssl3_SelectServerCert(sslSocket *ss);
|
||||
SECStatus ssl_PickSignatureScheme(sslSocket *ss,
|
||||
CERTCertificate *cert,
|
||||
SECKEYPublicKey *pubKey,
|
||||
SECKEYPrivateKey *privKey,
|
||||
const SSLSignatureScheme *peerSchemes,
|
||||
|
@ -1647,7 +1648,7 @@ SECStatus ssl_PickSignatureScheme(sslSocket *ss,
|
|||
PRBool requireSha1);
|
||||
SECOidTag ssl3_HashTypeToOID(SSLHashType hashType);
|
||||
SSLHashType ssl_SignatureSchemeToHashType(SSLSignatureScheme scheme);
|
||||
KeyType ssl_SignatureSchemeToKeyType(SSLSignatureScheme scheme);
|
||||
SSLAuthType ssl_SignatureSchemeToAuthType(SSLSignatureScheme scheme);
|
||||
|
||||
SECStatus ssl3_SetupCipherSuite(sslSocket *ss, PRBool initHashes);
|
||||
SECStatus ssl_InsertRecordHeader(const sslSocket *ss, ssl3CipherSpec *cwSpec,
|
||||
|
|
|
@ -117,6 +117,7 @@ const char kHkdfLabelFinishedSecret[] = "finished";
|
|||
const char kHkdfLabelResumptionMasterSecret[] = "res master";
|
||||
const char kHkdfLabelExporterMasterSecret[] = "exp master";
|
||||
const char kHkdfLabelResumption[] = "resumption";
|
||||
const char kHkdfLabelTrafficUpdate[] = "traffic upd";
|
||||
const char kHkdfPurposeKey[] = "key";
|
||||
const char kHkdfPurposeIv[] = "iv";
|
||||
|
||||
|
@ -603,8 +604,8 @@ tls13_UpdateTrafficKeys(sslSocket *ss, CipherSpecDirection direction)
|
|||
secret = tls13_TrafficSecretRef(ss, direction);
|
||||
rv = tls13_HkdfExpandLabel(*secret, tls13_GetHash(ss),
|
||||
NULL, 0,
|
||||
kHkdfLabelApplicationTrafficSecret,
|
||||
strlen(kHkdfLabelApplicationTrafficSecret),
|
||||
kHkdfLabelTrafficUpdate,
|
||||
strlen(kHkdfLabelTrafficUpdate),
|
||||
tls13_GetHmacMechanism(ss),
|
||||
tls13_GetHashSize(ss),
|
||||
&updatedSecret);
|
||||
|
@ -1417,30 +1418,6 @@ tls13_NegotiateKeyExchange(sslSocket *ss,
|
|||
return SECSuccess;
|
||||
}
|
||||
|
||||
SSLAuthType
|
||||
ssl_SignatureSchemeToAuthType(SSLSignatureScheme scheme)
|
||||
{
|
||||
switch (scheme) {
|
||||
case ssl_sig_rsa_pkcs1_sha1:
|
||||
case ssl_sig_rsa_pkcs1_sha256:
|
||||
case ssl_sig_rsa_pkcs1_sha384:
|
||||
case ssl_sig_rsa_pkcs1_sha512:
|
||||
/* We report PSS signatures as being just RSA signatures. */
|
||||
case ssl_sig_rsa_pss_rsae_sha256:
|
||||
case ssl_sig_rsa_pss_rsae_sha384:
|
||||
case ssl_sig_rsa_pss_rsae_sha512:
|
||||
return ssl_auth_rsa_sign;
|
||||
case ssl_sig_ecdsa_secp256r1_sha256:
|
||||
case ssl_sig_ecdsa_secp384r1_sha384:
|
||||
case ssl_sig_ecdsa_secp521r1_sha512:
|
||||
case ssl_sig_ecdsa_sha1:
|
||||
return ssl_auth_ecdsa;
|
||||
default:
|
||||
PORT_Assert(0);
|
||||
}
|
||||
return ssl_auth_null;
|
||||
}
|
||||
|
||||
SECStatus
|
||||
tls13_SelectServerCert(sslSocket *ss)
|
||||
{
|
||||
|
@ -1469,6 +1446,7 @@ tls13_SelectServerCert(sslSocket *ss)
|
|||
}
|
||||
|
||||
rv = ssl_PickSignatureScheme(ss,
|
||||
cert->serverCert,
|
||||
cert->serverKeyPair->pubKey,
|
||||
cert->serverKeyPair->privKey,
|
||||
ss->xtnData.sigSchemes,
|
||||
|
|
|
@ -42,29 +42,38 @@ certscript() {
|
|||
make_cert() {
|
||||
name=$1
|
||||
type=$2
|
||||
unset type_args trust sign
|
||||
|
||||
# defaults
|
||||
type_args=()
|
||||
trust=',,'
|
||||
sign=(-x)
|
||||
sighash=(-Z SHA256)
|
||||
|
||||
case $type in
|
||||
dsa) type_args='-g 1024' ;;
|
||||
rsa) type_args='-g 1024' ;;
|
||||
rsa2048) type_args='-g 2048';type=rsa ;;
|
||||
rsa8192) type_args='-g 8192';type=rsa ;;
|
||||
rsapss) type_args='-g 1024 --pss';type=rsa ;;
|
||||
p256) type_args='-q nistp256';type=ec ;;
|
||||
p384) type_args='-q secp384r1';type=ec ;;
|
||||
p521) type_args='-q secp521r1';type=ec ;;
|
||||
rsa_ca) type_args='-g 1024';trust='CT,CT,CT';type=rsa ;;
|
||||
rsa_chain) type_args='-g 1024';sign='-c rsa_ca';type=rsa;;
|
||||
rsapss_ca) type_args='-g 1024 --pss';trust='CT,CT,CT';type=rsa ;;
|
||||
rsapss_chain) type_args='-g 1024';sign='-c rsa_pss_ca';type=rsa;;
|
||||
rsa_ca_rsapss_chain) type_args='-g 1024 --pss-sign';sign='-c rsa_ca';type=rsa;;
|
||||
ecdh_rsa) type_args='-q nistp256';sign='-c rsa_ca';type=ec ;;
|
||||
dsa) type_args=(-g 1024) ;;
|
||||
rsa) type_args=(-g 1024) ;;
|
||||
rsa2048) type_args=(-g 2048);type=rsa ;;
|
||||
rsa8192) type_args=(-g 8192);type=rsa ;;
|
||||
rsapss) type_args=(-g 1024 --pss);type=rsa ;;
|
||||
rsapss384) type_args=(-g 1024 --pss);type=rsa;sighash=(-Z SHA384) ;;
|
||||
rsapss512) type_args=(-g 2048 --pss);type=rsa;sighash=(-Z SHA512) ;;
|
||||
rsapss_noparam) type_args=(-g 2048 --pss);type=rsa;sighash=() ;;
|
||||
p256) type_args=(-q nistp256);type=ec ;;
|
||||
p384) type_args=(-q secp384r1);type=ec ;;
|
||||
p521) type_args=(-q secp521r1);type=ec ;;
|
||||
rsa_ca) type_args=(-g 1024);trust='CT,CT,CT';type=rsa ;;
|
||||
rsa_chain) type_args=(-g 1024);sign=(-c rsa_ca);type=rsa;;
|
||||
rsapss_ca) type_args=(-g 1024 --pss);trust='CT,CT,CT';type=rsa ;;
|
||||
rsapss_chain) type_args=(-g 1024);sign=(-c rsa_pss_ca);type=rsa;;
|
||||
rsa_ca_rsapss_chain) type_args=(-g 1024 --pss-sign);sign=(-c rsa_ca);type=rsa;;
|
||||
ecdh_rsa) type_args=(-q nistp256);sign=(-c rsa_ca);type=ec ;;
|
||||
esac
|
||||
shift 2
|
||||
counter=$(($counter + 1))
|
||||
certscript $@ | ${BINDIR}/certutil -S \
|
||||
-z ${R_NOISE_FILE} -d "${PROFILEDIR}" \
|
||||
-n $name -s "CN=$name" -t ${trust:-,,} ${sign:--x} -m $counter \
|
||||
-w -2 -v 120 -k $type $type_args -Z SHA256 -1 -2
|
||||
-n $name -s "CN=$name" -t "$trust" "${sign[@]}" -m "$counter" \
|
||||
-w -2 -v 120 -k "$type" "${type_args[@]}" "${sighash[@]}" -1 -2
|
||||
html_msg $? 0 "create certificate: $@"
|
||||
}
|
||||
|
||||
|
@ -87,6 +96,9 @@ ssl_gtest_certs() {
|
|||
make_cert rsa8192 rsa8192 sign kex
|
||||
make_cert rsa_sign rsa sign
|
||||
make_cert rsa_pss rsapss sign
|
||||
make_cert rsa_pss384 rsapss384 sign
|
||||
make_cert rsa_pss512 rsapss512 sign
|
||||
make_cert rsa_pss_noparam rsapss_noparam sign
|
||||
make_cert rsa_decrypt rsa kex
|
||||
make_cert ecdsa256 p256 sign
|
||||
make_cert ecdsa384 p384 sign
|
||||
|
|
|
@ -651,7 +651,10 @@ impl<'le> GeckoElement<'le> {
|
|||
#[inline]
|
||||
fn extended_slots(&self) -> Option<&structs::FragmentOrElement_nsExtendedDOMSlots> {
|
||||
self.dom_slots().and_then(|s| unsafe {
|
||||
(s._base.mExtendedSlots.mPtr as *const structs::FragmentOrElement_nsExtendedDOMSlots)
|
||||
// For the bit usage, see nsContentSlots::GetExtendedSlots.
|
||||
let e_slots = s._base.mExtendedSlots &
|
||||
!structs::nsIContent_nsContentSlots_sNonOwningExtendedSlotsFlag;
|
||||
(e_slots as *const structs::FragmentOrElement_nsExtendedDOMSlots)
|
||||
.as_ref()
|
||||
})
|
||||
}
|
||||
|
|
|
@ -10,6 +10,5 @@
|
|||
"startup.homepage_override_url": "",
|
||||
"startup.homepage_welcome_url": "",
|
||||
"browser.startup.homepage": "about:blank",
|
||||
"browser.newtabpage.enabled": false,
|
||||
"security.sandbox.content.level": 0
|
||||
"browser.newtabpage.enabled": false
|
||||
}
|
||||
|
|
|
@ -8,6 +8,5 @@
|
|||
"network.proxy.type": 1,
|
||||
"plugin.disable": true,
|
||||
"startup.homepage_override_url": "",
|
||||
"startup.homepage_welcome_url": "",
|
||||
"security.sandbox.content.level": 0
|
||||
"startup.homepage_welcome_url": ""
|
||||
}
|
||||
|
|
|
@ -153,6 +153,7 @@ class AWSY(TestingMixin, MercurialScript, TooltoolMixin, CodeCoverageMixin):
|
|||
'resultsDir': self.results_dir}
|
||||
|
||||
# Check if this is a DMD build and if so enable it.
|
||||
dmd_enabled = False
|
||||
dmd_py_lib_dir = os.path.dirname(self.binary_path)
|
||||
if mozinfo.os == 'mac':
|
||||
# On mac binary is in MacOS and dmd.py is in Resources, ie:
|
||||
|
@ -162,6 +163,7 @@ class AWSY(TestingMixin, MercurialScript, TooltoolMixin, CodeCoverageMixin):
|
|||
|
||||
dmd_path = os.path.join(dmd_py_lib_dir, "dmd.py")
|
||||
if os.path.isfile(dmd_path):
|
||||
dmd_enabled = True
|
||||
runtime_testvars['dmd'] = True
|
||||
|
||||
# Allow the child process to import dmd.py
|
||||
|
@ -208,6 +210,8 @@ class AWSY(TestingMixin, MercurialScript, TooltoolMixin, CodeCoverageMixin):
|
|||
prefs_file = "prefs.json"
|
||||
|
||||
cmd.append("--preferences=%s" % os.path.join(self.awsy_path, "conf", prefs_file))
|
||||
if dmd_enabled:
|
||||
cmd.append("--pref=security.sandbox.content.level:0")
|
||||
cmd.append(test_file)
|
||||
|
||||
if self.config['single_stylo_traversal']:
|
||||
|
|
|
@ -109435,6 +109435,42 @@
|
|||
{}
|
||||
]
|
||||
],
|
||||
"css/css-content/element-replacement-alt.html": [
|
||||
[
|
||||
"/css/css-content/element-replacement-alt.html",
|
||||
[
|
||||
[
|
||||
"/css/css-content/element-replacement-alt-ref.html",
|
||||
"=="
|
||||
]
|
||||
],
|
||||
{}
|
||||
]
|
||||
],
|
||||
"css/css-content/element-replacement-display-contents.html": [
|
||||
[
|
||||
"/css/css-content/element-replacement-display-contents.html",
|
||||
[
|
||||
[
|
||||
"/css/css-content/resources/blank.html",
|
||||
"=="
|
||||
]
|
||||
],
|
||||
{}
|
||||
]
|
||||
],
|
||||
"css/css-content/element-replacement-display-none.html": [
|
||||
[
|
||||
"/css/css-content/element-replacement-display-none.html",
|
||||
[
|
||||
[
|
||||
"/css/css-content/resources/blank.html",
|
||||
"=="
|
||||
]
|
||||
],
|
||||
{}
|
||||
]
|
||||
],
|
||||
"css/css-content/element-replacement.html": [
|
||||
[
|
||||
"/css/css-content/element-replacement.html",
|
||||
|
@ -240880,11 +240916,21 @@
|
|||
{}
|
||||
]
|
||||
],
|
||||
"css/css-content/element-replacement-alt-ref.html": [
|
||||
[
|
||||
{}
|
||||
]
|
||||
],
|
||||
"css/css-content/element-replacement-ref.html": [
|
||||
[
|
||||
{}
|
||||
]
|
||||
],
|
||||
"css/css-content/resources/blank.html": [
|
||||
[
|
||||
{}
|
||||
]
|
||||
],
|
||||
"css/css-content/resources/rect.svg": [
|
||||
[
|
||||
{}
|
||||
|
@ -502683,6 +502729,22 @@
|
|||
"6b6cf2c15295940fb8831d17209635dc4e31cd78",
|
||||
"reftest"
|
||||
],
|
||||
"css/css-content/element-replacement-alt-ref.html": [
|
||||
"6c67290991bc0ca57223e65a995054bae04bca0a",
|
||||
"support"
|
||||
],
|
||||
"css/css-content/element-replacement-alt.html": [
|
||||
"383ba1ffc142ae6d783cc9300b296b83b4b2521f",
|
||||
"reftest"
|
||||
],
|
||||
"css/css-content/element-replacement-display-contents.html": [
|
||||
"980d17c7c90c1de3f703423bcf41d0f14d25f4c1",
|
||||
"reftest"
|
||||
],
|
||||
"css/css-content/element-replacement-display-none.html": [
|
||||
"b30f852673badcc7f9cb8a39cc4a12452d886d6f",
|
||||
"reftest"
|
||||
],
|
||||
"css/css-content/element-replacement-ref.html": [
|
||||
"f1ad3fca133b1b671e45ae1307fbe9454c40e3ec",
|
||||
"support"
|
||||
|
@ -502691,6 +502753,10 @@
|
|||
"f491ddf2b3062ea2f9b616c968c88b9cc95f22eb",
|
||||
"reftest"
|
||||
],
|
||||
"css/css-content/resources/blank.html": [
|
||||
"d96d45f3a57b58460787fcde5fd15ccb324b123c",
|
||||
"support"
|
||||
],
|
||||
"css/css-content/resources/rect.svg": [
|
||||
"e0c37ea653aee58f962133219edc4484a734c6e0",
|
||||
"support"
|
||||
|
@ -549660,7 +549726,7 @@
|
|||
"support"
|
||||
],
|
||||
"css/mediaqueries/test_media_queries.html": [
|
||||
"cff3585932589f611a7101329d3b5b6ca27820aa",
|
||||
"a7d78b13e119f8cd1ffa8812a9af67e59280084d",
|
||||
"testharness"
|
||||
],
|
||||
"css/mediaqueries/viewport-script-dynamic-ref.html": [
|
||||
|
@ -561264,7 +561330,7 @@
|
|||
"support"
|
||||
],
|
||||
"docs/assets/pullrequestbtn.png": [
|
||||
"85e1015ecff6ee444168858cea8cd41804696905",
|
||||
"41213000ac1fb6ab53c6a1199744ecde452eef55",
|
||||
"support"
|
||||
],
|
||||
"docs/assets/reftest_graph_example.svg": [
|
||||
|
@ -618412,7 +618478,7 @@
|
|||
"testharness"
|
||||
],
|
||||
"web-animations/animation-model/animation-types/property-list.js": [
|
||||
"9416f470f1ac1d320bb4d46461938e85946439e2",
|
||||
"5a818163c3ddcb6e0901b4f0086d555e9d440e27",
|
||||
"support"
|
||||
],
|
||||
"web-animations/animation-model/animation-types/property-types.js": [
|
||||
|
|
|
@ -1,2 +0,0 @@
|
|||
[element-replacement.html]
|
||||
expected: FAIL
|
|
@ -0,0 +1,4 @@
|
|||
<!DOCTYPE html>
|
||||
<title>CSS Test Reference</title>
|
||||
<link rel="author" href="mailto:emilio@crisal.io" title="Emilio Cobos Álvarez">
|
||||
<div style="content: url(broken);"></div>
|
|
@ -0,0 +1,6 @@
|
|||
<!DOCTYPE html>
|
||||
<title>The content CSS property with a broken image doesn't pull the alt attribute from that element</title>
|
||||
<link rel="author" href="mailto:emilio@crisal.io" title="Emilio Cobos Álvarez">
|
||||
<link rel="match" href="element-replacement-alt-ref.html">
|
||||
<link rel="help" href="https://drafts.csswg.org/css-content-3/#content-property">
|
||||
<div style="content: url(broken);" alt="Alt text">FAIL</div>
|
|
@ -0,0 +1,12 @@
|
|||
<!doctype html>
|
||||
<title>The content CSS property doesn't override display: contents</title>
|
||||
<link rel="author" href="mailto:emilio@crisal.io" title="Emilio Cobos Álvarez">
|
||||
<link rel="match" href="resources/blank.html">
|
||||
<link rel="help" href="https://drafts.csswg.org/css-content-3/#content-property">
|
||||
<style>
|
||||
div {
|
||||
display: contents;
|
||||
content: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAAKElEQVR42u3NQQ0AAAgEoNP+nTWFDzcoQE1udQQCgUAgEAgEAsGTYAGjxAE/G/Q2tQAAAABJRU5ErkJggg==);
|
||||
}
|
||||
</style>
|
||||
<div></div>
|
|
@ -0,0 +1,12 @@
|
|||
<!doctype html>
|
||||
<title>The content CSS property doesn't override display: none</title>
|
||||
<link rel="author" href="mailto:emilio@crisal.io" title="Emilio Cobos Álvarez">
|
||||
<link rel="match" href="resources/blank.html">
|
||||
<link rel="help" href="https://drafts.csswg.org/css-content-3/#content-property">
|
||||
<style>
|
||||
div {
|
||||
display: none;
|
||||
content: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAAKElEQVR42u3NQQ0AAAgEoNP+nTWFDzcoQE1udQQCgUAgEAgEAsGTYAGjxAE/G/Q2tQAAAABJRU5ErkJggg==);
|
||||
}
|
||||
</style>
|
||||
<div>FAIL</div>
|
|
@ -0,0 +1,4 @@
|
|||
<!doctype html>
|
||||
<title>CSS Test Reference</title>
|
||||
<link rel="author" href="mailto:emilio@crisal.io" title="Emilio Cobos Álvarez">
|
||||
<!-- Intentionally blank -->
|
|
@ -740,13 +740,8 @@ AsyncFetchAndSetIconForPage::OnStopRequest(nsIRequest* aRequest,
|
|||
|
||||
nsresult rv;
|
||||
|
||||
// If fetching the icon failed, add it to the failed cache.
|
||||
// If fetching the icon failed, bail out.
|
||||
if (NS_FAILED(aStatusCode) || mIcon.payloads.Length() == 0) {
|
||||
nsCOMPtr<nsIURI> iconURI;
|
||||
rv = NS_NewURI(getter_AddRefs(iconURI), mIcon.spec);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = favicons->AddFailedFavicon(iconURI);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -769,13 +764,8 @@ AsyncFetchAndSetIconForPage::OnStopRequest(nsIRequest* aRequest,
|
|||
payload.mimeType);
|
||||
}
|
||||
|
||||
// If the icon does not have a valid MIME type, add it to the failed cache.
|
||||
// If the icon does not have a valid MIME type, bail out.
|
||||
if (payload.mimeType.IsEmpty()) {
|
||||
nsCOMPtr<nsIURI> iconURI;
|
||||
rv = NS_NewURI(getter_AddRefs(iconURI), mIcon.spec);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = favicons->AddFailedFavicon(iconURI);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -33,9 +33,6 @@
|
|||
#include "NullPrincipal.h"
|
||||
#include "imgICache.h"
|
||||
|
||||
#define MAX_FAILED_FAVICONS 256
|
||||
#define FAVICON_CACHE_REDUCE_COUNT 64
|
||||
|
||||
#define UNASSOCIATED_FAVICONS_LENGTH 32
|
||||
|
||||
// When replaceFaviconData is called, we store the icons in an in-memory cache
|
||||
|
@ -132,9 +129,7 @@ NS_IMPL_ISUPPORTS_CI(
|
|||
)
|
||||
|
||||
nsFaviconService::nsFaviconService()
|
||||
: mFailedFaviconSerial(0)
|
||||
, mFailedFavicons(MAX_FAILED_FAVICONS / 2)
|
||||
, mUnassociatedIcons(UNASSOCIATED_FAVICONS_LENGTH)
|
||||
: mUnassociatedIcons(UNASSOCIATED_FAVICONS_LENGTH)
|
||||
, mDefaultIconURIPreferredSize(UINT16_MAX)
|
||||
{
|
||||
NS_ASSERTION(!gFaviconService,
|
||||
|
@ -327,19 +322,6 @@ nsFaviconService::SetAndFetchFaviconForPage(nsIURI* aPageURI,
|
|||
NS_ENSURE_ARG(aFaviconURI);
|
||||
NS_ENSURE_ARG_POINTER(_canceler);
|
||||
|
||||
// If a favicon is in the failed cache, only load it during a forced reload.
|
||||
bool previouslyFailed;
|
||||
nsresult rv = IsFailedFavicon(aFaviconURI, &previouslyFailed);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (previouslyFailed) {
|
||||
if (aForceReload) {
|
||||
RemoveFailedFavicon(aFaviconURI);
|
||||
}
|
||||
else {
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIPrincipal> loadingPrincipal = aLoadingPrincipal;
|
||||
MOZ_ASSERT(loadingPrincipal, "please provide aLoadingPrincipal for this favicon");
|
||||
if (!loadingPrincipal) {
|
||||
|
@ -362,7 +344,7 @@ nsFaviconService::SetAndFetchFaviconForPage(nsIURI* aPageURI,
|
|||
|
||||
// Build page data.
|
||||
PageData page;
|
||||
rv = aPageURI->GetSpec(page.spec);
|
||||
nsresult rv = aPageURI->GetSpec(page.spec);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
// URIs can arguably lack a host.
|
||||
Unused << aPageURI->GetHost(page.host);
|
||||
|
@ -709,62 +691,6 @@ nsFaviconService::GetFaviconLinkForIcon(nsIURI* aFaviconURI,
|
|||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsFaviconService::AddFailedFavicon(nsIURI* aFaviconURI)
|
||||
{
|
||||
NS_ENSURE_ARG(aFaviconURI);
|
||||
|
||||
nsAutoCString spec;
|
||||
nsresult rv = aFaviconURI->GetSpec(spec);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
mFailedFavicons.Put(spec, mFailedFaviconSerial);
|
||||
mFailedFaviconSerial ++;
|
||||
|
||||
if (mFailedFavicons.Count() > MAX_FAILED_FAVICONS) {
|
||||
// need to expire some entries, delete the FAVICON_CACHE_REDUCE_COUNT number
|
||||
// of items that are the oldest
|
||||
uint32_t threshold = mFailedFaviconSerial -
|
||||
MAX_FAILED_FAVICONS + FAVICON_CACHE_REDUCE_COUNT;
|
||||
for (auto iter = mFailedFavicons.Iter(); !iter.Done(); iter.Next()) {
|
||||
if (iter.Data() < threshold) {
|
||||
iter.Remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsFaviconService::RemoveFailedFavicon(nsIURI* aFaviconURI)
|
||||
{
|
||||
NS_ENSURE_ARG(aFaviconURI);
|
||||
|
||||
nsAutoCString spec;
|
||||
nsresult rv = aFaviconURI->GetSpec(spec);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// we silently do nothing and succeed if the icon is not in the cache
|
||||
mFailedFavicons.Remove(spec);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsFaviconService::IsFailedFavicon(nsIURI* aFaviconURI, bool* _retval)
|
||||
{
|
||||
NS_ENSURE_ARG(aFaviconURI);
|
||||
nsAutoCString spec;
|
||||
nsresult rv = aFaviconURI->GetSpec(spec);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
uint32_t serial;
|
||||
*_retval = mFailedFavicons.Get(spec, &serial);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
// nsFaviconService::GetFaviconLinkForIconString
|
||||
//
|
||||
// This computes a favicon URL with string input and using the cached
|
||||
|
|
|
@ -150,9 +150,6 @@ private:
|
|||
*/
|
||||
nsCOMPtr<nsIURI> mDefaultIcon;
|
||||
|
||||
uint32_t mFailedFaviconSerial;
|
||||
nsDataHashtable<nsCStringHashKey, uint32_t> mFailedFavicons;
|
||||
|
||||
// This class needs access to the icons cache.
|
||||
friend class mozilla::places::AsyncReplaceFaviconData;
|
||||
nsTHashtable<UnassociatedIconHashKey> mUnassociatedIcons;
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче