This commit is contained in:
Ryan VanderMeulen 2017-08-24 20:13:30 -04:00
Родитель 5696c3e525 c29574c405
Коммит 5684ae54bc
125 изменённых файлов: 2623 добавлений и 982 удалений

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

@ -899,19 +899,6 @@ public:
bool NeedsDOMUIEvent() const
{ return !(mStateFlags & eIgnoreDOMUIEvent); }
/**
* Get/set survivingInUpdate bit on child indicating that parent recollects
* its children.
*/
bool IsSurvivingInUpdate() const { return mStateFlags & eSurvivingInUpdate; }
void SetSurvivingInUpdate(bool aIsSurviving)
{
if (aIsSurviving)
mStateFlags |= eSurvivingInUpdate;
else
mStateFlags &= ~eSurvivingInUpdate;
}
/**
* Get/set repositioned bit indicating that the accessible was moved in
* the accessible tree, i.e. the accessible tree structure differs from DOM.
@ -1039,11 +1026,10 @@ protected:
eGroupInfoDirty = 1 << 5, // accessible needs to update group info
eKidsMutating = 1 << 6, // subtree is being mutated
eIgnoreDOMUIEvent = 1 << 7, // don't process DOM UI events for a11y events
eSurvivingInUpdate = 1 << 8, // parent drops children to recollect them
eRelocated = 1 << 9, // accessible was moved in tree
eNoXBLKids = 1 << 10, // accessible don't allows XBL children
eNoKidsFromDOM = 1 << 11, // accessible doesn't allow children from DOM
eHasTextKids = 1 << 12, // accessible have a text leaf in children
eRelocated = 1 << 8, // accessible was moved in tree
eNoXBLKids = 1 << 9, // accessible don't allows XBL children
eNoKidsFromDOM = 1 << 10, // accessible doesn't allow children from DOM
eHasTextKids = 1 << 11, // accessible have a text leaf in children
eLastStateFlag = eNoKidsFromDOM
};
@ -1144,7 +1130,7 @@ protected:
nsTArray<Accessible*> mChildren;
int32_t mIndexInParent;
static const uint8_t kStateFlagsBits = 13;
static const uint8_t kStateFlagsBits = 12;
static const uint8_t kContextFlagsBits = 3;
static const uint8_t kTypeBits = 6;
static const uint8_t kGenericTypesBits = 16;

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

@ -306,9 +306,11 @@ this.AccessFu = { // jshint ignore:line
break;
case "Accessibility:NextObject":
case "Accessibility:PreviousObject": {
let rule = data ?
data.rule.substr(0, 1).toUpperCase() + data.rule.substr(1).toLowerCase() :
"Simple";
let rule = "Simple";
if (data && data.rule && data.rule.length) {
rule = data.rule.substr(0, 1).toUpperCase() +
data.rule.substr(1).toLowerCase();
}
let method = event.replace(/Accessibility:(\w+)Object/, "move$1");
this.Input.moveCursor(method, rule, "gesture");
break;

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

@ -46,7 +46,7 @@ ia2Accessible::QueryInterface(REFIID iid, void** ppv)
*ppv = static_cast<IAccessible2_3*>(this);
else if (IID_IAccessible2_2 == iid)
*ppv = static_cast<IAccessible2_2*>(this);
else if (IID_IAccessible2 == iid && !Compatibility::IsIA2Off())
else if (IID_IAccessible2 == iid)
*ppv = static_cast<IAccessible2*>(this);
if (*ppv) {

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

@ -139,7 +139,7 @@ Compatibility::Init()
HMODULE jawsHandle = ::GetModuleHandleW(L"jhook");
if (jawsHandle)
sConsumers |= (IsModuleVersionLessThan(jawsHandle, 8, 2173)) ?
sConsumers |= (IsModuleVersionLessThan(jawsHandle, 18, 4315)) ?
OLDJAWS : JAWS;
if (::GetModuleHandleW(L"gwm32inc"))
@ -224,11 +224,15 @@ ReadCOMRegDefaultString(const nsString& aRegPath, nsAString& aOutBuf)
{
aOutBuf.Truncate();
nsAutoString fullyQualifiedRegPath;
fullyQualifiedRegPath.AppendLiteral(u"SOFTWARE\\Classes\\");
fullyQualifiedRegPath.Append(aRegPath);
// Get the required size and type of the registry value.
// We expect either REG_SZ or REG_EXPAND_SZ.
DWORD type;
DWORD bufLen = 0;
LONG result = ::RegGetValue(HKEY_CLASSES_ROOT, aRegPath.get(),
LONG result = ::RegGetValue(HKEY_LOCAL_MACHINE, fullyQualifiedRegPath.get(),
nullptr, RRF_RT_ANY, &type, nullptr, &bufLen);
if (result != ERROR_SUCCESS || (type != REG_SZ && type != REG_EXPAND_SZ)) {
return false;
@ -239,7 +243,7 @@ ReadCOMRegDefaultString(const nsString& aRegPath, nsAString& aOutBuf)
aOutBuf.SetLength((bufLen + 1) / sizeof(char16_t));
result = ::RegGetValue(HKEY_CLASSES_ROOT, aRegPath.get(), nullptr,
result = ::RegGetValue(HKEY_LOCAL_MACHINE, fullyQualifiedRegPath.get(), nullptr,
flags, nullptr, aOutBuf.BeginWriting(), &bufLen);
if (result != ERROR_SUCCESS) {
aOutBuf.Truncate();

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

@ -19,16 +19,16 @@ namespace a11y {
class Compatibility
{
public:
/**
* Return true if IAccessible2 disabled.
*/
static bool IsIA2Off() { return !!(sConsumers & OLDJAWS); }
/**
* Return true if JAWS mode is enabled.
*/
static bool IsJAWS() { return !!(sConsumers & (JAWS | OLDJAWS)); }
/**
* Return true if using an e10s incompatible Jaws.
*/
static bool IsOldJAWS() { return !!(sConsumers & OLDJAWS); }
/**
* Return true if WE mode is enabled.
*/

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

@ -39,22 +39,21 @@ a11y::PlatformInit()
nsWinUtils::MaybeStartWindowEmulation();
ia2AccessibleText::InitTextChangeData();
if (BrowserTabsRemoteAutostart()) {
mscom::InterceptorLog::Init();
UniquePtr<RegisteredProxy> regCustomProxy(
mscom::RegisterProxy());
gRegCustomProxy = regCustomProxy.release();
UniquePtr<RegisteredProxy> regProxy(
mscom::RegisterProxy(L"ia2marshal.dll"));
gRegProxy = regProxy.release();
UniquePtr<RegisteredProxy> regAccTlb(
mscom::RegisterTypelib(L"oleacc.dll",
RegistrationFlags::eUseSystemDirectory));
gRegAccTlb = regAccTlb.release();
UniquePtr<RegisteredProxy> regMiscTlb(
mscom::RegisterTypelib(L"Accessible.tlb"));
gRegMiscTlb = regMiscTlb.release();
}
mscom::InterceptorLog::Init();
UniquePtr<RegisteredProxy> regCustomProxy(
mscom::RegisterProxy());
gRegCustomProxy = regCustomProxy.release();
UniquePtr<RegisteredProxy> regProxy(
mscom::RegisterProxy(L"ia2marshal.dll"));
gRegProxy = regProxy.release();
UniquePtr<RegisteredProxy> regAccTlb(
mscom::RegisterTypelib(L"oleacc.dll",
RegistrationFlags::eUseSystemDirectory));
gRegAccTlb = regAccTlb.release();
UniquePtr<RegisteredProxy> regMiscTlb(
mscom::RegisterTypelib(L"Accessible.tlb"));
gRegMiscTlb = regMiscTlb.release();
}
void

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

@ -12,4 +12,4 @@ skip-if = !e10s || !crashreporter
[browser_autoSubmitRequest.js]
skip-if = !e10s || !crashreporter
[browser_noPermanentKey.js]
skip-if = !e10s || !crashreporter
skip-if = !e10s || !crashreporter || (os == "linux" && bits == 32 && debug) # Bug 1383315

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

