Merge mozilla-central to autoland. a=merge CLOSED TREE

This commit is contained in:
Cosmin Sabou 2018-06-01 12:43:38 +03:00
Родитель 08e410f7c9 292d295d6b
Коммит a9b5e2819a
37 изменённых файлов: 852 добавлений и 468 удалений

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

@ -0,0 +1,10 @@
. "$topsrcdir/browser/config/mozconfigs/macosx64/nightly"
TOOLTOOL_DIR=${TOOLTOOL_DIR:-$topsrcdir}
ac_add_options --disable-sandbox
ac_add_options --enable-coverage
export CFLAGS="-coverage"
export CXXFLAGS="-coverage"
export LDFLAGS="-coverage"

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

@ -0,0 +1,3 @@
. "$topsrcdir/browser/config/mozconfigs/macosx64/code-coverage"
ac_add_options --enable-debug

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

@ -852,7 +852,8 @@ nsContentList::MatchSelf(nsIContent *aContent)
}
void
nsContentList::PopulateSelf(uint32_t aNeededLength)
nsContentList::PopulateSelf(uint32_t aNeededLength,
uint32_t aExpectedElementsIfDirty)
{
if (!mRootNode) {
return;
@ -861,7 +862,7 @@ nsContentList::PopulateSelf(uint32_t aNeededLength)
ASSERT_IN_SYNC;
uint32_t count = mElements.Length();
NS_ASSERTION(mState != LIST_DIRTY || count == 0,
NS_ASSERTION(mState != LIST_DIRTY || count == aExpectedElementsIfDirty,
"Reset() not called when setting state to LIST_DIRTY?");
if (count >= aNeededLength) // We're all set
@ -1153,7 +1154,8 @@ nsLabelsNodeList::MaybeResetRoot(nsINode* aRootNode)
}
void
nsLabelsNodeList::PopulateSelf(uint32_t aNeededLength)
nsLabelsNodeList::PopulateSelf(uint32_t aNeededLength,
uint32_t aExpectedElementsIfDirty)
{
if (!mRootNode) {
return;
@ -1163,7 +1165,8 @@ nsLabelsNodeList::PopulateSelf(uint32_t aNeededLength)
nsINode* cur = mRootNode;
if (mElements.IsEmpty() && cur->IsElement() && Match(cur->AsElement())) {
mElements.AppendElement(cur->AsElement());
++aExpectedElementsIfDirty;
}
nsContentList::PopulateSelf(aNeededLength);
nsContentList::PopulateSelf(aNeededLength, aExpectedElementsIfDirty);
}

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

@ -433,8 +433,11 @@ protected:
*
* @param aNeededLength the length the list should have when we are
* done (unless it exhausts the document)
* @param aExpectedElementsIfDirty is for debugging only to
* assert that mElements has expected number of entries.
*/
virtual void PopulateSelf(uint32_t aNeededLength);
virtual void PopulateSelf(uint32_t aNeededLength,
uint32_t aExpectedElementsIfDirty = 0);
/**
* @param aContainer a content node which must be a descendant of
@ -684,7 +687,10 @@ private:
*
* @param aNeededLength The list of length should have when we are
* done (unless it exhausts the document).
* @param aExpectedElementsIfDirty is for debugging only to
* assert that mElements has expected number of entries.
*/
void PopulateSelf(uint32_t aNeededLength) override;
void PopulateSelf(uint32_t aNeededLength,
uint32_t aExpectedElementsIfDirty = 0) override;
};
#endif // nsContentList_h___

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

@ -280,6 +280,15 @@ nsINode::GetParentOrHostNode() const
nsINode*
nsINode::SubtreeRoot() const
{
auto RootOfNode = [](const nsINode* aStart) -> nsINode* {
const nsINode* node = aStart;
const nsINode* iter = node;
while ((iter = iter->GetParentNode())) {
node = iter;
}
return const_cast<nsINode*>(node);
};
// There are four cases of interest here. nsINodes that are really:
// 1. nsIDocument nodes - Are always in the document.
// 2.a nsIContent nodes not in a shadow tree - Are either in the document,
@ -294,19 +303,18 @@ nsINode::SubtreeRoot() const
} else if (IsContent()) {
ShadowRoot* containingShadow = AsContent()->GetContainingShadow();
node = containingShadow ? containingShadow : mSubtreeRoot;
if (!node) {
NS_WARNING("Using SubtreeRoot() on unlinked element?");
node = RootOfNode(this);
}
} else {
node = mSubtreeRoot;
}
NS_ASSERTION(node, "Should always have a node here!");
MOZ_ASSERT(node, "Should always have a node here!");
#ifdef DEBUG
{
const nsINode* slowNode = this;
const nsINode* iter = slowNode;
while ((iter = iter->GetParentNode())) {
slowNode = iter;
}
NS_ASSERTION(slowNode == node, "These should always be in sync!");
const nsINode* slowNode = RootOfNode(this);
MOZ_ASSERT(slowNode == node, "These should always be in sync!");
}
#endif
return node;

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

@ -205,7 +205,21 @@ WebGLContext::BindFakeBlack(uint32_t texUnit, TexTarget target, FakeBlackType fa
UniquePtr<FakeBlackTexture>& fakeBlackTex = *slot;
if (!fakeBlackTex) {
gl->fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT, 1);
if (IsWebGL2()) {
gl->fPixelStorei(LOCAL_GL_UNPACK_SKIP_PIXELS, 0);
gl->fPixelStorei(LOCAL_GL_UNPACK_SKIP_ROWS, 0);
gl->fPixelStorei(LOCAL_GL_UNPACK_SKIP_IMAGES, 0);
}
fakeBlackTex = FakeBlackTexture::Create(gl, target, fakeBlack);
gl->fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT, mPixelStore_UnpackAlignment);
if (IsWebGL2()) {
gl->fPixelStorei(LOCAL_GL_UNPACK_SKIP_PIXELS, mPixelStore_UnpackSkipPixels);
gl->fPixelStorei(LOCAL_GL_UNPACK_SKIP_ROWS, mPixelStore_UnpackSkipRows);
gl->fPixelStorei(LOCAL_GL_UNPACK_SKIP_IMAGES, mPixelStore_UnpackSkipImages);
}
if (!fakeBlackTex) {
return false;
}
@ -995,13 +1009,8 @@ WebGLContext::FakeBlackTexture::Create(gl::GLContext* gl, TexTarget target,
gl->fTexParameteri(target.get(), LOCAL_GL_TEXTURE_MIN_FILTER, LOCAL_GL_NEAREST);
gl->fTexParameteri(target.get(), LOCAL_GL_TEXTURE_MAG_FILTER, LOCAL_GL_NEAREST);
// We allocate our zeros on the heap, and we overallocate (16 bytes instead of 4) to
// minimize the risk of running into a driver bug in texImage2D, as it is a bit
// unusual maybe to create 1x1 textures, and the stack may not have the alignment that
// TexImage2D expects.
const webgl::DriverUnpackInfo dui = {texFormat, texFormat, LOCAL_GL_UNSIGNED_BYTE};
UniqueBuffer zeros = moz_xcalloc(1, 16); // Infallible allocation.
UniqueBuffer zeros = moz_xcalloc(1, 4); // Infallible allocation.
MOZ_ASSERT(gl->IsCurrent());

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

@ -473,14 +473,13 @@ nsGenericHTMLElement::UnbindFromTree(bool aDeep, bool aNullParent)
}
}
// We need to consider a labels element is removed from tree,
// it needs to update labels list and its root as well.
nsStyledElement::UnbindFromTree(aDeep, aNullParent);
// Invalidate .labels list. It will be repopulated when used the next time.
nsExtendedDOMSlots* slots = GetExistingExtendedDOMSlots();
if (slots && slots->mLabelsList) {
slots->mLabelsList->MaybeResetRoot(SubtreeRoot());
}
nsStyledElement::UnbindFromTree(aDeep, aNullParent);
}
HTMLFormElement*

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

