mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Merge inbound to m-c. a=merge
CLOSED TREE
This commit is contained in:
commit
1235490c83
@ -1506,9 +1506,9 @@ pref("devtools.gcli.hideIntro", false);
|
||||
pref("devtools.gcli.eagerHelper", 2);
|
||||
|
||||
// Alias to the script URLs for inject command.
|
||||
pref("devtools.gcli.jquerySrc", "http://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js");
|
||||
pref("devtools.gcli.lodashSrc", "http://cdnjs.cloudflare.com/ajax/libs/lodash.js/2.4.1/lodash.min.js");
|
||||
pref("devtools.gcli.underscoreSrc", "http://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.6.0/underscore-min.js");
|
||||
pref("devtools.gcli.jquerySrc", "https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js");
|
||||
pref("devtools.gcli.lodashSrc", "https://cdnjs.cloudflare.com/ajax/libs/lodash.js/2.4.1/lodash.min.js");
|
||||
pref("devtools.gcli.underscoreSrc", "https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.7.0/underscore-min.js");
|
||||
|
||||
// Remember the Web Console filters
|
||||
pref("devtools.webconsole.filter.network", true);
|
||||
|
@ -2,6 +2,8 @@
|
||||
* 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/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
//****************************************************************************//
|
||||
// Constants & Enumeration Values
|
||||
|
||||
@ -1846,10 +1848,9 @@ var gApplicationsPane = {
|
||||
return this._getIconURLForSystemDefault(aHandlerInfo);
|
||||
|
||||
case Ci.nsIHandlerInfo.useHelperApp:
|
||||
let (preferredApp = aHandlerInfo.preferredApplicationHandler) {
|
||||
if (this.isValidHandlerApp(preferredApp))
|
||||
return this._getIconURLForHandlerApp(preferredApp);
|
||||
}
|
||||
let preferredApp = aHandlerInfo.preferredApplicationHandler;
|
||||
if (this.isValidHandlerApp(preferredApp))
|
||||
return this._getIconURLForHandlerApp(preferredApp);
|
||||
break;
|
||||
|
||||
// This should never happen, but if preferredAction is set to some weird
|
||||
|
@ -52,11 +52,15 @@ XPCOMUtils.defineLazyGetter(this, "_stringBundle", function() {
|
||||
.createBundle("chrome://browser/locale/taskbar.properties");
|
||||
});
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "PlacesUtils",
|
||||
"resource://gre/modules/PlacesUtils.jsm");
|
||||
XPCOMUtils.defineLazyGetter(this, "PlacesUtils", function() {
|
||||
Components.utils.import("resource://gre/modules/PlacesUtils.jsm");
|
||||
return PlacesUtils;
|
||||
});
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "NetUtil",
|
||||
"resource://gre/modules/NetUtil.jsm");
|
||||
XPCOMUtils.defineLazyGetter(this, "NetUtil", function() {
|
||||
Components.utils.import("resource://gre/modules/NetUtil.jsm");
|
||||
return NetUtil;
|
||||
});
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "_idle",
|
||||
"@mozilla.org/widget/idleservice;1",
|
||||
@ -73,16 +77,6 @@ XPCOMUtils.defineLazyServiceGetter(this, "_winShellService",
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "PrivateBrowsingUtils",
|
||||
"resource://gre/modules/PrivateBrowsingUtils.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "gHistoryObserver", function() {
|
||||
return Object.freeze({
|
||||
onClearHistory() {
|
||||
WinTaskbarJumpList.update();
|
||||
},
|
||||
QueryInterface: XPCOMUtils.generateQI(Ci.nsINavHistoryObserver),
|
||||
__noSuchMethod__: () => {}, // Catch all of the other notifications.
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* Global functions
|
||||
*/
|
||||
@ -152,7 +146,7 @@ this.WinTaskbarJumpList =
|
||||
|
||||
/**
|
||||
* Startup, shutdown, and update
|
||||
*/
|
||||
*/
|
||||
|
||||
startup: function WTBJL_startup() {
|
||||
// exit if this isn't win7 or higher.
|
||||
@ -161,7 +155,7 @@ this.WinTaskbarJumpList =
|
||||
|
||||
// Win shell shortcut maintenance. If we've gone through an update,
|
||||
// this will update any pinned taskbar shortcuts. Not specific to
|
||||
// jump lists, but this was a convienent place to call it.
|
||||
// jump lists, but this was a convienent place to call it.
|
||||
try {
|
||||
// dev builds may not have helper.exe, ignore failures.
|
||||
this._shortcutMaintenance();
|
||||
@ -192,6 +186,14 @@ this.WinTaskbarJumpList =
|
||||
|
||||
_shutdown: function WTBJL__shutdown() {
|
||||
this._shuttingDown = true;
|
||||
|
||||
// Correctly handle a clear history on shutdown. If there are no
|
||||
// entries be sure to empty all history lists. Luckily Places caches
|
||||
// this value, so it's a pretty fast call.
|
||||
if (!PlacesUtils.history.hasHistoryEntries) {
|
||||
this.update();
|
||||
}
|
||||
|
||||
this._free();
|
||||
},
|
||||
|
||||
@ -251,13 +253,13 @@ this.WinTaskbarJumpList =
|
||||
|
||||
/**
|
||||
* Taskbar api wrappers
|
||||
*/
|
||||
*/
|
||||
|
||||
_startBuild: function WTBJL__startBuild() {
|
||||
var removedItems = Cc["@mozilla.org/array;1"].
|
||||
createInstance(Ci.nsIMutableArray);
|
||||
this._builder.abortListBuild();
|
||||
if (this._builder.initListBuild(removedItems)) {
|
||||
if (this._builder.initListBuild(removedItems)) {
|
||||
// Prior to building, delete removed items from history.
|
||||
this._clearHistory(removedItems);
|
||||
return true;
|
||||
@ -281,7 +283,7 @@ this.WinTaskbarJumpList =
|
||||
task.args, task.iconIndex, null);
|
||||
items.appendElement(item, false);
|
||||
}, this);
|
||||
|
||||
|
||||
if (items.length > 0)
|
||||
this._builder.addListToBuild(this._builder.JUMPLIST_CATEGORY_TASKS, items);
|
||||
},
|
||||
@ -292,6 +294,11 @@ this.WinTaskbarJumpList =
|
||||
},
|
||||
|
||||
_buildFrequent: function WTBJL__buildFrequent() {
|
||||
// If history is empty, just bail out.
|
||||
if (!PlacesUtils.history.hasHistoryEntries) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Windows supports default frequent and recent lists,
|
||||
// but those depend on internal windows visit tracking
|
||||
// which we don't populate. So we build our own custom
|
||||
@ -317,7 +324,7 @@ this.WinTaskbarJumpList =
|
||||
|
||||
let title = aResult.title || aResult.uri;
|
||||
let faviconPageUri = Services.io.newURI(aResult.uri, null, null);
|
||||
let shortcut = this._getHandlerAppItem(title, title, aResult.uri, 1,
|
||||
let shortcut = this._getHandlerAppItem(title, title, aResult.uri, 1,
|
||||
faviconPageUri);
|
||||
items.appendElement(shortcut, false);
|
||||
this._frequentHashList.push(aResult.uri);
|
||||
@ -327,6 +334,11 @@ this.WinTaskbarJumpList =
|
||||
},
|
||||
|
||||
_buildRecent: function WTBJL__buildRecent() {
|
||||
// If history is empty, just bail out.
|
||||
if (!PlacesUtils.history.hasHistoryEntries) {
|
||||
return;
|
||||
}
|
||||
|
||||
var items = Cc["@mozilla.org/array;1"].
|
||||
createInstance(Ci.nsIMutableArray);
|
||||
// Frequent items will be skipped, so we select a double amount of
|
||||
@ -374,8 +386,8 @@ this.WinTaskbarJumpList =
|
||||
* Jump list item creation helpers
|
||||
*/
|
||||
|
||||
_getHandlerAppItem: function WTBJL__getHandlerAppItem(name, description,
|
||||
args, iconIndex,
|
||||
_getHandlerAppItem: function WTBJL__getHandlerAppItem(name, description,
|
||||
args, iconIndex,
|
||||
faviconPageUri) {
|
||||
var file = Services.dirsvc.get("XREExeF", Ci.nsILocalFile);
|
||||
|
||||
@ -457,7 +469,7 @@ this.WinTaskbarJumpList =
|
||||
|
||||
/**
|
||||
* Prefs utilities
|
||||
*/
|
||||
*/
|
||||
|
||||
_refreshPrefs: function WTBJL__refreshPrefs() {
|
||||
this._enabled = _prefs.getBoolPref(PREF_TASKBAR_ENABLED);
|
||||
@ -469,7 +481,7 @@ this.WinTaskbarJumpList =
|
||||
|
||||
/**
|
||||
* Init and shutdown utilities
|
||||
*/
|
||||
*/
|
||||
|
||||
_initTaskbar: function WTBJL__initTaskbar() {
|
||||
this._builder = _taskbarService.createJumpListBuilder();
|
||||
@ -486,14 +498,12 @@ this.WinTaskbarJumpList =
|
||||
Services.obs.addObserver(this, "profile-before-change", false);
|
||||
Services.obs.addObserver(this, "browser:purge-session-history", false);
|
||||
_prefs.addObserver("", this, false);
|
||||
PlacesUtils.history.addObserver(gHistoryObserver, false);
|
||||
},
|
||||
|
||||
|
||||
_freeObs: function WTBJL__freeObs() {
|
||||
Services.obs.removeObserver(this, "profile-before-change");
|
||||
Services.obs.removeObserver(this, "browser:purge-session-history");
|
||||
_prefs.removeObserver("", this);
|
||||
PlacesUtils.history.removeObserver(gHistoryObserver);
|
||||
},
|
||||
|
||||
_updateTimer: function WTBJL__updateTimer() {
|
||||
|
@ -33,7 +33,7 @@ if test -n "$ENABLE_CLANG_PLUGIN"; then
|
||||
AC_MSG_ERROR([Cannot find an llvm-config binary for building a clang plugin])
|
||||
fi
|
||||
LLVM_CXXFLAGS=`$LLVMCONFIG --cxxflags`
|
||||
LLVM_LDFLAGS=`$LLVMCONFIG --ldflags --libs core mc analysis asmparser mcparser bitreader | xargs`
|
||||
LLVM_LDFLAGS=`$LLVMCONFIG --ldflags --system-libs --libs core mc analysis asmparser mcparser bitreader option | xargs`
|
||||
|
||||
if test "${OS_ARCH}" = "Darwin"; then
|
||||
CLANG_LDFLAGS="-lclangFrontend -lclangDriver -lclangSerialization"
|
||||
|
@ -12,12 +12,19 @@
|
||||
#include "clang/Frontend/MultiplexConsumer.h"
|
||||
#include "clang/Sema/Sema.h"
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include <memory>
|
||||
|
||||
#define CLANG_VERSION_FULL (CLANG_VERSION_MAJOR * 100 + CLANG_VERSION_MINOR)
|
||||
|
||||
using namespace llvm;
|
||||
using namespace clang;
|
||||
|
||||
#if CLANG_VERSION_FULL >= 306
|
||||
typedef std::unique_ptr<ASTConsumer> ASTConsumerPtr;
|
||||
#else
|
||||
typedef ASTConsumer *ASTConsumerPtr;
|
||||
#endif
|
||||
|
||||
namespace {
|
||||
|
||||
using namespace clang::ast_matchers;
|
||||
@ -25,7 +32,7 @@ class DiagnosticsMatcher {
|
||||
public:
|
||||
DiagnosticsMatcher();
|
||||
|
||||
ASTConsumer *makeASTConsumer() {
|
||||
ASTConsumerPtr makeASTConsumer() {
|
||||
return astMatcher.newASTConsumer();
|
||||
}
|
||||
|
||||
@ -54,7 +61,7 @@ class MozChecker : public ASTConsumer, public RecursiveASTVisitor<MozChecker> {
|
||||
public:
|
||||
MozChecker(const CompilerInstance &CI) : Diag(CI.getDiagnostics()), CI(CI) {}
|
||||
|
||||
ASTConsumer *getOtherConsumer() {
|
||||
ASTConsumerPtr getOtherConsumer() {
|
||||
return matcher.makeASTConsumer();
|
||||
}
|
||||
|
||||
@ -375,15 +382,24 @@ void DiagnosticsMatcher::NonHeapClassChecker::noteInferred(QualType T,
|
||||
|
||||
class MozCheckAction : public PluginASTAction {
|
||||
public:
|
||||
ASTConsumer *CreateASTConsumer(CompilerInstance &CI, StringRef fileName) {
|
||||
ASTConsumerPtr CreateASTConsumer(CompilerInstance &CI, StringRef fileName) override {
|
||||
#if CLANG_VERSION_FULL >= 306
|
||||
std::unique_ptr<MozChecker> checker(make_unique<MozChecker>(CI));
|
||||
|
||||
std::vector<std::unique_ptr<ASTConsumer>> consumers;
|
||||
consumers.push_back(std::move(checker));
|
||||
consumers.push_back(checker->getOtherConsumer());
|
||||
return make_unique<MultiplexConsumer>(std::move(consumers));
|
||||
#else
|
||||
MozChecker *checker = new MozChecker(CI);
|
||||
|
||||
ASTConsumer *consumers[] = { checker, checker->getOtherConsumer() };
|
||||
return new MultiplexConsumer(consumers);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool ParseArgs(const CompilerInstance &CI,
|
||||
const std::vector<std::string> &args) {
|
||||
const std::vector<std::string> &args) override {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
@ -71,7 +71,7 @@ GCONF_VERSION=1.2.1
|
||||
GIO_VERSION=2.20
|
||||
STARTUP_NOTIFICATION_VERSION=0.8
|
||||
DBUS_VERSION=0.60
|
||||
SQLITE_VERSION=3.8.7.2
|
||||
SQLITE_VERSION=3.8.7.4
|
||||
|
||||
MSMANIFEST_TOOL=
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
This is SQLite 3.8.7.2
|
||||
This is SQLite 3.8.7.4
|
||||
|
||||
See http://www.sqlite.org/ for more info.
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
/******************************************************************************
|
||||
** This file is an amalgamation of many separate C source files from SQLite
|
||||
** version 3.8.7.2. By combining all the individual C code files into this
|
||||
** version 3.8.7.4. By combining all the individual C code files into this
|
||||
** single large file, the entire code can be compiled as a single translation
|
||||
** unit. This allows many compilers to do optimizations that would not be
|
||||
** possible if the files were compiled separately. Performance improvements
|
||||
@ -231,9 +231,9 @@ extern "C" {
|
||||
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
|
||||
** [sqlite_version()] and [sqlite_source_id()].
|
||||
*/
|
||||
#define SQLITE_VERSION "3.8.7.2"
|
||||
#define SQLITE_VERSION "3.8.7.4"
|
||||
#define SQLITE_VERSION_NUMBER 3008007
|
||||
#define SQLITE_SOURCE_ID "2014-11-18 20:57:56 2ab564bf9655b7c7b97ab85cafc8a48329b27f93"
|
||||
#define SQLITE_SOURCE_ID "2014-12-09 01:34:36 f66f7a17b78ba617acde90fc810107f34f1a1f2e"
|
||||
|
||||
/*
|
||||
** CAPI3REF: Run-Time Library Version Numbers
|
||||
@ -11537,7 +11537,7 @@ struct Expr {
|
||||
/*
|
||||
** The following are the meanings of bits in the Expr.flags field.
|
||||
*/
|
||||
#define EP_FromJoin 0x000001 /* Originated in ON or USING clause of a join */
|
||||
#define EP_FromJoin 0x000001 /* Originates in ON/USING clause of outer join */
|
||||
#define EP_Agg 0x000002 /* Contains one or more aggregate functions */
|
||||
#define EP_Resolved 0x000004 /* IDs have been resolved to COLUMNs */
|
||||
#define EP_Error 0x000008 /* Expression contains one or more errors */
|
||||
@ -11557,6 +11557,7 @@ struct Expr {
|
||||
#define EP_NoReduce 0x020000 /* Cannot EXPRDUP_REDUCE this Expr */
|
||||
#define EP_Unlikely 0x040000 /* unlikely() or likelihood() function */
|
||||
#define EP_Constant 0x080000 /* Node is a constant */
|
||||
#define EP_CanBeNull 0x100000 /* Can be null despite NOT NULL constraint */
|
||||
|
||||
/*
|
||||
** These macros can be used to test, set, or clear bits in the
|
||||
@ -79504,6 +79505,10 @@ static int lookupName(
|
||||
if( pMatch ){
|
||||
pExpr->iTable = pMatch->iCursor;
|
||||
pExpr->pTab = pMatch->pTab;
|
||||
assert( (pMatch->jointype & JT_RIGHT)==0 ); /* RIGHT JOIN not (yet) supported */
|
||||
if( (pMatch->jointype & JT_LEFT)!=0 ){
|
||||
ExprSetProperty(pExpr, EP_CanBeNull);
|
||||
}
|
||||
pSchema = pExpr->pTab->pSchema;
|
||||
}
|
||||
} /* if( pSrcList ) */
|
||||
@ -82040,7 +82045,8 @@ SQLITE_PRIVATE int sqlite3ExprCanBeNull(const Expr *p){
|
||||
return 0;
|
||||
case TK_COLUMN:
|
||||
assert( p->pTab!=0 );
|
||||
return p->iColumn>=0 && p->pTab->aCol[p->iColumn].notNull==0;
|
||||
return ExprHasProperty(p, EP_CanBeNull) ||
|
||||
(p->iColumn>=0 && p->pTab->aCol[p->iColumn].notNull==0);
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
@ -87415,7 +87421,7 @@ static void initAvgEq(Index *pIdx){
|
||||
i64 nSum100 = 0; /* Number of terms contributing to sumEq */
|
||||
i64 nDist100; /* Number of distinct values in index */
|
||||
|
||||
if( pIdx->aiRowEst==0 || pIdx->aiRowEst[iCol+1]==0 ){
|
||||
if( !pIdx->aiRowEst || iCol>=pIdx->nKeyCol || pIdx->aiRowEst[iCol+1]==0 ){
|
||||
nRow = pFinal->anLt[iCol];
|
||||
nDist100 = (i64)100 * pFinal->anDLt[iCol];
|
||||
nSample--;
|
||||
@ -125888,6 +125894,16 @@ SQLITE_PRIVATE void sqlite3LeaveMutexAndCloseZombie(sqlite3 *db){
|
||||
for(j=0; j<db->nDb; j++){
|
||||
struct Db *pDb = &db->aDb[j];
|
||||
if( pDb->pBt ){
|
||||
if( pDb->pSchema ){
|
||||
/* Must clear the KeyInfo cache. See ticket [e4a18565a36884b00edf] */
|
||||
sqlite3BtreeEnter(pDb->pBt);
|
||||
for(i=sqliteHashFirst(&pDb->pSchema->idxHash); i; i=sqliteHashNext(i)){
|
||||
Index *pIdx = sqliteHashData(i);
|
||||
sqlite3KeyInfoUnref(pIdx->pKeyInfo);
|
||||
pIdx->pKeyInfo = 0;
|
||||
}
|
||||
sqlite3BtreeLeave(pDb->pBt);
|
||||
}
|
||||
sqlite3BtreeClose(pDb->pBt);
|
||||
pDb->pBt = 0;
|
||||
if( j!=1 ){
|
||||
@ -127535,7 +127551,9 @@ static int openDatabase(
|
||||
sqlite3Error(db, rc);
|
||||
goto opendb_out;
|
||||
}
|
||||
sqlite3BtreeEnter(db->aDb[0].pBt);
|
||||
db->aDb[0].pSchema = sqlite3SchemaGet(db, db->aDb[0].pBt);
|
||||
sqlite3BtreeLeave(db->aDb[0].pBt);
|
||||
db->aDb[1].pSchema = sqlite3SchemaGet(db, 0);
|
||||
|
||||
/* The default safety_level for the main database is 'full'; for the temp
|
||||
|
@ -107,9 +107,9 @@ extern "C" {
|
||||
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
|
||||
** [sqlite_version()] and [sqlite_source_id()].
|
||||
*/
|
||||
#define SQLITE_VERSION "3.8.7.2"
|
||||
#define SQLITE_VERSION "3.8.7.4"
|
||||
#define SQLITE_VERSION_NUMBER 3008007
|
||||
#define SQLITE_SOURCE_ID "2014-11-18 20:57:56 2ab564bf9655b7c7b97ab85cafc8a48329b27f93"
|
||||
#define SQLITE_SOURCE_ID "2014-12-09 01:34:36 f66f7a17b78ba617acde90fc810107f34f1a1f2e"
|
||||
|
||||
/*
|
||||
** CAPI3REF: Run-Time Library Version Numbers
|
||||
|
@ -326,13 +326,12 @@ AutoJSAPI::~AutoJSAPI()
|
||||
errorGlobal = xpc::PrivilegedJunkScope();
|
||||
JSAutoCompartment ac(cx(), errorGlobal);
|
||||
nsCOMPtr<nsPIDOMWindow> win = xpc::WindowGlobalOrNull(errorGlobal);
|
||||
const char *category = nsContentUtils::IsCallerChrome() ? "chrome javascript"
|
||||
: "content javascript";
|
||||
JS::Rooted<JS::Value> exn(cx());
|
||||
js::ErrorReport jsReport(cx());
|
||||
if (StealException(&exn) && jsReport.init(cx(), exn)) {
|
||||
nsRefPtr<xpc::ErrorReport> xpcReport = new xpc::ErrorReport();
|
||||
xpcReport->Init(jsReport.report(), jsReport.message(), category,
|
||||
xpcReport->Init(jsReport.report(), jsReport.message(),
|
||||
nsContentUtils::IsCallerChrome(),
|
||||
win ? win->WindowID() : 0);
|
||||
if (win) {
|
||||
DispatchScriptErrorEvent(win, JS_GetRuntime(cx()), xpcReport, exn);
|
||||
@ -483,10 +482,9 @@ WarningOnlyErrorReporter(JSContext* aCx, const char* aMessage, JSErrorReport* aR
|
||||
{
|
||||
MOZ_ASSERT(JSREPORT_IS_WARNING(aRep->flags));
|
||||
nsRefPtr<xpc::ErrorReport> xpcReport = new xpc::ErrorReport();
|
||||
const char* category = nsContentUtils::IsCallerChrome() ? "chrome javascript"
|
||||
: "content javascript";
|
||||
nsPIDOMWindow* win = xpc::WindowGlobalOrNull(JS::CurrentGlobalOrNull(aCx));
|
||||
xpcReport->Init(aRep, aMessage, category, win ? win->WindowID() : 0);
|
||||
xpcReport->Init(aRep, aMessage, nsContentUtils::IsCallerChrome(),
|
||||
win ? win->WindowID() : 0);
|
||||
xpcReport->LogToConsole();
|
||||
}
|
||||
|
||||
|
@ -23,13 +23,13 @@ namespace dom {
|
||||
// JSContext.
|
||||
|
||||
// Accept strings.
|
||||
bool
|
||||
MOZ_WARN_UNUSED_RESULT bool
|
||||
ToJSValue(JSContext* aCx,
|
||||
const nsAString& aArgument,
|
||||
JS::MutableHandle<JS::Value> aValue);
|
||||
|
||||
// Accept booleans.
|
||||
inline bool
|
||||
MOZ_WARN_UNUSED_RESULT inline bool
|
||||
ToJSValue(JSContext* aCx,
|
||||
bool aArgument,
|
||||
JS::MutableHandle<JS::Value> aValue)
|
||||
@ -125,7 +125,7 @@ ToJSValue(JSContext* aCx,
|
||||
}
|
||||
|
||||
// Accept CallbackObjects
|
||||
inline bool
|
||||
MOZ_WARN_UNUSED_RESULT inline bool
|
||||
ToJSValue(JSContext* aCx,
|
||||
CallbackObject& aArgument,
|
||||
JS::MutableHandle<JS::Value> aValue)
|
||||
@ -141,6 +141,7 @@ ToJSValue(JSContext* aCx,
|
||||
// Accept objects that inherit from nsWrapperCache (e.g. most
|
||||
// DOM objects).
|
||||
template <class T>
|
||||
MOZ_WARN_UNUSED_RESULT
|
||||
typename EnableIf<IsBaseOf<nsWrapperCache, T>::value, bool>::Type
|
||||
ToJSValue(JSContext* aCx,
|
||||
T& aArgument,
|
||||
@ -156,6 +157,7 @@ ToJSValue(JSContext* aCx,
|
||||
|
||||
// Accept typed arrays built from appropriate nsTArray values
|
||||
template<typename T>
|
||||
MOZ_WARN_UNUSED_RESULT
|
||||
typename EnableIf<IsBaseOf<AllTypedArraysBase, T>::value, bool>::Type
|
||||
ToJSValue(JSContext* aCx,
|
||||
const TypedArrayCreator<T>& aArgument,
|
||||
@ -184,6 +186,7 @@ ISupportsToJSValue(JSContext* aCx,
|
||||
// Accept objects that inherit from nsISupports but not nsWrapperCache (e.g.
|
||||
// nsIDOMFile).
|
||||
template <class T>
|
||||
MOZ_WARN_UNUSED_RESULT
|
||||
typename EnableIf<!IsBaseOf<nsWrapperCache, T>::value &&
|
||||
!IsBaseOf<CallbackObject, T>::value &&
|
||||
IsBaseOf<nsISupports, T>::value, bool>::Type
|
||||
@ -199,7 +202,7 @@ ToJSValue(JSContext* aCx,
|
||||
|
||||
// Accept nsRefPtr/nsCOMPtr
|
||||
template <typename T>
|
||||
bool
|
||||
MOZ_WARN_UNUSED_RESULT bool
|
||||
ToJSValue(JSContext* aCx,
|
||||
const nsCOMPtr<T>& aArgument,
|
||||
JS::MutableHandle<JS::Value> aValue)
|
||||
@ -208,7 +211,7 @@ ToJSValue(JSContext* aCx,
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool
|
||||
MOZ_WARN_UNUSED_RESULT bool
|
||||
ToJSValue(JSContext* aCx,
|
||||
const nsRefPtr<T>& aArgument,
|
||||
JS::MutableHandle<JS::Value> aValue)
|
||||
@ -218,6 +221,7 @@ ToJSValue(JSContext* aCx,
|
||||
|
||||
// Accept WebIDL dictionaries
|
||||
template <class T>
|
||||
MOZ_WARN_UNUSED_RESULT
|
||||
typename EnableIf<IsBaseOf<DictionaryBase, T>::value, bool>::Type
|
||||
ToJSValue(JSContext* aCx,
|
||||
const T& aArgument,
|
||||
@ -227,7 +231,7 @@ ToJSValue(JSContext* aCx,
|
||||
}
|
||||
|
||||
// Accept existing JS values (which may not be same-compartment with us
|
||||
inline bool
|
||||
MOZ_WARN_UNUSED_RESULT inline bool
|
||||
ToJSValue(JSContext* aCx, JS::Handle<JS::Value> aArgument,
|
||||
JS::MutableHandle<JS::Value> aValue)
|
||||
{
|
||||
@ -236,7 +240,7 @@ ToJSValue(JSContext* aCx, JS::Handle<JS::Value> aArgument,
|
||||
}
|
||||
|
||||
// Accept existing JS values on the Heap (which may not be same-compartment with us
|
||||
inline bool
|
||||
MOZ_WARN_UNUSED_RESULT inline bool
|
||||
ToJSValue(JSContext* aCx, const JS::Heap<JS::Value>& aArgument,
|
||||
JS::MutableHandle<JS::Value> aValue)
|
||||
{
|
||||
@ -245,7 +249,7 @@ ToJSValue(JSContext* aCx, const JS::Heap<JS::Value>& aArgument,
|
||||
}
|
||||
|
||||
// Accept existing rooted JS values (which may not be same-compartment with us
|
||||
inline bool
|
||||
MOZ_WARN_UNUSED_RESULT inline bool
|
||||
ToJSValue(JSContext* aCx, const JS::Rooted<JS::Value>& aArgument,
|
||||
JS::MutableHandle<JS::Value> aValue)
|
||||
{
|
||||
@ -255,7 +259,7 @@ ToJSValue(JSContext* aCx, const JS::Rooted<JS::Value>& aArgument,
|
||||
|
||||
// Accept nsresult, for use in rejections, and create an XPCOM
|
||||
// exception object representing that nsresult.
|
||||
bool
|
||||
MOZ_WARN_UNUSED_RESULT bool
|
||||
ToJSValue(JSContext* aCx,
|
||||
nsresult aArgument,
|
||||
JS::MutableHandle<JS::Value> aValue);
|
||||
@ -263,13 +267,14 @@ ToJSValue(JSContext* aCx,
|
||||
// Accept ErrorResult, for use in rejections, and create an exception
|
||||
// representing the failure. Note, the ErrorResult must indicate a failure
|
||||
// with aArgument.Failure() returning true.
|
||||
bool
|
||||
MOZ_WARN_UNUSED_RESULT bool
|
||||
ToJSValue(JSContext* aCx,
|
||||
ErrorResult& aArgument,
|
||||
JS::MutableHandle<JS::Value> aValue);
|
||||
|
||||
// Accept pointers to other things we accept
|
||||
template <typename T>
|
||||
MOZ_WARN_UNUSED_RESULT
|
||||
typename EnableIf<IsPointer<T>::value, bool>::Type
|
||||
ToJSValue(JSContext* aCx,
|
||||
T aArgument,
|
||||
@ -280,7 +285,7 @@ ToJSValue(JSContext* aCx,
|
||||
|
||||
// Accept arrays of other things we accept
|
||||
template <typename T>
|
||||
bool
|
||||
MOZ_WARN_UNUSED_RESULT bool
|
||||
ToJSValue(JSContext* aCx,
|
||||
T* aArguments,
|
||||
size_t aLength,
|
||||
@ -307,7 +312,7 @@ ToJSValue(JSContext* aCx,
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool
|
||||
MOZ_WARN_UNUSED_RESULT bool
|
||||
ToJSValue(JSContext* aCx,
|
||||
const nsTArray<T>& aArgument,
|
||||
JS::MutableHandle<JS::Value> aValue)
|
||||
@ -317,7 +322,7 @@ ToJSValue(JSContext* aCx,
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool
|
||||
MOZ_WARN_UNUSED_RESULT bool
|
||||
ToJSValue(JSContext* aCx,
|
||||
const FallibleTArray<T>& aArgument,
|
||||
JS::MutableHandle<JS::Value> aValue)
|
||||
@ -327,7 +332,7 @@ ToJSValue(JSContext* aCx,
|
||||
}
|
||||
|
||||
template <typename T, int N>
|
||||
bool
|
||||
MOZ_WARN_UNUSED_RESULT bool
|
||||
ToJSValue(JSContext* aCx,
|
||||
const T(&aArgument)[N],
|
||||
JS::MutableHandle<JS::Value> aValue)
|
||||
|
@ -1003,9 +1003,8 @@ ContactDB.prototype = {
|
||||
}
|
||||
// Invalidate the entire cache. It will be incrementally regenerated on demand
|
||||
// See getCacheForQuery
|
||||
let (getAllStore = txn.objectStore(SAVED_GETALL_STORE_NAME)) {
|
||||
getAllStore.clear().onerror = errorCb;
|
||||
}
|
||||
let getAllStore = txn.objectStore(SAVED_GETALL_STORE_NAME);
|
||||
getAllStore.clear().onerror = errorCb;
|
||||
}.bind(this);
|
||||
|
||||
this.incrementRevision(txn);
|
||||
|
@ -3233,7 +3233,11 @@ ContentParent::DeallocPNeckoParent(PNeckoParent* necko)
|
||||
PPrintingParent*
|
||||
ContentParent::AllocPPrintingParent()
|
||||
{
|
||||
#ifdef NS_PRINTING
|
||||
return new PrintingParent();
|
||||
#else
|
||||
return nullptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -14,6 +14,8 @@
|
||||
#include "mozilla/Base64.h"
|
||||
#include "nsIRandomGenerator.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "MediaTaskQueue.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
namespace mozilla {
|
||||
@ -269,5 +271,24 @@ GenerateRandomPathName(nsCString& aOutSalt, uint32_t aLength)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
class CreateTaskQueueTask : public nsRunnable {
|
||||
public:
|
||||
NS_IMETHOD Run() {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
mTaskQueue = new MediaTaskQueue(GetMediaDecodeThreadPool());
|
||||
return NS_OK;
|
||||
}
|
||||
nsRefPtr<MediaTaskQueue> mTaskQueue;
|
||||
};
|
||||
|
||||
already_AddRefed<MediaTaskQueue>
|
||||
CreateMediaDecodeTaskQueue()
|
||||
{
|
||||
// We must create the MediaTaskQueue/SharedThreadPool on the main thread.
|
||||
nsRefPtr<CreateTaskQueueTask> t(new CreateTaskQueueTask());
|
||||
nsresult rv = NS_DispatchToMainThread(t, NS_DISPATCH_SYNC);
|
||||
NS_ENSURE_SUCCESS(rv, nullptr);
|
||||
return t->mTaskQueue.forget();
|
||||
}
|
||||
|
||||
} // end namespace mozilla
|
||||
|
@ -263,6 +263,11 @@ ExtractH264CodecDetails(const nsAString& aCodecs,
|
||||
nsresult
|
||||
GenerateRandomPathName(nsCString& aOutSalt, uint32_t aLength);
|
||||
|
||||
class MediaTaskQueue;
|
||||
|
||||
already_AddRefed<MediaTaskQueue>
|
||||
CreateMediaDecodeTaskQueue();
|
||||
|
||||
} // end namespace mozilla
|
||||
|
||||
#endif
|
||||
|
@ -319,7 +319,8 @@ bool
|
||||
MP4Reader::IsSupportedVideoMimeType(const char* aMimeType)
|
||||
{
|
||||
return (!strcmp(aMimeType, "video/mp4") ||
|
||||
!strcmp(aMimeType, "video/avc")) &&
|
||||
!strcmp(aMimeType, "video/avc") ||
|
||||
!strcmp(aMimeType, "video/x-vnd.on2.vp6")) &&
|
||||
mPlatform->SupportsVideoMimeType(aMimeType);
|
||||
}
|
||||
|
||||
@ -339,11 +340,6 @@ MP4Reader::ReadMetadata(MediaInfo* aInfo,
|
||||
// To decode, we need valid video and a place to put it.
|
||||
mInfo.mVideo.mHasVideo = mVideo.mActive = mDemuxer->HasValidVideo() &&
|
||||
mDecoder->GetImageContainer();
|
||||
const VideoDecoderConfig& video = mDemuxer->VideoConfig();
|
||||
// If we have video, we *only* allow H.264 to be decoded.
|
||||
if (mInfo.mVideo.mHasVideo && strcmp(video.mime_type, "video/avc")) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
mInfo.mAudio.mHasAudio = mAudio.mActive = mDemuxer->HasValidAudio();
|
||||
|
||||
|
@ -75,26 +75,6 @@ PlatformDecoderModule::Init()
|
||||
}
|
||||
|
||||
#ifdef MOZ_EME
|
||||
class CreateTaskQueueTask : public nsRunnable {
|
||||
public:
|
||||
NS_IMETHOD Run() {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
mTaskQueue = new MediaTaskQueue(GetMediaDecodeThreadPool());
|
||||
return NS_OK;
|
||||
}
|
||||
nsRefPtr<MediaTaskQueue> mTaskQueue;
|
||||
};
|
||||
|
||||
static already_AddRefed<MediaTaskQueue>
|
||||
CreateTaskQueue()
|
||||
{
|
||||
// We must create the MediaTaskQueue/SharedThreadPool on the main thread.
|
||||
nsRefPtr<CreateTaskQueueTask> t(new CreateTaskQueueTask());
|
||||
nsresult rv = NS_DispatchToMainThread(t, NS_DISPATCH_SYNC);
|
||||
NS_ENSURE_SUCCESS(rv, nullptr);
|
||||
return t->mTaskQueue.forget();
|
||||
}
|
||||
|
||||
/* static */
|
||||
PlatformDecoderModule*
|
||||
PlatformDecoderModule::CreateCDMWrapper(CDMProxy* aProxy,
|
||||
@ -123,8 +103,7 @@ PlatformDecoderModule::CreateCDMWrapper(CDMProxy* aProxy,
|
||||
return new EMEDecoderModule(aProxy,
|
||||
pdm.forget(),
|
||||
cdmDecodesAudio,
|
||||
cdmDecodesVideo,
|
||||
CreateTaskQueue());
|
||||
cdmDecodesVideo);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include "mozilla/EMELog.h"
|
||||
#include "EMEH264Decoder.h"
|
||||
#include "EMEAudioDecoder.h"
|
||||
#include "mozilla/unused.h"
|
||||
#include <string>
|
||||
|
||||
namespace mozilla {
|
||||
@ -31,19 +32,19 @@ public:
|
||||
|
||||
EMEDecryptor(MediaDataDecoder* aDecoder,
|
||||
MediaDataDecoderCallback* aCallback,
|
||||
MediaTaskQueue* aTaskQueue,
|
||||
CDMProxy* aProxy)
|
||||
: mDecoder(aDecoder)
|
||||
, mCallback(aCallback)
|
||||
, mTaskQueue(aTaskQueue)
|
||||
, mTaskQueue(CreateMediaDecodeTaskQueue())
|
||||
, mProxy(aProxy)
|
||||
{
|
||||
}
|
||||
|
||||
virtual nsresult Init() MOZ_OVERRIDE {
|
||||
return mTaskQueue->SyncDispatch(
|
||||
NS_NewRunnableMethod(mDecoder,
|
||||
&MediaDataDecoder::Init));
|
||||
nsresult rv = mTaskQueue->SyncDispatch(
|
||||
NS_NewRunnableMethod(mDecoder, &MediaDataDecoder::Init));
|
||||
unused << NS_WARN_IF(NS_FAILED(rv));
|
||||
return rv;
|
||||
}
|
||||
|
||||
class RedeliverEncryptedInput : public nsRunnable {
|
||||
@ -123,40 +124,44 @@ public:
|
||||
}
|
||||
|
||||
void Decrypted(mp4_demuxer::MP4Sample* aSample) {
|
||||
mTaskQueue->Dispatch(
|
||||
nsresult rv = mTaskQueue->Dispatch(
|
||||
NS_NewRunnableMethodWithArg<mp4_demuxer::MP4Sample*>(
|
||||
mDecoder,
|
||||
&MediaDataDecoder::Input,
|
||||
aSample));
|
||||
unused << NS_WARN_IF(NS_FAILED(rv));
|
||||
}
|
||||
|
||||
virtual nsresult Flush() MOZ_OVERRIDE {
|
||||
mTaskQueue->SyncDispatch(
|
||||
nsresult rv = mTaskQueue->SyncDispatch(
|
||||
NS_NewRunnableMethod(
|
||||
mDecoder,
|
||||
&MediaDataDecoder::Flush));
|
||||
return NS_OK;
|
||||
unused << NS_WARN_IF(NS_FAILED(rv));
|
||||
return rv;
|
||||
}
|
||||
|
||||
virtual nsresult Drain() MOZ_OVERRIDE {
|
||||
mTaskQueue->Dispatch(
|
||||
nsresult rv = mTaskQueue->Dispatch(
|
||||
NS_NewRunnableMethod(
|
||||
mDecoder,
|
||||
&MediaDataDecoder::Drain));
|
||||
return NS_OK;
|
||||
unused << NS_WARN_IF(NS_FAILED(rv));
|
||||
return rv;
|
||||
}
|
||||
|
||||
virtual nsresult Shutdown() MOZ_OVERRIDE {
|
||||
mTaskQueue->SyncDispatch(
|
||||
nsresult rv = mTaskQueue->SyncDispatch(
|
||||
NS_NewRunnableMethod(
|
||||
mDecoder,
|
||||
&MediaDataDecoder::Shutdown));
|
||||
unused << NS_WARN_IF(NS_FAILED(rv));
|
||||
mDecoder = nullptr;
|
||||
mTaskQueue->BeginShutdown();
|
||||
mTaskQueue->AwaitShutdownAndIdle();
|
||||
mTaskQueue = nullptr;
|
||||
mProxy = nullptr;
|
||||
return NS_OK;
|
||||
return rv;
|
||||
}
|
||||
|
||||
private:
|
||||
@ -170,11 +175,9 @@ private:
|
||||
EMEDecoderModule::EMEDecoderModule(CDMProxy* aProxy,
|
||||
PlatformDecoderModule* aPDM,
|
||||
bool aCDMDecodesAudio,
|
||||
bool aCDMDecodesVideo,
|
||||
already_AddRefed<MediaTaskQueue> aTaskQueue)
|
||||
bool aCDMDecodesVideo)
|
||||
: mProxy(aProxy)
|
||||
, mPDM(aPDM)
|
||||
, mTaskQueue(aTaskQueue)
|
||||
, mCDMDecodesAudio(aCDMDecodesAudio)
|
||||
, mCDMDecodesVideo(aCDMDecodesVideo)
|
||||
{
|
||||
@ -190,8 +193,6 @@ EMEDecoderModule::Shutdown()
|
||||
if (mPDM) {
|
||||
return mPDM->Shutdown();
|
||||
}
|
||||
mTaskQueue->BeginShutdown();
|
||||
mTaskQueue->AwaitShutdownAndIdle();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -227,7 +228,6 @@ EMEDecoderModule::CreateVideoDecoder(const VideoDecoderConfig& aConfig,
|
||||
|
||||
nsRefPtr<MediaDataDecoder> emeDecoder(new EMEDecryptor(decoder,
|
||||
aCallback,
|
||||
mTaskQueue,
|
||||
mProxy));
|
||||
return emeDecoder.forget();
|
||||
}
|
||||
@ -258,7 +258,6 @@ EMEDecoderModule::CreateAudioDecoder(const AudioDecoderConfig& aConfig,
|
||||
|
||||
nsRefPtr<MediaDataDecoder> emeDecoder(new EMEDecryptor(decoder,
|
||||
aCallback,
|
||||
mTaskQueue,
|
||||
mProxy));
|
||||
return emeDecoder.forget();
|
||||
}
|
||||
|
@ -24,8 +24,7 @@ public:
|
||||
EMEDecoderModule(CDMProxy* aProxy,
|
||||
PlatformDecoderModule* aPDM,
|
||||
bool aCDMDecodesAudio,
|
||||
bool aCDMDecodesVideo,
|
||||
already_AddRefed<MediaTaskQueue> aDecodeTaskQueue);
|
||||
bool aCDMDecodesVideo);
|
||||
|
||||
virtual ~EMEDecoderModule();
|
||||
|
||||
|
@ -52,6 +52,11 @@ public:
|
||||
{
|
||||
return FFmpegAudioDecoder<V>::GetCodecId(aMimeType) != AV_CODEC_ID_NONE;
|
||||
}
|
||||
|
||||
virtual bool SupportsVideoMimeType(const char* aMimeType) MOZ_OVERRIDE
|
||||
{
|
||||
return FFmpegH264Decoder<V>::GetCodecId(aMimeType) != AV_CODEC_ID_NONE;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
@ -27,7 +27,7 @@ FFmpegH264Decoder<LIBAV_VER>::FFmpegH264Decoder(
|
||||
MediaTaskQueue* aTaskQueue, MediaDataDecoderCallback* aCallback,
|
||||
const mp4_demuxer::VideoDecoderConfig& aConfig,
|
||||
ImageContainer* aImageContainer)
|
||||
: FFmpegDataDecoder(aTaskQueue, AV_CODEC_ID_H264)
|
||||
: FFmpegDataDecoder(aTaskQueue, GetCodecId(aConfig.mime_type))
|
||||
, mCallback(aCallback)
|
||||
, mImageContainer(aImageContainer)
|
||||
{
|
||||
@ -174,6 +174,10 @@ FFmpegH264Decoder<LIBAV_VER>::AllocateYUV420PVideoBuffer(
|
||||
bool needAlign = aCodecContext->codec->capabilities & CODEC_CAP_DR1;
|
||||
int edgeWidth = needAlign ? avcodec_get_edge_width() : 0;
|
||||
int decodeWidth = aCodecContext->width + edgeWidth * 2;
|
||||
// Make sure the decodeWidth is a multiple of 32, so a UV plane stride will be
|
||||
// a multiple of 16. FFmpeg uses SSE2 accelerated code to copy a frame line by
|
||||
// line.
|
||||
decodeWidth = (decodeWidth + 31) & ~31;
|
||||
int decodeHeight = aCodecContext->height + edgeWidth * 2;
|
||||
|
||||
if (needAlign) {
|
||||
@ -275,4 +279,18 @@ FFmpegH264Decoder<LIBAV_VER>::~FFmpegH264Decoder()
|
||||
MOZ_COUNT_DTOR(FFmpegH264Decoder);
|
||||
}
|
||||
|
||||
AVCodecID
|
||||
FFmpegH264Decoder<LIBAV_VER>::GetCodecId(const char* aMimeType)
|
||||
{
|
||||
if (!strcmp(aMimeType, "video/avc")) {
|
||||
return AV_CODEC_ID_H264;
|
||||
}
|
||||
|
||||
if (!strcmp(aMimeType, "video/x-vnd.on2.vp6")) {
|
||||
return AV_CODEC_ID_VP6F;
|
||||
}
|
||||
|
||||
return AV_CODEC_ID_NONE;
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
|
@ -40,6 +40,7 @@ public:
|
||||
virtual nsresult Input(mp4_demuxer::MP4Sample* aSample) MOZ_OVERRIDE;
|
||||
virtual nsresult Drain() MOZ_OVERRIDE;
|
||||
virtual nsresult Flush() MOZ_OVERRIDE;
|
||||
static AVCodecID GetCodecId(const char* aMimeType);
|
||||
|
||||
private:
|
||||
void DecodeFrame(mp4_demuxer::MP4Sample* aSample);
|
||||
|
@ -16,6 +16,7 @@ extern "C" {
|
||||
}
|
||||
|
||||
#if LIBAVCODEC_VERSION_MAJOR < 55
|
||||
#define AV_CODEC_ID_VP6F CODEC_ID_VP6F
|
||||
#define AV_CODEC_ID_H264 CODEC_ID_H264
|
||||
#define AV_CODEC_ID_AAC CODEC_ID_AAC
|
||||
#define AV_CODEC_ID_MP3 CODEC_ID_MP3
|
||||
|
@ -22,7 +22,7 @@
|
||||
# do ok(true, "Type not supported") and stop the test.
|
||||
|
||||
[DEFAULT]
|
||||
skip-if = buildapp == 'mulet' || (os == 'win' && contentSandbox != 'off') # contentSandbox(Bug 1042735)
|
||||
skip-if = buildapp == 'mulet' || (os == 'win' && strictContentSandbox) # strictContentSandbox (Bug 1042735)
|
||||
support-files =
|
||||
320x240.ogv
|
||||
320x240.ogv^headers^
|
||||
|
@ -1,6 +1,6 @@
|
||||
[DEFAULT]
|
||||
# contentSandbox - bug 1042735, Android 2.3 - bug 981881
|
||||
skip-if = (os == 'win' && contentSandbox != 'off') || android_version == '10'
|
||||
# strictContentSandbox - bug 1042735, Android 2.3 - bug 981881
|
||||
skip-if = (os == 'win' && strictContentSandbox) || android_version == '10'
|
||||
support-files =
|
||||
head.js
|
||||
constraints.js
|
||||
|
@ -1,5 +1,5 @@
|
||||
[DEFAULT]
|
||||
skip-if = ((buildapp == 'mulet' || buildapp == 'b2g') && (toolkit != 'gonk' || debug)) || (os == 'win' && contentSandbox != 'off') #b2g-debug,b2g-desktop(bug 916135); contentSandbox(Bug 1042735)
|
||||
skip-if = ((buildapp == 'mulet' || buildapp == 'b2g') && (toolkit != 'gonk' || debug)) || (os == 'win' && strictContentSandbox) #b2g-debug,b2g-desktop(bug 916135); strictContentSandbox(Bug 1042735)
|
||||
support-files =
|
||||
audio-expected.wav
|
||||
audio-mono-expected-2.wav
|
||||
|
@ -14,7 +14,7 @@ DIRS += [
|
||||
'commandhandler',
|
||||
]
|
||||
|
||||
if CONFIG['MOZ_XUL'] and CONFIG['NS_PRINTING']:
|
||||
if CONFIG['MOZ_XUL']:
|
||||
DIRS += ['printingui']
|
||||
|
||||
DIRS += ['build']
|
||||
|
@ -8,13 +8,14 @@ EXPORTS.mozilla.embedding.printingui += [
|
||||
'PrintingParent.h',
|
||||
]
|
||||
|
||||
UNIFIED_SOURCES += [
|
||||
'nsPrintingPromptServiceProxy.cpp',
|
||||
'PrintDataUtils.cpp',
|
||||
'PrintingParent.cpp',
|
||||
'PrintProgressDialogChild.cpp',
|
||||
'PrintProgressDialogParent.cpp',
|
||||
]
|
||||
if CONFIG['NS_PRINTING']:
|
||||
UNIFIED_SOURCES += [
|
||||
'nsPrintingPromptServiceProxy.cpp',
|
||||
'PrintDataUtils.cpp',
|
||||
'PrintingParent.cpp',
|
||||
'PrintProgressDialogChild.cpp',
|
||||
'PrintProgressDialogParent.cpp',
|
||||
]
|
||||
|
||||
IPDL_SOURCES += [
|
||||
'PPrinting.ipdl',
|
||||
|
@ -8,9 +8,10 @@ toolkit = CONFIG['MOZ_WIDGET_TOOLKIT']
|
||||
|
||||
DIRS += ['ipc']
|
||||
|
||||
if toolkit == 'windows':
|
||||
DIRS += ['win']
|
||||
elif toolkit == 'cocoa':
|
||||
DIRS += ['mac']
|
||||
elif CONFIG['MOZ_PDF_PRINTING']:
|
||||
DIRS += ['unixshared']
|
||||
if CONFIG['NS_PRINTING']:
|
||||
if toolkit == 'windows':
|
||||
DIRS += ['win']
|
||||
elif toolkit == 'cocoa':
|
||||
DIRS += ['mac']
|
||||
elif CONFIG['MOZ_PDF_PRINTING']:
|
||||
DIRS += ['unixshared']
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include "gfxPoint.h" // for gfxIntSize
|
||||
#include "mozilla/Assertions.h" // for MOZ_ASSERT, etc
|
||||
#include "mozilla/gfx/2D.h" // for DataSourceSurface, Factory
|
||||
#include "mozilla/gfx/Logging.h" // for gfxDebug
|
||||
#include "mozilla/gfx/Tools.h" // for GetAlignedStride, etc
|
||||
#include "mozilla/mozalloc.h" // for operator delete, etc
|
||||
|
||||
@ -34,11 +35,11 @@ using namespace gfx;
|
||||
namespace {
|
||||
struct SurfaceBufferInfo
|
||||
{
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
int32_t width;
|
||||
int32_t height;
|
||||
SurfaceFormat format;
|
||||
|
||||
static uint32_t GetOffset()
|
||||
static int32_t GetOffset()
|
||||
{
|
||||
return GetAlignedStride<16>(sizeof(SurfaceBufferInfo));
|
||||
}
|
||||
@ -65,19 +66,39 @@ ImageDataSerializer::InitializeBufferInfo(IntSize aSize,
|
||||
Validate();
|
||||
}
|
||||
|
||||
static inline uint32_t
|
||||
ComputeStride(SurfaceFormat aFormat, uint32_t aWidth)
|
||||
static inline int32_t
|
||||
ComputeStride(SurfaceFormat aFormat, int32_t aWidth)
|
||||
{
|
||||
return GetAlignedStride<4>(BytesPerPixel(aFormat) * aWidth);
|
||||
CheckedInt<int32_t> size = BytesPerPixel(aFormat);
|
||||
size *= aWidth;
|
||||
if (!size.isValid() || size.value() <= 0) {
|
||||
gfxDebug() << "ComputeStride overflow " << aWidth;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return GetAlignedStride<4>(size.value());
|
||||
}
|
||||
|
||||
uint32_t
|
||||
ImageDataSerializerBase::ComputeMinBufferSize(IntSize aSize,
|
||||
SurfaceFormat aFormat)
|
||||
SurfaceFormat aFormat)
|
||||
{
|
||||
uint32_t bufsize = aSize.height * ComputeStride(aFormat, aSize.width);
|
||||
MOZ_ASSERT(aSize.height >= 0 && aSize.width >= 0);
|
||||
if (aSize.height <= 0 || aSize.width <= 0) {
|
||||
gfxDebug() << "Non-positive image buffer size request " << aSize.width << "x" << aSize.height;
|
||||
return 0;
|
||||
}
|
||||
|
||||
CheckedInt<int32_t> bufsize = ComputeStride(aFormat, aSize.width);
|
||||
bufsize *= aSize.height;
|
||||
|
||||
if (!bufsize.isValid() || bufsize.value() <= 0) {
|
||||
gfxDebug() << "Buffer size overflow " << aSize.width << "x" << aSize.height;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return SurfaceBufferInfo::GetOffset()
|
||||
+ GetAlignedStride<16>(bufsize);
|
||||
+ GetAlignedStride<16>(bufsize.value());
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include "gfx2DGlue.h" // for ToIntSize
|
||||
#include "mozilla/gfx/2D.h" // for DataSourceSurface, Factory
|
||||
#include "mozilla/gfx/BaseSize.h" // for BaseSize
|
||||
#include "mozilla/gfx/Logging.h" // for gfxDebug
|
||||
#include "mozilla/gfx/Types.h"
|
||||
#include "mozilla/mozalloc.h" // for operator delete
|
||||
#include "yuv_convert.h" // for ConvertYCbCrToRGB32, etc
|
||||
@ -73,7 +74,7 @@ void YCbCrImageDataDeserializerBase::Validate()
|
||||
info->mYStride,
|
||||
IntSize(info->mCbCrWidth, info->mCbCrHeight),
|
||||
info->mCbCrStride);
|
||||
mIsValid = requiredSize <= mDataSize;
|
||||
mIsValid = requiredSize && requiredSize <= mDataSize;
|
||||
|
||||
}
|
||||
|
||||
@ -140,10 +141,15 @@ static size_t ComputeOffset(uint32_t aHeight, uint32_t aStride)
|
||||
// Minimum required shmem size in bytes
|
||||
size_t
|
||||
YCbCrImageDataDeserializerBase::ComputeMinBufferSize(const gfx::IntSize& aYSize,
|
||||
uint32_t aYStride,
|
||||
const gfx::IntSize& aCbCrSize,
|
||||
uint32_t aCbCrStride)
|
||||
uint32_t aYStride,
|
||||
const gfx::IntSize& aCbCrSize,
|
||||
uint32_t aCbCrStride)
|
||||
{
|
||||
MOZ_ASSERT(aYSize.height >= 0 && aYSize.width >= 0);
|
||||
if (aYSize.height <= 0 || aYSize.width <= 0 || aCbCrSize.height <= 0 || aCbCrSize.width <= 0) {
|
||||
gfxDebug() << "Non-positive YCbCr buffer size request " << aYSize.height << "x" << aYSize.width << ", " << aCbCrSize.height << "x" << aCbCrSize.width;
|
||||
return 0;
|
||||
}
|
||||
return ComputeOffset(aYSize.height, aYStride)
|
||||
+ 2 * ComputeOffset(aCbCrSize.height, aCbCrStride)
|
||||
+ MOZ_ALIGN_WORD(sizeof(YCbCrBufferInfo));
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include "mozilla/layers/ISurfaceAllocator.h"
|
||||
#include "mozilla/layers/ShadowLayerUtilsX11.h"
|
||||
#include "mozilla/gfx/2D.h"
|
||||
#include "mozilla/gfx/Logging.h"
|
||||
#include "gfxXlibSurface.h"
|
||||
#include "gfx2DGlue.h"
|
||||
|
||||
@ -38,6 +39,8 @@ TextureClientX11::CreateSimilar(TextureFlags aFlags,
|
||||
{
|
||||
RefPtr<TextureClient> tex = new TextureClientX11(mAllocator, mFormat, mFlags);
|
||||
|
||||
// mSize is guaranteed to be non-negative
|
||||
MOZ_ASSERT(mSize.width >= 0 && mSize.height >= 0);
|
||||
if (!tex->AllocateForSurface(mSize, aAllocFlags)) {
|
||||
return nullptr;
|
||||
}
|
||||
@ -107,6 +110,11 @@ TextureClientX11::AllocateForSurface(IntSize aSize, TextureAllocationFlags aText
|
||||
MOZ_ASSERT(!IsAllocated());
|
||||
//MOZ_ASSERT(mFormat != gfx::FORMAT_YUV, "This TextureClient cannot use YCbCr data");
|
||||
|
||||
MOZ_ASSERT(aSize.width >= 0 && aSize.height >= 0);
|
||||
if (aSize.width <= 0 || aSize.height <= 0) {
|
||||
gfxDebug() << "Asking for X11 surface of invalid size " << aSize.width << "x" << aSize.height;
|
||||
return false;
|
||||
}
|
||||
gfxContentType contentType = ContentForFormat(mFormat);
|
||||
nsRefPtr<gfxASurface> surface = gfxPlatform::GetPlatform()->CreateOffscreenSurface(aSize, contentType);
|
||||
if (!surface || surface->GetType() != gfxSurfaceType::Xlib) {
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include "nsISupportsImpl.h" // for MOZ_COUNT_CTOR, etc
|
||||
#include "ImageContainer.h" // for PlanarYCbCrData, etc
|
||||
#include "mozilla/gfx/2D.h"
|
||||
#include "mozilla/gfx/Logging.h" // for gfxDebug
|
||||
#include "mozilla/layers/TextureClientOGL.h"
|
||||
#include "mozilla/layers/PTextureChild.h"
|
||||
#include "SharedSurface.h"
|
||||
@ -584,8 +585,10 @@ bool
|
||||
ShmemTextureClient::Allocate(uint32_t aSize)
|
||||
{
|
||||
MOZ_ASSERT(mValid);
|
||||
SharedMemory::SharedMemoryType memType = OptimalShmemType();
|
||||
mAllocated = GetAllocator()->AllocUnsafeShmem(aSize, memType, &mShmem);
|
||||
if (aSize > 0) {
|
||||
SharedMemory::SharedMemoryType memType = OptimalShmemType();
|
||||
mAllocated = GetAllocator()->AllocUnsafeShmem(aSize, memType, &mShmem);
|
||||
}
|
||||
return mAllocated;
|
||||
}
|
||||
|
||||
@ -716,8 +719,12 @@ BufferTextureClient::AllocateForSurface(gfx::IntSize aSize, TextureAllocationFla
|
||||
MOZ_ASSERT(mFormat != gfx::SurfaceFormat::YUV, "This textureClient cannot use YCbCr data");
|
||||
MOZ_ASSERT(aSize.width > 0 && aSize.height > 0);
|
||||
|
||||
int bufSize
|
||||
= ImageDataSerializer::ComputeMinBufferSize(aSize, mFormat);
|
||||
if (aSize.width <= 0 || aSize.height <= 0) {
|
||||
gfxDebug() << "Asking for buffer of invalid size " << aSize.width << "x" << aSize.height;
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t bufSize = ImageDataSerializer::ComputeMinBufferSize(aSize, mFormat);
|
||||
if (!Allocate(bufSize)) {
|
||||
return false;
|
||||
}
|
||||
|
@ -111,6 +111,9 @@ ISurfaceAllocator::AllocSurfaceDescriptorWithCaps(const gfx::IntSize& aSize,
|
||||
gfx::SurfaceFormat format =
|
||||
gfxPlatform::GetPlatform()->Optimal2DFormatForContent(aContent);
|
||||
size_t size = ImageDataSerializer::ComputeMinBufferSize(aSize, format);
|
||||
if (!size) {
|
||||
return false;
|
||||
}
|
||||
if (IsSameProcess()) {
|
||||
uint8_t *data = new (std::nothrow) uint8_t[size];
|
||||
if (!data) {
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include "base/task.h" // for NewRunnableFunction, etc
|
||||
#include "base/thread.h" // for Thread
|
||||
#include "base/tracked.h" // for FROM_HERE
|
||||
#include "mozilla/gfx/Logging.h" // for gfxDebug
|
||||
#include "mozilla/layers/SharedBufferManagerChild.h"
|
||||
#include "mozilla/layers/SharedBufferManagerParent.h"
|
||||
#include "mozilla/StaticPtr.h" // for StaticRefPtr
|
||||
@ -239,6 +240,11 @@ SharedBufferManagerChild::AllocGrallocBuffer(const gfx::IntSize& aSize,
|
||||
const uint32_t& aUsage,
|
||||
mozilla::layers::MaybeMagicGrallocBufferHandle* aBuffer)
|
||||
{
|
||||
if (aSize.width <= 0 || aSize.height <= 0) {
|
||||
gfxDebug() << "Asking for gralloc of invalid size " << aSize.width << "x" << aSize.height;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (InSharedBufferManagerChildThread()) {
|
||||
return SharedBufferManagerChild::AllocGrallocBufferNow(aSize, aFormat, aUsage, aBuffer);
|
||||
}
|
||||
@ -264,6 +270,9 @@ SharedBufferManagerChild::AllocGrallocBufferNow(const IntSize& aSize,
|
||||
const uint32_t& aUsage,
|
||||
mozilla::layers::MaybeMagicGrallocBufferHandle* aHandle)
|
||||
{
|
||||
// These are protected functions, we can just assert and ask the caller to test
|
||||
MOZ_ASSERT(aSize.width >= 0 && aSize.height >= 0);
|
||||
|
||||
#ifdef MOZ_HAVE_SURFACEDESCRIPTORGRALLOC
|
||||
mozilla::layers::MaybeMagicGrallocBufferHandle handle;
|
||||
SendAllocateGrallocBuffer(aSize, aFormat, aUsage, &handle);
|
||||
|
@ -106,6 +106,9 @@ SharedPlanarYCbCrImage::AllocateAndGetNewBuffer(uint32_t aSize)
|
||||
{
|
||||
NS_ABORT_IF_FALSE(!mTextureClient, "This image already has allocated data");
|
||||
size_t size = YCbCrImageDataSerializer::ComputeMinBufferSize(aSize);
|
||||
if (!size) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
mTextureClient = TextureClient::CreateWithBufferSize(mCompositable->GetForwarder(),
|
||||
gfx::SurfaceFormat::YUV, size,
|
||||
@ -219,7 +222,7 @@ SharedPlanarYCbCrImage::Allocate(PlanarYCbCrData& aData)
|
||||
mData.mCbCrSize);
|
||||
mSize = mData.mPicSize;
|
||||
|
||||
return true;
|
||||
return mBufferSize > 0;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include <algorithm>
|
||||
#include "mozilla/Attributes.h" // for MOZ_THIS_IN_INITIALIZER_LIST
|
||||
#include "mozilla/DebugOnly.h"
|
||||
#include "mozilla/Likely.h"
|
||||
#include "mozilla/Move.h"
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "mozilla/StaticPtr.h"
|
||||
@ -385,6 +386,8 @@ public:
|
||||
MOZ_ASSERT(mLockedCost <= mMaxCost, "Locked more than we can hold?");
|
||||
} else {
|
||||
mCosts.InsertElementSorted(costEntry);
|
||||
// This may fail during XPCOM shutdown, so we need to ensure the object is
|
||||
// tracked before calling RemoveObject in StopTracking.
|
||||
mExpirationTracker.AddObject(aSurface);
|
||||
}
|
||||
}
|
||||
@ -401,7 +404,14 @@ public:
|
||||
MOZ_ASSERT(!mCosts.Contains(costEntry),
|
||||
"Shouldn't have a cost entry for a locked surface");
|
||||
} else {
|
||||
mExpirationTracker.RemoveObject(aSurface);
|
||||
if (MOZ_LIKELY(aSurface->GetExpirationState()->IsTracked())) {
|
||||
mExpirationTracker.RemoveObject(aSurface);
|
||||
} else {
|
||||
// Our call to AddObject must have failed in StartTracking; most likely
|
||||
// we're in XPCOM shutdown right now.
|
||||
NS_WARNING("Not expiration-tracking an unlocked surface!");
|
||||
}
|
||||
|
||||
DebugOnly<bool> foundInCosts = mCosts.RemoveElementSorted(costEntry);
|
||||
MOZ_ASSERT(foundInCosts, "Lost track of costs for this surface");
|
||||
}
|
||||
|
@ -116,26 +116,31 @@ static const unsigned PushedRetAddr = 0;
|
||||
# endif
|
||||
static const unsigned PushedFP = 10;
|
||||
static const unsigned StoredFP = 14;
|
||||
static const unsigned PostStorePrePopFP = 0;
|
||||
#elif defined(JS_CODEGEN_X86)
|
||||
# if defined(DEBUG)
|
||||
static const unsigned PushedRetAddr = 0;
|
||||
# endif
|
||||
static const unsigned PushedFP = 8;
|
||||
static const unsigned StoredFP = 11;
|
||||
static const unsigned PostStorePrePopFP = 0;
|
||||
#elif defined(JS_CODEGEN_ARM)
|
||||
static const unsigned PushedRetAddr = 4;
|
||||
static const unsigned PushedFP = 16;
|
||||
static const unsigned StoredFP = 20;
|
||||
static const unsigned PostStorePrePopFP = 4;
|
||||
#elif defined(JS_CODEGEN_MIPS)
|
||||
static const unsigned PushedRetAddr = 8;
|
||||
static const unsigned PushedFP = 24;
|
||||
static const unsigned StoredFP = 28;
|
||||
static const unsigned PostStorePrePopFP = 4;
|
||||
#elif defined(JS_CODEGEN_NONE)
|
||||
# if defined(DEBUG)
|
||||
static const unsigned PushedRetAddr = 0;
|
||||
# endif
|
||||
static const unsigned PushedFP = 1;
|
||||
static const unsigned StoredFP = 1;
|
||||
static const unsigned PostStorePrePopFP = 0;
|
||||
#else
|
||||
# error "Unknown architecture!"
|
||||
#endif
|
||||
@ -221,21 +226,29 @@ GenerateProfilingEpilogue(MacroAssembler &masm, unsigned framePushed, AsmJSExit:
|
||||
if (reason != AsmJSExit::None)
|
||||
masm.store32(Imm32(AsmJSExit::None), Address(scratch, AsmJSActivation::offsetOfExitReason()));
|
||||
|
||||
// AsmJSProfilingFrameIterator assumes that there is only a single 'ret'
|
||||
// instruction (whose offset is recorded by profilingReturn) after the store
|
||||
// which sets AsmJSActivation::fp to the caller's fp. Use AutoForbidPools to
|
||||
// ensure that a pool is not inserted before the return (a pool inserts a
|
||||
// jump instruction).
|
||||
// AsmJSProfilingFrameIterator assumes fixed offsets of the last few
|
||||
// instructions from profilingReturn, so AutoForbidPools to ensure that
|
||||
// unintended instructions are not automatically inserted.
|
||||
{
|
||||
#if defined(JS_CODEGEN_ARM)
|
||||
AutoForbidPools afp(&masm, /* number of instructions in scope = */ 3);
|
||||
AutoForbidPools afp(&masm, /* number of instructions in scope = */ 4);
|
||||
#endif
|
||||
|
||||
// sp protects the stack from clobber via asynchronous signal handlers
|
||||
// and the async interrupt exit. Since activation.fp can be read at any
|
||||
// time and still points to the current frame, be careful to only update
|
||||
// sp after activation.fp has been repointed to the caller's frame.
|
||||
#if defined(JS_CODEGEN_ARM) || defined(JS_CODEGEN_MIPS)
|
||||
masm.pop(scratch2);
|
||||
masm.loadPtr(Address(StackPointer, 0), scratch2);
|
||||
masm.storePtr(scratch2, Address(scratch, AsmJSActivation::offsetOfFP()));
|
||||
DebugOnly<uint32_t> prePop = masm.currentOffset();
|
||||
masm.add32(Imm32(4), StackPointer);
|
||||
MOZ_ASSERT(PostStorePrePopFP == masm.currentOffset() - prePop);
|
||||
#else
|
||||
masm.pop(Address(scratch, AsmJSActivation::offsetOfFP()));
|
||||
MOZ_ASSERT(PostStorePrePopFP == 0);
|
||||
#endif
|
||||
|
||||
masm.bind(profilingReturn);
|
||||
masm.ret();
|
||||
}
|
||||
@ -439,9 +452,9 @@ AsmJSProfilingFrameIterator::initFromFP(const AsmJSActivation &activation)
|
||||
return;
|
||||
}
|
||||
|
||||
// Since we don't have the pc for fp, start unwinding at the caller of fp,
|
||||
// whose pc we do have via fp->returnAddress. This means that the innermost
|
||||
// frame is skipped but this is fine because:
|
||||
// Since we don't have the pc for fp, start unwinding at the caller of fp
|
||||
// (ReturnAddressFromFP(fp)). This means that the innermost frame is
|
||||
// skipped. This is fine because:
|
||||
// - for FFI calls, the innermost frame is a thunk, so the first frame that
|
||||
// shows up is the function calling the FFI;
|
||||
// - for Math and other builtin calls, when profiling is activated, we
|
||||
@ -472,13 +485,13 @@ AsmJSProfilingFrameIterator::initFromFP(const AsmJSActivation &activation)
|
||||
MOZ_CRASH("Unexpected CodeRange kind");
|
||||
}
|
||||
|
||||
// Since, despite the above reasoning for skipping a frame, we do want FFI
|
||||
// Despite the above reasoning for skipping a frame, we do actually want FFI
|
||||
// trampolines and interrupts to show up in the profile (so they can
|
||||
// accumulate self time and explain performance faults), an "exit reason" is
|
||||
// stored on all the paths leaving asm.js and the iterator logic treats this
|
||||
// reason as its own frame. If we have exited asm.js code without setting an
|
||||
// exit reason, the reason will be None and this means the code was
|
||||
// asynchronously interrupted.
|
||||
// accumulate self time and explain performance faults). To do this, an
|
||||
// "exit reason" is stored on all the paths leaving asm.js and this iterator
|
||||
// treats this exit reason as its own frame. If we have exited asm.js code
|
||||
// without setting an exit reason, the reason will be None and this means
|
||||
// the code was asynchronously interrupted.
|
||||
exitReason_ = activation.exitReason();
|
||||
if (exitReason_ == AsmJSExit::None)
|
||||
exitReason_ = AsmJSExit::Interrupt;
|
||||
@ -523,16 +536,14 @@ AsmJSProfilingFrameIterator::AsmJSProfilingFrameIterator(const AsmJSActivation &
|
||||
case AsmJSModule::CodeRange::SlowFFI:
|
||||
case AsmJSModule::CodeRange::Interrupt:
|
||||
case AsmJSModule::CodeRange::Thunk: {
|
||||
// While codeRange describes the *current* frame, the fp/pc state stored in
|
||||
// the iterator is the *caller's* frame. The reason for this is that the
|
||||
// activation.fp isn't always the AsmJSFrame for state.pc; during the
|
||||
// prologue/epilogue, activation.fp will point to the caller's frame.
|
||||
// Naively unwinding starting at activation.fp could thus lead to the
|
||||
// second-to-innermost function being skipped in the callstack which will
|
||||
// bork profiling stacks. Instead, we depend on the exact layout of the
|
||||
// prologue/epilogue, as generated by GenerateProfiling(Prologue|Epilogue)
|
||||
// below.
|
||||
uint32_t offsetInModule = ((uint8_t*)state.pc) - module_->codeBase();
|
||||
// When the pc is inside the prologue/epilogue, the innermost
|
||||
// call's AsmJSFrame is not complete and thus fp points to the the
|
||||
// second-to-innermost call's AsmJSFrame. Since fp can only tell you
|
||||
// about its caller (via ReturnAddressFromFP(fp)), naively unwinding
|
||||
// while pc is in the prologue/epilogue would skip the second-to-
|
||||
// innermost call. To avoid this problem, we use the static structure of
|
||||
// the code in the prologue and epilogue to do the Right Thing.
|
||||
uint32_t offsetInModule = (uint8_t*)state.pc - module_->codeBase();
|
||||
MOZ_ASSERT(offsetInModule < module_->codeBytes());
|
||||
MOZ_ASSERT(offsetInModule >= codeRange->begin());
|
||||
MOZ_ASSERT(offsetInModule < codeRange->end());
|
||||
@ -540,21 +551,34 @@ AsmJSProfilingFrameIterator::AsmJSProfilingFrameIterator(const AsmJSActivation &
|
||||
void **sp = (void**)state.sp;
|
||||
#if defined(JS_CODEGEN_ARM) || defined(JS_CODEGEN_MIPS)
|
||||
if (offsetInCodeRange < PushedRetAddr) {
|
||||
// First instruction of the ARM/MIPS function; the return address is
|
||||
// still in lr and fp still holds the caller's fp.
|
||||
callerPC_ = state.lr;
|
||||
callerFP_ = fp;
|
||||
AssertMatchesCallSite(*module_, codeRange, callerPC_, callerFP_, sp - 2);
|
||||
} else if (offsetInModule == codeRange->profilingReturn() - PostStorePrePopFP) {
|
||||
// Second-to-last instruction of the ARM/MIPS function; fp points to
|
||||
// the caller's fp; have not yet popped AsmJSFrame.
|
||||
callerPC_ = ReturnAddressFromFP(sp);
|
||||
callerFP_ = CallerFPFromFP(sp);
|
||||
AssertMatchesCallSite(*module_, codeRange, callerPC_, callerFP_, sp);
|
||||
} else
|
||||
#endif
|
||||
if (offsetInCodeRange < PushedFP || offsetInModule == codeRange->profilingReturn()) {
|
||||
// The return address has been pushed on the stack but not fp; fp
|
||||
// still points to the caller's fp.
|
||||
callerPC_ = *sp;
|
||||
callerFP_ = fp;
|
||||
AssertMatchesCallSite(*module_, codeRange, callerPC_, callerFP_, sp - 1);
|
||||
} else if (offsetInCodeRange < StoredFP) {
|
||||
// The full AsmJSFrame has been pushed; fp still points to the
|
||||
// caller's frame.
|
||||
MOZ_ASSERT(fp == CallerFPFromFP(sp));
|
||||
callerPC_ = ReturnAddressFromFP(sp);
|
||||
callerFP_ = CallerFPFromFP(sp);
|
||||
AssertMatchesCallSite(*module_, codeRange, callerPC_, callerFP_, sp);
|
||||
} else {
|
||||
// Not in the prologue/epilogue.
|
||||
callerPC_ = ReturnAddressFromFP(fp);
|
||||
callerFP_ = CallerFPFromFP(fp);
|
||||
AssertMatchesCallSite(*module_, codeRange, callerPC_, callerFP_, fp);
|
||||
@ -564,7 +588,7 @@ AsmJSProfilingFrameIterator::AsmJSProfilingFrameIterator(const AsmJSActivation &
|
||||
case AsmJSModule::CodeRange::Entry: {
|
||||
// The entry trampoline is the final frame in an AsmJSActivation. The entry
|
||||
// trampoline also doesn't GenerateAsmJSPrologue/Epilogue so we can't use
|
||||
// the general unwinding logic below.
|
||||
// the general unwinding logic above.
|
||||
MOZ_ASSERT(!fp);
|
||||
callerPC_ = nullptr;
|
||||
callerFP_ = nullptr;
|
||||
@ -577,9 +601,11 @@ AsmJSProfilingFrameIterator::AsmJSProfilingFrameIterator(const AsmJSActivation &
|
||||
return;
|
||||
}
|
||||
|
||||
// Inline code ranges execute in the frame of the caller have no
|
||||
// prologue/epilogue and thus don't require the general unwinding logic
|
||||
// as below.
|
||||
// Most inline code stubs execute after the prologue/epilogue have
|
||||
// completed so we can simply unwind based on fp. The only exception is
|
||||
// the async interrupt stub, since it can be executed at any time.
|
||||
// However, the async interrupt is super rare, so we can tolerate
|
||||
// skipped frames. Thus, we use simply unwind based on fp.
|
||||
callerPC_ = ReturnAddressFromFP(fp);
|
||||
callerFP_ = CallerFPFromFP(fp);
|
||||
AssertMatchesCallSite(*module_, codeRange, callerPC_, callerFP_, fp);
|
||||
@ -617,7 +643,6 @@ AsmJSProfilingFrameIterator::operator++()
|
||||
switch (codeRange->kind()) {
|
||||
case AsmJSModule::CodeRange::Entry:
|
||||
MOZ_ASSERT(callerFP_ == nullptr);
|
||||
MOZ_ASSERT(callerPC_ != nullptr);
|
||||
callerPC_ = nullptr;
|
||||
break;
|
||||
case AsmJSModule::CodeRange::Function:
|
||||
|
@ -5615,14 +5615,14 @@ CheckSimdLoadStoreArgs(FunctionCompiler &f, ParseNode *call, AsmJSSimdType opTyp
|
||||
{
|
||||
ParseNode *view = CallArgList(call);
|
||||
if (!view->isKind(PNK_NAME))
|
||||
return f.fail(view, "expected Uint8Array view as SIMD.*.store first argument");
|
||||
return f.fail(view, "expected Uint8Array view as SIMD.*.load/store first argument");
|
||||
|
||||
const ModuleCompiler::Global *global = f.lookupGlobal(view->name());
|
||||
if (!global ||
|
||||
global->which() != ModuleCompiler::Global::ArrayView ||
|
||||
global->viewType() != Scalar::Uint8)
|
||||
{
|
||||
return f.fail(view, "expected Uint8Array view as SIMD.*.store first argument");
|
||||
return f.fail(view, "expected Uint8Array view as SIMD.*.load/store first argument");
|
||||
}
|
||||
|
||||
*needsBoundsCheck = NEEDS_BOUNDS_CHECK;
|
||||
@ -5685,7 +5685,7 @@ CheckSimdStore(FunctionCompiler &f, ParseNode *call, AsmJSSimdType opType, MDefi
|
||||
{
|
||||
unsigned numArgs = CallArgListLength(call);
|
||||
if (numArgs != 3)
|
||||
return f.failf(call, "expected 3 arguments to SIMD load, got %u", numArgs);
|
||||
return f.failf(call, "expected 3 arguments to SIMD store, got %u", numArgs);
|
||||
|
||||
Scalar::Type viewType;
|
||||
MDefinition *index;
|
||||
@ -5772,11 +5772,11 @@ CheckSimdOperationCall(FunctionCompiler &f, ParseNode *call, const ModuleCompile
|
||||
case AsmJSSimdOperation_fromFloat32x4Bits:
|
||||
return CheckSimdCast<MSimdReinterpretCast>(f, call, AsmJSSimdType_float32x4, opType, def, type);
|
||||
|
||||
case AsmJSSimdOperation_shiftLeft:
|
||||
case AsmJSSimdOperation_shiftLeftByScalar:
|
||||
return CheckSimdBinary(f, call, opType, MSimdShift::lsh, def, type);
|
||||
case AsmJSSimdOperation_shiftRight:
|
||||
case AsmJSSimdOperation_shiftRightArithmeticByScalar:
|
||||
return CheckSimdBinary(f, call, opType, MSimdShift::rsh, def, type);
|
||||
case AsmJSSimdOperation_shiftRightLogical:
|
||||
case AsmJSSimdOperation_shiftRightLogicalByScalar:
|
||||
return CheckSimdBinary(f, call, opType, MSimdShift::ursh, def, type);
|
||||
|
||||
case AsmJSSimdOperation_abs:
|
||||
@ -6213,9 +6213,12 @@ CheckConditional(FunctionCompiler &f, ParseNode *ternary, MDefinition **def, Typ
|
||||
*type = Type::Double;
|
||||
} else if (thenType.isFloat() && elseType.isFloat()) {
|
||||
*type = Type::Float;
|
||||
} else if (elseType.isSimd() && thenType <= elseType && elseType <= thenType) {
|
||||
*type = thenType;
|
||||
} else {
|
||||
return f.failf(ternary, "then/else branches of conditional must both produce int or double, "
|
||||
"current types are %s and %s", thenType.toChars(), elseType.toChars());
|
||||
return f.failf(ternary, "then/else branches of conditional must both produce int, float, "
|
||||
"double or SIMD types, current types are %s and %s",
|
||||
thenType.toChars(), elseType.toChars());
|
||||
}
|
||||
|
||||
if (!f.joinIfElse(thenBlocks, elseExpr))
|
||||
|
@ -97,9 +97,9 @@
|
||||
V(notEqual, (CompareFunc<Int32x4, NotEqual>), 2, 0) \
|
||||
V(or, (BinaryFunc<Int32x4, Or, Int32x4>), 2, 0) \
|
||||
V(sub, (BinaryFunc<Int32x4, Sub, Int32x4>), 2, 0) \
|
||||
V(shiftLeft, (Int32x4BinaryScalar<ShiftLeft>), 2, 0) \
|
||||
V(shiftRight, (Int32x4BinaryScalar<ShiftRight>), 2, 0) \
|
||||
V(shiftRightLogical, (Int32x4BinaryScalar<ShiftRightLogical>), 2, 0) \
|
||||
V(shiftLeftByScalar, (Int32x4BinaryScalar<ShiftLeft>), 2, 0) \
|
||||
V(shiftRightArithmeticByScalar, (Int32x4BinaryScalar<ShiftRight>), 2, 0) \
|
||||
V(shiftRightLogicalByScalar, (Int32x4BinaryScalar<ShiftRightLogical>), 2, 0) \
|
||||
V(store, (Store<Int32x4, 4>), 3, 0) \
|
||||
V(storeXYZ, (Store<Int32x4, 3>), 3, 0) \
|
||||
V(storeXY, (Store<Int32x4, 2>), 3, 0) \
|
||||
@ -130,9 +130,9 @@
|
||||
#define FOREACH_INT32X4_SIMD_OP(_) \
|
||||
_(fromFloat32x4) \
|
||||
_(fromFloat32x4Bits) \
|
||||
_(shiftLeft) \
|
||||
_(shiftRight) \
|
||||
_(shiftRightLogical)
|
||||
_(shiftLeftByScalar) \
|
||||
_(shiftRightArithmeticByScalar) \
|
||||
_(shiftRightLogicalByScalar)
|
||||
#define FOREACH_FLOAT32X4_SIMD_OP(_) \
|
||||
_(abs) \
|
||||
_(sqrt) \
|
||||
|
@ -357,7 +357,7 @@ other kinds of objects.
|
||||
`url`
|
||||
: The script's `url` property must be equal to this value.
|
||||
|
||||
`source` <i>(not yet implemented)</i>
|
||||
`source`
|
||||
: The script's `source` property must be equal to this value.
|
||||
|
||||
`line`
|
||||
|
@ -269,11 +269,19 @@ js::ZonesIter::atAtomsZone(JSRuntime *rt)
|
||||
return rt->isAtomsZone(*it);
|
||||
}
|
||||
|
||||
bool Zone::isOnList()
|
||||
bool
|
||||
Zone::isOnList() const
|
||||
{
|
||||
return listNext_ != NotOnList;
|
||||
}
|
||||
|
||||
Zone *
|
||||
Zone::nextZone() const
|
||||
{
|
||||
MOZ_ASSERT(isOnList());
|
||||
return listNext_;
|
||||
}
|
||||
|
||||
ZoneList::ZoneList()
|
||||
: head(nullptr), tail(nullptr)
|
||||
{}
|
||||
|
@ -322,7 +322,8 @@ struct Zone : public JS::shadow::Zone,
|
||||
friend class js::gc::ZoneList;
|
||||
static Zone * const NotOnList;
|
||||
Zone *listNext_;
|
||||
bool isOnList();
|
||||
bool isOnList() const;
|
||||
Zone *nextZone() const;
|
||||
|
||||
friend bool js::CurrentThreadCanAccessZone(Zone *zone);
|
||||
friend class js::gc::GCRuntime;
|
||||
|
@ -150,6 +150,7 @@ assertAsmTypeFail('glob', USE_ASM + I32 + "function f() {var x=i4(1,2,3,4); retu
|
||||
assertAsmTypeFail('glob', USE_ASM + I32 + "function f() {var x=i4(1,2,3,4).y; return x|0;} return f");
|
||||
assertAsmTypeFail('glob', USE_ASM + I32 + "function f() {var x=i4(1,2,3,4); return (x.x > (1>>>0)) | 0;} return f");
|
||||
|
||||
// signMask
|
||||
function CheckSignMask(innerBody, coerceBefore, coerceAfter, expected) {
|
||||
var lanes = ['x', 'y', 'z', 'w'];
|
||||
for (var i = 0; i < lanes.length; i++) {
|
||||
@ -173,7 +174,6 @@ CheckSignMaskF4('var x=f4(' + (INT32_MAX + 1) + ', 2, 3, 4)', [INT32_MAX + 1, 2,
|
||||
CheckSignMaskF4('var x=f4(1.3, 2.4, 3.5, 98.76)', [1.3, 2.4, 3.5, 98.76]);
|
||||
CheckSignMaskF4('var x=f4(13.37, 2., 3., -0)', [13.37, 2, 3, -0]);
|
||||
|
||||
// signMask
|
||||
assertAsmTypeFail('glob', USE_ASM + I32 + "function f() {var x=i4(1,2,3,4); var y=0.0; y=x.signMask;} return f");
|
||||
assertAsmTypeFail('glob', USE_ASM + I32 + "function f() {var x=i4(1,2,3,4); return (x.signMask > (1>>>0)) | 0;} return f");
|
||||
assertAsmTypeFail('glob', USE_ASM + I32 + FROUND + "function f() {var x=i4(1,2,3,4); var y=f32(0.0); y=x.signMask;} return f");
|
||||
@ -231,6 +231,23 @@ CheckF4(FROUND, 'var x=f4(1,2,3,4); var y=f32(0); y=x.z; x=f4(y,y,y,y)', [3, 3,
|
||||
CheckI4('', 'var x=i4(1,2,3,4); var c=0; var d=0; c=x.w|0; d=x.w|0; x=i4(c,d,d,c)', [4, 4, 4, 4]);
|
||||
CheckF4(FROUND, 'var x=f4(1,2,3,4); var y=f32(0); var z=f32(0); y=x.z; z=x.z; x=f4(y,z,y,z)', [3, 3, 3, 3]);
|
||||
|
||||
// Uses in ternary conditionals
|
||||
assertAsmTypeFail('glob', USE_ASM + F32 + "function f() {var x=f4(1,2,3,4); var c=4; c=x?c:c;} return f");
|
||||
assertAsmTypeFail('glob', USE_ASM + F32 + "function f() {var x=f4(1,2,3,4); var c=4; x=1?x:c;} return f");
|
||||
assertAsmTypeFail('glob', USE_ASM + F32 + "function f() {var x=f4(1,2,3,4); var c=4; x=1?c:x;} return f");
|
||||
assertAsmTypeFail('glob', USE_ASM + F32 + I32 + "function f() {var x=f4(1,2,3,4); var y=i4(1,2,3,4); x=1?x:y;} return f");
|
||||
assertAsmTypeFail('glob', USE_ASM + F32 + I32 + "function f() {var x=f4(1,2,3,4); var y=i4(1,2,3,4); x=1?y:y;} return f");
|
||||
|
||||
CheckF4('', 'var x=f4(1,2,3,4); var y=f4(4,3,2,1); x=3?y:x', [4, 3, 2, 1]);
|
||||
assertEqX4(asmLink(asmCompile('glob', USE_ASM + F32 + "function f(x) {x=x|0; var v=f4(1,2,3,4); var w=f4(5,6,7,8); return f4(x?w:v);} return f"), this)(1), [5,6,7,8]);
|
||||
assertEqX4(asmLink(asmCompile('glob', USE_ASM + F32 + "function f(v) {v=f4(v); var w=f4(5,6,7,8); return f4(4?w:v);} return f"), this)(SIMD.float32x4(1,2,3,4)), [5,6,7,8]);
|
||||
assertEqX4(asmLink(asmCompile('glob', USE_ASM + F32 + "function f(v, x) {v=f4(v); x=x|0; var w=f4(5,6,7,8); return f4(x?w:v);} return f"), this)(SIMD.float32x4(1,2,3,4), 0), [1,2,3,4]);
|
||||
|
||||
CheckI4('', 'var x=i4(1,2,3,4); var y=i4(4,3,2,1); x=(x.x|0)?y:x', [4, 3, 2, 1]);
|
||||
assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + "function f(x) {x=x|0; var v=i4(1,2,3,4); var w=i4(5,6,7,8); return i4(x?w:v);} return f"), this)(1), [5,6,7,8]);
|
||||
assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + "function f(v) {v=i4(v); var w=i4(5,6,7,8); return i4(4?w:v);} return f"), this)(SIMD.int32x4(1,2,3,4)), [5,6,7,8]);
|
||||
assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + "function f(v, x) {v=i4(v); x=x|0; var w=i4(5,6,7,8); return i4(x?w:v);} return f"), this)(SIMD.int32x4(1,2,3,4), 0), [1,2,3,4]);
|
||||
|
||||
// 1.3.4 Return values
|
||||
assertAsmTypeFail('glob', USE_ASM + I32 + "function f() {var x=1; return i4(x)} return f");
|
||||
assertAsmTypeFail('glob', USE_ASM + I32 + "function f() {var x=1; return i4(x + x)} return f");
|
||||
@ -763,9 +780,9 @@ CheckF4(ORF32, 'var x=f4(42, 13.37,-1.42, 23.10); var y=f4(19.89, 2.4, 8.15, 16
|
||||
CheckF4(XORF32, 'var x=f4(42, 13.37,-1.42, 23.10); var y=f4(19.89, 2.4, 8.15, 16.36); x=xorr(x,y)', bitwise.xor([42, 13.37, -1.42, 23.10], [19.89, 2.4, 8.15, 16.36]));
|
||||
|
||||
// Logical ops
|
||||
const LSHI = 'var lsh=i4.shiftLeft;'
|
||||
const RSHI = 'var rsh=i4.shiftRight;'
|
||||
const URSHI = 'var ursh=i4.shiftRightLogical;'
|
||||
const LSHI = 'var lsh=i4.shiftLeftByScalar;'
|
||||
const RSHI = 'var rsh=i4.shiftRightArithmeticByScalar;'
|
||||
const URSHI = 'var ursh=i4.shiftRightLogicalByScalar;'
|
||||
|
||||
assertAsmTypeFail('glob', USE_ASM + I32 + F32 + FROUND + LSHI + "function f() {var x=f4(1,2,3,4); return i4(lsh(x,f32(42)));} return f");
|
||||
assertAsmTypeFail('glob', USE_ASM + I32 + F32 + FROUND + LSHI + "function f() {var x=f4(1,2,3,4); return i4(lsh(x,42));} return f");
|
||||
|
9
js/src/jit-test/tests/debug/bug1107525.js
Normal file
9
js/src/jit-test/tests/debug/bug1107525.js
Normal file
@ -0,0 +1,9 @@
|
||||
// |jit-test| error: InternalError
|
||||
enableSPSProfiling();
|
||||
var g = newGlobal();
|
||||
g.parent = this;
|
||||
g.eval("new Debugger(parent).onExceptionUnwind = function () { hits++; };");
|
||||
function f() {
|
||||
var x = f();
|
||||
}
|
||||
f();
|
7
js/src/jit-test/tests/debug/bug1107913.js
Normal file
7
js/src/jit-test/tests/debug/bug1107913.js
Normal file
@ -0,0 +1,7 @@
|
||||
// |jit-test| error: TypeError
|
||||
|
||||
var g = newGlobal();
|
||||
g.parent = this;
|
||||
g.eval("new Debugger(parent).onExceptionUnwind = function () {};");
|
||||
Object.preventExtensions(this);
|
||||
evaluate("function testcase() { }", { noScriptRval : true, compileAndGo : true });
|
15
js/src/jit-test/tests/debug/bug1108159.js
Normal file
15
js/src/jit-test/tests/debug/bug1108159.js
Normal file
@ -0,0 +1,15 @@
|
||||
// |jit-test| slow
|
||||
|
||||
if (helperThreadCount() == 0)
|
||||
quit(0);
|
||||
|
||||
var s = '';
|
||||
for (var i = 0; i < 70000; i++)
|
||||
{
|
||||
s += 'function x' + i + '() { x' + i + '(); }\n';
|
||||
}
|
||||
evaluate(s);
|
||||
var g = newGlobal();
|
||||
(new Debugger).addDebuggee(g);
|
||||
g.offThreadCompileScript('debugger;',{});
|
||||
g.runOffThreadScript();
|
@ -181,7 +181,7 @@ uint32_t
|
||||
jit::ExceptionHandlerBailout(JSContext *cx, const InlineFrameIterator &frame,
|
||||
ResumeFromException *rfe,
|
||||
const ExceptionBailoutInfo &excInfo,
|
||||
bool *overrecursed)
|
||||
bool *overrecursed, bool *poppedLastSPSFrameOut)
|
||||
{
|
||||
// We can be propagating debug mode exceptions without there being an
|
||||
// actual exception pending. For instance, when we return false from an
|
||||
@ -196,9 +196,8 @@ jit::ExceptionHandlerBailout(JSContext *cx, const InlineFrameIterator &frame,
|
||||
JitFrameIterator iter(jitActivations);
|
||||
|
||||
BaselineBailoutInfo *bailoutInfo = nullptr;
|
||||
bool poppedLastSPSFrame = false;
|
||||
uint32_t retval = BailoutIonToBaseline(cx, bailoutData.activation(), iter, true,
|
||||
&bailoutInfo, &excInfo, &poppedLastSPSFrame);
|
||||
&bailoutInfo, &excInfo, poppedLastSPSFrameOut);
|
||||
|
||||
if (retval == BAILOUT_RETURN_OK) {
|
||||
MOZ_ASSERT(bailoutInfo);
|
||||
|
@ -209,7 +209,7 @@ class ExceptionBailoutInfo
|
||||
uint32_t ExceptionHandlerBailout(JSContext *cx, const InlineFrameIterator &frame,
|
||||
ResumeFromException *rfe,
|
||||
const ExceptionBailoutInfo &excInfo,
|
||||
bool *overrecursed);
|
||||
bool *overrecursed, bool *poppedLastSPSFrameOut);
|
||||
|
||||
uint32_t FinishBailoutToBaseline(BaselineBailoutInfo *bailoutInfo);
|
||||
|
||||
|
@ -400,17 +400,31 @@ PatchBaselineFramesForDebugMode(JSContext *cx, const Debugger::ExecutionObservab
|
||||
BaselineScript *bl = script->baselineScript();
|
||||
ICEntry::Kind kind = entry.frameKind;
|
||||
|
||||
if (kind == ICEntry::Kind_Op) {
|
||||
// Case A above.
|
||||
//
|
||||
// Patching this case needs to patch both the stub frame and
|
||||
if (kind == ICEntry::Kind_Op || kind == ICEntry::Kind_NonOp) {
|
||||
uint8_t *retAddr;
|
||||
if (kind == ICEntry::Kind_Op) {
|
||||
// Case A above.
|
||||
retAddr = bl->returnAddressForIC(bl->icEntryFromPCOffset(pcOffset));
|
||||
} else {
|
||||
// Case H above.
|
||||
//
|
||||
// It could happen that the in-place Ion bailout chose the
|
||||
// return-from-IC address of a NonOp IC for the frame
|
||||
// iterators to report the correct bytecode pc.
|
||||
//
|
||||
// See note under propagatingIonExceptionForDebugMode in
|
||||
// InitFromBailout.
|
||||
MOZ_ASSERT(iter.baselineFrame()->isDebuggerHandlingException());
|
||||
retAddr = bl->returnAddressForIC(bl->anyKindICEntryFromPCOffset(pcOffset));
|
||||
}
|
||||
|
||||
// Patching these cases needs to patch both the stub frame and
|
||||
// the baseline frame. The stub frame is patched below. For
|
||||
// the baseline frame here, we resume right after the IC
|
||||
// returns.
|
||||
//
|
||||
// Since we're using the same IC stub code, we can resume
|
||||
// directly to the IC resume address.
|
||||
uint8_t *retAddr = bl->returnAddressForIC(bl->icEntryFromPCOffset(pcOffset));
|
||||
SpewPatchBaselineFrame(prev->returnAddress(), retAddr, script, kind, pc);
|
||||
DebugModeOSRVolatileJitFrameIterator::forwardLiveIterators(
|
||||
cx, prev->returnAddress(), retAddr);
|
||||
|
@ -576,7 +576,7 @@ BaselineScript::anyKindICEntryFromPCOffset(uint32_t pcOffset)
|
||||
|
||||
// Return any IC entry with a matching PC offset.
|
||||
for (size_t i = mid; i < numICEntries() && icEntry(i).pcOffset() == pcOffset; i--)
|
||||
return icEntry(i);
|
||||
return icEntry(i);
|
||||
for (size_t i = mid+1; i < numICEntries() && icEntry(i).pcOffset() == pcOffset; i++)
|
||||
return icEntry(i);
|
||||
MOZ_CRASH("Invalid PC offset for IC entry.");
|
||||
|
@ -7767,7 +7767,7 @@ static const VMFunctionsModal SetObjectElementInfo = VMFunctionsModal(
|
||||
void
|
||||
CodeGenerator::visitCallSetElement(LCallSetElement *lir)
|
||||
{
|
||||
pushArg(Imm32(current->mir()->strict()));
|
||||
pushArg(Imm32(lir->mir()->strict()));
|
||||
pushArg(ToValue(lir, LCallSetElement::Value));
|
||||
pushArg(ToValue(lir, LCallSetElement::Index));
|
||||
pushArg(ToRegister(lir->getOperand(0)));
|
||||
|
@ -8263,7 +8263,7 @@ IonBuilder::jsop_setelem()
|
||||
return emitted;
|
||||
|
||||
// Emit call.
|
||||
MInstruction *ins = MCallSetElement::New(alloc(), object, index, value);
|
||||
MInstruction *ins = MCallSetElement::New(alloc(), object, index, value, IsStrictSetPC(pc));
|
||||
current->add(ins);
|
||||
current->push(value);
|
||||
|
||||
|
@ -695,7 +695,7 @@ class InlineFrameIterator
|
||||
}
|
||||
|
||||
template <class Op>
|
||||
void unaliasedForEachActual(ThreadSafeContext *cx, Op op,
|
||||
void unaliasedForEachActual(JSContext *cx, Op op,
|
||||
ReadFrameArgsBehavior behavior,
|
||||
MaybeReadFallback &fallback) const
|
||||
{
|
||||
|
@ -412,7 +412,7 @@ CloseLiveIterator(JSContext *cx, const InlineFrameIterator &frame, uint32_t loca
|
||||
|
||||
static void
|
||||
HandleExceptionIon(JSContext *cx, const InlineFrameIterator &frame, ResumeFromException *rfe,
|
||||
bool *overrecursed)
|
||||
bool *overrecursed, bool *poppedLastSPSFrameOut)
|
||||
{
|
||||
RootedScript script(cx, frame.script());
|
||||
jsbytecode *pc = frame.pc();
|
||||
@ -444,7 +444,8 @@ HandleExceptionIon(JSContext *cx, const InlineFrameIterator &frame, ResumeFromEx
|
||||
// to the stack depth at the snapshot, as we could've thrown in the
|
||||
// middle of a call.
|
||||
ExceptionBailoutInfo propagateInfo;
|
||||
uint32_t retval = ExceptionHandlerBailout(cx, frame, rfe, propagateInfo, overrecursed);
|
||||
uint32_t retval = ExceptionHandlerBailout(cx, frame, rfe, propagateInfo, overrecursed,
|
||||
poppedLastSPSFrameOut);
|
||||
if (retval == BAILOUT_RETURN_OK)
|
||||
return;
|
||||
}
|
||||
@ -486,7 +487,8 @@ HandleExceptionIon(JSContext *cx, const InlineFrameIterator &frame, ResumeFromEx
|
||||
// Bailout at the start of the catch block.
|
||||
jsbytecode *catchPC = script->main() + tn->start + tn->length;
|
||||
ExceptionBailoutInfo excInfo(frame.frameNo(), catchPC, tn->stackDepth);
|
||||
uint32_t retval = ExceptionHandlerBailout(cx, frame, rfe, excInfo, overrecursed);
|
||||
uint32_t retval = ExceptionHandlerBailout(cx, frame, rfe, excInfo, overrecursed,
|
||||
poppedLastSPSFrameOut);
|
||||
if (retval == BAILOUT_RETURN_OK)
|
||||
return;
|
||||
|
||||
@ -742,7 +744,8 @@ HandleException(ResumeFromException *rfe)
|
||||
bool invalidated = iter.checkInvalidation(&ionScript);
|
||||
|
||||
for (;;) {
|
||||
HandleExceptionIon(cx, frames, rfe, &overrecursed);
|
||||
bool poppedLastSPSFrame = false;
|
||||
HandleExceptionIon(cx, frames, rfe, &overrecursed, &poppedLastSPSFrame);
|
||||
|
||||
if (rfe->kind == ResumeFromException::RESUME_BAILOUT) {
|
||||
if (invalidated)
|
||||
@ -764,6 +767,11 @@ HandleException(ResumeFromException *rfe)
|
||||
if (frames.more())
|
||||
popSPSFrame = false;
|
||||
|
||||
// Don't pop the last SPS frame if it's already been popped by
|
||||
// bailing out.
|
||||
if (poppedLastSPSFrame)
|
||||
popSPSFrame = false;
|
||||
|
||||
// When profiling, each frame popped needs a notification that
|
||||
// the function has exited, so invoke the probe that a function
|
||||
// is exiting.
|
||||
@ -874,7 +882,8 @@ HandleParallelFailure(ResumeFromException *rfe)
|
||||
SnapshotIterator snapIter(frameIter);
|
||||
|
||||
cx->bailoutRecord->setIonBailoutKind(snapIter.bailoutKind());
|
||||
cx->bailoutRecord->rematerializeFrames(cx, frameIter);
|
||||
while (!frameIter.done())
|
||||
++frameIter;
|
||||
|
||||
rfe->kind = ResumeFromException::RESUME_ENTRY_FRAME;
|
||||
|
||||
|
@ -5746,6 +5746,10 @@ class LCallSetElement : public LCallInstructionHelper<0, 1 + 2 * BOX_PIECES, 0>
|
||||
|
||||
static const size_t Index = 1;
|
||||
static const size_t Value = 1 + BOX_PIECES;
|
||||
|
||||
const MCallSetElement *mir() const {
|
||||
return mir_->toCallSetElement();
|
||||
}
|
||||
};
|
||||
|
||||
// Call js::InitElementArray.
|
||||
|
@ -10154,9 +10154,11 @@ class MSetPropertyInstruction : public MBinaryInstruction
|
||||
class MSetElementInstruction
|
||||
: public MTernaryInstruction
|
||||
{
|
||||
bool strict_;
|
||||
protected:
|
||||
MSetElementInstruction(MDefinition *object, MDefinition *index, MDefinition *value)
|
||||
: MTernaryInstruction(object, index, value)
|
||||
MSetElementInstruction(MDefinition *object, MDefinition *index, MDefinition *value, bool strict)
|
||||
: MTernaryInstruction(object, index, value),
|
||||
strict_(strict)
|
||||
{
|
||||
}
|
||||
|
||||
@ -10170,6 +10172,9 @@ class MSetElementInstruction
|
||||
MDefinition *value() const {
|
||||
return getOperand(2);
|
||||
}
|
||||
bool strict() const {
|
||||
return strict_;
|
||||
}
|
||||
};
|
||||
|
||||
class MDeleteProperty
|
||||
@ -10295,13 +10300,11 @@ class MSetElementCache
|
||||
: public MSetElementInstruction,
|
||||
public MixPolicy<ObjectPolicy<0>, BoxPolicy<1> >::Data
|
||||
{
|
||||
bool strict_;
|
||||
bool guardHoles_;
|
||||
|
||||
MSetElementCache(MDefinition *obj, MDefinition *index, MDefinition *value, bool strict,
|
||||
bool guardHoles)
|
||||
: MSetElementInstruction(obj, index, value),
|
||||
strict_(strict),
|
||||
: MSetElementInstruction(obj, index, value, strict),
|
||||
guardHoles_(guardHoles)
|
||||
{
|
||||
}
|
||||
@ -10315,9 +10318,6 @@ class MSetElementCache
|
||||
return new(alloc) MSetElementCache(obj, index, value, strict, guardHoles);
|
||||
}
|
||||
|
||||
bool strict() const {
|
||||
return strict_;
|
||||
}
|
||||
bool guardHoles() const {
|
||||
return guardHoles_;
|
||||
}
|
||||
@ -10402,8 +10402,8 @@ class MCallSetElement
|
||||
: public MSetElementInstruction,
|
||||
public CallSetElementPolicy::Data
|
||||
{
|
||||
MCallSetElement(MDefinition *object, MDefinition *index, MDefinition *value)
|
||||
: MSetElementInstruction(object, index, value)
|
||||
MCallSetElement(MDefinition *object, MDefinition *index, MDefinition *value, bool strict)
|
||||
: MSetElementInstruction(object, index, value, strict)
|
||||
{
|
||||
}
|
||||
|
||||
@ -10411,9 +10411,9 @@ class MCallSetElement
|
||||
INSTRUCTION_HEADER(CallSetElement)
|
||||
|
||||
static MCallSetElement *New(TempAllocator &alloc, MDefinition *object, MDefinition *index,
|
||||
MDefinition *value)
|
||||
MDefinition *value, bool strict)
|
||||
{
|
||||
return new(alloc) MCallSetElement(object, index, value);
|
||||
return new(alloc) MCallSetElement(object, index, value, strict);
|
||||
}
|
||||
|
||||
bool possiblyCalls() const {
|
||||
|
@ -549,7 +549,8 @@ jit::BailoutPar(BailoutStack *sp, uint8_t **entryFramePointer)
|
||||
SnapshotIterator snapIter(frameIter);
|
||||
|
||||
cx->bailoutRecord->setIonBailoutKind(snapIter.bailoutKind());
|
||||
cx->bailoutRecord->rematerializeFrames(cx, frameIter);
|
||||
while (!frameIter.done())
|
||||
++frameIter;
|
||||
|
||||
MOZ_ASSERT(frameIter.done());
|
||||
*entryFramePointer = frameIter.fp();
|
||||
|
@ -28,8 +28,8 @@ struct CopyValueToRematerializedFrame
|
||||
}
|
||||
};
|
||||
|
||||
RematerializedFrame::RematerializedFrame(ThreadSafeContext *cx, uint8_t *top,
|
||||
unsigned numActualArgs, InlineFrameIterator &iter)
|
||||
RematerializedFrame::RematerializedFrame(JSContext *cx, uint8_t *top, unsigned numActualArgs,
|
||||
InlineFrameIterator &iter)
|
||||
: prevUpToDate_(false),
|
||||
isDebuggee_(iter.script()->isDebuggee()),
|
||||
top_(top),
|
||||
@ -46,7 +46,7 @@ RematerializedFrame::RematerializedFrame(ThreadSafeContext *cx, uint8_t *top,
|
||||
}
|
||||
|
||||
/* static */ RematerializedFrame *
|
||||
RematerializedFrame::New(ThreadSafeContext *cx, uint8_t *top, InlineFrameIterator &iter)
|
||||
RematerializedFrame::New(JSContext *cx, uint8_t *top, InlineFrameIterator &iter)
|
||||
{
|
||||
unsigned numFormals = iter.isFunctionFrame() ? iter.callee()->nargs() : 0;
|
||||
unsigned numActualArgs = Max(numFormals, iter.numActualArgs());
|
||||
@ -62,7 +62,7 @@ RematerializedFrame::New(ThreadSafeContext *cx, uint8_t *top, InlineFrameIterato
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
RematerializedFrame::RematerializeInlineFrames(ThreadSafeContext *cx, uint8_t *top,
|
||||
RematerializedFrame::RematerializeInlineFrames(JSContext *cx, uint8_t *top,
|
||||
InlineFrameIterator &iter,
|
||||
Vector<RematerializedFrame *> &frames)
|
||||
{
|
||||
@ -71,9 +71,19 @@ RematerializedFrame::RematerializeInlineFrames(ThreadSafeContext *cx, uint8_t *t
|
||||
|
||||
while (true) {
|
||||
size_t frameNo = iter.frameNo();
|
||||
frames[frameNo] = RematerializedFrame::New(cx, top, iter);
|
||||
if (!frames[frameNo])
|
||||
RematerializedFrame *frame = RematerializedFrame::New(cx, top, iter);
|
||||
if (!frame)
|
||||
return false;
|
||||
if (frame->scopeChain()) {
|
||||
// Frames are often rematerialized with the cx inside a Debugger's
|
||||
// compartment. To create CallObjects, we need to be in that
|
||||
// frame's compartment.
|
||||
AutoCompartment ac(cx, frame->scopeChain());
|
||||
if (!EnsureHasScopeObjects(cx, frame))
|
||||
return false;
|
||||
}
|
||||
|
||||
frames[frameNo] = frame;
|
||||
|
||||
if (!iter.more())
|
||||
break;
|
||||
@ -112,6 +122,26 @@ RematerializedFrame::callObj() const
|
||||
return scope->as<CallObject>();
|
||||
}
|
||||
|
||||
void
|
||||
RematerializedFrame::pushOnScopeChain(ScopeObject &scope)
|
||||
{
|
||||
MOZ_ASSERT(*scopeChain() == scope.enclosingScope() ||
|
||||
*scopeChain() == scope.as<CallObject>().enclosingScope().as<DeclEnvObject>().enclosingScope());
|
||||
scopeChain_ = &scope;
|
||||
}
|
||||
|
||||
bool
|
||||
RematerializedFrame::initFunctionScopeObjects(JSContext *cx)
|
||||
{
|
||||
MOZ_ASSERT(isNonEvalFunctionFrame());
|
||||
MOZ_ASSERT(fun()->isHeavyweight());
|
||||
CallObject *callobj = CallObject::createForFunction(cx, this);
|
||||
if (!callobj)
|
||||
return false;
|
||||
pushOnScopeChain(*callobj);
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
RematerializedFrame::mark(JSTracer *trc)
|
||||
{
|
||||
|
@ -46,16 +46,15 @@ class RematerializedFrame
|
||||
Value thisValue_;
|
||||
Value slots_[1];
|
||||
|
||||
RematerializedFrame(ThreadSafeContext *cx, uint8_t *top, unsigned numActualArgs,
|
||||
RematerializedFrame(JSContext *cx, uint8_t *top, unsigned numActualArgs,
|
||||
InlineFrameIterator &iter);
|
||||
|
||||
public:
|
||||
static RematerializedFrame *New(ThreadSafeContext *cx, uint8_t *top,
|
||||
InlineFrameIterator &iter);
|
||||
static RematerializedFrame *New(JSContext *cx, uint8_t *top, InlineFrameIterator &iter);
|
||||
|
||||
// Rematerialize all remaining frames pointed to by |iter| into |frames|
|
||||
// in older-to-younger order, e.g., frames[0] is the oldest frame.
|
||||
static bool RematerializeInlineFrames(ThreadSafeContext *cx, uint8_t *top,
|
||||
static bool RematerializeInlineFrames(JSContext *cx, uint8_t *top,
|
||||
InlineFrameIterator &iter,
|
||||
Vector<RematerializedFrame *> &frames);
|
||||
|
||||
@ -104,8 +103,13 @@ class RematerializedFrame
|
||||
JSObject *scopeChain() const {
|
||||
return scopeChain_;
|
||||
}
|
||||
void pushOnScopeChain(ScopeObject &scope);
|
||||
bool initFunctionScopeObjects(JSContext *cx);
|
||||
|
||||
bool hasCallObj() const {
|
||||
return maybeFun() && fun()->isHeavyweight();
|
||||
return maybeFun() &&
|
||||
fun()->isHeavyweight() &&
|
||||
scopeChain()->is<CallObject>();
|
||||
}
|
||||
CallObject &callObj() const;
|
||||
|
||||
|
@ -560,12 +560,7 @@ void
|
||||
JSCompartment::sweepGlobalObject(FreeOp *fop)
|
||||
{
|
||||
if (global_.unbarrieredGet() && IsObjectAboutToBeFinalizedFromAnyThread(global_.unsafeGet())) {
|
||||
// For main thread compartments, the invariant is that debug mode
|
||||
// implies having at least one Debugger still attached. However, for
|
||||
// off-thread compartments, which are used in off-thread parsing, they
|
||||
// may be isDebuggee() without there being any Debuggers to prohibit
|
||||
// asm.js.
|
||||
if (isDebuggee() && !global_->compartment()->options().invisibleToDebugger())
|
||||
if (isDebuggee())
|
||||
Debugger::detachAllDebuggersFromGlobal(fop, global_);
|
||||
global_.set(nullptr);
|
||||
}
|
||||
|
@ -430,8 +430,8 @@ struct JSCompartment
|
||||
// InterpreterFrame::isDebuggee, and Baseline::isDebuggee are enumerated
|
||||
// below.
|
||||
//
|
||||
// 1. When a compartment's isDebuggee() == true, relazification and lazy
|
||||
// parsing are disabled.
|
||||
// 1. When a compartment's isDebuggee() == true, relazification, lazy
|
||||
// parsing, and asm.js are disabled.
|
||||
//
|
||||
// 2. When a compartment's debugObservesAllExecution() == true, all of the
|
||||
// compartment's scripts are considered debuggee scripts.
|
||||
|
@ -546,12 +546,14 @@ FinalizeTypedArenas(FreeOp *fop,
|
||||
if (!fop->onBackgroundThread())
|
||||
maybeLock.emplace(fop->runtime());
|
||||
|
||||
/*
|
||||
* During parallel sections, we sometimes finalize the parallel arenas,
|
||||
* but in that case, we want to hold on to the memory in our arena
|
||||
* lists, not offer it up for reuse.
|
||||
*/
|
||||
MOZ_ASSERT_IF(InParallelSection(), keepArenas);
|
||||
// During background sweeping free arenas are released later on in
|
||||
// sweepBackgroundThings().
|
||||
MOZ_ASSERT_IF(fop->onBackgroundThread(), keepArenas == ArenaLists::KEEP_ARENAS);
|
||||
|
||||
// During parallel sections, we sometimes finalize the parallel arenas, but
|
||||
// in that case, we want to hold on to the memory in our arena lists, not
|
||||
// offer it up for reuse.
|
||||
MOZ_ASSERT_IF(InParallelSection(), keepArenas == ArenaLists::KEEP_ARENAS);
|
||||
|
||||
size_t thingSize = Arena::thingSize(thingKind);
|
||||
size_t thingsPerArena = Arena::thingsPerArena(thingSize);
|
||||
@ -561,18 +563,12 @@ FinalizeTypedArenas(FreeOp *fop,
|
||||
size_t nmarked = aheader->getArena()->finalize<T>(fop, thingKind, thingSize);
|
||||
size_t nfree = thingsPerArena - nmarked;
|
||||
|
||||
if (nmarked) {
|
||||
if (nmarked)
|
||||
dest.insertAt(aheader, nfree);
|
||||
} else if (keepArenas == ArenaLists::KEEP_ARENAS) {
|
||||
else if (keepArenas == ArenaLists::KEEP_ARENAS)
|
||||
aheader->chunk()->recycleArena(aheader, dest, thingKind, thingsPerArena);
|
||||
} else if (fop->onBackgroundThread()) {
|
||||
// When background sweeping, take the lock around each release so
|
||||
// that we do not block the foreground for extended periods.
|
||||
AutoLockGC lock(fop->runtime());
|
||||
fop->runtime()->gc.releaseArena(aheader, lock);
|
||||
} else {
|
||||
else
|
||||
fop->runtime()->gc.releaseArena(aheader, maybeLock.ref());
|
||||
}
|
||||
|
||||
budget.step(thingsPerArena);
|
||||
if (budget.isOverBudget())
|
||||
@ -3438,11 +3434,10 @@ void
|
||||
GCRuntime::sweepBackgroundThings(ZoneList &zones, ThreadType threadType)
|
||||
{
|
||||
// We must finalize thing kinds in the order specified by BackgroundFinalizePhases.
|
||||
ArenaHeader *emptyArenas = nullptr;
|
||||
FreeOp fop(rt, threadType);
|
||||
while (!zones.isEmpty()) {
|
||||
Zone *zone = zones.front();
|
||||
ArenaHeader *emptyArenas = nullptr;
|
||||
for (unsigned phase = 0 ; phase < ArrayLength(BackgroundFinalizePhases) ; ++phase) {
|
||||
for (unsigned phase = 0 ; phase < ArrayLength(BackgroundFinalizePhases) ; ++phase) {
|
||||
for (Zone *zone = zones.front(); zone; zone = zone->nextZone()) {
|
||||
for (unsigned index = 0 ; index < BackgroundFinalizePhases[phase].length ; ++index) {
|
||||
AllocKind kind = BackgroundFinalizePhases[phase].kinds[index];
|
||||
ArenaHeader *arenas = zone->allocator.arenas.arenaListsToSweep[kind];
|
||||
@ -3450,11 +3445,12 @@ GCRuntime::sweepBackgroundThings(ZoneList &zones, ThreadType threadType)
|
||||
ArenaLists::backgroundFinalize(&fop, arenas, &emptyArenas);
|
||||
}
|
||||
}
|
||||
|
||||
AutoLockGC lock(rt);
|
||||
ReleaseArenaList(rt, emptyArenas, lock);
|
||||
zones.removeFront();
|
||||
}
|
||||
|
||||
AutoLockGC lock(rt);
|
||||
ReleaseArenaList(rt, emptyArenas, lock);
|
||||
while (!zones.isEmpty())
|
||||
zones.removeFront();
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1,35 +0,0 @@
|
||||
// |reftest| skip-if(!this.hasOwnProperty("SIMD"))
|
||||
var BUGNUMBER = 996076;
|
||||
var float32x4 = SIMD.float32x4;
|
||||
var int32x4 = SIMD.int32x4;
|
||||
|
||||
var summary = 'int32x4 lsh';
|
||||
|
||||
function test() {
|
||||
print(BUGNUMBER + ": " + summary);
|
||||
|
||||
for (var bits = 0; bits < 32; bits++) {
|
||||
var a = int32x4(-1, 2, -3, 4);
|
||||
var c = SIMD.int32x4.shiftLeft(a, bits);
|
||||
assertEq(c.x, -1 << bits);
|
||||
assertEq(c.y, 2 << bits);
|
||||
assertEq(c.z, -3 << bits);
|
||||
assertEq(c.w, 4 << bits);
|
||||
}
|
||||
|
||||
var INT32_MAX = Math.pow(2, 31) - 1;
|
||||
var INT32_MIN = -Math.pow(2, 31);
|
||||
|
||||
var d = int32x4(INT32_MAX, INT32_MIN, INT32_MAX, INT32_MIN);
|
||||
var f = SIMD.int32x4.shiftLeft(d, 1);
|
||||
assertEq(f.x, (INT32_MAX << 1) | 0);
|
||||
assertEq(f.y, (INT32_MIN << 1) | 0);
|
||||
assertEq(f.z, (INT32_MAX << 1) | 0);
|
||||
assertEq(f.w, (INT32_MIN << 1) | 0);
|
||||
|
||||
if (typeof reportCompare === "function")
|
||||
reportCompare(true, true);
|
||||
}
|
||||
|
||||
test();
|
||||
|
@ -1,34 +0,0 @@
|
||||
// |reftest| skip-if(!this.hasOwnProperty("SIMD"))
|
||||
var BUGNUMBER = 996076;
|
||||
var float32x4 = SIMD.float32x4;
|
||||
var int32x4 = SIMD.int32x4;
|
||||
|
||||
var summary = 'int32x4 rsh';
|
||||
|
||||
function test() {
|
||||
print(BUGNUMBER + ": " + summary);
|
||||
|
||||
for (var bits = 0; bits < 32; bits++) {
|
||||
var a = int32x4(-1, 2, -3, 4);
|
||||
var c = SIMD.int32x4.shiftRight(a, bits);
|
||||
assertEq(c.x, -1 >> bits);
|
||||
assertEq(c.y, 2 >> bits);
|
||||
assertEq(c.z, -3 >> bits);
|
||||
assertEq(c.w, 4 >> bits);
|
||||
}
|
||||
|
||||
var INT32_MAX = Math.pow(2, 31) - 1;
|
||||
var INT32_MIN = -Math.pow(2, 31);
|
||||
var d = int32x4(INT32_MAX, INT32_MIN, INT32_MAX, INT32_MIN);
|
||||
var f = SIMD.int32x4.shiftRight(d, 1);
|
||||
assertEq(f.x, INT32_MAX >> 1);
|
||||
assertEq(f.y, INT32_MIN >> 1);
|
||||
assertEq(f.z, INT32_MAX >> 1);
|
||||
assertEq(f.w, INT32_MIN >> 1);
|
||||
|
||||
if (typeof reportCompare === "function")
|
||||
reportCompare(true, true);
|
||||
}
|
||||
|
||||
test();
|
||||
|
@ -1,35 +0,0 @@
|
||||
// |reftest| skip-if(!this.hasOwnProperty("SIMD"))
|
||||
var BUGNUMBER = 996076;
|
||||
var float32x4 = SIMD.float32x4;
|
||||
var int32x4 = SIMD.int32x4;
|
||||
|
||||
var summary = 'int32x4 ursh';
|
||||
|
||||
function test() {
|
||||
print(BUGNUMBER + ": " + summary);
|
||||
|
||||
for (var bits = 0; bits < 32; bits++) {
|
||||
var a = int32x4(-1, 2, -3, 4);
|
||||
var c = SIMD.int32x4.shiftRightLogical(a, bits);
|
||||
assertEq(c.x >>> 0, -1 >>> bits);
|
||||
assertEq(c.y >>> 0, 2 >>> bits);
|
||||
assertEq(c.z >>> 0, -3 >>> bits);
|
||||
assertEq(c.w >>> 0, 4 >>> bits);
|
||||
}
|
||||
|
||||
var INT32_MAX = Math.pow(2, 31) - 1;
|
||||
var INT32_MIN = -Math.pow(2, 31);
|
||||
|
||||
var d = int32x4(INT32_MAX, INT32_MIN, INT32_MAX, INT32_MIN);
|
||||
var f = SIMD.int32x4.shiftRightLogical(d, 0);
|
||||
assertEq(f.x, (INT32_MAX >>> 0) | 0);
|
||||
assertEq(f.y, (INT32_MIN >>> 0) | 0);
|
||||
assertEq(f.z, (INT32_MAX >>> 0) | 0);
|
||||
assertEq(f.w, (INT32_MIN >>> 0) | 0);
|
||||
|
||||
if (typeof reportCompare === "function")
|
||||
reportCompare(true, true);
|
||||
}
|
||||
|
||||
test();
|
||||
|
@ -28,3 +28,13 @@ function testBinaryFunc(v, w, simdFunc, func) {
|
||||
for (var i = 0; i < observed.length; i++)
|
||||
assertEq(observed[i], expected[i]);
|
||||
}
|
||||
|
||||
function testBinaryScalarFunc(v, scalar, simdFunc, func) {
|
||||
var varr = simdToArray(v);
|
||||
|
||||
var observed = simdToArray(simdFunc(v, scalar));
|
||||
var expected = varr.map(function(v, i) { return func(varr[i], scalar); });
|
||||
|
||||
for (var i = 0; i < observed.length; i++)
|
||||
assertEq(observed[i], expected[i]);
|
||||
}
|
||||
|
37
js/src/tests/ecma_7/SIMD/shifts.js
Normal file
37
js/src/tests/ecma_7/SIMD/shifts.js
Normal file
@ -0,0 +1,37 @@
|
||||
// |reftest| skip-if(!this.hasOwnProperty("SIMD"))
|
||||
|
||||
/*
|
||||
* Any copyright is dedicated to the Public Domain.
|
||||
* https://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
var int32x4 = SIMD.int32x4;
|
||||
|
||||
function lsh(a, b) {
|
||||
return (a << b) | 0;
|
||||
}
|
||||
function rsh(a, b) {
|
||||
return (a >> b) | 0;
|
||||
}
|
||||
function ursh(a, b) {
|
||||
return (a >>> b) | 0;
|
||||
}
|
||||
|
||||
function test() {
|
||||
for (var v of [
|
||||
int32x4(-1, 2, -3, 4),
|
||||
int32x4(INT32_MAX, INT32_MIN, INT32_MAX - 1, INT32_MIN + 1)
|
||||
])
|
||||
{
|
||||
for (var bits = 0; bits < 32; bits++) {
|
||||
testBinaryScalarFunc(v, bits, int32x4.shiftLeftByScalar, lsh);
|
||||
testBinaryScalarFunc(v, bits, int32x4.shiftRightArithmeticByScalar, rsh);
|
||||
testBinaryScalarFunc(v, bits, int32x4.shiftRightLogicalByScalar, ursh);
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof reportCompare === "function")
|
||||
reportCompare(true, true);
|
||||
}
|
||||
|
||||
test();
|
@ -3560,43 +3560,35 @@ class MOZ_STACK_CLASS Debugger::ObjectQuery
|
||||
if (!prepareQuery())
|
||||
return false;
|
||||
|
||||
// Ensure that all of our debuggee globals are rooted so that they are
|
||||
// visible in the RootList.
|
||||
JS::AutoObjectVector debuggees(cx);
|
||||
for (GlobalObjectSet::Range r = dbg->allDebuggees(); !r.empty(); r.popFront()) {
|
||||
if (!debuggees.append(r.front()))
|
||||
return false;
|
||||
}
|
||||
|
||||
{
|
||||
/*
|
||||
* We can't tolerate the GC moving things around while we're
|
||||
* searching the heap. Check that nothing we do causes a GC.
|
||||
*/
|
||||
JS::AutoCheckCannotGC autoCannotGC;
|
||||
Maybe<JS::AutoCheckCannotGC> maybeNoGC;
|
||||
RootedObject dbgObj(cx, dbg->object);
|
||||
JS::ubi::RootList rootList(cx, maybeNoGC);
|
||||
if (!rootList.init(cx, dbgObj))
|
||||
return false;
|
||||
|
||||
Traversal traversal(cx, *this, autoCannotGC);
|
||||
Traversal traversal(cx, *this, maybeNoGC.ref());
|
||||
if (!traversal.init())
|
||||
return false;
|
||||
traversal.wantNames = false;
|
||||
|
||||
/* Add each debuggee global as a start point of our traversal. */
|
||||
for (GlobalObjectSet::Range r = dbg->debuggees.all(); !r.empty(); r.popFront()) {
|
||||
if (!traversal.addStartVisited(JS::ubi::Node(static_cast<JSObject *>(r.front()))))
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Iterate over all compartments and add traversal start points at
|
||||
* objects that have CCWs in other compartments keeping them alive.
|
||||
*/
|
||||
for (CompartmentsIter c(cx->runtime(), SkipAtoms); !c.done(); c.next()) {
|
||||
JSCompartment *comp = c.get();
|
||||
if (!comp)
|
||||
continue;
|
||||
for (JSCompartment::WrapperEnum e(comp); !e.empty(); e.popFront()) {
|
||||
const CrossCompartmentKey &key = e.front().key();
|
||||
if (key.kind != CrossCompartmentKey::ObjectWrapper)
|
||||
continue;
|
||||
JSObject *obj = static_cast<JSObject *>(key.wrapped);
|
||||
if (!traversal.addStartVisited(JS::ubi::Node(obj)))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!traversal.traverse())
|
||||
if (!traversal.addStart(JS::ubi::Node(&rootList)) ||
|
||||
!traversal.traverse())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Iterate over the visited set of nodes and accumulate all
|
||||
@ -3604,8 +3596,9 @@ class MOZ_STACK_CLASS Debugger::ObjectQuery
|
||||
*/
|
||||
for (Traversal::NodeMap::Range r = traversal.visited.all(); !r.empty(); r.popFront()) {
|
||||
JS::ubi::Node node = r.front().key();
|
||||
if (!node.is<JSObject>() || !dbg->isDebuggee(node.compartment()))
|
||||
if (!node.is<JSObject>())
|
||||
continue;
|
||||
MOZ_ASSERT(dbg->isDebuggee(node.compartment()));
|
||||
|
||||
JSObject *obj = node.as<JSObject>();
|
||||
|
||||
@ -3625,15 +3618,17 @@ class MOZ_STACK_CLASS Debugger::ObjectQuery
|
||||
|
||||
/*
|
||||
* |ubi::Node::BreadthFirst| interface.
|
||||
*
|
||||
* We use an empty traversal function and just iterate over the traversal's
|
||||
* visited set post-facto in |findObjects|.
|
||||
*/
|
||||
|
||||
class NodeData {};
|
||||
typedef JS::ubi::BreadthFirst<ObjectQuery> Traversal;
|
||||
bool operator() (Traversal &, JS::ubi::Node, const JS::ubi::Edge &, NodeData *, bool)
|
||||
bool operator() (Traversal &traversal, JS::ubi::Node origin, const JS::ubi::Edge &edge,
|
||||
NodeData *, bool first)
|
||||
{
|
||||
/* Only follow edges within our set of debuggee compartments. */
|
||||
JSCompartment *comp = edge.referent.compartment();
|
||||
if (first && comp && !dbg->isDebuggee(edge.referent.compartment()))
|
||||
traversal.abandonReferent();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1875,41 +1875,6 @@ ParallelBailoutRecord::reset()
|
||||
cause = ParallelBailoutNone;
|
||||
}
|
||||
|
||||
void
|
||||
ParallelBailoutRecord::rematerializeFrames(ForkJoinContext *cx, JitFrameIterator &frameIter)
|
||||
{
|
||||
// This function is infallible. These are only called when we are already
|
||||
// erroring out. If we OOM here, free what we've allocated and return. Error
|
||||
// reporting is then unable to give the user detailed stack information.
|
||||
|
||||
MOZ_ASSERT(frames().empty());
|
||||
|
||||
for (; !frameIter.done(); ++frameIter) {
|
||||
if (!frameIter.isIonJS())
|
||||
continue;
|
||||
|
||||
InlineFrameIterator inlineIter(cx, &frameIter);
|
||||
Vector<RematerializedFrame *> inlineFrames(cx);
|
||||
|
||||
if (!RematerializedFrame::RematerializeInlineFrames(cx, frameIter.fp(),
|
||||
inlineIter, inlineFrames))
|
||||
{
|
||||
RematerializedFrame::FreeInVector(inlineFrames);
|
||||
RematerializedFrame::FreeInVector(frames());
|
||||
return;
|
||||
}
|
||||
|
||||
// Reverse the inline frames into the main vector.
|
||||
while (!inlineFrames.empty()) {
|
||||
if (!frames().append(inlineFrames.popCopy())) {
|
||||
RematerializedFrame::FreeInVector(inlineFrames);
|
||||
RematerializedFrame::FreeInVector(frames());
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//
|
||||
|
@ -370,8 +370,6 @@ struct ParallelBailoutRecord
|
||||
joinCause(ParallelBailoutExecution);
|
||||
ionBailoutKind = kind;
|
||||
}
|
||||
|
||||
void rematerializeFrames(ForkJoinContext *cx, jit::JitFrameIterator &frameIter);
|
||||
};
|
||||
|
||||
class ForkJoinShared;
|
||||
|
@ -197,7 +197,17 @@ ParseTask::ParseTask(ExclusiveContext *cx, JSObject *exclusiveContextGlobal, JSC
|
||||
bool
|
||||
ParseTask::init(JSContext *cx, const ReadOnlyCompileOptions &options)
|
||||
{
|
||||
return this->options.copy(cx, options);
|
||||
if (!this->options.copy(cx, options))
|
||||
return false;
|
||||
|
||||
// If the main-thread global is a debuggee, disable asm.js
|
||||
// compilation. This is preferred to marking the task compartment as a
|
||||
// debuggee, as the task compartment is (1) invisible to Debugger and (2)
|
||||
// cannot have any Debuggers.
|
||||
if (cx->compartment()->isDebuggee())
|
||||
this->options.asmJSOption = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
@ -364,12 +374,6 @@ js::StartOffThreadParseScript(JSContext *cx, const ReadOnlyCompileOptions &optio
|
||||
} else {
|
||||
task->activate(cx->runtime());
|
||||
|
||||
if (cx->compartment()->isDebuggee()) {
|
||||
task->cx->compartment()->setIsDebuggee();
|
||||
if (cx->compartment()->debugObservesAllExecution())
|
||||
task->cx->compartment()->setDebugObservesAllExecution();
|
||||
}
|
||||
|
||||
AutoLockHelperThreadState lock;
|
||||
|
||||
if (!HelperThreadState().parseWorklist().append(task.get()))
|
||||
|
@ -463,7 +463,9 @@ AbstractFramePtr::initFunctionScopeObjects(JSContext *cx)
|
||||
{
|
||||
if (isInterpreterFrame())
|
||||
return asInterpreterFrame()->initFunctionScopeObjects(cx);
|
||||
return asBaselineFrame()->initFunctionScopeObjects(cx);
|
||||
if (isBaselineFrame())
|
||||
return asBaselineFrame()->initFunctionScopeObjects(cx);
|
||||
return asRematerializedFrame()->initFunctionScopeObjects(cx);
|
||||
}
|
||||
|
||||
inline JSCompartment *
|
||||
|
@ -963,7 +963,7 @@ FrameIter::isConstructing() const
|
||||
}
|
||||
|
||||
bool
|
||||
FrameIter::ensureHasRematerializedFrame(ThreadSafeContext *cx)
|
||||
FrameIter::ensureHasRematerializedFrame(JSContext *cx)
|
||||
{
|
||||
MOZ_ASSERT(isIon());
|
||||
return !!activation()->asJit()->getRematerializedFrame(cx, data_.jitFrames_);
|
||||
@ -1445,7 +1445,7 @@ jit::JitActivation::clearRematerializedFrames()
|
||||
}
|
||||
|
||||
jit::RematerializedFrame *
|
||||
jit::JitActivation::getRematerializedFrame(ThreadSafeContext *cx, const JitFrameIterator &iter, size_t inlineDepth)
|
||||
jit::JitActivation::getRematerializedFrame(JSContext *cx, const JitFrameIterator &iter, size_t inlineDepth)
|
||||
{
|
||||
// Only allow rematerializing from the same thread.
|
||||
MOZ_ASSERT(cx->perThreadData == cx_->perThreadData);
|
||||
|
@ -1330,7 +1330,7 @@ class JitActivation : public Activation
|
||||
// provided, as values need to be read out of snapshots.
|
||||
//
|
||||
// The inlineDepth must be within bounds of the frame pointed to by iter.
|
||||
RematerializedFrame *getRematerializedFrame(ThreadSafeContext *cx, const JitFrameIterator &iter,
|
||||
RematerializedFrame *getRematerializedFrame(JSContext *cx, const JitFrameIterator &iter,
|
||||
size_t inlineDepth = 0);
|
||||
|
||||
// Look up a rematerialized frame by the fp. If inlineDepth is out of
|
||||
@ -1636,7 +1636,7 @@ class FrameIter
|
||||
|
||||
// Ensures that we have rematerialized the top frame and its associated
|
||||
// inline frames. Can only be called when isIon().
|
||||
bool ensureHasRematerializedFrame(ThreadSafeContext *cx);
|
||||
bool ensureHasRematerializedFrame(JSContext *cx);
|
||||
|
||||
// True when isInterp() or isBaseline(). True when isIon() if it
|
||||
// has a rematerialized frame. False otherwise false otherwise.
|
||||
|
@ -149,4 +149,4 @@ fuzzy-if(d2d,47,400) == linear-onestopposition-1.html linear-onestopposition-1-r
|
||||
fuzzy(1,800000) == large-gradient-1.html large-gradient-1-ref.html
|
||||
== large-gradient-2.html large-gradient-2-ref.html
|
||||
fails-if(browserIsRemote&&!B2G) fuzzy-if(!browserIsRemote||B2G,1,800000) == large-gradient-3.html large-gradient-3-ref.html
|
||||
fails-if(browserIsRemote&&!B2G) == large-gradient-4.html large-gradient-4-ref.html
|
||||
== large-gradient-4.html large-gradient-4-ref.html
|
||||
|
@ -1480,6 +1480,12 @@ function UpdateCurrentCanvasForInvalidation(rects)
|
||||
var right = Math.ceil(r.right);
|
||||
var bottom = Math.ceil(r.bottom);
|
||||
|
||||
// Clamp the values to the canvas size
|
||||
left = Math.max(0, Math.min(left, gCurrentCanvas.width));
|
||||
top = Math.max(0, Math.min(top, gCurrentCanvas.height));
|
||||
right = Math.max(0, Math.min(right, gCurrentCanvas.width));
|
||||
bottom = Math.max(0, Math.min(bottom, gCurrentCanvas.height));
|
||||
|
||||
ctx.save();
|
||||
ctx.translate(left, top);
|
||||
DoDrawWindow(ctx, left, top, right - left, bottom - top);
|
||||
|
@ -22,6 +22,7 @@ namespace stagefright {
|
||||
|
||||
extern const char *MEDIA_MIMETYPE_IMAGE_JPEG;
|
||||
|
||||
extern const char *MEDIA_MIMETYPE_VIDEO_VP6;
|
||||
extern const char *MEDIA_MIMETYPE_VIDEO_VP8;
|
||||
extern const char *MEDIA_MIMETYPE_VIDEO_VP9;
|
||||
extern const char *MEDIA_MIMETYPE_VIDEO_AVC;
|
||||
|
@ -320,6 +320,9 @@ static const char *FourCC2MIME(uint32_t fourcc) {
|
||||
case FOURCC('s', 'a', 'w', 'b'):
|
||||
return MEDIA_MIMETYPE_AUDIO_AMR_WB;
|
||||
|
||||
case FOURCC('.', 'm', 'p', '3'):
|
||||
return MEDIA_MIMETYPE_AUDIO_MPEG;
|
||||
|
||||
case FOURCC('m', 'p', '4', 'v'):
|
||||
return MEDIA_MIMETYPE_VIDEO_MPEG4;
|
||||
|
||||
@ -332,6 +335,9 @@ static const char *FourCC2MIME(uint32_t fourcc) {
|
||||
case FOURCC('a', 'v', 'c', '3'):
|
||||
return MEDIA_MIMETYPE_VIDEO_AVC;
|
||||
|
||||
case FOURCC('V', 'P', '6', 'F'):
|
||||
return MEDIA_MIMETYPE_VIDEO_VP6;
|
||||
|
||||
default:
|
||||
CHECK(!"should not be here.");
|
||||
return NULL;
|
||||
@ -1216,6 +1222,7 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) {
|
||||
}
|
||||
|
||||
case FOURCC('m', 'p', '4', 'a'):
|
||||
case FOURCC('.', 'm', 'p', '3'):
|
||||
case FOURCC('e', 'n', 'c', 'a'):
|
||||
case FOURCC('s', 'a', 'm', 'r'):
|
||||
case FOURCC('s', 'a', 'w', 'b'):
|
||||
@ -1270,6 +1277,7 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) {
|
||||
case FOURCC('h', '2', '6', '3'):
|
||||
case FOURCC('a', 'v', 'c', '1'):
|
||||
case FOURCC('a', 'v', 'c', '3'):
|
||||
case FOURCC('V', 'P', '6', 'F'):
|
||||
{
|
||||
mHasVideo = true;
|
||||
|
||||
|
@ -20,6 +20,7 @@ namespace stagefright {
|
||||
|
||||
const char *MEDIA_MIMETYPE_IMAGE_JPEG = "image/jpeg";
|
||||
|
||||
const char *MEDIA_MIMETYPE_VIDEO_VP6 = "video/x-vnd.on2.vp6";
|
||||
const char *MEDIA_MIMETYPE_VIDEO_VP8 = "video/x-vnd.on2.vp8";
|
||||
const char *MEDIA_MIMETYPE_VIDEO_VP9 = "video/x-vnd.on2.vp9";
|
||||
const char *MEDIA_MIMETYPE_VIDEO_AVC = "video/avc";
|
||||
|
@ -121,11 +121,14 @@ JsepSessionImpl::AddAudioRtpExtension(const std::string& extensionName)
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
mAudioRtpExtensions.push_back(
|
||||
SdpExtmapAttributeList::Extmap extmap =
|
||||
{ static_cast<uint16_t>(mAudioRtpExtensions.size() + 1),
|
||||
SdpDirectionAttribute::kSendrecv,
|
||||
false, // don't actually specify direction
|
||||
extensionName, "" });
|
||||
extensionName,
|
||||
"" };
|
||||
|
||||
mAudioRtpExtensions.push_back(extmap);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -139,11 +142,13 @@ JsepSessionImpl::AddVideoRtpExtension(const std::string& extensionName)
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
mVideoRtpExtensions.push_back(
|
||||
SdpExtmapAttributeList::Extmap extmap =
|
||||
{ static_cast<uint16_t>(mVideoRtpExtensions.size() + 1),
|
||||
SdpDirectionAttribute::kSendrecv,
|
||||
false, // don't actually specify direction
|
||||
extensionName, "" });
|
||||
extensionName, "" };
|
||||
|
||||
mVideoRtpExtensions.push_back(extmap);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -392,7 +397,7 @@ JsepSessionImpl::AddCommonExtmaps(const SdpMediaSection& remoteMsection,
|
||||
if (ourExtmap->mExtmaps.back().entry >= 4096) {
|
||||
ourExtmap->mExtmaps.back().entry = j->entry;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -256,8 +256,9 @@ public:
|
||||
bool direction_specified, const std::string& extensionname,
|
||||
const std::string& extensionattributes = "")
|
||||
{
|
||||
mExtmaps.push_back({ entry, direction, direction_specified, extensionname,
|
||||
extensionattributes });
|
||||
Extmap value = { entry, direction, direction_specified, extensionname,
|
||||
extensionattributes };
|
||||
mExtmaps.push_back(value);
|
||||
}
|
||||
|
||||
virtual void Serialize(std::ostream& os) const MOZ_OVERRIDE;
|
||||
@ -343,7 +344,8 @@ public:
|
||||
void
|
||||
PushEntry(HashAlgorithm hashFunc, const std::vector<uint8_t>& fingerprint)
|
||||
{
|
||||
mFingerprints.push_back({ hashFunc, fingerprint });
|
||||
Fingerprint value = { hashFunc, fingerprint };
|
||||
mFingerprints.push_back(value);
|
||||
}
|
||||
|
||||
virtual void Serialize(std::ostream& os) const MOZ_OVERRIDE;
|
||||
@ -420,7 +422,8 @@ public:
|
||||
void
|
||||
PushEntry(Semantics semantics, const std::vector<std::string>& tags)
|
||||
{
|
||||
mGroups.push_back({ semantics, tags });
|
||||
Group value = { semantics, tags };
|
||||
mGroups.push_back(value);
|
||||
}
|
||||
|
||||
virtual void Serialize(std::ostream& os) const MOZ_OVERRIDE;
|
||||
@ -600,7 +603,8 @@ public:
|
||||
void
|
||||
PushEntry(const std::string& identifier, const std::string& appdata = "")
|
||||
{
|
||||
mMsids.push_back({ identifier, appdata });
|
||||
Msid value = { identifier, appdata };
|
||||
mMsids.push_back(value);
|
||||
}
|
||||
|
||||
virtual void Serialize(std::ostream& os) const MOZ_OVERRIDE;
|
||||
@ -721,7 +725,8 @@ public:
|
||||
PushEntry(const std::string& pt, Type type, const std::string& parameter = "",
|
||||
const std::string& extra = "")
|
||||
{
|
||||
mFeedbacks.push_back({ pt, type, parameter, extra });
|
||||
Feedback value = { pt, type, parameter, extra };
|
||||
mFeedbacks.push_back(value);
|
||||
}
|
||||
|
||||
virtual void Serialize(std::ostream& os) const MOZ_OVERRIDE;
|
||||
@ -792,7 +797,8 @@ public:
|
||||
PushEntry(const std::string& pt, CodecType codec, const std::string& name,
|
||||
uint32_t clock, uint32_t channels = 0)
|
||||
{
|
||||
mRtpmaps.push_back({ pt, codec, name, clock, channels });
|
||||
Rtpmap value = { pt, codec, name, clock, channels };
|
||||
mRtpmaps.push_back(value);
|
||||
}
|
||||
|
||||
virtual void Serialize(std::ostream& os) const MOZ_OVERRIDE;
|
||||
@ -1068,7 +1074,8 @@ public:
|
||||
PushEntry(const std::string& pt, const std::string& name,
|
||||
uint32_t streams = 0)
|
||||
{
|
||||
mSctpmaps.push_back({ pt, name, streams });
|
||||
Sctpmap value = { pt, name, streams };
|
||||
mSctpmaps.push_back(value);
|
||||
}
|
||||
|
||||
virtual void Serialize(std::ostream& os) const MOZ_OVERRIDE;
|
||||
@ -1168,7 +1175,8 @@ public:
|
||||
void
|
||||
PushEntry(uint32_t ssrc, const std::string& attribute)
|
||||
{
|
||||
mSsrcs.push_back({ ssrc, attribute });
|
||||
Ssrc value = { ssrc, attribute };
|
||||
mSsrcs.push_back(value);
|
||||
}
|
||||
|
||||
virtual void Serialize(std::ostream& os) const MOZ_OVERRIDE;
|
||||
@ -1204,7 +1212,8 @@ public:
|
||||
void
|
||||
PushEntry(Semantics semantics, const std::vector<uint32_t>& ssrcs)
|
||||
{
|
||||
mSsrcGroups.push_back({ semantics, ssrcs });
|
||||
SsrcGroup value = { semantics, ssrcs };
|
||||
mSsrcGroups.push_back(value);
|
||||
}
|
||||
|
||||
virtual void Serialize(std::ostream& os) const MOZ_OVERRIDE;
|
||||
|
@ -444,8 +444,8 @@ tinybool sdp_timespec_valid (void *sdp_ptr)
|
||||
}
|
||||
|
||||
if ((sdp_p->timespec_p == NULL) ||
|
||||
(sdp_p->timespec_p->start_time == '\0') ||
|
||||
(sdp_p->timespec_p->stop_time == '\0')) {
|
||||
(sdp_p->timespec_p->start_time[0] == '\0') ||
|
||||
(sdp_p->timespec_p->stop_time[0] == '\0')) {
|
||||
return (FALSE);
|
||||
} else {
|
||||
return (TRUE);
|
||||
|
@ -926,8 +926,8 @@ sdp_result_e sdp_parse_timespec (sdp_t *sdp_p, uint16_t level, const char *ptr)
|
||||
sdp_result_e sdp_build_timespec (sdp_t *sdp_p, uint16_t level, flex_string *fs)
|
||||
{
|
||||
if ((sdp_p->timespec_p == NULL) ||
|
||||
(sdp_p->timespec_p->start_time == '\0') ||
|
||||
(sdp_p->timespec_p->stop_time == '\0')) {
|
||||
(sdp_p->timespec_p->start_time[0] == '\0') ||
|
||||
(sdp_p->timespec_p->stop_time[0] == '\0')) {
|
||||
if (sdp_p->conf_p->timespec_reqd == TRUE) {
|
||||
CSFLogError(logTag, "%s Invalid params for t= time spec line, "
|
||||
"build failed.", sdp_p->debug_str);
|
||||
|
@ -1246,7 +1246,8 @@ class SignalingAgent {
|
||||
if (getRemoteDescription().empty()) {
|
||||
// Not time to add this, because the unit-test code hasn't set the
|
||||
// description yet.
|
||||
deferredCandidates_.push_back({candidate, mid, level, true});
|
||||
DeferredCandidate candidateStruct = {candidate, mid, level, true};
|
||||
deferredCandidates_.push_back(candidateStruct);
|
||||
} else {
|
||||
AddIceCandidate(candidate, mid, level, true);
|
||||
}
|
||||
|
@ -24,20 +24,13 @@ pref("security.ssl3.ecdhe_rsa_aes_128_sha", true);
|
||||
pref("security.ssl3.ecdhe_ecdsa_aes_128_sha", true);
|
||||
pref("security.ssl3.ecdhe_rsa_aes_256_sha", true);
|
||||
pref("security.ssl3.ecdhe_ecdsa_aes_256_sha", true);
|
||||
pref("security.ssl3.ecdhe_rsa_des_ede3_sha", false);
|
||||
pref("security.ssl3.dhe_rsa_aes_128_sha", true);
|
||||
pref("security.ssl3.dhe_rsa_camellia_128_sha", false);
|
||||
pref("security.ssl3.dhe_rsa_aes_256_sha", true);
|
||||
pref("security.ssl3.dhe_rsa_camellia_256_sha", false);
|
||||
pref("security.ssl3.dhe_rsa_des_ede3_sha", false);
|
||||
pref("security.ssl3.dhe_dss_aes_128_sha", true);
|
||||
pref("security.ssl3.dhe_dss_aes_256_sha", false);
|
||||
pref("security.ssl3.dhe_dss_aes_128_sha", false);
|
||||
pref("security.ssl3.ecdhe_rsa_rc4_128_sha", true);
|
||||
pref("security.ssl3.ecdhe_ecdsa_rc4_128_sha", true);
|
||||
pref("security.ssl3.rsa_aes_128_sha", true);
|
||||
pref("security.ssl3.rsa_camellia_128_sha", false);
|
||||
pref("security.ssl3.rsa_aes_256_sha", true);
|
||||
pref("security.ssl3.rsa_camellia_256_sha", false);
|
||||
pref("security.ssl3.rsa_des_ede3_sha", true);
|
||||
pref("security.ssl3.rsa_rc4_128_sha", true);
|
||||
pref("security.ssl3.rsa_rc4_128_md5", true);
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include "mozilla/net/RemoteOpenFileParent.h"
|
||||
#include "mozilla/net/ChannelDiverterParent.h"
|
||||
#include "mozilla/dom/ContentParent.h"
|
||||
#include "mozilla/dom/TabContext.h"
|
||||
#include "mozilla/dom/TabParent.h"
|
||||
#include "mozilla/dom/network/TCPSocketParent.h"
|
||||
#include "mozilla/dom/network/TCPServerSocketParent.h"
|
||||
@ -41,6 +42,7 @@
|
||||
#include "mozilla/net/OfflineObserver.h"
|
||||
|
||||
using mozilla::dom::ContentParent;
|
||||
using mozilla::dom::TabContext;
|
||||
using mozilla::dom::TabParent;
|
||||
using mozilla::net::PTCPSocketParent;
|
||||
using mozilla::dom::TCPSocketParent;
|
||||
@ -113,22 +115,23 @@ NeckoParent::GetValidatedAppInfo(const SerializedLoadContext& aSerialized,
|
||||
}
|
||||
}
|
||||
|
||||
const InfallibleTArray<PBrowserParent*>& browsers = aContent->ManagedPBrowserParent();
|
||||
for (uint32_t i = 0; i < browsers.Length(); i++) {
|
||||
nsRefPtr<TabParent> tabParent = static_cast<TabParent*>(browsers[i]);
|
||||
uint32_t appId = tabParent->OwnOrContainingAppId();
|
||||
nsTArray<TabContext> contextArray =
|
||||
static_cast<ContentParent*>(aContent)->GetManagedTabContext();
|
||||
for (uint32_t i = 0; i < contextArray.Length(); i++) {
|
||||
TabContext tabContext = contextArray[i];
|
||||
uint32_t appId = tabContext.OwnOrContainingAppId();
|
||||
bool inBrowserElement = aSerialized.IsNotNull() ? aSerialized.mIsInBrowserElement
|
||||
: tabParent->IsBrowserElement();
|
||||
: tabContext.IsBrowserElement();
|
||||
|
||||
if (appId == NECKO_UNKNOWN_APP_ID) {
|
||||
continue;
|
||||
}
|
||||
// We may get appID=NO_APP if child frame is neither a browser nor an app
|
||||
if (appId == NECKO_NO_APP_ID) {
|
||||
if (tabParent->HasOwnApp()) {
|
||||
if (tabContext.HasOwnApp()) {
|
||||
continue;
|
||||
}
|
||||
if (UsingNeckoIPCSecurity() && tabParent->IsBrowserElement()) {
|
||||
if (UsingNeckoIPCSecurity() && tabContext.IsBrowserElement()) {
|
||||
// <iframe mozbrowser> which doesn't have an <iframe mozapp> above it.
|
||||
// This is not supported now, and we'll need to do a code audit to make
|
||||
// sure we can handle it (i.e don't short-circuit using separate
|
||||
@ -141,7 +144,7 @@ NeckoParent::GetValidatedAppInfo(const SerializedLoadContext& aSerialized,
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (browsers.Length() != 0) {
|
||||
if (contextArray.Length() != 0) {
|
||||
return "App does not have permission";
|
||||
}
|
||||
|
||||
@ -521,10 +524,11 @@ NeckoParent::AllocPRemoteOpenFileParent(const SerializedLoadContext& aSerialized
|
||||
bool haveValidBrowser = false;
|
||||
bool hasManage = false;
|
||||
nsCOMPtr<mozIApplication> mozApp;
|
||||
for (uint32_t i = 0; i < Manager()->ManagedPBrowserParent().Length(); i++) {
|
||||
nsRefPtr<TabParent> tabParent =
|
||||
static_cast<TabParent*>(Manager()->ManagedPBrowserParent()[i]);
|
||||
uint32_t appId = tabParent->OwnOrContainingAppId();
|
||||
nsTArray<TabContext> contextArray =
|
||||
static_cast<ContentParent*>(Manager())->GetManagedTabContext();
|
||||
for (uint32_t i = 0; i < contextArray.Length(); i++) {
|
||||
TabContext tabContext = contextArray[i];
|
||||
uint32_t appId = tabContext.OwnOrContainingAppId();
|
||||
// Note: this enforces that SerializedLoadContext.appID is one of the apps
|
||||
// in the child process, but there's currently no way to verify the
|
||||
// request is not from a different app in that process.
|
||||
@ -814,10 +818,11 @@ NeckoParent::OfflineNotification(nsISupports *aSubject)
|
||||
uint32_t targetAppId = NECKO_UNKNOWN_APP_ID;
|
||||
info->GetAppId(&targetAppId);
|
||||
|
||||
for (uint32_t i = 0; i < Manager()->ManagedPBrowserParent().Length(); ++i) {
|
||||
nsRefPtr<TabParent> tabParent =
|
||||
static_cast<TabParent*>(Manager()->ManagedPBrowserParent()[i]);
|
||||
uint32_t appId = tabParent->OwnOrContainingAppId();
|
||||
nsTArray<TabContext> contextArray =
|
||||
static_cast<ContentParent*>(Manager())->GetManagedTabContext();
|
||||
for (uint32_t i = 0; i < contextArray.Length(); ++i) {
|
||||
TabContext tabContext = contextArray[i];
|
||||
uint32_t appId = tabContext.OwnOrContainingAppId();
|
||||
|
||||
if (appId == targetAppId) {
|
||||
if (gIOService) {
|
||||
|
@ -644,28 +644,14 @@ static const CipherPref sCipherPrefs[] = {
|
||||
{ "security.ssl3.ecdhe_ecdsa_aes_256_sha",
|
||||
TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, true },
|
||||
|
||||
{ "security.ssl3.ecdhe_rsa_des_ede3_sha",
|
||||
TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, false }, // deprecated (3DES)
|
||||
|
||||
{ "security.ssl3.dhe_rsa_aes_128_sha",
|
||||
TLS_DHE_RSA_WITH_AES_128_CBC_SHA, true },
|
||||
|
||||
{ "security.ssl3.dhe_rsa_camellia_128_sha",
|
||||
TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA, false }, // deprecated (Camellia)
|
||||
|
||||
{ "security.ssl3.dhe_rsa_aes_256_sha",
|
||||
TLS_DHE_RSA_WITH_AES_256_CBC_SHA, true },
|
||||
|
||||
{ "security.ssl3.dhe_rsa_camellia_256_sha",
|
||||
TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA, false }, // deprecated (Camellia)
|
||||
|
||||
{ "security.ssl3.dhe_rsa_des_ede3_sha",
|
||||
TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA, false }, // deprecated (3DES)
|
||||
|
||||
{ "security.ssl3.dhe_dss_aes_128_sha",
|
||||
TLS_DHE_DSS_WITH_AES_128_CBC_SHA, true }, // deprecated (DSS)
|
||||
{ "security.ssl3.dhe_dss_aes_256_sha",
|
||||
TLS_DHE_DSS_WITH_AES_256_CBC_SHA, false }, // deprecated (DSS)
|
||||
TLS_DHE_DSS_WITH_AES_128_CBC_SHA, false }, // deprecated (DSS)
|
||||
|
||||
{ "security.ssl3.ecdhe_rsa_rc4_128_sha",
|
||||
TLS_ECDHE_RSA_WITH_RC4_128_SHA, true, true }, // deprecated (RC4)
|
||||
@ -674,12 +660,8 @@ static const CipherPref sCipherPrefs[] = {
|
||||
|
||||
{ "security.ssl3.rsa_aes_128_sha",
|
||||
TLS_RSA_WITH_AES_128_CBC_SHA, true }, // deprecated (RSA key exchange)
|
||||
{ "security.ssl3.rsa_camellia_128_sha",
|
||||
TLS_RSA_WITH_CAMELLIA_128_CBC_SHA, false }, // deprecated (RSA, Camellia)
|
||||
{ "security.ssl3.rsa_aes_256_sha",
|
||||
TLS_RSA_WITH_AES_256_CBC_SHA, true }, // deprecated (RSA key exchange)
|
||||
{ "security.ssl3.rsa_camellia_256_sha",
|
||||
TLS_RSA_WITH_CAMELLIA_256_CBC_SHA, false }, // deprecated (RSA, Camellia)
|
||||
{ "security.ssl3.rsa_des_ede3_sha",
|
||||
TLS_RSA_WITH_3DES_EDE_CBC_SHA, true }, // deprecated (RSA key exchange, 3DES)
|
||||
|
||||
|
@ -18,6 +18,12 @@ let gIsWindows = ("@mozilla.org/windows-registry-key;1" in Cc);
|
||||
const isDebugBuild = Cc["@mozilla.org/xpcom/debug;1"]
|
||||
.getService(Ci.nsIDebug2).isDebugBuild;
|
||||
|
||||
// The test EV roots are only enabled in debug builds as a security measure.
|
||||
//
|
||||
// Bug 1008316: B2G doesn't have EV enabled, so EV is not expected even in debug
|
||||
// builds.
|
||||
const gEVExpected = isDebugBuild && !("@mozilla.org/b2g-process-global;1" in Cc);
|
||||
|
||||
const SSS_STATE_FILE_NAME = "SiteSecurityServiceState.txt";
|
||||
|
||||
const SEC_ERROR_BASE = Ci.nsINSSErrorsService.NSS_SEC_ERROR_BASE;
|
||||
|
@ -5,13 +5,6 @@
|
||||
|
||||
"use strict";
|
||||
|
||||
// XXX: The isDebugBuild tests you see are here because the test EV root is
|
||||
// only enabled for EV in debug builds, as a security measure. An ugly hack.
|
||||
//
|
||||
// Bug 1008316: B2G doesn't have EV enabled, so EV is not expected even in debug
|
||||
// builds.
|
||||
const gEVExpected = isDebugBuild && !("@mozilla.org/b2g-process-global;1" in Cc);
|
||||
|
||||
do_get_profile(); // must be called before getting nsIX509CertDB
|
||||
const certdb = Cc["@mozilla.org/security/x509certdb;1"]
|
||||
.getService(Ci.nsIX509CertDB);
|
||||
@ -33,7 +26,7 @@ let certList = [
|
||||
// Testing a root that looks like EV but is not EV enabled
|
||||
'int-non-ev-root',
|
||||
'non-ev-root',
|
||||
]
|
||||
];
|
||||
|
||||
function load_ca(ca_name) {
|
||||
var ca_filename = ca_name + ".der";
|
||||
|
@ -114,12 +114,12 @@ function checkForKeyType(keyType, inadequateKeySize, adequateKeySize) {
|
||||
// in such a build.
|
||||
let intFullName = intOKName + "-" + rootOKName;
|
||||
let eeFullName = eeOKName + "-" + intOKName + "-" + rootOKName;
|
||||
let expectedNamesForOCSP = isDebugBuild
|
||||
let expectedNamesForOCSP = gEVExpected
|
||||
? [ intFullName,
|
||||
eeFullName ]
|
||||
: [ eeFullName ];
|
||||
addKeySizeTestForEV(expectedNamesForOCSP, rootOKCertFileName,
|
||||
[ intFullName ], eeFullName, isDebugBuild);
|
||||
[ intFullName ], eeFullName, gEVExpected);
|
||||
|
||||
// Chain with a root cert that has an inadequate size for EV, but
|
||||
// adequate size for DV
|
||||
@ -133,7 +133,7 @@ function checkForKeyType(keyType, inadequateKeySize, adequateKeySize) {
|
||||
// adequate size for DV
|
||||
intFullName = intNotOKName + "-" + rootOKName;
|
||||
eeFullName = eeOKName + "-" + intNotOKName + "-" + rootOKName;
|
||||
expectedNamesForOCSP = isDebugBuild
|
||||
expectedNamesForOCSP = gEVExpected
|
||||
? [ intFullName ]
|
||||
: [ eeFullName ];
|
||||
addKeySizeTestForEV(expectedNamesForOCSP, rootOKCertFileName,
|
||||
|
@ -24,9 +24,6 @@ support-files =
|
||||
[test_hmac.js]
|
||||
|
||||
[test_sts_preloadlist_perwindowpb.js]
|
||||
# Bug 978426: Test fails consistently only on B2G ARM
|
||||
skip-if = buildapp == "b2g" && processor == "arm"
|
||||
|
||||
[test_sts_preloadlist_selfdestruct.js]
|
||||
[test_sts_holepunch.js]
|
||||
[test_sts_ipv4_ipv6.js]
|
||||
@ -84,8 +81,6 @@ run-sequentially = hardcoded ports
|
||||
[test_keysize.js]
|
||||
[test_keysize_ev.js]
|
||||
run-sequentially = hardcoded ports
|
||||
# Bug 1008316: B2G doesn't have EV enabled
|
||||
skip-if = buildapp == "b2g"
|
||||
[test_cert_chains.js]
|
||||
run-sequentially = hardcoded ports
|
||||
[test_client_cert.js]
|
||||
|
@ -757,6 +757,12 @@ CheckPresentedIDConformsToNameConstraintsSubtrees(
|
||||
case GeneralNameType::dNSName:
|
||||
matches = PresentedDNSIDMatchesReferenceDNSID(
|
||||
presentedID, ValidDNSIDMatchType::NameConstraint, base);
|
||||
// If matches is not false, then base must be syntactically valid
|
||||
// because PresentedDNSIDMatchesReferenceDNSID verifies that.
|
||||
if (!matches &&
|
||||
!IsValidDNSID(base, ValidDNSIDMatchType::NameConstraint)) {
|
||||
return Result::ERROR_CERT_NOT_IN_NAME_SPACE;
|
||||
}
|
||||
break;
|
||||
|
||||
case GeneralNameType::iPAddress:
|
||||
@ -846,15 +852,15 @@ CheckPresentedIDConformsToNameConstraintsSubtrees(
|
||||
// follow NSS's stricter policy by accepting wildcards only of the form
|
||||
// <x>*.<DNSID>, where <x> may be empty.
|
||||
//
|
||||
// An absolute presented DNS ID matches an absolute reference ID and a relative
|
||||
// reference ID, and vice-versa. For example, all of these are matches:
|
||||
// An relative presented DNS ID matches both an absolute reference ID and a
|
||||
// relative reference ID. Absolute presented DNS IDs are not supported:
|
||||
//
|
||||
// Presented ID Reference ID
|
||||
// ---------------------------
|
||||
// example.com example.com
|
||||
// example.com. example.com
|
||||
// example.com example.com.
|
||||
// example.com. exmaple.com.
|
||||
// Presented ID Reference ID Result
|
||||
// -------------------------------------
|
||||
// example.com example.com Match
|
||||
// example.com. example.com Mismatch
|
||||
// example.com example.com. Match
|
||||
// example.com. example.com. Mismatch
|
||||
//
|
||||
// There are more subtleties documented inline in the code.
|
||||
//
|
||||
@ -929,22 +935,16 @@ CheckPresentedIDConformsToNameConstraintsSubtrees(
|
||||
// Q: Are name constraints allowed to be specified as absolute names?
|
||||
// For example, does a presented ID of "example.com" match a name
|
||||
// constraint of "example.com." and vice versa.
|
||||
// A: Relative DNSNames match relative DNSName constraints but not
|
||||
// absolute DNSName constraints. Absolute DNSNames match absolute
|
||||
// DNSName constraints but not relative DNSName constraints (except "";
|
||||
// see below). This follows from the requirement that matching DNSNames
|
||||
// are constructed "by simply adding zero or more labels to the
|
||||
// left-hand side" of the constraint.
|
||||
// A: Absolute names are not supported as presented IDs or name
|
||||
// constraints. Only reference IDs may be absolute.
|
||||
//
|
||||
// Q: Are "" and "." valid DNSName constraints? If so, what do they mean?
|
||||
// A: Yes, both are valid. All relative and absolute DNSNames match
|
||||
// a constraint of "" because any DNSName can be formed "by simply
|
||||
// adding zero or more labels to the left-hand side" of "". In
|
||||
// particular, an excludedSubtrees DNSName constraint of "" forbids all
|
||||
// DNSNames. Only absolute names match a DNSName constraint of ".";
|
||||
// relative DNSNames do not match "." because one cannot form a relative
|
||||
// DNSName "by simply adding zero or more labels to the left-hand side"
|
||||
// of "." (all such names would be absolute).
|
||||
// Q: Is "" a valid DNSName constraints? If so, what does it mean?
|
||||
// A: Yes. Any valid presented DNSName can be formed "by simply adding zero
|
||||
// or more labels to the left-hand side" of "". In particular, an
|
||||
// excludedSubtrees DNSName constraint of "" forbids all DNSNames.
|
||||
//
|
||||
// Q: Is "." a valid DNSName constraints? If so, what does it mean?
|
||||
// A: No, because absolute names are not allowed (see above).
|
||||
//
|
||||
// [0] RFC 6265 (Cookies) Domain Matching rules:
|
||||
// http://tools.ietf.org/html/rfc6265#section-5.1.3
|
||||
@ -1043,55 +1043,42 @@ PresentedDNSIDMatchesReferenceDNSID(
|
||||
return false;
|
||||
}
|
||||
|
||||
bool isFirstPresentedByte = true;
|
||||
do {
|
||||
uint8_t presentedByte;
|
||||
if (presented.Read(presentedByte) != Success) {
|
||||
// We only allow wildcard labels that consist only of '*'.
|
||||
if (presented.Peek('*')) {
|
||||
Result rv = presented.Skip(1);
|
||||
if (rv != Success) {
|
||||
assert(false);
|
||||
return false;
|
||||
}
|
||||
if (presentedByte == '*') {
|
||||
// RFC 6125 is unclear about whether "www*.example.org" matches
|
||||
// "www.example.org". The Chromium test suite has this test:
|
||||
//
|
||||
// { false, "w.bar.foo.com", "w*.bar.foo.com" },
|
||||
//
|
||||
// We agree with Chromium by forbidding "*" from expanding to the empty
|
||||
// string.
|
||||
do {
|
||||
uint8_t referenceByte;
|
||||
if (reference.Read(referenceByte) != Success) {
|
||||
return false;
|
||||
}
|
||||
} while (!reference.Peek('.'));
|
||||
|
||||
// We also don't allow a non-IDN presented ID label to match an IDN
|
||||
// reference ID label, except when the entire presented ID label is "*".
|
||||
// This avoids confusion when matching a presented ID like
|
||||
// "xn-*.example.org" against "xn--www.example.org" (which attempts to
|
||||
// abuse the punycode syntax) or "www-*.example.org" against
|
||||
// "xn--www--ep4c4a2kpf" (which makes sense to match, semantically, but
|
||||
// no implementations actually do).
|
||||
if (!isFirstPresentedByte && StartsWithIDNALabel(referenceDNSID)) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
// Allow an absolute presented DNS ID to match a relative reference DNS
|
||||
// ID.
|
||||
if (reference.AtEnd() && presented.AtEnd() && presentedByte == '.') {
|
||||
return true;
|
||||
}
|
||||
|
||||
do {
|
||||
uint8_t referenceByte;
|
||||
if (reference.Read(referenceByte) != Success) {
|
||||
return false;
|
||||
}
|
||||
if (LocaleInsensitveToLower(presentedByte) !=
|
||||
LocaleInsensitveToLower(referenceByte)) {
|
||||
} while (!reference.Peek('.'));
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
uint8_t presentedByte;
|
||||
if (presented.Read(presentedByte) != Success) {
|
||||
return false;
|
||||
}
|
||||
uint8_t referenceByte;
|
||||
if (reference.Read(referenceByte) != Success) {
|
||||
return false;
|
||||
}
|
||||
if (LocaleInsensitveToLower(presentedByte) !=
|
||||
LocaleInsensitveToLower(referenceByte)) {
|
||||
return false;
|
||||
}
|
||||
if (presented.AtEnd()) {
|
||||
// Don't allow presented IDs to be absolute.
|
||||
if (presentedByte == '.') {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
isFirstPresentedByte = false;
|
||||
} while (!presented.AtEnd());
|
||||
}
|
||||
|
||||
// Allow a relative presented DNS ID to match an absolute reference DNS ID,
|
||||
// unless we're matching a name constraint.
|
||||
@ -1577,16 +1564,34 @@ IsValidDNSID(Input hostname, ValidDNSIDMatchType matchType)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool allowWildcard = matchType == ValidDNSIDMatchType::PresentedID;
|
||||
bool isWildcard = false;
|
||||
size_t dotCount = 0;
|
||||
|
||||
size_t labelLength = 0;
|
||||
bool labelIsAllNumeric = false;
|
||||
bool labelIsWildcard = false;
|
||||
bool labelEndsWithHyphen = false;
|
||||
|
||||
bool isFirstByte = true;
|
||||
// Only presented IDs are allowed to have wildcard labels. And, like
|
||||
// Chromium, be stricter than RFC 6125 requires by insisting that a
|
||||
// wildcard label consist only of '*'.
|
||||
bool isWildcard = matchType == ValidDNSIDMatchType::PresentedID &&
|
||||
input.Peek('*');
|
||||
bool isFirstByte = !isWildcard;
|
||||
if (isWildcard) {
|
||||
Result rv = input.Skip(1);
|
||||
if (rv != Success) {
|
||||
assert(false);
|
||||
return false;
|
||||
}
|
||||
|
||||
uint8_t b;
|
||||
rv = input.Read(b);
|
||||
if (rv != Success) {
|
||||
return false;
|
||||
}
|
||||
if (b != '.') {
|
||||
return false;
|
||||
}
|
||||
++dotCount;
|
||||
}
|
||||
|
||||
do {
|
||||
static const size_t MAX_LABEL_LENGTH = 63;
|
||||
@ -1595,14 +1600,6 @@ IsValidDNSID(Input hostname, ValidDNSIDMatchType matchType)
|
||||
if (input.Read(b) != Success) {
|
||||
return false;
|
||||
}
|
||||
if (labelIsWildcard) {
|
||||
// Like NSS, be stricter than RFC6125 requires by insisting that the
|
||||
// "*" must be the last character in the label. This also prevents
|
||||
// multiple "*" in the label.
|
||||
if (b != '.') {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
switch (b) {
|
||||
case '-':
|
||||
if (labelLength == 0) {
|
||||
@ -1657,20 +1654,6 @@ IsValidDNSID(Input hostname, ValidDNSIDMatchType matchType)
|
||||
}
|
||||
break;
|
||||
|
||||
case '*':
|
||||
if (!allowWildcard) {
|
||||
return false;
|
||||
}
|
||||
labelIsWildcard = true;
|
||||
isWildcard = true;
|
||||
labelIsAllNumeric = false;
|
||||
labelEndsWithHyphen = false;
|
||||
++labelLength;
|
||||
if (labelLength > MAX_LABEL_LENGTH) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
||||
case '.':
|
||||
++dotCount;
|
||||
if (labelLength == 0 &&
|
||||
@ -1681,8 +1664,6 @@ IsValidDNSID(Input hostname, ValidDNSIDMatchType matchType)
|
||||
if (labelEndsWithHyphen) {
|
||||
return false; // Labels must not end with a hyphen.
|
||||
}
|
||||
allowWildcard = false; // only allowed in the first label.
|
||||
labelIsWildcard = false;
|
||||
labelLength = 0;
|
||||
break;
|
||||
|
||||
@ -1692,6 +1673,12 @@ IsValidDNSID(Input hostname, ValidDNSIDMatchType matchType)
|
||||
isFirstByte = false;
|
||||
} while (!input.AtEnd());
|
||||
|
||||
// Only reference IDs, not presented IDs or name constraints, may be
|
||||
// absolute.
|
||||
if (labelLength == 0 && matchType != ValidDNSIDMatchType::ReferenceID) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (labelEndsWithHyphen) {
|
||||
return false; // Labels must not end with a hyphen.
|
||||
}
|
||||
|
@ -89,24 +89,24 @@ static const PresentedMatchesReference DNSID_MATCH_PARAMS[] =
|
||||
// digits
|
||||
DNS_ID_MATCH("a1", "a1"),
|
||||
|
||||
// A trailing dot indicates an absolute name, and absolute names can match
|
||||
// relative names, and vice-versa.
|
||||
// A trailing dot indicates an absolute name. Absolute presented names are
|
||||
// not allowed, but absolute reference names are allowed.
|
||||
DNS_ID_MATCH("example", "example"),
|
||||
DNS_ID_MATCH("example.", "example."),
|
||||
DNS_ID_MISMATCH("example.", "example."),
|
||||
DNS_ID_MATCH("example", "example."),
|
||||
DNS_ID_MATCH("example.", "example"),
|
||||
DNS_ID_MISMATCH("example.", "example"),
|
||||
DNS_ID_MATCH("example.com", "example.com"),
|
||||
DNS_ID_MATCH("example.com.", "example.com."),
|
||||
DNS_ID_MISMATCH("example.com.", "example.com."),
|
||||
DNS_ID_MATCH("example.com", "example.com."),
|
||||
DNS_ID_MATCH("example.com.", "example.com"),
|
||||
DNS_ID_MISMATCH("example.com.", "example.com"),
|
||||
DNS_ID_MISMATCH("example.com..", "example.com."),
|
||||
DNS_ID_MISMATCH("example.com..", "example.com"),
|
||||
DNS_ID_MISMATCH("example.com...", "example.com."),
|
||||
|
||||
// xn-- IDN prefix
|
||||
DNS_ID_MATCH("x*.b.a", "xa.b.a"),
|
||||
DNS_ID_MATCH("x*.b.a", "xna.b.a"),
|
||||
DNS_ID_MATCH("x*.b.a", "xn-a.b.a"),
|
||||
DNS_ID_MISMATCH("x*.b.a", "xa.b.a"),
|
||||
DNS_ID_MISMATCH("x*.b.a", "xna.b.a"),
|
||||
DNS_ID_MISMATCH("x*.b.a", "xn-a.b.a"),
|
||||
DNS_ID_MISMATCH("x*.b.a", "xn--a.b.a"),
|
||||
DNS_ID_MISMATCH("xn*.b.a", "xn--a.b.a"),
|
||||
DNS_ID_MISMATCH("xn-*.b.a", "xn--a.b.a"),
|
||||
@ -150,7 +150,8 @@ static const PresentedMatchesReference DNSID_MATCH_PARAMS[] =
|
||||
|
||||
DNS_ID_MISMATCH("w*w.bar.foo.c0m", "wwww.bar.foo.com"),
|
||||
|
||||
DNS_ID_MATCH("wa*.bar.foo.com", "WALLY.bar.foo.com"),
|
||||
// '*' must be the only character in the wildcard label
|
||||
DNS_ID_MISMATCH("wa*.bar.foo.com", "WALLY.bar.foo.com"),
|
||||
|
||||
// We require "*" to be the last character in a wildcard label, but
|
||||
// Chromium does not.
|
||||
@ -199,8 +200,9 @@ static const PresentedMatchesReference DNSID_MATCH_PARAMS[] =
|
||||
DNS_ID_MISMATCH("*.example.com", "example.com"),
|
||||
// (e.g., baz*.example.net and *baz.example.net and b*z.example.net would
|
||||
// be taken to match baz1.example.net and foobaz.example.net and
|
||||
// buzz.example.net, respectively
|
||||
DNS_ID_MATCH("baz*.example.net", "baz1.example.net"),
|
||||
// buzz.example.net, respectively. However, we don't allow any characters
|
||||
// other than '*' in the wildcard label.
|
||||
DNS_ID_MISMATCH("baz*.example.net", "baz1.example.net"),
|
||||
|
||||
// Both of these are different from Chromium, but match NSS, becaues the
|
||||
// wildcard character "*" is not the last character of the label.
|
||||
@ -245,17 +247,18 @@ static const PresentedMatchesReference DNSID_MATCH_PARAMS[] =
|
||||
|
||||
// Absolute vs relative DNS name tests. Although not explicitly specified
|
||||
// in RFC 6125, absolute reference names (those ending in a .) should
|
||||
// match either absolute or relative presented names.
|
||||
// match either absolute or relative presented names. We don't allow
|
||||
// absolute presented names.
|
||||
// TODO: File errata against RFC 6125 about this.
|
||||
DNS_ID_MATCH("foo.com.", "foo.com"),
|
||||
DNS_ID_MISMATCH("foo.com.", "foo.com"),
|
||||
DNS_ID_MATCH("foo.com", "foo.com."),
|
||||
DNS_ID_MATCH("foo.com.", "foo.com."),
|
||||
DNS_ID_MATCH("f.", "f"),
|
||||
DNS_ID_MISMATCH("foo.com.", "foo.com."),
|
||||
DNS_ID_MISMATCH("f.", "f"),
|
||||
DNS_ID_MATCH("f", "f."),
|
||||
DNS_ID_MATCH("f.", "f."),
|
||||
DNS_ID_MATCH("*.bar.foo.com.", "www-3.bar.foo.com"),
|
||||
DNS_ID_MISMATCH("f.", "f."),
|
||||
DNS_ID_MISMATCH("*.bar.foo.com.", "www-3.bar.foo.com"),
|
||||
DNS_ID_MATCH("*.bar.foo.com", "www-3.bar.foo.com."),
|
||||
DNS_ID_MATCH("*.bar.foo.com.", "www-3.bar.foo.com."),
|
||||
DNS_ID_MISMATCH("*.bar.foo.com.", "www-3.bar.foo.com."),
|
||||
|
||||
// We require the reference ID to be a valid DNS name, so we cannot test this
|
||||
// case.
|
||||
@ -269,8 +272,10 @@ static const PresentedMatchesReference DNSID_MATCH_PARAMS[] =
|
||||
|
||||
// The result is different than Chromium because we don't know that co.uk is
|
||||
// a TLD.
|
||||
DNS_ID_MATCH("*.co.uk.", "foo.co.uk"),
|
||||
DNS_ID_MATCH("*.co.uk.", "foo.co.uk."),
|
||||
DNS_ID_MATCH("*.co.uk", "foo.co.uk"),
|
||||
DNS_ID_MATCH("*.co.uk", "foo.co.uk."),
|
||||
DNS_ID_MISMATCH("*.co.uk.", "foo.co.uk"),
|
||||
DNS_ID_MISMATCH("*.co.uk.", "foo.co.uk."),
|
||||
};
|
||||
|
||||
struct InputValidity
|
||||
@ -309,10 +314,10 @@ static const InputValidity DNSNAMES_VALIDITY[] =
|
||||
I("a.b..c", false, false),
|
||||
I(".a.b.c.", false, false),
|
||||
|
||||
// absolute names
|
||||
I("a.", true, true),
|
||||
I("a.b.", true, true),
|
||||
I("a.b.c.", true, true),
|
||||
// absolute names (only allowed for reference names)
|
||||
I("a.", true, false),
|
||||
I("a.b.", true, false),
|
||||
I("a.b.c.", true, false),
|
||||
|
||||
// absolute names with empty label at end
|
||||
I("a..", false, false),
|
||||
@ -432,17 +437,18 @@ static const InputValidity DNSNAMES_VALIDITY[] =
|
||||
I("a-----------------b", true, true),
|
||||
|
||||
// Wildcard specifications are not valid reference names, but are valid
|
||||
// presented names if there are enough labels
|
||||
// presented names if there are enough labels and if '*' is the only
|
||||
// character in the wildcard label.
|
||||
I("*.a", false, false),
|
||||
I("a*", false, false),
|
||||
I("a*.", false, false),
|
||||
I("a*.a", false, false),
|
||||
I("a*.a.", false, false),
|
||||
I("*.a.b", false, true),
|
||||
I("*.a.b.", false, true),
|
||||
I("a*.b.c", false, true),
|
||||
I("*.a.b.", false, false),
|
||||
I("a*.b.c", false, false),
|
||||
I("*.a.b.c", false, true),
|
||||
I("a*.b.c.d", false, true),
|
||||
I("a*.b.c.d", false, false),
|
||||
|
||||
// Multiple wildcards are not allowed.
|
||||
I("a**.b.c", false, false),
|
||||
@ -463,9 +469,9 @@ static const InputValidity DNSNAMES_VALIDITY[] =
|
||||
I("a*b.c.d", false, false),
|
||||
|
||||
// Wildcards not allowed with IDNA prefix
|
||||
I("x*.a.b", false, true),
|
||||
I("xn*.a.b", false, true),
|
||||
I("xn-*.a.b", false, true),
|
||||
I("x*.a.b", false, false),
|
||||
I("xn*.a.b", false, false),
|
||||
I("xn-*.a.b", false, false),
|
||||
I("xn--*.a.b", false, false),
|
||||
I("xn--w*.a.b", false, false),
|
||||
|
||||
@ -1074,7 +1080,6 @@ static const uint8_t ipv6_other_addr_bytes[] = {
|
||||
static const uint8_t ipv4_other_addr_bytes[] = {
|
||||
5, 6, 7, 8
|
||||
};
|
||||
static const uint8_t ipv4_other_addr_str[] = "5.6.7.8";
|
||||
static const uint8_t ipv4_other_addr_bytes_FFFFFFFF[] = {
|
||||
5, 6, 7, 8, 0xff, 0xff, 0xff, 0xff
|
||||
};
|
||||
@ -1762,25 +1767,30 @@ static const NameConstraintParams NAME_CONSTRAINT_PARAMS[] =
|
||||
// For example, does a presented ID of "example.com" match a name
|
||||
// constraint of "example.com." and vice versa.
|
||||
//
|
||||
{ ByteString(), DNSName("example.com"),
|
||||
{ // The DNSName in the constraint is not valid because constraint DNS IDs
|
||||
// are not allowed to be absolute.
|
||||
ByteString(), DNSName("example.com"),
|
||||
GeneralSubtree(DNSName("example.com.")),
|
||||
Result::ERROR_CERT_NOT_IN_NAME_SPACE, Success,
|
||||
Result::ERROR_CERT_NOT_IN_NAME_SPACE, Result::ERROR_CERT_NOT_IN_NAME_SPACE,
|
||||
},
|
||||
{ ByteString(), DNSName("example.com."),
|
||||
{ // The DNSName in the SAN is not valid because presented DNS IDs are not
|
||||
// allowed to be absolute.
|
||||
ByteString(), DNSName("example.com."),
|
||||
GeneralSubtree(DNSName("example.com")),
|
||||
Result::ERROR_CERT_NOT_IN_NAME_SPACE, Success,
|
||||
},
|
||||
{ // The presented ID is the same length as the constraint, because the
|
||||
// subdomain is only one character long and because the constraint both
|
||||
// begins and ends with ".".
|
||||
// begins and ends with ".". But, it doesn't matter because absolute names
|
||||
// are not allowed for DNSName constraints.
|
||||
ByteString(), DNSName("p.example.com"),
|
||||
GeneralSubtree(DNSName(".example.com.")),
|
||||
Result::ERROR_CERT_NOT_IN_NAME_SPACE, Success,
|
||||
Result::ERROR_CERT_NOT_IN_NAME_SPACE, Result::ERROR_CERT_NOT_IN_NAME_SPACE,
|
||||
},
|
||||
{ // Same as previous test case, but using a wildcard presented ID.
|
||||
ByteString(), DNSName("*.example.com"),
|
||||
GeneralSubtree(DNSName(".example.com.")),
|
||||
Result::ERROR_CERT_NOT_IN_NAME_SPACE, Success
|
||||
Result::ERROR_CERT_NOT_IN_NAME_SPACE, Result::ERROR_CERT_NOT_IN_NAME_SPACE
|
||||
},
|
||||
|
||||
// Q: Are "" and "." valid DNSName constraints? If so, what do they mean?
|
||||
@ -1788,17 +1798,19 @@ static const NameConstraintParams NAME_CONSTRAINT_PARAMS[] =
|
||||
GeneralSubtree(DNSName("")),
|
||||
Success, Result::ERROR_CERT_NOT_IN_NAME_SPACE
|
||||
},
|
||||
{ ByteString(), DNSName("example.com."),
|
||||
{ // The malformed (absolute) presented ID does not match.
|
||||
ByteString(), DNSName("example.com."),
|
||||
GeneralSubtree(DNSName("")),
|
||||
Success, Result::ERROR_CERT_NOT_IN_NAME_SPACE
|
||||
Result::ERROR_CERT_NOT_IN_NAME_SPACE, Success
|
||||
},
|
||||
{ ByteString(), DNSName("example.com"),
|
||||
{ // Invalid syntax in name constraint -> ERROR_CERT_NOT_IN_NAME_SPACE.
|
||||
ByteString(), DNSName("example.com"),
|
||||
GeneralSubtree(DNSName(".")),
|
||||
Result::ERROR_CERT_NOT_IN_NAME_SPACE, Success,
|
||||
Result::ERROR_CERT_NOT_IN_NAME_SPACE, Result::ERROR_CERT_NOT_IN_NAME_SPACE,
|
||||
},
|
||||
{ ByteString(), DNSName("example.com."),
|
||||
GeneralSubtree(DNSName(".")),
|
||||
Success, Result::ERROR_CERT_NOT_IN_NAME_SPACE
|
||||
Result::ERROR_CERT_NOT_IN_NAME_SPACE, Result::ERROR_CERT_NOT_IN_NAME_SPACE
|
||||
},
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
@ -1908,12 +1920,12 @@ static const NameConstraintParams NAME_CONSTRAINT_PARAMS[] =
|
||||
},
|
||||
{ // The presented IPv4 constraint is truncated
|
||||
ByteString(), IPAddress(ipv4_addr_bytes),
|
||||
GeneralSubtree(IPAddress(ipv4_addr_truncated_bytes)),
|
||||
GeneralSubtree(IPAddress(ipv4_constraint_truncated_bytes)),
|
||||
Result::ERROR_BAD_DER, Result::ERROR_BAD_DER
|
||||
},
|
||||
{ // The presented IPv4 constraint is too long
|
||||
ByteString(), IPAddress(ipv4_addr_bytes),
|
||||
GeneralSubtree(IPAddress(ipv4_addr_overlong_bytes)),
|
||||
GeneralSubtree(IPAddress(ipv4_constraint_overlong_bytes)),
|
||||
Result::ERROR_BAD_DER, Result::ERROR_BAD_DER
|
||||
},
|
||||
{ // The presented IPv6 address is empty
|
||||
@ -1938,12 +1950,12 @@ static const NameConstraintParams NAME_CONSTRAINT_PARAMS[] =
|
||||
},
|
||||
{ // The presented IPv6 constraint is truncated
|
||||
ByteString(), IPAddress(ipv6_addr_bytes),
|
||||
GeneralSubtree(IPAddress(ipv6_addr_truncated_bytes)),
|
||||
GeneralSubtree(IPAddress(ipv6_constraint_truncated_bytes)),
|
||||
Result::ERROR_BAD_DER, Result::ERROR_BAD_DER
|
||||
},
|
||||
{ // The presented IPv6 constraint is too long
|
||||
ByteString(), IPAddress(ipv6_addr_bytes),
|
||||
GeneralSubtree(IPAddress(ipv6_addr_overlong_bytes)),
|
||||
GeneralSubtree(IPAddress(ipv6_constraint_overlong_bytes)),
|
||||
Result::ERROR_BAD_DER, Result::ERROR_BAD_DER
|
||||
},
|
||||
|
||||
@ -2161,4 +2173,4 @@ TEST_P(pkixnames_CheckNameConstraints,
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(pkixnames_CheckNameConstraints,
|
||||
pkixnames_CheckNameConstraints,
|
||||
testing::ValuesIn(NAME_CONSTRAINT_PARAMS));
|
||||
testing::ValuesIn(NAME_CONSTRAINT_PARAMS));
|
||||
|
@ -298,56 +298,60 @@ DataReportingService.prototype = Object.freeze({
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
_loadClientID: Task.async(function* () {
|
||||
_loadClientID: function () {
|
||||
if (this._loadClientIdTask) {
|
||||
return this._loadClientIdTask;
|
||||
}
|
||||
|
||||
// Previously we had the stable client ID managed in FHR.
|
||||
// As we want to start correlating FHR and telemetry data (and moving towards
|
||||
// unifying the two), we moved the ID management to the datareporting
|
||||
// service. Consequently, we try to import the FHR ID first, so we can keep
|
||||
// using it.
|
||||
this._loadClientIdTask = Task.spawn(function* () {
|
||||
// Previously we had the stable client ID managed in FHR.
|
||||
// As we want to start correlating FHR and telemetry data (and moving towards
|
||||
// unifying the two), we moved the ID management to the datareporting
|
||||
// service. Consequently, we try to import the FHR ID first, so we can keep
|
||||
// using it.
|
||||
|
||||
// Try to load the client id from the DRS state file first.
|
||||
try {
|
||||
let state = yield CommonUtils.readJSON(this._stateFilePath);
|
||||
if (state && 'clientID' in state && typeof(state.clientID) == 'string') {
|
||||
this._clientID = state.clientID;
|
||||
this._loadClientIdTask = null;
|
||||
return this._clientID;
|
||||
// Try to load the client id from the DRS state file first.
|
||||
try {
|
||||
let state = yield CommonUtils.readJSON(this._stateFilePath);
|
||||
if (state && 'clientID' in state && typeof(state.clientID) == 'string') {
|
||||
this._clientID = state.clientID;
|
||||
this._loadClientIdTask = null;
|
||||
return this._clientID;
|
||||
}
|
||||
} catch (e) {
|
||||
// fall through to next option
|
||||
}
|
||||
} catch (e) {
|
||||
// fall through to next option
|
||||
}
|
||||
|
||||
// If we dont have DRS state yet, try to import from the FHR state.
|
||||
try {
|
||||
let fhrStatePath = OS.Path.join(OS.Constants.Path.profileDir, "healthreport", "state.json");
|
||||
let state = yield CommonUtils.readJSON(fhrStatePath);
|
||||
if (state && 'clientID' in state && typeof(state.clientID) == 'string') {
|
||||
this._clientID = state.clientID;
|
||||
this._loadClientIdTask = null;
|
||||
this._saveClientID();
|
||||
return this._clientID;
|
||||
// If we dont have DRS state yet, try to import from the FHR state.
|
||||
try {
|
||||
let fhrStatePath = OS.Path.join(OS.Constants.Path.profileDir, "healthreport", "state.json");
|
||||
let state = yield CommonUtils.readJSON(fhrStatePath);
|
||||
if (state && 'clientID' in state && typeof(state.clientID) == 'string') {
|
||||
this._clientID = state.clientID;
|
||||
this._loadClientIdTask = null;
|
||||
this._saveClientID();
|
||||
return this._clientID;
|
||||
}
|
||||
} catch (e) {
|
||||
// fall through to next option
|
||||
}
|
||||
} catch (e) {
|
||||
// fall through to next option
|
||||
}
|
||||
|
||||
// We dont have an id from FHR yet, generate a new ID.
|
||||
this._clientID = CommonUtils.generateUUID();
|
||||
this._loadClientIdTask = null;
|
||||
this._saveClientIdTask = this._saveClientID();
|
||||
// We dont have an id from FHR yet, generate a new ID.
|
||||
this._clientID = CommonUtils.generateUUID();
|
||||
this._loadClientIdTask = null;
|
||||
this._saveClientIdTask = this._saveClientID();
|
||||
|
||||
// Wait on persisting the id. Otherwise failure to save the ID would result in
|
||||
// the client creating and subsequently sending multiple IDs to the server.
|
||||
// This would appear as multiple clients submitting similar data, which would
|
||||
// result in orphaning.
|
||||
yield this._saveClientIdTask;
|
||||
// Wait on persisting the id. Otherwise failure to save the ID would result in
|
||||
// the client creating and subsequently sending multiple IDs to the server.
|
||||
// This would appear as multiple clients submitting similar data, which would
|
||||
// result in orphaning.
|
||||
yield this._saveClientIdTask;
|
||||
|
||||
return this._clientID;
|
||||
}),
|
||||
return this._clientID;
|
||||
}.bind(this));
|
||||
|
||||
return this._loadClientIdTask;
|
||||
},
|
||||
|
||||
_saveClientID: Task.async(function* () {
|
||||
let obj = { clientID: this._clientID };
|
||||
@ -364,13 +368,8 @@ DataReportingService.prototype = Object.freeze({
|
||||
* @return Promise<string> The stable client ID.
|
||||
*/
|
||||
getClientID: function() {
|
||||
if (this._loadClientIdTask) {
|
||||
return this._loadClientIdTask;
|
||||
}
|
||||
|
||||
if (!this._clientID) {
|
||||
this._loadClientIdTask = this._loadClientID();
|
||||
return this._loadClientIdTask;
|
||||
return this._loadClientID();
|
||||
}
|
||||
|
||||
return Promise.resolve(this._clientID);
|
||||
|
@ -191,7 +191,7 @@ class MochitestRunner(MozbuildObject):
|
||||
rerun_failures=False, no_autorun=False, repeat=0, run_until_failure=False,
|
||||
slow=False, chunk_by_dir=0, total_chunks=None, this_chunk=None, extraPrefs=[],
|
||||
jsdebugger=False, debug_on_failure=False, start_at=None, end_at=None,
|
||||
e10s=False, content_sandbox='off', dmd=False, dump_output_directory=None,
|
||||
e10s=False, strict_content_sandbox=False, dmd=False, dump_output_directory=None,
|
||||
dump_about_memory_after_test=False, dump_dmd_after_test=False,
|
||||
install_extension=None, quiet=False, environment=[], app_override=None, bisectChunk=None, runByDir=False,
|
||||
useTestMediaDevices=False, timeout=None, **kwargs):
|
||||
@ -313,9 +313,7 @@ class MochitestRunner(MozbuildObject):
|
||||
options.startAt = start_at
|
||||
options.endAt = end_at
|
||||
options.e10s = e10s
|
||||
options.contentSandbox = content_sandbox
|
||||
if options.contentSandbox != 'off':
|
||||
options.e10s = True
|
||||
options.strictContentSandbox = strict_content_sandbox
|
||||
options.dumpAboutMemoryAfterTest = dump_about_memory_after_test
|
||||
options.dumpDMDAfterTest = dump_dmd_after_test
|
||||
options.dumpOutputDirectory = dump_output_directory
|
||||
@ -502,13 +500,13 @@ def MochitestCommand(func):
|
||||
help='Start the browser JS debugger before running the test. Implies --no-autorun.')
|
||||
func = jsdebugger(func)
|
||||
|
||||
this_chunk = CommandArgument('--e10s', action='store_true',
|
||||
e10s = CommandArgument('--e10s', action='store_true',
|
||||
help='Run tests with electrolysis preferences and test filtering enabled.')
|
||||
func = this_chunk(func)
|
||||
func = e10s(func)
|
||||
|
||||
this_chunk = CommandArgument('--content-sandbox', default='off', choices=['off', 'warn', 'on'],
|
||||
help='Run tests with the content sandbox enabled or in warn only mode (Windows only). --e10s is assumed.')
|
||||
func = this_chunk(func)
|
||||
strict_content_sandbox = CommandArgument('--strict-content-sandbox', action='store_true',
|
||||
help='Run tests with a more strict content sandbox (Windows only).')
|
||||
func = strict_content_sandbox(func)
|
||||
|
||||
dmd = CommandArgument('--dmd', action='store_true',
|
||||
help='Run tests with DMD active.')
|
||||
|
@ -363,11 +363,11 @@ class MochitestOptions(optparse.OptionParser):
|
||||
"dest": "e10s",
|
||||
"help": "Run tests with electrolysis preferences and test filtering enabled.",
|
||||
}],
|
||||
[["--content-sandbox"],
|
||||
{ "choices": ["off", "warn", "on"],
|
||||
"default": "off",
|
||||
"dest": "contentSandbox",
|
||||
"help": "Run tests with the content sandbox enabled or in warn only mode (Windows only). --e10s is assumed.",
|
||||
[["--strict-content-sandbox"],
|
||||
{ "action": "store_true",
|
||||
"default": False,
|
||||
"dest": "strictContentSandbox",
|
||||
"help": "Run tests with a more strict content sandbox (Windows only).",
|
||||
}],
|
||||
[["--dmd-path"],
|
||||
{ "action": "store",
|
||||
@ -479,11 +479,8 @@ class MochitestOptions(optparse.OptionParser):
|
||||
def verifyOptions(self, options, mochitest):
|
||||
""" verify correct options and cleanup paths """
|
||||
|
||||
if options.contentSandbox != 'off':
|
||||
options.e10s = True
|
||||
|
||||
mozinfo.update({"e10s": options.e10s}) # for test manifest parsing.
|
||||
mozinfo.update({"contentSandbox": options.contentSandbox}) # for test manifest parsing.
|
||||
mozinfo.update({"strictContentSandbox": options.strictContentSandbox}) # for test manifest parsing.
|
||||
|
||||
if options.app is None:
|
||||
if build_obj is not None:
|
||||
|
@ -1159,7 +1159,8 @@ class Mochitest(MochitestUtilsMixin):
|
||||
if options.browserChrome and options.timeout:
|
||||
options.extraPrefs.append("testing.browserTestHarness.timeout=%d" % options.timeout)
|
||||
options.extraPrefs.append("browser.tabs.remote.autostart=%s" % ('true' if options.e10s else 'false'))
|
||||
options.extraPrefs.append("browser.tabs.remote.sandbox=%s" % options.contentSandbox)
|
||||
if options.strictContentSandbox:
|
||||
options.extraPrefs.append("security.sandbox.windows.content.moreStrict=true")
|
||||
|
||||
# get extensions to install
|
||||
extensions = self.getExtensionsToInstall(options)
|
||||
|
@ -79,7 +79,7 @@ function run_test()
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
add_task(function setup() {
|
||||
add_task(function* setup() {
|
||||
// Avoid creating smart bookmarks during the test.
|
||||
Services.prefs.setIntPref("browser.places.smartBookmarksVersion", -1);
|
||||
|
||||
@ -107,7 +107,7 @@ add_task(function setup() {
|
||||
remove_all_bookmarks();
|
||||
});
|
||||
|
||||
add_task(function test_import_new()
|
||||
add_task(function* test_import_new()
|
||||
{
|
||||
// Test importing a Places bookmarks.html file.
|
||||
// 1. import bookmarks.exported.html
|
||||
@ -121,7 +121,7 @@ add_task(function test_import_new()
|
||||
remove_all_bookmarks();
|
||||
});
|
||||
|
||||
add_task(function test_emptytitle_export()
|
||||
add_task(function* test_emptytitle_export()
|
||||
{
|
||||
// Test exporting and importing with an empty-titled bookmark.
|
||||
// 1. import bookmarks
|
||||
@ -159,7 +159,7 @@ add_task(function test_emptytitle_export()
|
||||
remove_all_bookmarks();
|
||||
});
|
||||
|
||||
add_task(function test_import_chromefavicon()
|
||||
add_task(function* test_import_chromefavicon()
|
||||
{
|
||||
// Test exporting and importing with a bookmark pointing to a chrome favicon.
|
||||
// 1. import bookmarks
|
||||
@ -225,7 +225,7 @@ add_task(function test_import_chromefavicon()
|
||||
remove_all_bookmarks();
|
||||
});
|
||||
|
||||
add_task(function test_import_ontop()
|
||||
add_task(function* test_import_ontop()
|
||||
{
|
||||
// Test importing the exported bookmarks.html file *on top of* the existing
|
||||
// bookmarks.
|
||||
@ -244,7 +244,7 @@ add_task(function test_import_ontop()
|
||||
remove_all_bookmarks();
|
||||
});
|
||||
|
||||
function testImportedBookmarks()
|
||||
function* testImportedBookmarks()
|
||||
{
|
||||
for (let group in test_bookmarks) {
|
||||
do_print("[testImportedBookmarks()] Checking group '" + group + "'");
|
||||
@ -273,37 +273,7 @@ function testImportedBookmarks()
|
||||
}
|
||||
}
|
||||
|
||||
function testImportedBookmarksToFolder(aFolder)
|
||||
{
|
||||
root = PlacesUtils.getFolderContents(aFolder).root;
|
||||
|
||||
// Menu bookmarks are put directly into the folder, while other roots are
|
||||
// imported into subfolders.
|
||||
let rootFolderCount = test_bookmarks.menu.length;
|
||||
|
||||
for (let i = 0; i < root.childCount; i++) {
|
||||
let child = root.getChild(i);
|
||||
// This check depends on all "menu" bookmarks being listed first in the imported file :-|
|
||||
if (i < rootFolderCount) {
|
||||
checkItem(test_bookmarks.menu[i], child);
|
||||
}
|
||||
else {
|
||||
let container = child.QueryInterface(Ci.nsINavHistoryContainerResultNode);
|
||||
let group = /Toolbar/.test(container.title) ? test_bookmarks.toolbar
|
||||
: test_bookmarks.unfiled;
|
||||
container.containerOpen = true;
|
||||
do_print("[testImportedBookmarksToFolder()] Checking container '" + container.title + "'");
|
||||
for (let t = 0; t < container.childCount; t++) {
|
||||
checkItem(group[t], container.getChild(t));
|
||||
}
|
||||
container.containerOpen = false;
|
||||
}
|
||||
}
|
||||
|
||||
root.containerOpen = false;
|
||||
}
|
||||
|
||||
function checkItem(aExpected, aNode)
|
||||
function* checkItem(aExpected, aNode)
|
||||
{
|
||||
let id = aNode.itemId;
|
||||
|
||||
@ -373,7 +343,9 @@ function checkItem(aExpected, aNode)
|
||||
folder.containerOpen = true;
|
||||
do_check_eq(folder.childCount, aExpected.children.length);
|
||||
|
||||
aExpected.children.forEach(function (item, index) checkItem(item, folder.getChild(index)));
|
||||
for (let index = 0; index < aExpected.children.length; index++) {
|
||||
yield checkItem(aExpected.children[index], folder.getChild(index));
|
||||
}
|
||||
|
||||
folder.containerOpen = false;
|
||||
break;
|
||||
|
@ -2,6 +2,7 @@
|
||||
* 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/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
@ -21,7 +22,7 @@ Prompter.prototype = {
|
||||
QueryInterface : XPCOMUtils.generateQI([Ci.nsIPromptFactory, Ci.nsIPromptService, Ci.nsIPromptService2]),
|
||||
|
||||
|
||||
/* ---------- private memebers ---------- */
|
||||
/* ---------- private members ---------- */
|
||||
|
||||
pickPrompter : function (domWin) {
|
||||
return new ModalPrompter(domWin);
|
||||
@ -210,7 +211,7 @@ let PromptUtilsTemp = {
|
||||
|
||||
// If the URI explicitly specified a port, only include it when
|
||||
// it's not the default. (We never want "http://foo.com:80")
|
||||
port = uri.port;
|
||||
let port = uri.port;
|
||||
if (port != -1) {
|
||||
let handler = Services.io.getProtocolHandler(scheme);
|
||||
if (port != handler.defaultPort)
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user