@ -950,6 +950,7 @@ const DownloadsViewPrototype = {
*/
onDownloadBatchEnded() {
this._loading = false;
this._updateViews();
},
/**
@ -1029,6 +1030,19 @@ const DownloadsViewPrototype = {
_updateView() {
throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
},
/**
* Computes aggregate values and propagates the changes to our views.
*/
_updateViews() {
// Do not update the status indicators during batch loads of download items.
if (this._loading) {
return;
}
this._refreshProperties();
this._views.forEach(this._updateView, this);
},
};
// DownloadsIndicatorData
@ -1065,13 +1079,6 @@ DownloadsIndicatorDataCtor.prototype = {
}
},
// Callback functions from DownloadsData
onDataLoadCompleted() {
DownloadsViewPrototype.onDataLoadCompleted.call(this);
this._updateViews();
},
onDownloadAdded(download) {
DownloadsViewPrototype.onDownloadAdded.call(this, download);
this._itemCount++;
@ -1149,20 +1156,6 @@ DownloadsIndicatorDataCtor.prototype = {
},
_attentionSuppressed: false,
/**
* Computes aggregate values and propagates the changes to our views.
*/
_updateViews() {
// Do not update the status indicators during batch loads of download items.
if (this._loading) {
return;
}
this._refreshProperties();
this._views.forEach(this._updateView, this);
},
/**
* Updates the specified view with the current aggregate values.
*
@ -1297,15 +1290,6 @@ DownloadsSummaryData.prototype = {
}
},
// Callback functions from DownloadsData - see the documentation in
// DownloadsViewPrototype for more information on what these functions
// are used for.
onDataLoadCompleted() {
DownloadsViewPrototype.onDataLoadCompleted.call(this);
this._updateViews();
},
onDownloadAdded(download) {
DownloadsViewPrototype.onDownloadAdded.call(this, download);
this._downloads.unshift(download);
@ -1331,19 +1315,6 @@ DownloadsSummaryData.prototype = {
// Propagation of properties to our views
/**
* Computes aggregate values and propagates the changes to our views.
*/
_updateViews() {
// Do not update the status indicators during batch loads of download items.
if (this._loading) {
return;
}
this._refreshProperties();
this._views.forEach(this._updateView, this);
},
/**
* Updates the specified view with the current aggregate values.
*

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

@ -2,6 +2,8 @@
* This file contains tests for the Preferences search bar.
*/
requestLongerTimeout(2);
// Enabling Searching functionatily. Will display search bar form this testcase forward.
add_task(async function() {
await SpecialPowers.pushPrefEnv({"set": [["browser.preferences.search", true]]});

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

@ -2,6 +2,8 @@
* This file contains tests for the Preferences search bar.
*/
requestLongerTimeout(2);
// Enabling Searching functionatily. Will display search bar form this testcase forward.
add_task(async function() {
await SpecialPowers.pushPrefEnv({"set": [

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

@ -2,6 +2,8 @@
* This file contains tests for the Preferences search bar.
*/
requestLongerTimeout(2);
// Enabling Searching functionatily. Will display search bar form this testcase forward.
add_task(async function() {
await SpecialPowers.pushPrefEnv({"set": [["browser.preferences.search", true]]});

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

@ -0,0 +1,224 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "CanRunScriptChecker.h"
#include "CustomMatchers.h"
void CanRunScriptChecker::registerMatchers(MatchFinder* AstMatcher) {
auto InvalidArg =
// We want to find any expression,
ignoreTrivials(expr(
// which has a refcounted pointer type,
hasType(pointerType(
pointee(hasDeclaration(cxxRecordDecl(isRefCounted()))))),
// and which is not this,
unless(cxxThisExpr()),
// and which is not a method call on a smart ptr,
unless(cxxMemberCallExpr(on(hasType(isSmartPtrToRefCounted())))),
// and which is not a parameter of the parent function,
unless(declRefExpr(to(parmVarDecl()))),
// and which is not a MOZ_KnownLive wrapped value.
unless(callExpr(callee(
functionDecl(hasName("MOZ_KnownLive"))))),
expr().bind("invalidArg")));
auto OptionalInvalidExplicitArg =
anyOf(
// We want to find any argument which is invalid.
hasAnyArgument(InvalidArg),
// This makes this matcher optional.
anything());
// Please not that the hasCanRunScriptAnnotation() matchers are not present
// directly in the cxxMemberCallExpr, callExpr and constructExpr matchers
// because we check that the corresponding functions can run script later in
// the checker code.
AstMatcher->addMatcher(
expr(
anyOf(
// We want to match a method call expression,
cxxMemberCallExpr(
// which optionally has an invalid arg,
OptionalInvalidExplicitArg,
// or which optionally has an invalid implicit this argument,
anyOf(
// which derefs into an invalid arg,
on(cxxOperatorCallExpr(
anyOf(
hasAnyArgument(InvalidArg),
anything()))),
// or is an invalid arg.
on(InvalidArg),
anything()),
expr().bind("callExpr")),
// or a regular call expression,
callExpr(
// which optionally has an invalid arg.
OptionalInvalidExplicitArg,
expr().bind("callExpr")),
// or a construct expression,
cxxConstructExpr(
// which optionally has an invalid arg.
OptionalInvalidExplicitArg,
expr().bind("constructExpr"))),
anyOf(
// We want to match the parent function.
forFunction(functionDecl().bind("nonCanRunScriptParentFunction")),
// ... optionally.
anything())),
this);
}
void CanRunScriptChecker::onStartOfTranslationUnit() {
IsFuncSetBuilt = false;
CanRunScriptFuncs.clear();
}
namespace {
/// This class is a callback used internally to match function declarations
/// with the MOZ_CAN_RUN_SCRIPT annotation, adding these functions and all
/// the methods they override to the can-run-script function set.
class FuncSetCallback : public MatchFinder::MatchCallback {
public:
FuncSetCallback(std::unordered_set<const FunctionDecl*> &FuncSet)
: CanRunScriptFuncs(FuncSet) {}
void run(const MatchFinder::MatchResult &Result) override;
private:
/// This method recursively adds all the methods overriden by the given
/// paremeter.
void addAllOverriddenMethodsRecursively(const CXXMethodDecl* Method);
std::unordered_set<const FunctionDecl*> &CanRunScriptFuncs;
};
void FuncSetCallback::run(const MatchFinder::MatchResult &Result) {
const FunctionDecl* Func =
Result.Nodes.getNodeAs<FunctionDecl>("canRunScriptFunction");
CanRunScriptFuncs.insert(Func);
// If this is a method, we check the methods it overrides.
if (auto* Method = dyn_cast<CXXMethodDecl>(Func)) {
addAllOverriddenMethodsRecursively(Method);
}
}
void FuncSetCallback::addAllOverriddenMethodsRecursively(
const CXXMethodDecl* Method) {
for (auto OverriddenMethod : Method->overridden_methods()) {
CanRunScriptFuncs.insert(OverriddenMethod);
// If this is not the definition, we also add the definition (if it
// exists) to the set.
if (!OverriddenMethod->isThisDeclarationADefinition()) {
if (auto Def = OverriddenMethod->getDefinition()) {
CanRunScriptFuncs.insert(Def);
}
}
addAllOverriddenMethodsRecursively(OverriddenMethod);
}
}
} // namespace
void CanRunScriptChecker::buildFuncSet(ASTContext *Context) {
// We create a match finder.
MatchFinder Finder;
// We create the callback which will be called when we find a function with
// a MOZ_CAN_RUN_SCRIPT annotation.
FuncSetCallback Callback(CanRunScriptFuncs);
// We add the matcher to the finder, linking it to our callback.
Finder.addMatcher(functionDecl(hasCanRunScriptAnnotation())
.bind("canRunScriptFunction"),
&Callback);
// We start the analysis, given the ASTContext our main checker is in.
Finder.matchAST(*Context);
}
void CanRunScriptChecker::check(
const MatchFinder::MatchResult &Result) {
// If the set of functions which can run script is not yet built, then build
// it.
if (!IsFuncSetBuilt) {
buildFuncSet(Result.Context);
IsFuncSetBuilt = true;
}
const char* ErrorInvalidArg =
"arguments must all be strong refs or parent parameters when calling a "
"function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object "
"argument)";
const char* ErrorNonCanRunScriptParent =
"functions marked as MOZ_CAN_RUN_SCRIPT can only be called from "
"functions also marked as MOZ_CAN_RUN_SCRIPT";
const char* NoteNonCanRunScriptParent =
"parent function declared here";
const Expr* InvalidArg = Result.Nodes.getNodeAs<Expr>("invalidArg");
const CallExpr* Call = Result.Nodes.getNodeAs<CallExpr>("callExpr");
// If we don't find the FunctionDecl linked to this call or if it's not marked
// as can-run-script, consider that we didn't find a match.
if (Call && (!Call->getDirectCallee() ||
!CanRunScriptFuncs.count(Call->getDirectCallee()))) {
Call = nullptr;
}
const CXXConstructExpr* Construct =
Result.Nodes.getNodeAs<CXXConstructExpr>("constructExpr");
// If we don't find the CXXConstructorDecl linked to this construct expression
// or if it's not marked as can-run-script, consider that we didn't find a
// match.
if (Construct && (!Construct->getConstructor() ||
!CanRunScriptFuncs.count(Construct->getConstructor()))) {
Construct = nullptr;
}
const FunctionDecl* ParentFunction =
Result.Nodes.getNodeAs<FunctionDecl>("nonCanRunScriptParentFunction");
// If the parent function can run script, consider that we didn't find a match
// because we only care about parent functions which can't run script.
if (ParentFunction && CanRunScriptFuncs.count(ParentFunction)) {
ParentFunction = nullptr;
}
// Get the call range from either the CallExpr or the ConstructExpr.
SourceRange CallRange;
if (Call) {
CallRange = Call->getSourceRange();
} else if (Construct) {
CallRange = Construct->getSourceRange();
} else {
// If we have neither a Call nor a Construct, we have nothing do to here.
return;
}
// If we have an invalid argument in the call, we emit the diagnostic to
// signal it.
if (InvalidArg) {
diag(CallRange.getBegin(), ErrorInvalidArg, DiagnosticIDs::Error)
<< CallRange;
}
// If the parent function is not marked as MOZ_CAN_RUN_SCRIPT, we emit an
// error and a not indicating it.
if (ParentFunction) {
diag(CallRange.getBegin(), ErrorNonCanRunScriptParent, DiagnosticIDs::Error)
<< CallRange;
diag(ParentFunction->getLocation(), NoteNonCanRunScriptParent,
DiagnosticIDs::Note);
}
}

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

@ -0,0 +1,32 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef CanRunScriptChecker_h__
#define CanRunScriptChecker_h__
#include "plugin.h"
#include <unordered_set>
class CanRunScriptChecker : public BaseCheck {
public:
CanRunScriptChecker(StringRef CheckName,
ContextType *Context = nullptr)
: BaseCheck(CheckName, Context) {}
void registerMatchers(MatchFinder* AstMatcher) override;
void check(const MatchFinder::MatchResult &Result) override;
// Simply initialize the can-run-script function set at the beginning of each
// translation unit.
void onStartOfTranslationUnit() override;
private:
/// Runs the inner matcher on the AST to find all the can-run-script
/// functions using custom rules (not only the annotation).
void buildFuncSet(ASTContext *Context);
bool IsFuncSetBuilt;
std::unordered_set<const FunctionDecl*> CanRunScriptFuncs;
};
#endif

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

@ -6,6 +6,7 @@
CHECK(ArithmeticArgChecker, "arithmetic-argument")
CHECK(AssertAssignmentChecker, "assignment-in-assert")
CHECK(CanRunScriptChecker, "can-run-script")
CHECK(DanglingOnTemporaryChecker, "dangling-on-temporary")
CHECK(ExplicitImplicitChecker, "implicit-constructor")
CHECK(ExplicitOperatorBoolChecker, "explicit-operator-bool")

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

@ -7,6 +7,7 @@
#include "ArithmeticArgChecker.h"
#include "AssertAssignmentChecker.h"
#include "CanRunScriptChecker.h"
#include "DanglingOnTemporaryChecker.h"
#include "ExplicitImplicitChecker.h"
#include "ExplicitOperatorBoolChecker.h"

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

@ -65,6 +65,12 @@ AST_MATCHER(FunctionDecl, hasNoAddRefReleaseOnReturnAttr) {
return hasCustomAnnotation(&Node, "moz_no_addref_release_on_return");
}
/// This matcher will match any function declaration that is marked as being
/// allowed to run script.
AST_MATCHER(FunctionDecl, hasCanRunScriptAnnotation) {
return hasCustomAnnotation(&Node, "moz_can_run_script");
}
/// This matcher will match all arithmetic binary operators.
AST_MATCHER(BinaryOperator, binaryArithmeticOperator) {
BinaryOperatorKind OpCode = Node.getOpcode();
@ -137,11 +143,15 @@ AST_MATCHER(MemberExpr, isAddRefOrRelease) {
return false;
}
/// This matcher will select classes which are refcounted.
/// This matcher will select classes which are refcounted AND have an mRefCnt
/// member.
AST_MATCHER(CXXRecordDecl, hasRefCntMember) {
return isClassRefCounted(&Node) && getClassRefCntMember(&Node);
}
/// This matcher will select classes which are refcounted.
AST_MATCHER(CXXRecordDecl, isRefCounted) { return isClassRefCounted(&Node); }
AST_MATCHER(QualType, hasVTable) { return typeHasVTable(Node); }
AST_MATCHER(CXXRecordDecl, hasNeedsNoVTableTypeAttr) {
@ -239,6 +249,17 @@ AST_MATCHER(CXXRecordDecl, isLambdaDecl) { return Node.isLambda(); }
AST_MATCHER(QualType, isRefPtr) { return typeIsRefPtr(Node); }
AST_MATCHER(QualType, isSmartPtrToRefCounted) {
auto *D = getNonTemplateSpecializedCXXRecordDecl(Node);
if (!D) {
return false;
}
D = D->getCanonicalDecl();
return D && hasCustomAnnotation(D, "moz_is_smartptr_to_refcounted");
}
AST_MATCHER(CXXRecordDecl, hasBaseClasses) {
const CXXRecordDecl *Decl = Node.getCanonicalDecl();
@ -260,6 +281,50 @@ AST_MATCHER(FunctionDecl, isMozMustReturnFromCaller) {
const FunctionDecl *Decl = Node.getCanonicalDecl();
return Decl && hasCustomAnnotation(Decl, "moz_must_return_from_caller");
}
#if CLANG_VERSION_FULL < 309
/// DISCLAIMER: This is a copy/paste from the Clang source code starting from
/// Clang 3.9, so that this matcher is supported in lower versions.
///
/// \brief Matches declaration of the function the statement belongs to
///
/// Given:
/// \code
/// F& operator=(const F& o) {
/// std::copy_if(o.begin(), o.end(), begin(), [](V v) { return v > 0; });
/// return *this;
/// }
/// \endcode
/// returnStmt(forFunction(hasName("operator=")))
/// matches 'return *this'
/// but does match 'return > 0'
AST_MATCHER_P(Stmt, forFunction, internal::Matcher<FunctionDecl>,
InnerMatcher) {
const auto &Parents = Finder->getASTContext().getParents(Node);
llvm::SmallVector<ast_type_traits::DynTypedNode, 8> Stack(Parents.begin(),
Parents.end());
while(!Stack.empty()) {
const auto &CurNode = Stack.back();
Stack.pop_back();
if(const auto *FuncDeclNode = CurNode.get<FunctionDecl>()) {
if(InnerMatcher.matches(*FuncDeclNode, Finder, Builder)) {
return true;
}
} else if(const auto *LambdaExprNode = CurNode.get<LambdaExpr>()) {
if(InnerMatcher.matches(*LambdaExprNode->getCallOperator(),
Finder, Builder)) {
return true;
}
} else {
for(const auto &Parent: Finder->getASTContext().getParents(CurNode))
Stack.push_back(Parent);
}
}
return false;
}
#endif
}
}

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

@ -428,6 +428,29 @@ inline bool inThirdPartyPath(const Decl *D, ASTContext *context) {
return inThirdPartyPath(Loc, SM);
}
inline CXXRecordDecl* getNonTemplateSpecializedCXXRecordDecl(QualType Q) {
auto *D = Q->getAsCXXRecordDecl();
if (!D) {
auto TemplateQ = Q->getAs<TemplateSpecializationType>();
if (!TemplateQ) {
return nullptr;
}
auto TemplateDecl = TemplateQ->getTemplateName().getAsTemplateDecl();
if (!TemplateDecl) {
return nullptr;
}
D = dyn_cast_or_null<CXXRecordDecl>(TemplateDecl->getTemplatedDecl());
if (!D) {
return nullptr;
}
}
return D;
}
inline bool inThirdPartyPath(const Decl *D) {
return inThirdPartyPath(D, &D->getASTContext());
}

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

@ -11,6 +11,7 @@ SOURCES += ['!ThirdPartyPaths.cpp']
UNIFIED_SOURCES += [
'ArithmeticArgChecker.cpp',
'AssertAssignmentChecker.cpp',
'CanRunScriptChecker.cpp',
'CustomTypeAnnotation.cpp',
'DanglingOnTemporaryChecker.cpp',
'DiagnosticsMatcher.cpp',

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

@ -0,0 +1,107 @@
#include <mozilla/RefPtr.h>
#define MOZ_CAN_RUN_SCRIPT __attribute__((annotate("moz_can_run_script")))
MOZ_CAN_RUN_SCRIPT void test() {
}
void test_parent() { // expected-note {{parent function declared here}}
test(); // expected-error {{functions marked as MOZ_CAN_RUN_SCRIPT can only be called from functions also marked as MOZ_CAN_RUN_SCRIPT}}
}
MOZ_CAN_RUN_SCRIPT void test_parent2() {
test();
}
struct RefCountedBase;
MOZ_CAN_RUN_SCRIPT void test2(RefCountedBase* param) {
}
struct RefCountedBase {
void AddRef();
void Release();
MOZ_CAN_RUN_SCRIPT void method_test() {
test();
}
MOZ_CAN_RUN_SCRIPT void method_test2() {
test2(this);
}
virtual void method_test3() {
test();
}
};
void test2_parent() { // expected-note {{parent function declared here}}
test2(new RefCountedBase); // expected-error {{arguments must all be strong refs or parent parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument)}} \
// expected-error {{functions marked as MOZ_CAN_RUN_SCRIPT can only be called from functions also marked as MOZ_CAN_RUN_SCRIPT}}
}
MOZ_CAN_RUN_SCRIPT void test2_parent2() {
test2(new RefCountedBase); // expected-error {{arguments must all be strong refs or parent parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument)}}
}
MOZ_CAN_RUN_SCRIPT void test2_parent3(RefCountedBase* param) {
test2(param);
}
MOZ_CAN_RUN_SCRIPT void test2_parent4() {
RefPtr<RefCountedBase> refptr = new RefCountedBase;
test2(refptr);
}
MOZ_CAN_RUN_SCRIPT void test2_parent5() {
test2(MOZ_KnownLive(new RefCountedBase));
}
MOZ_CAN_RUN_SCRIPT void test2_parent6() {
RefPtr<RefCountedBase> refptr = new RefCountedBase;
refptr->method_test();
refptr->method_test2();
}
MOZ_CAN_RUN_SCRIPT void test2_parent7() {
RefCountedBase* t = new RefCountedBase;
t->method_test(); // expected-error {{arguments must all be strong refs or parent parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument)}}
t->method_test2(); // expected-error {{arguments must all be strong refs or parent parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument)}}
}
MOZ_CAN_RUN_SCRIPT void test3(int* param) {}
MOZ_CAN_RUN_SCRIPT void test3_parent() {
test3(new int);
}
struct RefCountedChild : public RefCountedBase {
virtual void method_test3() override;
};
void RefCountedChild::method_test3() {
test();
}
struct RefCountedSubChild : public RefCountedChild {
MOZ_CAN_RUN_SCRIPT void method_test3() override;
};
void RefCountedSubChild::method_test3() {
test();
}
MOZ_CAN_RUN_SCRIPT void test4() {
RefPtr<RefCountedBase> refptr1 = new RefCountedChild;
refptr1->method_test3();
RefPtr<RefCountedBase> refptr2 = new RefCountedSubChild;
refptr2->method_test3();
RefPtr<RefCountedChild> refptr3 = new RefCountedSubChild;
refptr3->method_test3();
RefPtr<RefCountedSubChild> refptr4 = new RefCountedSubChild;
refptr4->method_test3();
}

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

@ -10,6 +10,7 @@ Library('clang-plugin-tests')
SOURCES += [
'TestAssertWithAssignment.cpp',
'TestBadImplicitConversionCtor.cpp',
'TestCanRunScript.cpp',
'TestCustomHeap.cpp',
'TestDanglingOnTemporary.cpp',
'TestExplicitOperatorBool.cpp',

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

@ -1,6 +1,6 @@
/******************************************************************************
** This file is an amalgamation of many separate C source files from SQLite
** version 3.20.0. By combining all the individual C code files into this
** version 3.20.1. 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
@ -1150,9 +1150,9 @@ extern "C" {
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
** [sqlite_version()] and [sqlite_source_id()].
*/
#define SQLITE_VERSION "3.20.0"
#define SQLITE_VERSION_NUMBER 3020000
#define SQLITE_SOURCE_ID "2017-08-01 13:24:15 9501e22dfeebdcefa783575e47c60b514d7c2e0cad73b2a496c0bc4b680900a8"
#define SQLITE_VERSION "3.20.1"
#define SQLITE_VERSION_NUMBER 3020001
#define SQLITE_SOURCE_ID "2017-08-24 16:21:36 8d3a7ea6c5690d6b7c3767558f4f01b511c55463e3f9e64506801fe9b74dce34"
/*
** CAPI3REF: Run-Time Library Version Numbers
@ -77122,7 +77122,8 @@ SQLITE_API void sqlite3_result_pointer(
){
Mem *pOut = pCtx->pOut;
assert( sqlite3_mutex_held(pOut->db->mutex) );
sqlite3VdbeMemSetNull(pOut);
sqlite3VdbeMemRelease(pOut);
pOut->flags = MEM_Null;
sqlite3VdbeMemSetPointer(pOut, pPtr, zPType, xDestructor);
}
SQLITE_API void sqlite3_result_subtype(sqlite3_context *pCtx, unsigned int eSubtype){
@ -200275,7 +200276,7 @@ static void fts5SourceIdFunc(
){
assert( nArg==0 );
UNUSED_PARAM2(nArg, apUnused);
sqlite3_result_text(pCtx, "fts5: 2017-08-01 13:24:15 9501e22dfeebdcefa783575e47c60b514d7c2e0cad73b2a496c0bc4b680900a8", -1, SQLITE_TRANSIENT);
sqlite3_result_text(pCtx, "fts5: 2017-08-24 16:21:36 8d3a7ea6c5690d6b7c3767558f4f01b511c55463e3f9e64506801fe9b74dce34", -1, SQLITE_TRANSIENT);
}
static int fts5Init(sqlite3 *db){

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

@ -121,9 +121,9 @@ extern "C" {
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
** [sqlite_version()] and [sqlite_source_id()].
*/
#define SQLITE_VERSION "3.20.0"
#define SQLITE_VERSION_NUMBER 3020000
#define SQLITE_SOURCE_ID "2017-08-01 13:24:15 9501e22dfeebdcefa783575e47c60b514d7c2e0cad73b2a496c0bc4b680900a8"
#define SQLITE_VERSION "3.20.1"
#define SQLITE_VERSION_NUMBER 3020001
#define SQLITE_SOURCE_ID "2017-08-24 16:21:36 8d3a7ea6c5690d6b7c3767558f4f01b511c55463e3f9e64506801fe9b74dce34"
/*
** CAPI3REF: Run-Time Library Version Numbers

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

@ -5,6 +5,9 @@
#include "ChromeUtils.h"
#include "jsfriendapi.h"
#include "WrapperFactory.h"
#include "mozilla/Base64.h"
#include "mozilla/BasePrincipal.h"
@ -126,6 +129,141 @@ ThreadSafeChromeUtils::Base64URLDecode(GlobalObject& aGlobal,
aRetval.set(buffer);
}
/* static */ void
ChromeUtils::WaiveXrays(GlobalObject& aGlobal,
JS::HandleValue aVal,
JS::MutableHandleValue aRetval,
ErrorResult& aRv)
{
JS::RootedValue value(aGlobal.Context(), aVal);
if (!xpc::WrapperFactory::WaiveXrayAndWrap(aGlobal.Context(), &value)) {
aRv.NoteJSContextException(aGlobal.Context());
} else {
aRetval.set(value);
}
}
/* static */ void
ChromeUtils::UnwaiveXrays(GlobalObject& aGlobal,
JS::HandleValue aVal,
JS::MutableHandleValue aRetval,
ErrorResult& aRv)
{
if (!aVal.isObject()) {
aRetval.set(aVal);
return;
}
JS::RootedObject obj(aGlobal.Context(), js::UncheckedUnwrap(&aVal.toObject()));
if (!JS_WrapObject(aGlobal.Context(), &obj)) {
aRv.NoteJSContextException(aGlobal.Context());
} else {
aRetval.setObject(*obj);
}
}
/* static */ void
ChromeUtils::GetClassName(GlobalObject& aGlobal,
JS::HandleObject aObj,
bool aUnwrap,
nsAString& aRetval)
{
JS::RootedObject obj(aGlobal.Context(), aObj);
if (aUnwrap) {
obj = js::UncheckedUnwrap(obj, /* stopAtWindowProxy = */ false);
}
aRetval = NS_ConvertUTF8toUTF16(nsDependentCString(js::GetObjectClass(obj)->name));
}
/* static */ void
ChromeUtils::ShallowClone(GlobalObject& aGlobal,
JS::HandleObject aObj,
JS::HandleObject aTarget,
JS::MutableHandleObject aRetval,
ErrorResult& aRv)
{
JSContext* cx = aGlobal.Context();
auto cleanup = MakeScopeExit([&] () {
aRv.NoteJSContextException(cx);
});
JS::Rooted<JS::IdVector> ids(cx, JS::IdVector(cx));
JS::AutoValueVector values(cx);
{
JS::RootedObject obj(cx, js::CheckedUnwrap(aObj));
if (!obj) {
js::ReportAccessDenied(cx);
return;
}
if (js::IsScriptedProxy(obj)) {
JS_ReportErrorASCII(cx, "Shallow cloning a proxy object is not allowed");
return;
}
JSAutoCompartment ac(cx, obj);
if (!JS_Enumerate(cx, obj, &ids) ||
!values.reserve(ids.length())) {
return;
}
JS::Rooted<JS::PropertyDescriptor> desc(cx);
JS::RootedId id(cx);
for (jsid idVal : ids) {
id = idVal;
if (!JS_GetOwnPropertyDescriptorById(cx, obj, id, &desc)) {
continue;
}
if (desc.setter() || desc.getter()) {
continue;
}
values.infallibleAppend(desc.value());
}
}
JS::RootedObject obj(cx);
{
Maybe<JSAutoCompartment> ac;
if (aTarget) {
JS::RootedObject target(cx, js::CheckedUnwrap(aTarget));
if (!target) {
js::ReportAccessDenied(cx);
return;
}
ac.emplace(cx, target);
}
obj = JS_NewPlainObject(cx);
if (!obj) {
return;
}
JS::RootedValue value(cx);
JS::RootedId id(cx);
for (uint32_t i = 0; i < ids.length(); i++) {
id = ids[i];
value = values[i];
JS_MarkCrossZoneId(cx, id);
if (!JS_WrapValue(cx, &value) ||
!JS_SetPropertyById(cx, obj, id, value)) {
return;
}
}
}
if (aTarget && !JS_WrapObject(cx, &obj)) {
return;
}
cleanup.release();
aRetval.set(obj);
}
/* static */ void
ChromeUtils::OriginAttributesToSuffix(dom::GlobalObject& aGlobal,
const dom::OriginAttributesDictionary& aAttrs,

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

@ -124,6 +124,27 @@ public:
const nsAString& aUrl,
const dom::CompileScriptOptionsDictionary& aOptions,
ErrorResult& aRv);
static void WaiveXrays(GlobalObject& aGlobal,
JS::HandleValue aVal,
JS::MutableHandleValue aRetval,
ErrorResult& aRv);
static void UnwaiveXrays(GlobalObject& aGlobal,
JS::HandleValue aVal,
JS::MutableHandleValue aRetval,
ErrorResult& aRv);
static void GetClassName(GlobalObject& aGlobal,
JS::HandleObject aObj,
bool aUnwrap,
nsAString& aRetval);
static void ShallowClone(GlobalObject& aGlobal,
JS::HandleObject aObj,
JS::HandleObject aTarget,
JS::MutableHandleObject aRetval,
ErrorResult& aRv);
};
} // namespace dom

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

@ -90,3 +90,7 @@ method DataTransfer.mozSetDataAt
method DataTransfer.mozGetDataAt
attribute DataTransfer.mozUserCancelled
attribute DataTransfer.mozSourceNode
// JavaScript feature usage
custom JS_asmjs uses asm.js
custom JS_wasm uses WebAssembly

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

@ -8921,12 +8921,9 @@ nsContentUtils::GetWindowRoot(nsIDocument* aDoc)
bool
nsContentUtils::IsPreloadType(nsContentPolicyType aType)
{
if (aType == nsIContentPolicy::TYPE_INTERNAL_SCRIPT_PRELOAD ||
aType == nsIContentPolicy::TYPE_INTERNAL_IMAGE_PRELOAD ||
aType == nsIContentPolicy::TYPE_INTERNAL_STYLESHEET_PRELOAD) {
return true;
}
return false;
return (aType == nsIContentPolicy::TYPE_INTERNAL_SCRIPT_PRELOAD ||
aType == nsIContentPolicy::TYPE_INTERNAL_IMAGE_PRELOAD ||
aType == nsIContentPolicy::TYPE_INTERNAL_STYLESHEET_PRELOAD);
}
nsresult

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

@ -9765,19 +9765,23 @@ already_AddRefed<nsIURI>
nsDocument::ResolvePreloadImage(nsIURI *aBaseURI,
const nsAString& aSrcAttr,
const nsAString& aSrcsetAttr,
const nsAString& aSizesAttr)
const nsAString& aSizesAttr,
bool *aIsImgSet)
{
nsString sourceURL;
bool isImgSet;
if (mPreloadPictureDepth == 1 && !mPreloadPictureFoundSource.IsVoid()) {
// We're in a <picture> element and found a URI from a source previous to
// this image, use it.
sourceURL = mPreloadPictureFoundSource;
isImgSet = true;
} else {
// Otherwise try to use this <img> as a source
HTMLImageElement::SelectSourceForTagWithAttrs(this, false, aSrcAttr,
aSrcsetAttr, aSizesAttr,
NullString(), NullString(),
sourceURL);
isImgSet = !aSrcsetAttr.IsEmpty();
}
// Empty sources are not loaded by <img> (i.e. not resolved to the baseURI)
@ -9795,6 +9799,8 @@ nsDocument::ResolvePreloadImage(nsIURI *aBaseURI,
return nullptr;
}
*aIsImgSet = isImgSet;
// We don't clear mPreloadPictureFoundSource because subsequent <img> tags in
// this this <picture> share the same <sources> (though this is not valid per
// spec)
@ -9803,16 +9809,12 @@ nsDocument::ResolvePreloadImage(nsIURI *aBaseURI,
void
nsDocument::MaybePreLoadImage(nsIURI* uri, const nsAString &aCrossOriginAttr,
ReferrerPolicy aReferrerPolicy)
ReferrerPolicy aReferrerPolicy, bool aIsImgSet)
{
// Early exit if the img is already present in the img-cache
// which indicates that the "real" load has already started and
// that we shouldn't preload it.
int16_t blockingStatus;
if (nsContentUtils::IsImageInCache(uri, static_cast<nsIDocument *>(this)) ||
!nsContentUtils::CanLoadImage(uri, static_cast<nsIDocument *>(this),
this, NodePrincipal(), &blockingStatus,
nsIContentPolicy::TYPE_INTERNAL_IMAGE_PRELOAD)) {
if (nsContentUtils::IsImageInCache(uri, static_cast<nsIDocument *>(this))) {
return;
}
@ -9831,6 +9833,10 @@ nsDocument::MaybePreLoadImage(nsIURI* uri, const nsAString &aCrossOriginAttr,
MOZ_CRASH("Unknown CORS mode!");
}
nsContentPolicyType policyType =
aIsImgSet ? nsIContentPolicy::TYPE_IMAGESET :
nsIContentPolicy::TYPE_INTERNAL_IMAGE_PRELOAD;
// Image not in cache - trigger preload
RefPtr<imgRequestProxy> request;
nsresult rv =
@ -9844,7 +9850,7 @@ nsDocument::MaybePreLoadImage(nsIURI* uri, const nsAString &aCrossOriginAttr,
loadFlags,
NS_LITERAL_STRING("img"),
getter_AddRefs(request),
nsIContentPolicy::TYPE_INTERNAL_IMAGE_PRELOAD);
policyType);
// Pin image-reference to avoid evicting it from the img-cache before
// the "real" load occurs. Unpinned in DispatchContentLoadedEvents and

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

@ -823,11 +823,14 @@ public:
ResolvePreloadImage(nsIURI *aBaseURI,
const nsAString& aSrcAttr,
const nsAString& aSrcsetAttr,
const nsAString& aSizesAttr) override;
const nsAString& aSizesAttr,
bool *aIsImgSet) override;
virtual void MaybePreLoadImage(nsIURI* uri,
const nsAString &aCrossOriginAttr,
ReferrerPolicy aReferrerPolicy) override;
ReferrerPolicy aReferrerPolicy,
bool aIsImgSet) override;
virtual void ForgetImagePreload(nsIURI* aURI) override;
virtual void MaybePreconnect(nsIURI* uri,

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

@ -974,7 +974,7 @@ nsGenericDOMDataNode::GetText()
uint32_t
nsGenericDOMDataNode::TextLength() const
{
return mText.GetLength();
return TextDataLength();
}
nsresult

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

@ -228,6 +228,11 @@ public:
rv = ReplaceData(aOffset, aCount, aData);
}
uint32_t TextDataLength() const
{
return mText.GetLength();
}
//----------------------------------------
#ifdef DEBUG

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

@ -2403,21 +2403,27 @@ public:
* nesting and possible sources, which are used to inform URL selection
* responsive <picture> or <img srcset> images. Unset attributes are expected
* to be marked void.
* If this image is for <picture> or <img srcset>, aIsImgSet will be set to
* true, false otherwise.
*/
virtual already_AddRefed<nsIURI>
ResolvePreloadImage(nsIURI *aBaseURI,
const nsAString& aSrcAttr,
const nsAString& aSrcsetAttr,
const nsAString& aSizesAttr) = 0;
const nsAString& aSizesAttr,
bool *aIsImgSet) = 0;
/**
* Called by nsParser to preload images. Can be removed and code moved
* to nsPreloadURIs::PreloadURIs() in file nsParser.cpp whenever the
* parser-module is linked with gklayout-module. aCrossOriginAttr should
* be a void string if the attr is not present.
* aIsImgSet is the value got from calling ResolvePreloadImage, it is true
* when this image is for loading <picture> or <img srcset> images.
*/
virtual void MaybePreLoadImage(nsIURI* uri,
const nsAString& aCrossOriginAttr,
ReferrerPolicyEnum aReferrerPolicy) = 0;
ReferrerPolicyEnum aReferrerPolicy,
bool aIsImgSet) = 0;
/**
* Called by images to forget an image preload when they start doing

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

@ -3747,8 +3747,7 @@ AssertReflectorHasGivenProto(JSContext* aCx, JSObject* aReflector,
#endif // DEBUG
void
SetDocumentAndPageUseCounter(JSContext* aCx, JSObject* aObject,
UseCounter aUseCounter)
SetDocumentAndPageUseCounter(JSObject* aObject, UseCounter aUseCounter)
{
nsGlobalWindow* win = xpc::WindowGlobalOrNull(js::UncheckedUnwrap(aObject));
if (win && win->GetDocument()) {

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

@ -3376,8 +3376,7 @@ CreateHTMLElement(const GlobalObject& aGlobal, const JS::CallArgs& aCallArgs,
JS::Handle<JSObject*> aGivenProto, ErrorResult& aRv);
void
SetDocumentAndPageUseCounter(JSContext* aCx, JSObject* aObject,
UseCounter aUseCounter);
SetDocumentAndPageUseCounter(JSObject* aObject, UseCounter aUseCounter);
// Warnings
void

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

@ -626,6 +626,16 @@ DOMInterfaces = {
'nativeType': 'mozilla::dom::time::TimeManager',
},
'MozStorageAsyncStatementParams': {
'headerFile': 'mozilla/storage/mozStorageAsyncStatementParams.h',
'nativeType': 'mozilla::storage::AsyncStatementParams',
},
'MozStorageStatementParams': {
'headerFile': 'mozilla/storage/mozStorageStatementParams.h',
'nativeType': 'mozilla::storage::StatementParams',
},
'MozStorageStatementRow': {
'headerFile': 'mozilla/storage/mozStorageStatementRow.h',
'nativeType': 'mozilla::storage::StatementRow',

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

@ -7878,7 +7878,7 @@ class CGPerSignatureCall(CGThing):
if useCounterName:
# Generate a telemetry call for when [UseCounter] is used.
code = "SetDocumentAndPageUseCounter(cx, obj, eUseCounter_%s);\n" % useCounterName
code = "SetDocumentAndPageUseCounter(obj, eUseCounter_%s);\n" % useCounterName
cgThings.append(CGGeneric(code))
self.cgRoot = CGList(cgThings)

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

@ -2795,7 +2795,7 @@ nsTextEditorState::HasNonEmptyValue()
if (mTextEditor && mBoundFrame && mEditorInitialized &&
!mIsCommittingComposition) {
bool empty;
nsresult rv = mTextEditor->GetDocumentIsEmpty(&empty);
nsresult rv = mTextEditor->DocumentIsEmpty(&empty);
if (NS_SUCCEEDED(rv)) {
return !empty;
}

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

@ -15,18 +15,33 @@ function getGlobalState(key)
{
var data;
getObjectState(key, function(x) {
data = x.wrappedJSObject.data;
data = x && x.wrappedJSObject.data;
});
return data;
}
function finishBlockedRequest(request, response, query)
{
response.setStatusLine(request.httpVersion, 200, "OK");
response.setHeader("Cache-Control", "no-cache", false);
response.setHeader("Content-Type", "application/javascript", false);
response.write("window.script_executed_" + query[1] + " = true; ok(true, 'Script " + query[1] + " executed');");
response.finish();
}
function handleRequest(request, response)
{
var query = request.queryString.split('&');
switch (query[0]) {
case "blocked":
setGlobalState(response, query[1]);
response.processAsync();
var alreadyUnblocked = getGlobalState(query[1]);
if (alreadyUnblocked) {
// the unblock request came before the blocked request, just go on and finish synchronously
finishBlockedRequest(request, response, query);
} else {
setGlobalState(response, query[1]);
response.processAsync();
}
break;
case "unblock":
@ -36,11 +51,12 @@ function handleRequest(request, response)
response.write("\x89PNG"); // just a broken image is enough for our purpose
var blockedResponse = getGlobalState(query[1]);
blockedResponse.setStatusLine(request.httpVersion, 200, "OK");
blockedResponse.setHeader("Cache-Control", "no-cache", false);
blockedResponse.setHeader("Content-Type", "application/javascript", false);
blockedResponse.write("window.script_executed_" + query[1] + " = true; ok(true, 'Script " + query[1] + " executed');");
blockedResponse.finish();
if (!blockedResponse) {
// the unblock request came before the blocked request, remember to not block it
setGlobalState(true, query[1]);
} else {
finishBlockedRequest(request, blockedResponse, query);
}
break;
default:

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

@ -69,6 +69,38 @@ interface ChromeUtils : ThreadSafeChromeUtils {
[NewObject, Throws]
static Promise<PrecompiledScript>
compileScript(DOMString url, optional CompileScriptOptionsDictionary options);
/**
* Waive Xray on a given value. Identity op for primitives.
*/
[Throws]
static any waiveXrays(any val);
/**
* Strip off Xray waivers on a given value. Identity op for primitives.
*/
[Throws]
static any unwaiveXrays(any val);
/**
* Gets the name of the JSClass of the object.
*
* if |unwrap| is true, all wrappers are unwrapped first. Unless you're
* specifically trying to detect whether the object is a proxy, this is
* probably what you want.
*/
static DOMString getClassName(object obj, optional boolean unwrap = true);
/**
* Clones the properties of the given object into a new object in the given
* target compartment (or the caller compartment if no target is provided).
* Property values themeselves are not cloned.
*
* Ignores non-enumerable properties, properties on prototypes, and properties
* with getters or setters.
*/
[Throws]
static object shallowClone(object obj, optional object? target = null);
};
/**

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

@ -0,0 +1,22 @@
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
[ChromeOnly]
interface MozStorageAsyncStatementParams
{
readonly attribute unsigned long length;
[Throws]
getter any(unsigned long index);
[Throws]
getter any(DOMString name);
[Throws]
setter creator void(unsigned long index, any arg);
[Throws]
setter creator void(DOMString name, any arg);
};

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

@ -0,0 +1,22 @@
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
[ChromeOnly]
interface MozStorageStatementParams
{
readonly attribute unsigned long length;
[Throws]
getter any(unsigned long index);
[Throws]
getter any(DOMString name);
[Throws]
setter creator void(unsigned long index, any arg);
[Throws]
setter creator void(DOMString name, any arg);
};

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

@ -699,6 +699,8 @@ WEBIDL_FILES = [
'MouseEvent.webidl',
'MouseScrollEvent.webidl',
'MozSelfSupport.webidl',
'MozStorageAsyncStatementParams.webidl',
'MozStorageStatementParams.webidl',
'MozStorageStatementRow.webidl',
'MozTimeManager.webidl',
'MozWakeLock.webidl',

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

@ -3753,12 +3753,6 @@ EditorBase::IsTextNode(nsIDOMNode* aNode)
return (nodeType == nsIDOMNode::TEXT_NODE);
}
bool
EditorBase::IsTextNode(nsINode* aNode)
{
return aNode->NodeType() == nsIDOMNode::TEXT_NODE;
}
nsCOMPtr<nsIDOMNode>
EditorBase::GetChildAt(nsIDOMNode* aParent, int32_t aOffset)
{
@ -5023,18 +5017,6 @@ EditorBase::FinalizeSelection()
return NS_OK;
}
Element*
EditorBase::GetRoot()
{
if (!mRootElement) {
// Let GetRootElement() do the work
nsCOMPtr<nsIDOMElement> root;
GetRootElement(getter_AddRefs(root));
}
return mRootElement;
}
Element*
EditorBase::GetEditorRoot()
{

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

@ -877,7 +877,10 @@ public:
virtual bool AreNodesSameType(nsIContent* aNode1, nsIContent* aNode2);
static bool IsTextNode(nsIDOMNode* aNode);
static bool IsTextNode(nsINode* aNode);
static bool IsTextNode(nsINode* aNode)
{
return aNode->NodeType() == nsIDOMNode::TEXT_NODE;
}
static nsCOMPtr<nsIDOMNode> GetChildAt(nsIDOMNode* aParent, int32_t aOffset);
static nsIContent* GetNodeAtRangeOffsetPoint(nsINode* aParentOrNode,
@ -969,7 +972,16 @@ public:
/**
* Fast non-refcounting editor root element accessor
*/
Element* GetRoot();
Element* GetRoot()
{
if (!mRootElement) {
// Let GetRootElement() do the work
nsCOMPtr<nsIDOMElement> root;
GetRootElement(getter_AddRefs(root));
}
return mRootElement;
}
/**
* Likewise, but gets the editor's root instead, which is different for HTML

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

@ -358,28 +358,12 @@ TextEditRules::DidDoAction(Selection* aSelection,
NS_IMETHODIMP_(bool)
TextEditRules::DocumentIsEmpty()
{
if (mBogusNode) {
return true;
bool retVal = false;
if (!mTextEditor || NS_FAILED(mTextEditor->DocumentIsEmpty(&retVal))) {
retVal = true;
}
// Even if there is no bogus node, we should detect as empty document
// if all children are text node and these are no content.
if (NS_WARN_IF(!mTextEditor)) {
return true;
}
Element* rootElement = mTextEditor->GetRoot();
if (!rootElement) {
return true;
}
for (nsIContent* child = rootElement->GetFirstChild();
child; child = child->GetNextSibling()) {
if (!EditorBase::IsTextNode(child) ||
child->Length()) {
return false;
}
}
return true;
return retVal;
}
void

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

@ -115,6 +115,11 @@ public:
*/
static void FillBufWithPWChars(nsAString* aOutString, int32_t aLength);
bool HasBogusNode()
{
return !!mBogusNode;
}
protected:
void InitFields();

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

@ -52,6 +52,7 @@
#include "nsString.h"
#include "nsStringFwd.h"
#include "nsSubstringTuple.h"
#include "nsTextNode.h"
#include "nsUnicharUtils.h"
#include "nsXPCOM.h"
@ -899,17 +900,41 @@ TextEditor::GetInputEventTargetContent()
return target.forget();
}
nsresult
TextEditor::DocumentIsEmpty(bool* aIsEmpty)
{
NS_ENSURE_TRUE(mRules, NS_ERROR_NOT_INITIALIZED);
if (static_cast<TextEditRules*>(mRules.get())->HasBogusNode()) {
*aIsEmpty = true;
return NS_OK;
}
// Even if there is no bogus node, we should be detected as empty document
// if all the children are text nodes and these have no content.
Element* rootElement = GetRoot();
if (!rootElement) {
*aIsEmpty = true;
return NS_OK;
}
for (nsIContent* child = rootElement->GetFirstChild();
child; child = child->GetNextSibling()) {
if (!EditorBase::IsTextNode(child) ||
static_cast<nsTextNode*>(child)->TextDataLength()) {
*aIsEmpty = false;
return NS_OK;
}
}
*aIsEmpty = true;
return NS_OK;
}
NS_IMETHODIMP
TextEditor::GetDocumentIsEmpty(bool* aDocumentIsEmpty)
{
NS_ENSURE_TRUE(aDocumentIsEmpty, NS_ERROR_NULL_POINTER);
NS_ENSURE_TRUE(mRules, NS_ERROR_NOT_INITIALIZED);
// Protect the edit rules object from dying
nsCOMPtr<nsIEditRules> rules(mRules);
*aDocumentIsEmpty = rules->DocumentIsEmpty();
return NS_OK;
return DocumentIsEmpty(aDocumentIsEmpty);
}
NS_IMETHODIMP

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

@ -78,6 +78,7 @@ public:
nsISelectionController* aSelCon, uint32_t aFlags,
const nsAString& aValue) override;
nsresult DocumentIsEmpty(bool* aIsEmpty);
NS_IMETHOD GetDocumentIsEmpty(bool* aDocumentIsEmpty) override;
NS_IMETHOD DeleteSelection(EDirection aAction,

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

@ -310,9 +310,11 @@ RotatedContentBuffer::BorrowDrawTargetForQuadrantUpdate(const IntRect& aBounds,
if (aSetTransform) {
mLoanedDrawTarget->SetTransform(transform);
mSetTransform = true;
} else {
MOZ_ASSERT(aOutMatrix);
*aOutMatrix = transform;
mSetTransform = false;
}
return mLoanedDrawTarget;
@ -324,7 +326,9 @@ BorrowDrawTarget::ReturnDrawTarget(gfx::DrawTarget*& aReturned)
MOZ_ASSERT(mLoanedDrawTarget);
MOZ_ASSERT(aReturned == mLoanedDrawTarget);
if (mLoanedDrawTarget) {
mLoanedDrawTarget->SetTransform(mLoanedTransform);
if (mSetTransform) {
mLoanedDrawTarget->SetTransform(mLoanedTransform);
}
mLoanedDrawTarget = nullptr;
}
aReturned = nullptr;
@ -743,7 +747,8 @@ RotatedContentBuffer::BeginPaint(PaintedLayer* aLayer,
RefPtr<CapturedPaintState>
RotatedContentBuffer::BorrowDrawTargetForRecording(PaintState& aPaintState,
DrawIterator* aIter)
DrawIterator* aIter,
bool aSetTransform)
{
if (aPaintState.mMode == SurfaceMode::SURFACE_NONE) {
return nullptr;
@ -752,7 +757,7 @@ RotatedContentBuffer::BorrowDrawTargetForRecording(PaintState& aPaintState,
Matrix transform;
DrawTarget* result = BorrowDrawTargetForQuadrantUpdate(aPaintState.mRegionToDraw.GetBounds(),
BUFFER_BOTH, aIter,
false,
aSetTransform,
&transform);
if (!result) {
return nullptr;
@ -831,21 +836,17 @@ RotatedContentBuffer::BorrowDrawTargetForPainting(PaintState& aPaintState,
DrawIterator* aIter /* = nullptr */)
{
RefPtr<CapturedPaintState> capturedState =
BorrowDrawTargetForRecording(aPaintState, aIter);
BorrowDrawTargetForRecording(aPaintState, aIter, true);
if (!capturedState) {
return nullptr;
}
// BorrowDrawTargetForRecording doesn't apply the transform, so we have to.
RefPtr<DrawTarget> target = capturedState->mTarget;
target->SetTransform(capturedState->mTargetTransform);
if (!RotatedContentBuffer::PrepareDrawTargetForPainting(capturedState)) {
return nullptr;
}
return target;
return capturedState->mTarget;
}
already_AddRefed<SourceSurface>

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

@ -162,6 +162,11 @@ protected:
// correctly restore state when it is returned.
RefPtr<gfx::DrawTarget> mLoanedDrawTarget;
gfx::Matrix mLoanedTransform;
// This flag denotes whether or not a transform was already applied
// to mLoanedDrawTarget and thus needs to be reset to mLoanedTransform
// upon returning the drawtarget.
bool mSetTransform;
};
/**
@ -298,12 +303,13 @@ public:
DrawIterator* aIter = nullptr);
/**
* Borrow a draw target for recording. The aOutTransform is not applied
* to the returned DrawTarget, BUT it is required to be painting in the right
* location whenever drawing does happen.
* Borrow a draw target for recording. The required transform for correct painting
* is not applied to the returned DrawTarget by default, BUT it is
* required to be whenever drawing does happen.
*/
RefPtr<CapturedPaintState> BorrowDrawTargetForRecording(PaintState& aPaintState,
DrawIterator* aIter);
DrawIterator* aIter,
bool aSetTransform = false);
nsIntRegion ExpandDrawRegion(PaintState& aPaintState,
DrawIterator* aIter,
@ -385,6 +391,7 @@ protected:
* ReturnDrawTarget will by default restore the transform on the draw target.
* But it is the callers responsibility to restore the clip.
* The caller should flush the draw target, if necessary.
* If aSetTransform is false, the required transform will be set in aOutTransform.
*/
gfx::DrawTarget*
BorrowDrawTargetForQuadrantUpdate(const gfx::IntRect& aBounds,

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

@ -4,6 +4,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nsCollation.h"
#include "mozilla/intl/LocaleService.h"
#include "nsIServiceManager.h"
#include "nsString.h"
@ -117,7 +118,20 @@ nsCollation::Initialize(const nsACString& locale)
{
NS_ENSURE_TRUE((!mInit), NS_ERROR_ALREADY_INITIALIZED);
mLocale = locale;
// Check whether locale parameter is valid. If no, use application locale
UErrorCode status = U_ZERO_ERROR;
UCollator* collator = ucol_open(PromiseFlatCString(locale).get(), &status);
if (U_SUCCESS(status)) {
mLocale = locale;
} else {
status = U_ZERO_ERROR;
mozilla::LocaleService::GetInstance()->GetAppLocaleAsLangTag(mLocale);
collator = ucol_open(mLocale.get(), &status);
if (NS_WARN_IF(U_FAILURE(status))) {
return NS_ERROR_UNEXPECTED;
}
}
ucol_close(collator);
mInit = true;
return NS_OK;

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

@ -0,0 +1,51 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "gtest/gtest.h"
#include "mozilla/Services.h"
#include "nsCollationCID.h"
#include "nsComponentManagerUtils.h"
#include "nsCOMPtr.h"
#include "nsICollation.h"
#include "nsString.h"
TEST(Collation, AllocateRowSortKey) {
nsCOMPtr<nsICollationFactory> colFactory =
do_CreateInstance(NS_COLLATIONFACTORY_CONTRACTID);
ASSERT_TRUE(colFactory);
// Don't throw error even if locale name is invalid
nsCOMPtr<nsICollation> collator;
nsresult rv =
colFactory->CreateCollationForLocale(NS_LITERAL_CSTRING("$languageName"),
getter_AddRefs(collator));
ASSERT_TRUE(NS_SUCCEEDED(rv));
uint8_t* sortKey1 = nullptr;
uint32_t sortKeyLen1 = 0;
// Don't throw error even if locale name is invalid
rv = collator->AllocateRawSortKey(nsICollation::kCollationStrengthDefault,
NS_LITERAL_STRING("ABC"),
&sortKey1, &sortKeyLen1);
ASSERT_TRUE(NS_SUCCEEDED(rv));
uint8_t* sortKey2 = nullptr;
uint32_t sortKeyLen2 = 0;
// Don't throw error even if locale name is invalid
rv = collator->AllocateRawSortKey(nsICollation::kCollationStrengthDefault,
NS_LITERAL_STRING("DEF"),
&sortKey2, &sortKeyLen2);
ASSERT_TRUE(NS_SUCCEEDED(rv));
int32_t result;
rv = collator->CompareRawSortKey(sortKey1, sortKeyLen1,
sortKey2, sortKeyLen2, &result);
ASSERT_TRUE(NS_SUCCEEDED(rv));
ASSERT_TRUE(result < 0);
free(sortKey1);
free(sortKey2);
}

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

@ -5,6 +5,7 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
UNIFIED_SOURCES += [
'TestCollation.cpp',
'TestLocaleService.cpp',
'TestLocaleServiceNegotiate.cpp',
]

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

@ -8,10 +8,12 @@
#include "mozilla/Assertions.h"
#include "mozilla/mscom/Utils.h"
#include "mozilla/RefPtr.h"
#include "mozilla/UniquePtr.h"
#include <guiddef.h>
#include <objidl.h>
#include <winnt.h>
namespace {
@ -56,9 +58,14 @@ struct DUALSTRINGARRAY
struct OBJREF_STANDARD
{
static size_t SizeOfFixedLenHeader()
{
return sizeof(mStd);
}
size_t SizeOf() const
{
return sizeof(mStd) + mResAddr.SizeOf();
return SizeOfFixedLenHeader() + mResAddr.SizeOf();
}
STDOBJREF mStd;
@ -67,9 +74,14 @@ struct OBJREF_STANDARD
struct OBJREF_HANDLER
{
static size_t SizeOfFixedLenHeader()
{
return sizeof(mStd) + sizeof(mClsid);
}
size_t SizeOf() const
{
return sizeof(mStd) + sizeof(mClsid) + mResAddr.SizeOf();
return SizeOfFixedLenHeader() + mResAddr.SizeOf();
}
STDOBJREF mStd;
@ -77,6 +89,19 @@ struct OBJREF_HANDLER
DUALSTRINGARRAY mResAddr;
};
struct OBJREF_CUSTOM
{
static size_t SizeOfFixedLenHeader()
{
return sizeof(mClsid) + sizeof(mCbExtension) + sizeof(mReserved);
}
CLSID mClsid;
uint32_t mCbExtension;
uint32_t mReserved;
uint8_t mPayload[1];
};
enum OBJREF_FLAGS
{
OBJREF_TYPE_STANDARD = 0x00000001UL,
@ -112,6 +137,7 @@ struct OBJREF
union {
OBJREF_STANDARD mObjRefStd;
OBJREF_HANDLER mObjRefHandler;
OBJREF_CUSTOM mObjRefCustom;
// There are others but we're not supporting them here
};
};
@ -183,7 +209,7 @@ StripHandlerFromOBJREF(NotNull<IStream*> aStream, const uint64_t aStartPos,
seekTo.QuadPart = sizeof(STDOBJREF) + sizeof(CLSID);
hr = aStream->Seek(seekTo, STREAM_SEEK_CUR, nullptr);
if (FAILED(hr)) {
return hr;
return false;
}
uint16_t numEntries;
@ -259,5 +285,108 @@ StripHandlerFromOBJREF(NotNull<IStream*> aStream, const uint64_t aStartPos,
return SUCCEEDED(aStream->Seek(seekTo, STREAM_SEEK_CUR, nullptr));
}
uint32_t
GetOBJREFSize(NotNull<IStream*> aStream)
{
// Make a clone so that we don't manipulate aStream's seek pointer
RefPtr<IStream> cloned;
HRESULT hr = aStream->Clone(getter_AddRefs(cloned));
if (FAILED(hr)) {
return 0;
}
uint32_t accumulatedSize = 0;
ULONG bytesRead;
uint32_t signature;
hr = cloned->Read(&signature, sizeof(signature), &bytesRead);
if (FAILED(hr) || bytesRead != sizeof(signature) ||
signature != OBJREF_SIGNATURE) {
return 0;
}
accumulatedSize += bytesRead;
uint32_t type;
hr = cloned->Read(&type, sizeof(type), &bytesRead);
if (FAILED(hr) || bytesRead != sizeof(type)) {
return 0;
}
accumulatedSize += bytesRead;
IID iid;
hr = cloned->Read(&iid, sizeof(iid), &bytesRead);
if (FAILED(hr) || bytesRead != sizeof(iid) || !IsValidGUID(iid)) {
return 0;
}
accumulatedSize += bytesRead;
LARGE_INTEGER seekTo;
if (type == OBJREF_TYPE_CUSTOM) {
CLSID clsid;
hr = cloned->Read(&clsid, sizeof(CLSID), &bytesRead);
if (FAILED(hr) || bytesRead != sizeof(CLSID)) {
return 0;
}
MOZ_ASSERT(clsid == CLSID_StdMarshal);
if (clsid != CLSID_StdMarshal) {
// We can only calulate the size if the payload is a standard OBJREF as
// identified by clsid == CLSID_StdMarshal.
return 0;
}
accumulatedSize += bytesRead;
seekTo.QuadPart = sizeof(OBJREF_CUSTOM::mCbExtension) +
sizeof(OBJREF_CUSTOM::mReserved);
hr = cloned->Seek(seekTo, STREAM_SEEK_CUR, nullptr);
if (FAILED(hr)) {
return 0;
}
accumulatedSize += seekTo.LowPart;
uint32_t payloadLen = GetOBJREFSize(WrapNotNull(cloned.get()));
if (!payloadLen) {
return 0;
}
accumulatedSize += payloadLen;
return accumulatedSize;
}
switch (type) {
case OBJREF_TYPE_STANDARD:
seekTo.QuadPart = OBJREF_STANDARD::SizeOfFixedLenHeader();
break;
case OBJREF_TYPE_HANDLER:
seekTo.QuadPart = OBJREF_HANDLER::SizeOfFixedLenHeader();
break;
default:
return 0;
}
hr = cloned->Seek(seekTo, STREAM_SEEK_CUR, nullptr);
if (FAILED(hr)) {
return 0;
}
accumulatedSize += seekTo.LowPart;
uint16_t numEntries;
hr = cloned->Read(&numEntries, sizeof(numEntries), &bytesRead);
if (FAILED(hr) || bytesRead != sizeof(numEntries)) {
return 0;
}
accumulatedSize += DUALSTRINGARRAY::SizeFromNumEntries(numEntries);
return accumulatedSize;
}
} // namespace mscom
} // namespace mozilla

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

@ -29,6 +29,16 @@ StripHandlerFromOBJREF(NotNull<IStream*> aStream,
const uint64_t aStart,
const uint64_t aEnd);
/**
* Given a buffer containing a serialized proxy to an interface, this function
* returns the length of the serialized data.
* @param aStream IStream containing a serialized proxy. The stream pointer
* must be positioned at the beginning of the OBJREF.
* @return The size of the serialized proxy, or 0 on error.
*/
uint32_t
GetOBJREFSize(NotNull<IStream*> aStream);
} // namespace mscom
} // namespace mozilla

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

@ -8,7 +8,6 @@
#include "mozilla/mscom/EnsureMTA.h"
#include "mozilla/mscom/ProxyStream.h"
#include "mozilla/mscom/Utils.h"
#include "mozilla/WindowsVersion.h"
#if defined(MOZ_CRASHREPORTER)
#include "InterfaceRegistrationAnnotator.h"
@ -34,8 +33,7 @@ ProxyStream::ProxyStream()
// reconstructing the stream from a buffer anyway.
ProxyStream::ProxyStream(REFIID aIID, const BYTE* aInitBuf,
const int aInitBufSize)
: mStream(InitStream(aInitBuf, static_cast<const UINT>(aInitBufSize)))
, mGlobalLockedBuf(nullptr)
: mGlobalLockedBuf(nullptr)
, mHGlobal(nullptr)
, mBufSize(aInitBufSize)
{
@ -43,6 +41,16 @@ ProxyStream::ProxyStream(REFIID aIID, const BYTE* aInitBuf,
NS_NAMED_LITERAL_CSTRING(kCrashReportKey, "ProxyStreamUnmarshalStatus");
#endif
HRESULT createStreamResult = CreateStream(aInitBuf, aInitBufSize,
getter_AddRefs(mStream));
if (FAILED(createStreamResult)) {
#if defined(MOZ_CRASHREPORTER)
nsPrintfCString hrAsStr("0x%08X", createStreamResult);
CrashReporter::AnnotateCrashReport(kCrashReportKey, hrAsStr);
#endif // defined(MOZ_CRASHREPORTER)
return;
}
if (!aInitBufSize) {
#if defined(MOZ_CRASHREPORTER)
CrashReporter::AnnotateCrashReport(kCrashReportKey,
@ -98,67 +106,6 @@ ProxyStream::ProxyStream(REFIID aIID, const BYTE* aInitBuf,
#endif // defined(MOZ_CRASHREPORTER)
}
/* static */
already_AddRefed<IStream>
ProxyStream::InitStream(const BYTE* aInitBuf, const UINT aInitBufSize)
{
if (!aInitBuf || !aInitBufSize) {
return nullptr;
}
HRESULT hr;
RefPtr<IStream> stream;
if (IsWin8OrLater()) {
// This function is not safe for us to use until Windows 8
stream = already_AddRefed<IStream>(::SHCreateMemStream(aInitBuf, aInitBufSize));
if (!stream) {
return nullptr;
}
} else {
HGLOBAL hglobal = ::GlobalAlloc(GMEM_MOVEABLE, aInitBufSize);
if (!hglobal) {
return nullptr;
}
// stream takes ownership of hglobal if this call is successful
hr = ::CreateStreamOnHGlobal(hglobal, TRUE, getter_AddRefs(stream));
if (FAILED(hr)) {
::GlobalFree(hglobal);
return nullptr;
}
// The default stream size is derived from ::GlobalSize(hglobal), which due
// to rounding may be larger than aInitBufSize. We forcibly set the correct
// stream size here.
ULARGE_INTEGER streamSize;
streamSize.QuadPart = aInitBufSize;
hr = stream->SetSize(streamSize);
if (FAILED(hr)) {
return nullptr;
}
void* streamBuf = ::GlobalLock(hglobal);
if (!streamBuf) {
return nullptr;
}
memcpy(streamBuf, aInitBuf, aInitBufSize);
::GlobalUnlock(hglobal);
}
// Ensure that the stream is rewound
LARGE_INTEGER streamOffset;
streamOffset.QuadPart = 0;
hr = stream->Seek(streamOffset, STREAM_SEEK_SET, nullptr);
if (FAILED(hr)) {
return nullptr;
}
return stream.forget();
}
ProxyStream::ProxyStream(ProxyStream&& aOther)
: mGlobalLockedBuf(nullptr)
, mHGlobal(nullptr)

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

@ -46,10 +46,6 @@ public:
return this == &aOther;
}
private:
static already_AddRefed<IStream> InitStream(const BYTE* aInitBuf,
const UINT aInitBufSize);
private:
RefPtr<IStream> mStream;
BYTE* mGlobalLockedBuf;

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

@ -11,11 +11,14 @@
#endif
#endif
#include "mozilla/mscom/Objref.h"
#include "mozilla/mscom/Utils.h"
#include "mozilla/RefPtr.h"
#include "mozilla/WindowsVersion.h"
#include <objbase.h>
#include <objidl.h>
#include <shlwapi.h>
#include <winnt.h>
#if defined(_MSC_VER)
@ -98,6 +101,126 @@ GetContainingModuleHandle()
return reinterpret_cast<uintptr_t>(thisModule);
}
uint32_t
CreateStream(const uint8_t* aInitBuf, const uint32_t aInitBufSize,
IStream** aOutStream)
{
if (!aInitBufSize || !aOutStream) {
return E_INVALIDARG;
}
*aOutStream = nullptr;
HRESULT hr;
RefPtr<IStream> stream;
if (IsWin8OrLater()) {
// SHCreateMemStream is not safe for us to use until Windows 8. On older
// versions of Windows it is not thread-safe and it creates IStreams that do
// not support the full IStream API.
// If aInitBuf is null then initSize must be 0.
UINT initSize = aInitBuf ? aInitBufSize : 0;
stream = already_AddRefed<IStream>(::SHCreateMemStream(aInitBuf, initSize));
if (!stream) {
return E_OUTOFMEMORY;
}
if (!aInitBuf) {
// Now we'll set the required size
ULARGE_INTEGER newSize;
newSize.QuadPart = aInitBufSize;
hr = stream->SetSize(newSize);
if (FAILED(hr)) {
return hr;
}
}
} else {
HGLOBAL hglobal = ::GlobalAlloc(GMEM_MOVEABLE, aInitBufSize);
if (!hglobal) {
return HRESULT_FROM_WIN32(::GetLastError());
}
// stream takes ownership of hglobal if this call is successful
hr = ::CreateStreamOnHGlobal(hglobal, TRUE, getter_AddRefs(stream));
if (FAILED(hr)) {
::GlobalFree(hglobal);
return hr;
}
// The default stream size is derived from ::GlobalSize(hglobal), which due
// to rounding may be larger than aInitBufSize. We forcibly set the correct
// stream size here.
ULARGE_INTEGER streamSize;
streamSize.QuadPart = aInitBufSize;
hr = stream->SetSize(streamSize);
if (FAILED(hr)) {
return hr;
}
if (aInitBuf) {
ULONG bytesWritten;
hr = stream->Write(aInitBuf, aInitBufSize, &bytesWritten);
if (FAILED(hr)) {
return hr;
}
if (bytesWritten != aInitBufSize) {
return E_UNEXPECTED;
}
}
}
// Ensure that the stream is rewound
LARGE_INTEGER streamOffset;
streamOffset.QuadPart = 0LL;
hr = stream->Seek(streamOffset, STREAM_SEEK_SET, nullptr);
if (FAILED(hr)) {
return hr;
}
stream.forget(aOutStream);
return S_OK;
}
uint32_t
CopySerializedProxy(IStream* aInStream, IStream** aOutStream)
{
if (!aInStream || !aOutStream) {
return E_INVALIDARG;
}
*aOutStream = nullptr;
uint32_t desiredStreamSize = GetOBJREFSize(WrapNotNull(aInStream));
if (!desiredStreamSize) {
return E_INVALIDARG;
}
RefPtr<IStream> stream;
HRESULT hr = CreateStream(nullptr, desiredStreamSize, getter_AddRefs(stream));
if (FAILED(hr)) {
return hr;
}
ULARGE_INTEGER numBytesToCopy;
numBytesToCopy.QuadPart = desiredStreamSize;
hr = aInStream->CopyTo(stream, numBytesToCopy, nullptr, nullptr);
if (FAILED(hr)) {
return hr;
}
LARGE_INTEGER seekTo;
seekTo.QuadPart = 0LL;
hr = stream->Seek(seekTo, STREAM_SEEK_SET, nullptr);
if (FAILED(hr)) {
return hr;
}
stream.forget(aOutStream);
return S_OK;
}
#if defined(MOZILLA_INTERNAL_API)
void

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

@ -13,6 +13,7 @@
#include <guiddef.h>
struct IStream;
struct IUnknown;
namespace mozilla {
@ -23,6 +24,28 @@ bool IsProxy(IUnknown* aUnknown);
bool IsValidGUID(REFGUID aCheckGuid);
uintptr_t GetContainingModuleHandle();
/**
* Given a buffer, create a new IStream object.
* @param aBuf Buffer containing data to initialize the stream. This parameter
* may be nullptr, causing the stream to be created with aBufLen
* bytes of uninitialized data.
* @param aBufLen Length of data in aBuf, or desired stream size if aBuf is
* nullptr.
* @param aOutStream Outparam to receive the newly created stream.
* @return HRESULT error code.
*/
uint32_t CreateStream(const uint8_t* aBuf, const uint32_t aBufLen,
IStream** aOutStream);
/**
* Creates a deep copy of a proxy contained in a stream.
* @param aInStream Stream containing the proxy to copy. Its seek pointer must
* be positioned to point at the beginning of the proxy data.
* @param aOutStream Outparam to receive the newly created stream.
* @return HRESULT error code.
*/
uint32_t CopySerializedProxy(IStream* aInStream, IStream** aOutStream);
#if defined(MOZILLA_INTERNAL_API)
void GUIDToString(REFGUID aGuid, nsAString& aOutString);
#endif // defined(MOZILLA_INTERNAL_API)

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

@ -524,12 +524,61 @@ ModuleNamespaceObject::ProxyHandler::getOwnPropertyDescriptor(JSContext* cx, Han
return true;
}
static bool
ValidatePropertyDescriptor(JSContext* cx, Handle<PropertyDescriptor> desc,
bool expectedWritable, bool expectedEnumerable,
bool expectedConfigurable, HandleValue expectedValue,
ObjectOpResult& result)
{
if (desc.isAccessorDescriptor())
return result.fail(JSMSG_CANT_REDEFINE_PROP);
if (desc.hasWritable() && desc.writable() != expectedWritable)
return result.fail(JSMSG_CANT_REDEFINE_PROP);
if (desc.hasEnumerable() && desc.enumerable() != expectedEnumerable)
return result.fail(JSMSG_CANT_REDEFINE_PROP);
if (desc.hasConfigurable() && desc.configurable() != expectedConfigurable)
return result.fail(JSMSG_CANT_REDEFINE_PROP);
if (desc.hasValue()) {
bool same;
if (!SameValue(cx, desc.value(), expectedValue, &same))
return false;
if (!same)
return result.fail(JSMSG_CANT_REDEFINE_PROP);
}
return result.succeed();
}
bool
ModuleNamespaceObject::ProxyHandler::defineProperty(JSContext* cx, HandleObject proxy, HandleId id,
Handle<PropertyDescriptor> desc,
ObjectOpResult& result) const
{
return result.failReadOnly();
if (JSID_IS_SYMBOL(id)) {
if (JSID_TO_SYMBOL(id) == cx->wellKnownSymbols().toStringTag) {
RootedValue value(cx, StringValue(cx->names().Module));
return ValidatePropertyDescriptor(cx, desc, false, false, false, value, result);
}
return result.fail(JSMSG_CANT_DEFINE_PROP_OBJECT_NOT_EXTENSIBLE);
}
const IndirectBindingMap& bindings = proxy->as<ModuleNamespaceObject>().bindings();
ModuleEnvironmentObject* env;
Shape* shape;
if (!bindings.lookup(id, &env, &shape))
return result.fail(JSMSG_CANT_DEFINE_PROP_OBJECT_NOT_EXTENSIBLE);
RootedValue value(cx, env->getSlot(shape->slot()));
if (value.isMagic(JS_UNINITIALIZED_LEXICAL)) {
ReportRuntimeLexicalError(cx, JSMSG_UNINITIALIZED_LEXICAL, id);
return false;
}
return ValidatePropertyDescriptor(cx, desc, true, true, false, value, result);
}
bool

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

@ -1323,7 +1323,6 @@ PromiseConstructor(JSContext* cx, unsigned argc, Value* vp)
// Steps 3-10.
RootedObject newTarget(cx, &args.newTarget().toObject());
bool needsWrapping = false;
// If the constructor is called via an Xray wrapper, then the newTarget
// hasn't been unwrapped. We want that because, while the actual instance
@ -1352,6 +1351,9 @@ PromiseConstructor(JSContext* cx, unsigned argc, Value* vp)
// just end up with a rejected Promise. Really, we want to chain the two
// Promises, with the unprivileged one resolved with the resolution of the
// privileged one.
bool needsWrapping = false;
RootedObject proto(cx);
if (IsWrapper(newTarget)) {
JSObject* unwrappedNewTarget = CheckedUnwrap(newTarget);
MOZ_ASSERT(unwrappedNewTarget);
@ -1367,15 +1369,15 @@ PromiseConstructor(JSContext* cx, unsigned argc, Value* vp)
// Promise subclasses don't get the special Xray treatment, so
// we only need to do the complex wrapping and unwrapping scheme
// described above for instances of Promise itself.
if (newTarget == promiseCtor)
if (newTarget == promiseCtor) {
needsWrapping = true;
if (!GetBuiltinPrototype(cx, JSProto_Promise, &proto))
return false;
}
}
}
RootedObject proto(cx);
if (needsWrapping) {
if (!GetPrototypeFromConstructor(cx, newTarget, &proto))
return false;
if (!cx->compartment()->wrap(cx, &proto))
return false;
} else {

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

@ -2314,8 +2314,7 @@ Parser<FullParseHandler, char16_t>::moduleBody(ModuleSharedContext* modulesc)
if (!AtomToPrintableString(context, name, &str))
return null();
JS_ReportErrorNumberLatin1(context, GetErrorMessage, nullptr,
JSMSG_MISSING_EXPORT, str.ptr());
errorAt(TokenStream::NoOffset, JSMSG_MISSING_EXPORT, str.ptr());
return null();
}

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

@ -0,0 +1,8 @@
if (helperThreadCount() == 0)
quit();
load(libdir + "asserts.js")
// Don't assert.
offThreadCompileModule("export { x };");
assertThrowsInstanceOf(() => finishOffThreadModule(), SyntaxError);

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

@ -1487,7 +1487,7 @@ void
MacroAssembler::Push(Register reg)
{
ma_push(reg);
adjustFrame(sizeof(intptr_t));
adjustFrame(int32_t(sizeof(intptr_t)));
}
void
@ -1495,7 +1495,7 @@ MacroAssembler::Push(const Imm32 imm)
{
ma_li(ScratchRegister, imm);
ma_push(ScratchRegister);
adjustFrame(sizeof(intptr_t));
adjustFrame(int32_t(sizeof(intptr_t)));
}
void
@ -1503,7 +1503,7 @@ MacroAssembler::Push(const ImmWord imm)
{
ma_li(ScratchRegister, imm);
ma_push(ScratchRegister);
adjustFrame(sizeof(intptr_t));
adjustFrame(int32_t(sizeof(intptr_t)));
}
void
@ -1517,28 +1517,28 @@ MacroAssembler::Push(const ImmGCPtr ptr)
{
ma_li(ScratchRegister, ptr);
ma_push(ScratchRegister);
adjustFrame(sizeof(intptr_t));
adjustFrame(int32_t(sizeof(intptr_t)));
}
void
MacroAssembler::Push(FloatRegister f)
{
ma_push(f);
adjustFrame(sizeof(double));
adjustFrame(int32_t(sizeof(double)));
}
void
MacroAssembler::Pop(Register reg)
{
ma_pop(reg);
adjustFrame(-sizeof(intptr_t));
adjustFrame(-int32_t(sizeof(intptr_t)));
}
void
MacroAssembler::Pop(FloatRegister f)
{
ma_pop(f);
adjustFrame(-sizeof(double));
adjustFrame(-int32_t(sizeof(double)));
}
void

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

@ -35,6 +35,7 @@
#include <float.h>
#include "jit/AtomicOperations.h"
#include "jit/mips32/Assembler-mips32.h"
#include "vm/Runtime.h"
#include "wasm/WasmInstance.h"
@ -380,6 +381,7 @@ SimInstruction::instructionType() const
case ff_movz:
case ff_movn:
case ff_movci:
case ff_sync:
return kRegisterType;
default:
return kUnsupported;
@ -448,6 +450,8 @@ SimInstruction::instructionType() const
case op_ldc1:
case op_swc1:
case op_sdc1:
case op_ll:
case op_sc:
return kImmediateType;
// 26 bits immediate type instructions. e.g.: j imm26.
case op_j:
@ -1143,10 +1147,10 @@ GetCachePageLocked(SimulatorProcess::ICacheMap& i_cache, void* page)
SimulatorProcess::ICacheMap::AddPtr p = i_cache.lookupForAdd(page);
if (p)
return p->value();
AutoEnterOOMUnsafeRegion oomUnsafe;
CachePage* new_page = js_new<CachePage>();
if (!i_cache.add(p, page, new_page))
return nullptr;
if (!new_page || !i_cache.add(p, page, new_page))
oomUnsafe.crash("Simulator CachePage");
return new_page;
}
@ -1275,6 +1279,9 @@ Simulator::Simulator()
FPUregisters_[i] = 0;
}
FCSR_ = 0;
LLBit_ = false;
LLAddr_ = 0;
lastLLValue_ = 0;
// The ra and pc are initialized to a known bad value that will cause an
// access violation if the simulator ever tries to execute it.
@ -1350,11 +1357,10 @@ class Redirection
}
}
AutoEnterOOMUnsafeRegion oomUnsafe;
Redirection* redir = (Redirection*)js_malloc(sizeof(Redirection));
if (!redir) {
MOZ_ReportAssertionFailure("[unhandlable oom] Simulator redirection",
__FILE__, __LINE__);
MOZ_CRASH();
oomUnsafe.crash("Simulator redirection");
}
new(redir) Redirection(nativeFunction, type);
return redir;
@ -1445,13 +1451,6 @@ Simulator::setFpuRegisterFloat(int fpureg, float value)
*mozilla::BitwiseCast<float*>(&FPUregisters_[fpureg]) = value;
}
void
Simulator::setFpuRegisterFloat(int fpureg, int64_t value)
{
setFpuRegister(fpureg, value & 0xffffffff);
setFpuRegister(fpureg + 1, value >> 32);
}
void
Simulator::setFpuRegisterDouble(int fpureg, double value)
{
@ -1460,13 +1459,6 @@ Simulator::setFpuRegisterDouble(int fpureg, double value)
*mozilla::BitwiseCast<double*>(&FPUregisters_[fpureg]) = value;
}
void
Simulator::setFpuRegisterDouble(int fpureg, int64_t value)
{
setFpuRegister(fpureg, value & 0xffffffff);
setFpuRegister(fpureg + 1, value >> 32);
}
// Get the register from the architecture state. This function does handle
// the special case of accessing the PC register.
int32_t
@ -1629,33 +1621,100 @@ Simulator::get_pc() const
void
Simulator::startInterrupt(WasmActivation* activation)
{
MOZ_CRASH("NIY");
JS::ProfilingFrameIterator::RegisterState state;
state.pc = (void*) get_pc();
state.fp = (void*) getRegister(fp);
state.sp = (void*) getRegister(sp);
state.lr = (void*) getRegister(ra);
activation->startInterrupt(state);
}
// The signal handler only redirects the PC to the interrupt stub when the PC is
// in function code. However, this guard is racy for the simulator since the
// signal handler samples PC in the middle of simulating an instruction and thus
// the current PC may have advanced once since the signal handler's guard. So we
// re-check here.
void
Simulator::handleWasmInterrupt()
{
MOZ_CRASH("NIY");
void* pc = (void*)get_pc();
void* fp = (void*)getRegister(Register::fp);
WasmActivation* activation = wasm::ActivationIfInnermost(TlsContext.get());
const wasm::CodeSegment* segment;
const wasm::Code* code = activation->compartment()->wasm.lookupCode(pc, &segment);
if (!code || !segment->containsFunctionPC(pc))
return;
// fp can be null during the prologue/epilogue of the entry function.
if (!fp)
return;
startInterrupt(activation);
set_pc(int32_t(segment->interruptCode()));
}
// The MIPS cannot do unaligned reads and writes. On some MIPS platforms an
// interrupt is caused. On others it does a funky rotation thing. For now we
// simply disallow unaligned reads, but at some point we may want to move to
// emulating the rotate behaviour. Note that simulator runs have the runtime
// system running directly on the host system and only generated code is
// executed in the simulator. Since the host is typically IA32 we will not
// get the correct MIPS-like behaviour on unaligned accesses.
// WebAssembly memories contain an extra region of guard pages (see
// WasmArrayRawBuffer comment). The guard pages catch out-of-bounds accesses
// using a signal handler that redirects PC to a stub that safely reports an
// error. However, if the handler is hit by the simulator, the PC is in C++ code
// and cannot be redirected. Therefore, we must avoid hitting the handler by
// redirecting in the simulator before the real handler would have been hit.
bool
Simulator::handleWasmFault(int32_t addr, unsigned numBytes)
{
JSContext* cx = TlsContext.get();
WasmActivation* act = wasm::ActivationIfInnermost(cx);
if (!act)
return false;
void* pc = reinterpret_cast<void*>(get_pc());
uint8_t* fp = reinterpret_cast<uint8_t*>(getRegister(Register::fp));
// Cache the wasm::Code to avoid lookup on every load/store.
if (!wasm_code_ || !wasm_code_->containsCodePC(pc))
wasm_code_ = act->compartment()->wasm.lookupCode(pc);
if (!wasm_code_)
return false;
wasm::Instance* instance = wasm::LookupFaultingInstance(*wasm_code_, pc, fp);
if (!instance || !instance->memoryAccessInGuardRegion((uint8_t*)addr, numBytes))
return false;
LLBit_ = false;
const wasm::CodeSegment* segment;
const wasm::MemoryAccess* memoryAccess = instance->code().lookupMemoryAccess(pc, &segment);
if (!memoryAccess) {
startInterrupt(act);
if (!instance->code().containsCodePC(pc, &segment))
MOZ_CRASH("Cannot map PC to trap handler");
set_pc(int32_t(segment->outOfBoundsCode()));
return true;
}
MOZ_ASSERT(memoryAccess->hasTrapOutOfLineCode());
set_pc(int32_t(memoryAccess->trapOutOfLineCode(segment->base())));
return true;
}
// MIPS memory instructions (except lwl/r and swl/r) trap on unaligned memory
// access enabling the OS to handle them via trap-and-emulate.
// Note that simulator runs have the runtime system running directly on the host
// system and only generated code is executed in the simulator.
// Since the host is typically IA32 it will not trap on unaligned memory access.
// We assume that that executing correct generated code will not produce unaligned
// memory access, so we explicitly check for address alignment and trap.
// Note that trapping does not occur when executing wasm code, which requires that
// unaligned memory access provides correct result.
int
Simulator::readW(uint32_t addr, SimInstruction* instr)
{
if (addr < 0x400) {
// This has to be a NULL-dereference, drop into debugger.
printf("Memory read from bad address: 0x%08x, pc=0x%08" PRIxPTR "\n",
addr, reinterpret_cast<intptr_t>(instr));
MOZ_CRASH();
}
if ((addr & kPointerAlignmentMask) == 0) {
if (handleWasmFault(addr, 4))
return -1;
if ((addr & kPointerAlignmentMask) == 0 || wasm::InCompiledCode(reinterpret_cast<void *>(get_pc()))) {
intptr_t* ptr = reinterpret_cast<intptr_t*>(addr);
return *ptr;
}
@ -1669,14 +1728,12 @@ Simulator::readW(uint32_t addr, SimInstruction* instr)
void
Simulator::writeW(uint32_t addr, int value, SimInstruction* instr)
{
if (addr < 0x400) {
// This has to be a NULL-dereference, drop into debugger.
printf("Memory write to bad address: 0x%08x, pc=0x%08" PRIxPTR "\n",
addr, reinterpret_cast<intptr_t>(instr));
MOZ_CRASH();
}
if ((addr & kPointerAlignmentMask) == 0) {
if (handleWasmFault(addr, 4))
return;
if ((addr & kPointerAlignmentMask) == 0 || wasm::InCompiledCode(reinterpret_cast<void *>(get_pc()))) {
intptr_t* ptr = reinterpret_cast<intptr_t*>(addr);
LLBit_ = false;
*ptr = value;
return;
}
@ -1689,7 +1746,10 @@ Simulator::writeW(uint32_t addr, int value, SimInstruction* instr)
double
Simulator::readD(uint32_t addr, SimInstruction* instr)
{
if ((addr & kDoubleAlignmentMask) == 0) {
if (handleWasmFault(addr, 8))
return NAN;
if ((addr & kDoubleAlignmentMask) == 0 || wasm::InCompiledCode(reinterpret_cast<void *>(get_pc()))) {
double* ptr = reinterpret_cast<double*>(addr);
return *ptr;
}
@ -1703,8 +1763,12 @@ Simulator::readD(uint32_t addr, SimInstruction* instr)
void
Simulator::writeD(uint32_t addr, double value, SimInstruction* instr)
{
if ((addr & kDoubleAlignmentMask) == 0) {
if (handleWasmFault(addr, 8))
return;
if ((addr & kDoubleAlignmentMask) == 0 || wasm::InCompiledCode(reinterpret_cast<void *>(get_pc()))) {
double* ptr = reinterpret_cast<double*>(addr);
LLBit_ = false;
*ptr = value;
return;
}
@ -1717,7 +1781,10 @@ Simulator::writeD(uint32_t addr, double value, SimInstruction* instr)
uint16_t
Simulator::readHU(uint32_t addr, SimInstruction* instr)
{
if ((addr & 1) == 0) {
if (handleWasmFault(addr, 2))
return 0xffff;
if ((addr & 1) == 0 || wasm::InCompiledCode(reinterpret_cast<void *>(get_pc()))) {
uint16_t* ptr = reinterpret_cast<uint16_t*>(addr);
return *ptr;
}
@ -1731,7 +1798,10 @@ Simulator::readHU(uint32_t addr, SimInstruction* instr)
int16_t
Simulator::readH(uint32_t addr, SimInstruction* instr)
{
if ((addr & 1) == 0) {
if (handleWasmFault(addr, 2))
return -1;
if ((addr & 1) == 0 || wasm::InCompiledCode(reinterpret_cast<void *>(get_pc()))) {
int16_t* ptr = reinterpret_cast<int16_t*>(addr);
return *ptr;
}
@ -1745,8 +1815,12 @@ Simulator::readH(uint32_t addr, SimInstruction* instr)
void
Simulator::writeH(uint32_t addr, uint16_t value, SimInstruction* instr)
{
if ((addr & 1) == 0) {
if (handleWasmFault(addr, 2))
return;
if ((addr & 1) == 0 || wasm::InCompiledCode(reinterpret_cast<void *>(get_pc()))) {
uint16_t* ptr = reinterpret_cast<uint16_t*>(addr);
LLBit_ = false;
*ptr = value;
return;
}
@ -1759,8 +1833,12 @@ Simulator::writeH(uint32_t addr, uint16_t value, SimInstruction* instr)
void
Simulator::writeH(uint32_t addr, int16_t value, SimInstruction* instr)
{
if ((addr & 1) == 0) {
if (handleWasmFault(addr, 2))
return;
if ((addr & 1) == 0 || wasm::InCompiledCode(reinterpret_cast<void *>(get_pc()))) {
int16_t* ptr = reinterpret_cast<int16_t*>(addr);
LLBit_ = false;
*ptr = value;
return;
}
@ -1773,6 +1851,9 @@ Simulator::writeH(uint32_t addr, int16_t value, SimInstruction* instr)
uint32_t
Simulator::readBU(uint32_t addr)
{
if (handleWasmFault(addr, 1))
return 0xff;
uint8_t* ptr = reinterpret_cast<uint8_t*>(addr);
return *ptr;
}
@ -1780,6 +1861,9 @@ Simulator::readBU(uint32_t addr)
int32_t
Simulator::readB(uint32_t addr)
{
if (handleWasmFault(addr, 1))
return -1;
int8_t* ptr = reinterpret_cast<int8_t*>(addr);
return *ptr;
}
@ -1787,17 +1871,75 @@ Simulator::readB(uint32_t addr)
void
Simulator::writeB(uint32_t addr, uint8_t value)
{
if (handleWasmFault(addr, 1))
return;
uint8_t* ptr = reinterpret_cast<uint8_t*>(addr);
LLBit_ = false;
*ptr = value;
}
void
Simulator::writeB(uint32_t addr, int8_t value)
{
if (handleWasmFault(addr, 1))
return;
int8_t* ptr = reinterpret_cast<int8_t*>(addr);
LLBit_ = false;
*ptr = value;
}
int
Simulator::loadLinkedW(uint32_t addr, SimInstruction* instr)
{
if ((addr & kPointerAlignmentMask) == 0) {
volatile int32_t* ptr = reinterpret_cast<volatile int32_t*>(addr);
int32_t value = *ptr;
lastLLValue_ = value;
LLAddr_ = addr;
// Note that any memory write or "external" interrupt should reset this value to false.
LLBit_ = true;
return value;
}
printf("Unaligned read at 0x%08x, pc=0x%08" PRIxPTR "\n",
addr,
reinterpret_cast<intptr_t>(instr));
MOZ_CRASH();
return 0;
}
int
Simulator::storeConditionalW(uint32_t addr, int value, SimInstruction* instr)
{
// Correct behavior in this case, as defined by architecture, is to just return 0,
// but there is no point at allowing that. It is certainly an indicator of a bug.
if (addr != LLAddr_) {
printf("SC to bad address: 0x%08x, pc=0x%08" PRIxPTR ", expected: 0x%08x\n",
addr, reinterpret_cast<intptr_t>(instr), LLAddr_);
MOZ_CRASH();
}
if ((addr & kPointerAlignmentMask) == 0) {
SharedMem<int32_t*> ptr = SharedMem<int32_t*>::shared(reinterpret_cast<int32_t*>(addr));
if (!LLBit_) {
return 0;
}
LLBit_ = false;
LLAddr_ = 0;
int32_t expected = lastLLValue_;
int32_t old = AtomicOperations::compareExchangeSeqCst(ptr, expected, int32_t(value));
return (old == expected) ? 1:0;
}
printf("Unaligned SC at 0x%08x, pc=0x%08" PRIxPTR "\n",
addr,
reinterpret_cast<intptr_t>(instr));
MOZ_CRASH();
return 0;
}
uintptr_t
Simulator::stackLimit() const
{
@ -1860,6 +2002,8 @@ typedef int32_t (*Prototype_Int_DoubleIntInt)(double arg0, int32_t arg1, int32_t
typedef int32_t (*Prototype_Int_IntDoubleIntInt)(int32_t arg0, double arg1, int32_t arg2,
int32_t arg3);
typedef float (*Prototype_Float32_Float32)(float arg0);
typedef float (*Prototype_Float32_Float32Float32)(float arg0, float arg1);
typedef float (*Prototype_Float32_IntInt)(int arg0, int arg1);
typedef double (*Prototype_DoubleInt)(double arg0, int32_t arg1);
typedef double (*Prototype_Double_IntInt)(int32_t arg0, int32_t arg1);
@ -2019,6 +2163,22 @@ Simulator::softwareInterrupt(SimInstruction* instr)
setCallResultFloat(fresult);
break;
}
case Args_Float32_Float32Float32: {
float fval0;
float fval1;
fval0 = getFpuRegisterFloat(12);
fval1 = getFpuRegisterFloat(14);
Prototype_Float32_Float32Float32 target = reinterpret_cast<Prototype_Float32_Float32Float32>(external);
float fresult = target(fval0,fval1);
setCallResultFloat(fresult);
break;
}
case Args_Float32_IntInt: {
Prototype_Float32_IntInt target = reinterpret_cast<Prototype_Float32_IntInt>(external);
float fresult = target(arg0, arg1);
setCallResultFloat(fresult);
break;
}
case Args_Double_Int: {
Prototype_Double_Int target = reinterpret_cast<Prototype_Double_Int>(external);
double dresult = target(arg0);
@ -2406,6 +2566,7 @@ Simulator::configureTypeRegister(SimInstruction* instr,
case ff_movn:
case ff_movz:
case ff_movci:
case ff_sync:
// No action taken on decode.
break;
case ff_div:
@ -2524,7 +2685,6 @@ Simulator::decodeTypeRegister(SimInstruction* instr)
MOZ_CRASH();
break;
case rs_cfc1:
setRegister(rt_reg, alu_out);
case rs_mfc1:
setRegister(rt_reg, alu_out);
break;
@ -2545,7 +2705,6 @@ Simulator::decodeTypeRegister(SimInstruction* instr)
case rs_s:
float f, ft_value, fs_value;
uint32_t cc, fcsr_cc;
int64_t i64;
fs_value = getFpuRegisterFloat(fs_reg);
ft_value = getFpuRegisterFloat(ft_reg);
cc = instr->fcccValue();
@ -2649,37 +2808,30 @@ Simulator::decodeTypeRegister(SimInstruction* instr)
}
break;
}
case ff_cvt_l_fmt: { // Mips32r2: Truncate float to 64-bit long-word.
float rounded = truncf(fs_value);
i64 = static_cast<int64_t>(rounded);
setFpuRegisterFloat(fd_reg, i64);
break;
}
case ff_round_l_fmt: { // Mips32r2 instruction.
float rounded =
fs_value > 0 ? std::floor(fs_value + 0.5) : std::ceil(fs_value - 0.5);
i64 = static_cast<int64_t>(rounded);
setFpuRegisterFloat(fd_reg, i64);
break;
}
case ff_trunc_l_fmt: { // Mips32r2 instruction.
float rounded = truncf(fs_value);
i64 = static_cast<int64_t>(rounded);
setFpuRegisterFloat(fd_reg, i64);
break;
}
case ff_floor_l_fmt: // Mips32r2 instruction.
i64 = static_cast<int64_t>(std::floor(fs_value));
setFpuRegisterFloat(fd_reg, i64);
break;
case ff_ceil_l_fmt: // Mips32r2 instruction.
i64 = static_cast<int64_t>(std::ceil(fs_value));
setFpuRegisterFloat(fd_reg, i64);
break;
case ff_cvt_l_fmt:
case ff_round_l_fmt:
case ff_trunc_l_fmt:
case ff_floor_l_fmt:
case ff_ceil_l_fmt:
case ff_cvt_ps_s:
case ff_c_f_fmt:
MOZ_CRASH();
break;
case ff_movf_fmt:
if (testFCSRBit(fcsr_cc)) {
setFpuRegisterFloat(fd_reg, getFpuRegisterFloat(fs_reg));
}
break;
case ff_movz_fmt:
if (rt == 0) {
setFpuRegisterFloat(fd_reg, getFpuRegisterFloat(fs_reg));
}
break;
case ff_movn_fmt:
if (rt != 0) {
setFpuRegisterFloat(fd_reg, getFpuRegisterFloat(fs_reg));
}
break;
default:
MOZ_CRASH();
}
@ -2798,33 +2950,11 @@ Simulator::decodeTypeRegister(SimInstruction* instr)
case ff_cvt_s_fmt: // Convert double to float (single).
setFpuRegisterFloat(fd_reg, static_cast<float>(ds_value));
break;
case ff_cvt_l_fmt: { // Mips32r2: Truncate double to 64-bit long-word.
double rounded = trunc(ds_value);
i64 = static_cast<int64_t>(rounded);
setFpuRegisterDouble(fd_reg, i64);
break;
}
case ff_trunc_l_fmt: { // Mips32r2 instruction.
double rounded = trunc(ds_value);
i64 = static_cast<int64_t>(rounded);
setFpuRegisterDouble(fd_reg, i64);
break;
}
case ff_round_l_fmt: { // Mips32r2 instruction.
double rounded =
ds_value > 0 ? std::floor(ds_value + 0.5) : std::ceil(ds_value - 0.5);
i64 = static_cast<int64_t>(rounded);
setFpuRegisterDouble(fd_reg, i64);
break;
}
case ff_floor_l_fmt: // Mips32r2 instruction.
i64 = static_cast<int64_t>(std::floor(ds_value));
setFpuRegisterDouble(fd_reg, i64);
break;
case ff_ceil_l_fmt: // Mips32r2 instruction.
i64 = static_cast<int64_t>(std::ceil(ds_value));
setFpuRegisterDouble(fd_reg, i64);
break;
case ff_cvt_l_fmt:
case ff_trunc_l_fmt:
case ff_round_l_fmt:
case ff_floor_l_fmt:
case ff_ceil_l_fmt:
case ff_c_f_fmt:
MOZ_CRASH();
break;
@ -2863,13 +2993,7 @@ Simulator::decodeTypeRegister(SimInstruction* instr)
break;
case rs_l:
switch (instr->functionFieldRaw()) {
case ff_cvt_d_fmt: // Mips32r2 instruction.
// Watch the signs here, we want 2 32-bit vals
// to make a sign-64.
i64 = static_cast<uint32_t>(getFpuRegister(fs_reg));
i64 |= static_cast<int64_t>(getFpuRegister(fs_reg + 1)) << 32;
setFpuRegisterDouble(fd_reg, static_cast<double>(i64));
break;
case ff_cvt_d_fmt:
case ff_cvt_s_fmt:
MOZ_CRASH();
break;
@ -2962,6 +3086,20 @@ Simulator::decodeTypeRegister(SimInstruction* instr)
softwareInterrupt(instr);
}
break;
case ff_sync:
switch(instr->bits(10, 6)){
case 0x0:
case 0x4:
case 0x10:
case 0x11:
case 0x12:
case 0x13:
AtomicOperations::fenceSeqCst();
break;
default:
MOZ_CRASH();
}
break;
// Conditional moves.
case ff_movn:
if (rt) setRegister(rd_reg, rs);
@ -3249,6 +3387,14 @@ Simulator::decodeTypeImmediate(SimInstruction* instr)
case op_sdc1:
addr = rs + se_imm16;
break;
case op_ll:
addr = rs + se_imm16;
alu_out = loadLinkedW(addr, instr);
break;
case op_sc:
addr = rs + se_imm16;
alu_out = storeConditionalW(addr,rt,instr);
break;
default:
MOZ_CRASH();
}
@ -3294,6 +3440,8 @@ Simulator::decodeTypeImmediate(SimInstruction* instr)
case op_lbu:
case op_lhu:
case op_lwr:
case op_ll:
case op_sc:
setRegister(rt_reg, alu_out);
break;
case op_sb:

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

@ -36,6 +36,7 @@
#include "jit/IonTypes.h"
#include "threading/Thread.h"
#include "vm/MutexIDs.h"
#include "wasm/WasmCode.h"
namespace js {
@ -261,6 +262,9 @@ class Simulator {
inline double readD(uint32_t addr, SimInstruction* instr);
inline void writeD(uint32_t addr, double value, SimInstruction* instr);
inline int32_t loadLinkedW(uint32_t addr, SimInstruction* instr);
inline int32_t storeConditionalW(uint32_t addr, int32_t value, SimInstruction* instr);
// Executing is handled based on the instruction type.
void decodeTypeRegister(SimInstruction* instr);
@ -294,6 +298,9 @@ class Simulator {
void handleWasmInterrupt();
void startInterrupt(WasmActivation* act);
// Handle any wasm faults, returning true if the fault was handled.
bool handleWasmFault(int32_t addr, unsigned numBytes);
// Executes one instruction.
void instructionDecode(SimInstruction* instr);
// Execute one instruction placed in a branch delay slot.
@ -336,6 +343,10 @@ class Simulator {
// FPU control register.
uint32_t FCSR_;
bool LLBit_;
uint32_t LLAddr_;
int32_t lastLLValue_;
// Simulator support.
char* stack_;
uintptr_t stackLimit_;
@ -343,8 +354,9 @@ class Simulator {
int icount_;
int break_count_;
// wasm async interrupt support
// wasm async interrupt / fault support
bool wasm_interrupt_;
wasm::SharedCode wasm_code_;
// Debugger input.
char* lastDebuggerInput_;

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

@ -113,6 +113,14 @@ class FloatRegister : public FloatRegisterMIPSShared
: reg_(Encoding(FloatRegisters::invalid_freg)), kind_(Codes::Double)
{ }
static uint32_t SetSize(SetType x) {
// Count the number of non-aliased registers.
x |= x >> Codes::TotalPhys;
x &= Codes::AllPhysMask;
static_assert(Codes::AllPhysMask <= 0xffffffff, "We can safely use CountPopulation32");
return mozilla::CountPopulation32(x);
}
bool operator==(const FloatRegister& other) const {
MOZ_ASSERT(!isInvalid());
MOZ_ASSERT(!other.isInvalid());

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

@ -40,6 +40,8 @@
#include "jit/mips64/Assembler-mips64.h"
#include "threading/LockGuard.h"
#include "vm/Runtime.h"
#include "wasm/WasmInstance.h"
#include "wasm/WasmSignalHandlers.h"
#define I8(v) static_cast<int8_t>(v)
#define I16(v) static_cast<int16_t>(v)
@ -1267,7 +1269,7 @@ Simulator::Simulator()
pc_modified_ = false;
icount_ = 0;
break_count_ = 0;
resume_pc_ = 0;
wasm_interrupt_ = false;
break_pc_ = nullptr;
break_instr_ = 0;
single_stepping_ = false;
@ -1610,6 +1612,18 @@ Simulator::get_pc() const
return registers_[pc];
}
void
Simulator::startInterrupt(WasmActivation* activation)
{
MOZ_CRASH("NIY");
}
void
Simulator::handleWasmInterrupt()
{
MOZ_CRASH("NIY");
}
// The MIPS cannot do unaligned reads and writes. On some MIPS platforms an
// interrupt is caused. On others it does a funky rotation thing. For now we
// simply disallow unaligned reads, but at some point we may want to move to
@ -2720,6 +2734,7 @@ Simulator::decodeTypeRegister(SimInstruction* instr)
break;
case rs_cfc1:
setRegister(rt_reg, alu_out);
MOZ_FALLTHROUGH;
case rs_mfc1:
setRegister(rt_reg, alu_out);
break;
@ -2808,6 +2823,7 @@ Simulator::decodeTypeRegister(SimInstruction* instr)
// Rounding modes are not yet supported.
MOZ_ASSERT((FCSR_ & 3) == 0);
// In rounding mode 0 it should behave like ROUND.
MOZ_FALLTHROUGH;
case ff_round_w_fmt: { // Round double to word (round half to even).
float rounded = std::floor(fs_value + 0.5);
int32_t result = I32(rounded);
@ -2943,6 +2959,7 @@ Simulator::decodeTypeRegister(SimInstruction* instr)
// Rounding modes are not yet supported.
MOZ_ASSERT((FCSR_ & 3) == 0);
// In rounding mode 0 it should behave like ROUND.
MOZ_FALLTHROUGH;
case ff_round_w_fmt: { // Round double to word (round half to even).
double rounded = std::floor(ds_value + 0.5);
int32_t result = I32(rounded);
@ -3314,6 +3331,7 @@ Simulator::decodeTypeImmediate(SimInstruction* instr)
} else {
next_pc = current_pc + kBranchReturnOffset;
}
break;
default:
break;
};
@ -3722,7 +3740,6 @@ Simulator::execute()
// Get the PC to simulate. Cannot use the accessor here as we need the
// raw PC value and not the one used as input to arithmetic instructions.
int64_t program_counter = get_pc();
WasmActivation* activation = TlsContext.get()->wasmActivationStack();
while (program_counter != end_sim_pc) {
if (enableStopSimAt && (icount_ == Simulator::StopSimAt)) {
@ -3735,12 +3752,9 @@ Simulator::execute()
instructionDecode(instr);
icount_++;
int64_t rpc = resume_pc_;
if (MOZ_UNLIKELY(rpc != 0)) {
// wasm signal handler ran and we have to adjust the pc.
activation->setResumePC((void*)get_pc());
set_pc(rpc);
resume_pc_ = 0;
if (MOZ_UNLIKELY(wasm_interrupt_)) {
handleWasmInterrupt();
wasm_interrupt_ = false;
}
}
program_counter = get_pc();

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

@ -39,6 +39,9 @@
#include "vm/MutexIDs.h"
namespace js {
class WasmActivation;
namespace jit {
class Simulator;
@ -193,9 +196,12 @@ class Simulator {
template <typename T>
T get_pc_as() const { return reinterpret_cast<T>(get_pc()); }
void set_resume_pc(void* value) {
resume_pc_ = int64_t(value);
}
void trigger_wasm_interrupt() {
// This can be called several times if a single interrupt isn't caught
// and handled by the simulator, but this is fine; once the current
// instruction is done executing, the interrupt will be handled anyhow.
wasm_interrupt_ = true;
}
void enable_single_stepping(SingleStepCallback cb, void* arg);
void disable_single_stepping();
@ -297,6 +303,9 @@ class Simulator {
void increaseStopCounter(uint32_t code);
void printStopInfo(uint32_t code);
// Handle a wasm interrupt triggered by an async signal handler.
void handleWasmInterrupt();
void startInterrupt(WasmActivation* act);
// Executes one instruction.
void instructionDecode(SimInstruction* instr);
@ -345,7 +354,8 @@ class Simulator {
int64_t icount_;
int64_t break_count_;
int64_t resume_pc_;
// wasm async interrupt support
bool wasm_interrupt_;
// Debugger input.
char* lastDebuggerInput_;

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

@ -657,6 +657,12 @@ JS_SetAccumulateTelemetryCallback(JSContext* cx, JSAccumulateTelemetryDataCallba
cx->runtime()->setTelemetryCallback(cx->runtime(), callback);
}
JS_FRIEND_API(void)
JS_SetSetUseCounterCallback(JSContext* cx, JSSetUseCounterCallback callback)
{
cx->runtime()->setUseCounterCallback(cx->runtime(), callback);
}
JS_FRIEND_API(JSObject*)
JS_CloneObject(JSContext* cx, HandleObject obj, HandleObject protoArg)
{

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

@ -172,6 +172,24 @@ typedef void
extern JS_FRIEND_API(void)
JS_SetAccumulateTelemetryCallback(JSContext* cx, JSAccumulateTelemetryDataCallback callback);
/*
* Use counter names passed to the accumulate use counter callback.
*
* It's OK to for these enum values to change as they will be mapped to a
* fixed member of the mozilla::UseCounter enum by the callback.
*/
enum class JSUseCounter {
ASMJS,
WASM
};
typedef void
(*JSSetUseCounterCallback)(JSObject* obj, JSUseCounter counter);
extern JS_FRIEND_API(void)
JS_SetSetUseCounterCallback(JSContext* cx, JSSetUseCounterCallback callback);
extern JS_FRIEND_API(bool)
JS_GetIsSecureContext(JSCompartment* compartment);

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

@ -740,3 +740,7 @@ skip script test262/language/expressions/class/dstr-meth-static-obj-ptrn-rest-ob
skip script test262/language/expressions/class/dstr-gen-meth-static-dflt-obj-ptrn-rest-obj-nested-rest.js
skip script test262/language/expressions/class/dstr-async-gen-meth-static-dflt-obj-ptrn-rest-obj-nested-rest.js
skip script test262/language/expressions/class/dstr-gen-meth-static-dflt-obj-ptrn-rest-nested-obj.js
# https://github.com/tc39/test262/pull/1170
skip script test262/language/module-code/namespace/internals/define-own-property.js
skip script test262/language/module-code/namespace/internals/set.js

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

@ -444,6 +444,19 @@ JSRuntime::setTelemetryCallback(JSRuntime* rt, JSAccumulateTelemetryDataCallback
rt->telemetryCallback = callback;
}
void
JSRuntime::setUseCounter(JSObject* obj, JSUseCounter counter)
{
if (useCounterCallback)
(*useCounterCallback)(obj, counter);
}
void
JSRuntime::setUseCounterCallback(JSRuntime* rt, JSSetUseCounterCallback callback)
{
rt->useCounterCallback = callback;
}
void
JSRuntime::addSizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf, JS::RuntimeSizes* rtSizes)
{

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

@ -455,6 +455,10 @@ struct JSRuntime : public js::MallocProvider<JSRuntime>
/* Call this to accumulate telemetry data. */
js::ActiveThreadData<JSAccumulateTelemetryDataCallback> telemetryCallback;
/* Call this to accumulate use counter data. */
js::ActiveThreadData<JSSetUseCounterCallback> useCounterCallback;
public:
// Accumulates data for Firefox telemetry. |id| is the ID of a JS_TELEMETRY_*
// histogram. |key| provides an additional key to identify the histogram.
@ -463,6 +467,13 @@ struct JSRuntime : public js::MallocProvider<JSRuntime>
void setTelemetryCallback(JSRuntime* rt, JSAccumulateTelemetryDataCallback callback);
// Sets the use counter for a specific feature, measuring the presence or
// absence of usage of a feature on a specific web page and document which
// the passed JSObject belongs to.
void setUseCounter(JSObject* obj, JSUseCounter counter);
void setUseCounterCallback(JSRuntime* rt, JSSetUseCounterCallback callback);
public:
js::UnprotectedData<js::OffThreadPromiseRuntimeState> offThreadPromiseState;

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

@ -1206,5 +1206,8 @@ Module::instantiate(JSContext* cx,
uint32_t mode = uint32_t(metadata().isAsmJS() ? Telemetry::ASMJS : Telemetry::WASM);
cx->runtime()->addTelemetry(JS_TELEMETRY_AOT_USAGE, mode);
JSUseCounter useCounter = metadata().isAsmJS() ? JSUseCounter::ASMJS : JSUseCounter::WASM;
cx->runtime()->setUseCounter(instance, useCounter);
return true;
}

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

@ -1174,7 +1174,7 @@ wasm::GenerateInterruptExit(MacroAssembler& masm, Label* throwLabel)
// Reclaim the reserve space.
masm.addToStackPtr(Imm32(2 * sizeof(intptr_t)));
masm.as_jr(HeapReg);
masm.loadPtr(Address(StackPointer, -sizeof(intptr_t)), HeapReg);
masm.loadPtr(Address(StackPointer, -int32_t(sizeof(intptr_t))), HeapReg);
#elif defined(JS_CODEGEN_ARM)
{
// Be careful not to clobber scratch registers before they are saved.

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

@ -2663,6 +2663,21 @@ AccumulateTelemetryCallback(int id, uint32_t sample, const char* key)
}
}
static void
SetUseCounterCallback(JSObject* obj, JSUseCounter counter)
{
switch (counter) {
case JSUseCounter::ASMJS:
SetDocumentAndPageUseCounter(obj, eUseCounter_custom_JS_asmjs);
break;
case JSUseCounter::WASM:
SetDocumentAndPageUseCounter(obj, eUseCounter_custom_JS_wasm);
break;
default:
MOZ_ASSERT_UNREACHABLE("Unexpected JSUseCounter id");
}
}
static void
CompartmentNameCallback(JSContext* cx, JSCompartment* comp,
char* buf, size_t bufsize)
@ -2865,6 +2880,7 @@ XPCJSRuntime::Initialize(JSContext* cx)
JS_SetWrapObjectCallbacks(cx, &WrapObjectCallbacks);
js::SetPreserveWrapperCallback(cx, PreserveWrapper);
JS_SetAccumulateTelemetryCallback(cx, AccumulateTelemetryCallback);
JS_SetSetUseCounterCallback(cx, SetUseCounterCallback);
js::SetWindowProxyClass(cx, &OuterWindowProxyClass);
js::SetXrayJitInfo(&gXrayJitInfo);
JS::SetProcessLargeAllocationFailureCallback(OnLargeAllocationFailureCallback);

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

@ -426,6 +426,9 @@
*
* The static analyses that are performed by the plugin are as follows:
*
* MOZ_CAN_RUN_SCRIPT: Applies to functions which can run script. Callers of
* this function must also be marked as MOZ_CAN_RUN_SCRIPT, and all refcounted
* arguments must be strongly held in the caller.
* MOZ_MUST_OVERRIDE: Applies to all C++ member functions. All immediate
* subclasses must provide an exact override of this method; if a subclass
* does not override this method, the compiler will emit an error. This
@ -478,6 +481,14 @@
* are disallowed by default unless they are marked as MOZ_IMPLICIT. This
* attribute must be used for constructors which intend to provide implicit
* conversions.
* MOZ_IS_REFPTR: Applies to class declarations of ref pointer to mark them as
* such for use with static-analysis.
* A ref pointer is an object wrapping a pointer and automatically taking care
* of its refcounting upon construction/destruction/transfer of ownership.
* This annotation implies MOZ_IS_SMARTPTR_TO_REFCOUNTED.
* MOZ_IS_SMARTPTR_TO_REFCOUNTED: Applies to class declarations of smart
* pointers to ref counted classes to mark them as such for use with
* static-analysis.
* MOZ_NO_ARITHMETIC_EXPR_IN_ARGUMENT: Applies to functions. Makes it a compile
* time error to pass arithmetic expressions on variables to the function.
* MOZ_OWNING_REF: Applies to declarations of pointers to reference counted
@ -576,6 +587,7 @@
* MOZ_MUST_RETURN_FROM_CALLER function or method.
*/
#ifdef MOZ_CLANG_PLUGIN
# define MOZ_CAN_RUN_SCRIPT __attribute__((annotate("moz_can_run_script")))
# define MOZ_MUST_OVERRIDE __attribute__((annotate("moz_must_override")))
# define MOZ_STACK_CLASS __attribute__((annotate("moz_stack_class")))
# define MOZ_NONHEAP_CLASS __attribute__((annotate("moz_nonheap_class")))
@ -590,6 +602,9 @@
MOZ_TRIVIAL_CTOR_DTOR
# endif
# define MOZ_IMPLICIT __attribute__((annotate("moz_implicit")))
# define MOZ_IS_SMARTPTR_TO_REFCOUNTED __attribute__((annotate("moz_is_smartptr_to_refcounted")))
# define MOZ_IS_REFPTR __attribute__((annotate("moz_is_refptr"))) \
MOZ_IS_SMARTPTR_TO_REFCOUNTED
# define MOZ_NO_ARITHMETIC_EXPR_IN_ARGUMENT __attribute__((annotate("moz_no_arith_expr_in_arg")))
# define MOZ_OWNING_REF __attribute__((annotate("moz_strong_ref")))
# define MOZ_NON_OWNING_REF __attribute__((annotate("moz_weak_ref")))
@ -627,6 +642,7 @@
__attribute__((annotate("moz_heap_allocator"))) \
_Pragma("clang diagnostic pop")
#else
# define MOZ_CAN_RUN_SCRIPT /* nothing */
# define MOZ_MUST_OVERRIDE /* nothing */
# define MOZ_STACK_CLASS /* nothing */
# define MOZ_NONHEAP_CLASS /* nothing */
@ -635,6 +651,8 @@
# define MOZ_TRIVIAL_CTOR_DTOR /* nothing */
# define MOZ_ONLY_USED_TO_AVOID_STATIC_CONSTRUCTORS /* nothing */
# define MOZ_IMPLICIT /* nothing */
# define MOZ_IS_SMARTPTR_TO_REFCOUNTED /* nothing */
# define MOZ_IS_REFPTR /* nothing */
# define MOZ_NO_ARITHMETIC_EXPR_IN_ARGUMENT /* nothing */
# define MOZ_HEAP_ALLOCATOR /* nothing */
# define MOZ_OWNING_REF /* nothing */

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

@ -44,7 +44,7 @@ struct RefPtrTraits
} // namespace mozilla
template <class T>
class RefPtr
class MOZ_IS_REFPTR RefPtr
{
private:
void

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

@ -21,10 +21,20 @@
#ifdef MOZ_CLANG_PLUGIN
#ifdef __cplusplus
/**
* MOZ_KnownLive - used to opt an argument out of the CanRunScript checker so
* that we don't check it if is a strong ref.
*
* Example:
* canRunScript(MOZ_KnownLive(rawPointer));
*/
template <typename T>
static MOZ_ALWAYS_INLINE T* MOZ_KnownLive(T* ptr) { return ptr; }
extern "C" {
#endif
/*
/**
* MOZ_AssertAssignmentTest - used in MOZ_ASSERT in order to test the possible
* presence of assignment instead of logical comparisons.
*

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

@ -1030,6 +1030,11 @@ public abstract class GeckoApp extends GeckoActivity
@Override // GeckoView.ContentListener
public void onFullScreen(final GeckoView view, final boolean fullScreen) {
if (fullScreen) {
SnackbarBuilder.builder(this)
.message(R.string.fullscreen_warning)
.duration(Snackbar.LENGTH_LONG).buildAndShow();
}
ThreadUtils.assertOnUiThread();
ActivityUtils.setFullScreen(this, fullScreen);
}

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

@ -857,3 +857,5 @@ is simply hidden from the Activity Stream panel. -->
<!ENTITY private_tab_panel_description "&brandShortName; blocks parts of the pages that may track your browsing activity.">
<!ENTITY private_tab_panel_description2 "We won\'t remember any history, but downloaded files and new bookmarks will still be saved to your device.">
<!ENTITY private_tab_learn_more "Want to learn more?">
<!ENTITY fullscreen_warning "Entered full screen">

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

@ -636,4 +636,6 @@
<string name="private_tab_panel_description">&private_tab_panel_description;</string>
<string name="private_tab_panel_description2">&private_tab_panel_description2;</string>
<string name="private_tab_learn_more">&private_tab_learn_more;</string>
<string name="fullscreen_warning">&fullscreen_warning;</string>
</resources>

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

@ -5775,7 +5775,7 @@ pref("security.mixed_content.hsts_priming_request_timeout", 2000);
// a NullPrincipal as the security context.
// Otherwise it will inherit the origin from parent node, this is the legacy
// behavior of Firefox.
pref("security.data_uri.unique_opaque_origin", false);
pref("security.data_uri.unique_opaque_origin", true);
// TODO: Bug 1380959: Block toplevel data: URI navigations
// If true, all toplevel data: URI navigations will be blocked.

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

@ -66,7 +66,7 @@ W32API_VERSION=3.14
GCONF_VERSION=1.2.1
STARTUP_NOTIFICATION_VERSION=0.8
DBUS_VERSION=0.60
SQLITE_VERSION=3.20.0
SQLITE_VERSION=3.20.1
dnl Set various checks
dnl ========================================================

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

@ -995,8 +995,9 @@ nsHtml5TreeOpExecutor::PreloadImage(const nsAString& aURL,
const nsAString& aImageReferrerPolicy)
{
nsCOMPtr<nsIURI> baseURI = BaseURIForPreload();
bool isImgSet = false;
nsCOMPtr<nsIURI> uri = mDocument->ResolvePreloadImage(baseURI, aURL, aSrcset,
aSizes);
aSizes, &isImgSet);
if (uri && ShouldPreloadURI(uri)) {
// use document wide referrer policy
mozilla::net::ReferrerPolicy referrerPolicy = mSpeculationReferrerPolicy;
@ -1006,7 +1007,7 @@ nsHtml5TreeOpExecutor::PreloadImage(const nsAString& aURL,
referrerPolicy = imageReferrerPolicy;
}
mDocument->MaybePreLoadImage(uri, aCrossOrigin, referrerPolicy);
mDocument->MaybePreLoadImage(uri, aCrossOrigin, referrerPolicy, isImgSet);
}
}

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

@ -4,8 +4,8 @@
import os
import sys
from distutils.spawn import find_executable
import py
import pytest
from mozlint import cli
@ -39,7 +39,7 @@ def test_cli_run_with_fix(run, capfd):
assert out.endswith('{}\n')
@pytest.mark.skipif(not py.path.local.sysfind("echo"), reason="No `echo` executable found.")
@pytest.mark.skipif(not find_executable("echo"), reason="No `echo` executable found.")
def test_cli_run_with_edit(run, parser, capfd):
os.environ['EDITOR'] = 'echo'

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

@ -35,7 +35,8 @@ SandboxBrokerClient::~SandboxBrokerClient()
int
SandboxBrokerClient::DoCall(const Request* aReq, const char* aPath,
void* aResponseBuff, bool expectFd)
const char* aPath2, void* aResponseBuff,
bool expectFd)
{
// Remap /proc/self to the actual pid, so that the broker can open
// it. This happens here instead of in the broker to follow the
@ -63,28 +64,38 @@ SandboxBrokerClient::DoCall(const Request* aReq, const char* aPath,
}
}
struct iovec ios[2];
struct iovec ios[3];
int respFds[2];
// Set up iovecs for request + path.
ios[0].iov_base = const_cast<Request*>(aReq);
ios[0].iov_len = sizeof(*aReq);
ios[1].iov_base = const_cast<char*>(path);
ios[1].iov_len = strlen(path);
ios[1].iov_len = strlen(path) + 1;
if (aPath2 != nullptr) {
ios[2].iov_base = const_cast<char*>(aPath2);
ios[2].iov_len = strlen(aPath2) + 1;
} else {
ios[2].iov_base = nullptr;
ios[2].iov_len = 0;
}
if (ios[1].iov_len > kMaxPathLen) {
return -ENAMETOOLONG;
}
if (ios[2].iov_len > kMaxPathLen) {
return -ENAMETOOLONG;
}
// Create response socket and send request.
if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, respFds) < 0) {
return -errno;
}
const ssize_t sent = SendWithFd(mFileDesc, ios, 2, respFds[1]);
const ssize_t sent = SendWithFd(mFileDesc, ios, 3, respFds[1]);
const int sendErrno = errno;
MOZ_ASSERT(sent < 0 ||
static_cast<size_t>(sent) == ios[0].iov_len
+ ios[1].iov_len);
+ ios[1].iov_len
+ ios[2].iov_len);
close(respFds[1]);
if (sent < 0) {
close(respFds[0]);
@ -145,7 +156,7 @@ int
SandboxBrokerClient::Open(const char* aPath, int aFlags)
{
Request req = { SANDBOX_FILE_OPEN, aFlags, 0 };
int maybeFd = DoCall(&req, aPath, nullptr, true);
int maybeFd = DoCall(&req, aPath, nullptr, nullptr, true);
if (maybeFd >= 0) {
// NSPR has opinions about file flags. Fix O_CLOEXEC.
if ((aFlags & O_CLOEXEC) == 0) {
@ -159,56 +170,77 @@ int
SandboxBrokerClient::Access(const char* aPath, int aMode)
{
Request req = { SANDBOX_FILE_ACCESS, aMode, 0 };
return DoCall(&req, aPath, nullptr, false);
return DoCall(&req, aPath, nullptr, nullptr, false);
}
int
SandboxBrokerClient::Stat(const char* aPath, statstruct* aStat)
{
Request req = { SANDBOX_FILE_STAT, 0, sizeof(statstruct) };
return DoCall(&req, aPath, (void*)aStat, false);
return DoCall(&req, aPath, nullptr, (void*)aStat, false);
}
int
SandboxBrokerClient::LStat(const char* aPath, statstruct* aStat)
{
Request req = { SANDBOX_FILE_STAT, O_NOFOLLOW, sizeof(statstruct) };
return DoCall(&req, aPath, (void*)aStat, false);
return DoCall(&req, aPath, nullptr, (void*)aStat, false);
}
int
SandboxBrokerClient::Chmod(const char* aPath, int aMode)
{
Request req = {SANDBOX_FILE_CHMOD, aMode, 0};
return DoCall(&req, aPath, nullptr, false);
return DoCall(&req, aPath, nullptr, nullptr, false);
}
int
SandboxBrokerClient::Link(const char* aOldPath, const char* aNewPath)
{
Request req = {SANDBOX_FILE_LINK, 0, 0};
return DoCall(&req, aOldPath, aNewPath, nullptr, false);
}
int
SandboxBrokerClient::Symlink(const char* aOldPath, const char* aNewPath)
{
Request req = {SANDBOX_FILE_SYMLINK, 0, 0};
return DoCall(&req, aOldPath, aNewPath, nullptr, false);
}
int
SandboxBrokerClient::Rename(const char* aOldPath, const char* aNewPath)
{
Request req = {SANDBOX_FILE_RENAME, 0, 0};
return DoCall(&req, aOldPath, aNewPath, nullptr, false);
}
int
SandboxBrokerClient::Mkdir(const char* aPath, int aMode)
{
Request req = {SANDBOX_FILE_MKDIR, aMode, 0};
return DoCall(&req, aPath, nullptr, false);
return DoCall(&req, aPath, nullptr, nullptr, false);
}
int
SandboxBrokerClient::Unlink(const char* aPath)
{
Request req = {SANDBOX_FILE_UNLINK, 0, 0};
return DoCall(&req, aPath, nullptr, false);
return DoCall(&req, aPath, nullptr, nullptr, false);
}
int
SandboxBrokerClient::Rmdir(const char* aPath)
{
Request req = {SANDBOX_FILE_RMDIR, 0, 0};
return DoCall(&req, aPath, nullptr, false);
return DoCall(&req, aPath, nullptr, nullptr, false);
}
int
SandboxBrokerClient::Readlink(const char* aPath, void* aBuff, size_t aSize)
{
Request req = {SANDBOX_FILE_READLINK, 0, aSize};
return DoCall(&req, aPath, aBuff, false);
return DoCall(&req, aPath, nullptr, aBuff, false);
}
} // namespace mozilla

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

@ -35,7 +35,10 @@ class SandboxBrokerClient final : private SandboxBrokerCommon {
int Stat(const char* aPath, statstruct* aStat);
int LStat(const char* aPath, statstruct* aStat);
int Chmod(const char* aPath, int aMode);
int Link(const char* aPath, const char* aPath2);
int Mkdir(const char* aPath, int aMode);
int Symlink(const char* aOldPath, const char* aNewPath);
int Rename(const char* aOldPath, const char* aNewPath);
int Unlink(const char* aPath);
int Rmdir(const char* aPath);
int Readlink(const char* aPath, void* aBuf, size_t aBufSize);
@ -45,6 +48,7 @@ class SandboxBrokerClient final : private SandboxBrokerCommon {
int DoCall(const Request* aReq,
const char* aPath,
const char* aPath2,
void *aReponseBuff,
bool expectFd);
};

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

@ -446,6 +446,27 @@ private:
return broker->Chmod(path, mode);
}
static intptr_t LinkTrap(ArgsRef aArgs, void *aux) {
auto broker = static_cast<SandboxBrokerClient*>(aux);
auto path = reinterpret_cast<const char*>(aArgs.args[0]);
auto path2 = reinterpret_cast<const char*>(aArgs.args[1]);
return broker->Link(path, path2);
}
static intptr_t SymlinkTrap(ArgsRef aArgs, void *aux) {
auto broker = static_cast<SandboxBrokerClient*>(aux);
auto path = reinterpret_cast<const char*>(aArgs.args[0]);
auto path2 = reinterpret_cast<const char*>(aArgs.args[1]);
return broker->Symlink(path, path2);
}
static intptr_t RenameTrap(ArgsRef aArgs, void *aux) {
auto broker = static_cast<SandboxBrokerClient*>(aux);
auto path = reinterpret_cast<const char*>(aArgs.args[0]);
auto path2 = reinterpret_cast<const char*>(aArgs.args[1]);
return broker->Rename(path, path2);
}
static intptr_t MkdirTrap(ArgsRef aArgs, void* aux) {
auto broker = static_cast<SandboxBrokerClient*>(aux);
auto path = reinterpret_cast<const char*>(aArgs.args[0]);
@ -594,8 +615,14 @@ public:
return Trap(StatAtTrap, mBroker);
case __NR_chmod:
return Trap(ChmodTrap, mBroker);
case __NR_link:
return Trap(LinkTrap, mBroker);
case __NR_mkdir:
return Trap(MkdirTrap, mBroker);
case __NR_symlink:
return Trap(SymlinkTrap, mBroker);
case __NR_rename:
return Trap(RenameTrap, mBroker);
case __NR_rmdir:
return Trap(RmdirTrap, mBroker);
case __NR_unlink:
@ -614,7 +641,10 @@ public:
CASES_FOR_lstat:
CASES_FOR_fstatat:
case __NR_chmod:
case __NR_link:
case __NR_mkdir:
case __NR_symlink:
case __NR_rename:
case __NR_rmdir:
case __NR_unlink:
case __NR_readlink:
@ -811,6 +841,9 @@ public:
case __NR_fallocate:
return Allow();
case __NR_get_mempolicy:
return Allow();
#endif // DESKTOP
#ifdef __NR_getrandom

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

@ -486,6 +486,19 @@ DoStat(const char* aPath, void* aBuff, int aFlags)
return statsyscall(aPath, (statstruct*)aBuff);
}
static int
DoLink(const char* aPath, const char* aPath2,
SandboxBrokerCommon::Operation aOper)
{
if (aOper == SandboxBrokerCommon::Operation::SANDBOX_FILE_LINK) {
return link(aPath, aPath2);
}
if (aOper == SandboxBrokerCommon::Operation::SANDBOX_FILE_SYMLINK) {
return symlink(aPath, aPath2);
}
MOZ_CRASH("SandboxBroker: Unknown link operation");
}
size_t
SandboxBroker::ConvertToRealPath(char* aPath, size_t aBufSize, size_t aPathLen)
{
@ -574,7 +587,12 @@ SandboxBroker::ThreadMain(void)
while (true) {
struct iovec ios[2];
char recvBuf[kMaxPathLen + 1];
// We will receive the path strings in 1 buffer and split them back up.
char recvBuf[2 * (kMaxPathLen + 1)];
char pathBuf[kMaxPathLen + 1];
char pathBuf2[kMaxPathLen + 1];
size_t pathLen = 0;
size_t pathLen2 = 0;
char respBuf[kMaxPathLen + 1]; // Also serves as struct stat
Request req;
Response resp;
@ -583,10 +601,13 @@ SandboxBroker::ThreadMain(void)
// Make sure stat responses fit in the response buffer
MOZ_ASSERT((kMaxPathLen + 1) > sizeof(struct stat));
// This makes our string handling below a bit less error prone.
memset(recvBuf, 0, sizeof(recvBuf));
ios[0].iov_base = &req;
ios[0].iov_len = sizeof(req);
ios[1].iov_base = recvBuf;
ios[1].iov_len = sizeof(recvBuf) - 1;
ios[1].iov_len = sizeof(recvBuf);
const ssize_t recvd = RecvWithFd(mFileDesc, ios, 2, &respfd);
if (recvd == 0) {
@ -618,6 +639,7 @@ SandboxBroker::ThreadMain(void)
// Initialize the response with the default failure.
memset(&resp, 0, sizeof(resp));
memset(&respBuf, 0, sizeof(respBuf));
resp.mError = -EACCES;
ios[0].iov_base = &resp;
ios[0].iov_len = sizeof(resp);
@ -625,28 +647,62 @@ SandboxBroker::ThreadMain(void)
ios[1].iov_len = 0;
int openedFd = -1;
size_t origPathLen = static_cast<size_t>(recvd) - sizeof(req);
// Null-terminate to get a C-style string.
MOZ_RELEASE_ASSERT(origPathLen < sizeof(recvBuf));
recvBuf[origPathLen] = '\0';
// Clear permissions
int perms;
// Look up the pathname but first translate relative paths.
// (Make a copy so we can get back the original path if needed.)
char pathBuf[kMaxPathLen + 1];
base::strlcpy(pathBuf, recvBuf, sizeof(pathBuf));
size_t pathLen = ConvertToRealPath(pathBuf, sizeof(pathBuf), origPathLen);
int perms = mPolicy->Lookup(nsDependentCString(pathBuf, pathLen));
// Find end of first string, make sure the buffer is still
// 0 terminated.
size_t recvBufLen = static_cast<size_t>(recvd) - sizeof(req);
if (recvBufLen > 0 && recvBuf[recvBufLen - 1] != 0) {
SANDBOX_LOG_ERROR("corrupted path buffer from pid %d", mChildPid);
shutdown(mFileDesc, SHUT_RD);
break;
}
// We don't have read permissions on the requested dir.
// Did we arrive from a symlink in a path that is not writable?
// Then try to figure out the original path and see if that is readable.
if (!(perms & MAY_READ)) {
// Work on the original path,
// this reverses ConvertToRealPath above.
int symlinkPerms = SymlinkPermissions(recvBuf, origPathLen);
if (symlinkPerms > 0) {
perms = symlinkPerms;
// First path should fit in maximum path length buffer.
size_t first_len = strlen(recvBuf);
if (first_len <= kMaxPathLen) {
strcpy(pathBuf, recvBuf);
// Skip right over the terminating 0, and try to copy in the
// second path, if any. If there's no path, this will hit a
// 0 immediately (we nulled the buffer before receiving).
// We do not assume the second path is 0-terminated, this is
// enforced below.
strncpy(pathBuf2, recvBuf + first_len + 1, kMaxPathLen + 1);
// First string is guaranteed to be 0-terminated.
pathLen = first_len;
// Look up the first pathname but first translate relative paths.
pathLen = ConvertToRealPath(pathBuf, sizeof(pathBuf), pathLen);
perms = mPolicy->Lookup(nsDependentCString(pathBuf, pathLen));
// We don't have read permissions on the requested dir.
// Did we arrive from a symlink in a path that is not writable?
// Then try to figure out the original path and see if that is readable.
if (!(perms & MAY_READ)) {
// Work on the original path,
// this reverses ConvertToRealPath above.
int symlinkPerms = SymlinkPermissions(recvBuf, first_len);
if (symlinkPerms > 0) {
perms = symlinkPerms;
}
}
// Same for the second path.
pathLen2 = strnlen(pathBuf2, kMaxPathLen);
if (pathLen2 > 0) {
// Force 0 termination.
pathBuf2[pathLen2] = '\0';
pathLen2 = ConvertToRealPath(pathBuf2, sizeof(pathBuf2), pathLen2);
int perms2 = mPolicy->Lookup(nsDependentCString(pathBuf2, pathLen2));
// Take the intersection of the permissions for both paths.
perms &= perms2;
}
} else {
// Failed to receive intelligible paths.
perms = 0;
}
// And now perform the operation if allowed.
@ -711,6 +767,31 @@ SandboxBroker::ThreadMain(void)
}
break;
case SANDBOX_FILE_LINK:
case SANDBOX_FILE_SYMLINK:
if (permissive || AllowOperation(W_OK, perms)) {
if (DoLink(pathBuf, pathBuf2, req.mOp) == 0) {
resp.mError = 0;
} else {
resp.mError = -errno;
}
} else {
AuditDenial(req.mOp, req.mFlags, perms, pathBuf);
}
break;
case SANDBOX_FILE_RENAME:
if (permissive || AllowOperation(W_OK, perms)) {
if (rename(pathBuf, pathBuf2) == 0) {
resp.mError = 0;
} else {
resp.mError = -errno;
}
} else {
AuditDenial(req.mOp, req.mFlags, perms, pathBuf);
}
break;
case SANDBOX_FILE_MKDIR:
if (permissive || AllowOperation(W_OK | X_OK, perms)) {
if (mkdir(pathBuf, req.mFlags) == 0) {
@ -756,12 +837,9 @@ SandboxBroker::ThreadMain(void)
case SANDBOX_FILE_READLINK:
if (permissive || AllowOperation(R_OK, perms)) {
ssize_t respSize = readlink(pathBuf, (char*)&respBuf, sizeof(respBuf) - 1);
ssize_t respSize = readlink(pathBuf, (char*)&respBuf, sizeof(respBuf));
if (respSize >= 0) {
if (respSize > 0) {
// Null-terminate for nsDependentCString.
MOZ_RELEASE_ASSERT(static_cast<size_t>(respSize) < sizeof(respBuf));
respBuf[respSize] = '\0';
if (respSize > 0) {
// Record the mapping so we can invert the file to the original
// symlink.
nsDependentCString orig(pathBuf, pathLen);

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

@ -30,7 +30,10 @@ public:
SANDBOX_FILE_ACCESS,
SANDBOX_FILE_STAT,
SANDBOX_FILE_CHMOD,
SANDBOX_FILE_LINK,
SANDBOX_FILE_SYMLINK,
SANDBOX_FILE_MKDIR,
SANDBOX_FILE_RENAME,
SANDBOX_FILE_RMDIR,
SANDBOX_FILE_UNLINK,
SANDBOX_FILE_READLINK,

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

@ -231,9 +231,7 @@ UniquePtr<SandboxBroker::Policy>
SandboxBrokerPolicyFactory::GetContentPolicy(int aPid, bool aFileProcess)
{
// Policy entries that vary per-process (currently the only reason
// that can happen is because they contain the pid) are added here,
// as well as entries that depend on preferences or paths not available
// in early startup.
// that can happen is because they contain the pid) are added here.
MOZ_ASSERT(NS_IsMainThread());
// File broker usage is controlled through a pref.
@ -274,11 +272,6 @@ SandboxBrokerPolicyFactory::GetContentPolicy(int aPid, bool aFileProcess)
policy->AddPath(rdonly, nsPrintfCString("/proc/%d/statm", aPid).get());
policy->AddPath(rdonly, nsPrintfCString("/proc/%d/smaps", aPid).get());
// Bug 1384804, notably comment 15
// Used by libnuma, included by x265/ffmpeg, who falls back
// to get_mempolicy if this fails
policy->AddPath(rdonly, nsPrintfCString("/proc/%d/status", aPid).get());
// userContent.css and the extensions dir sit in the profile, which is
// normally blocked and we can't get the profile dir earlier in startup,
// so this must happen here.

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

@ -64,9 +64,18 @@ protected:
int Chmod(const char* aPath, int aMode) {
return mClient->Chmod(aPath, aMode);
}
int Link(const char* aPath, const char* bPath) {
return mClient->Link(aPath, bPath);
}
int Mkdir(const char* aPath, int aMode) {
return mClient->Mkdir(aPath, aMode);
}
int Symlink(const char* aPath, const char* bPath) {
return mClient->Symlink(aPath, bPath);
}
int Rename(const char* aPath, const char* bPath) {
return mClient->Rename(aPath, bPath);
}
int Rmdir(const char* aPath) {
return mClient->Rmdir(aPath);
}
@ -271,6 +280,43 @@ TEST_F(SandboxBrokerTest, Chmod)
PrePostTestCleanup();
}
TEST_F(SandboxBrokerTest, Link)
{
PrePostTestCleanup();
int fd = Open("/tmp/blublu", O_WRONLY | O_CREAT);
ASSERT_GE(fd, 0) << "Opening /tmp/blublu for writing failed.";
close(fd);
ASSERT_EQ(0, Link("/tmp/blublu", "/tmp/blublublu"));
EXPECT_EQ(0, Access("/tmp/blublublu", F_OK));
// Not whitelisted target path
EXPECT_EQ(-EACCES, Link("/tmp/blublu", "/tmp/nope"));
EXPECT_EQ(0, unlink("/tmp/blublublu"));
EXPECT_EQ(0, unlink("/tmp/blublu"));
PrePostTestCleanup();
}
TEST_F(SandboxBrokerTest, Symlink)
{
PrePostTestCleanup();
int fd = Open("/tmp/blublu", O_WRONLY | O_CREAT);
ASSERT_GE(fd, 0) << "Opening /tmp/blublu for writing failed.";
close(fd);
ASSERT_EQ(0, Symlink("/tmp/blublu", "/tmp/blublublu"));
EXPECT_EQ(0, Access("/tmp/blublublu", F_OK));
statstruct aStat;
ASSERT_EQ(0, lstatsyscall("/tmp/blublublu", &aStat));
EXPECT_EQ((mode_t)S_IFLNK, aStat.st_mode & S_IFMT);
// Not whitelisted target path
EXPECT_EQ(-EACCES, Symlink("/tmp/blublu", "/tmp/nope"));
EXPECT_EQ(0, unlink("/tmp/blublublu"));
EXPECT_EQ(0, unlink("/tmp/blublu"));
PrePostTestCleanup();
}
TEST_F(SandboxBrokerTest, Mkdir)
{
PrePostTestCleanup();
@ -290,6 +336,24 @@ TEST_F(SandboxBrokerTest, Mkdir)
PrePostTestCleanup();
}
TEST_F(SandboxBrokerTest, Rename)
{
PrePostTestCleanup();
ASSERT_EQ(0, mkdir("/tmp/blublu", 0600))
<< "Creating dir /tmp/blublu failed.";
EXPECT_EQ(0, Access("/tmp/blublu", F_OK));
ASSERT_EQ(0, Rename("/tmp/blublu", "/tmp/blublublu"));
EXPECT_EQ(0, Access("/tmp/blublublu", F_OK));
EXPECT_EQ(-ENOENT , Access("/tmp/blublu", F_OK));
// Not whitelisted target path
EXPECT_EQ(-EACCES, Rename("/tmp/blublublu", "/tmp/nope"))
<< "Renaming dir without write access succeed.";
EXPECT_EQ(0, rmdir("/tmp/blublublu"));
PrePostTestCleanup();
}
TEST_F(SandboxBrokerTest, Rmdir)
{
PrePostTestCleanup();
@ -332,7 +396,7 @@ TEST_F(SandboxBrokerTest, Readlink)
int fd = Open("/tmp/blublu", O_WRONLY | O_CREAT);
ASSERT_GE(fd, 0) << "Opening /tmp/blublu for writing failed.";
close(fd);
ASSERT_EQ(0, symlink("/tmp/blublu", "/tmp/blublublu"));
ASSERT_EQ(0, Symlink("/tmp/blublu", "/tmp/blublublu"));
EXPECT_EQ(0, Access("/tmp/blublublu", F_OK));
char linkBuff[256];
EXPECT_EQ(11, Readlink("/tmp/blublublu", linkBuff, sizeof(linkBuff)));

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

@ -29,7 +29,6 @@ XPIDL_SOURCES += [
'mozIStorageService.idl',
'mozIStorageStatement.idl',
'mozIStorageStatementCallback.idl',
'mozIStorageStatementParams.idl',
'mozIStorageVacuumParticipant.idl',
'mozIStorageValueArray.idl',
]
@ -47,6 +46,8 @@ EXPORTS.mozilla += [
# NOTE When adding something to this list, you probably need to add it to the
# storage.h file too.
EXPORTS.mozilla.storage += [
'mozStorageAsyncStatementParams.h',
'mozStorageStatementParams.h',
'mozStorageStatementRow.h',
'StatementCache.h',
'Variant.h',

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

@ -1,11 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nsISupports.idl"
[scriptable, uuid(e65fe6e2-2643-463c-97e2-27665efe2386)]
interface mozIStorageStatementParams : nsISupports {
// Magic interface for parameter setting that implements nsIXPCScriptable.
};

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

@ -18,12 +18,11 @@
#include "StorageBaseStatementInternal.h"
#include "mozilla/Attributes.h"
class nsIXPConnectJSObjectHolder;
namespace mozilla {
namespace storage {
class AsyncStatementJSHelper;
class AsyncStatementParamsHolder;
class Connection;
class AsyncStatement final : public mozIStorageAsyncStatement
@ -87,7 +86,7 @@ private:
/**
* Caches the JS 'params' helper for this statement.
*/
nsMainThreadPtrHandle<nsIXPConnectJSObjectHolder> mStatementParamsHolder;
nsMainThreadPtrHandle<AsyncStatementParamsHolder> mStatementParamsHolder;
/**
* Have we been explicitly finalized by the user?

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

@ -33,7 +33,6 @@ AsyncStatementJSHelper::getParams(AsyncStatement *aStatement,
JS::Value *_params)
{
MOZ_ASSERT(NS_IsMainThread());
nsresult rv;
#ifdef DEBUG
int32_t state;
@ -42,32 +41,32 @@ AsyncStatementJSHelper::getParams(AsyncStatement *aStatement,
"Invalid state to get the params object - all calls will fail!");
#endif
JS::RootedObject scope(aCtx, aScopeObj);
if (!aStatement->mStatementParamsHolder) {
nsCOMPtr<mozIStorageStatementParams> params =
new AsyncStatementParams(aStatement);
dom::GlobalObject global(aCtx, scope);
if (global.Failed()) {
return NS_ERROR_UNEXPECTED;
}
nsCOMPtr<nsPIDOMWindowInner> window = do_QueryInterface(global.GetAsSupports());
RefPtr<AsyncStatementParams> params(new AsyncStatementParams(window, aStatement));
NS_ENSURE_TRUE(params, NS_ERROR_OUT_OF_MEMORY);
JS::RootedObject scope(aCtx, aScopeObj);
nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
nsCOMPtr<nsIXPConnect> xpc(Service::getXPConnect());
rv = xpc->WrapNativeHolder(
aCtx,
::JS_GetGlobalForObject(aCtx, scope),
params,
NS_GET_IID(mozIStorageStatementParams),
getter_AddRefs(holder)
);
NS_ENSURE_SUCCESS(rv, rv);
RefPtr<AsyncStatementParamsHolder> paramsHolder =
new AsyncStatementParamsHolder(holder);
RefPtr<AsyncStatementParamsHolder> paramsHolder = new AsyncStatementParamsHolder(params);
NS_ENSURE_TRUE(paramsHolder, NS_ERROR_OUT_OF_MEMORY);
aStatement->mStatementParamsHolder =
new nsMainThreadPtrHolder<nsIXPConnectJSObjectHolder>(
"AsyncStatement::mStatementParamsHolder", paramsHolder);
new nsMainThreadPtrHolder<AsyncStatementParamsHolder>(
"Statement::mStatementParamsHolder", paramsHolder);
}
JS::Rooted<JSObject*> obj(aCtx);
obj = aStatement->mStatementParamsHolder->GetJSObject();
NS_ENSURE_STATE(obj);
RefPtr<AsyncStatementParams> params(aStatement->mStatementParamsHolder->Get());
JSObject* obj = params->WrapObject(aCtx, nullptr);
if (!obj) {
return NS_ERROR_UNEXPECTED;
}
_params->setObject(*obj);
return NS_OK;
@ -130,30 +129,14 @@ AsyncStatementJSHelper::Resolve(nsIXPConnectWrappedNative *aWrapper,
////////////////////////////////////////////////////////////////////////////////
//// AsyncStatementParamsHolder
NS_IMPL_ISUPPORTS(AsyncStatementParamsHolder, nsIXPConnectJSObjectHolder);
JSObject*
AsyncStatementParamsHolder::GetJSObject()
{
return mHolder->GetJSObject();
}
AsyncStatementParamsHolder::AsyncStatementParamsHolder(nsIXPConnectJSObjectHolder* aHolder)
: mHolder(aHolder)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(mHolder);
}
NS_IMPL_ISUPPORTS0(AsyncStatementParamsHolder);
AsyncStatementParamsHolder::~AsyncStatementParamsHolder()
{
MOZ_ASSERT(NS_IsMainThread());
// We are considered dead at this point, so any wrappers for row or params
// need to lose their reference to the statement.
nsCOMPtr<nsIXPConnectWrappedNative> wrapper = do_QueryInterface(mHolder);
nsCOMPtr<mozIStorageStatementParams> iObj = do_QueryWrappedNative(wrapper);
AsyncStatementParams *obj = static_cast<AsyncStatementParams *>(iObj.get());
obj->mStatement = nullptr;
mParams->mStatement = nullptr;
}
} // namespace storage

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

@ -10,11 +10,12 @@
#include "nsIXPCScriptable.h"
#include "nsIXPConnect.h"
class AsyncStatement;
namespace mozilla {
namespace storage {
class AsyncStatement;
class AsyncStatementParams;
/**
* A modified version of StatementJSHelper that only exposes the async-specific
* 'params' helper. We do not expose 'row' or 'step' as they do not apply to
@ -35,17 +36,24 @@ private:
* For cycle-avoidance reasons they do not hold reference-counted references,
* so it is important we do this.
*/
class AsyncStatementParamsHolder final : public nsIXPConnectJSObjectHolder
{
class AsyncStatementParamsHolder final : public nsISupports {
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIXPCONNECTJSOBJECTHOLDER
explicit AsyncStatementParamsHolder(nsIXPConnectJSObjectHolder* aHolder);
explicit AsyncStatementParamsHolder(AsyncStatementParams* aParams)
: mParams(aParams)
{
}
AsyncStatementParams* Get() const {
MOZ_ASSERT(mParams);
return mParams;
}
private:
virtual ~AsyncStatementParamsHolder();
nsCOMPtr<nsIXPConnectJSObjectHolder> mHolder;
RefPtr<AsyncStatementParams> mParams;
};
} // namespace storage

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

@ -4,19 +4,14 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nsJSUtils.h"
#include "nsMemory.h"
#include "nsString.h"
#include "nsCOMPtr.h"
#include "nsJSUtils.h"
#include "jsapi.h"
#include "mozilla/dom/MozStorageAsyncStatementParamsBinding.h"
#include "mozStoragePrivateHelpers.h"
#include "mozStorageAsyncStatement.h"
#include "mozStorageAsyncStatementParams.h"
#include "mozIStorageStatement.h"
#include "xpc_make_class.h"
namespace mozilla {
namespace storage {
@ -24,107 +19,109 @@ namespace storage {
////////////////////////////////////////////////////////////////////////////////
//// AsyncStatementParams
AsyncStatementParams::AsyncStatementParams(AsyncStatement *aStatement)
: mStatement(aStatement)
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(AsyncStatementParams, mWindow)
NS_INTERFACE_TABLE_HEAD(AsyncStatementParams)
NS_WRAPPERCACHE_INTERFACE_TABLE_ENTRY
NS_INTERFACE_TABLE(AsyncStatementParams, nsISupports)
NS_INTERFACE_TABLE_TO_MAP_SEGUE_CYCLE_COLLECTION(AsyncStatementParams)
NS_INTERFACE_MAP_END
NS_IMPL_CYCLE_COLLECTING_ADDREF(AsyncStatementParams)
NS_IMPL_CYCLE_COLLECTING_RELEASE(AsyncStatementParams)
AsyncStatementParams::AsyncStatementParams(nsPIDOMWindowInner* aWindow, AsyncStatement *aStatement)
: mWindow(aWindow),
mStatement(aStatement)
{
NS_ASSERTION(mStatement != nullptr, "mStatement is null");
}
NS_IMPL_ISUPPORTS(
AsyncStatementParams
, mozIStorageStatementParams
, nsIXPCScriptable
)
////////////////////////////////////////////////////////////////////////////////
//// nsIXPCScriptable
#define XPC_MAP_CLASSNAME AsyncStatementParams
#define XPC_MAP_QUOTED_CLASSNAME "AsyncStatementParams"
#define XPC_MAP_FLAGS (XPC_SCRIPTABLE_WANT_SETPROPERTY | \
XPC_SCRIPTABLE_WANT_RESOLVE | \
XPC_SCRIPTABLE_ALLOW_PROP_MODS_DURING_RESOLVE)
#include "xpc_map_end.h"
NS_IMETHODIMP
AsyncStatementParams::SetProperty(
nsIXPConnectWrappedNative *aWrapper,
JSContext *aCtx,
JSObject *aScopeObj,
jsid aId,
JS::Value *_vp,
bool *_retval
)
JSObject*
AsyncStatementParams::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
{
NS_ENSURE_TRUE(mStatement, NS_ERROR_NOT_INITIALIZED);
if (JSID_IS_INT(aId)) {
int idx = JSID_TO_INT(aId);
nsCOMPtr<nsIVariant> variant(convertJSValToVariant(aCtx, *_vp));
NS_ENSURE_TRUE(variant, NS_ERROR_UNEXPECTED);
nsresult rv = mStatement->BindByIndex(idx, variant);
NS_ENSURE_SUCCESS(rv, rv);
}
else if (JSID_IS_STRING(aId)) {
JSString *str = JSID_TO_STRING(aId);
nsAutoJSString autoStr;
if (!autoStr.init(aCtx, str)) {
return NS_ERROR_FAILURE;
}
NS_ConvertUTF16toUTF8 name(autoStr);
nsCOMPtr<nsIVariant> variant(convertJSValToVariant(aCtx, *_vp));
NS_ENSURE_TRUE(variant, NS_ERROR_UNEXPECTED);
nsresult rv = mStatement->BindByName(name, variant);
NS_ENSURE_SUCCESS(rv, rv);
}
else {
return NS_ERROR_INVALID_ARG;
}
*_retval = true;
return NS_OK;
return dom::MozStorageAsyncStatementParamsBinding::Wrap(aCx, this, aGivenProto);
}
NS_IMETHODIMP
AsyncStatementParams::Resolve(nsIXPConnectWrappedNative *aWrapper,
JSContext *aCtx,
JSObject *aScopeObj,
jsid aId,
bool *aResolvedp,
bool *_retval)
void
AsyncStatementParams::NamedGetter(JSContext* aCx,
const nsAString& aName,
bool& aFound,
JS::MutableHandle<JS::Value> aResult,
mozilla::ErrorResult& aRv)
{
JS::Rooted<JSObject*> scopeObj(aCtx, aScopeObj);
NS_ENSURE_TRUE(mStatement, NS_ERROR_NOT_INITIALIZED);
// We do not throw at any point after this because we want to allow the
// prototype chain to be checked for the property.
bool resolved = false;
bool ok = true;
if (JSID_IS_INT(aId)) {
uint32_t idx = JSID_TO_INT(aId);
// All indexes are good because we don't know how many parameters there
// really are.
ok = ::JS_DefineElement(aCtx, scopeObj, idx, JS::UndefinedHandleValue,
JSPROP_RESOLVING);
resolved = true;
}
else if (JSID_IS_STRING(aId)) {
// We are unable to tell if there's a parameter with this name and so
// we must assume that there is. This screws the rest of the prototype
// chain, but people really shouldn't be depending on this anyways.
JS::Rooted<jsid> id(aCtx, aId);
ok = ::JS_DefinePropertyById(aCtx, scopeObj, id, JS::UndefinedHandleValue,
JSPROP_RESOLVING);
resolved = true;
if (!mStatement) {
aRv.Throw(NS_ERROR_NOT_INITIALIZED);
return;
}
*_retval = ok;
*aResolvedp = resolved && ok;
return NS_OK;
// Unfortunately there's no API that lets us return the parameter value.
aFound = false;
}
void
AsyncStatementParams::NamedSetter(JSContext* aCx,
const nsAString& aName,
JS::Handle<JS::Value> aValue,
mozilla::ErrorResult& aRv)
{
if (!mStatement) {
aRv.Throw(NS_ERROR_NOT_INITIALIZED);
return;
}
NS_ConvertUTF16toUTF8 name(aName);
nsCOMPtr<nsIVariant> variant(convertJSValToVariant(aCx, aValue));
if (!variant) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return;
}
aRv = mStatement->BindByName(name, variant);
}
void
AsyncStatementParams::GetSupportedNames(nsTArray<nsString>& aNames)
{
// We don't know how many params there are, so we can't implement this for
// AsyncStatementParams.
}
void
AsyncStatementParams::IndexedGetter(JSContext* aCx,
uint32_t aIndex,
bool& aFound,
JS::MutableHandle<JS::Value> aResult,
mozilla::ErrorResult& aRv)
{
if (!mStatement) {
aRv.Throw(NS_ERROR_NOT_INITIALIZED);
return;
}
// Unfortunately there's no API that lets us return the parameter value.
aFound = false;
}
void
AsyncStatementParams::IndexedSetter(JSContext* aCx,
uint32_t aIndex,
JS::Handle<JS::Value> aValue,
mozilla::ErrorResult& aRv)
{
if (!mStatement) {
aRv.Throw(NS_ERROR_NOT_INITIALIZED);
return;
}
nsCOMPtr<nsIVariant> variant(convertJSValToVariant(aCx, aValue));
if (!variant) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return;
}
aRv = mStatement->BindByIndex(aIndex, variant);
}
} // namespace storage

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

@ -7,34 +7,68 @@
#ifndef mozilla_storage_mozStorageAsyncStatementParams_h_
#define mozilla_storage_mozStorageAsyncStatementParams_h_
#include "mozIStorageStatementParams.h"
#include "nsIXPCScriptable.h"
#include "mozilla/Attributes.h"
#include "mozilla/ErrorResult.h"
#include "nsPIDOMWindow.h"
#include "nsWrapperCache.h"
namespace mozilla {
namespace storage {
class AsyncStatement;
/*
* Since mozIStorageStatementParams is just a tagging interface we do not have
* an async variant.
*/
class AsyncStatementParams final : public mozIStorageStatementParams
, public nsIXPCScriptable
class AsyncStatementParams final : public nsISupports
, public nsWrapperCache
{
public:
explicit AsyncStatementParams(AsyncStatement *aStatement);
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(AsyncStatementParams)
// interfaces
NS_DECL_ISUPPORTS
NS_DECL_MOZISTORAGESTATEMENTPARAMS
NS_DECL_NSIXPCSCRIPTABLE
explicit AsyncStatementParams(nsPIDOMWindowInner* aWindow, AsyncStatement* aStatement);
protected:
void NamedGetter(JSContext* aCx,
const nsAString& aName,
bool& aFound,
JS::MutableHandle<JS::Value> aResult,
mozilla::ErrorResult& aRv);
void NamedSetter(JSContext* aCx,
const nsAString& aName,
JS::Handle<JS::Value> aValue,
mozilla::ErrorResult& aRv);
uint32_t Length() const {
// WebIDL requires a .length property when there's an indexed getter.
// Unfortunately we don't know how many params there are in the async case,
// so we have to lie.
return UINT16_MAX;
}
void IndexedGetter(JSContext* aCx,
uint32_t aIndex,
bool& aFound,
JS::MutableHandle<JS::Value> aResult,
mozilla::ErrorResult& aRv);
void IndexedSetter(JSContext* aCx,
uint32_t aIndex,
JS::Handle<JS::Value> aValue,
mozilla::ErrorResult& aRv);
void GetSupportedNames(nsTArray<nsString>& aNames);
JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
nsPIDOMWindowInner* GetParentObject() const
{
return mWindow;
}
private:
virtual ~AsyncStatementParams() {}
AsyncStatement *mStatement;
nsCOMPtr<nsPIDOMWindowInner> mWindow;
AsyncStatement* mStatement;
friend class AsyncStatementParamsHolder;
};

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