@ -698,12 +698,16 @@ ImageBridgeChild::IdentifyCompositorTextureHost(const TextureFactoryIdentifier&
void
ImageBridgeChild::UpdateTextureFactoryIdentifier(const TextureFactoryIdentifier& aIdentifier)
{
// ImageHost is incompatible between WebRender enabled and WebRender disabled.
// Then drop all ImageContainers' ImageClients during disabling WebRender.
bool disablingWebRender = GetCompositorBackendType() == LayersBackend::LAYERS_WR &&
aIdentifier.mParentBackend != LayersBackend::LAYERS_WR;
// D3DTexture might become obsolte. To prevent to use obsoleted D3DTexture,
// drop all ImageContainers' ImageClients.
bool needsDrop = GetCompositorBackendType() == LayersBackend::LAYERS_D3D11 || disablingWebRender;
IdentifyTextureHost(aIdentifier);
if (disablingWebRender) {
// ImageHost is incompatible between WebRender enabled and WebRender disabled.
// Then drop all ImageContainers' ImageClients during disabling WebRender.
if (needsDrop) {
nsTArray<RefPtr<ImageContainerListener> > listeners;
{
MutexAutoLock lock(mContainerMapLock);

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

@ -2,7 +2,7 @@ This is the Sanitiser for OpenType project, from http://code.google.com/p/ots/.
Our reference repository is https://github.com/khaledhosny/ots/.
Current revision: c903692702e888dd9bc3e62a129d01af07320ad8 (6.1.1)
Current revision: 7c8f3fc9cf8b79edb241d94a4847968a5009e78d (7.0.0)
Upstream files included: LICENSE, src/, include/, tests/*.cc

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

@ -23,7 +23,7 @@ class OpenTypeFVAR : public Table {
bool Parse(const uint8_t* data, size_t length);
bool Serialize(OTSStream* out);
const uint16_t AxisCount() const { return axisCount; }
uint16_t AxisCount() const { return axisCount; }
private:
uint16_t majorVersion;

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

@ -154,3 +154,5 @@ bool OpenTypeGVAR::Serialize(OTSStream* out) {
}
} // namespace ots
#undef TABLE_NAME

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

@ -85,3 +85,5 @@ bool OpenTypeHVAR::Serialize(OTSStream* out) {
}
} // namespace ots
#undef TABLE_NAME

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

@ -105,3 +105,5 @@ bool OpenTypeMVAR::Serialize(OTSStream* out) {
}
} // namespace ots
#undef TABLE_NAME

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

@ -47,7 +47,7 @@ class OpenTypeSTAT : public Table {
uint16_t flags;
uint16_t valueNameID;
Fixed value;
static const size_t Length() {
static size_t Length() {
return 3 * sizeof(uint16_t) + sizeof(Fixed);
}
};
@ -59,7 +59,7 @@ class OpenTypeSTAT : public Table {
Fixed nominalValue;
Fixed rangeMinValue;
Fixed rangeMaxValue;
static const size_t Length() {
static size_t Length() {
return 3 * sizeof(uint16_t) + 3 * sizeof(Fixed);
}
};
@ -70,7 +70,7 @@ class OpenTypeSTAT : public Table {
uint16_t valueNameID;
Fixed value;
Fixed linkedValue;
static const size_t Length() {
static size_t Length() {
return 3 * sizeof(uint16_t) + 2 * sizeof(Fixed);
}
};
@ -84,7 +84,7 @@ class OpenTypeSTAT : public Table {
Fixed value;
};
std::vector<AxisValue> axisValues;
const size_t Length() const {
size_t Length() const {
return 3 * sizeof(uint16_t) + axisValues.size() * (sizeof(uint16_t) + sizeof(Fixed));
}
};

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

@ -246,3 +246,5 @@ bool ParseVariationData(const Font* font, const uint8_t* data, size_t length,
}
} // namespace ots
#undef TABLE_NAME

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

@ -95,3 +95,5 @@ bool OpenTypeVVAR::Serialize(OTSStream* out) {
}
} // namespace ots
#undef TABLE_NAME

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

@ -6965,10 +6965,13 @@ GCRuntime::resetIncrementalGC(gc::AbortReason reason, AutoTraceSession& session)
namespace {
class AutoGCSlice {
/*
* Temporarily disable barriers during GC slices.
*/
class AutoDisableBarriers {
public:
explicit AutoGCSlice(JSRuntime* rt);
~AutoGCSlice();
explicit AutoDisableBarriers(JSRuntime* rt);
~AutoDisableBarriers();
private:
JSRuntime* runtime;
@ -6977,7 +6980,7 @@ class AutoGCSlice {
} /* anonymous namespace */
AutoGCSlice::AutoGCSlice(JSRuntime* rt)
AutoDisableBarriers::AutoDisableBarriers(JSRuntime* rt)
: runtime(rt)
{
for (GCZonesIter zone(rt); !zone.done(); zone.next()) {
@ -6985,7 +6988,7 @@ AutoGCSlice::AutoGCSlice(JSRuntime* rt)
* Clear needsIncrementalBarrier early so we don't do any write
* barriers during GC. We don't need to update the Ion barriers (which
* is expensive) because Ion code doesn't run during GC. If need be,
* we'll update the Ion barriers in ~AutoGCSlice.
* we'll update the Ion barriers in ~AutoDisableBarriers.
*/
if (zone->isGCMarking()) {
MOZ_ASSERT(zone->needsIncrementalBarrier());
@ -6995,7 +6998,7 @@ AutoGCSlice::AutoGCSlice(JSRuntime* rt)
}
}
AutoGCSlice::~AutoGCSlice()
AutoDisableBarriers::~AutoDisableBarriers()
{
/* We can't use GCZonesIter if this is the end of the last slice. */
for (ZonesIter zone(runtime, WithAtoms); !zone.done(); zone.next()) {
@ -7052,7 +7055,7 @@ GCRuntime::incrementalCollectSlice(SliceBudget& budget, JS::gcreason::Reason rea
if (isIncrementalGCInProgress() && !atomsZone->isCollecting())
session.maybeLock.reset();
AutoGCSlice slice(rt);
AutoDisableBarriers disableBarriers(rt);
bool destroyingRuntime = (reason == JS::gcreason::DESTROY_RUNTIME);
@ -7069,6 +7072,14 @@ GCRuntime::incrementalCollectSlice(SliceBudget& budget, JS::gcreason::Reason rea
bool useZeal = false;
#endif
#ifdef DEBUG
{
char budgetBuffer[32];
budget.describe(budgetBuffer, 32);
stats().writeLogMessage("Incremental: %d, useZeal: %d, budget: %s",
bool(isIncremental), bool(useZeal), budgetBuffer);
}
#endif
MOZ_ASSERT_IF(isIncrementalGCInProgress(), isIncremental);
if (isIncrementalGCInProgress() && budget.isUnlimited())
changeToNonIncrementalGC();
@ -7080,6 +7091,8 @@ GCRuntime::incrementalCollectSlice(SliceBudget& budget, JS::gcreason::Reason rea
* Yields between slices occurs at predetermined points in these modes;
* the budget is not used.
*/
stats().writeLogMessage(
"Using unlimited budget for two-slice zeal mode");
budget.makeUnlimited();
}
@ -7127,7 +7140,7 @@ GCRuntime::incrementalCollectSlice(SliceBudget& budget, JS::gcreason::Reason rea
MOZ_ASSERT(marker.isDrained());
/*
* In incremental GCs where we have already performed more than once
* In incremental GCs where we have already performed more than one
* slice we yield after marking with the aim of starting the sweep in
* the next slice, since the first slice of sweeping can be expensive.
*
@ -7144,6 +7157,7 @@ GCRuntime::incrementalCollectSlice(SliceBudget& budget, JS::gcreason::Reason rea
(useZeal && hasZealMode(ZealMode::YieldBeforeSweeping))))
{
lastMarkSlice = true;
stats().writeLogMessage("Yeilding before starting sweeping");
break;
}
@ -7619,6 +7633,9 @@ GCRuntime::collect(bool nonincrementalByAPI, SliceBudget budget, JS::gcreason::R
if (!checkIfGCAllowedInCurrentState(reason))
return;
stats().writeLogMessage("GC starting in state %s",
StateName(incrementalState));
AutoTraceLog logGC(TraceLoggerForCurrentThread(), TraceLogger_GC);
AutoStopVerifyingBarriers av(rt, IsShutdownGC(reason));
AutoEnqueuePendingParseTasksAfterGC aept(*this);
@ -7630,6 +7647,7 @@ GCRuntime::collect(bool nonincrementalByAPI, SliceBudget budget, JS::gcreason::R
if (reason == JS::gcreason::ABORT_GC) {
MOZ_ASSERT(!isIncrementalGCInProgress());
stats().writeLogMessage("GC aborted by request");
break;
}
@ -7669,6 +7687,7 @@ GCRuntime::collect(bool nonincrementalByAPI, SliceBudget budget, JS::gcreason::R
MOZ_RELEASE_ASSERT(CheckGrayMarkingState(rt));
}
#endif
stats().writeLogMessage("GC ending");
}
js::AutoEnqueuePendingParseTasksAfterGC::~AutoEnqueuePendingParseTasksAfterGC()

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

@ -97,6 +97,30 @@ js::gcstats::ExplainAbortReason(gc::AbortReason reason)
}
}
static FILE*
MaybeOpenFileFromEnv(const char* env)
{
FILE *file;
const char* value = getenv(env);
if (!value)
return nullptr;
if (strcmp(value, "none") == 0) {
file = nullptr;
} else if (strcmp(value, "stdout") == 0) {
file = stdout;
} else if (strcmp(value, "stderr") == 0) {
file = stderr;
} else {
file = fopen(value, "a");
if (!file)
MOZ_CRASH("Failed to open log file.");
}
return file;
}
struct PhaseKindInfo
{
Phase firstPhase;
@ -551,6 +575,24 @@ Statistics::renderNurseryJson(JSRuntime* rt) const
return UniqueChars(printer.release());
}
#ifdef DEBUG
void
Statistics::writeLogMessage(const char* fmt, ...)
{
va_list args;
va_start(args, fmt);
if (gcDebugFile) {
TimeDuration sinceStart = TimeStamp::Now() -
TimeStamp::ProcessCreation();
fprintf(gcDebugFile, "%12.3f: ", sinceStart.ToMicroseconds());
vfprintf(gcDebugFile, fmt, args);
fprintf(gcDebugFile, "\n");
fflush(gcDebugFile);
}
va_end(args);
}
#endif
UniqueChars
Statistics::renderJsonMessage(uint64_t timestamp, bool includeSlices) const
{
@ -695,7 +737,8 @@ Statistics::formatJsonPhaseTimes(const PhaseTimeTable& phaseTimes, JSONPrinter&
Statistics::Statistics(JSRuntime* rt)
: runtime(rt),
fp(nullptr),
gcTimerFile(nullptr),
gcDebugFile(nullptr),
nonincrementalReason_(gc::AbortReason::None),
preBytes(0),
thresholdTriggered(false),
@ -734,22 +777,10 @@ Statistics::Statistics(JSRuntime* rt)
MOZ_ALWAYS_TRUE(phaseStack.reserve(MAX_PHASE_NESTING));
MOZ_ALWAYS_TRUE(suspendedPhases.reserve(MAX_SUSPENDED_PHASES));
const char* env = getenv("MOZ_GCTIMER");
if (env) {
if (strcmp(env, "none") == 0) {
fp = nullptr;
} else if (strcmp(env, "stdout") == 0) {
fp = stdout;
} else if (strcmp(env, "stderr") == 0) {
fp = stderr;
} else {
fp = fopen(env, "a");
if (!fp)
MOZ_CRASH("Failed to open MOZ_GCTIMER log file.");
}
}
gcTimerFile = MaybeOpenFileFromEnv("MOZ_GCTIMER");
gcDebugFile = MaybeOpenFileFromEnv("JS_GC_DEBUG");
env = getenv("JS_GC_PROFILE");
const char* env = getenv("JS_GC_PROFILE");
if (env) {
if (0 == strcmp(env, "help")) {
fprintf(stderr, "JS_GC_PROFILE=N\n"
@ -763,8 +794,10 @@ Statistics::Statistics(JSRuntime* rt)
Statistics::~Statistics()
{
if (fp && fp != stdout && fp != stderr)
fclose(fp);
if (gcTimerFile && gcTimerFile != stdout && gcTimerFile != stderr)
fclose(gcTimerFile);
if (gcDebugFile && gcDebugFile != stdout && gcDebugFile != stderr)
fclose(gcDebugFile);
}
/* static */ bool
@ -918,16 +951,16 @@ void
Statistics::printStats()
{
if (aborted) {
fprintf(fp, "OOM during GC statistics collection. The report is unavailable for this GC.\n");
fprintf(gcTimerFile, "OOM during GC statistics collection. The report is unavailable for this GC.\n");
} else {
UniqueChars msg = formatDetailedMessage();
if (msg) {
double secSinceStart =
(slices_[0].start - TimeStamp::ProcessCreation()).ToSeconds();
fprintf(fp, "GC(T+%.3fs) %s\n", secSinceStart, msg.get());
fprintf(gcTimerFile, "GC(T+%.3fs) %s\n", secSinceStart, msg.get());
}
}
fflush(fp);
fflush(gcTimerFile);
}
void
@ -1035,6 +1068,8 @@ Statistics::beginSlice(const ZoneGCStats& zoneStats, JSGCInvocationKind gckind,
(*sliceCallback)(cx, JS::GC_CYCLE_BEGIN, desc);
(*sliceCallback)(cx, JS::GC_SLICE_BEGIN, desc);
}
writeLogMessage("begin slice");
}
void
@ -1049,6 +1084,7 @@ Statistics::endSlice()
slice.endFaults = GetPageFaultCount();
slice.finalState = runtime->gc.state();
writeLogMessage("end slice");
TimeDuration sliceTime = slice.end - slice.start;
runtime->addTelemetry(JS_TELEMETRY_GC_SLICE_MS, t(sliceTime));
runtime->addTelemetry(JS_TELEMETRY_GC_RESET, slice.wasReset());
@ -1086,7 +1122,7 @@ Statistics::endSlice()
bool last = !runtime->gc.isIncrementalGCInProgress();
if (last) {
if (fp)
if (gcTimerFile)
printStats();
if (!aborted)
@ -1250,6 +1286,7 @@ Statistics::recordPhaseBegin(Phase phase)
phaseStack.infallibleAppend(phase);
phaseStartTimes[phase] = now;
writeLogMessage("begin: %s", phases[phase].path);
}
void
@ -1299,6 +1336,7 @@ Statistics::recordPhaseEnd(Phase phase)
#ifdef DEBUG
phaseEndTimes[phase] = now;
writeLogMessage("end: %s", phases[phase].path);
#endif
}

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

@ -166,6 +166,8 @@ struct Statistics
void nonincremental(gc::AbortReason reason) {
MOZ_ASSERT(reason != gc::AbortReason::None);
nonincrementalReason_ = reason;
writeLogMessage("Non-incremental reason: %s",
nonincrementalReason());
}
bool nonincremental() const {
@ -266,11 +268,21 @@ struct Statistics
// Return JSON for the previous nursery collection.
UniqueChars renderNurseryJson(JSRuntime* rt) const;
#ifdef DEBUG
// Print a logging message.
void writeLogMessage(const char* fmt, ...);
#else
void writeLogMessage(const char* fmt, ...) { };
#endif
private:
JSRuntime* runtime;
/* File pointer used for MOZ_GCTIMER output. */
FILE* fp;
/* File used for MOZ_GCTIMER output. */
FILE* gcTimerFile;
/* File used for JS_GC_DEBUG output. */
FILE* gcDebugFile;
ZoneGCStats zoneStats;

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

@ -113,13 +113,84 @@ function checkMiscPrefixed(opcode, expect_failure) {
}
//-----------------------------------------------------------
// Verification cases for memory.copy/fill
// Verification cases for memory.copy/fill opcode encodings
checkMiscPrefixed(0x3f, true); // unassigned
checkMiscPrefixed(0x40, false); // memory.copy
checkMiscPrefixed(0x41, false); // memory.fill
checkMiscPrefixed(0x42, true); // unassigned
//-----------------------------------------------------------
// Verification cases for memory.copy/fill arguments
// Invalid argument types
{
const tys = ['i32', 'f32', 'i64', 'f64'];
const ops = ['copy', 'fill'];
for (let ty1 of tys) {
for (let ty2 of tys) {
for (let ty3 of tys) {
for (let op of ops) {
if (ty1 == 'i32' && ty2 == 'i32' && ty3 == 'i32')
continue; // this is the only valid case
let text =
`(module
(memory (export "memory") 1 1)
(func (export "testfn")
(memory.${op} (${ty1}.const 10) (${ty2}.const 20) (${ty3}.const 30))
)
)`;
assertErrorMessage(() => wasmEvalText(text),
WebAssembly.CompileError, /type mismatch/);
}}}}
}
// Not enough, or too many, args
{
for (let op of ['copy', 'fill']) {
let text1 =
`(module
(memory (export "memory") 1 1)
(func (export "testfn")
(i32.const 10)
(i32.const 20)
memory.${op}
)
)`;
assertErrorMessage(() => wasmEvalText(text1),
WebAssembly.CompileError,
/popping value from empty stack/);
let text2 =
`(module
(memory (export "memory") 1 1)
(func (export "testfn")
(i32.const 10)
(i32.const 20)
(i32.const 30)
(i32.const 40)
memory.${op}
)
)`;
assertErrorMessage(() => wasmEvalText(text2),
WebAssembly.CompileError,
/unused values not explicitly dropped by end of block/);
}
}
// Module doesn't have a memory
{
for (let op of ['copy', 'fill']) {
let text =
`(module
(func (export "testfn")
(memory.${op} (i32.const 10) (i32.const 20) (i32.const 30))
)
)`;
assertErrorMessage(() => wasmEvalText(text),
WebAssembly.CompileError,
/can't touch memory without memory/);
}
}
//---------------------------------------------------------------------//
//---------------------------------------------------------------------//
@ -139,14 +210,14 @@ function checkRange(arr, minIx, maxIxPlusOne, expectedValue)
// Range valid
{
let inst = new WebAssembly.Instance(new WebAssembly.Module(wasmTextToBinary(
let inst = wasmEvalText(
`(module
(memory (export "memory") 1 1)
(func (export "testfn")
(memory.fill (i32.const 0xFF00) (i32.const 0x55) (i32.const 256))
)
)`
)));
);
inst.exports.testfn();
let b = new Uint8Array(inst.exports.memory.buffer);
checkRange(b, 0x00000, 0x0FF00, 0x00);
@ -155,42 +226,42 @@ function checkRange(arr, minIx, maxIxPlusOne, expectedValue)
// Range invalid
{
let inst = new WebAssembly.Instance(new WebAssembly.Module(wasmTextToBinary(
let inst = wasmEvalText(
`(module
(memory (export "memory") 1 1)
(func (export "testfn")
(memory.fill (i32.const 0xFF00) (i32.const 0x55) (i32.const 257))
)
)`
)));
);
assertErrorMessage(() => inst.exports.testfn(),
WebAssembly.RuntimeError, /index out of bounds/);
}
// Wraparound the end of 32-bit offset space
{
let inst = new WebAssembly.Instance(new WebAssembly.Module(wasmTextToBinary(
let inst = wasmEvalText(
`(module
(memory (export "memory") 1 1)
(func (export "testfn")
(memory.fill (i32.const 0xFFFFFF00) (i32.const 0x55) (i32.const 257))
)
)`
)));
);
assertErrorMessage(() => inst.exports.testfn(),
WebAssembly.RuntimeError, /index out of bounds/);
}
// Zero len with offset in-bounds is a no-op
{
let inst = new WebAssembly.Instance(new WebAssembly.Module(wasmTextToBinary(
let inst = wasmEvalText(
`(module
(memory (export "memory") 1 1)
(func (export "testfn")
(memory.fill (i32.const 0x12) (i32.const 0x55) (i32.const 0))
)
)`
)));
);
inst.exports.testfn();
let b = new Uint8Array(inst.exports.memory.buffer);
checkRange(b, 0x00000, 0x10000, 0x00);
@ -198,28 +269,28 @@ function checkRange(arr, minIx, maxIxPlusOne, expectedValue)
// Zero len with offset out-of-bounds gets an exception
{
let inst = new WebAssembly.Instance(new WebAssembly.Module(wasmTextToBinary(
let inst = wasmEvalText(
`(module
(memory (export "memory") 1 1)
(func (export "testfn")
(memory.fill (i32.const 0x10000) (i32.const 0x55) (i32.const 0))
)
)`
)));
);
assertErrorMessage(() => inst.exports.testfn(),
WebAssembly.RuntimeError, /index out of bounds/);
}
// Very large range
{
let inst = new WebAssembly.Instance(new WebAssembly.Module(wasmTextToBinary(
let inst = wasmEvalText(
`(module
(memory (export "memory") 1 1)
(func (export "testfn")
(memory.fill (i32.const 0x1) (i32.const 0xAA) (i32.const 0xFFFE))
)
)`
)));
);
inst.exports.testfn();
let b = new Uint8Array(inst.exports.memory.buffer);
checkRange(b, 0x00000, 0x00001, 0x00);
@ -229,7 +300,7 @@ function checkRange(arr, minIx, maxIxPlusOne, expectedValue)
// Sequencing
{
let i = new WebAssembly.Instance(new WebAssembly.Module(wasmTextToBinary(
let i = wasmEvalText(
`(module
(memory (export "memory") 1 1)
(func (export "testfn") (result i32)
@ -238,7 +309,7 @@ function checkRange(arr, minIx, maxIxPlusOne, expectedValue)
i32.const 99
)
)`
)));
);
i.exports.testfn();
let b = new Uint8Array(i.exports.memory.buffer);
checkRange(b, 0x0, 0x12+0, 0x00);
@ -255,7 +326,7 @@ function checkRange(arr, minIx, maxIxPlusOne, expectedValue)
// Both ranges valid. Copy 5 bytes backwards by 1 (overlapping).
// result = 0x00--(09) 0x55--(11) 0x00--(pagesize-20)
{
let inst = new WebAssembly.Instance(new WebAssembly.Module(wasmTextToBinary(
let inst = wasmEvalText(
`(module
(memory (export "memory") 1 1)
(func (export "testfn")
@ -263,7 +334,7 @@ function checkRange(arr, minIx, maxIxPlusOne, expectedValue)
(memory.copy (i32.const 9) (i32.const 10) (i32.const 5))
)
)`
)));
);
inst.exports.testfn();
let b = new Uint8Array(inst.exports.memory.buffer);
checkRange(b, 0, 0+9, 0x00);
@ -274,7 +345,7 @@ function checkRange(arr, minIx, maxIxPlusOne, expectedValue)
// Both ranges valid. Copy 5 bytes forwards by 1 (overlapping).
// result = 0x00--(10) 0x55--(11) 0x00--(pagesize-19)
{
let inst = new WebAssembly.Instance(new WebAssembly.Module(wasmTextToBinary(
let inst = wasmEvalText(
`(module
(memory (export "memory") 1 1)
(func (export "testfn")
@ -282,7 +353,7 @@ function checkRange(arr, minIx, maxIxPlusOne, expectedValue)
(memory.copy (i32.const 16) (i32.const 15) (i32.const 5))
)
)`
)));
);
inst.exports.testfn();
let b = new Uint8Array(inst.exports.memory.buffer);
checkRange(b, 0, 0+10, 0x00);
@ -292,63 +363,63 @@ function checkRange(arr, minIx, maxIxPlusOne, expectedValue)
// Destination range invalid
{
let inst = new WebAssembly.Instance(new WebAssembly.Module(wasmTextToBinary(
let inst = wasmEvalText(
`(module
(memory (export "memory") 1 1)
(func (export "testfn")
(memory.copy (i32.const 0xFF00) (i32.const 0x8000) (i32.const 257))
)
)`
)));
);
assertErrorMessage(() => inst.exports.testfn(),
WebAssembly.RuntimeError, /index out of bounds/);
}
// Destination wraparound the end of 32-bit offset space
{
let inst = new WebAssembly.Instance(new WebAssembly.Module(wasmTextToBinary(
let inst = wasmEvalText(
`(module
(memory (export "memory") 1 1)
(func (export "testfn")
(memory.copy (i32.const 0xFFFFFF00) (i32.const 0x4000) (i32.const 257))
)
)`
)));
);
assertErrorMessage(() => inst.exports.testfn(),
WebAssembly.RuntimeError, /index out of bounds/);
}
// Source range invalid
{
let inst = new WebAssembly.Instance(new WebAssembly.Module(wasmTextToBinary(
let inst = wasmEvalText(
`(module
(memory (export "memory") 1 1)
(func (export "testfn")
(memory.copy (i32.const 0x8000) (i32.const 0xFF00) (i32.const 257))
)
)`
)));
);
assertErrorMessage(() => inst.exports.testfn(),
WebAssembly.RuntimeError, /index out of bounds/);
}
// Source wraparound the end of 32-bit offset space
{
let inst = new WebAssembly.Instance(new WebAssembly.Module(wasmTextToBinary(
let inst = wasmEvalText(
`(module
(memory (export "memory") 1 1)
(func (export "testfn")
(memory.copy (i32.const 0x4000) (i32.const 0xFFFFFF00) (i32.const 257))
)
)`
)));
);
assertErrorMessage(() => inst.exports.testfn(),
WebAssembly.RuntimeError, /index out of bounds/);
}
// Zero len with both offsets in-bounds is a no-op
{
let inst = new WebAssembly.Instance(new WebAssembly.Module(wasmTextToBinary(
let inst = wasmEvalText(
`(module
(memory (export "memory") 1 1)
(func (export "testfn")
@ -357,7 +428,7 @@ function checkRange(arr, minIx, maxIxPlusOne, expectedValue)
(memory.copy (i32.const 0x9000) (i32.const 0x7000) (i32.const 0))
)
)`
)));
);
inst.exports.testfn();
let b = new Uint8Array(inst.exports.memory.buffer);
checkRange(b, 0x00000, 0x08000, 0x55);
@ -366,28 +437,28 @@ function checkRange(arr, minIx, maxIxPlusOne, expectedValue)
// Zero len with dest offset out-of-bounds is an exception
{
let inst = new WebAssembly.Instance(new WebAssembly.Module(wasmTextToBinary(
let inst = wasmEvalText(
`(module
(memory (export "memory") 1 1)
(func (export "testfn")
(memory.copy (i32.const 0x10000) (i32.const 0x7000) (i32.const 0))
)
)`
)));
);
assertErrorMessage(() => inst.exports.testfn(),
WebAssembly.RuntimeError, /index out of bounds/);
}
// Zero len with src offset out-of-bounds is an exception
{
let inst = new WebAssembly.Instance(new WebAssembly.Module(wasmTextToBinary(
let inst = wasmEvalText(
`(module
(memory (export "memory") 1 1)
(func (export "testfn")
(memory.copy (i32.const 0x9000) (i32.const 0x10000) (i32.const 0))
)
)`
)));
);
assertErrorMessage(() => inst.exports.testfn(),
WebAssembly.RuntimeError, /index out of bounds/);
}
@ -395,7 +466,7 @@ function checkRange(arr, minIx, maxIxPlusOne, expectedValue)
// 100 random fills followed by 100 random copies, in a single-page buffer,
// followed by verification of the (now heavily mashed-around) buffer.
{
let inst = new WebAssembly.Instance(new WebAssembly.Module(wasmTextToBinary(
let inst = wasmEvalText(
`(module
(memory (export "memory") 1 1)
(func (export "testfn")
@ -601,7 +672,7 @@ function checkRange(arr, minIx, maxIxPlusOne, expectedValue)
(memory.copy (i32.const 50370) (i32.const 41271) (i32.const 1406))
)
)`
)));
);
inst.exports.testfn();
let b = new Uint8Array(inst.exports.memory.buffer);
checkRange(b, 0, 124, 0);

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

@ -4409,6 +4409,16 @@ nsDisplayTableBackgroundImage::nsDisplayTableBackgroundImage(nsDisplayListBuilde
, mStyleFrame(aCellFrame)
, mTableType(GetTableTypeFromFrame(mStyleFrame))
{
if (aBuilder->IsRetainingDisplayList()) {
mStyleFrame->AddDisplayItem(this);
}
}
nsDisplayTableBackgroundImage::~nsDisplayTableBackgroundImage()
{
if (mStyleFrame) {
mStyleFrame->RemoveDisplayItem(this);
}
}
bool
@ -7461,6 +7471,9 @@ nsDisplayTableFixedPosition::nsDisplayTableFixedPosition(nsDisplayListBuilder* a
, mAncestorFrame(aAncestorFrame)
, mTableType(GetTableTypeFromFrame(aAncestorFrame))
{
if (aBuilder->IsRetainingDisplayList()) {
mAncestorFrame->AddDisplayItem(this);
}
}
/* static */ nsDisplayTableFixedPosition*

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

@ -4226,6 +4226,7 @@ TableType GetTableTypeFromFrame(nsIFrame* aFrame);
class nsDisplayTableBackgroundImage : public nsDisplayBackgroundImage {
public:
nsDisplayTableBackgroundImage(nsDisplayListBuilder* aBuilder, const InitData& aInitData, nsIFrame* aCellFrame);
~nsDisplayTableBackgroundImage();
virtual uint32_t GetPerFrameKey() const override {
return (mLayer << (TYPE_BITS + static_cast<uint8_t>(TableTypeBits::COUNT))) |
@ -4237,6 +4238,17 @@ public:
virtual nsIFrame* FrameForInvalidation() const override { return mStyleFrame; }
virtual bool HasDeletedFrame() const override {
return !mStyleFrame || nsDisplayBackgroundImage::HasDeletedFrame();
}
virtual void RemoveFrame(nsIFrame* aFrame) override {
if (aFrame == mStyleFrame) {
mStyleFrame = nullptr;
}
nsDisplayBackgroundImage::RemoveFrame(aFrame);
}
NS_DISPLAY_DECL_NAME("TableBackgroundImage", TYPE_TABLE_BACKGROUND_IMAGE)
protected:
virtual nsIFrame* StyleFrame() const override { return mStyleFrame; }
@ -4324,7 +4336,16 @@ public:
: nsDisplayThemedBackground(aBuilder, aFrame, aBackgroundRect)
, mAncestorFrame(aAncestorFrame)
, mTableType(GetTableTypeFromFrame(aAncestorFrame))
{ }
{
if (aBuilder->IsRetainingDisplayList()) {
mAncestorFrame->AddDisplayItem(this);
}
}
~nsDisplayTableThemedBackground() {
if (mAncestorFrame) {
mAncestorFrame->RemoveDisplayItem(this);
}
}
virtual uint32_t GetPerFrameKey() const override {
return (static_cast<uint8_t>(mTableType) << TYPE_BITS) |
@ -4333,6 +4354,17 @@ public:
virtual nsIFrame* FrameForInvalidation() const override { return mAncestorFrame; }
virtual bool HasDeletedFrame() const override {
return !mAncestorFrame || nsDisplayThemedBackground::HasDeletedFrame();
}
virtual void RemoveFrame(nsIFrame* aFrame) override {
if (aFrame == mAncestorFrame) {
mAncestorFrame = nullptr;
}
nsDisplayThemedBackground::RemoveFrame(aFrame);
}
NS_DISPLAY_DECL_NAME("TableThemedBackground", TYPE_TABLE_THEMED_BACKGROUND_IMAGE)
protected:
virtual nsIFrame* StyleFrame() const override { return mAncestorFrame; }
@ -4467,10 +4499,30 @@ public:
: nsDisplayBackgroundColor(aBuilder, aFrame, aBackgroundRect, aBackgroundStyle, aColor)
, mAncestorFrame(aAncestorFrame)
, mTableType(GetTableTypeFromFrame(aAncestorFrame))
{ }
{
if (aBuilder->IsRetainingDisplayList()) {
mAncestorFrame->AddDisplayItem(this);
}
}
~nsDisplayTableBackgroundColor() {
if (mAncestorFrame) {
mAncestorFrame->RemoveDisplayItem(this);
}
}
virtual nsIFrame* FrameForInvalidation() const override { return mAncestorFrame; }
virtual bool HasDeletedFrame() const override {
return !mAncestorFrame || nsDisplayBackgroundColor::HasDeletedFrame();
}
virtual void RemoveFrame(nsIFrame* aFrame) override {
if (aFrame == mAncestorFrame) {
mAncestorFrame = nullptr;
}
nsDisplayBackgroundColor::RemoveFrame(aFrame);
}
virtual uint32_t GetPerFrameKey() const override {
return (static_cast<uint8_t>(mTableType) << TYPE_BITS) |
nsDisplayItem::GetPerFrameKey();
@ -5459,14 +5511,27 @@ public:
: nsDisplayBlendMode(aBuilder, aFrame, aList, aBlendMode, aActiveScrolledRoot, aIndex)
, mAncestorFrame(aAncestorFrame)
, mTableType(GetTableTypeFromFrame(aAncestorFrame))
{}
{
if (aBuilder->IsRetainingDisplayList()) {
mAncestorFrame->AddDisplayItem(this);
}
}
nsDisplayTableBlendMode(nsDisplayListBuilder* aBuilder,
const nsDisplayTableBlendMode& aOther)
: nsDisplayBlendMode(aBuilder, aOther)
, mAncestorFrame(aOther.mAncestorFrame)
, mTableType(aOther.mTableType)
{}
{
if (aBuilder->IsRetainingDisplayList()) {
mAncestorFrame->AddDisplayItem(this);
}
}
~nsDisplayTableBlendMode() {
if (mAncestorFrame) {
mAncestorFrame->RemoveDisplayItem(this);
}
}
virtual nsDisplayWrapList* Clone(nsDisplayListBuilder* aBuilder) const override
{
@ -5475,6 +5540,17 @@ public:
virtual nsIFrame* FrameForInvalidation() const override { return mAncestorFrame; }
virtual bool HasDeletedFrame() const override {
return !mAncestorFrame || nsDisplayBlendMode::HasDeletedFrame();
}
virtual void RemoveFrame(nsIFrame* aFrame) override {
if (aFrame == mAncestorFrame) {
mAncestorFrame = nullptr;
}
nsDisplayBlendMode::RemoveFrame(aFrame);
}
virtual uint32_t GetPerFrameKey() const override {
return (mIndex << (TYPE_BITS + static_cast<uint8_t>(TableTypeBits::COUNT))) |
(static_cast<uint8_t>(mTableType) << TYPE_BITS) |
@ -5571,6 +5647,17 @@ public:
virtual nsIFrame* FrameForInvalidation() const override { return mAncestorFrame; }
virtual bool HasDeletedFrame() const override {
return !mAncestorFrame || nsDisplayBlendContainer::HasDeletedFrame();
}
virtual void RemoveFrame(nsIFrame* aFrame) override {
if (aFrame == mAncestorFrame) {
mAncestorFrame = nullptr;
}
nsDisplayBlendContainer::RemoveFrame(aFrame);
}
virtual uint32_t GetPerFrameKey() const override {
return (static_cast<uint8_t>(mTableType) << TYPE_BITS) |
nsDisplayItem::GetPerFrameKey();
@ -5586,14 +5673,27 @@ protected:
: nsDisplayBlendContainer(aBuilder, aFrame, aList, aActiveScrolledRoot, aIsForBackground)
, mAncestorFrame(aAncestorFrame)
, mTableType(GetTableTypeFromFrame(aAncestorFrame))
{}
{
if (aBuilder->IsRetainingDisplayList()) {
mAncestorFrame->AddDisplayItem(this);
}
}
nsDisplayTableBlendContainer(nsDisplayListBuilder* aBuilder,
const nsDisplayTableBlendContainer& aOther)
: nsDisplayBlendContainer(aBuilder, aOther)
, mAncestorFrame(aOther.mAncestorFrame)
, mTableType(aOther.mTableType)
{}
{
if (aBuilder->IsRetainingDisplayList()) {
mAncestorFrame->AddDisplayItem(this);
}
}
~nsDisplayTableBlendContainer() {
if (mAncestorFrame) {
mAncestorFrame->RemoveDisplayItem(this);
}
}
nsIFrame* mAncestorFrame;
TableType mTableType;
@ -5939,6 +6039,17 @@ public:
virtual nsIFrame* FrameForInvalidation() const override { return mAncestorFrame; }
virtual bool HasDeletedFrame() const override {
return !mAncestorFrame || nsDisplayFixedPosition::HasDeletedFrame();
}
virtual void RemoveFrame(nsIFrame* aFrame) override {
if (aFrame == mAncestorFrame) {
mAncestorFrame = nullptr;
}
nsDisplayFixedPosition::RemoveFrame(aFrame);
}
virtual uint32_t GetPerFrameKey() const override {
return (mIndex << (TYPE_BITS + static_cast<uint8_t>(TableTypeBits::COUNT))) |
(static_cast<uint8_t>(mTableType) << TYPE_BITS) |
@ -5956,7 +6067,16 @@ protected:
: nsDisplayFixedPosition(aBuilder, aOther)
, mAncestorFrame(aOther.mAncestorFrame)
, mTableType(aOther.mTableType)
{}
{
if (aBuilder->IsRetainingDisplayList()) {
mAncestorFrame->AddDisplayItem(this);
}
}
~nsDisplayTableFixedPosition() {
if (mAncestorFrame) {
mAncestorFrame->RemoveDisplayItem(this);
}
}
nsIFrame* mAncestorFrame;
TableType mTableType;

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

@ -1196,9 +1196,9 @@ fuzzy-if(webrender,4,361) == 449519-1.html 449519-1-ref.html
== 455280-1.xhtml 455280-1-ref.xhtml
== 455826-1.html 455826-1-ref.html
fails-if(Android||cocoaWidget||winWidget) == 456147.xul 456147-ref.html # bug 458047
fuzzy-if(Android,11,41) fuzzy-if(winWidget||gtkWidget,4,6) fuzzy-if(d2d,15,69) fuzzy-if(skiaContent,42,154) fuzzy-if(webrender,56-60,450-497) == 456219-1a.html 456219-1-ref.html # bug 1128229
fuzzy-if(Android,11,41) fuzzy-if(winWidget||gtkWidget,4,6) fuzzy-if(d2d,15,69) fuzzy-if(skiaContent,42,154) fuzzy-if(webrender,56-60,450-497) == 456219-1b.html 456219-1-ref.html # bug 1128229
fuzzy-if(Android,11,41) fuzzy-if(winWidget||gtkWidget,4,6) fuzzy-if(d2d,15,69) fuzzy-if(skiaContent,42,154) fuzzy-if(webrender,56-60,450-497) == 456219-1c.html 456219-1-ref.html # bug 1128229
fuzzy-if(Android,11,41) fuzzy-if(winWidget||gtkWidget,4,6) fuzzy-if(d2d,15,69) fuzzy-if(skiaContent,42,154) fuzzy-if(webrender,56-60,449-497) == 456219-1a.html 456219-1-ref.html # bug 1128229
fuzzy-if(Android,11,41) fuzzy-if(winWidget||gtkWidget,4,6) fuzzy-if(d2d,15,69) fuzzy-if(skiaContent,42,154) fuzzy-if(webrender,56-60,449-497) == 456219-1b.html 456219-1-ref.html # bug 1128229
fuzzy-if(Android,11,41) fuzzy-if(winWidget||gtkWidget,4,6) fuzzy-if(d2d,15,69) fuzzy-if(skiaContent,42,154) fuzzy-if(webrender,56-60,449-497) == 456219-1c.html 456219-1-ref.html # bug 1128229
fuzzy-if(skiaContent,1,45) fuzzy-if(webrender,9-9,8-8) == 456219-2.html 456219-2-ref.html
== 456330-1.gif 456330-1-ref.png
== 456484-1.html 456484-1-ref.html

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

@ -1,62 +1,62 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>CSS Reftest Reference</title>
<link rel="author" title="Yusuf Sermet" href="mailto:ysermet@mozilla.com">
<style>
div {
position: relative;
width: 100px;
}
#div1,
#div3 {
background-color: #cfc;
}
#div1 {
z-index: 5;
}
#div2 {
z-index: 1;
background-color: #fdd;
height: 100px;
top: -20px;
}
#div2_1 {
background-color: #ffc;
z-index: 6;
top: -10px;
}
#div2_2 {
z-index: 3;
position: absolute;
top: -15px;
width: 40px;
height: 100px;
background-color: #ddf;
}
#div3 {
z-index: 2;
top: -50px;
}
</style>
</head>
<body>
<div id="div1">
<br/><br/>
</div>
<div id="div2">
<div id="div2_1">
<br/><br/>
</div>
<div id="div2_2">
</div>
</div>
<div id="div3">
<br/><br/>
</div>
</body>
</html>
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>CSS Reftest Reference</title>
<link rel="author" title="Yusuf Sermet" href="mailto:ysermet@mozilla.com">
<style>
div {
position: relative;
width: 100px;
}
#div1,
#div3 {
background-color: #cfc;
}
#div1 {
z-index: 5;
}
#div2 {
z-index: 1;
background-color: #fdd;
height: 100px;
top: -20px;
}
#div2_1 {
background-color: #ffc;
z-index: 6;
top: -10px;
}
#div2_2 {
z-index: 3;
position: absolute;
top: -15px;
width: 40px;
height: 100px;
background-color: #ddf;
}
#div3 {
z-index: 2;
top: -50px;
}
</style>
</head>
<body>
<div id="div1">
<br/><br/>
</div>
<div id="div2">
<div id="div2_1">
<br/><br/>
</div>
<div id="div2_2">
</div>
</div>
<div id="div3">
<br/><br/>
</div>
</body>
</html>

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

@ -1,66 +1,66 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>CSS Test: 'contain: paint' with stacking contents. Z-index is defined only for siblings and children.</title>
<link rel="author" title="Yusuf Sermet" href="mailto:ysermet@mozilla.com">
<link rel="help" href="https://drafts.csswg.org/css2/visuren.html#x43">
<link rel="help" href="https://drafts.csswg.org/css-contain/#containment-paint">
<link rel="match" href="contain-paint-stacking-context-001-ref.html">
<style>
div {
position: relative;
width: 100px;
}
#div1,
#div3 {
background-color: #cfc;
}
#div1 {
z-index: 5;
}
#div2 {
contain: paint;
background-color: #fdd;
height: 100px;
top: -20px;
}
#div2_1 {
background-color: #ffc;
z-index: 6;
top: -10px;
}
#div2_2 {
z-index: 3;
position: absolute;
top: -15px;
width: 40px;
height: 100px;
background-color: #ddf;
}
#div3 {
z-index: 2;
top: -50px;
}
</style>
</head>
<body>
<div id="div1">
<br/><br/>
</div>
<div id="div2">
<div id="div2_1">
<br/><br/>
</div>
<div id="div2_2">
</div>
</div>
<div id="div3">
<br/><br/>
</div>
</body>
</html>
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>CSS Test: 'contain: paint' with stacking contents. Z-index is defined only for siblings and children.</title>
<link rel="author" title="Yusuf Sermet" href="mailto:ysermet@mozilla.com">
<link rel="help" href="https://drafts.csswg.org/css2/visuren.html#x43">
<link rel="help" href="https://drafts.csswg.org/css-contain/#containment-paint">
<link rel="match" href="contain-paint-stacking-context-001-ref.html">
<style>
div {
position: relative;
width: 100px;
}
#div1,
#div3 {
background-color: #cfc;
}
#div1 {
z-index: 5;
}
#div2 {
contain: paint;
background-color: #fdd;
height: 100px;
top: -20px;
}
#div2_1 {
background-color: #ffc;
z-index: 6;
top: -10px;
}
#div2_2 {
z-index: 3;
position: absolute;
top: -15px;
width: 40px;
height: 100px;
background-color: #ddf;
}
#div3 {
z-index: 2;
top: -50px;
}
</style>
</head>
<body>
<div id="div1">
<br/><br/>
</div>
<div id="div2">
<div id="div2_1">
<br/><br/>
</div>
<div id="div2_2">
</div>
</div>
<div id="div3">
<br/><br/>
</div>
</body>
</html>

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

@ -1,66 +1,66 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>CSS Test: 'will-change: contain' with stacking contents. Z-index is defined only for siblings and children.</title>
<link rel="author" title="Yusuf Sermet" href="mailto:ysermet@mozilla.com">
<link rel="help" href="https://drafts.csswg.org/css2/visuren.html#x43">
<link rel="help" href="https://drafts.csswg.org/css-contain/#containment-paint">
<link rel="match" href="contain-paint-stacking-context-001-ref.html">
<style>
div {
position: relative;
width: 100px;
}
#div1,
#div3 {
background-color: #cfc;
}
#div1 {
z-index: 5;
}
#div2 {
will-change: contain;
background-color: #fdd;
height: 100px;
top: -20px;
}
#div2_1 {
background-color: #ffc;
z-index: 6;
top: -10px;
}
#div2_2 {
z-index: 3;
position: absolute;
top: -15px;
width: 40px;
height: 100px;
background-color: #ddf;
}
#div3 {
z-index: 2;
top: -50px;
}
</style>
</head>
<body>
<div id="div1">
<br/><br/>
</div>
<div id="div2">
<div id="div2_1">
<br/><br/>
</div>
<div id="div2_2">
</div>
</div>
<div id="div3">
<br/><br/>
</div>
</body>
</html>
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>CSS Test: 'will-change: contain' with stacking contents. Z-index is defined only for siblings and children.</title>
<link rel="author" title="Yusuf Sermet" href="mailto:ysermet@mozilla.com">
<link rel="help" href="https://drafts.csswg.org/css2/visuren.html#x43">
<link rel="help" href="https://drafts.csswg.org/css-contain/#containment-paint">
<link rel="match" href="contain-paint-stacking-context-001-ref.html">
<style>
div {
position: relative;
width: 100px;
}
#div1,
#div3 {
background-color: #cfc;
}
#div1 {
z-index: 5;
}
#div2 {
will-change: contain;
background-color: #fdd;
height: 100px;
top: -20px;
}
#div2_1 {
background-color: #ffc;
z-index: 6;
top: -10px;
}
#div2_2 {
z-index: 3;
position: absolute;
top: -15px;
width: 40px;
height: 100px;
background-color: #ddf;
}
#div3 {
z-index: 2;
top: -50px;
}
</style>
</head>
<body>
<div id="div1">
<br/><br/>
</div>
<div id="div2">
<div id="div2_1">
<br/><br/>
</div>
<div id="div2_2">
</div>
</div>
<div id="div3">
<br/><br/>
</div>
</body>
</html>

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

