mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-13 13:25:37 +00:00
Merge inbound to central, a=merge
This commit is contained in:
commit
0246d86e61
@ -1450,10 +1450,20 @@ WebConsoleFrame.prototype = {
|
||||
errorMessage = errorMessage.initial;
|
||||
}
|
||||
|
||||
let displayOrigin = aScriptError.sourceName;
|
||||
|
||||
// TLS errors are related to the connection and not the resource; therefore
|
||||
// it makes sense to only display the protcol, host and port (prePath).
|
||||
// This also means messages are grouped for a single origin.
|
||||
if (aScriptError.category && aScriptError.category == "SHA-1 Signature") {
|
||||
let sourceURI = Services.io.newURI(aScriptError.sourceName, null, null).QueryInterface(Ci.nsIURL);
|
||||
displayOrigin = sourceURI.prePath;
|
||||
}
|
||||
|
||||
// Create a new message
|
||||
let msg = new Messages.Simple(errorMessage, {
|
||||
location: {
|
||||
url: aScriptError.sourceName,
|
||||
url: displayOrigin,
|
||||
line: aScriptError.lineNumber,
|
||||
column: aScriptError.columnNumber
|
||||
},
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include "nsBidiUtils.h"
|
||||
#include "nsUnicharUtils.h"
|
||||
#include "nsUTF8Utils.h"
|
||||
#include "mozilla/CheckedInt.h"
|
||||
#include "mozilla/MemoryReporting.h"
|
||||
#include "mozilla/SSE.h"
|
||||
#include "nsTextFragmentImpl.h"
|
||||
@ -30,6 +31,8 @@ static char* sSpaceSharedString[TEXTFRAG_MAX_NEWLINES + 1];
|
||||
static char* sTabSharedString[TEXTFRAG_MAX_NEWLINES + 1];
|
||||
static char sSingleCharSharedString[256];
|
||||
|
||||
using mozilla::CheckedUint32;
|
||||
|
||||
// static
|
||||
nsresult
|
||||
nsTextFragment::Init()
|
||||
@ -105,12 +108,15 @@ nsTextFragment::operator=(const nsTextFragment& aOther)
|
||||
m1b = aOther.m1b; // This will work even if aOther is using m2b
|
||||
}
|
||||
else {
|
||||
size_t m2bSize = aOther.mState.mLength *
|
||||
(aOther.mState.mIs2b ? sizeof(char16_t) : sizeof(char));
|
||||
CheckedUint32 m2bSize = aOther.mState.mLength;
|
||||
m2bSize *= (aOther.mState.mIs2b ? sizeof(char16_t) : sizeof(char));
|
||||
m2b = nullptr;
|
||||
if (m2bSize.isValid()) {
|
||||
m2b = static_cast<char16_t*>(malloc(m2bSize.value()));
|
||||
}
|
||||
|
||||
m2b = static_cast<char16_t*>(malloc(m2bSize));
|
||||
if (m2b) {
|
||||
memcpy(m2b, aOther.m2b, m2bSize);
|
||||
memcpy(m2b, aOther.m2b, m2bSize.value());
|
||||
} else {
|
||||
// allocate a buffer for a single REPLACEMENT CHARACTER
|
||||
m2b = static_cast<char16_t*>(moz_xmalloc(sizeof(char16_t)));
|
||||
@ -255,12 +261,17 @@ nsTextFragment::SetTo(const char16_t* aBuffer, int32_t aLength, bool aUpdateBidi
|
||||
|
||||
if (first16bit != -1) { // aBuffer contains no non-8bit character
|
||||
// Use ucs2 storage because we have to
|
||||
size_t m2bSize = aLength * sizeof(char16_t);
|
||||
m2b = (char16_t *)malloc(m2bSize);
|
||||
CheckedUint32 m2bSize = aLength;
|
||||
m2bSize *= sizeof(char16_t);
|
||||
if (!m2bSize.isValid()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
m2b = static_cast<char16_t*>(malloc(m2bSize.value()));
|
||||
if (!m2b) {
|
||||
return false;
|
||||
}
|
||||
memcpy(m2b, aBuffer, m2bSize);
|
||||
memcpy(m2b, aBuffer, m2bSize.value());
|
||||
|
||||
mState.mIs2b = true;
|
||||
if (aUpdateBidi) {
|
||||
@ -269,7 +280,7 @@ nsTextFragment::SetTo(const char16_t* aBuffer, int32_t aLength, bool aUpdateBidi
|
||||
|
||||
} else {
|
||||
// Use 1 byte storage because we can
|
||||
char* buff = (char *)malloc(aLength * sizeof(char));
|
||||
char* buff = static_cast<char*>(malloc(aLength));
|
||||
if (!buff) {
|
||||
return false;
|
||||
}
|
||||
@ -325,9 +336,21 @@ nsTextFragment::Append(const char16_t* aBuffer, uint32_t aLength, bool aUpdateBi
|
||||
|
||||
// Should we optimize for aData.Length() == 0?
|
||||
|
||||
CheckedUint32 length = mState.mLength;
|
||||
length += aLength;
|
||||
|
||||
if (!length.isValid()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (mState.mIs2b) {
|
||||
length *= sizeof(char16_t);
|
||||
if (!length.isValid()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Already a 2-byte string so the result will be too
|
||||
char16_t* buff = (char16_t*)realloc(m2b, (mState.mLength + aLength) * sizeof(char16_t));
|
||||
char16_t* buff = static_cast<char16_t*>(realloc(m2b, length.value()));
|
||||
if (!buff) {
|
||||
return false;
|
||||
}
|
||||
@ -347,10 +370,14 @@ nsTextFragment::Append(const char16_t* aBuffer, uint32_t aLength, bool aUpdateBi
|
||||
int32_t first16bit = FirstNon8Bit(aBuffer, aBuffer + aLength);
|
||||
|
||||
if (first16bit != -1) { // aBuffer contains no non-8bit character
|
||||
length *= sizeof(char16_t);
|
||||
if (!length.isValid()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// The old data was 1-byte, but the new is not so we have to expand it
|
||||
// all to 2-byte
|
||||
char16_t* buff =
|
||||
(char16_t*)malloc((mState.mLength + aLength) * sizeof(char16_t));
|
||||
char16_t* buff = static_cast<char16_t*>(malloc(length.value()));
|
||||
if (!buff) {
|
||||
return false;
|
||||
}
|
||||
@ -380,14 +407,13 @@ nsTextFragment::Append(const char16_t* aBuffer, uint32_t aLength, bool aUpdateBi
|
||||
// The new and the old data is all 1-byte
|
||||
char* buff;
|
||||
if (mState.mInHeap) {
|
||||
buff = (char*)realloc(const_cast<char*>(m1b),
|
||||
(mState.mLength + aLength) * sizeof(char));
|
||||
buff = static_cast<char*>(realloc(const_cast<char*>(m1b), length.value()));
|
||||
if (!buff) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
buff = (char*)malloc((mState.mLength + aLength) * sizeof(char));
|
||||
buff = static_cast<char*>(malloc(length.value()));
|
||||
if (!buff) {
|
||||
return false;
|
||||
}
|
||||
|
@ -2349,28 +2349,33 @@ BackgroundRequestChild::Recv__delete__(const RequestResponse& aResponse)
|
||||
* BackgroundCursorChild
|
||||
******************************************************************************/
|
||||
|
||||
class BackgroundCursorChild::DelayedDeleteRunnable final
|
||||
class BackgroundCursorChild::DelayedActionRunnable final
|
||||
: public nsICancelableRunnable
|
||||
{
|
||||
using ActionFunc = void (BackgroundCursorChild::*)();
|
||||
|
||||
BackgroundCursorChild* mActor;
|
||||
nsRefPtr<IDBRequest> mRequest;
|
||||
ActionFunc mActionFunc;
|
||||
|
||||
public:
|
||||
explicit
|
||||
DelayedDeleteRunnable(BackgroundCursorChild* aActor)
|
||||
DelayedActionRunnable(BackgroundCursorChild* aActor, ActionFunc aActionFunc)
|
||||
: mActor(aActor)
|
||||
, mRequest(aActor->mRequest)
|
||||
, mActionFunc(aActionFunc)
|
||||
{
|
||||
MOZ_ASSERT(aActor);
|
||||
aActor->AssertIsOnOwningThread();
|
||||
MOZ_ASSERT(mRequest);
|
||||
MOZ_ASSERT(mActionFunc);
|
||||
}
|
||||
|
||||
// Does not need to be threadsafe since this only runs on one thread.
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
private:
|
||||
~DelayedDeleteRunnable()
|
||||
~DelayedActionRunnable()
|
||||
{ }
|
||||
|
||||
NS_DECL_NSIRUNNABLE
|
||||
@ -2510,7 +2515,8 @@ BackgroundCursorChild::HandleResponse(const void_t& aResponse)
|
||||
DispatchSuccessEvent(&helper);
|
||||
|
||||
if (!mCursor) {
|
||||
nsCOMPtr<nsIRunnable> deleteRunnable = new DelayedDeleteRunnable(this);
|
||||
nsCOMPtr<nsIRunnable> deleteRunnable = new DelayedActionRunnable(
|
||||
this, &BackgroundCursorChild::SendDeleteMeInternal);
|
||||
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(NS_DispatchToCurrentThread(deleteRunnable)));
|
||||
}
|
||||
}
|
||||
@ -2745,19 +2751,20 @@ DispatchMutableFileResult(IDBRequest* aRequest,
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS(BackgroundCursorChild::DelayedDeleteRunnable,
|
||||
NS_IMPL_ISUPPORTS(BackgroundCursorChild::DelayedActionRunnable,
|
||||
nsIRunnable,
|
||||
nsICancelableRunnable)
|
||||
|
||||
NS_IMETHODIMP
|
||||
BackgroundCursorChild::
|
||||
DelayedDeleteRunnable::Run()
|
||||
DelayedActionRunnable::Run()
|
||||
{
|
||||
MOZ_ASSERT(mActor);
|
||||
mActor->AssertIsOnOwningThread();
|
||||
MOZ_ASSERT(mRequest);
|
||||
MOZ_ASSERT(mActionFunc);
|
||||
|
||||
mActor->SendDeleteMeInternal();
|
||||
(mActor->*mActionFunc)();
|
||||
|
||||
mActor = nullptr;
|
||||
mRequest = nullptr;
|
||||
@ -2767,7 +2774,7 @@ DelayedDeleteRunnable::Run()
|
||||
|
||||
NS_IMETHODIMP
|
||||
BackgroundCursorChild::
|
||||
DelayedDeleteRunnable::Cancel()
|
||||
DelayedActionRunnable::Cancel()
|
||||
{
|
||||
if (NS_WARN_IF(!mActor)) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
@ -624,7 +624,7 @@ class BackgroundCursorChild final
|
||||
friend class BackgroundTransactionChild;
|
||||
friend class BackgroundVersionChangeTransactionChild;
|
||||
|
||||
class DelayedDeleteRunnable;
|
||||
class DelayedActionRunnable;
|
||||
|
||||
IDBRequest* mRequest;
|
||||
IDBTransaction* mTransaction;
|
||||
|
@ -7639,6 +7639,9 @@ protected:
|
||||
|
||||
virtual void
|
||||
Cleanup() override;
|
||||
|
||||
nsresult
|
||||
PopulateResponseFromStatement(DatabaseConnection::CachedStatement& aStmt);
|
||||
};
|
||||
|
||||
class Cursor::OpenOp final
|
||||
@ -13469,7 +13472,11 @@ TransactionBase::VerifyRequestParams(const CursorRequestParams& aParams) const
|
||||
break;
|
||||
|
||||
case CursorRequestParams::TAdvanceParams:
|
||||
break;
|
||||
if (NS_WARN_IF(aParams.get_AdvanceParams().count() == 0)) {
|
||||
ASSERT_UNLESS_FUZZING();
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
MOZ_CRASH("Should never get here!");
|
||||
@ -24435,6 +24442,91 @@ CursorOpBase::Cleanup()
|
||||
TransactionDatabaseOperationBase::Cleanup();
|
||||
}
|
||||
|
||||
nsresult
|
||||
Cursor::
|
||||
CursorOpBase::PopulateResponseFromStatement(
|
||||
DatabaseConnection::CachedStatement& aStmt)
|
||||
{
|
||||
Transaction()->AssertIsOnConnectionThread();
|
||||
MOZ_ASSERT(mResponse.type() == CursorResponse::T__None);
|
||||
MOZ_ASSERT(mFiles.IsEmpty());
|
||||
|
||||
nsresult rv = mCursor->mKey.SetFromStatement(aStmt, 0);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
switch (mCursor->mType) {
|
||||
case OpenCursorParams::TObjectStoreOpenCursorParams: {
|
||||
StructuredCloneReadInfo cloneInfo;
|
||||
rv = GetStructuredCloneReadInfoFromStatement(aStmt,
|
||||
2,
|
||||
1,
|
||||
mCursor->mFileManager,
|
||||
&cloneInfo);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
mResponse = ObjectStoreCursorResponse();
|
||||
|
||||
auto& response = mResponse.get_ObjectStoreCursorResponse();
|
||||
response.cloneInfo().data().SwapElements(cloneInfo.mData);
|
||||
response.key() = mCursor->mKey;
|
||||
|
||||
mFiles.SwapElements(cloneInfo.mFiles);
|
||||
break;
|
||||
}
|
||||
|
||||
case OpenCursorParams::TObjectStoreOpenKeyCursorParams: {
|
||||
mResponse = ObjectStoreKeyCursorResponse(mCursor->mKey);
|
||||
break;
|
||||
}
|
||||
|
||||
case OpenCursorParams::TIndexOpenCursorParams: {
|
||||
rv = mCursor->mObjectKey.SetFromStatement(aStmt, 1);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
StructuredCloneReadInfo cloneInfo;
|
||||
rv = GetStructuredCloneReadInfoFromStatement(aStmt,
|
||||
3,
|
||||
2,
|
||||
mCursor->mFileManager,
|
||||
&cloneInfo);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
mResponse = IndexCursorResponse();
|
||||
|
||||
auto& response = mResponse.get_IndexCursorResponse();
|
||||
response.cloneInfo().data().SwapElements(cloneInfo.mData);
|
||||
response.key() = mCursor->mKey;
|
||||
response.objectKey() = mCursor->mObjectKey;
|
||||
|
||||
mFiles.SwapElements(cloneInfo.mFiles);
|
||||
break;
|
||||
}
|
||||
|
||||
case OpenCursorParams::TIndexOpenKeyCursorParams: {
|
||||
rv = mCursor->mObjectKey.SetFromStatement(aStmt, 1);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
mResponse = IndexKeyCursorResponse(mCursor->mKey, mCursor->mObjectKey);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
MOZ_CRASH("Should never get here!");
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
Cursor::
|
||||
OpenOp::GetRangeKeyInfo(bool aLowerBound, Key* aKey, bool* aOpen)
|
||||
@ -24512,6 +24604,8 @@ OpenOp::DoObjectStoreDatabaseWork(DatabaseConnection* aConnection)
|
||||
MOZ_CRASH("Should never get here!");
|
||||
}
|
||||
|
||||
// Note: Changing the number or order of SELECT columns in the query will
|
||||
// require changes to CursorOpBase::PopulateResponseFromStatement.
|
||||
nsCString firstQuery =
|
||||
queryStart +
|
||||
keyRangeClause +
|
||||
@ -24549,17 +24643,7 @@ OpenOp::DoObjectStoreDatabaseWork(DatabaseConnection* aConnection)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
rv = mCursor->mKey.SetFromStatement(stmt, 0);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
StructuredCloneReadInfo cloneInfo;
|
||||
rv = GetStructuredCloneReadInfoFromStatement(stmt,
|
||||
2,
|
||||
1,
|
||||
mCursor->mFileManager,
|
||||
&cloneInfo);
|
||||
rv = PopulateResponseFromStatement(stmt);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
@ -24624,14 +24708,6 @@ OpenOp::DoObjectStoreDatabaseWork(DatabaseConnection* aConnection)
|
||||
directionClause +
|
||||
openLimit;
|
||||
|
||||
mResponse = ObjectStoreCursorResponse();
|
||||
|
||||
auto& response = mResponse.get_ObjectStoreCursorResponse();
|
||||
response.cloneInfo().data().SwapElements(cloneInfo.mData);
|
||||
response.key() = mCursor->mKey;
|
||||
|
||||
mFiles.SwapElements(cloneInfo.mFiles);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -24687,6 +24763,8 @@ OpenOp::DoObjectStoreKeyDatabaseWork(DatabaseConnection* aConnection)
|
||||
MOZ_CRASH("Should never get here!");
|
||||
}
|
||||
|
||||
// Note: Changing the number or order of SELECT columns in the query will
|
||||
// require changes to CursorOpBase::PopulateResponseFromStatement.
|
||||
nsCString firstQuery =
|
||||
queryStart +
|
||||
keyRangeClause +
|
||||
@ -24724,7 +24802,7 @@ OpenOp::DoObjectStoreKeyDatabaseWork(DatabaseConnection* aConnection)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
rv = mCursor->mKey.SetFromStatement(stmt, 0);
|
||||
rv = PopulateResponseFromStatement(stmt);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
@ -24788,8 +24866,6 @@ OpenOp::DoObjectStoreKeyDatabaseWork(DatabaseConnection* aConnection)
|
||||
directionClause +
|
||||
openLimit;
|
||||
|
||||
mResponse = ObjectStoreKeyCursorResponse(mCursor->mKey);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -24864,6 +24940,8 @@ OpenOp::DoIndexDatabaseWork(DatabaseConnection* aConnection)
|
||||
"WHERE index_table.index_id = :") +
|
||||
id;
|
||||
|
||||
// Note: Changing the number or order of SELECT columns in the query will
|
||||
// require changes to CursorOpBase::PopulateResponseFromStatement.
|
||||
nsCString firstQuery =
|
||||
queryStart +
|
||||
keyRangeClause +
|
||||
@ -24901,22 +24979,7 @@ OpenOp::DoIndexDatabaseWork(DatabaseConnection* aConnection)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
rv = mCursor->mKey.SetFromStatement(stmt, 0);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
rv = mCursor->mObjectKey.SetFromStatement(stmt, 1);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
StructuredCloneReadInfo cloneInfo;
|
||||
rv = GetStructuredCloneReadInfoFromStatement(stmt,
|
||||
3,
|
||||
2,
|
||||
mCursor->mFileManager,
|
||||
&cloneInfo);
|
||||
rv = PopulateResponseFromStatement(stmt);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
@ -25019,15 +25082,6 @@ OpenOp::DoIndexDatabaseWork(DatabaseConnection* aConnection)
|
||||
MOZ_CRASH("Should never get here!");
|
||||
}
|
||||
|
||||
mResponse = IndexCursorResponse();
|
||||
|
||||
auto& response = mResponse.get_IndexCursorResponse();
|
||||
response.cloneInfo().data().SwapElements(cloneInfo.mData);
|
||||
response.key() = mCursor->mKey;
|
||||
response.objectKey() = mCursor->mObjectKey;
|
||||
|
||||
mFiles.SwapElements(cloneInfo.mFiles);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -25093,6 +25147,8 @@ OpenOp::DoIndexKeyDatabaseWork(DatabaseConnection* aConnection)
|
||||
NS_LITERAL_CSTRING(" WHERE index_id = :") +
|
||||
id;
|
||||
|
||||
// Note: Changing the number or order of SELECT columns in the query will
|
||||
// require changes to CursorOpBase::PopulateResponseFromStatement.
|
||||
nsCString firstQuery =
|
||||
queryStart +
|
||||
keyRangeClause +
|
||||
@ -25130,12 +25186,7 @@ OpenOp::DoIndexKeyDatabaseWork(DatabaseConnection* aConnection)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
rv = mCursor->mKey.SetFromStatement(stmt, 0);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
rv = mCursor->mObjectKey.SetFromStatement(stmt, 1);
|
||||
rv = PopulateResponseFromStatement(stmt);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
@ -25237,12 +25288,6 @@ OpenOp::DoIndexKeyDatabaseWork(DatabaseConnection* aConnection)
|
||||
MOZ_CRASH("Should never get here!");
|
||||
}
|
||||
|
||||
mResponse = IndexKeyCursorResponse();
|
||||
|
||||
auto& response = mResponse.get_IndexKeyCursorResponse();
|
||||
response.key() = mCursor->mKey;
|
||||
response.objectKey() = mCursor->mObjectKey;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -25347,8 +25392,10 @@ ContinueOp::DoDatabaseWork(DatabaseConnection* aConnection)
|
||||
// greater than (or less than, if we're running a PREV cursor) or equal to the
|
||||
// key that was specified.
|
||||
|
||||
nsAutoCString countString;
|
||||
// Note: Changing the number or order of SELECT columns in the query will
|
||||
// require changes to CursorOpBase::PopulateResponseFromStatement.
|
||||
nsCString query;
|
||||
nsAutoCString countString;
|
||||
|
||||
bool hasContinueKey = false;
|
||||
uint32_t advanceCount;
|
||||
@ -25367,6 +25414,7 @@ ContinueOp::DoDatabaseWork(DatabaseConnection* aConnection)
|
||||
}
|
||||
} else {
|
||||
advanceCount = mParams.get_AdvanceParams().count();
|
||||
MOZ_ASSERT(advanceCount > 0);
|
||||
countString.AppendInt(advanceCount);
|
||||
|
||||
query = mCursor->mContinueQuery + countString;
|
||||
@ -25429,108 +25477,17 @@ ContinueOp::DoDatabaseWork(DatabaseConnection* aConnection)
|
||||
}
|
||||
|
||||
if (!hasResult) {
|
||||
break;
|
||||
mCursor->mKey.Unset();
|
||||
mCursor->mRangeKey.Unset();
|
||||
mCursor->mObjectKey.Unset();
|
||||
mResponse = void_t();
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
if (!hasResult) {
|
||||
mCursor->mKey.Unset();
|
||||
mCursor->mRangeKey.Unset();
|
||||
mCursor->mObjectKey.Unset();
|
||||
mResponse = void_t();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
switch (mCursor->mType) {
|
||||
case OpenCursorParams::TObjectStoreOpenCursorParams: {
|
||||
rv = mCursor->mKey.SetFromStatement(stmt, 0);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
StructuredCloneReadInfo cloneInfo;
|
||||
rv = GetStructuredCloneReadInfoFromStatement(stmt,
|
||||
2,
|
||||
1,
|
||||
mCursor->mFileManager,
|
||||
&cloneInfo);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
mResponse = ObjectStoreCursorResponse();
|
||||
|
||||
auto& response = mResponse.get_ObjectStoreCursorResponse();
|
||||
response.cloneInfo().data().SwapElements(cloneInfo.mData);
|
||||
response.key() = mCursor->mKey;
|
||||
|
||||
mFiles.SwapElements(cloneInfo.mFiles);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case OpenCursorParams::TObjectStoreOpenKeyCursorParams: {
|
||||
rv = mCursor->mKey.SetFromStatement(stmt, 0);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
mResponse = ObjectStoreKeyCursorResponse(mCursor->mKey);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case OpenCursorParams::TIndexOpenCursorParams: {
|
||||
rv = mCursor->mKey.SetFromStatement(stmt, 0);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
rv = mCursor->mObjectKey.SetFromStatement(stmt, 1);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
StructuredCloneReadInfo cloneInfo;
|
||||
rv = GetStructuredCloneReadInfoFromStatement(stmt,
|
||||
3,
|
||||
2,
|
||||
mCursor->mFileManager,
|
||||
&cloneInfo);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
mResponse = IndexCursorResponse();
|
||||
|
||||
auto& response = mResponse.get_IndexCursorResponse();
|
||||
response.cloneInfo().data().SwapElements(cloneInfo.mData);
|
||||
response.key() = mCursor->mKey;
|
||||
response.objectKey() = mCursor->mObjectKey;
|
||||
|
||||
mFiles.SwapElements(cloneInfo.mFiles);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case OpenCursorParams::TIndexOpenKeyCursorParams: {
|
||||
rv = mCursor->mKey.SetFromStatement(stmt, 0);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
rv = mCursor->mObjectKey.SetFromStatement(stmt, 1);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
mResponse = IndexKeyCursorResponse(mCursor->mKey, mCursor->mObjectKey);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
MOZ_CRASH("Should never get here!");
|
||||
rv = PopulateResponseFromStatement(stmt);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
@ -786,73 +786,73 @@ nsCSPDirective::toDomCSPStruct(mozilla::dom::CSP& outCSP) const
|
||||
switch(mDirective) {
|
||||
case nsIContentSecurityPolicy::DEFAULT_SRC_DIRECTIVE:
|
||||
outCSP.mDefault_src.Construct();
|
||||
outCSP.mDefault_src.Value() = srcs;
|
||||
outCSP.mDefault_src.Value() = mozilla::Move(srcs);
|
||||
return;
|
||||
|
||||
case nsIContentSecurityPolicy::SCRIPT_SRC_DIRECTIVE:
|
||||
outCSP.mScript_src.Construct();
|
||||
outCSP.mScript_src.Value() = srcs;
|
||||
outCSP.mScript_src.Value() = mozilla::Move(srcs);
|
||||
return;
|
||||
|
||||
case nsIContentSecurityPolicy::OBJECT_SRC_DIRECTIVE:
|
||||
outCSP.mObject_src.Construct();
|
||||
outCSP.mObject_src.Value() = srcs;
|
||||
outCSP.mObject_src.Value() = mozilla::Move(srcs);
|
||||
return;
|
||||
|
||||
case nsIContentSecurityPolicy::STYLE_SRC_DIRECTIVE:
|
||||
outCSP.mStyle_src.Construct();
|
||||
outCSP.mStyle_src.Value() = srcs;
|
||||
outCSP.mStyle_src.Value() = mozilla::Move(srcs);
|
||||
return;
|
||||
|
||||
case nsIContentSecurityPolicy::IMG_SRC_DIRECTIVE:
|
||||
outCSP.mImg_src.Construct();
|
||||
outCSP.mImg_src.Value() = srcs;
|
||||
outCSP.mImg_src.Value() = mozilla::Move(srcs);
|
||||
return;
|
||||
|
||||
case nsIContentSecurityPolicy::MEDIA_SRC_DIRECTIVE:
|
||||
outCSP.mMedia_src.Construct();
|
||||
outCSP.mMedia_src.Value() = srcs;
|
||||
outCSP.mMedia_src.Value() = mozilla::Move(srcs);
|
||||
return;
|
||||
|
||||
case nsIContentSecurityPolicy::FRAME_SRC_DIRECTIVE:
|
||||
outCSP.mFrame_src.Construct();
|
||||
outCSP.mFrame_src.Value() = srcs;
|
||||
outCSP.mFrame_src.Value() = mozilla::Move(srcs);
|
||||
return;
|
||||
|
||||
case nsIContentSecurityPolicy::FONT_SRC_DIRECTIVE:
|
||||
outCSP.mFont_src.Construct();
|
||||
outCSP.mFont_src.Value() = srcs;
|
||||
outCSP.mFont_src.Value() = mozilla::Move(srcs);
|
||||
return;
|
||||
|
||||
case nsIContentSecurityPolicy::CONNECT_SRC_DIRECTIVE:
|
||||
outCSP.mConnect_src.Construct();
|
||||
outCSP.mConnect_src.Value() = srcs;
|
||||
outCSP.mConnect_src.Value() = mozilla::Move(srcs);
|
||||
return;
|
||||
|
||||
case nsIContentSecurityPolicy::REPORT_URI_DIRECTIVE:
|
||||
outCSP.mReport_uri.Construct();
|
||||
outCSP.mReport_uri.Value() = srcs;
|
||||
outCSP.mReport_uri.Value() = mozilla::Move(srcs);
|
||||
return;
|
||||
|
||||
case nsIContentSecurityPolicy::FRAME_ANCESTORS_DIRECTIVE:
|
||||
outCSP.mFrame_ancestors.Construct();
|
||||
outCSP.mFrame_ancestors.Value() = srcs;
|
||||
outCSP.mFrame_ancestors.Value() = mozilla::Move(srcs);
|
||||
return;
|
||||
|
||||
case nsIContentSecurityPolicy::WEB_MANIFEST_SRC_DIRECTIVE:
|
||||
outCSP.mManifest_src.Construct();
|
||||
outCSP.mManifest_src.Value() = srcs;
|
||||
outCSP.mManifest_src.Value() = mozilla::Move(srcs);
|
||||
return;
|
||||
// not supporting REFLECTED_XSS_DIRECTIVE
|
||||
|
||||
case nsIContentSecurityPolicy::BASE_URI_DIRECTIVE:
|
||||
outCSP.mBase_uri.Construct();
|
||||
outCSP.mBase_uri.Value() = srcs;
|
||||
outCSP.mBase_uri.Value() = mozilla::Move(srcs);
|
||||
return;
|
||||
|
||||
case nsIContentSecurityPolicy::FORM_ACTION_DIRECTIVE:
|
||||
outCSP.mForm_action.Construct();
|
||||
outCSP.mForm_action.Value() = srcs;
|
||||
outCSP.mForm_action.Value() = mozilla::Move(srcs);
|
||||
return;
|
||||
|
||||
// REFERRER_DIRECTIVE is handled in nsCSPPolicy::toDomCSPStruct()
|
||||
|
@ -18,11 +18,9 @@ namespace mozilla {
|
||||
nsresult
|
||||
SVGLengthList::CopyFrom(const SVGLengthList& rhs)
|
||||
{
|
||||
if (!mLengths.SetCapacity(rhs.Length(), fallible)) {
|
||||
// Yes, we do want fallible alloc here
|
||||
if (!mLengths.Assign(rhs.mLengths, fallible)) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
mLengths = rhs.mLengths;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -197,13 +197,10 @@ SVGMotionSMILType::Assign(nsSMILValue& aDest, const nsSMILValue& aSrc) const
|
||||
|
||||
const MotionSegmentArray& srcArr = ExtractMotionSegmentArray(aSrc);
|
||||
MotionSegmentArray& dstArr = ExtractMotionSegmentArray(aDest);
|
||||
|
||||
// Ensure we have sufficient memory.
|
||||
if (!dstArr.SetCapacity(srcArr.Length(), fallible)) {
|
||||
if (!dstArr.Assign(srcArr, fallible)) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
dstArr = srcArr; // Do the assignment.
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -17,11 +17,9 @@ namespace mozilla {
|
||||
nsresult
|
||||
SVGNumberList::CopyFrom(const SVGNumberList& rhs)
|
||||
{
|
||||
if (!mNumbers.SetCapacity(rhs.Length(), fallible)) {
|
||||
// Yes, we do want fallible alloc here
|
||||
if (!mNumbers.Assign(rhs.mNumbers, fallible)) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
mNumbers = rhs.mNumbers;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -34,11 +34,9 @@ static bool IsMoveto(uint16_t aSegType)
|
||||
nsresult
|
||||
SVGPathData::CopyFrom(const SVGPathData& rhs)
|
||||
{
|
||||
if (!mData.SetCapacity(rhs.mData.Length(), fallible)) {
|
||||
// Yes, we do want fallible alloc here
|
||||
if (!mData.Assign(rhs.mData, fallible)) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
mData = rhs.mData;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -16,11 +16,9 @@ namespace mozilla {
|
||||
nsresult
|
||||
SVGPointList::CopyFrom(const SVGPointList& rhs)
|
||||
{
|
||||
if (!SetCapacity(rhs.Length())) {
|
||||
// Yes, we do want fallible alloc here
|
||||
if (!mItems.Assign(rhs.mItems, fallible)) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
mItems = rhs.mItems;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -16,11 +16,9 @@ namespace mozilla {
|
||||
nsresult
|
||||
SVGStringList::CopyFrom(const SVGStringList& rhs)
|
||||
{
|
||||
if (!mStrings.SetCapacity(rhs.Length(), fallible)) {
|
||||
// Yes, we do want fallible alloc here
|
||||
if (!mStrings.Assign(rhs.mStrings, fallible)) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
mStrings = rhs.mStrings;
|
||||
mIsSet = true;
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -43,11 +43,9 @@ SVGTransformList::CopyFrom(const SVGTransformList& rhs)
|
||||
nsresult
|
||||
SVGTransformList::CopyFrom(const nsTArray<nsSVGTransform>& aTransformArray)
|
||||
{
|
||||
if (!mItems.SetCapacity(aTransformArray.Length(), fallible)) {
|
||||
// Yes, we do want fallible alloc here
|
||||
if (!mItems.Assign(aTransformArray, fallible)) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
mItems = aTransformArray;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -48,12 +48,9 @@ SVGTransformListSMILType::Assign(nsSMILValue& aDest,
|
||||
const TransformArray* srcTransforms =
|
||||
static_cast<const TransformArray*>(aSrc.mU.mPtr);
|
||||
TransformArray* dstTransforms = static_cast<TransformArray*>(aDest.mU.mPtr);
|
||||
|
||||
// Before we assign, ensure we have sufficient memory
|
||||
bool result = dstTransforms->SetCapacity(srcTransforms->Length(), fallible);
|
||||
NS_ENSURE_TRUE(result,NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
*dstTransforms = *srcTransforms;
|
||||
if (!dstTransforms->Assign(*srcTransforms, fallible)) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -1473,9 +1473,6 @@ MessageChannel::MaybeUndeferIncall()
|
||||
IPC_ASSERT(mDeferred.top().interrupt_remote_stack_depth_guess() <= stackDepth,
|
||||
"fatal logic error");
|
||||
|
||||
if (mDeferred.top().interrupt_remote_stack_depth_guess() < RemoteViewOfStackDepth(stackDepth))
|
||||
return;
|
||||
|
||||
// maybe time to process this message
|
||||
Message call = mDeferred.top();
|
||||
mDeferred.pop();
|
||||
|
20
ipc/ipdl/test/cxx/PTestRaceDeadlock.ipdl
Normal file
20
ipc/ipdl/test/cxx/PTestRaceDeadlock.ipdl
Normal file
@ -0,0 +1,20 @@
|
||||
namespace mozilla {
|
||||
namespace _ipdltest {
|
||||
|
||||
intr protocol PTestRaceDeadlock {
|
||||
both:
|
||||
async StartRace();
|
||||
|
||||
parent:
|
||||
intr Lose();
|
||||
|
||||
child:
|
||||
intr Win();
|
||||
intr Rpc();
|
||||
async __delete__();
|
||||
|
||||
/* Tests that race resolution does not cause deadlocks */
|
||||
};
|
||||
|
||||
} // namespace _ipdltest
|
||||
} // namespace mozilla
|
130
ipc/ipdl/test/cxx/TestRaceDeadlock.cpp
Normal file
130
ipc/ipdl/test/cxx/TestRaceDeadlock.cpp
Normal file
@ -0,0 +1,130 @@
|
||||
#include "TestRaceDeadlock.h"
|
||||
|
||||
#include "IPDLUnitTests.h" // fail etc.
|
||||
|
||||
// #define TEST_TIMEOUT 5000
|
||||
|
||||
using namespace mozilla::ipc;
|
||||
typedef mozilla::ipc::MessageChannel::Message Message;
|
||||
|
||||
namespace mozilla {
|
||||
namespace _ipdltest {
|
||||
|
||||
static RacyInterruptPolicy
|
||||
MediateRace(const Message& parent, const Message& child)
|
||||
{
|
||||
return (PTestRaceDeadlock::Msg_Win__ID == parent.type()) ?
|
||||
RIPParentWins : RIPChildWins;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// parent
|
||||
|
||||
TestRaceDeadlockParent::TestRaceDeadlockParent()
|
||||
{
|
||||
MOZ_COUNT_CTOR(TestRaceDeadlockParent);
|
||||
}
|
||||
|
||||
TestRaceDeadlockParent::~TestRaceDeadlockParent()
|
||||
{
|
||||
MOZ_COUNT_DTOR(TestRaceDeadlockParent);
|
||||
}
|
||||
|
||||
void
|
||||
TestRaceDeadlockParent::Main()
|
||||
{
|
||||
Test1();
|
||||
|
||||
Close();
|
||||
}
|
||||
|
||||
bool
|
||||
TestRaceDeadlockParent::ShouldContinueFromReplyTimeout()
|
||||
{
|
||||
fail("This test should not hang");
|
||||
GetIPCChannel()->CloseWithTimeout();
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
TestRaceDeadlockParent::Test1()
|
||||
{
|
||||
#if defined(TEST_TIMEOUT)
|
||||
SetReplyTimeoutMs(TEST_TIMEOUT);
|
||||
#endif
|
||||
if (!SendStartRace()) {
|
||||
fail("sending StartRace");
|
||||
}
|
||||
if (!CallRpc()) {
|
||||
fail("calling Rpc");
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
TestRaceDeadlockParent::AnswerLose()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
RacyInterruptPolicy
|
||||
TestRaceDeadlockParent::MediateInterruptRace(const Message& parent,
|
||||
const Message& child)
|
||||
{
|
||||
return MediateRace(parent, child);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// child
|
||||
|
||||
TestRaceDeadlockChild::TestRaceDeadlockChild()
|
||||
{
|
||||
MOZ_COUNT_CTOR(TestRaceDeadlockChild);
|
||||
}
|
||||
|
||||
TestRaceDeadlockChild::~TestRaceDeadlockChild()
|
||||
{
|
||||
MOZ_COUNT_DTOR(TestRaceDeadlockChild);
|
||||
}
|
||||
|
||||
bool
|
||||
TestRaceDeadlockParent::RecvStartRace()
|
||||
{
|
||||
if (!CallWin()) {
|
||||
fail("calling Win");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
TestRaceDeadlockChild::RecvStartRace()
|
||||
{
|
||||
if (!SendStartRace()) {
|
||||
fail("calling SendStartRace");
|
||||
}
|
||||
if (!CallLose()) {
|
||||
fail("calling Lose");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
TestRaceDeadlockChild::AnswerWin()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
TestRaceDeadlockChild::AnswerRpc()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
RacyInterruptPolicy
|
||||
TestRaceDeadlockChild::MediateInterruptRace(const Message& parent,
|
||||
const Message& child)
|
||||
{
|
||||
return MediateRace(parent, child);
|
||||
}
|
||||
|
||||
} // namespace _ipdltest
|
||||
} // namespace mozilla
|
75
ipc/ipdl/test/cxx/TestRaceDeadlock.h
Normal file
75
ipc/ipdl/test/cxx/TestRaceDeadlock.h
Normal file
@ -0,0 +1,75 @@
|
||||
#ifndef mozilla__ipdltest_TestRaceDeadlock_h
|
||||
#define mozilla__ipdltest_TestRaceDeadlock_h 1
|
||||
|
||||
#include "mozilla/_ipdltest/IPDLUnitTests.h"
|
||||
|
||||
#include "mozilla/_ipdltest/PTestRaceDeadlockParent.h"
|
||||
#include "mozilla/_ipdltest/PTestRaceDeadlockChild.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace _ipdltest {
|
||||
|
||||
class TestRaceDeadlockParent :
|
||||
public PTestRaceDeadlockParent
|
||||
{
|
||||
public:
|
||||
TestRaceDeadlockParent();
|
||||
virtual ~TestRaceDeadlockParent();
|
||||
|
||||
static bool RunTestInProcesses() { return true; }
|
||||
static bool RunTestInThreads() { return true; }
|
||||
|
||||
void Main();
|
||||
|
||||
protected:
|
||||
virtual bool ShouldContinueFromReplyTimeout() override;
|
||||
|
||||
void Test1();
|
||||
|
||||
virtual bool RecvStartRace() override;
|
||||
virtual bool AnswerLose() override;
|
||||
|
||||
virtual mozilla::ipc::RacyInterruptPolicy
|
||||
MediateInterruptRace(const Message& parent, const Message& child) override;
|
||||
|
||||
virtual void ActorDestroy(ActorDestroyReason why) override
|
||||
{
|
||||
if (NormalShutdown != why)
|
||||
fail("unexpected destruction!");
|
||||
passed("ok");
|
||||
QuitParent();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class TestRaceDeadlockChild :
|
||||
public PTestRaceDeadlockChild
|
||||
{
|
||||
public:
|
||||
TestRaceDeadlockChild();
|
||||
virtual ~TestRaceDeadlockChild();
|
||||
|
||||
protected:
|
||||
virtual bool RecvStartRace() override;
|
||||
|
||||
virtual bool AnswerWin() override;
|
||||
|
||||
virtual bool AnswerRpc() override;
|
||||
|
||||
virtual mozilla::ipc::RacyInterruptPolicy
|
||||
MediateInterruptRace(const Message& parent, const Message& child) override;
|
||||
|
||||
virtual void ActorDestroy(ActorDestroyReason why) override
|
||||
{
|
||||
if (NormalShutdown != why)
|
||||
fail("unexpected destruction!");
|
||||
QuitChild();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
} // namespace _ipdltest
|
||||
} // namespace mozilla
|
||||
|
||||
|
||||
#endif // ifndef mozilla__ipdltest_TestRaceDeadlock_h
|
@ -33,6 +33,7 @@ SOURCES += [
|
||||
'TestMultiMgrs.cpp',
|
||||
'TestNestedLoops.cpp',
|
||||
'TestOpens.cpp',
|
||||
'TestRaceDeadlock.cpp',
|
||||
'TestRaceDeferral.cpp',
|
||||
'TestRacyInterruptReplies.cpp',
|
||||
'TestRacyReentry.cpp',
|
||||
@ -102,6 +103,7 @@ IPDL_SOURCES += [
|
||||
'PTestNestedLoops.ipdl',
|
||||
'PTestOpens.ipdl',
|
||||
'PTestOpensOpened.ipdl',
|
||||
'PTestRaceDeadlock.ipdl',
|
||||
'PTestRaceDeferral.ipdl',
|
||||
'PTestRacyInterruptReplies.ipdl',
|
||||
'PTestRacyReentry.ipdl',
|
||||
|
@ -7724,6 +7724,8 @@ IonBuilder::jsop_getelem()
|
||||
}
|
||||
|
||||
obj = maybeUnboxForPropertyAccess(obj);
|
||||
if (obj->type() == MIRType_Object)
|
||||
obj = convertUnboxedObjects(obj);
|
||||
|
||||
bool emitted = false;
|
||||
|
||||
@ -8766,7 +8768,7 @@ IonBuilder::jsop_setelem()
|
||||
|
||||
MDefinition* value = current->pop();
|
||||
MDefinition* index = current->pop();
|
||||
MDefinition* object = current->pop();
|
||||
MDefinition* object = convertUnboxedObjects(current->pop());
|
||||
|
||||
trackTypeInfo(TrackedTypeSite::Receiver, object->type(), object->resultTypeSet());
|
||||
trackTypeInfo(TrackedTypeSite::Index, index->type(), index->resultTypeSet());
|
||||
@ -9478,8 +9480,7 @@ IonBuilder::jsop_rest()
|
||||
}
|
||||
|
||||
uint32_t
|
||||
IonBuilder::getDefiniteSlot(TemporaryTypeSet* types, PropertyName* name, uint32_t* pnfixed,
|
||||
BaselineInspector::ObjectGroupVector& convertUnboxedGroups)
|
||||
IonBuilder::getDefiniteSlot(TemporaryTypeSet* types, PropertyName* name, uint32_t* pnfixed)
|
||||
{
|
||||
if (!types || types->unknownObject()) {
|
||||
trackOptimizationOutcome(TrackedOutcome::NoTypeInfo);
|
||||
@ -9503,21 +9504,6 @@ IonBuilder::getDefiniteSlot(TemporaryTypeSet* types, PropertyName* name, uint32_
|
||||
return UINT32_MAX;
|
||||
}
|
||||
|
||||
// If we encounter a group for an unboxed property which has a
|
||||
// corresponding native group, look for a definite slot in that native
|
||||
// group, and force conversion of incoming objects to the native group.
|
||||
if (key->isGroup() && key->group()->maybeUnboxedLayout()) {
|
||||
if (ObjectGroup* nativeGroup = key->group()->unboxedLayout().nativeGroup()) {
|
||||
if (!convertUnboxedGroups.append(key->group()))
|
||||
CrashAtUnhandlableOOM("IonBuilder::getDefiniteSlot");
|
||||
key = TypeSet::ObjectKey::get(nativeGroup);
|
||||
if (key->unknownProperties()) {
|
||||
trackOptimizationOutcome(TrackedOutcome::UnknownProperties);
|
||||
return UINT32_MAX;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
HeapTypeSetKey property = key->property(NameToId(name));
|
||||
if (!property.maybeTypes() ||
|
||||
!property.maybeTypes()->definiteProperty() ||
|
||||
@ -10033,6 +10019,8 @@ IonBuilder::jsop_getprop(PropertyName* name)
|
||||
}
|
||||
|
||||
obj = maybeUnboxForPropertyAccess(obj);
|
||||
if (obj->type() == MIRType_Object)
|
||||
obj = convertUnboxedObjects(obj);
|
||||
|
||||
BarrierKind barrier = PropertyReadNeedsTypeBarrier(analysisContext, constraints(),
|
||||
obj, name, types);
|
||||
@ -10513,12 +10501,43 @@ IonBuilder::getPropTryComplexPropOfTypedObject(bool* emitted,
|
||||
fieldPrediction, fieldTypeObj);
|
||||
}
|
||||
|
||||
MDefinition*
|
||||
IonBuilder::convertUnboxedObjects(MDefinition* obj)
|
||||
{
|
||||
// If obj might be in any particular unboxed group which should be
|
||||
// converted to a native representation, perform that conversion. This does
|
||||
// not guarantee the object will not have such a group afterwards, if the
|
||||
// object's possible groups are not precisely known.
|
||||
TemporaryTypeSet* types = obj->resultTypeSet();
|
||||
if (!types || types->unknownObject())
|
||||
return obj;
|
||||
|
||||
BaselineInspector::ObjectGroupVector list(alloc());
|
||||
for (size_t i = 0; i < types->getObjectCount(); i++) {
|
||||
TypeSet::ObjectKey* key = obj->resultTypeSet()->getObject(i);
|
||||
if (!key || !key->isGroup())
|
||||
continue;
|
||||
|
||||
if (UnboxedLayout* layout = key->group()->maybeUnboxedLayout()) {
|
||||
if (layout->nativeGroup() && !list.append(key->group()))
|
||||
CrashAtUnhandlableOOM("IonBuilder::convertUnboxedObjects");
|
||||
}
|
||||
}
|
||||
|
||||
return convertUnboxedObjects(obj, list);
|
||||
}
|
||||
|
||||
MDefinition*
|
||||
IonBuilder::convertUnboxedObjects(MDefinition* obj,
|
||||
const BaselineInspector::ObjectGroupVector& list)
|
||||
{
|
||||
for (size_t i = 0; i < list.length(); i++) {
|
||||
obj = MConvertUnboxedObjectToNative::New(alloc(), obj, list[i]);
|
||||
ObjectGroup* group = list[i];
|
||||
if (TemporaryTypeSet* types = obj->resultTypeSet()) {
|
||||
if (!types->hasType(TypeSet::ObjectType(group)))
|
||||
continue;
|
||||
}
|
||||
obj = MConvertUnboxedObjectToNative::New(alloc(), obj, group);
|
||||
current->add(obj->toInstruction());
|
||||
}
|
||||
return obj;
|
||||
@ -10530,10 +10549,8 @@ IonBuilder::getPropTryDefiniteSlot(bool* emitted, MDefinition* obj, PropertyName
|
||||
{
|
||||
MOZ_ASSERT(*emitted == false);
|
||||
|
||||
BaselineInspector::ObjectGroupVector convertUnboxedGroups(alloc());
|
||||
|
||||
uint32_t nfixed;
|
||||
uint32_t slot = getDefiniteSlot(obj->resultTypeSet(), name, &nfixed, convertUnboxedGroups);
|
||||
uint32_t slot = getDefiniteSlot(obj->resultTypeSet(), name, &nfixed);
|
||||
if (slot == UINT32_MAX)
|
||||
return true;
|
||||
|
||||
@ -10543,8 +10560,6 @@ IonBuilder::getPropTryDefiniteSlot(bool* emitted, MDefinition* obj, PropertyName
|
||||
obj = guard;
|
||||
}
|
||||
|
||||
obj = convertUnboxedObjects(obj, convertUnboxedGroups);
|
||||
|
||||
MInstruction* load;
|
||||
if (slot < nfixed) {
|
||||
load = MLoadFixedSlot::New(alloc(), obj, slot);
|
||||
@ -11151,7 +11166,7 @@ bool
|
||||
IonBuilder::jsop_setprop(PropertyName* name)
|
||||
{
|
||||
MDefinition* value = current->pop();
|
||||
MDefinition* obj = current->pop();
|
||||
MDefinition* obj = convertUnboxedObjects(current->pop());
|
||||
|
||||
bool emitted = false;
|
||||
startTrackingOptimizations();
|
||||
@ -11450,10 +11465,8 @@ IonBuilder::setPropTryDefiniteSlot(bool* emitted, MDefinition* obj,
|
||||
return true;
|
||||
}
|
||||
|
||||
BaselineInspector::ObjectGroupVector convertUnboxedGroups(alloc());
|
||||
|
||||
uint32_t nfixed;
|
||||
uint32_t slot = getDefiniteSlot(obj->resultTypeSet(), name, &nfixed, convertUnboxedGroups);
|
||||
uint32_t slot = getDefiniteSlot(obj->resultTypeSet(), name, &nfixed);
|
||||
if (slot == UINT32_MAX)
|
||||
return true;
|
||||
|
||||
@ -11471,8 +11484,6 @@ IonBuilder::setPropTryDefiniteSlot(bool* emitted, MDefinition* obj,
|
||||
writeBarrier |= property.needsBarrier(constraints());
|
||||
}
|
||||
|
||||
obj = convertUnboxedObjects(obj, convertUnboxedGroups);
|
||||
|
||||
MInstruction* store;
|
||||
if (slot < nfixed) {
|
||||
store = MStoreFixedSlot::New(alloc(), obj, slot, value);
|
||||
@ -12308,8 +12319,8 @@ IonBuilder::jsop_setaliasedvar(ScopeCoordinate sc)
|
||||
bool
|
||||
IonBuilder::jsop_in()
|
||||
{
|
||||
MDefinition* obj = current->peek(-1);
|
||||
MDefinition* id = current->peek(-2);
|
||||
MDefinition* obj = convertUnboxedObjects(current->pop());
|
||||
MDefinition* id = current->pop();
|
||||
|
||||
do {
|
||||
if (shouldAbortOnPreliminaryGroups(obj))
|
||||
@ -12324,11 +12335,9 @@ IonBuilder::jsop_in()
|
||||
if (ElementAccessHasExtraIndexedProperty(constraints(), obj))
|
||||
break;
|
||||
|
||||
return jsop_in_dense(unboxedType);
|
||||
return jsop_in_dense(obj, id, unboxedType);
|
||||
} while (false);
|
||||
|
||||
current->pop();
|
||||
current->pop();
|
||||
MIn* ins = MIn::New(alloc(), id, obj);
|
||||
|
||||
current->add(ins);
|
||||
@ -12338,11 +12347,8 @@ IonBuilder::jsop_in()
|
||||
}
|
||||
|
||||
bool
|
||||
IonBuilder::jsop_in_dense(JSValueType unboxedType)
|
||||
IonBuilder::jsop_in_dense(MDefinition* obj, MDefinition* id, JSValueType unboxedType)
|
||||
{
|
||||
MDefinition* obj = current->pop();
|
||||
MDefinition* id = current->pop();
|
||||
|
||||
bool needsHoleCheck = !ElementAccessIsPacked(constraints(), obj);
|
||||
|
||||
// Ensure id is an integer.
|
||||
|
@ -692,7 +692,7 @@ class IonBuilder
|
||||
bool jsop_isnoiter();
|
||||
bool jsop_iterend();
|
||||
bool jsop_in();
|
||||
bool jsop_in_dense(JSValueType unboxedType);
|
||||
bool jsop_in_dense(MDefinition* obj, MDefinition* id, JSValueType unboxedType);
|
||||
bool jsop_instanceof();
|
||||
bool jsop_getaliasedvar(ScopeCoordinate sc);
|
||||
bool jsop_setaliasedvar(ScopeCoordinate sc);
|
||||
@ -927,8 +927,8 @@ class IonBuilder
|
||||
JSObject* testSingletonProperty(JSObject* obj, PropertyName* name);
|
||||
JSObject* testSingletonPropertyTypes(MDefinition* obj, PropertyName* name);
|
||||
|
||||
uint32_t getDefiniteSlot(TemporaryTypeSet* types, PropertyName* name, uint32_t* pnfixed,
|
||||
BaselineInspector::ObjectGroupVector& convertUnboxedGroups);
|
||||
uint32_t getDefiniteSlot(TemporaryTypeSet* types, PropertyName* name, uint32_t* pnfixed);
|
||||
MDefinition* convertUnboxedObjects(MDefinition* obj);
|
||||
MDefinition* convertUnboxedObjects(MDefinition* obj,
|
||||
const BaselineInspector::ObjectGroupVector& list);
|
||||
uint32_t getUnboxedOffset(TemporaryTypeSet* types, PropertyName* name,
|
||||
|
@ -632,7 +632,7 @@ IonBuilder::inlineArrayPopShift(CallInfo& callInfo, MArrayPopShift::Mode mode)
|
||||
OBJECT_FLAG_LENGTH_OVERFLOW |
|
||||
OBJECT_FLAG_ITERATED;
|
||||
|
||||
MDefinition* obj = callInfo.thisArg();
|
||||
MDefinition* obj = convertUnboxedObjects(callInfo.thisArg());
|
||||
TemporaryTypeSet* thisTypes = obj->resultTypeSet();
|
||||
if (!thisTypes)
|
||||
return InliningStatus_NotInlined;
|
||||
@ -758,7 +758,7 @@ IonBuilder::inlineArrayPush(CallInfo& callInfo)
|
||||
return InliningStatus_NotInlined;
|
||||
}
|
||||
|
||||
MDefinition* obj = callInfo.thisArg();
|
||||
MDefinition* obj = convertUnboxedObjects(callInfo.thisArg());
|
||||
MDefinition* value = callInfo.getArg(0);
|
||||
if (PropertyWriteNeedsTypeBarrier(alloc(), constraints(), current,
|
||||
&obj, nullptr, &value, /* canModify = */ false))
|
||||
@ -839,17 +839,20 @@ IonBuilder::inlineArrayConcat(CallInfo& callInfo)
|
||||
return InliningStatus_NotInlined;
|
||||
}
|
||||
|
||||
MDefinition* thisArg = convertUnboxedObjects(callInfo.thisArg());
|
||||
MDefinition* objArg = convertUnboxedObjects(callInfo.getArg(0));
|
||||
|
||||
// Ensure |this|, argument and result are objects.
|
||||
if (getInlineReturnType() != MIRType_Object)
|
||||
return InliningStatus_NotInlined;
|
||||
if (callInfo.thisArg()->type() != MIRType_Object)
|
||||
if (thisArg->type() != MIRType_Object)
|
||||
return InliningStatus_NotInlined;
|
||||
if (callInfo.getArg(0)->type() != MIRType_Object)
|
||||
if (objArg->type() != MIRType_Object)
|
||||
return InliningStatus_NotInlined;
|
||||
|
||||
// |this| and the argument must be dense arrays.
|
||||
TemporaryTypeSet* thisTypes = callInfo.thisArg()->resultTypeSet();
|
||||
TemporaryTypeSet* argTypes = callInfo.getArg(0)->resultTypeSet();
|
||||
TemporaryTypeSet* thisTypes = thisArg->resultTypeSet();
|
||||
TemporaryTypeSet* argTypes = objArg->resultTypeSet();
|
||||
if (!thisTypes || !argTypes)
|
||||
return InliningStatus_NotInlined;
|
||||
|
||||
@ -874,10 +877,10 @@ IonBuilder::inlineArrayConcat(CallInfo& callInfo)
|
||||
|
||||
JSValueType unboxedType = JSVAL_TYPE_MAGIC;
|
||||
if (clasp == &UnboxedArrayObject::class_) {
|
||||
unboxedType = UnboxedArrayElementType(constraints(), callInfo.thisArg(), nullptr);
|
||||
unboxedType = UnboxedArrayElementType(constraints(), thisArg, nullptr);
|
||||
if (unboxedType == JSVAL_TYPE_MAGIC)
|
||||
return InliningStatus_NotInlined;
|
||||
if (unboxedType != UnboxedArrayElementType(constraints(), callInfo.getArg(0), nullptr))
|
||||
if (unboxedType != UnboxedArrayElementType(constraints(), objArg, nullptr))
|
||||
return InliningStatus_NotInlined;
|
||||
}
|
||||
|
||||
@ -937,8 +940,7 @@ IonBuilder::inlineArrayConcat(CallInfo& callInfo)
|
||||
|
||||
callInfo.setImplicitlyUsedUnchecked();
|
||||
|
||||
MArrayConcat* ins = MArrayConcat::New(alloc(), constraints(),
|
||||
callInfo.thisArg(), callInfo.getArg(0),
|
||||
MArrayConcat* ins = MArrayConcat::New(alloc(), constraints(), thisArg, objArg,
|
||||
templateObj,
|
||||
templateObj->group()->initialHeap(constraints()),
|
||||
unboxedType);
|
||||
@ -958,10 +960,12 @@ IonBuilder::inlineArraySlice(CallInfo& callInfo)
|
||||
return InliningStatus_NotInlined;
|
||||
}
|
||||
|
||||
MDefinition* obj = convertUnboxedObjects(callInfo.thisArg());
|
||||
|
||||
// Ensure |this| and result are objects.
|
||||
if (getInlineReturnType() != MIRType_Object)
|
||||
return InliningStatus_NotInlined;
|
||||
if (callInfo.thisArg()->type() != MIRType_Object)
|
||||
if (obj->type() != MIRType_Object)
|
||||
return InliningStatus_NotInlined;
|
||||
|
||||
// Arguments for the sliced region must be integers.
|
||||
@ -975,7 +979,7 @@ IonBuilder::inlineArraySlice(CallInfo& callInfo)
|
||||
}
|
||||
|
||||
// |this| must be a dense array.
|
||||
TemporaryTypeSet* thisTypes = callInfo.thisArg()->resultTypeSet();
|
||||
TemporaryTypeSet* thisTypes = obj->resultTypeSet();
|
||||
if (!thisTypes)
|
||||
return InliningStatus_NotInlined;
|
||||
|
||||
@ -991,7 +995,7 @@ IonBuilder::inlineArraySlice(CallInfo& callInfo)
|
||||
|
||||
JSValueType unboxedType = JSVAL_TYPE_MAGIC;
|
||||
if (clasp == &UnboxedArrayObject::class_) {
|
||||
unboxedType = UnboxedArrayElementType(constraints(), callInfo.thisArg(), nullptr);
|
||||
unboxedType = UnboxedArrayElementType(constraints(), obj, nullptr);
|
||||
if (unboxedType == JSVAL_TYPE_MAGIC)
|
||||
return InliningStatus_NotInlined;
|
||||
}
|
||||
@ -1038,18 +1042,18 @@ IonBuilder::inlineArraySlice(CallInfo& callInfo)
|
||||
if (callInfo.argc() > 1) {
|
||||
end = callInfo.getArg(1);
|
||||
} else if (clasp == &ArrayObject::class_) {
|
||||
MElements* elements = MElements::New(alloc(), callInfo.thisArg());
|
||||
MElements* elements = MElements::New(alloc(), obj);
|
||||
current->add(elements);
|
||||
|
||||
end = MArrayLength::New(alloc(), elements);
|
||||
current->add(end->toInstruction());
|
||||
} else {
|
||||
end = MUnboxedArrayLength::New(alloc(), callInfo.thisArg());
|
||||
end = MUnboxedArrayLength::New(alloc(), obj);
|
||||
current->add(end->toInstruction());
|
||||
}
|
||||
|
||||
MArraySlice* ins = MArraySlice::New(alloc(), constraints(),
|
||||
callInfo.thisArg(), begin, end,
|
||||
obj, begin, end,
|
||||
templateObj,
|
||||
templateObj->group()->initialHeap(constraints()),
|
||||
unboxedType);
|
||||
@ -2114,7 +2118,7 @@ IonBuilder::inlineDefineDataProperty(CallInfo& callInfo)
|
||||
if (callInfo.argc() != 3)
|
||||
return InliningStatus_NotInlined;
|
||||
|
||||
MDefinition* obj = callInfo.getArg(0);
|
||||
MDefinition* obj = convertUnboxedObjects(callInfo.getArg(0));
|
||||
MDefinition* id = callInfo.getArg(1);
|
||||
MDefinition* value = callInfo.getArg(2);
|
||||
|
||||
|
@ -4757,6 +4757,35 @@ MArrayJoin::foldsTo(TempAllocator& alloc)
|
||||
return MStringReplace::New(alloc, string, pattern, replacement);
|
||||
}
|
||||
|
||||
MConvertUnboxedObjectToNative*
|
||||
MConvertUnboxedObjectToNative::New(TempAllocator& alloc, MDefinition* obj, ObjectGroup* group)
|
||||
{
|
||||
MConvertUnboxedObjectToNative* res = new(alloc) MConvertUnboxedObjectToNative(obj, group);
|
||||
|
||||
ObjectGroup* nativeGroup = group->unboxedLayout().nativeGroup();
|
||||
|
||||
// Make a new type set for the result of this instruction which replaces
|
||||
// the input group with the native group we will convert it to.
|
||||
TemporaryTypeSet* types = obj->resultTypeSet();
|
||||
if (types && !types->unknownObject()) {
|
||||
TemporaryTypeSet* newTypes = types->cloneWithoutObjects(alloc.lifoAlloc());
|
||||
if (newTypes) {
|
||||
for (size_t i = 0; i < types->getObjectCount(); i++) {
|
||||
TypeSet::ObjectKey* key = types->getObject(i);
|
||||
if (!key)
|
||||
continue;
|
||||
if (key->unknownProperties() || !key->isGroup() || key->group() != group)
|
||||
newTypes->addType(TypeSet::ObjectType(key), alloc.lifoAlloc());
|
||||
else
|
||||
newTypes->addType(TypeSet::ObjectType(nativeGroup), alloc.lifoAlloc());
|
||||
}
|
||||
res->setResultTypeSet(newTypes);
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
bool
|
||||
jit::ElementAccessIsDenseNative(CompilerConstraintList* constraints,
|
||||
MDefinition* obj, MDefinition* id)
|
||||
|
@ -9049,9 +9049,7 @@ class MConvertUnboxedObjectToNative
|
||||
INSTRUCTION_HEADER(ConvertUnboxedObjectToNative)
|
||||
|
||||
static MConvertUnboxedObjectToNative* New(TempAllocator& alloc, MDefinition* obj,
|
||||
ObjectGroup* group) {
|
||||
return new(alloc) MConvertUnboxedObjectToNative(obj, group);
|
||||
}
|
||||
ObjectGroup* group);
|
||||
|
||||
MDefinition* object() const {
|
||||
return getOperand(0);
|
||||
|
5
layout/reftests/bugs/1114526-1-ref.html
Normal file
5
layout/reftests/bugs/1114526-1-ref.html
Normal file
@ -0,0 +1,5 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<body>
|
||||
</body>
|
||||
</html>
|
BIN
layout/reftests/bugs/1114526-1.gif
Normal file
BIN
layout/reftests/bugs/1114526-1.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 317 B |
64
layout/reftests/bugs/1114526-1.html
Normal file
64
layout/reftests/bugs/1114526-1.html
Normal file
@ -0,0 +1,64 @@
|
||||
<!DOCTYPE html>
|
||||
<html class="reftest-wait">
|
||||
<head>
|
||||
<script>
|
||||
var startPaintCount = 0;
|
||||
function doTest() {
|
||||
startPaintCount = window.mozPaintCount;
|
||||
setTimeout(check, 200);
|
||||
}
|
||||
var calls = 0;
|
||||
function check() {
|
||||
calls++;
|
||||
if ((window.mozPaintCount - startPaintCount) > 2) {
|
||||
finishSuccess();
|
||||
return;
|
||||
}
|
||||
if (calls > 10) {
|
||||
finishFail();
|
||||
return;
|
||||
}
|
||||
setTimeout(check, 200);
|
||||
}
|
||||
function finishSuccess() {
|
||||
cleanup();
|
||||
document.documentElement.className = "";
|
||||
}
|
||||
function finishFail() {
|
||||
cleanup();
|
||||
document.body.appendChild(document.createTextNode("FAIL FAIL FAIL"));
|
||||
document.documentElement.className = "";
|
||||
}
|
||||
function cleanup() {
|
||||
var src = document.getElementById("src");
|
||||
var dest = document.getElementById("dest");
|
||||
src.parentNode.removeChild(src);
|
||||
dest.parentNode.removeChild(dest);
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
div {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
#src {
|
||||
background-image: url('1114526-1.gif');
|
||||
top: -500px;
|
||||
}
|
||||
|
||||
#dest {
|
||||
background-image: -moz-element(#src);
|
||||
top: 100px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="src"></div>
|
||||
<div id="dest"></div>
|
||||
<script>
|
||||
window.addEventListener("MozReftestInvalidate", doTest, false);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -1859,6 +1859,7 @@ test-pref(layout.testing.overlay-scrollbars.always-visible,false) == 1081072-1.h
|
||||
== 1105137-1.html 1105137-1-ref.html
|
||||
fuzzy-if(d2d,36,304) HTTP(..) == 1116480-1-fakeitalic-overflow.html 1116480-1-fakeitalic-overflow-ref.html
|
||||
== 1111753-1.html about:blank
|
||||
== 1114526-1.html 1114526-1-ref.html
|
||||
== 1119117-1a.html 1119117-1-ref.html
|
||||
== 1119117-1b.html 1119117-1-ref.html
|
||||
== 1120431-1.html 1120431-1-ref.html
|
||||
|
@ -1 +1 @@
|
||||
0.0.19
|
||||
0.0.20
|
||||
|
@ -25,12 +25,14 @@ set -x -e
|
||||
: MOZHARNESS_REF ${MOZHARNESS_REF:=${MOZHARNESS_REV}}
|
||||
: MOZHARNESS_HEAD_REV ${MOZHARNESS_HEAD_REV:=${MOZHARNESS_REV}}
|
||||
: MOZHARNESS_HEAD_REF ${MOZHARNESS_HEAD_REF:=${MOZHARNESS_REF}}
|
||||
: MOZHARNESS_DISABLE ${MOZHARNESS_DISABLE:=false}
|
||||
|
||||
: TOOLS_REPOSITORY ${TOOLS_REPOSITORY:=https://hg.mozilla.org/build/tools}
|
||||
: TOOLS_BASE_REPOSITORY ${TOOLS_BASE_REPOSITORY:=${TOOLS_REPOSITORY}}
|
||||
: TOOLS_HEAD_REPOSITORY ${TOOLS_HEAD_REPOSITORY:=${TOOLS_REPOSITORY}}
|
||||
: TOOLS_HEAD_REV ${TOOLS_HEAD_REV:=default}
|
||||
: TOOLS_HEAD_REF ${TOOLS_HEAD_REF:=${TOOLS_HEAD_REV}}
|
||||
: TOOLS_DISABLE ${TOOLS_DISABLE:=false}
|
||||
|
||||
: MH_CUSTOM_BUILD_VARIANT_CFG ${MH_CUSTOM_BUILD_VARIANT_CFG}
|
||||
: MH_BRANCH ${MH_BRANCH:=mozilla-central}
|
||||
@ -41,13 +43,20 @@ set -x -e
|
||||
set -v
|
||||
|
||||
# check out mozharness
|
||||
tc-vcs checkout mozharness $MOZHARNESS_BASE_REPOSITORY $MOZHARNESS_HEAD_REPOSITORY $MOZHARNESS_HEAD_REV $MOZHARNESS_HEAD_REF
|
||||
if [ ! "$MOZHARNESS_DISABLE" = "true" ]
|
||||
then
|
||||
tc-vcs checkout mozharness $MOZHARNESS_BASE_REPOSITORY $MOZHARNESS_HEAD_REPOSITORY $MOZHARNESS_HEAD_REV $MOZHARNESS_HEAD_REF
|
||||
fi
|
||||
|
||||
# check out tools where mozharness expects it to be ($PWD/build/tools and $WORKSPACE/build/tools)
|
||||
tc-vcs checkout $WORKSPACE/build/tools $TOOLS_BASE_REPOSITORY $TOOLS_HEAD_REPOSITORY $TOOLS_HEAD_REV $TOOLS_HEAD_REF
|
||||
if [ ! -d build ]; then
|
||||
mkdir -p build
|
||||
ln -s $WORKSPACE/build/tools build/tools
|
||||
if [ ! "$TOOLS_DISABLE" = true ]
|
||||
then
|
||||
tc-vcs checkout $WORKSPACE/build/tools $TOOLS_BASE_REPOSITORY $TOOLS_HEAD_REPOSITORY $TOOLS_HEAD_REV $TOOLS_HEAD_REF
|
||||
|
||||
if [ ! -d build ]; then
|
||||
mkdir -p build
|
||||
ln -s $WORKSPACE/build/tools build/tools
|
||||
fi
|
||||
fi
|
||||
|
||||
# and check out mozilla-central where mozharness will use it as a cache (/builds/hg-shared)
|
||||
|
22
testing/taskcluster/scripts/builder/build-sm.sh
Executable file
22
testing/taskcluster/scripts/builder/build-sm.sh
Executable file
@ -0,0 +1,22 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -x
|
||||
|
||||
: SPIDERMONKEY_VARIANT ${SPIDERMONKEY_VARIANT:-plain}
|
||||
|
||||
UPLOAD_DIR=$HOME/workspace/artifacts/
|
||||
|
||||
# cd into the correct directory
|
||||
cd $HOME/workspace/
|
||||
|
||||
# Run the script
|
||||
./build/src/js/src/devtools/automation/autospider.sh $SPIDERMONKEY_VARIANT
|
||||
BUILD_STATUS=$?
|
||||
|
||||
# Ensure upload dir exists
|
||||
mkdir -p $UPLOAD_DIR
|
||||
|
||||
# Move artifacts for upload by TaskCluster
|
||||
mv ./build/src/obj-spider/dist/* $UPLOAD_DIR
|
||||
|
||||
exit $BUILD_STATUS
|
@ -1175,6 +1175,31 @@ public:
|
||||
//
|
||||
// Mutation methods
|
||||
//
|
||||
|
||||
template<class Allocator, typename ActualAlloc = Alloc>
|
||||
typename ActualAlloc::ResultType Assign(
|
||||
const nsTArray_Impl<E, Allocator>& aOther)
|
||||
{
|
||||
return ActualAlloc::ConvertBoolToResultType(
|
||||
!!ReplaceElementsAt<E, ActualAlloc>(0, Length(),
|
||||
aOther.Elements(), aOther.Length()));
|
||||
}
|
||||
|
||||
template<class Allocator>
|
||||
/* MOZ_WARN_UNUSED_RESULT */
|
||||
bool Assign(const nsTArray_Impl<E, Allocator>& aOther,
|
||||
const mozilla::fallible_t&)
|
||||
{
|
||||
return Assign<Allocator, FallibleAlloc>(aOther);
|
||||
}
|
||||
|
||||
template<class Allocator>
|
||||
void Assign(nsTArray_Impl<E, Allocator>&& aOther)
|
||||
{
|
||||
Clear();
|
||||
SwapElements(aOther);
|
||||
}
|
||||
|
||||
// This method call the destructor on each element of the array, empties it,
|
||||
// but does not shrink the array's capacity.
|
||||
// See also SetLengthAndRetainStorage.
|
||||
|
57
xpcom/tests/gtest/TestTArray.cpp
Normal file
57
xpcom/tests/gtest/TestTArray.cpp
Normal file
@ -0,0 +1,57 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsTArray.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
namespace TestTArray {
|
||||
|
||||
const nsTArray<int>& DummyArray()
|
||||
{
|
||||
static nsTArray<int> sArray;
|
||||
if (sArray.IsEmpty()) {
|
||||
const int data[] = {4, 1, 2, 8};
|
||||
sArray.AppendElements(data, ArrayLength(data));
|
||||
}
|
||||
return sArray;
|
||||
}
|
||||
|
||||
// This returns an invalid nsTArray with a huge length in order to test that
|
||||
// fallible operations actually fail.
|
||||
#ifdef DEBUG
|
||||
const nsTArray<int>& FakeHugeArray()
|
||||
{
|
||||
static nsTArray<int> sArray;
|
||||
if (sArray.IsEmpty()) {
|
||||
sArray.AppendElement();
|
||||
((nsTArrayHeader*)sArray.DebugGetHeader())->mLength = UINT32_MAX;
|
||||
}
|
||||
return sArray;
|
||||
}
|
||||
#endif
|
||||
|
||||
TEST(TArray, assign)
|
||||
{
|
||||
nsTArray<int> array;
|
||||
array.Assign(DummyArray());
|
||||
ASSERT_EQ(DummyArray(), array);
|
||||
|
||||
ASSERT_TRUE(array.Assign(DummyArray(), fallible));
|
||||
ASSERT_EQ(DummyArray(), array);
|
||||
|
||||
#ifdef DEBUG
|
||||
ASSERT_FALSE(array.Assign(FakeHugeArray(), fallible));
|
||||
#endif
|
||||
|
||||
nsTArray<int> array2;
|
||||
array2.Assign(Move(array));
|
||||
ASSERT_TRUE(array.IsEmpty());
|
||||
ASSERT_EQ(DummyArray(), array2);
|
||||
}
|
||||
|
||||
}
|
@ -17,6 +17,7 @@ UNIFIED_SOURCES += [
|
||||
'TestStrings.cpp',
|
||||
'TestStringStream.cpp',
|
||||
'TestSynchronization.cpp',
|
||||
'TestTArray.cpp',
|
||||
'TestThreadPool.cpp',
|
||||
'TestThreads.cpp',
|
||||
'TestTimeStamp.cpp',
|
||||
|
Loading…
Reference in New Issue
Block a user