merge mozilla-inbound to mozilla-central a=merge

This commit is contained in:
Carsten "Tomcat" Book 2014-10-01 14:51:20 +02:00
Родитель a521762182 784c2ac8ee
Коммит bcd85e4b9f
115 изменённых файлов: 1525 добавлений и 482 удалений

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

@ -196,7 +196,7 @@ def dumpLeakLog(leakLogFile, filter = False):
# Simply copy the log.
log.info(leakReport.rstrip("\n"))
def processSingleLeakFile(leakLogFileName, processType, leakThreshold):
def processSingleLeakFile(leakLogFileName, processType, leakThreshold, ignoreMissingLeaks):
"""Process a single leak log.
"""
@ -273,11 +273,14 @@ def processSingleLeakFile(leakLogFileName, processType, leakThreshold):
if crashedOnPurpose:
log.info("TEST-INFO | leakcheck | %s deliberate crash and thus no leak log"
% processString)
else:
# TODO: This should be a TEST-UNEXPECTED-FAIL, but was changed to a warning
# due to too many intermittent failures (see bug 831223).
log.info("WARNING | leakcheck | %s missing output line for total leaks!"
elif ignoreMissingLeaks:
log.info("TEST-INFO | leakcheck | %s ignoring missing output line for total leaks"
% processString)
else:
log.info("TEST-UNEXPECTED-FAIL | leakcheck | %s missing output line for total leaks!"
% processString)
log.info("TEST-INFO | leakcheck | missing output line from log file %s"
% leakLogFileName)
return
if totalBytesLeaked == 0:
@ -306,7 +309,7 @@ def processSingleLeakFile(leakLogFileName, processType, leakThreshold):
log.info("%s | leakcheck | %s %d bytes leaked (%s)"
% (prefix, processString, totalBytesLeaked, leakedObjectSummary))
def processLeakLog(leakLogFile, leakThresholds):
def processLeakLog(leakLogFile, leakThresholds, ignoreMissingLeaks):
"""Process the leak log, including separate leak logs created
by child processes.
@ -363,7 +366,8 @@ def processLeakLog(leakLogFile, leakThresholds):
log.info("TEST-UNEXPECTED-FAIL | leakcheck | Leak log with unknown process type %s"
% processType)
leakThreshold = leakThresholds.get(processType, 0)
processSingleLeakFile(thisFile, processType, leakThreshold)
processSingleLeakFile(thisFile, processType, leakThreshold,
processType in ignoreMissingLeaks)
def replaceBackSlashes(input):
return input.replace('\\', '/')

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

@ -31,7 +31,7 @@ gyp_vars = {
'use_openssl': 0,
# saves 4MB when webrtc_trace is off
'enable_lazy_trace_alloc': 0,
'enable_lazy_trace_alloc': 1 if CONFIG['RELEASE_BUILD'] else 0,
'use_x11': 1 if CONFIG['MOZ_X11'] else 0,
'use_glib': 1 if CONFIG['GLIB_LIBS'] else 0,

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

@ -9178,14 +9178,6 @@ nsDocument::CloneDocHelper(nsDocument* clone) const
nsresult rv = clone->Init();
NS_ENSURE_SUCCESS(rv, rv);
// Set URI/principal
clone->nsDocument::SetDocumentURI(nsIDocument::GetDocumentURI());
clone->SetChromeXHRDocURI(mChromeXHRDocURI);
// Must set the principal first, since SetBaseURI checks it.
clone->SetPrincipal(NodePrincipal());
clone->mDocumentBaseURI = mDocumentBaseURI;
clone->SetChromeXHRDocBaseURI(mChromeXHRDocBaseURI);
if (mCreatingStaticClone) {
nsCOMPtr<nsILoadGroup> loadGroup;
@ -9210,6 +9202,18 @@ nsDocument::CloneDocHelper(nsDocument* clone) const
clone->SetContainer(mDocumentContainer);
}
// Now ensure that our clone has the same URI, base URI, and principal as us.
// We do this after the mCreatingStaticClone block above, because that block
// can set the base URI to an incorrect value in cases when base URI
// information came from the channel. So we override explicitly, and do it
// for all these properties, in case ResetToURI messes with any of the rest of
// them.
clone->nsDocument::SetDocumentURI(nsIDocument::GetDocumentURI());
clone->SetChromeXHRDocURI(mChromeXHRDocURI);
clone->SetPrincipal(NodePrincipal());
clone->mDocumentBaseURI = mDocumentBaseURI;
clone->SetChromeXHRDocBaseURI(mChromeXHRDocBaseURI);
// Set scripting object
bool hasHadScriptObject = true;
nsIScriptGlobalObject* scriptObject =

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

@ -1090,7 +1090,7 @@ nsXMLHttpRequest::GetResponseURL(nsAString& aUrl)
}
nsAutoCString temp;
responseUrl->GetSpec(temp);
responseUrl->GetSpecIgnoringRef(temp);
CopyUTF8toUTF16(temp, aUrl);
}

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

@ -189,6 +189,11 @@ function testSuccessResponse() {
skip: isInWorker(),
reason: "cross-origin redirect request not works on Workers, see bug 882458"
},
{
message: "request URL has fragment",
requestURL: "http://mochi.test:8888/tests/content/base/test/file_XHRResponseURL.text#fragment",
responseURL: "http://mochi.test:8888/tests/content/base/test/file_XHRResponseURL.text"
},
// tests for non-http(s) URL
{

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

@ -63,7 +63,7 @@ PRLogModuleInfo* gMediaStreamGraphLog;
/**
* The singleton graph instance.
*/
static MediaStreamGraphImpl* gGraph;
static nsDataHashtable<nsUint32HashKey, MediaStreamGraphImpl*> gGraphs;
MediaStreamGraphImpl::~MediaStreamGraphImpl()
{
@ -1633,9 +1633,10 @@ MediaStreamGraphImpl::RunInStableState(bool aSourceIsMSG)
NS_DispatchToMainThread(event);
LIFECYCLE_LOG("Disconnecting MediaStreamGraph %p", this);
if (this == gGraph) {
MediaStreamGraphImpl* graph;
if (gGraphs.Get(mAudioChannel, &graph) && graph == this) {
// null out gGraph if that's the graph being shut down
gGraph = nullptr;
gGraphs.Remove(mAudioChannel);
}
}
} else {
@ -1786,9 +1787,12 @@ MediaStreamGraphImpl::AppendMessage(ControlMessage* aMessage)
delete aMessage;
if (IsEmpty() &&
mLifecycleState >= LIFECYCLE_WAITING_FOR_STREAM_DESTRUCTION) {
if (gGraph == this) {
gGraph = nullptr;
MediaStreamGraphImpl* graph;
if (gGraphs.Get(mAudioChannel, &graph) && graph == this) {
gGraphs.Remove(mAudioChannel);
}
Destroy();
}
return;
@ -2736,6 +2740,7 @@ MediaStreamGraphImpl::MediaStreamGraphImpl(bool aRealtime,
#ifdef DEBUG
, mCanRunMessagesSynchronously(false)
#endif
, mAudioChannel(static_cast<uint32_t>(aChannel))
{
#ifdef PR_LOGGING
if (!gMediaStreamGraphLog) {
@ -2774,15 +2779,26 @@ NS_IMPL_ISUPPORTS(MediaStreamGraphShutdownObserver, nsIObserver)
static bool gShutdownObserverRegistered = false;
namespace {
PLDHashOperator
ForceShutdownEnumerator(const uint32_t& /* aAudioChannel */,
MediaStreamGraphImpl* aGraph,
void* /* aUnused */)
{
aGraph->ForceShutDown();
return PL_DHASH_NEXT;
}
} // anonymous namespace
NS_IMETHODIMP
MediaStreamGraphShutdownObserver::Observe(nsISupports *aSubject,
const char *aTopic,
const char16_t *aData)
{
if (strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID) == 0) {
if (gGraph) {
gGraph->ForceShutDown();
}
gGraphs.EnumerateRead(ForceShutdownEnumerator, nullptr);
nsContentUtils::UnregisterShutdownObserver(this);
gShutdownObserverRegistered = false;
}
@ -2794,7 +2810,10 @@ MediaStreamGraph::GetInstance(DOMMediaStream::TrackTypeHints aHint, dom::AudioCh
{
NS_ASSERTION(NS_IsMainThread(), "Main thread only");
if (!gGraph) {
uint32_t channel = static_cast<uint32_t>(aChannel);
MediaStreamGraphImpl* graph = nullptr;
if (!gGraphs.Get(channel, &graph)) {
if (!gShutdownObserverRegistered) {
gShutdownObserverRegistered = true;
nsContentUtils::RegisterShutdownObserver(new MediaStreamGraphShutdownObserver());
@ -2802,12 +2821,13 @@ MediaStreamGraph::GetInstance(DOMMediaStream::TrackTypeHints aHint, dom::AudioCh
CubebUtils::InitPreferredSampleRate();
gGraph = new MediaStreamGraphImpl(true, CubebUtils::PreferredSampleRate(), aHint, aChannel);
graph = new MediaStreamGraphImpl(true, CubebUtils::PreferredSampleRate(), aHint, aChannel);
gGraphs.Put(channel, graph);
STREAM_LOG(PR_LOG_DEBUG, ("Starting up MediaStreamGraph %p", gGraph));
STREAM_LOG(PR_LOG_DEBUG, ("Starting up MediaStreamGraph %p", graph));
}
return gGraph;
return graph;
}
MediaStreamGraph*
@ -2978,7 +2998,10 @@ MediaStreamGraph::CreateAudioNodeStream(AudioNodeEngine* aEngine,
bool
MediaStreamGraph::IsNonRealtime() const
{
return this != gGraph;
const MediaStreamGraphImpl* impl = static_cast<const MediaStreamGraphImpl*>(this);
MediaStreamGraphImpl* graph;
return !gGraphs.Get(impl->AudioChannel(), &graph) || graph != impl;
}
void

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

@ -654,6 +654,8 @@ public:
nsRefPtr<AudioOutputObserver> mFarendObserverRef;
#endif
uint32_t AudioChannel() const { return mAudioChannel; }
private:
virtual ~MediaStreamGraphImpl();
@ -687,6 +689,9 @@ private:
bool mCanRunMessagesSynchronously;
#endif
// We use uint32_t instead AudioChannel because this is just used as key for
// the hashtable gGraphs.
uint32_t mAudioChannel;
};
}

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

@ -168,9 +168,11 @@ static const int32_t MAX_VIDEO_HEIGHT = 3000;
void ScaleDisplayByAspectRatio(nsIntSize& aDisplay, float aAspectRatio);
// The amount of virtual memory reserved for thread stacks.
#if (defined(XP_WIN) || defined(LINUX)) && !defined(MOZ_ASAN)
#define MEDIA_THREAD_STACK_SIZE (128 * 1024)
#elif defined(XP_MACOSX) && !defined(MOZ_ASAN)
#if defined(MOZ_ASAN)
// Use the system default in ASAN builds, because the default is assumed to be
// larger than the size we want to use and is hopefully sufficient for ASAN.
#define MEDIA_THREAD_STACK_SIZE nsIThreadManager::DEFAULT_STACK_SIZE
#elif defined(XP_WIN) || defined(XP_MACOSX) || defined(LINUX)
#define MEDIA_THREAD_STACK_SIZE (256 * 1024)
#else
// All other platforms use their system defaults.

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

@ -263,8 +263,12 @@ GMPChild::LoadPluginLibrary(const std::string& aPluginPath)
// Enable sandboxing here -- we know the plugin file's path, but
// this process's execution hasn't been affected by its content yet.
MOZ_ASSERT(mozilla::CanSandboxMediaPlugin());
mozilla::SetMediaPluginSandbox(nativePath.get());
if (mozilla::CanSandboxMediaPlugin()) {
mozilla::SetMediaPluginSandbox(nativePath.get());
} else {
printf_stderr("GMPChild::LoadPluginLibrary: Loading media plugin %s unsandboxed.\n",
nativePath.get());
}
#endif // XP_LINUX && MOZ_GMP_SANDBOX
libFile->Load(&mLib);

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

@ -18,6 +18,9 @@
#include "nsIObserverService.h"
#include "GMPTimerParent.h"
#include "runnable_utils.h"
#if defined(XP_LINUX) && defined(MOZ_GMP_SANDBOX)
#include "mozilla/Sandbox.h"
#endif
#include "mozilla/dom/CrashReporterParent.h"
using mozilla::dom::CrashReporterParent;
@ -852,6 +855,17 @@ GMPParent::ReadGMPMetaData()
}
}
#if defined(XP_LINUX) && defined(MOZ_GMP_SANDBOX)
if (cap->mAPIName.EqualsLiteral("eme-decrypt") &&
!mozilla::CanSandboxMediaPlugin()) {
printf_stderr("GMPParent::ReadGMPMetaData: Plugin \"%s\" is an EME CDM"
" but this system can't sandbox it; not loading.\n",
mDisplayName.get());
delete cap;
return NS_ERROR_FAILURE;
}
#endif
mCapabilities.AppendElement(cap);
}

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

@ -435,6 +435,14 @@ GeckoMediaPluginService::GetGMPDecryptor(nsTArray<nsCString>* aTags,
const nsAString& aOrigin,
GMPDecryptorProxy** aDecryptor)
{
#if defined(XP_LINUX) && defined(MOZ_GMP_SANDBOX)
if (!mozilla::CanSandboxMediaPlugin()) {
NS_WARNING("GeckoMediaPluginService::GetGMPDecryptor: "
"EME decryption not available without sandboxing support.");
return NS_ERROR_NOT_AVAILABLE;
}
#endif
MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread);
NS_ENSURE_ARG(aTags && aTags->Length() > 0);
NS_ENSURE_ARG(aDecryptor);
@ -625,11 +633,6 @@ NS_IMETHODIMP
GeckoMediaPluginService::AddPluginDirectory(const nsAString& aDirectory)
{
MOZ_ASSERT(NS_IsMainThread());
#if defined(XP_LINUX) && defined(MOZ_GMP_SANDBOX)
if (!mozilla::CanSandboxMediaPlugin()) {
return NS_ERROR_NOT_AVAILABLE;
}
#endif
nsCOMPtr<nsIThread> thread;
nsresult rv = GetThread(getter_AddRefs(thread));
if (NS_FAILED(rv)) {

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

@ -240,8 +240,7 @@ static int webm_read(void* aBuffer, size_t aLength, void* aUserData)
// Check the read length.
if (aLength > ioData->data.Length()) {
NS_ERROR("Invalid read length");
return -1;
return 0;
}
// Check eos.
@ -292,7 +291,7 @@ static int webm_seek(int64_t aOffset, int aWhence, void* aUserData)
return -1;
}
return 1;
return 0;
}
static int64_t webm_tell(void* aUserData)

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

@ -289,7 +289,15 @@ void
SourceBuffer::StopUpdating()
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(mUpdating);
if (!mUpdating) {
// The buffer append algorithm has been interrupted by abort().
//
// If the sequence appendBuffer(), abort(), appendBuffer() occurs before
// the first StopUpdating() runnable runs, then a second StopUpdating()
// runnable will be scheduled, but still only one (the first) will queue
// events.
return;
}
mUpdating = false;
QueueAsyncSimpleEvent("update");
QueueAsyncSimpleEvent("updateend");

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

@ -648,12 +648,6 @@ AudioContext::MozAudioChannelType() const
return mDestination->MozAudioChannelType();
}
void
AudioContext::SetMozAudioChannelType(AudioChannel aValue, ErrorResult& aRv)
{
mDestination->SetMozAudioChannelType(aValue, aRv);
}
AudioChannel
AudioContext::TestAudioChannelInAudioNodeStream()
{

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

@ -222,7 +222,6 @@ public:
JSObject* GetGlobalJSObject() const;
AudioChannel MozAudioChannelType() const;
void SetMozAudioChannelType(AudioChannel aValue, ErrorResult& aRv);
AudioChannel TestAudioChannelInAudioNodeStream();

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

@ -376,16 +376,17 @@ public:
float* higherWaveData = nullptr;
float* lowerWaveData = nullptr;
float tableInterpolationFactor;
float rate = 1.0 / mSource->SampleRate();
// Phase increment at frequency of 1 Hz.
// mPhase runs [0,periodicWaveSize) here instead of [0,2*M_PI).
float basePhaseIncrement =
static_cast<float>(periodicWaveSize) / mSource->SampleRate();
for (uint32_t i = aStart; i < aEnd; ++i) {
UpdateParametersIfNeeded(ticks, i);
mPeriodicWave->waveDataForFundamentalFrequency(mFinalFrequency,
lowerWaveData,
higherWaveData,
tableInterpolationFactor);
// mPhase runs 0..periodicWaveSize here instead of 0..2*M_PI.
mPhase += periodicWaveSize * mFinalFrequency * rate;
mPhase = fmod(mPhase, periodicWaveSize);
// Bilinear interpolation between adjacent samples in each table.
uint32_t j1 = floor(mPhase);
@ -394,12 +395,14 @@ public:
j2 -= periodicWaveSize;
}
float sampleInterpolationFactor = mPhase - j1;
float lower = sampleInterpolationFactor * lowerWaveData[j1] +
(1 - sampleInterpolationFactor) * lowerWaveData[j2];
float higher = sampleInterpolationFactor * higherWaveData[j1] +
(1 - sampleInterpolationFactor) * higherWaveData[j2];
aOutput[i] = tableInterpolationFactor * lower +
(1 - tableInterpolationFactor) * higher;
float lower = (1.0f - sampleInterpolationFactor) * lowerWaveData[j1] +
sampleInterpolationFactor * lowerWaveData[j2];
float higher = (1.0f - sampleInterpolationFactor) * higherWaveData[j1] +
sampleInterpolationFactor * higherWaveData[j2];
aOutput[i] = (1.0f - tableInterpolationFactor) * lower +
tableInterpolationFactor * higher;
mPhase += basePhaseIncrement * mFinalFrequency;
}
}

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

@ -18,27 +18,23 @@ function test_basic() {
// Default
is(ac.mozAudioChannelType, "normal", "Default ac channel == 'normal'");
// random wrong channel
ac.mozAudioChannelType = "foo";
is(ac.mozAudioChannelType, "normal", "Default ac channel == 'normal'");
// Unpermitted channels
ac.mozAudioChannelType = "content";
ac = new AudioContext("content");
is(ac.mozAudioChannelType, "normal", "Default ac channel == 'normal'");
ac.mozAudioChannelType = "notification";
ac = new AudioContext("notification");
is(ac.mozAudioChannelType, "normal", "Default ac channel == 'normal'");
ac.mozAudioChannelType = "alarm";
ac = new AudioContext("alarm");
is(ac.mozAudioChannelType, "normal", "Default ac channel == 'normal'");
ac.mozAudioChannelType = "telephony";
ac = new AudioContext("telephony");
is(ac.mozAudioChannelType, "normal", "Default ac channel == 'normal'");
ac.mozAudioChannelType = "ringer";
ac = new AudioContext("ringer");
is(ac.mozAudioChannelType, "normal", "Default ac channel == 'normal'");
ac.mozAudioChannelType = "publicnotification";
ac = new AudioContext("publicnotification");
is(ac.mozAudioChannelType, "normal", "Default ac channel == 'normal'");
runTest();
@ -56,7 +52,7 @@ function test_permission(aChannel) {
SpecialPowers.pushPermissions(
[{ "type": "audio-channel-" + aChannel, "allow": true, "context": document }],
function() {
ac.mozAudioChannelType = aChannel;
var ac = new AudioContext(aChannel);
is(ac.mozAudioChannelType, aChannel, "Default ac channel == '" + aChannel + "'");
var channel = SpecialPowers.wrap(ac).testAudioChannelInAudioNodeStream();

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

@ -11,11 +11,26 @@
<script class="testbody" type="text/javascript">
SimpleTest.waitForExplicitFinish();
// real and imag are used in separate PeriodicWaves to make their peak values
// easy to determine.
const realMax = 99;
var real = new Float32Array(realMax + 1);
real[1] = 2.0; // fundamental
real[realMax] = 3.0;
const realPeak = real[1] + real[realMax];
const realFundamental = 19.0;
var imag = new Float32Array(4);
imag[0] = 6.0; // should be ignored.
imag[3] = 0.5;
const imagPeak = imag[3];
const imagFundamental = 551.0;
const testLength = 4096;
addLoadEvent(function() {
var ac = new AudioContext();
var real = new Float32Array(4096);
var imag = new Float32Array(4096);
var table = ac.createPeriodicWave(real, imag);
ac.createPeriodicWave(new Float32Array(4096), new Float32Array(4096));
expectException(function() {
ac.createPeriodicWave(new Float32Array(512), imag);
}, DOMException.NOT_SUPPORTED_ERR);
@ -25,9 +40,54 @@ addLoadEvent(function() {
expectException(function() {
ac.createPeriodicWave(new Float32Array(4097), new Float32Array(4097));
}, DOMException.NOT_SUPPORTED_ERR);
SimpleTest.finish();
runTest();
});
var gTest = {
createGraph: function(context) {
var merger = context.createChannelMerger();
var osc0 = context.createOscillator();
var osc1 = context.createOscillator();
osc0.setPeriodicWave(context.
createPeriodicWave(real,
new Float32Array(real.length)));
osc1.setPeriodicWave(context.
createPeriodicWave(new Float32Array(imag.length),
imag));
osc0.frequency.value = realFundamental;
osc1.frequency.value = imagFundamental;
osc0.start();
osc1.start();
osc0.connect(merger, 0, 0);
osc1.connect(merger, 0, 1);
return merger;
},
createExpectedBuffers: function(context) {
var buffer = context.createBuffer(2, testLength, context.sampleRate);
for (var i = 0; i < buffer.length; ++i) {
buffer.getChannelData(0)[i] = 1.0 / realPeak *
(real[1] * Math.cos(2 * Math.PI * realFundamental * i /
context.sampleRate) +
real[realMax] * Math.cos(2 * Math.PI * realMax * realFundamental * i /
context.sampleRate));
buffer.getChannelData(1)[i] = 1.0 / imagPeak *
imag[3] * Math.sin(2 * Math.PI * 3 * imagFundamental * i /
context.sampleRate);
}
return buffer;
},
};
</script>
</pre>
</body>

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

@ -56,6 +56,9 @@ TestInterfaceJS.prototype = {
get cachedAttr() { return this._cachedAttr; },
setCachedAttr: function(n) { this._cachedAttr = n; },
clearCachedAttrCache: function () { this.__DOM_IMPL__._clearCachedCachedAttrValue(); },
testSequenceOverload: function(arg) {},
testSequenceUnion: function(arg) {},
};
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([TestInterfaceJS])

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

@ -50,3 +50,5 @@ skip-if = debug == false
[test_throwing_method_noDCE.html]
[test_treat_non_object_as_null.html]
[test_traceProtos.html]
[test_sequence_detection.html]
skip-if = debug == false

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

@ -0,0 +1,52 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=1066432
-->
<head>
<meta charset="utf-8">
<title>Test for Bug 1066432</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script type="application/javascript">
/** Test for Bug 1066432 **/
SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPrefEnv({set: [['dom.expose_test_interfaces', true]]}, function() {
var testInterfaceJS = new TestInterfaceJS();
ok(testInterfaceJS, "got a TestInterfaceJS object");
try {
testInterfaceJS.testSequenceOverload(
{ "@@iterator": 5, [Symbol.iterator]: Array.prototype[Symbol.iterator] });
ok(false, "Should have thrown in the overload case");
} catch (e) {
ise(e.name, "TypeError", "Should get a TypeError for the overload case");
ok(e.message.contains("not iterable"),
"Should have a message about being non-iterable in the overload case");
}
try {
testInterfaceJS.testSequenceUnion(
{ "@@iterator": 5, [Symbol.iterator]: Array.prototype[Symbol.iterator] });
ok(false, "Should have thrown in the union case");
} catch (e) {
ise(e.name, "TypeError", "Should get a TypeError for the union case");
ok(e.message.contains("not iterable"),
"Should have a message about being non-iterable in the union case");
}
SimpleTest.finish();
});
</script>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1066432">Mozilla Bug 1066432</a>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
</pre>
</body>
</html>

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

@ -824,7 +824,7 @@ private:
param.data = (unsigned char*) &oaepParams;
param.len = sizeof(oaepParams);
uint32_t outLen;
uint32_t outLen = 0;
if (mEncrypt) {
// PK11_PubEncrypt() checks the plaintext's length and fails if it is too
// long to encrypt, i.e. if it is longer than (k - 2hLen - 2) with 'k'
@ -841,9 +841,9 @@ private:
mResult.Elements(), &outLen, mResult.Length(),
mData.Elements(), mData.Length()));
}
mResult.SetLength(outLen);
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_OPERATION_ERR);
mResult.SetLength(outLen);
return NS_OK;
}
};

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

@ -342,6 +342,7 @@ namespace mozilla {
namespace dom {
#ifdef MOZ_NUWA_PROCESS
int32_t ContentParent::sNuwaPid = 0;
bool ContentParent::sNuwaReady = false;
#endif
@ -587,6 +588,7 @@ ContentParent::RunNuwaProcess()
/* aIsNuwaProcess = */ true);
nuwaProcess->Init();
#ifdef MOZ_NUWA_PROCESS
sNuwaPid = nuwaProcess->Pid();
sNuwaReady = false;
#endif
return nuwaProcess.forget();
@ -1990,6 +1992,7 @@ ContentParent::~ContentParent()
#ifdef MOZ_NUWA_PROCESS
if (IsNuwaProcess()) {
sNuwaReady = false;
sNuwaPid = 0;
}
#endif
}
@ -3699,6 +3702,12 @@ ContentParent::DoSendAsyncMessage(JSContext* aCx,
if (aCpows && !GetCPOWManager()->Wrap(aCx, aCpows, &cpows)) {
return false;
}
#ifdef MOZ_NUWA_PROCESS
if (IsNuwaProcess() && IsNuwaReady()) {
// Nuwa won't receive frame messages after it is frozen.
return true;
}
#endif
return SendAsyncMessage(nsString(aMessage), data, cpows, Principal(aPrincipal));
}

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

@ -79,6 +79,10 @@ class ContentParent MOZ_FINAL : public PContentParent
public:
#ifdef MOZ_NUWA_PROCESS
static int32_t NuwaPid() {
return sNuwaPid;
}
static bool IsNuwaReady() {
return sNuwaReady;
}
@ -725,6 +729,7 @@ private:
#endif
#ifdef MOZ_NUWA_PROCESS
static int32_t sNuwaPid;
static bool sNuwaReady;
#endif
};

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

@ -301,7 +301,6 @@ function RTCPeerConnection() {
this._localType = null;
this._remoteType = null;
this._trickleIce = false;
this._peerIdentity = null;
/**
@ -326,7 +325,6 @@ RTCPeerConnection.prototype = {
init: function(win) { this._win = win; },
__init: function(rtcConfig) {
this._trickleIce = Services.prefs.getBoolPref("media.peerconnection.trickle_ice");
if (!rtcConfig.iceServers ||
!Services.prefs.getBoolPref("media.peerconnection.use_document_iceservers")) {
rtcConfig.iceServers =
@ -365,8 +363,7 @@ RTCPeerConnection.prototype = {
this._queueOrRun({
func: this._initialize,
args: [rtcConfig],
// If not trickling, suppress start.
wait: !this._trickleIce
wait: false
});
},
@ -500,7 +497,11 @@ RTCPeerConnection.prototype = {
},
dispatchEvent: function(event) {
this.__DOM_IMPL__.dispatchEvent(event);
// PC can close while events are firing if there is an async dispatch
// in c++ land
if (!this._closed) {
this.__DOM_IMPL__.dispatchEvent(event);
}
},
// Log error message to web console and window.onerror, if present.

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

@ -1937,6 +1937,10 @@ PeerConnectionWrapper.prototype = {
var self = this;
self._remote_ice_candidates.push(candidate);
if (self.signalingstate === 'closed') {
info("Received ICE candidate for closed PeerConnection - discarding");
return;
}
if (self.remoteDescriptionSet) {
self.addIceCandidate(candidate);
} else {
@ -2566,15 +2570,9 @@ PeerConnectionWrapper.prototype = {
* Closes the connection
*/
close : function PCW_close() {
// It might be that a test has already closed the pc. In those cases
// we should not fail.
try {
this._pc.close();
info(this + ": Closed connection.");
}
catch (e) {
info(this + ": Failure in closing connection - " + e.message);
}
this._ice_candidates_to_add = [];
this._pc.close();
info(this + ": Closed connection.");
},
/**

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

@ -589,8 +589,15 @@ DOMStorageDBParent::Observe(const char* aTopic,
const nsACString& aScopePrefix)
{
if (mIPCOpen) {
mozilla::unused << SendObserve(nsDependentCString(aTopic),
nsCString(aScopePrefix));
#ifdef MOZ_NUWA_PROCESS
if (!(static_cast<ContentParent*>(Manager())->IsNuwaProcess() &&
ContentParent::IsNuwaReady())) {
#endif
mozilla::unused << SendObserve(nsDependentCString(aTopic),
nsCString(aScopePrefix));
#ifdef MOZ_NUWA_PROCESS
}
#endif
}
return NS_OK;

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

@ -78,8 +78,8 @@ interface AudioContext : EventTarget {
// Mozilla extensions
partial interface AudioContext {
// Read AudioChannel.webidl for more information about this attribute.
[Pref="media.useAudioChannelService", SetterThrows]
attribute AudioChannel mozAudioChannelType;
[Pref="media.useAudioChannelService"]
readonly attribute AudioChannel mozAudioChannelType;
// These 2 events are dispatched when the AudioContext object is muted by
// the AudioChannelService. It's call 'interrupt' because when this event is

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

@ -42,4 +42,10 @@ interface TestInterfaceJS {
readonly attribute short cachedAttr;
void setCachedAttr(short n);
void clearCachedAttrCache();
// Test for sequence overloading and union behavior
void testSequenceOverload(sequence<DOMString> arg);
void testSequenceOverload(DOMString arg);
void testSequenceUnion((sequence<DOMString> or DOMString) arg);
};

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

@ -2205,7 +2205,7 @@ RuntimeService::CancelWorkersForWindow(nsPIDOMWindow* aWindow)
for (uint32_t index = 0; index < workers.Length(); index++) {
WorkerPrivate*& worker = workers[index];
if (worker->IsSharedWorker()) {
if (worker->IsSharedWorker() || worker->IsServiceWorker()) {
worker->CloseSharedWorkersForWindow(aWindow);
} else if (!worker->Cancel(cx)) {
JS_ReportPendingException(cx);

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

@ -128,7 +128,7 @@ txStylesheet::findTemplate(const txXPathNode& aNode,
endFrame = aImportedBy->mFirstNotImported;
}
#ifdef PR_LOGGING
#if defined(PR_LOGGING) && defined(TX_TO_STRING)
txPattern* match = 0;
#endif
@ -149,7 +149,7 @@ txStylesheet::findTemplate(const txXPathNode& aNode,
if (templ.mMatch->matches(aNode, aContext)) {
matchTemplate = templ.mFirstInstruction;
*aImportFrame = frame;
#ifdef PR_LOGGING
#if defined(PR_LOGGING) && defined(TX_TO_STRING)
match = templ.mMatch;
#endif
}

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

@ -64,8 +64,7 @@ MOZ_END_ENUM_CLASS(BufferMode)
MOZ_BEGIN_ENUM_CLASS(DrawRegionClip, int8_t)
DRAW,
DRAW_SNAPPED,
CLIP_NONE
NONE
MOZ_END_ENUM_CLASS(DrawRegionClip)
MOZ_BEGIN_ENUM_CLASS(SurfaceMode, int8_t)

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

@ -695,7 +695,7 @@ RotatedContentBuffer::BeginPaint(PaintedLayer* aLayer,
nsIntRegion invalidate;
invalidate.Sub(aLayer->GetValidRegion(), destBufferRect);
result.mRegionToInvalidate.Or(result.mRegionToInvalidate, invalidate);
result.mClip = DrawRegionClip::DRAW_SNAPPED;
result.mClip = DrawRegionClip::DRAW;
result.mMode = mode;
return result;

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

@ -229,7 +229,7 @@ public:
: mRegionToDraw()
, mRegionToInvalidate()
, mMode(SurfaceMode::SURFACE_NONE)
, mClip(DrawRegionClip::CLIP_NONE)
, mClip(DrawRegionClip::NONE)
, mContentType(gfxContentType::SENTINEL)
, mDidSelfCopy(false)
{}

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

@ -91,7 +91,7 @@ BasicPaintedLayer::PaintThebes(gfxContext* aContext,
groupContext = aContext;
}
SetAntialiasingFlags(this, groupContext->GetDrawTarget());
aCallback(this, groupContext, toDraw, DrawRegionClip::CLIP_NONE, nsIntRegion(), aCallbackData);
aCallback(this, groupContext, toDraw, DrawRegionClip::NONE, nsIntRegion(), aCallbackData);
if (needsGroup) {
aContext->PopGroupToSource();
if (needsClipToVisibleRegion) {

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

@ -443,7 +443,17 @@ ClientLayerManager::MakeSnapshotIfRequired()
}
if (mWidget) {
if (CompositorChild* remoteRenderer = GetRemoteRenderer()) {
// The compositor doesn't draw to a different sized surface
// when there's a rotation. Instead we rotate the result
// when drawing into dt
nsIntRect outerBounds;
mWidget->GetBounds(outerBounds);
nsIntRect bounds = ToOutsideIntRect(mShadowTarget->GetClipExtents());
if (mTargetRotation) {
bounds = RotateRect(bounds, outerBounds, mTargetRotation);
}
SurfaceDescriptor inSnapshot;
if (!bounds.IsEmpty() &&
mForwarder->AllocSurfaceDescriptor(bounds.Size().ToIntSize(),
@ -452,11 +462,18 @@ ClientLayerManager::MakeSnapshotIfRequired()
remoteRenderer->SendMakeSnapshot(inSnapshot, bounds)) {
RefPtr<DataSourceSurface> surf = GetSurfaceForDescriptor(inSnapshot);
DrawTarget* dt = mShadowTarget->GetDrawTarget();
Rect dstRect(bounds.x, bounds.y, bounds.width, bounds.height);
Rect srcRect(0, 0, bounds.width, bounds.height);
gfx::Matrix rotate = ComputeTransformForUnRotation(outerBounds, mTargetRotation);
gfx::Matrix oldMatrix = dt->GetTransform();
dt->SetTransform(oldMatrix * rotate);
dt->DrawSurface(surf, dstRect, srcRect,
DrawSurfaceOptions(),
DrawOptions(1.0f, CompositionOp::OP_OVER));
dt->SetTransform(oldMatrix);
}
mForwarder->DestroySharedSurface(&inSnapshot);
}

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

@ -934,7 +934,7 @@ ClientTiledLayerBuffer::PaintThebes(const nsIntRegion& aNewValidRegion,
PROFILER_LABEL("ClientTiledLayerBuffer", "PaintThebesSingleBufferDraw",
js::ProfileEntry::Category::GRAPHICS);
mCallback(mPaintedLayer, ctxt, aPaintRegion, DrawRegionClip::CLIP_NONE, nsIntRegion(), mCallbackData);
mCallback(mPaintedLayer, ctxt, aPaintRegion, DrawRegionClip::NONE, nsIntRegion(), mCallbackData);
}
#ifdef GFX_TILEDLAYER_PREF_WARNINGS
@ -1304,7 +1304,7 @@ ClientTiledLayerBuffer::ValidateTile(TileClient aTile,
Scale(mResolution, mResolution));
mCallback(mPaintedLayer, ctxt,
tileRegion.GetBounds(),
DrawRegionClip::CLIP_NONE,
DrawRegionClip::NONE,
nsIntRegion(), mCallbackData);
}

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

@ -537,7 +537,7 @@ PaintedLayerD3D9::DrawRegion(nsIntRegion &aRegion, SurfaceMode aMode,
context->SetMatrix(context->CurrentMatrix().Translate(-bounds.x, -bounds.y));
LayerManagerD3D9::CallbackInfo cbInfo = mD3DManager->GetCallbackInfo();
cbInfo.Callback(this, context, aRegion, DrawRegionClip::CLIP_NONE, nsIntRegion(), cbInfo.CallbackData);
cbInfo.Callback(this, context, aRegion, DrawRegionClip::NONE, nsIntRegion(), cbInfo.CallbackData);
for (uint32_t i = 0; i < aReadbackUpdates.Length(); ++i) {
NS_ASSERTION(aMode == SurfaceMode::SURFACE_OPAQUE,

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

@ -13,6 +13,7 @@
#ifdef MOZ_NUWA_PROCESS
#include "ipc/Nuwa.h"
#include "mozilla/Preferences.h"
#include "mozilla/dom/ContentParent.h"
#endif
#include "mozilla/Assertions.h"
@ -70,6 +71,9 @@ ProcessLink::ProcessLink(MessageChannel *aChan)
, mTransport(nullptr)
, mIOLoop(nullptr)
, mExistingListener(nullptr)
#ifdef MOZ_NUWA_PROCESS
, mIsToNuwaProcess(false)
#endif
{
}
@ -168,6 +172,26 @@ ProcessLink::SendMessage(Message *msg)
mChan->AssertWorkerThread();
mChan->mMonitor->AssertCurrentThreadOwns();
#ifdef MOZ_NUWA_PROCESS
if (mIsToNuwaProcess && mozilla::dom::ContentParent::IsNuwaReady()) {
switch (msg->type()) {
case mozilla::dom::PContent::Msg_NuwaFork__ID:
case mozilla::dom::PContent::Reply_AddNewProcess__ID:
case mozilla::dom::PContent::Msg_NotifyPhoneStateChange__ID:
case GOODBYE_MESSAGE_TYPE:
break;
default:
#ifdef DEBUG
MOZ_CRASH();
#else
// In optimized build, message will be dropped.
printf_stderr("Sending message to frozen Nuwa");
return;
#endif
}
}
#endif
mIOLoop->PostTask(
FROM_HERE,
NewRunnableMethod(mTransport, &Transport::Send, msg));
@ -360,6 +384,10 @@ ProcessLink::OnChannelConnected(int32_t peer_pid)
if (mExistingListener)
mExistingListener->OnChannelConnected(peer_pid);
#ifdef MOZ_NUWA_PROCESS
mIsToNuwaProcess = (peer_pid == mozilla::dom::ContentParent::NuwaPid());
#endif
if (notifyChannel) {
mChan->OnChannelConnected(peer_pid);
}

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

@ -170,6 +170,9 @@ class ProcessLink
Transport* mTransport;
MessageLoop* mIOLoop; // thread where IO happens
Transport::Listener* mExistingListener; // channel's previous listener
#ifdef MOZ_NUWA_PROCESS
bool mIsToNuwaProcess;
#endif
};
class ThreadLink : public MessageLink

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

@ -2016,6 +2016,12 @@ CheckSideEffects(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn, bool
*answer = true;
}
}
if (pn->isHoistedLetUse()) {
// Hoisted uses of lexical bindings throw on access.
*answer = true;
}
if (pn->isKind(PNK_DOT)) {
/* Dotted property references in general can call getters. */
*answer = true;

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

@ -0,0 +1,23 @@
function assertThrowsReferenceError(f) {
var e = null;
try {
f();
} catch (ex) {
e = ex;
}
assertEq(e instanceof ReferenceError, true);
}
assertThrowsReferenceError(function () { delete x; let x; });
// FIXME do this unconditionally once bug 611388 lands.
function constIsLexical() {
try {
(function () { z++; const z; })();
return false;
} catch (e) {
return true;
}
}
if (constIsLexical())
assertThrowsReferenceError(function () { delete x; const x; });

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

@ -0,0 +1,24 @@
function assertThrowsReferenceError(f) {
var e = null;
try {
f();
} catch (ex) {
e = ex;
}
assertEq(e instanceof ReferenceError, true);
}
// TDZ is effectful, don't optimize out x.
assertThrowsReferenceError(function () { x; let x; });
// FIXME do this unconditionally once bug 611388 lands.
function constIsLexical() {
try {
(function () { z++; const z; })();
return false;
} catch (e) {
return true;
}
}
if (constIsLexical())
assertThrowsReferenceError(function () { x; const x; });

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

@ -0,0 +1,5 @@
// |jit-test| error: ReferenceError
{
while (x && 0) {}
let x
}

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

@ -0,0 +1,10 @@
try {
let x = ((function f(y) {
if (y > 0) {
f(-1)
}
x
})(1))
} catch (e) {
assertEq(e instanceof ReferenceError, true);
}

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

@ -7911,13 +7911,28 @@ ICSetPropNativeAddCompiler::generateStubCode(MacroAssembler &masm)
masm.loadPtr(Address(BaselineStubReg, ICSetProp_NativeAdd::offsetOfNewShape()), scratch);
masm.storePtr(scratch, shapeAddr);
// Change the object's type if required.
// Try to change the object's type.
Label noTypeChange;
// Check if the cache has a new type to change to.
masm.loadPtr(Address(BaselineStubReg, ICSetProp_NativeAdd::offsetOfNewType()), scratch);
masm.branchTestPtr(Assembler::Zero, scratch, scratch, &noTypeChange);
// Check if the old type still has a newScript.
masm.loadPtr(Address(objReg, JSObject::offsetOfType()), scratch);
masm.branchPtr(Assembler::Equal,
Address(scratch, types::TypeObject::offsetOfNewScript()),
ImmWord(0),
&noTypeChange);
// Reload the new type from the cache.
masm.loadPtr(Address(BaselineStubReg, ICSetProp_NativeAdd::offsetOfNewType()), scratch);
// Change the object's type.
Address typeAddr(objReg, JSObject::offsetOfType());
EmitPreBarrier(masm, typeAddr, MIRType_TypeObject);
masm.storePtr(scratch, typeAddr);
masm.bind(&noTypeChange);
Register holderReg;

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

@ -2583,11 +2583,27 @@ GenerateAddSlot(JSContext *cx, MacroAssembler &masm, IonCache::StubAttacher &att
if (oldType != obj->type()) {
// Changing object's type from a partially to fully initialized type,
// per the acquired properties analysis.
// per the acquired properties analysis. Only change the type if the
// old type still has a newScript.
Label noTypeChange, skipPop;
masm.push(object);
masm.loadPtr(Address(object, JSObject::offsetOfType()), object);
masm.branchPtr(Assembler::Equal,
Address(object, types::TypeObject::offsetOfNewScript()),
ImmWord(0),
&noTypeChange);
masm.pop(object);
Address typeAddr(object, JSObject::offsetOfType());
if (cx->zone()->needsIncrementalBarrier())
masm.callPreBarrier(typeAddr, MIRType_TypeObject);
masm.storePtr(ImmGCPtr(obj->type()), typeAddr);
masm.jump(&skipPop);
masm.bind(&noTypeChange);
masm.pop(object);
masm.bind(&skipPop);
}
// Set the value on the object. Since this is an add, obj->lastProperty()

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

@ -573,6 +573,13 @@ jit::MakeSingletonTypeSet(types::CompilerConstraintList *constraints, JSObject *
return alloc->new_<types::TemporaryTypeSet>(alloc, types::Type::ObjectType(obj));
}
static types::TemporaryTypeSet *
MakeUnknownTypeSet()
{
LifoAlloc *alloc = GetIonContext()->temp->lifoAlloc();
return alloc->new_<types::TemporaryTypeSet>(alloc, types::Type::UnknownType());
}
MConstant::MConstant(const js::Value &vp, types::CompilerConstraintList *constraints)
: value_(vp)
{
@ -582,6 +589,16 @@ MConstant::MConstant(const js::Value &vp, types::CompilerConstraintList *constra
// other types as the result type encodes all needed information.
setResultTypeSet(MakeSingletonTypeSet(constraints, &vp.toObject()));
}
if (vp.isMagic() && vp.whyMagic() == JS_UNINITIALIZED_LEXICAL) {
// JS_UNINITIALIZED_LEXICAL does not escape to script and is not
// observed in type sets. However, it may flow around freely during
// Ion compilation. Give it an unknown typeset to poison any type sets
// it merges with.
//
// TODO We could track uninitialized lexicals more precisely by tracking
// them in type sets.
setResultTypeSet(MakeUnknownTypeSet());
}
setMovable();
}

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

@ -7,17 +7,19 @@ The tests in this directory exercise the JSAPI.
If you built JS, you already built the tests.
If you did `make check` in your JS objdir, you already ran them.
The tests are built by default when you build JS. All the tests are compiled
into a single binary named jsapi-tests. They all run in a single process.
To run the tests:
cd $OBJDIR/dist/bin
./jsapi-tests
To run the tests in a debugger:
cd $OBJDIR/jsapi-tests
cd $OBJDIR/dist/bin
gdb ./jsapi-tests
--- Creating new tests
1. You can either add to an existing test*.cpp file or make a new one.

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

@ -29,6 +29,7 @@ UNIFIED_SOURCES += [
'testException.cpp',
'testExternalStrings.cpp',
'testFindSCCs.cpp',
'testForOfIterator.cpp',
'testFreshGlobalEvalRedefinition.cpp',
'testFuncCallback.cpp',
'testFunctionProperties.cpp',

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

@ -0,0 +1,53 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sts=4 et sw=4 tw=99:
*/
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "jsapi-tests/tests.h"
BEGIN_TEST(testForOfIterator_basicNonIterable)
{
JS::RootedValue v(cx);
// Hack to make it simple to produce an object that has a property
// named Symbol.iterator.
EVAL("var obj = { '@@iterator': 5, [Symbol.iterator]: Array.prototype[Symbol.iterator] }; obj;", &v);
JS::ForOfIterator iter(cx);
bool ok = iter.init(v);
CHECK(!ok);
JS_ClearPendingException(cx);
return true;
}
END_TEST(testForOfIterator_basicNonIterable)
BEGIN_TEST(testForOfIterator_bug515273_part1)
{
JS::RootedValue v(cx);
// Hack to make it simple to produce an object that has a property
// named Symbol.iterator.
EVAL("var obj = { '@@iterator': 5, [Symbol.iterator]: Array.prototype[Symbol.iterator] }; obj;", &v);
JS::ForOfIterator iter(cx);
bool ok = iter.init(v, JS::ForOfIterator::AllowNonIterable);
CHECK(!ok);
JS_ClearPendingException(cx);
return true;
}
END_TEST(testForOfIterator_bug515273_part1)
BEGIN_TEST(testForOfIterator_bug515273_part2)
{
JS::RootedObject obj(cx,
JS_NewObject(cx, nullptr, JS::NullPtr(), JS::NullPtr()));
CHECK(obj);
JS::RootedValue v(cx, JS::ObjectValue(*obj));
JS::ForOfIterator iter(cx);
bool ok = iter.init(v, JS::ForOfIterator::AllowNonIterable);
CHECK(ok);
CHECK(!iter.valueIsIterable());
return true;
}
END_TEST(testForOfIterator_bug515273_part2)

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

@ -5191,10 +5191,10 @@ class MOZ_STACK_CLASS JS_PUBLIC_API(ForOfIterator) {
};
/*
* Initialize the iterator. If AllowNonIterable is passed then if iterable
* does not have a callable @@iterator init() will just return true instead
* of throwing. Callers should then check valueIsIterable() before
* continuing with the iteration.
* Initialize the iterator. If AllowNonIterable is passed then if getting
* the @@iterator property from iterable returns undefined init() will just
* return true instead of throwing. Callers must then check
* valueIsIterable() before continuing with the iteration.
*/
bool init(JS::HandleValue iterable,
NonIterableBehavior nonIterableBehavior = ThrowOnNonIterable);

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

@ -1236,6 +1236,10 @@ struct TypeObject : public gc::TenuredCell
return offsetof(TypeObject, proto_);
}
static inline uint32_t offsetOfNewScript() {
return offsetof(TypeObject, newScript_);
}
private:
inline uint32_t basePropertyCount() const;
inline void setBasePropertyCount(uint32_t count);

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

@ -1366,13 +1366,17 @@ ForOfIterator::init(HandleValue iterable, NonIterableBehavior nonIterableBehavio
if (!JSObject::getProperty(cx, iterableObj, iterableObj, cx->names().std_iterator, &callee))
return false;
// Throw if obj[@@iterator] isn't callable if we were asked to do so.
// If obj[@@iterator] is undefined and we were asked to allow non-iterables,
// bail out now without setting iterator. This will make valueIsIterable(),
// which our caller should check, return false.
if (nonIterableBehavior == AllowNonIterable && callee.isUndefined())
return true;
// Throw if obj[@@iterator] isn't callable.
// js::Invoke is about to check for this kind of error anyway, but it would
// throw an inscrutable error message about |method| rather than this nice
// one about |obj|.
if (!callee.isObject() || !callee.toObject().isCallable()) {
if (nonIterableBehavior == AllowNonIterable)
return true;
char *bytes = DecompileValueGenerator(cx, JSDVG_SEARCH_STACK, iterable, NullPtr());
if (!bytes)
return false;

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

@ -254,7 +254,10 @@ FetchName(JSContext *cx, HandleObject obj, HandleObject obj2, HandlePropertyName
return false;
}
}
return true;
// NAME operations are the slow paths already, so unconditionally check
// for uninitialized lets.
return CheckUninitializedLexical(cx, name, vp);
}
inline bool
@ -264,7 +267,7 @@ FetchNameNoGC(JSObject *pobj, Shape *shape, MutableHandleValue vp)
return false;
vp.set(pobj->nativeGetSlot(shape->slot()));
return true;
return !IsUninitializedLexical(vp);
}
inline bool

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

@ -298,17 +298,9 @@ NameOperation(JSContext *cx, InterpreterFrame *fp, jsbytecode *pc, MutableHandle
/* Kludge to allow (typeof foo == "undefined") tests. */
JSOp op2 = JSOp(pc[JSOP_NAME_LENGTH]);
if (op2 == JSOP_TYPEOF) {
if (!FetchName<true>(cx, scopeRoot, pobjRoot, nameRoot, shapeRoot, vp))
return false;
} else {
if (!FetchName<false>(cx, scopeRoot, pobjRoot, nameRoot, shapeRoot, vp))
return false;
}
// NAME operations are the slow paths already, so unconditionally check
// for uninitialized lets.
return CheckUninitializedLexical(cx, nameRoot, vp);
if (op2 == JSOP_TYPEOF)
return FetchName<true>(cx, scopeRoot, pobjRoot, nameRoot, shapeRoot, vp);
return FetchName<false>(cx, scopeRoot, pobjRoot, nameRoot, shapeRoot, vp);
}
static inline bool
@ -3564,7 +3556,7 @@ js::GetScopeName(JSContext *cx, HandleObject scopeChain, HandlePropertyName name
if (!JSObject::getProperty(cx, obj, obj, name, vp))
return false;
// See note in NameOperation.
// See note in FetchName.
return CheckUninitializedLexical(cx, name, vp);
}
@ -3589,7 +3581,7 @@ js::GetScopeNameForTypeOf(JSContext *cx, HandleObject scopeChain, HandleProperty
if (!JSObject::getProperty(cx, obj, obj, name, vp))
return false;
// See note in NameOperation.
// See note in FetchName.
return CheckUninitializedLexical(cx, name, vp);
}
@ -3874,6 +3866,13 @@ js::DeleteNameOperation(JSContext *cx, HandlePropertyName name, HandleObject sco
return true;
}
// NAME operations are the slow paths already, so unconditionally check
// for uninitialized lets.
if (pobj == scope && IsUninitializedLexicalSlot(scope, shape)) {
ReportUninitializedLexical(cx, name);
return false;
}
bool succeeded;
RootedId id(cx, NameToId(name));
if (!JSObject::deleteGeneric(cx, scope, id, &succeeded))

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

@ -4371,7 +4371,7 @@ FrameLayerBuilder::PaintItems(nsTArray<ClippedDisplayItem>& aItems,
static bool ShouldDrawRectsSeparately(gfxContext* aContext, DrawRegionClip aClip)
{
if (!gfxPrefs::LayoutPaintRectsSeparately() ||
aClip == DrawRegionClip::CLIP_NONE) {
aClip == DrawRegionClip::NONE) {
return false;
}
@ -4453,9 +4453,7 @@ FrameLayerBuilder::DrawPaintedLayer(PaintedLayer* aLayer,
bool shouldDrawRectsSeparately = ShouldDrawRectsSeparately(aContext, aClip);
if (!shouldDrawRectsSeparately) {
if (aClip == DrawRegionClip::DRAW_SNAPPED) {
gfxUtils::ClipToRegionSnapped(aContext, aRegionToDraw);
} else if (aClip == DrawRegionClip::DRAW) {
if (aClip == DrawRegionClip::DRAW) {
gfxUtils::ClipToRegion(aContext, aRegionToDraw);
}
@ -4486,7 +4484,7 @@ FrameLayerBuilder::DrawPaintedLayer(PaintedLayer* aLayer,
while (const nsIntRect* iterRect = it.Next()) {
gfxContextAutoSaveRestore save(aContext);
aContext->NewPath();
aContext->Rectangle(*iterRect, aClip == DrawRegionClip::DRAW_SNAPPED);
aContext->Rectangle(*iterRect);
aContext->Clip();
DrawForcedBackgroundColor(aContext, aLayer, userData->mForcedBackgroundColor);
@ -4522,9 +4520,7 @@ FrameLayerBuilder::DrawPaintedLayer(PaintedLayer* aLayer,
if (presContext->GetPaintFlashing() && isActiveLayerManager) {
gfxContextAutoSaveRestore save(aContext);
if (shouldDrawRectsSeparately) {
if (aClip == DrawRegionClip::DRAW_SNAPPED) {
gfxUtils::ClipToRegionSnapped(aContext, aRegionToDraw);
} else if (aClip == DrawRegionClip::DRAW) {
if (aClip == DrawRegionClip::DRAW) {
gfxUtils::ClipToRegion(aContext, aRegionToDraw);
}
}

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

@ -3069,6 +3069,16 @@ ElementRestyler::RestyleSelf(nsIFrame* aSelf,
oldContext.get(), newContext.get());
oldContext->SwapStyleData(newContext, equalStructs);
*aSwappedStructs |= equalStructs;
#ifdef RESTYLE_LOGGING
uint32_t structs = RestyleManager::StructsToLog() & equalStructs;
if (structs) {
LOG_RESTYLE_INDENT();
LOG_RESTYLE("old style context now has: %s",
oldContext->GetCachedStyleDataAsString(structs).get());
LOG_RESTYLE("new style context now has: %s",
newContext->GetCachedStyleDataAsString(structs).get());
}
#endif
}
LOG_RESTYLE("setting new style context");
aSelf->SetStyleContext(newContext);
@ -3636,6 +3646,39 @@ RestyleManager::ComputeStyleChangeFor(nsIFrame* aFrame,
}
}
#ifdef RESTYLE_LOGGING
uint32_t
RestyleManager::StructsToLog()
{
static bool initialized = false;
static uint32_t structs;
if (!initialized) {
structs = 0;
const char* value = getenv("MOZ_DEBUG_RESTYLE_STRUCTS");
if (value) {
nsCString s(value);
while (!s.IsEmpty()) {
int32_t index = s.FindChar(',');
nsStyleStructID sid;
bool found;
if (index == -1) {
found = nsStyleContext::LookupStruct(s, sid);
s.Truncate();
} else {
found = nsStyleContext::LookupStruct(Substring(s, 0, index), sid);
s = Substring(s, index + 1);
}
if (found) {
structs |= nsCachedStyleData::GetBitForSID(sid);
}
}
}
initialized = true;
}
return structs;
}
#endif
#ifdef DEBUG
/* static */ nsCString
RestyleManager::RestyleHintToString(nsRestyleHint aHint)

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

@ -386,6 +386,13 @@ public:
return animations;
}
// Set MOZ_DEBUG_RESTYLE_STRUCTS to a comma-separated string of
// style struct names -- such as "Font,SVGReset" -- to log the style context
// tree and those cached struct pointers before each restyle. This
// function returns a bitfield of the structs named in the
// environment variable.
static uint32_t StructsToLog();
static nsCString StructNamesToString(uint32_t aSIDs);
int32_t& LoggingDepth() { return mLoggingDepth; }
#endif

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

@ -162,7 +162,17 @@ RestyleTracker::ProcessOneRestyle(Element* aElement,
RestyleManager::ChangeHintToString(aChangeHint).get());
nsIFrame* primaryFrame = aElement->GetPrimaryFrame();
if (aRestyleHint & ~eRestyle_LaterSiblings) {
#ifdef RESTYLE_LOGGING
if (ShouldLogRestyle() && primaryFrame &&
RestyleManager::StructsToLog() != 0) {
LOG_RESTYLE("style context tree before restyle:");
LOG_RESTYLE_INDENT();
primaryFrame->StyleContext()->LogStyleContextTree(
LoggingDepth(), RestyleManager::StructsToLog());
}
#endif
mRestyleManager->RestyleElement(aElement, primaryFrame, aChangeHint,
*this, aRestyleHint);
} else if (aChangeHint &&

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

@ -1224,7 +1224,8 @@ void
nsBidiPresUtils::ReorderFrames(nsIFrame* aFirstFrameOnLine,
int32_t aNumFramesOnLine,
WritingMode aLineWM,
nscoord& aLineWidth)
nscoord& aLineWidth,
nscoord aStart)
{
// If this line consists of a line frame, reorder the line frame's children.
if (aFirstFrameOnLine->GetType() == nsGkAtoms::lineFrame) {
@ -1237,7 +1238,7 @@ nsBidiPresUtils::ReorderFrames(nsIFrame* aFirstFrameOnLine,
}
BidiLineData bld(aFirstFrameOnLine, aNumFramesOnLine);
RepositionInlineFrames(&bld, aFirstFrameOnLine, aLineWM, aLineWidth);
RepositionInlineFrames(&bld, aFirstFrameOnLine, aLineWM, aLineWidth, aStart);
}
nsIFrame*
@ -1279,6 +1280,7 @@ nsBidiPresUtils::GetFrameBaseLevel(nsIFrame* aFrame)
void
nsBidiPresUtils::IsFirstOrLast(nsIFrame* aFrame,
nsContinuationStates* aContinuationStates,
bool aSpanDirMatchesLineDir,
bool& aIsFirst /* out */,
bool& aIsLast /* out */)
{
@ -1293,6 +1295,7 @@ nsBidiPresUtils::IsFirstOrLast(nsIFrame* aFrame,
* chain on this line.
*/
bool firstInLineOrder, lastInLineOrder;
nsFrameContinuationState* frameState = aContinuationStates->GetEntry(aFrame);
nsFrameContinuationState* firstFrameState;
@ -1327,16 +1330,30 @@ nsBidiPresUtils::IsFirstOrLast(nsIFrame* aFrame,
}
frameState->mHasContOnNextLines = (frame != nullptr);
aIsFirst = !frameState->mHasContOnPrevLines;
firstInLineOrder = true;
firstFrameState = frameState;
} else {
// aFrame is not the first visual frame of its continuation chain
aIsFirst = false;
firstInLineOrder = false;
firstFrameState = aContinuationStates->GetEntry(frameState->mFirstVisualFrame);
}
aIsLast = (firstFrameState->mFrameCount == 1 &&
!firstFrameState->mHasContOnNextLines);
lastInLineOrder = (firstFrameState->mFrameCount == 1);
if (aSpanDirMatchesLineDir) {
aIsFirst = firstInLineOrder;
aIsLast = lastInLineOrder;
} else {
aIsFirst = lastInLineOrder;
aIsLast = firstInLineOrder;
}
if (frameState->mHasContOnPrevLines) {
aIsFirst = false;
}
if (firstFrameState->mHasContOnNextLines) {
aIsLast = false;
}
if ((aIsFirst || aIsLast) &&
(aFrame->GetStateBits() & NS_FRAME_PART_OF_IBSPLIT)) {
@ -1356,6 +1373,24 @@ nsBidiPresUtils::IsFirstOrLast(nsIFrame* aFrame,
// Reduce number of remaining frames of the continuation chain on the line.
firstFrameState->mFrameCount--;
nsInlineFrame* testFrame = do_QueryFrame(aFrame);
if (testFrame) {
aFrame->AddStateBits(NS_INLINE_FRAME_BIDI_VISUAL_STATE_IS_SET);
if (aIsFirst) {
aFrame->AddStateBits(NS_INLINE_FRAME_BIDI_VISUAL_IS_FIRST);
} else {
aFrame->RemoveStateBits(NS_INLINE_FRAME_BIDI_VISUAL_IS_FIRST);
}
if (aIsLast) {
aFrame->AddStateBits(NS_INLINE_FRAME_BIDI_VISUAL_IS_LAST);
} else {
aFrame->RemoveStateBits(NS_INLINE_FRAME_BIDI_VISUAL_IS_LAST);
}
}
}
void
@ -1363,55 +1398,46 @@ nsBidiPresUtils::RepositionFrame(nsIFrame* aFrame,
bool aIsEvenLevel,
nscoord& aStart,
nsContinuationStates* aContinuationStates,
WritingMode aLineWM,
nscoord& aLineWidth)
WritingMode aContainerWM,
nscoord& aContainerWidth)
{
if (!aFrame)
return;
bool isFirst, isLast;
WritingMode frameWM = aFrame->GetWritingMode();
IsFirstOrLast(aFrame,
aContinuationStates,
aContainerWM.IsBidiLTR() == frameWM.IsBidiLTR(),
isFirst /* out */,
isLast /* out */);
WritingMode frameWM = aFrame->GetWritingMode();
nsInlineFrame* testFrame = do_QueryFrame(aFrame);
// We only need the margin if the frame is first or last in its own
// writing mode, but we're traversing the frames in the order of the
// container's writing mode. To get the right values, we set start and
// end margins on a logical margin in the frame's writing mode, and
// then convert the margin to the container's writing mode to set the
// coordinates.
if (testFrame) {
aFrame->AddStateBits(NS_INLINE_FRAME_BIDI_VISUAL_STATE_IS_SET);
if (isFirst) {
aFrame->AddStateBits(NS_INLINE_FRAME_BIDI_VISUAL_IS_FIRST);
} else {
aFrame->RemoveStateBits(NS_INLINE_FRAME_BIDI_VISUAL_IS_FIRST);
}
if (isLast) {
aFrame->AddStateBits(NS_INLINE_FRAME_BIDI_VISUAL_IS_LAST);
} else {
aFrame->RemoveStateBits(NS_INLINE_FRAME_BIDI_VISUAL_IS_LAST);
}
}
// This method is called from nsBlockFrame::PlaceLine via the call to
// bidiUtils->ReorderFrames, so this is guaranteed to be after the inlines
// have been reflowed, which is required for GetUsedMargin/Border/Padding
LogicalMargin margin(aLineWM, aFrame->GetUsedMargin());
if (isFirst) {
aStart += margin.IStart(aLineWM);
LogicalMargin frameMargin = aFrame->GetLogicalUsedMargin(frameWM);
LogicalMargin borderPadding = aFrame->GetLogicalUsedBorderAndPadding(frameWM);
if (!isFirst) {
frameMargin.IStart(frameWM) = 0;
borderPadding.IStart(frameWM) = 0;
}
if (!isLast) {
frameMargin.IEnd(frameWM) = 0;
borderPadding.IEnd(frameWM) = 0;
}
LogicalMargin margin = frameMargin.ConvertTo(aContainerWM, frameWM);
aStart += margin.IStart(aContainerWM);
nscoord start = aStart;
nscoord frameISize = aFrame->ISize(aLineWM);
if (!IsBidiLeaf(aFrame))
{
nscoord iCoord = 0;
LogicalMargin borderPadding(frameWM, aFrame->GetUsedBorderAndPadding());
if (isFirst) {
iCoord += borderPadding.IStart(frameWM);
}
if (!IsBidiLeaf(aFrame)) {
// If the resolved direction of the container is different from the
// direction of the frame, we need to traverse the child list in reverse
// order, to make it O(n) we store the list locally and iterate the list
@ -1430,35 +1456,33 @@ nsBidiPresUtils::RepositionFrame(nsIFrame* aFrame,
// Reposition the child frames
int32_t index = 0;
nscoord iCoord = borderPadding.IStart(frameWM);
while (frame) {
RepositionFrame(frame,
aIsEvenLevel,
iCoord,
aContinuationStates,
frameWM,
frameISize);
aFrame->GetLogicalSize(aContainerWM).Width(aContainerWM));
index++;
frame = reverseOrder ?
childList[childList.Length() - index - 1] :
frame->GetNextSibling();
}
if (isLast) {
iCoord += borderPadding.IEnd(frameWM);
}
aStart += iCoord;
aStart += iCoord + borderPadding.IEnd(frameWM);
} else {
aStart += frameISize;
aStart += aFrame->ISize(aContainerWM);
}
LogicalRect logicalRect(aLineWM, aFrame->GetRect(), aLineWidth);
logicalRect.IStart(aLineWM) = start;
logicalRect.ISize(aLineWM) = aStart - start;
aFrame->SetRect(aLineWM, logicalRect, aLineWidth);
LogicalRect logicalRect = aFrame->GetLogicalRect(aContainerWM,
aContainerWidth);
logicalRect.IStart(aContainerWM) = start;
logicalRect.ISize(aContainerWM) = aStart - start;
aFrame->SetRect(aContainerWM, logicalRect, aContainerWidth);
if (isLast) {
aStart += margin.IEnd(aLineWM);
}
aStart += margin.IEnd(aContainerWM);
}
void
@ -1485,20 +1509,10 @@ void
nsBidiPresUtils::RepositionInlineFrames(BidiLineData *aBld,
nsIFrame* aFirstChild,
WritingMode aLineWM,
nscoord& aLineWidth)
nscoord& aLineWidth,
nscoord& aStart)
{
nscoord startSpace = 0;
// This method is called from nsBlockFrame::PlaceLine via the call to
// bidiUtils->ReorderFrames, so this is guaranteed to be after the inlines
// have been reflowed, which is required for GetUsedMargin/Border/Padding
LogicalMargin margin(aLineWM, aFirstChild->GetUsedMargin());
if (!aFirstChild->GetPrevContinuation() &&
!aFirstChild->FrameIsNonFirstInIBSplit())
startSpace = margin.IStart(aLineWM);
nscoord start = LogicalRect(aLineWM, aFirstChild->GetRect(),
aLineWidth).IStart(aLineWM) - startSpace;
nscoord start = aStart;
nsIFrame* frame;
int32_t count = aBld->mVisualFrames.Length();
int32_t index;

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

@ -160,7 +160,8 @@ public:
static void ReorderFrames(nsIFrame* aFirstFrameOnLine,
int32_t aNumFramesOnLine,
mozilla::WritingMode aLineWM,
nscoord& aLineWidth);
nscoord& aLineWidth,
nscoord aStart);
/**
* Format Unicode text, taking into account bidi capabilities
@ -397,8 +398,8 @@ private:
bool aIsEvenLevel,
nscoord& aStart,
nsContinuationStates* aContinuationStates,
mozilla::WritingMode aLineWM,
nscoord& aLineWidth);
mozilla::WritingMode aContainerWM,
nscoord& aContainerWidth);
/*
* Initialize the continuation state(nsFrameContinuationState) to
@ -412,22 +413,32 @@ private:
nsContinuationStates* aContinuationStates);
/*
* Determine if aFrame is leftmost or rightmost, and set aIsLeftMost and
* aIsRightMost values. Also set continuation states of aContinuationStates.
* Determine if aFrame is first or last, and set aIsFirst and
* aIsLast values. Also set continuation states of
* aContinuationStates.
*
* A frame is leftmost if it's the first appearance of its continuation chain
* on the line and the chain is on its first line if it's LTR or the chain is
* on its last line if it's RTL.
* A frame is rightmost if it's the last appearance of its continuation chain
* on the line and the chain is on its first line if it's RTL or the chain is
* on its last line if it's LTR.
* A frame is first if it's the first appearance of its continuation
* chain on the line and the chain is on its first line.
* A frame is last if it's the last appearance of its continuation
* chain on the line and the chain is on its last line.
*
* @param aContinuationStates A map from nsIFrame* to nsFrameContinuationState
* @param[out] aIsLeftMost TRUE means aFrame is leftmost frame or continuation
* @param[out] aIsRightMost TRUE means aFrame is rightmost frame or continuation
* N.B: "First appearance" and "Last appearance" in the previous
* paragraph refer to the frame's inline direction, not necessarily
* the line's.
*
* @param aContinuationStates A map from nsIFrame* to
* nsFrameContinuationState
* @param[in] aSpanDirMatchesLineDir TRUE means that the inline
* direction of aFrame is the same
* as its container
* @param[out] aIsFirst TRUE means aFrame is first frame
* or continuation
* @param[out] aIsLast TRUE means aFrame is last frame
* or continuation
*/
static void IsFirstOrLast(nsIFrame* aFrame,
nsContinuationStates* aContinuationStates,
bool aSpanInLineOrder /* in */,
bool& aIsFirst /* out */,
bool& aIsLast /* out */);
@ -441,7 +452,8 @@ private:
static void RepositionInlineFrames(BidiLineData* aBld,
nsIFrame* aFirstChild,
mozilla::WritingMode aLineWM,
nscoord& aLineWidth);
nscoord& aLineWidth,
nscoord& aStart);
/**
* Helper method for Resolve()

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

@ -2598,20 +2598,22 @@ nsLineLayout::TextAlignLine(nsLineBox* aLine,
}
}
if (dx) {
if (mPresContext->BidiEnabled() &&
(!mPresContext->IsVisualMode() || !lineWM.IsBidiLTR())) {
nsBidiPresUtils::ReorderFrames(psd->mFirstFrame->mFrame,
aLine->GetChildCount(),
lineWM, mContainerWidth,
psd->mIStart + mTextIndent + dx);
if (dx) {
aLine->IndentBy(dx, mContainerWidth);
}
} else if (dx) {
for (PerFrameData* pfd = psd->mFirstFrame; pfd; pfd = pfd->mNext) {
pfd->mBounds.IStart(lineWM) += dx;
pfd->mFrame->SetRect(lineWM, pfd->mBounds, mContainerWidth);
}
aLine->IndentBy(dx, mContainerWidth);
}
if (mPresContext->BidiEnabled() &&
(!mPresContext->IsVisualMode() || !lineWM.IsBidiLTR())) {
nsBidiPresUtils::ReorderFrames(psd->mFirstFrame->mFrame,
aLine->GetChildCount(),
lineWM, mContainerWidth);
}
}
void

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

@ -0,0 +1,15 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Test for bug 1069941 -- borders</title>
</head>
<body>
<div dir="ltr">
<span dir="ltr" style="color:transparent;background:gray;border-left:10px solid teal;">+٥</span>
</div>
<div dir="ltr">
<span dir="ltr" style="color:transparent;background:gray;border-right:10px solid teal;">+٥</span>
</div>
</body>
</html>

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

@ -0,0 +1,15 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Test for bug 1069941 -- borders</title>
</head>
<body>
<div dir="ltr">
<span dir="rtl" style="color:transparent;background:gray;border-left:10px solid teal;">+٥</span>
</div>
<div dir="ltr">
<span dir="rtl" style="color:transparent;background:gray;border-right:10px solid teal;">+٥</span>
</div>
</body>
</html>

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

@ -0,0 +1,20 @@
<!DOCTYPE html>
<html>
<head>
<title>Test for bug 1069941 -- margins</title>
<style type="text/css">
.outer {
display: inline-block;
border: 1px solid lime;
}
.inner {
color:transparent;
margin-left: 50px;
border: 2px solid teal;
}
</style>
</head>
<body>
<span class="outer"><span class="inner">(12]</span></span>
</body>
</html>

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

@ -0,0 +1,20 @@
<!DOCTYPE html>
<html>
<head>
<title>Test for bug 1069941 -- margins</title>
<style type="text/css">
.outer {
display: inline-block;
border: 1px solid lime;
}
.inner {
color:transparent;
margin-left: 50px;
border: 2px solid teal;
}
</style>
</head>
<body>
<span class="outer"><span class="inner" dir="rtl">[12)</span></span>
</body>
</html>

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

@ -142,3 +142,6 @@ skip-if(B2G) == 726420-1.html 726420-1-ref.html
skip-if(B2G&&browserIsRemote) == 869833-1.xul 869833-1-ref.xul
== 922530-1.html 922530-1-ref.html
== 922550-1.html 922550-1-ref.html
== 1069941-inline-bidi-border-1.html 1069941-inline-bidi-border-1-ref.html
== 1069941-inline-bidi-margin-1.html 1069941-inline-bidi-margin-1-ref.html

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

@ -1048,6 +1048,21 @@ nsStyleContext::StructName(nsStyleStructID aSID)
return "Unknown";
}
}
/* static */ bool
nsStyleContext::LookupStruct(const nsACString& aName, nsStyleStructID& aResult)
{
if (false)
;
#define STYLE_STRUCT(name_, checkdata_cb_) \
else if (aName.EqualsLiteral(#name_)) \
aResult = eStyleStruct_##name_;
#include "nsStyleStructList.h"
#undef STYLE_STRUCT
else
return false;
return true;
}
#endif
bool
@ -1162,3 +1177,96 @@ nsStyleContext::DoClearCachedInheritedStyleDataOnDescendants(uint32_t aStructs)
ClearCachedInheritedStyleDataOnDescendants(aStructs);
}
#ifdef RESTYLE_LOGGING
nsCString
nsStyleContext::GetCachedStyleDataAsString(uint32_t aStructs)
{
nsCString structs;
for (nsStyleStructID i = nsStyleStructID(0);
i < nsStyleStructID_Length;
i = nsStyleStructID(i + 1)) {
if (aStructs & nsCachedStyleData::GetBitForSID(i)) {
const void* data = GetCachedStyleData(i);
if (!structs.IsEmpty()) {
structs.Append(' ');
}
structs.AppendPrintf("%s=%p", StructName(i), data);
if (HasCachedInheritedStyleData(i)) {
structs.AppendLiteral("(dependent)");
} else {
structs.AppendLiteral("(owned)");
}
}
}
return structs;
}
int32_t&
nsStyleContext::LoggingDepth()
{
static int32_t depth = 0;
return depth;
}
void
nsStyleContext::LogStyleContextTree(int32_t aLoggingDepth, uint32_t aStructs)
{
LoggingDepth() = aLoggingDepth;
LogStyleContextTree(true, aStructs);
}
void
nsStyleContext::LogStyleContextTree(bool aFirst, uint32_t aStructs)
{
nsCString structs = GetCachedStyleDataAsString(aStructs);
if (!structs.IsEmpty()) {
structs.Append(' ');
}
nsCString pseudo;
if (mPseudoTag) {
nsAutoString pseudoTag;
mPseudoTag->ToString(pseudoTag);
AppendUTF16toUTF8(pseudoTag, pseudo);
pseudo.Append(' ');
}
nsCString flags;
if (IsStyleIfVisited()) {
flags.AppendLiteral("IS_STYLE_IF_VISITED ");
}
if (UsesGrandancestorStyle()) {
flags.AppendLiteral("USES_GRANDANCESTOR_STYLE ");
}
if (IsShared()) {
flags.AppendLiteral("IS_SHARED ");
}
nsCString parent;
if (aFirst) {
parent.AppendPrintf("parent=%p ", mParent);
}
LOG_RESTYLE("%p(%d) %s%s%s%s",
this, mRefCnt,
structs.get(), pseudo.get(), flags.get(), parent.get());
LOG_RESTYLE_INDENT();
if (nullptr != mChild) {
nsStyleContext* child = mChild;
do {
child->LogStyleContextTree(false, aStructs);
child = child->mNextSibling;
} while (mChild != child);
}
if (nullptr != mEmptyChild) {
nsStyleContext* child = mEmptyChild;
do {
child->LogStyleContextTree(false, aStructs);
child = child->mNextSibling;
} while (mEmptyChild != child);
}
}
#endif

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

@ -8,6 +8,7 @@
#ifndef _nsStyleContext_h_
#define _nsStyleContext_h_
#include "mozilla/RestyleLogging.h"
#include "nsRuleNode.h"
#include "nsCSSPseudoElements.h"
@ -397,6 +398,13 @@ public:
void List(FILE* out, int32_t aIndent);
static void AssertStyleStructMaxDifferenceValid();
static const char* StructName(nsStyleStructID aSID);
static bool LookupStruct(const nsACString& aName, nsStyleStructID& aResult);
#endif
#ifdef RESTYLE_LOGGING
nsCString GetCachedStyleDataAsString(uint32_t aStructs);
void LogStyleContextTree(int32_t aLoggingDepth, uint32_t aStructs);
int32_t& LoggingDepth();
#endif
private:
@ -450,6 +458,15 @@ private:
int32_t aLevels) const;
#endif
#ifdef RESTYLE_LOGGING
void LogStyleContextTree(bool aFirst, uint32_t aStructs);
// This only gets called under call trees where we've already checked
// that PresContext()->RestyleManager()->ShouldLogRestyle() returned true.
// It exists here just to satisfy LOG_RESTYLE's expectations.
bool ShouldLogRestyle() { return true; }
#endif
nsStyleContext* mParent; // STRONG
// Children are kept in two circularly-linked lists. The list anchor

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

@ -164,6 +164,7 @@ class RemoteOptions(ReftestOptions):
# Android does not run leak tests, but set some reasonable defaults to avoid errors.
options.leakThresholds = {}
options.ignoreMissingLeaks = []
# TODO: Copied from main, but I think these are no longer used in a post xulrunner world
#options.xrePath = options.remoteTestRoot + self.automation._product + '/xulrunner'

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

@ -344,7 +344,7 @@ class RefTest(object):
# give the JS harness 30 seconds to deal
# with its own timeouts
timeout=options.timeout + 30.0)
processLeakLog(self.leakLogFile, options.leakThresholds)
processLeakLog(self.leakLogFile, options.leakThresholds, options.ignoreMissingLeaks)
self.automation.log.info("\nREFTEST INFO | runreftest.py | Running tests: end.")
finally:
self.cleanup(profileDir)
@ -513,6 +513,8 @@ class ReftestOptions(OptionParser):
options.leakThresholds = {"default": options.defaultLeakThreshold}
options.ignoreMissingLeaks = []
return options
def main():

0
media/libcubeb/update.sh Normal file → Executable file
Просмотреть файл

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

@ -1,3 +1,5 @@
[![Build Status](https://travis-ci.org/kinetiknz/nestegg.svg?branch=master)](https://travis-ci.org/kinetiknz/nestegg)
See INSTALL for build instructions.
Licensed under an ISC-style license. See LICENSE for details.

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

@ -5,4 +5,4 @@ Makefile.in build files for the Mozilla build system.
The nestegg git repository is: git://github.com/kinetiknz/nestegg.git
The git commit ID used was 46ab96bcc8b099704cc8a15993f80fe0269a5284.
The git commit ID used was 59220ae3e801cbad0f8160129c4df315469af671.

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

@ -381,8 +381,11 @@ int nestegg_sniff(unsigned char const * buffer, size_t length);
* Set the underlying allocation function for library allocations.
*
* @param realloc_func The desired function.
* @retval 0 realloc_func(p, 0) does not act as free()
* @retval 1 realloc_func(p, 0) acts as free()
* @retval -1 malloc failed during realloc_func test
*/
void nestegg_set_halloc_func(void * (* realloc_func)(void *, size_t));
int nestegg_set_halloc_func(void * (* realloc_func)(void *, size_t));
#if defined(__cplusplus)
}

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

@ -46,7 +46,7 @@ realloc_t halloc_allocator = NULL;
/*
* static methods
*/
static void _set_allocator(void);
int halloc_set_allocator(realloc_t realloc_func);
static void * _realloc(void * ptr, size_t n);
static int _relate(hblock_t * b, hblock_t * p);
@ -62,7 +62,10 @@ void * halloc(void * ptr, size_t len)
/* set up default allocator */
if (! allocator)
{
_set_allocator();
if (halloc_set_allocator(realloc) == 0)
{
halloc_set_allocator(_realloc);
}
assert(allocator);
}
@ -172,7 +175,7 @@ char * h_strdup(const char * str)
/*
* static stuff
*/
static void _set_allocator(void)
int halloc_set_allocator(realloc_t realloc_func)
{
void * p;
assert(! allocator);
@ -187,17 +190,17 @@ static void _set_allocator(void)
*
* Thanks to Stan Tobias for pointing this tricky part out.
*/
allocator = realloc;
if (! (p = malloc(1)))
if (! (p = realloc_func(NULL, 1)))
/* hmm */
return;
return -1;
if ((p = realloc(p, 0)))
if ((p = realloc_func(p, 0)))
{
/* realloc cannot be used as free() */
allocator = _realloc;
free(p);
/* realloc_func cannot be used as free() */
return 0;
}
allocator = realloc_func;
return 1;
}
static void * _realloc(void * ptr, size_t n)

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

@ -321,9 +321,18 @@ struct block_additional {
struct block_additional * next;
};
#define NE_IO_BUFSZ 16384
struct nestegg_io_buf {
nestegg_io io;
unsigned char buffer[NE_IO_BUFSZ];
size_t bufsz;
int offset;
};
/* Public (opaque) Structures */
struct nestegg {
nestegg_io * io;
struct nestegg_io_buf * io;
nestegg_log log;
struct pool_ctx * alloc_pool;
uint64_t last_id;
@ -546,19 +555,99 @@ ne_alloc(size_t size)
}
static int
ne_io_read(nestegg_io * io, void * buffer, size_t length)
ne_io_read(struct nestegg_io_buf * io, void * buffer, size_t length)
{
return io->read(buffer, length, io->userdata);
int64_t off;
int r;
size_t avail;
assert(io->offset == -1 || (io->offset >= 0 && (unsigned int) io->offset < io->bufsz));
/* Too big to buffer, invalidate buffer and read through */
if (length > io->bufsz) {
if (io->offset != -1) {
r = io->io.seek(-(io->bufsz - io->offset), NESTEGG_SEEK_CUR, io->io.userdata);
if (r != 0) {
return -1;
}
}
io->offset = -1;
return io->io.read(buffer, length, io->io.userdata);
}
/* Buffer invalid */
if (io->offset == -1) {
off = io->io.tell(io->io.userdata);
if (off == -1) {
return -1;
}
/* Refill buffer */
r = io->io.read(io->buffer, io->bufsz, io->io.userdata);
if (r != 1) {
/* Read truncated due to being within io->bufsz of EOS, reset read
position and switch to read through mode */
io->offset = -1;
io->bufsz = 0;
if (r == 0) {
r = io->io.seek(off, NESTEGG_SEEK_SET, io->io.userdata);
}
if (r == 0) {
return io->io.read(buffer, length, io->io.userdata);
}
return -1;
}
if (r == 1) {
io->offset = 0;
}
}
/* Service request with what we have */
avail = length;
if (io->bufsz - io->offset < length) {
avail = io->bufsz - io->offset;
}
memcpy(buffer, io->buffer + io->offset, avail);
io->offset += avail;
if ((unsigned int) io->offset == io->bufsz) {
io->offset = -1;
}
/* Still more to read, invalidate buffer and read more */
if (length - avail > 0) {
return ne_io_read(io, (char *) buffer + avail, length - avail);
}
return 1;
}
static int
ne_io_seek(nestegg_io * io, int64_t offset, int whence)
ne_io_seek(struct nestegg_io_buf * io, int64_t offset, int whence)
{
return io->seek(offset, whence, io->userdata);
/* Invalidate buffer */
io->offset = -1;
return io->io.seek(offset, whence, io->io.userdata);
}
static int64_t
ne_io_tell(struct nestegg_io_buf * io)
{
int64_t off;
off = io->io.tell(io->io.userdata);
if (off == -1) {
return -1;
}
if (io->offset == -1) {
return off;
}
assert(off >= (int64_t) io->bufsz - io->offset);
return off - io->bufsz + (unsigned int) io->offset;
}
static int
ne_io_read_skip(nestegg_io * io, size_t length)
ne_io_read_skip(struct nestegg_io_buf * io, size_t length)
{
size_t get;
unsigned char buf[8192];
@ -575,14 +664,8 @@ ne_io_read_skip(nestegg_io * io, size_t length)
return r;
}
static int64_t
ne_io_tell(nestegg_io * io)
{
return io->tell(io->userdata);
}
static int
ne_bare_read_vint(nestegg_io * io, uint64_t * value, uint64_t * length, enum vint_mask maskflag)
ne_bare_read_vint(struct nestegg_io_buf * io, uint64_t * value, uint64_t * length, enum vint_mask maskflag)
{
int r;
unsigned char b;
@ -619,19 +702,19 @@ ne_bare_read_vint(nestegg_io * io, uint64_t * value, uint64_t * length, enum vin
}
static int
ne_read_id(nestegg_io * io, uint64_t * value, uint64_t * length)
ne_read_id(struct nestegg_io_buf * io, uint64_t * value, uint64_t * length)
{
return ne_bare_read_vint(io, value, length, MASK_NONE);
}
static int
ne_read_vint(nestegg_io * io, uint64_t * value, uint64_t * length)
ne_read_vint(struct nestegg_io_buf * io, uint64_t * value, uint64_t * length)
{
return ne_bare_read_vint(io, value, length, MASK_FIRST_BIT);
}
static int
ne_read_svint(nestegg_io * io, int64_t * value, uint64_t * length)
ne_read_svint(struct nestegg_io_buf * io, int64_t * value, uint64_t * length)
{
int r;
uint64_t uvalue;
@ -653,7 +736,7 @@ ne_read_svint(nestegg_io * io, int64_t * value, uint64_t * length)
}
static int
ne_read_uint(nestegg_io * io, uint64_t * val, uint64_t length)
ne_read_uint(struct nestegg_io_buf * io, uint64_t * val, uint64_t length)
{
unsigned char b;
int r;
@ -675,7 +758,7 @@ ne_read_uint(nestegg_io * io, uint64_t * val, uint64_t length)
}
static int
ne_read_int(nestegg_io * io, int64_t * val, uint64_t length)
ne_read_int(struct nestegg_io_buf * io, int64_t * val, uint64_t length)
{
int r;
uint64_t uval, base;
@ -688,8 +771,8 @@ ne_read_int(nestegg_io * io, int64_t * val, uint64_t length)
base = 1;
base <<= length * 8 - 1;
if (uval >= base) {
base = 1;
base <<= length * 8;
base = 1;
base <<= length * 8;
} else {
base = 0;
}
@ -702,7 +785,7 @@ ne_read_int(nestegg_io * io, int64_t * val, uint64_t length)
}
static int
ne_read_float(nestegg_io * io, double * val, uint64_t length)
ne_read_float(struct nestegg_io_buf * io, double * val, uint64_t length)
{
union {
uint64_t u;
@ -736,9 +819,9 @@ ne_read_string(nestegg * ctx, char ** val, uint64_t length)
if (!str)
return -1;
if (length) {
r = ne_io_read(ctx->io, (unsigned char *) str, length);
if (r != 1)
return r;
r = ne_io_read(ctx->io, (unsigned char *) str, length);
if (r != 1)
return r;
}
str[length] = '\0';
*val = str;
@ -1018,8 +1101,9 @@ ne_read_simple(nestegg * ctx, struct ebml_element_desc * desc, size_t length)
break;
case TYPE_MASTER:
case TYPE_UNKNOWN:
assert(0);
default:
r = 0;
assert(0);
break;
}
@ -1136,7 +1220,7 @@ ne_xiph_lace_value(unsigned char ** np)
}
static int
ne_read_xiph_lace_value(nestegg_io * io, uint64_t * value, size_t * consumed)
ne_read_xiph_lace_value(struct nestegg_io_buf * io, uint64_t * value, size_t * consumed)
{
int r;
uint64_t lace;
@ -1159,7 +1243,7 @@ ne_read_xiph_lace_value(nestegg_io * io, uint64_t * value, size_t * consumed)
}
static int
ne_read_xiph_lacing(nestegg_io * io, size_t block, size_t * read, uint64_t n, uint64_t * sizes)
ne_read_xiph_lacing(struct nestegg_io_buf * io, size_t block, size_t * read, uint64_t n, uint64_t * sizes)
{
int r;
size_t i = 0;
@ -1182,7 +1266,7 @@ ne_read_xiph_lacing(nestegg_io * io, size_t block, size_t * read, uint64_t n, ui
}
static int
ne_read_ebml_lacing(nestegg_io * io, size_t block, size_t * read, uint64_t n, uint64_t * sizes)
ne_read_ebml_lacing(struct nestegg_io_buf * io, size_t block, size_t * read, uint64_t n, uint64_t * sizes)
{
int r;
uint64_t lace, sum, length;
@ -1792,9 +1876,9 @@ struct sniff_buffer {
};
static int
ne_buffer_read(void * buffer, size_t length, void * user_data)
ne_buffer_read(void * buffer, size_t length, void * userdata)
{
struct sniff_buffer * sb = user_data;
struct sniff_buffer * sb = userdata;
int rv = 1;
size_t available = sb->length - sb->offset;
@ -1809,21 +1893,21 @@ ne_buffer_read(void * buffer, size_t length, void * user_data)
}
static int
ne_buffer_seek(int64_t offset, int whence, void * user_data)
ne_buffer_seek(int64_t offset, int whence, void * userdata)
{
struct sniff_buffer * sb = user_data;
struct sniff_buffer * sb = userdata;
int64_t o = sb->offset;
switch(whence) {
case NESTEGG_SEEK_SET:
o = offset;
break;
case NESTEGG_SEEK_CUR:
o += offset;
break;
case NESTEGG_SEEK_END:
o = sb->length + offset;
break;
case NESTEGG_SEEK_SET:
o = offset;
break;
case NESTEGG_SEEK_CUR:
o += offset;
break;
case NESTEGG_SEEK_END:
o = sb->length + offset;
break;
}
if (o < 0 || o > (int64_t) sb->length)
@ -1834,9 +1918,9 @@ ne_buffer_seek(int64_t offset, int whence, void * user_data)
}
static int64_t
ne_buffer_tell(void * user_data)
ne_buffer_tell(void * userdata)
{
struct sniff_buffer * sb = user_data;
struct sniff_buffer * sb = userdata;
return sb->offset;
}
@ -1860,7 +1944,9 @@ ne_match_webm(nestegg_io io, int64_t max_offset)
nestegg_destroy(ctx);
return -1;
}
*ctx->io = io;
ctx->io->io = io;
ctx->io->bufsz = NE_IO_BUFSZ;
ctx->io->offset = -1;
ctx->alloc_pool = ne_pool_init();
if (!ctx->alloc_pool) {
nestegg_destroy(ctx);
@ -1918,7 +2004,9 @@ nestegg_init(nestegg ** context, nestegg_io io, nestegg_log callback, int64_t ma
nestegg_destroy(ctx);
return -1;
}
*ctx->io = io;
ctx->io->io = io;
ctx->io->bufsz = NE_IO_BUFSZ;
ctx->io->offset = -1;
ctx->log = callback;
ctx->alloc_pool = ne_pool_init();
if (!ctx->alloc_pool) {
@ -2264,35 +2352,35 @@ nestegg_track_codec_data(nestegg * ctx, unsigned int track, unsigned int item,
return -1;
if (nestegg_track_codec_id(ctx, track) != NESTEGG_CODEC_VORBIS
&& nestegg_track_codec_id(ctx, track) != NESTEGG_CODEC_OPUS)
&& nestegg_track_codec_id(ctx, track) != NESTEGG_CODEC_OPUS)
return -1;
if (ne_get_binary(entry->codec_private, &codec_private) != 0)
return -1;
if (nestegg_track_codec_id(ctx, track) == NESTEGG_CODEC_VORBIS) {
p = codec_private.data;
count = *p++ + 1;
p = codec_private.data;
count = *p++ + 1;
if (count > 3)
if (count > 3)
return -1;
i = 0;
total = 0;
while (--count) {
sizes[i] = ne_xiph_lace_value(&p);
total += sizes[i];
i += 1;
}
sizes[i] = codec_private.length - total - (p - codec_private.data);
for (i = 0; i < item; ++i) {
if (sizes[i] > LIMIT_FRAME)
return -1;
i = 0;
total = 0;
while (--count) {
sizes[i] = ne_xiph_lace_value(&p);
total += sizes[i];
i += 1;
}
sizes[i] = codec_private.length - total - (p - codec_private.data);
for (i = 0; i < item; ++i) {
if (sizes[i] > LIMIT_FRAME)
return -1;
p += sizes[i];
}
*data = p;
*length = sizes[item];
p += sizes[i];
}
*data = p;
*length = sizes[item];
} else {
*data = codec_private.data;
*length = codec_private.length;
@ -2494,7 +2582,7 @@ nestegg_free_packet(nestegg_packet * pkt)
free(block_additional);
}
free(pkt);
free(pkt);
}
int
@ -2588,28 +2676,31 @@ int
nestegg_has_cues(nestegg * ctx)
{
return ctx->segment.cues.cue_point.head ||
ne_find_seek_for_id(ctx->segment.seek_head.head, ID_CUES);
ne_find_seek_for_id(ctx->segment.seek_head.head, ID_CUES);
}
int
nestegg_sniff(unsigned char const * buffer, size_t length)
{
nestegg_io io;
struct sniff_buffer user_data;
struct sniff_buffer userdata;
user_data.buffer = buffer;
user_data.length = length;
user_data.offset = 0;
userdata.buffer = buffer;
userdata.length = length;
userdata.offset = 0;
io.read = ne_buffer_read;
io.seek = ne_buffer_seek;
io.tell = ne_buffer_tell;
io.userdata = &user_data;
io.userdata = &userdata;
return ne_match_webm(io, length);
}
void
/* From halloc.c */
int halloc_set_allocator(realloc_t realloc_func);
int
nestegg_set_halloc_func(void * (* realloc_func)(void *, size_t))
{
halloc_allocator = realloc_func;
return halloc_set_allocator(realloc_func);
}

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

@ -7,7 +7,7 @@ cp $1/halloc/src/halloc.c src
cp $1/halloc/src/hlist.h src
cp $1/halloc/src/macros.h src
cp $1/LICENSE .
cp $1/README .
cp $1/README.md .
cp $1/AUTHORS .
if [ -d $1/.git ]; then
rev=$(cd $1 && git rev-parse --verify HEAD)

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

@ -2549,12 +2549,12 @@ cc_boolean vcmCheckAttribs(cc_uint32_t media_type, void *sdp_p, int level,
rcap->max_cpb = t_uint;
}
if ( ccsdpAttrGetFmtpMaxCpb(sdp_p, level, 0, fmtp_inst, &t_uint) == SDP_SUCCESS )
if ( ccsdpAttrGetFmtpMaxDpb(sdp_p, level, 0, fmtp_inst, &t_uint) == SDP_SUCCESS )
{
rcap->max_dpb = t_uint;
}
if ( ccsdpAttrGetFmtpMaxCpb(sdp_p, level, 0, fmtp_inst, &t_uint) == SDP_SUCCESS )
if ( ccsdpAttrGetFmtpMaxBr(sdp_p, level, 0, fmtp_inst, &t_uint) == SDP_SUCCESS )
{
rcap->max_br = t_uint;
}

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

@ -1124,6 +1124,7 @@ public abstract class GeckoApp
mGeckoReadyStartupTimer = new Telemetry.UptimeTimer("FENNEC_STARTUP_TIME_GECKOREADY");
final Intent intent = getIntent();
final String action = intent.getAction();
final String args = intent.getStringExtra("args");
earlyStartJavaSampler(intent);
@ -1163,7 +1164,13 @@ public abstract class GeckoApp
}
}
BrowserDB.initialize(getProfile().getName());
// Speculatively pre-fetch the profile in the background.
ThreadUtils.postToBackgroundThread(new Runnable() {
@Override
public void run() {
getProfile();
}
});
// Workaround for <http://code.google.com/p/android/issues/detail?id=20915>.
try {
@ -1205,6 +1212,30 @@ public abstract class GeckoApp
// without killing the entire application (see Bug 769269).
mIsRestoringActivity = true;
Telemetry.HistogramAdd("FENNEC_RESTORING_ACTIVITY", 1);
} else {
final String uri = getURIFromIntent(intent);
GeckoThread.setArgs(args);
GeckoThread.setAction(action);
GeckoThread.setUri(TextUtils.isEmpty(uri) ? null : uri);
}
if (!ACTION_DEBUG.equals(action) &&
GeckoThread.checkAndSetLaunchState(GeckoThread.LaunchState.Launching,
GeckoThread.LaunchState.Launched)) {
GeckoThread.createAndStart();
} else if (ACTION_DEBUG.equals(action) &&
GeckoThread.checkAndSetLaunchState(GeckoThread.LaunchState.Launching,
GeckoThread.LaunchState.WaitForDebugger)) {
ThreadUtils.getUiHandler().postDelayed(new Runnable() {
@Override
public void run() {
GeckoThread.setLaunchState(GeckoThread.LaunchState.Launched);
GeckoThread.createAndStart();
}
}, 1000 * 5 /* 5 seconds */);
}
Bundle stateBundle = getIntent().getBundleExtra(EXTRA_STATE_BUNDLE);
@ -1368,6 +1399,9 @@ public abstract class GeckoApp
layerView.initializeView(EventDispatcher.getInstance());
mLayerView = layerView;
GeckoAppShell.setLayerView(layerView);
GeckoAppShell.sendEventToGecko(GeckoEvent.createObjectEvent(
GeckoEvent.ACTION_OBJECT_LAYER_CLIENT, layerView.getLayerClientObject()));
// bind the GeckoEditable instance to the new LayerView
GeckoAppShell.notifyIMEContext(GeckoEditableListener.IME_STATE_DISABLED, "", "", "");
}
@ -1425,6 +1459,8 @@ public abstract class GeckoApp
initializeChrome();
BrowserDB.initialize(getProfile().getName());
// If we are doing a restore, read the session data and send it to Gecko
if (!mIsRestoringActivity) {
String restoreMessage = null;
@ -1467,25 +1503,6 @@ public abstract class GeckoApp
Telemetry.HistogramAdd("FENNEC_STARTUP_GECKOAPP_ACTION", startupAction.ordinal());
if (!mIsRestoringActivity) {
GeckoThread.setArgs(intent.getStringExtra("args"));
GeckoThread.setAction(intent.getAction());
GeckoThread.setUri(passedUri);
}
if (!ACTION_DEBUG.equals(action) &&
GeckoThread.checkAndSetLaunchState(GeckoThread.LaunchState.Launching, GeckoThread.LaunchState.Launched)) {
GeckoThread.createAndStart();
} else if (ACTION_DEBUG.equals(action) &&
GeckoThread.checkAndSetLaunchState(GeckoThread.LaunchState.Launching, GeckoThread.LaunchState.WaitForDebugger)) {
ThreadUtils.getUiHandler().postDelayed(new Runnable() {
@Override
public void run() {
GeckoThread.setLaunchState(GeckoThread.LaunchState.Launching);
GeckoThread.createAndStart();
}
}, 1000 * 5 /* 5 seconds */);
}
// Check if launched from data reporting notification.
if (ACTION_LAUNCH_SETTINGS.equals(action)) {
Intent settingsIntent = new Intent(GeckoApp.this, GeckoPreferences.class);
@ -1580,7 +1597,6 @@ public abstract class GeckoApp
if (selectedTab != null)
Tabs.getInstance().notifyListeners(selectedTab, Tabs.TabEvents.SELECTED);
geckoConnected();
GeckoAppShell.setLayerClient(mLayerView.getLayerClientObject());
GeckoAppShell.sendEventToGecko(GeckoEvent.createBroadcastEvent("Viewport:Flush", null));
}
@ -1647,7 +1663,7 @@ public abstract class GeckoApp
}
}
public GeckoProfile getProfile() {
public synchronized GeckoProfile getProfile() {
// fall back to default profile if we didn't load a specific one
if (mProfile == null) {
mProfile = GeckoProfile.get(this);

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

@ -205,8 +205,6 @@ public class GeckoAppShell
public static native void nativeInit();
// helper methods
// public static native void setSurfaceView(GeckoSurfaceView sv);
public static native void setLayerClient(Object client);
public static native void onResume();
public static void callObserver(String observerKey, String topic, String data) {
sendEventToGecko(GeckoEvent.createCallObserverEvent(observerKey, topic, data));
@ -342,9 +340,6 @@ public class GeckoAppShell
// run gecko -- it will spawn its own thread
GeckoAppShell.nativeInit();
if (sLayerView != null)
GeckoAppShell.setLayerClient(sLayerView.getLayerClientObject());
// First argument is the .apk path
String combinedArgs = apkPath + " -greomni " + apkPath;
if (args != null)

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

@ -76,6 +76,7 @@ public class GeckoEvent {
KEY_EVENT(1),
MOTION_EVENT(2),
SENSOR_EVENT(3),
PROCESS_OBJECT(4),
LOCATION_EVENT(5),
IME_EVENT(6),
SIZE_CHANGED(8),
@ -183,6 +184,8 @@ public class GeckoEvent {
public static final int ACTION_GAMEPAD_BUTTON = 1;
public static final int ACTION_GAMEPAD_AXES = 2;
public static final int ACTION_OBJECT_LAYER_CLIENT = 1;
private final int mType;
private int mAction;
private boolean mAckNeeded;
@ -245,6 +248,8 @@ public class GeckoEvent {
private String[] mPrefNames;
private Object mObject;
private GeckoEvent(NativeGeckoEvent event) {
mType = event.value;
}
@ -597,6 +602,13 @@ public class GeckoEvent {
return event;
}
public static GeckoEvent createObjectEvent(final int action, final Object object) {
GeckoEvent event = GeckoEvent.get(NativeGeckoEvent.PROCESS_OBJECT);
event.mAction = action;
event.mObject = object;
return event;
}
public static GeckoEvent createLocationEvent(Location l) {
GeckoEvent event = GeckoEvent.get(NativeGeckoEvent.LOCATION_EVENT);
event.mLocation = l;

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

@ -17,7 +17,7 @@ import java.util.Hashtable;
import org.mozilla.gecko.GeckoProfileDirectories.NoMozillaDirectoryException;
import org.mozilla.gecko.GeckoProfileDirectories.NoSuchProfileException;
import org.mozilla.gecko.db.BrowserDB;
import org.mozilla.gecko.db.LocalBrowserDB;
import org.mozilla.gecko.distribution.Distribution;
import org.mozilla.gecko.mozglue.RobocopTarget;
import org.mozilla.gecko.util.INIParser;
@ -209,7 +209,7 @@ public final class GeckoProfile {
* Now do the things that createProfileDirectory normally does --
* right now that's kicking off DB init.
*/
profile.enqueueInitialization();
profile.enqueueInitialization(profile.getDir());
return profile;
} catch (Exception ex) {
@ -650,7 +650,7 @@ public final class GeckoProfile {
// Trigger init for non-webapp profiles.
if (!mIsWebAppProfile) {
enqueueInitialization();
enqueueInitialization(profileDir);
}
// Write out profile creation time, mirroring the logic in nsToolkitProfileService.
@ -684,7 +684,7 @@ public final class GeckoProfile {
* This is public for use *from tests only*!
*/
@RobocopTarget
public void enqueueInitialization() {
public void enqueueInitialization(final File profileDir) {
Log.i(LOGTAG, "Enqueuing profile init.");
final Context context = mApplicationContext;
@ -697,13 +697,24 @@ public final class GeckoProfile {
final ContentResolver cr = context.getContentResolver();
// We pass the number of added bookmarks to ensure that the
// indices of the distribution and default bookmarks are
// contiguous. Because there are always at least as many
// bookmarks as there are favicons, we can also guarantee that
// the favicon IDs won't overlap.
final int offset = BrowserDB.addDistributionBookmarks(cr, distribution, 0);
BrowserDB.addDefaultBookmarks(context, cr, offset);
// Because we are running in the background, we want to synchronize on the
// GeckoProfile instance so that we don't race with main thread operations
// such as locking/unlocking/removing the profile.
synchronized (GeckoProfile.this) {
// Skip initialization if the profile directory has been removed.
if (!profileDir.exists()) {
return;
}
// We pass the number of added bookmarks to ensure that the
// indices of the distribution and default bookmarks are
// contiguous. Because there are always at least as many
// bookmarks as there are favicons, we can also guarantee that
// the favicon IDs won't overlap.
final LocalBrowserDB db = new LocalBrowserDB(getName());
final int offset = db.addDistributionBookmarks(cr, distribution, 0);
db.addDefaultBookmarks(context, cr, offset);
}
}
});
}

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

@ -136,25 +136,29 @@ public class GeckoThread extends Thread implements GeckoEventListener {
}
private String addCustomProfileArg(String args) {
String profile = "";
String guest = "";
String profileArg = "";
String guestArg = "";
if (GeckoAppShell.getGeckoInterface() != null) {
if (GeckoAppShell.getGeckoInterface().getProfile().inGuestMode()) {
final GeckoProfile profile = GeckoAppShell.getGeckoInterface().getProfile();
if (profile.inGuestMode()) {
try {
profile = " -profile " + GeckoAppShell.getGeckoInterface().getProfile().getDir().getCanonicalPath();
} catch (IOException ioe) { Log.e(LOGTAG, "error getting guest profile path", ioe); }
profileArg = " -profile " + profile.getDir().getCanonicalPath();
} catch (final IOException ioe) {
Log.e(LOGTAG, "error getting guest profile path", ioe);
}
if (args == null || !args.contains(BrowserApp.GUEST_BROWSING_ARG)) {
guest = " " + BrowserApp.GUEST_BROWSING_ARG;
guestArg = " " + BrowserApp.GUEST_BROWSING_ARG;
}
} else if (!GeckoProfile.sIsUsingCustomProfile) {
// If nothing was passed in in the intent, force Gecko to use the default profile for
// for this activity
profile = " -P " + GeckoAppShell.getGeckoInterface().getProfile().getName();
// If nothing was passed in the intent, make sure the default profile exists and
// force Gecko to use the default profile for this activity
profileArg = " -P " + profile.forceCreate().getName();
}
}
return (args != null ? args : "") + profile + guest;
return (args != null ? args : "") + profileArg + guestArg;
}
@Override

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

@ -174,6 +174,8 @@ public class GeckoView extends LayerView
BrowserDB.initialize(profile.getName());
GeckoAppShell.setLayerView(this);
GeckoAppShell.sendEventToGecko(GeckoEvent.createObjectEvent(
GeckoEvent.ACTION_OBJECT_LAYER_CLIENT, getLayerClientObject()));
GeckoThread.createAndStart();
} else if(GeckoThread.checkLaunchState(GeckoThread.LaunchState.GeckoRunning)) {
// If Gecko is already running, that means the Activity was
@ -247,7 +249,6 @@ public class GeckoView extends LayerView
if (selectedTab != null)
Tabs.getInstance().notifyListeners(selectedTab, Tabs.TabEvents.SELECTED);
geckoConnected();
GeckoAppShell.setLayerClient(getLayerClientObject());
GeckoAppShell.sendEventToGecko(GeckoEvent.createBroadcastEvent("Viewport:Flush", null));
}

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

@ -157,7 +157,7 @@ public class SuggestedSites {
final Context context;
final Distribution distribution;
final File file;
private File cachedFile;
private Map<String, Site> cachedSites;
private Set<String> cachedBlacklist;
@ -166,14 +166,20 @@ public class SuggestedSites {
}
public SuggestedSites(Context appContext, Distribution distribution) {
this(appContext, distribution,
GeckoProfile.get(appContext).getFile(FILENAME));
this(appContext, distribution, null);
}
public SuggestedSites(Context appContext, Distribution distribution, File file) {
this.context = appContext;
this.distribution = distribution;
this.file = file;
this.cachedFile = file;
}
synchronized File getFile() {
if (cachedFile == null) {
cachedFile = GeckoProfile.get(context).getFile(FILENAME);
}
return cachedFile;
}
private static boolean isNewLocale(Context context, Locale requestedLocale) {
@ -306,6 +312,7 @@ public class SuggestedSites {
setCachedSites(sites);
// Save the result to disk.
final File file = getFile();
synchronized (file) {
saveSites(file, sites);
}
@ -349,6 +356,7 @@ public class SuggestedSites {
private Map<String, Site> loadFromProfile() {
try {
final File file = getFile();
synchronized (file) {
return loadSites(file);
}
@ -462,7 +470,7 @@ public class SuggestedSites {
// Force the suggested sites file in profile dir to be re-generated
// if the locale has changed.
if (isNewLocale) {
file.delete();
getFile().delete();
}
if (cachedSites == null || isNewLocale) {

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

@ -133,7 +133,7 @@ abstract class BaseTest extends BaseRobocopTest {
// In Robocop tests, we typically don't get initialized correctly, because
// GeckoProfile doesn't create the profile directory.
profile.enqueueInitialization();
profile.enqueueInitialization(profile.getDir());
}
@Override

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

@ -12,44 +12,65 @@ import java.util.concurrent.SynchronousQueue;
final class GeckoBackgroundThread extends Thread {
private static final String LOOPER_NAME = "GeckoBackgroundThread";
// Guarded by 'this'.
private static Handler sHandler;
private SynchronousQueue<Handler> mHandlerQueue = new SynchronousQueue<Handler>();
// Guarded by 'GeckoBackgroundThread.class'.
private static Handler handler;
private static Thread thread;
// The initial Runnable to run on the new thread. Its purpose
// is to avoid us having to wait for the new thread to start.
private Runnable initialRunnable;
// Singleton, so private constructor.
private GeckoBackgroundThread() {
super();
private GeckoBackgroundThread(final Runnable initialRunnable) {
this.initialRunnable = initialRunnable;
}
@Override
public void run() {
setName(LOOPER_NAME);
Looper.prepare();
try {
mHandlerQueue.put(new Handler());
} catch (InterruptedException ie) {}
synchronized (GeckoBackgroundThread.class) {
handler = new Handler();
GeckoBackgroundThread.class.notify();
}
if (initialRunnable != null) {
initialRunnable.run();
initialRunnable = null;
}
Looper.loop();
}
// Get a Handler for a looper thread, or create one if it doesn't yet exist.
/*package*/ static synchronized Handler getHandler() {
if (sHandler == null) {
GeckoBackgroundThread lt = new GeckoBackgroundThread();
ThreadUtils.setBackgroundThread(lt);
lt.start();
try {
sHandler = lt.mHandlerQueue.take();
} catch (InterruptedException ie) {}
}
return sHandler;
private static void startThread(final Runnable initialRunnable) {
thread = new GeckoBackgroundThread(initialRunnable);
ThreadUtils.setBackgroundThread(thread);
thread.setDaemon(true);
thread.start();
}
/*package*/ static void post(Runnable runnable) {
Handler handler = getHandler();
if (handler == null) {
throw new IllegalStateException("No handler! Must have been interrupted. Not posting.");
// Get a Handler for a looper thread, or create one if it doesn't yet exist.
/*package*/ static synchronized Handler getHandler() {
if (thread == null) {
startThread(null);
}
handler.post(runnable);
while (handler == null) {
try {
GeckoBackgroundThread.class.wait();
} catch (final InterruptedException e) {
}
}
return handler;
}
/*package*/ static synchronized void post(final Runnable runnable) {
if (thread == null) {
startThread(runnable);
return;
}
getHandler().post(runnable);
}
}

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

@ -189,6 +189,7 @@ public final class ThreadUtils {
return isOnThread(getUiThread());
}
@RobocopTarget
public static boolean isOnBackgroundThread() {
if (sBackgroundThread == null) {
return false;
@ -197,6 +198,7 @@ public final class ThreadUtils {
return isOnThread(sBackgroundThread);
}
@RobocopTarget
public static boolean isOnThread(Thread thread) {
return (Thread.currentThread().getId() == thread.getId());
}

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

@ -9,7 +9,7 @@ const Cu = Components.utils;
Cu.import("resource://gre/modules/PrivateBrowsingUtils.jsm");
if (!PrivateBrowsingUtils.isWindowPrivate(window)) {
if (!PrivateBrowsingUtils.isContentWindowPrivate(window)) {
document.addEventListener("DOMContentLoaded", function () {
document.body.setAttribute("class", "normal");
}, false);

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

@ -98,6 +98,8 @@ if test ! "$RELEASE_BUILD"; then
MOZ_ANDROID_DOWNLOADS_INTEGRATION=1
fi
# Enable generational GC on mobile.
JSGC_GENERATIONAL=1
# Use the low-memory GC tuning.
JS_GC_SMALL_CHUNK_SIZE=1

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

@ -12,6 +12,9 @@ jar.sources += [
'src/harness/BrowserInstrumentationTestRunner.java',
'src/harness/BrowserTestListener.java',
'src/TestDistribution.java',
'src/TestGeckoBackgroundThread.java',
'src/TestGeckoMenu.java',
'src/TestGeckoProfilesProvider.java',
'src/TestGeckoSharedPrefs.java',
'src/TestImageDownloader.java',
'src/TestJarReader.java',

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

@ -0,0 +1,55 @@
/* 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/. */
package org.mozilla.gecko;
import org.mozilla.gecko.util.ThreadUtils;
public class TestGeckoBackgroundThread extends BrowserTestCase {
private boolean finishedTest;
private boolean ranFirstRunnable;
public void testGeckoBackgroundThread() throws InterruptedException {
final Thread testThread = Thread.currentThread();
ThreadUtils.postToBackgroundThread(new Runnable() {
@Override
public void run() {
// Must *not* be on thread that posted the Runnable.
assertFalse(ThreadUtils.isOnThread(testThread));
// Must be on background thread.
assertTrue(ThreadUtils.isOnBackgroundThread());
ranFirstRunnable = true;
}
});
// Post a second Runnable to make sure it still runs on the background thread,
// and it only runs after the first Runnable has run.
ThreadUtils.postToBackgroundThread(new Runnable() {
@Override
public void run() {
// Must still be on background thread.
assertTrue(ThreadUtils.isOnBackgroundThread());
// This Runnable must be run after the first Runnable had finished.
assertTrue(ranFirstRunnable);
synchronized (TestGeckoBackgroundThread.this) {
finishedTest = true;
TestGeckoBackgroundThread.this.notify();
}
}
});
synchronized (this) {
while (!finishedTest) {
wait();
}
}
}
}

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

@ -135,7 +135,7 @@ pref("dom.serviceWorkers.enabled", false);
pref("dom.enable_performance", true);
// Whether resource timing will be gathered and returned by performance.GetEntries*
pref("dom.enable_resource_timing", false);
pref("dom.enable_resource_timing", true);
// Whether the Gamepad API is enabled
pref("dom.gamepad.enabled", true);
@ -341,7 +341,6 @@ pref("media.peerconnection.video.max_bitrate", 2000);
#endif
pref("media.navigator.permission.disabled", false);
pref("media.peerconnection.default_iceservers", "[{\"url\": \"stun:stun.services.mozilla.com\"}]");
pref("media.peerconnection.trickle_ice", true);
pref("media.peerconnection.use_document_iceservers", true);
// Do not enable identity before ensuring that the UX cannot be spoofed
// see Bug 884573 for details

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

@ -96,25 +96,6 @@ Java_org_mozilla_gecko_GeckoAppShell_nativeInit(JNIEnv * arg0, jclass arg1) {
#ifdef JNI_STUBS
typedef void (*Java_org_mozilla_gecko_GeckoAppShell_setLayerClient_t)(JNIEnv *, jclass, jobject);
static Java_org_mozilla_gecko_GeckoAppShell_setLayerClient_t f_Java_org_mozilla_gecko_GeckoAppShell_setLayerClient;
extern "C" NS_EXPORT void JNICALL
Java_org_mozilla_gecko_GeckoAppShell_setLayerClient(JNIEnv * arg0, jclass arg1, jobject arg2) {
if (!f_Java_org_mozilla_gecko_GeckoAppShell_setLayerClient) {
arg0->ThrowNew(arg0->FindClass("java/lang/UnsupportedOperationException"),
"JNI Function called before it was loaded");
return ;
}
f_Java_org_mozilla_gecko_GeckoAppShell_setLayerClient(arg0, arg1, arg2);
}
#endif
#ifdef JNI_BINDINGS
xul_dlsym("Java_org_mozilla_gecko_GeckoAppShell_setLayerClient", &f_Java_org_mozilla_gecko_GeckoAppShell_setLayerClient);
#endif
#ifdef JNI_STUBS
typedef void (*Java_org_mozilla_gecko_GeckoAppShell_onResume_t)(JNIEnv *, jclass);
static Java_org_mozilla_gecko_GeckoAppShell_onResume_t f_Java_org_mozilla_gecko_GeckoAppShell_onResume;
extern "C" NS_EXPORT void JNICALL

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

@ -615,6 +615,10 @@ class MochitestOptions(optparse.OptionParser):
"tab": 10000, # See dependencies of bug 1051230.
}
# Bug 1051230 - Leak logging does not yet work for tab processes on desktop.
# Bug 1065098 - The geckomediaplugin process fails to produce a leak log for some reason.
options.ignoreMissingLeaks = ["tab", "geckomediaplugin"]
return options
@ -819,6 +823,12 @@ class B2GOptions(MochitestOptions):
options.sslPort = tempSSL
options.httpPort = tempPort
# Bug 1071866 - B2G Mochitests do not always produce a leak log.
options.ignoreMissingLeaks.append("default")
# Bug 1070068 - Leak logging does not work for tab processes on B2G.
assert "tab" in options.ignoreMissingLeaks, "Ignore failures for tab processes on B2G"
return options
def elf_arm(self, filename):

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

@ -1842,7 +1842,7 @@ class Mochitest(MochitestUtilsMixin):
self.stopVMwareRecording();
self.stopServers()
processLeakLog(self.leak_report_file, options.leakThresholds)
processLeakLog(self.leak_report_file, options.leakThresholds, options.ignoreMissingLeaks)
if self.nsprLogs:
with zipfile.ZipFile("%s/nsprlog.zip" % browserEnv["MOZ_UPLOAD_DIR"], "w", zipfile.ZIP_DEFLATED) as logzip:

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

@ -202,7 +202,7 @@ class B2GMochitest(MochitestUtilsMixin):
self.app_ctx.dm.getFile(self.leak_report_file, local_leak_file.name)
self.app_ctx.dm.removeFile(self.leak_report_file)
processLeakLog(local_leak_file.name, options.leakThresholds)
processLeakLog(local_leak_file.name, options.leakThresholds, options.ignoreMissingLeaks)
except KeyboardInterrupt:
self.log.info("runtests.py | Received keyboard interrupt.\n");
status = -1

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

@ -231,8 +231,11 @@ class RemoteB2GVersion(B2GVersion):
self._info[desired_props[key]] = value
if self._info.get('device_id', '').lower() == 'flame':
self._info['device_firmware_version_base'] = dm._runCmd(
['shell', 'getprop', 't2m.sw.version']).output[0]
for prop in ['ro.boot.bootloader', 't2m.sw.version']:
value = dm.shellCheckOutput(['getprop', prop])
if value:
self._info['device_firmware_version_base'] = value
break
def get_version(binary=None, sources=None, dm_type=None, host=None,

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