@ -84,67 +84,20 @@ private:
};
template <typename MMPolicy, uint32_t kChunkSize>
class VMSharingPolicyShared : public MMPolicyBase
class VMSharingPolicyShared;
// We only support this policy for in-proc MMPolicy
template <uint32_t kChunkSize>
class VMSharingPolicyShared<MMPolicyInProcess, kChunkSize> : public MMPolicyBase
{
typedef VMSharingPolicyUnique<MMPolicy, kChunkSize> ValueT;
// We use pid instead of HANDLE for mapping, since more than one handle may
// map to the same pid. We don't worry about pid reuse becuase each mVMPolicy
// holds an open handle to pid, thus keeping the pid reserved at least for the
// lifetime of mVMPolicy.
struct ProcMapEntry
{
ProcMapEntry()
: mPid(::GetCurrentProcessId())
{
}
explicit ProcMapEntry(HANDLE aProc)
: mPid(::GetProcessId(aProc))
, mVMPolicy(aProc)
{
}
ProcMapEntry(ProcMapEntry&& aOther)
: mPid(aOther.mPid)
, mVMPolicy(Move(aOther.mVMPolicy))
{
aOther.mPid = 0;
}
ProcMapEntry(const ProcMapEntry&) = delete;
ProcMapEntry& operator=(const ProcMapEntry&) = delete;
ProcMapEntry& operator=(ProcMapEntry&& aOther)
{
mPid = aOther.mPid;
mVMPolicy = Move(aOther.mVMPolicy);
aOther.mPid = 0;
return *this;
}
bool operator==(DWORD aPid) const
{
return mPid == aPid;
}
DWORD mPid;
ValueT mVMPolicy;
};
// We normally expect to reference only one other process at a time, but this
// is not a requirement.
typedef Vector<ProcMapEntry, 1> MapT;
typedef VMSharingPolicyUnique<MMPolicyInProcess, kChunkSize> UniquePolicyT;
public:
typedef MMPolicy MMPolicyT;
typedef MMPolicyInProcess MMPolicyT;
template <typename... Args>
explicit VMSharingPolicyShared(Args... aArgs)
: mPid(GetPid(aArgs...))
VMSharingPolicyShared()
{
static const bool isAlloc = []() -> bool {
sPerProcVM = new MapT();
DWORD flags = 0;
#if defined(RELEASE_OR_BETA)
flags |= CRITICAL_SECTION_NO_DEBUG_INFO;
@ -152,101 +105,48 @@ public:
::InitializeCriticalSectionEx(&sCS, 4000, flags);
return true;
}();
MOZ_ASSERT(mPid);
if (!mPid) {
return;
}
AutoCriticalSection lock(&sCS);
if (find(mPid)) {
return;
}
bool appended = sPerProcVM->append(ProcMapEntry(aArgs...));
MOZ_RELEASE_ASSERT(appended);
}
explicit operator bool() const
{
AutoCriticalSection lock(&sCS);
ProcMapEntry* entry;
bool found = find(mPid, &entry);
MOZ_RELEASE_ASSERT(found);
return !!entry->mVMPolicy;
return !!sUniqueVM;
}
operator const MMPolicy&() const
operator const MMPolicyInProcess&() const
{
AutoCriticalSection lock(&sCS);
ProcMapEntry* entry;
bool found = find(mPid, &entry);
MOZ_RELEASE_ASSERT(found);
return entry->mVMPolicy;
return sUniqueVM;
}
bool ShouldUnhookUponDestruction() const
{
AutoCriticalSection lock(&sCS);
ProcMapEntry* entry;
if (!find(mPid, &entry)) {
return 0;
}
return entry->mVMPolicy.ShouldUnhookUponDestruction();
return sUniqueVM.ShouldUnhookUponDestruction();
}
bool Reserve(uint32_t aCount)
{
AutoCriticalSection lock(&sCS);
ProcMapEntry* entry;
if (!find(mPid, &entry)) {
return false;
}
return entry->mVMPolicy.Reserve(aCount);
return sUniqueVM.Reserve(aCount);
}
bool IsPageAccessible(void* aVAddress) const
{
AutoCriticalSection lock(&sCS);
ProcMapEntry* entry;
if (!find(mPid, &entry)) {
return false;
}
return entry->mVMPolicy.IsPageAccessible(aVAddress);
return sUniqueVM.IsPageAccessible(aVAddress);
}
Trampoline<MMPolicy> GetNextTrampoline()
Trampoline<MMPolicyInProcess> GetNextTrampoline()
{
AutoCriticalSection lock(&sCS);
ProcMapEntry* entry;
if (!find(mPid, &entry)) {
return nullptr;
}
return entry->mVMPolicy.GetNextTrampoline();
return sUniqueVM.GetNextTrampoline();
}
TrampolineCollection<MMPolicy> Items() const
TrampolineCollection<MMPolicyInProcess> Items() const
{
AutoCriticalSection lock(&sCS);
ProcMapEntry* entry;
bool found = find(mPid, &entry);
MOZ_RELEASE_ASSERT(found);
TrampolineCollection<MMPolicy> items(Move(entry->mVMPolicy.Items()));
TrampolineCollection<MMPolicyInProcess> items(Move(sUniqueVM.Items()));
// We need to continue holding the lock until items is destroyed.
items.Lock(sCS);
@ -268,43 +168,16 @@ public:
VMSharingPolicyShared& operator=(VMSharingPolicyShared&&) = delete;
private:
static bool find(DWORD aPid, ProcMapEntry** aOutEntry = nullptr)
{
MOZ_ASSERT(sPerProcVM);
if (!sPerProcVM) {
return false;
}
if (aOutEntry) {
*aOutEntry = nullptr;
}
for (auto&& mapping : *sPerProcVM) {
if (mapping == aPid) {
if (aOutEntry) {
*aOutEntry = &mapping;
}
return true;
}
}
return false;
}
static DWORD GetPid() { return ::GetCurrentProcessId(); }
static DWORD GetPid(HANDLE aHandle) { return ::GetProcessId(aHandle); }
DWORD mPid;
static MapT* sPerProcVM;
static UniquePolicyT sUniqueVM;
static CRITICAL_SECTION sCS;
};
template <typename MMPolicy, uint32_t kChunkSize>
typename VMSharingPolicyShared<MMPolicy, kChunkSize>::MapT *
VMSharingPolicyShared<MMPolicy, kChunkSize>::sPerProcVM;
template <uint32_t kChunkSize>
typename VMSharingPolicyShared<MMPolicyInProcess, kChunkSize>::UniquePolicyT
VMSharingPolicyShared<MMPolicyInProcess, kChunkSize>::sUniqueVM;
template <typename MMPolicy, uint32_t kChunkSize>
CRITICAL_SECTION VMSharingPolicyShared<MMPolicy, kChunkSize>::sCS;
template <uint32_t kChunkSize>
CRITICAL_SECTION VMSharingPolicyShared<MMPolicyInProcess, kChunkSize>::sCS;
} // namespace interceptor
} // namespace mozilla

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

@ -140,7 +140,7 @@ nsBufferedStream::Seek(int32_t whence, int64_t offset)
nsCOMPtr<nsISeekableStream> ras = do_QueryInterface(mStream, &rv);
if (NS_FAILED(rv)) {
#ifdef DEBUG
NS_ERROR("mStream doesn't QI to nsISeekableStream");
NS_WARNING("mStream doesn't QI to nsISeekableStream");
#endif
return rv;
}

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

@ -277,3 +277,37 @@ macosx64-nightly/opt:
- linux64-llvm-dsymutil
- linux64-rust-macos
- linux64-sccache
macosx64-ccov/debug:
description: "MacOS X x64 Cross-compile Code Coverage"
index:
product: firefox
job-name: macosx64-ccov-debug
treeherder:
platform: osx-cross-ccov/debug
symbol: B
tier: 1
worker-type: aws-provisioner-v1/gecko-{level}-b-macosx64
worker:
max-run-time: 5400
env:
TOOLTOOL_MANIFEST: "browser/config/tooltool-manifests/macosx64/cross-releng.manifest"
run:
using: mozharness
actions: [get-secrets build update]
config:
- builds/releng_base_firefox.py
- builds/releng_base_mac_64_cross_builds.py
script: "mozharness/scripts/fx_desktop_build.py"
secrets: true
custom-build-variant-cfg: code-coverage-debug
tooltool-downloads: internal
run-on-projects: ['try']
toolchains:
- linux64-cctools-port
- linux64-clang-6-pre-macosx-cross
- linux64-hfsplus
- linux64-libdmg
- linux64-llvm-dsymutil
- linux64-rust-macos
- linux64-sccache

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

@ -261,6 +261,11 @@ macosx64-qr/debug:
test-sets:
- macosx64-qr-tests
macosx64-ccov/debug:
build-platform: macosx64-ccov/debug
test-sets:
- macosx64-tests
##
# Android platforms (matching /android.*/)

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

@ -33,6 +33,7 @@ BUILDER_NAME_PREFIX = {
'linux64-devedition-nightly': 'Ubuntu VM 12.04 x64',
'macosx64': 'Rev7 MacOSX Yosemite 10.10.5',
'macosx64-devedition': 'Rev7 MacOSX Yosemite 10.10.5 DevEdition',
'macosx64-ccov': 'Rev7 MacOSX Yosemite 10.10.5 Code Coverage',
'android-4.3-arm7-api-16': 'Android 4.3 armv7 api-16+',
'android-4.2-x86': 'Android 4.2 x86 Emulator',
'android-4.3-arm7-api-16-gradle': 'Android 4.3 armv7 api-16+',

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

@ -702,8 +702,7 @@ def handle_suite_category(config, tests):
@transforms.add
def enable_code_coverage(config, tests):
"""Enable code coverage for the linux64-ccov/.* & linux64-jsdcov/.* & win64-ccov/.*
build-platforms"""
"""Enable code coverage for the ccov and jsdcov build-platforms"""
for test in tests:
if 'ccov' in test['build-platform'] and not test['test-name'].startswith('test-verify'):
test['mozharness'].setdefault('extra-options', []).append('--code-coverage')

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

@ -0,0 +1,29 @@
import os
config = {
'default_actions': [
'clobber',
'build',
'check-test',
'update', # decided by query_is_nightly()
],
'stage_platform': 'macosx64-ccov-debug',
'debug_build': True,
#### 64 bit build specific #####
'env': {
'MOZBUILD_STATE_PATH': os.path.join(os.getcwd(), '.mozbuild'),
'HG_SHARE_BASE_DIR': '/builds/hg-shared',
'MOZ_OBJDIR': '%(abs_obj_dir)s',
'TINDERBOX_OUTPUT': '1',
'TOOLTOOL_CACHE': '/builds/tooltool_cache',
'TOOLTOOL_HOME': '/builds',
'MOZ_CRASHREPORTER_NO_REPORT': '1',
'LC_ALL': 'C',
## 64 bit specific
'PATH': '/tools/python/bin:/opt/local/bin:/usr/bin:'
'/bin:/usr/sbin:/sbin:/usr/local/bin:/usr/X11/bin',
##
},
'mozconfig_variant': 'code-coverage-debug',
#######################
}

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

@ -1,3 +1,2 @@
[label-attributes.html]
prefs: [dom.webcomponents.shadowdom.enabled:true]
max-asserts: 8

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

@ -227,7 +227,8 @@
}, "A labelable element is moved to iframe.");
test(function () {
var labels1 = document.getElementById("test14").labels;
var test14 = document.getElementById("test14");
var labels1 = test14.labels;
var labels2 = document.getElementById("test15").labels;
assert_true(labels1 instanceof NodeList,
"A form control's 'labels' property should be an instance of a NodeList.");
@ -237,12 +238,17 @@
"The number of labels associated with a form control should be the number of label elements for which it is a labeled control.");
assert_array_equals(labels1, [document.getElementById("lbl14")],
"The labels for a form control should be returned in tree order.");
assert_array_equals(labels2, [document.getElementById("lbl15")],
"The labels for a form control should be returned in tree order.");
document.getElementById('div6').removeChild(document.getElementById('div7'));
assert_equals(labels1.length, 0,
"The number of labels should be 0 after the labelable element is removed.");
assert_equals(labels1.length, 1,
"The number of labels should be 1 after the labelable element is removed but label element is still in the same tree.");
assert_equals(labels2.length, 0,
"The number of labels should be 0 since there is no label with a 'for' attribute associated with this labelable element.");
test14.remove();
assert_equals(labels1.length, 0,
"The number of labels should be 0 after the labelable element is removed.");
}, "A div element which contains labelable element is removed.");
test(function () {

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

@ -17,6 +17,7 @@
#include "base/basictypes.h"
#include "nsMultiplexInputStream.h"
#include "nsIBufferedStreams.h"
#include "nsICloneableInputStream.h"
#include "nsIMultiplexInputStream.h"
#include "nsISeekableStream.h"
@ -27,6 +28,8 @@
#include "mozilla/ipc/InputStreamUtils.h"
#include "nsIAsyncInputStream.h"
#include "nsIInputStreamLength.h"
#include "nsNetUtil.h"
#include "nsStreamUtils.h"
using namespace mozilla;
using namespace mozilla::ipc;
@ -69,11 +72,12 @@ public:
struct StreamData
{
void Initialize(nsIInputStream* aStream)
void Initialize(nsIInputStream* aStream, bool aBuffered)
{
mStream = aStream;
mAsyncStream = do_QueryInterface(aStream);
mSeekableStream = do_QueryInterface(aStream);
mBuffered = aBuffered;
}
nsCOMPtr<nsIInputStream> mStream;
@ -82,6 +86,9 @@ public:
nsCOMPtr<nsIAsyncInputStream> mAsyncStream;
// This can be null.
nsCOMPtr<nsISeekableStream> mSeekableStream;
// True if the stream is wrapped with nsIBufferedInputStream.
bool mBuffered;
};
Mutex& GetLock()
@ -240,6 +247,18 @@ nsMultiplexInputStream::GetCount(uint32_t* aCount)
NS_IMETHODIMP
nsMultiplexInputStream::AppendStream(nsIInputStream* aStream)
{
nsCOMPtr<nsIInputStream> stream = aStream;
bool buffered = false;
if (!NS_InputStreamIsBuffered(stream)) {
nsCOMPtr<nsIInputStream> bufferedStream;
nsresult rv = NS_NewBufferedInputStream(getter_AddRefs(bufferedStream),
stream.forget(), 4096);
NS_ENSURE_SUCCESS(rv, rv);
stream = bufferedStream.forget();
buffered = true;
}
MutexAutoLock lock(mLock);
StreamData* streamData = mStreams.AppendElement();
@ -247,7 +266,7 @@ nsMultiplexInputStream::AppendStream(nsIInputStream* aStream)
return NS_ERROR_OUT_OF_MEMORY;
}
streamData->Initialize(aStream);
streamData->Initialize(stream, buffered);
UpdateQIMap(*streamData, 1);
@ -271,6 +290,17 @@ nsMultiplexInputStream::GetStream(uint32_t aIndex, nsIInputStream** aResult)
StreamData& streamData = mStreams.ElementAt(aIndex);
nsCOMPtr<nsIInputStream> stream = streamData.mStream;
if (streamData.mBuffered) {
nsCOMPtr<nsIBufferedInputStream> bufferedStream = do_QueryInterface(stream);
MOZ_ASSERT(bufferedStream);
nsresult rv = bufferedStream->GetData(getter_AddRefs(stream));
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
}
stream.forget(aResult);
return NS_OK;
}

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

@ -10,6 +10,7 @@
#include "nsIInputStream.h"
#include "nsIMultiplexInputStream.h"
#include "nsISeekableStream.h"
#include "nsStreamUtils.h"
#include "nsThreadUtils.h"
#include "Helpers.h"
@ -230,8 +231,7 @@ public:
ReadSegments(nsWriteSegmentFun aWriter, void* aClosure,
uint32_t aCount, uint32_t *aResult) override
{
MOZ_CRASH("This should not be called!");
return NS_OK;
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHOD
@ -281,8 +281,7 @@ public:
ReadSegments(nsWriteSegmentFun aWriter, void* aClosure,
uint32_t aCount, uint32_t *aResult) override
{
MOZ_CRASH("This should not be called!");
return NS_OK;
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHOD
@ -387,6 +386,90 @@ TEST(TestMultiplexInputStream, Available) {
ASSERT_EQ(buffer.Length(), length);
}
class NonBufferableStringStream final : public nsIInputStream
{
nsCOMPtr<nsIInputStream> mStream;
public:
NS_DECL_THREADSAFE_ISUPPORTS
explicit NonBufferableStringStream(const nsACString& aBuffer)
{
NS_NewCStringInputStream(getter_AddRefs(mStream), aBuffer);
}
NS_IMETHOD
Available(uint64_t* aLength) override
{
return mStream->Available(aLength);
}
NS_IMETHOD
Read(char* aBuffer, uint32_t aCount, uint32_t* aReadCount) override
{
return mStream->Read(aBuffer, aCount, aReadCount);
}
NS_IMETHOD
ReadSegments(nsWriteSegmentFun aWriter, void* aClosure,
uint32_t aCount, uint32_t *aResult) override
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHOD
Close() override
{
return mStream->Close();
}
NS_IMETHOD
IsNonBlocking(bool* aNonBlocking) override
{
return mStream->IsNonBlocking(aNonBlocking);
}
private:
~NonBufferableStringStream() = default;
};
NS_IMPL_ISUPPORTS(NonBufferableStringStream, nsIInputStream)
TEST(TestMultiplexInputStream, Bufferable) {
nsCOMPtr<nsIMultiplexInputStream> multiplexStream =
do_CreateInstance("@mozilla.org/io/multiplex-input-stream;1");
nsCOMPtr<nsIInputStream> s = do_QueryInterface(multiplexStream);
ASSERT_TRUE(!!s);
nsCString buf1;
buf1.AssignLiteral("Hello ");
nsCOMPtr<nsIInputStream> inputStream1;
nsresult rv = NS_NewCStringInputStream(getter_AddRefs(inputStream1), buf1);
ASSERT_TRUE(NS_SUCCEEDED(rv));
nsCString buf2;
buf2.AssignLiteral("world");
nsCOMPtr<nsIInputStream> inputStream2 = new NonBufferableStringStream(buf2);
rv = multiplexStream->AppendStream(inputStream1);
ASSERT_TRUE(NS_SUCCEEDED(rv));
rv = multiplexStream->AppendStream(inputStream2);
ASSERT_TRUE(NS_SUCCEEDED(rv));
nsCOMPtr<nsIInputStream> stream(do_QueryInterface(multiplexStream));
ASSERT_TRUE(!!stream);
char buf3[1024];
uint32_t size = 0;
rv = stream->ReadSegments(NS_CopySegmentToBuffer, buf3, sizeof(buf3), &size);
ASSERT_TRUE(NS_SUCCEEDED(rv));
ASSERT_EQ(size, buf1.Length() + buf2.Length());
ASSERT_TRUE(!strncmp(buf3, "Hello world", size));
}
TEST(TestMultiplexInputStream, QILengthInputStream) {
nsCString buf;
buf.AssignLiteral("Hello world");