This commit is contained in:
Ryan VanderMeulen 2013-12-11 13:32:11 -05:00
Родитель 06d4b0a2d3 0920b6c4c8
Коммит f88ec242eb
65 изменённых файлов: 1190 добавлений и 905 удалений

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

@ -3101,6 +3101,15 @@ HTMLInputElement::Focus(ErrorResult& aError)
NS_IMETHODIMP
HTMLInputElement::Select()
{
if (mType == NS_FORM_INPUT_NUMBER) {
nsNumberControlFrame* numberControlFrame =
do_QueryFrame(GetPrimaryFrame());
if (numberControlFrame) {
return numberControlFrame->HandleSelectCall();
}
return NS_OK;
}
if (!IsSingleLineTextControl(false)) {
return NS_OK;
}

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

@ -23,7 +23,7 @@ interface nsIMarkupDocumentViewer;
[ref] native nsIMarkupDocumentViewerTArray(nsTArray<nsCOMPtr<nsIMarkupDocumentViewer> >);
[scriptable, uuid(6acfadef-22ee-4924-be6c-776e8def6e1b)]
[scriptable, uuid(3528324f-f5d3-4724-bd8d-9233a7114112)]
interface nsIMarkupDocumentViewer : nsISupports
{
@ -64,51 +64,6 @@ interface nsIMarkupDocumentViewer : nsISupports
*/
void getContentSize(out long width, out long height);
/**
* Options for Bidi presentation.
*
* Use these attributes to access the individual Bidi options.
*/
/**
* bidiTextDirection: the default direction for the layout of bidirectional text.
* 1 - left to right
* 2 - right to left
*/
attribute octet bidiTextDirection;
/**
* bidiTextType: the ordering of bidirectional text. This may be either "logical"
* or "visual". Logical text will be reordered for presentation using the Unicode
* Bidi Algorithm. Visual text will be displayed without reordering.
* 1 - the default order for the charset
* 2 - logical order
* 3 - visual order
*/
attribute octet bidiTextType;
/**
* bidiNumeral: the type of numerals to display.
* 1 - depending on context, default is Arabic numerals
* 2 - depending on context, default is Hindi numerals
* 3 - Arabic numerals
* 4 - Hindi numerals
*/
attribute octet bidiNumeral;
/**
* bidiSupport: whether to use platform bidi support or Mozilla's bidi support
* 1 - Use Mozilla's bidi support
* 2 - Use the platform bidi support
* 3 - Disable bidi support
*/
attribute octet bidiSupport;
/**
* Use this attribute to access all the Bidi options in one operation
*/
attribute uint32_t bidiOptions;
/** The minimum font size */
attribute long minFontSize;

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

@ -132,6 +132,14 @@ static_assert(MAX_WORKERS_PER_DOMAIN >= 1,
#define PREF_JIT_HARDENING "jit_hardening"
#define PREF_GCZEAL "gcZeal"
#if !(defined(DEBUG) || defined(MOZ_ENABLE_JS_DUMP))
#define DUMP_CONTROLLED_BY_PREF 1
#define PREF_DOM_WINDOW_DUMP_ENABLED "browser.dom.window.dump.enabled"
#endif
#define PREF_PROMISE_ENABLED "dom.promise.enabled"
#define PREF_WORKERS_LATEST_JS_VERSION "dom.workers.latestJSVersion"
namespace {
const uint32_t kNoIndex = uint32_t(-1);
@ -175,13 +183,6 @@ const char* gStringChars[] = {
static_assert(NS_ARRAY_LENGTH(gStringChars) == ID_COUNT,
"gStringChars should have the right length.");
#if !(defined(DEBUG) || defined(MOZ_ENABLE_JS_DUMP))
#define DUMP_CONTROLLED_BY_PREF 1
#define PREF_DOM_WINDOW_DUMP_ENABLED "browser.dom.window.dump.enabled"
#endif
#define PREF_PROMISE_ENABLED "dom.promise.enabled"
class LiteralRebindingCString : public nsDependentCString
{
public:
@ -875,9 +876,9 @@ CreateJSContextForWorker(WorkerPrivate* aWorkerPrivate, JSRuntime* aRuntime)
js::SetCTypesActivityCallback(aRuntime, CTypesActivityCallback);
JS::ContextOptionsRef(workerCx) = aWorkerPrivate->IsChromeWorker()
? settings.chrome.options
: settings.content.options;
JS::ContextOptionsRef(workerCx) =
aWorkerPrivate->IsChromeWorker() ? settings.chrome.contextOptions
: settings.content.contextOptions;
JS_SetJitHardening(aRuntime, settings.jitHardening);
@ -1593,9 +1594,10 @@ RuntimeService::Init()
// Initialize JSSettings.
if (!sDefaultJSSettings.gcSettings[0].IsSet()) {
sDefaultJSSettings.chrome.options = kRequiredJSContextOptions;
sDefaultJSSettings.chrome.contextOptions = kRequiredJSContextOptions;
sDefaultJSSettings.chrome.maxScriptRuntime = -1;
sDefaultJSSettings.content.options = kRequiredJSContextOptions;
sDefaultJSSettings.chrome.compartmentOptions.setVersion(JSVERSION_LATEST);
sDefaultJSSettings.content.contextOptions = kRequiredJSContextOptions;
sDefaultJSSettings.content.maxScriptRuntime = MAX_SCRIPT_RUN_TIME_SEC;
#ifdef JS_GC_ZEAL
sDefaultJSSettings.gcZealFrequency = JS_DEFAULT_ZEAL_FREQ;
@ -1670,21 +1672,25 @@ RuntimeService::Init()
#endif
#if DUMP_CONTROLLED_BY_PREF
NS_FAILED(Preferences::RegisterCallbackAndCall(
WorkerPrefChanged,
PREF_DOM_WINDOW_DUMP_ENABLED,
reinterpret_cast<void *>(WORKERPREF_DUMP))) ||
WorkerPrefChanged,
PREF_DOM_WINDOW_DUMP_ENABLED,
reinterpret_cast<void *>(WORKERPREF_DUMP))) ||
#endif
NS_FAILED(Preferences::RegisterCallbackAndCall(
WorkerPrefChanged,
PREF_PROMISE_ENABLED,
reinterpret_cast<void *>(WORKERPREF_PROMISE))) ||
WorkerPrefChanged,
PREF_PROMISE_ENABLED,
reinterpret_cast<void *>(WORKERPREF_PROMISE))) ||
NS_FAILED(Preferences::RegisterCallback(LoadJSContextOptions,
PREF_JS_OPTIONS_PREFIX,
nullptr)) ||
NS_FAILED(Preferences::RegisterCallbackAndCall(
LoadJSContextOptions,
PREF_WORKERS_OPTIONS_PREFIX,
nullptr))) {
nullptr)) ||
NS_FAILED(Preferences::RegisterCallbackAndCall(
JSVersionChanged,
PREF_WORKERS_LATEST_JS_VERSION,
nullptr))) {
NS_WARNING("Failed to register pref callbacks!");
}
@ -1834,19 +1840,24 @@ RuntimeService::Cleanup()
NS_ASSERTION(!mWindowMap.Count(), "All windows should have been released!");
if (mObserved) {
if (NS_FAILED(Preferences::UnregisterCallback(LoadJSContextOptions,
if (NS_FAILED(Preferences::UnregisterCallback(JSVersionChanged,
PREF_WORKERS_LATEST_JS_VERSION,
nullptr)) ||
NS_FAILED(Preferences::UnregisterCallback(LoadJSContextOptions,
PREF_JS_OPTIONS_PREFIX,
nullptr)) ||
NS_FAILED(Preferences::UnregisterCallback(LoadJSContextOptions,
PREF_WORKERS_OPTIONS_PREFIX,
nullptr)) ||
NS_FAILED(Preferences::UnregisterCallback(WorkerPrefChanged,
PREF_PROMISE_ENABLED,
reinterpret_cast<void *>(WORKERPREF_PROMISE))) ||
NS_FAILED(Preferences::UnregisterCallback(
WorkerPrefChanged,
PREF_PROMISE_ENABLED,
reinterpret_cast<void *>(WORKERPREF_PROMISE))) ||
#if DUMP_CONTROLLED_BY_PREF
NS_FAILED(Preferences::UnregisterCallback(WorkerPrefChanged,
PREF_DOM_WINDOW_DUMP_ENABLED,
reinterpret_cast<void *>(WORKERPREF_DUMP))) ||
NS_FAILED(Preferences::UnregisterCallback(
WorkerPrefChanged,
PREF_DOM_WINDOW_DUMP_ENABLED,
reinterpret_cast<void *>(WORKERPREF_DUMP))) ||
#endif
#ifdef JS_GC_ZEAL
NS_FAILED(Preferences::UnregisterCallback(
@ -2224,8 +2235,8 @@ void
RuntimeService::UpdateAllWorkerJSContextOptions()
{
BROADCAST_ALL_WORKERS(UpdateJSContextOptions,
sDefaultJSSettings.content.options,
sDefaultJSSettings.chrome.options);
sDefaultJSSettings.content.contextOptions,
sDefaultJSSettings.chrome.contextOptions);
}
void
@ -2333,3 +2344,13 @@ RuntimeService::WorkerPrefChanged(const char* aPrefName, void* aClosure)
rts->UpdateAllWorkerPreference(key, sDefaultPreferences[key]);
}
}
void
RuntimeService::JSVersionChanged(const char* /* aPrefName */, void* /* aClosure */)
{
AssertIsOnMainThread();
bool useLatest = Preferences::GetBool(PREF_WORKERS_LATEST_JS_VERSION, false);
JS::CompartmentOptions& options = sDefaultJSSettings.content.compartmentOptions;
options.setVersion(useLatest ? JSVERSION_LATEST : JSVERSION_DEFAULT);
}

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

@ -194,8 +194,8 @@ public:
const JS::ContextOptions& aChromeOptions)
{
AssertIsOnMainThread();
sDefaultJSSettings.content.options = aContentOptions;
sDefaultJSSettings.chrome.options = aChromeOptions;
sDefaultJSSettings.content.contextOptions = aContentOptions;
sDefaultJSSettings.chrome.contextOptions = aChromeOptions;
}
void
@ -295,6 +295,9 @@ private:
static void
WorkerPrefChanged(const char* aPrefName, void* aClosure);
static void
JSVersionChanged(const char* aPrefName, void* aClosure);
};
END_WORKERS_NAMESPACE

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

@ -2816,16 +2816,17 @@ WorkerPrivateParent<Derived>::GetInnerWindowId()
template <class Derived>
void
WorkerPrivateParent<Derived>::UpdateJSContextOptions(JSContext* aCx,
const JS::ContextOptions& aContentOptions,
const JS::ContextOptions& aChromeOptions)
WorkerPrivateParent<Derived>::UpdateJSContextOptions(
JSContext* aCx,
const JS::ContextOptions& aContentOptions,
const JS::ContextOptions& aChromeOptions)
{
AssertIsOnParentThread();
{
MutexAutoLock lock(mMutex);
mJSSettings.content.options = aContentOptions;
mJSSettings.chrome.options = aChromeOptions;
mJSSettings.content.contextOptions = aContentOptions;
mJSSettings.chrome.contextOptions = aChromeOptions;
}
nsRefPtr<UpdateJSContextOptionsRunnable> runnable =
@ -5449,14 +5450,7 @@ WorkerPrivate::CreateGlobalScope(JSContext* aCx)
globalScope = new DedicatedWorkerGlobalScope(this);
}
JS::CompartmentOptions options;
if (IsChromeWorker()) {
options.setVersion(JSVERSION_LATEST);
}
JS::Rooted<JSObject*> global(aCx,
globalScope->WrapGlobalObject(aCx, options,
GetWorkerPrincipal()));
JS::Rooted<JSObject*> global(aCx, globalScope->WrapGlobalObject(aCx));
NS_ENSURE_TRUE(global, nullptr);
JSAutoCompartment ac(aCx, global);

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

@ -377,7 +377,6 @@ private:
ErrorResult& aRv);
public:
virtual JSObject*
WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope) MOZ_OVERRIDE;
@ -696,6 +695,14 @@ public:
aSettings = mJSSettings;
}
void
CopyJSCompartmentOptions(JS::CompartmentOptions& aOptions)
{
mozilla::MutexAutoLock lock(mMutex);
aOptions = IsChromeWorker() ? mJSSettings.chrome.compartmentOptions
: mJSSettings.content.compartmentOptions;
}
// The ability to be a chrome worker is orthogonal to the type of
// worker [Dedicated|Shared].
bool

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

@ -6,11 +6,6 @@
#include "WorkerScope.h"
#include "Location.h"
#include "Navigator.h"
#include "ScriptLoader.h"
#include "WorkerPrivate.h"
#include "jsapi.h"
#include "mozilla/dom/FunctionBinding.h"
#include "mozilla/dom/DedicatedWorkerGlobalScopeBinding.h"
@ -20,7 +15,12 @@
#include <android/log.h>
#endif
#include "RuntimeService.h" // For WorkersDumpEnabled().
#include "Location.h"
#include "Navigator.h"
#include "Principal.h"
#include "RuntimeService.h"
#include "ScriptLoader.h"
#include "WorkerPrivate.h"
#define UNWRAP_WORKER_OBJECT(Interface, obj, value) \
UnwrapObject<prototypes::id::Interface##_workers, \
@ -261,19 +261,20 @@ DedicatedWorkerGlobalScope::Visible(JSContext* aCx, JSObject* aObj)
}
JSObject*
DedicatedWorkerGlobalScope::WrapGlobalObject(JSContext* aCx,
JS::CompartmentOptions& aOptions,
JSPrincipals* aPrincipal)
DedicatedWorkerGlobalScope::WrapGlobalObject(JSContext* aCx)
{
mWorkerPrivate->AssertIsOnWorkerThread();
MOZ_ASSERT(!mWorkerPrivate->IsSharedWorker());
JS::CompartmentOptions options;
mWorkerPrivate->CopyJSCompartmentOptions(options);
// We're wrapping the global, so the scope is undefined.
JS::Rooted<JSObject*> scope(aCx);
return DedicatedWorkerGlobalScopeBinding_workers::Wrap(aCx, scope, this,
this, aOptions,
aPrincipal);
this, options,
GetWorkerPrincipal());
}
void
@ -301,18 +302,20 @@ SharedWorkerGlobalScope::Visible(JSContext* aCx, JSObject* aObj)
}
JSObject*
SharedWorkerGlobalScope::WrapGlobalObject(JSContext* aCx,
JS::CompartmentOptions& aOptions,
JSPrincipals* aPrincipal)
SharedWorkerGlobalScope::WrapGlobalObject(JSContext* aCx)
{
mWorkerPrivate->AssertIsOnWorkerThread();
MOZ_ASSERT(mWorkerPrivate->IsSharedWorker());
JS::CompartmentOptions options;
mWorkerPrivate->CopyJSCompartmentOptions(options);
// We're wrapping the global, so the scope is undefined.
JS::Rooted<JSObject*> scope(aCx);
return SharedWorkerGlobalScopeBinding_workers::Wrap(aCx, scope, this, this,
aOptions, aPrincipal);
options,
GetWorkerPrincipal());
}
bool

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

@ -40,8 +40,7 @@ public:
WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope) MOZ_OVERRIDE;
virtual JSObject*
WrapGlobalObject(JSContext* aCx, JS::CompartmentOptions& aOptions,
JSPrincipals* aPrincipal) = 0;
WrapGlobalObject(JSContext* aCx) = 0;
virtual JSObject*
GetGlobalJSObject(void) MOZ_OVERRIDE
@ -115,8 +114,7 @@ public:
Visible(JSContext* aCx, JSObject* aObj);
virtual JSObject*
WrapGlobalObject(JSContext* aCx, JS::CompartmentOptions& aOptions,
JSPrincipals* aPrincipal) MOZ_OVERRIDE;
WrapGlobalObject(JSContext* aCx) MOZ_OVERRIDE;
void
PostMessage(JSContext* aCx, JS::Handle<JS::Value> aMessage,
@ -139,8 +137,7 @@ public:
Visible(JSContext* aCx, JSObject* aObj);
virtual JSObject*
WrapGlobalObject(JSContext* aCx, JS::CompartmentOptions& aOptions,
JSPrincipals* aPrincipal) MOZ_OVERRIDE;
WrapGlobalObject(JSContext* aCx) MOZ_OVERRIDE;
void GetName(DOMString& aName) const {
aName.AsAString() = mName;

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

@ -95,11 +95,12 @@ struct JSSettings
// Settings that change based on chrome/content context.
struct JSContentChromeSettings
{
JS::ContextOptions options;
JS::ContextOptions contextOptions;
JS::CompartmentOptions compartmentOptions;
int32_t maxScriptRuntime;
JSContentChromeSettings()
: options(), maxScriptRuntime(0)
: contextOptions(), compartmentOptions(), maxScriptRuntime(0)
{ }
};

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

@ -0,0 +1,14 @@
onmessage = function(evt) {
if (evt.data != 0) {
var worker = new Worker('jsversion_worker.js');
worker.onmessage = function(evt) {
postMessage(evt.data);
}
worker.postMessage(evt.data - 1);
return;
}
let foo = 'bar';
postMessage(true);
}

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

@ -56,6 +56,7 @@ support-files =
xhr_implicit_cancel_worker.js
xhr_worker.js
url_exceptions_worker.js
jsversion_worker.js
[test_404.html]
[test_atob.html]
@ -113,3 +114,4 @@ support-files =
[test_xhr_system.html]
[test_xhr_system.js]
[test_url_exceptions.html]
[test_jsversion.html]

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

@ -0,0 +1,68 @@
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/
-->
<!DOCTYPE HTML>
<html>
<head>
<title>Test for JSVersion in workers - Bug 487070</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
<script class="testbody" language="javascript">
var gExpectedError = false;
onerror = function(evt) {
ok(gExpectedError, "Error expected!");
runTest();
}
function doMagic() {
var worker = new Worker('jsversion_worker.js');
worker.onmessage = function(evt) {
ok(evt.data, 'All the tests passed');
runTest();
}
worker.postMessage(1);
}
var tests = [
// No custom version
function() {
gExpectedError = true;
SpecialPowers.pushPrefEnv({"set":[['dom.workers.latestJSVersion', false]]},
function() { doMagic(true); });
},
// Enable latest JS Version
function() {
gExpectedError = false;
SpecialPowers.pushPrefEnv({"set":[['dom.workers.latestJSVersion', true]]},
function() { doMagic(false); });
}
];
function runTest() {
if (!tests.length) {
SimpleTest.finish();
return;
}
var test = tests.shift();
test();
}
SimpleTest.waitForExplicitFinish();
runTest();
</script>
</pre>
</body>
</html>

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

@ -250,13 +250,15 @@ TextureImageTextureSourceOGL::Update(gfx::DataSourceSurface* aSurface,
size,
gfx::ContentForFormat(aSurface->GetFormat()),
WrapMode(mGL, aFlags & TEXTURE_ALLOW_REPEAT),
FlagsToGLFlags(aFlags));
FlagsToGLFlags(aFlags),
SurfaceFormatToImageFormat(aSurface->GetFormat()));
} else {
mTexImage = CreateBasicTextureImage(mGL,
size,
gfx::ContentForFormat(aSurface->GetFormat()),
WrapMode(mGL, aFlags & TEXTURE_ALLOW_REPEAT),
FlagsToGLFlags(aFlags));
FlagsToGLFlags(aFlags),
SurfaceFormatToImageFormat(aSurface->GetFormat()));
}
}

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

@ -282,7 +282,7 @@ gfxDWriteFontFamily::LocalizedName(nsAString &aLocalizedName)
}
UINT32 idx = 0;
BOOL exists;
hr = names->FindLocaleName(localeName.BeginReading(),
hr = names->FindLocaleName(localeName.get(),
&idx,
&exists);
if (FAILED(hr)) {

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

@ -44,8 +44,9 @@ gfxDWriteShaper::ShapeText(gfxContext *aContext,
* in a single call, so we cannot exceed that limit.
*/
UINT32 length = aLength;
char16ptr_t text = aText;
TextAnalysis analysis(aText, length, nullptr, readingDirection);
TextAnalysis analysis(text, length, nullptr, readingDirection);
TextAnalysis::Run *runHead;
hr = analysis.GenerateResults(analyzer, &runHead);
@ -80,7 +81,7 @@ trymoreglyphs:
UINT32 actualGlyphs;
hr = analyzer->GetGlyphs(aText, length,
hr = analyzer->GetGlyphs(text, length,
font->GetFontFace(), FALSE,
readingDirection == DWRITE_READING_DIRECTION_RIGHT_TO_LEFT,
&runHead->mScript, nullptr, nullptr, nullptr, nullptr, 0,
@ -107,7 +108,7 @@ trymoreglyphs:
if (!static_cast<gfxDWriteFont*>(mFont)->mUseSubpixelPositions) {
hr = analyzer->GetGdiCompatibleGlyphPlacements(
aText,
text,
clusters.Elements(),
textProperties.Elements(),
length,
@ -129,7 +130,7 @@ trymoreglyphs:
advances.Elements(),
glyphOffsets.Elements());
} else {
hr = analyzer->GetGlyphPlacements(aText,
hr = analyzer->GetGlyphPlacements(text,
clusters.Elements(),
textProperties.Elements(),
length,

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

@ -90,7 +90,7 @@ gfxGDIFont::CopyWithAntialiasOption(AntialiasOption anAAOption)
static bool
UseUniscribe(gfxShapedText *aShapedText,
const PRUnichar *aText,
char16ptr_t aText,
uint32_t aLength)
{
uint32_t flags = aShapedText->Flags();

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

@ -323,7 +323,7 @@ GDIFontEntry::TestCharacterMap(uint32_t aCh)
HFONT hfont = font->GetHFONT();
HFONT oldFont = (HFONT)SelectObject(dc, hfont);
PRUnichar str[1] = { (PRUnichar)aCh };
wchar_t str[1] = { aCh };
WORD glyph[1];
bool hasGlyph = false;

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

@ -31,7 +31,7 @@ gfxGDIShaper::ShapeText(gfxContext *aContext,
}
WORD *glyphs = glyphArray.Elements();
DWORD ret = ::GetGlyphIndicesW(dc, aText, length,
DWORD ret = ::GetGlyphIndicesW(dc, char16ptr_t(aText), length,
glyphs, GGI_MARK_NONEXISTING_GLYPHS);
if (ret == GDI_ERROR) {
return false;

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

@ -67,7 +67,7 @@ public:
HRESULT rv;
HDC shapeDC = nullptr;
const PRUnichar *str = mAlternativeString ? mAlternativeString : mItemString;
char16ptr_t str = mAlternativeString ? mAlternativeString : mItemString;
mScriptItem->a.fLogicalOrder = true;
SCRIPT_ANALYSIS sa = mScriptItem->a;
@ -417,7 +417,7 @@ public:
}
private:
const PRUnichar *mString;
char16ptr_t mString;
gfxShapedText *mShapedText;
uint32_t mOffset;
uint32_t mLength;

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

@ -1118,7 +1118,7 @@ gfxWindowsPlatform::UseClearTypeAlways()
}
void
gfxWindowsPlatform::GetDLLVersion(const PRUnichar *aDLLPath, nsAString& aVersion)
gfxWindowsPlatform::GetDLLVersion(char16ptr_t aDLLPath, nsAString& aVersion)
{
DWORD versInfoSize, vers[4] = {0};
// version info not available case

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

@ -238,7 +238,7 @@ public:
bool UseClearTypeForDownloadableFonts();
bool UseClearTypeAlways();
static void GetDLLVersion(const PRUnichar *aDLLPath, nsAString& aVersion);
static void GetDLLVersion(char16ptr_t aDLLPath, nsAString& aVersion);
// returns ClearType tuning information for each display
static void GetCleartypeParams(nsTArray<ClearTypeParameterInfo>& aParams);

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

@ -10,6 +10,7 @@
#include "mozilla/Assertions.h"
#include "vm/ArgumentsObject.h"
#include "vm/ForkJoin.h"
#include "jsgcinlines.h"
@ -64,7 +65,11 @@ StoreBuffer::WholeCellEdges::mark(JSTracer *trc)
JS_ASSERT(tenured->isTenured());
JSGCTraceKind kind = GetGCThingTraceKind(tenured);
if (kind <= JSTRACE_OBJECT) {
MarkChildren(trc, static_cast<JSObject *>(tenured));
JSObject *object = static_cast<JSObject *>(tenured);
if (object->is<ArgumentsObject>())
ArgumentsObject::trace(trc, object);
else
MarkChildren(trc, object);
return;
}
#ifdef JS_ION

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

@ -2343,6 +2343,26 @@ BaselineCompiler::emitFormalArgAccess(uint32_t arg, bool get)
} else {
masm.patchableCallPreBarrier(argAddr, MIRType_Value);
storeValue(frame.peek(-1), argAddr, R0);
#ifdef JSGC_GENERATIONAL
// Fully sync the stack if post-barrier is needed.
frame.syncStack(0);
// Reload the arguments object
Register reg = R2.scratchReg();
masm.loadPtr(Address(BaselineFrameReg, BaselineFrame::reverseOffsetOfArgsObj()), reg);
Nursery &nursery = cx->runtime()->gcNursery;
Label skipBarrier;
Label isTenured;
masm.branchPtr(Assembler::Below, reg, ImmWord(nursery.start()), &isTenured);
masm.branchPtr(Assembler::Below, reg, ImmWord(nursery.heapEnd()), &skipBarrier);
masm.bind(&isTenured);
masm.call(&postBarrierSlot_);
masm.bind(&skipBarrier);
#endif
}
masm.bind(&done);

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

@ -9111,7 +9111,10 @@ IonBuilder::jsop_setarg(uint32_t arg)
// If an arguments object is in use, and it aliases formals, then all SETARGs
// must go through the arguments object.
if (info().argsObjAliasesFormals()) {
current->add(MSetArgumentsObjectArg::New(alloc(), current->argumentsObject(), GET_SLOTNO(pc), val));
if (NeedsPostBarrier(info(), val))
current->add(MPostWriteBarrier::New(alloc(), current->argumentsObject(), val));
current->add(MSetArgumentsObjectArg::New(alloc(), current->argumentsObject(),
GET_SLOTNO(pc), val));
return true;
}

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

@ -3752,6 +3752,10 @@ nsCSSFrameConstructor::ConstructFrameFromItemInternal(FrameConstructionItem& aIt
((bits & FCDATA_IS_LINE_PARTICIPANT) != 0),
"Incorrectly set FCDATA_IS_LINE_PARTICIPANT bits");
if (aItem.mIsAnonymousContentCreatorContent) {
primaryFrame->AddStateBits(NS_FRAME_ANONYMOUSCONTENTCREATOR_CONTENT);
}
// Even if mCreatingExtraFrames is set, we may need to SetPrimaryFrame for
// generated content that doesn't have one yet. Note that we have to examine
// the frame bit, because by this point mIsGeneratedContent has been cleared
@ -3808,6 +3812,7 @@ nsCSSFrameConstructor::CreateAnonymousFrames(nsFrameConstructorState& aState,
if (newFrame) {
NS_ASSERTION(content->GetPrimaryFrame(),
"Content must have a primary frame now");
newFrame->AddStateBits(NS_FRAME_ANONYMOUSCONTENTCREATOR_CONTENT);
aChildItems.AddChild(newFrame);
}
else {
@ -5357,6 +5362,8 @@ nsCSSFrameConstructor::AddFrameConstructionItemsInternal(nsFrameConstructorState
item->mIsText = isText;
item->mIsGeneratedContent = isGeneratedContent;
item->mIsAnonymousContentCreatorContent =
aFlags & ITEM_IS_ANONYMOUSCONTENTCREATOR_CONTENT;
if (isGeneratedContent) {
NS_ADDREF(item->mContent);
}
@ -8172,6 +8179,12 @@ nsCSSFrameConstructor::CreateContinuingFrame(nsPresContext* aPresContext,
newFrame->AddStateBits(NS_FRAME_GENERATED_CONTENT);
}
// A continuation of nsIAnonymousContentCreator content is also
// nsIAnonymousContentCreator created content
if (aFrame->GetStateBits() & NS_FRAME_ANONYMOUSCONTENTCREATOR_CONTENT) {
newFrame->AddStateBits(NS_FRAME_ANONYMOUSCONTENTCREATOR_CONTENT);
}
// A continuation of an out-of-flow is also an out-of-flow
if (aFrame->GetStateBits() & NS_FRAME_OUT_OF_FLOW) {
newFrame->AddStateBits(NS_FRAME_OUT_OF_FLOW);
@ -8631,6 +8644,27 @@ nsCSSFrameConstructor::RecreateFramesForContent(nsIContent* aContent,
return RecreateFramesForContent(nonGeneratedAncestor->GetContent(), aAsyncInsert);
}
if (frame->GetStateBits() & NS_FRAME_ANONYMOUSCONTENTCREATOR_CONTENT) {
// Recreate the frames for the entire nsIAnonymousContentCreator tree
// since |frame| or one of its descendants may need an nsStyleContext
// that associates it to a CSS pseudo-element, and only the
// nsIAnonymousContentCreator that created this content knows how to make
// that happen.
nsIAnonymousContentCreator* acc = nullptr;
nsIFrame* ancestor = frame->GetParent();
while (!(acc = do_QueryFrame(ancestor))) {
ancestor = ancestor->GetParent();
}
NS_ASSERTION(acc, "Where is the nsIAnonymousContentCreator? We may fail "
"to recreate its content correctly");
// nsSVGUseFrame is special, and we know this is unnecessary for it.
if (ancestor->GetType() != nsGkAtoms::svgUseFrame) {
NS_ASSERTION(aContent->IsInNativeAnonymousSubtree(),
"Why is NS_FRAME_ANONYMOUSCONTENTCREATOR_CONTENT set?");
return RecreateFramesForContent(ancestor->GetContent(), aAsyncInsert);
}
}
nsIFrame* parent = frame->GetParent();
nsIContent* parentContent = parent ? parent->GetContent() : nullptr;
// If the parent frame is a leaf then the subsequent insert will fail to
@ -9207,7 +9241,8 @@ nsCSSFrameConstructor::AddFCItemsForAnonymousContent(
anonChildren = &aAnonymousItems[i].mChildren;
}
uint32_t flags = ITEM_ALLOW_XBL_BASE | ITEM_ALLOW_PAGE_BREAK | aExtraFlags;
uint32_t flags = ITEM_ALLOW_XBL_BASE | ITEM_ALLOW_PAGE_BREAK |
ITEM_IS_ANONYMOUSCONTENTCREATOR_CONTENT | aExtraFlags;
AddFrameConstructionItemsInternal(aState, content, aFrame,
content->Tag(), content->GetNameSpaceID(),

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

@ -908,6 +908,7 @@ private:
mPendingBinding(aPendingBinding), mStyleContext(aStyleContext),
mSuppressWhiteSpaceOptimizations(aSuppressWhiteSpaceOptimizations),
mIsText(false), mIsGeneratedContent(false),
mIsAnonymousContentCreatorContent(false),
mIsRootPopupgroup(false), mIsAllInline(false), mIsBlock(false),
mHasInlineEnds(false), mIsPopup(false),
mIsLineParticipant(false), mIsForSVGAElement(false)
@ -975,6 +976,8 @@ private:
// Whether this is a generated content container.
// If it is, mContent is a strong pointer.
bool mIsGeneratedContent;
// Whether this is an item for nsIAnonymousContentCreator content.
bool mIsAnonymousContentCreatorContent;
// Whether this is an item for the root popupgroup.
bool mIsRootPopupgroup;
// Whether construction from this item will create only frames that are
@ -1164,6 +1167,8 @@ private:
#define ITEM_IS_WITHIN_SVG_TEXT 0x8
/* The item allows items to be created for SVG <textPath> children. */
#define ITEM_ALLOWS_TEXT_PATH_CHILD 0x10
/* The item is content created by an nsIAnonymousContentCreator frame */
#define ITEM_IS_ANONYMOUSCONTENTCREATOR_CONTENT 0x20
// The guts of AddFrameConstructionItems
// aParentFrame might be null. If it is, that means it was an
// inline frame.

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

@ -107,7 +107,6 @@ static const char sPrintOptionsContractID[] = "@mozilla.org/gfx/printset
#include "nsIDOMEventListener.h"
#include "nsISelectionController.h"
#include "nsBidiUtils.h"
#include "nsISHEntry.h"
#include "nsISHistory.h"
#include "nsISHistoryInternal.h"
@ -3108,118 +3107,6 @@ nsDocumentViewer::SetHintCharacterSet(const nsACString& aHintCharacterSet)
return NS_OK;
}
static void
SetChildBidiOptions(nsIMarkupDocumentViewer* aChild, void* aClosure)
{
aChild->SetBidiOptions(NS_PTR_TO_INT32(aClosure));
}
NS_IMETHODIMP nsDocumentViewer::SetBidiTextDirection(uint8_t aTextDirection)
{
uint32_t bidiOptions;
GetBidiOptions(&bidiOptions);
SET_BIDI_OPTION_DIRECTION(bidiOptions, aTextDirection);
SetBidiOptions(bidiOptions);
return NS_OK;
}
NS_IMETHODIMP nsDocumentViewer::GetBidiTextDirection(uint8_t* aTextDirection)
{
uint32_t bidiOptions;
if (aTextDirection) {
GetBidiOptions(&bidiOptions);
*aTextDirection = GET_BIDI_OPTION_DIRECTION(bidiOptions);
}
return NS_OK;
}
NS_IMETHODIMP nsDocumentViewer::SetBidiTextType(uint8_t aTextType)
{
uint32_t bidiOptions;
GetBidiOptions(&bidiOptions);
SET_BIDI_OPTION_TEXTTYPE(bidiOptions, aTextType);
SetBidiOptions(bidiOptions);
return NS_OK;
}
NS_IMETHODIMP nsDocumentViewer::GetBidiTextType(uint8_t* aTextType)
{
uint32_t bidiOptions;
if (aTextType) {
GetBidiOptions(&bidiOptions);
*aTextType = GET_BIDI_OPTION_TEXTTYPE(bidiOptions);
}
return NS_OK;
}
NS_IMETHODIMP nsDocumentViewer::SetBidiNumeral(uint8_t aNumeral)
{
uint32_t bidiOptions;
GetBidiOptions(&bidiOptions);
SET_BIDI_OPTION_NUMERAL(bidiOptions, aNumeral);
SetBidiOptions(bidiOptions);
return NS_OK;
}
NS_IMETHODIMP nsDocumentViewer::GetBidiNumeral(uint8_t* aNumeral)
{
uint32_t bidiOptions;
if (aNumeral) {
GetBidiOptions(&bidiOptions);
*aNumeral = GET_BIDI_OPTION_NUMERAL(bidiOptions);
}
return NS_OK;
}
NS_IMETHODIMP nsDocumentViewer::SetBidiSupport(uint8_t aSupport)
{
uint32_t bidiOptions;
GetBidiOptions(&bidiOptions);
SET_BIDI_OPTION_SUPPORT(bidiOptions, aSupport);
SetBidiOptions(bidiOptions);
return NS_OK;
}
NS_IMETHODIMP nsDocumentViewer::GetBidiSupport(uint8_t* aSupport)
{
uint32_t bidiOptions;
if (aSupport) {
GetBidiOptions(&bidiOptions);
*aSupport = GET_BIDI_OPTION_SUPPORT(bidiOptions);
}
return NS_OK;
}
NS_IMETHODIMP nsDocumentViewer::SetBidiOptions(uint32_t aBidiOptions)
{
if (mPresContext) {
mPresContext->SetBidi(aBidiOptions, true); // could cause reflow
}
// now set bidi on all children of mContainer
CallChildren(SetChildBidiOptions, NS_INT32_TO_PTR(aBidiOptions));
return NS_OK;
}
NS_IMETHODIMP nsDocumentViewer::GetBidiOptions(uint32_t* aBidiOptions)
{
if (aBidiOptions) {
if (mPresContext) {
*aBidiOptions = mPresContext->GetBidi();
}
else
*aBidiOptions = IBMBIDI_DEFAULT_BIDI_OPTIONS;
}
return NS_OK;
}
static void
AppendChildSubtree(nsIMarkupDocumentViewer* aChild, void* aClosure)
{

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

@ -488,6 +488,12 @@ nsNumberControlFrame::HandleFocusEvent(WidgetEvent* aEvent)
}
}
nsresult
nsNumberControlFrame::HandleSelectCall()
{
return HTMLInputElement::FromContent(mTextField)->Select();
}
#define STYLES_DISABLING_NATIVE_THEMING \
NS_AUTHOR_SPECIFIED_BACKGROUND | \
NS_AUTHOR_SPECIFIED_PADDING | \

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

@ -129,6 +129,11 @@ public:
void HandleFocusEvent(WidgetEvent* aEvent);
/**
* Our element had HTMLInputElement::Select() called on it.
*/
nsresult HandleSelectCall();
virtual Element* GetPseudoElement(nsCSSPseudoElements::Type aType) MOZ_OVERRIDE;
bool ShouldUseNativeStyleForSpinner() const;

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

@ -5306,6 +5306,9 @@ nsIFrame::ListGeneric(FILE* out, int32_t aIndent, uint32_t aFlags) const
pseudoTag->ToString(atomString);
fprintf(out, "%s", NS_LossyConvertUTF16toASCII(atomString).get());
}
if (mParent && mStyleContext->GetParent() != mParent->StyleContext()) {
fprintf(out, ",parent=%p", mStyleContext->GetParent());
}
}
fputs("]", out);
}

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

@ -143,6 +143,9 @@ typedef uint64_t nsFrameState;
// continuation, e.g. a bidi continuation.
#define NS_FRAME_IS_FLUID_CONTINUATION NS_FRAME_STATE_BIT(2)
// For nsIAnonymousContentCreator content that's created using ContentInfo.
#define NS_FRAME_ANONYMOUSCONTENTCREATOR_CONTENT NS_FRAME_STATE_BIT(3)
// If this bit is set, then a reference to the frame is being held
// elsewhere. The frame may want to send a notification when it is
// destroyed to allow these references to be cleared.

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

@ -0,0 +1,17 @@
<!DOCTYPE html>
<html>
<head>
<style>
input {
font-size: 30pt;
background-color: lightblue;
}
</style>
</head>
<body>
<input type="number">
</body>
</html>

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

@ -0,0 +1,44 @@
<!DOCTYPE html>
<html class="reftest-wait">
<head>
<style>
input {
font-size: 30pt;
background-color: lightblue;
}
</style>
<script>
document.addEventListener("DOMContentLoaded", function() {
document.body.style.backgroundImage = "none";
}, false);
function PostRebuildAllStyleDataEvent() {
// trigger http://mxr.mozilla.org/mozilla-central/source/layout/base/RestyleManager.cpp?rev=a8b06549f680#1490
var m = document.createElementNS("http://www.w3.org/1998/Math/MathML", "math");
document.head.appendChild(m);
document.head.removeChild(m);
}
function reframe() {
PostRebuildAllStyleDataEvent();
document.documentElement.className = "";
}
document.addEventListener("MozReftestInvalidate", function() {
// Calling reframe now would be too early to reproduce the bug that we're
// testing for. Note that in the event that we start faling this test this
// timeout may make the failure seem intermittent when in fact we would
// always fail if it was longer.
setTimeout(reframe, 500);
}, false);
</script>
</head>
<body>
<input type="number">
</body>
</html>

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

@ -0,0 +1,18 @@
<!DOCTYPE html>
<html class="reftest-wait">
<head>
<script>
document.addEventListener("MozReftestInvalidate", function() {
document.getElementById("i").select();
document.documentElement.className = "";
}, false);
</script>
</head>
<body>
<input id="i" type="text" value="123">
<!-- div to cover spin box area -->
<div style="display:block; position:absolute; background-color:black; width:200px; height:100px; top:0px; left:100px;">
</body>
</html>

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

@ -0,0 +1,18 @@
<!DOCTYPE html>
<html class="reftest-wait">
<head>
<script>
document.addEventListener("MozReftestInvalidate", function() {
document.getElementById("i").select();
document.documentElement.className = "";
}, false);
</script>
</head>
<body>
<input id="i" type="number" value="123">
<!-- div to cover spin box area -->
<div style="display:block; position:absolute; background-color:black; width:200px; height:100px; top:0px; left:100px;">
</body>
</html>

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

@ -23,6 +23,14 @@ fuzzy-if(/^Windows\x20NT\x205\.1/.test(http.oscpu),64,4) fuzzy-if(cocoaWidget,63
# focus
needs-focus == focus-handling.html focus-handling-ref.html
# select
== number-selected.html number-selected-ref.html
# pseudo-elements not usable from content:
== number-pseudo-elements.html number-pseudo-elements-ref.html
# check that if the anonymous text control is reframed, we reframe the whole
# number control (the fuzzy is for the top-right and bottom-left of the border
# bevel which gets slightly different antialiasing after invalidation):
fuzzy(128,4) == number-reframe-anon-text-field.html number-reframe-anon-text-field-ref.html

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

@ -0,0 +1,48 @@
<!DOCTYPE html>
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/
-->
<html>
<head>
<title>CSS Reftest Reference</title>
<link rel="author" title="Daniel Holbert" href="mailto:dholbert@mozilla.com">
<style>
.flexContainer {
background: purple;
display: flex;
flex-wrap: wrap;
width: 70px;
height: 70px;
float: left;
margin-right: 5px;
}
.bigItem {
background: blue;
width: 50px;
height: 200px;
}
.smallItem {
background: teal;
width: 50px;
height: 20px;
}
.hidden > .bigItem {
/* To match the testcase's "overflow:hidden"-cropped flex item, we
just use a smaller height that exactly fits the space remaining
in our container, after wrapping */
height: 50px;
}
</style>
</head>
<body>
<div class="flexContainer"><!-- (overflow un-set) -->
<div class="smallItem"></div>
<div class="bigItem"></div>
</div>
<div class="flexContainer hidden">
<div class="smallItem"></div>
<div class="bigItem"></div>
</div>
</body>
</html>

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

@ -0,0 +1,49 @@
<!DOCTYPE html>
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/
-->
<!-- This testcase checks that we honor "flex-wrap" on a horizontal
flex container that has "overflow:hidden". We use a large flex item,
large enough that it overflows the container in the cross axis, to be
sure that "overflow: hidden" is actually applying. -->
<html>
<head>
<title>CSS Test: Testing 'overflow' property on a horizontal flex container, with 'flex-wrap: wrap'</title>
<link rel="author" title="Daniel Holbert" href="mailto:dholbert@mozilla.com">
<link rel="help" href="http://www.w3.org/TR/css3-flexbox/#flex-wrap-property">
<link rel="match" href="flexbox-overflow-horiz-4-ref.html">
<style>
.flexContainer {
background: purple;
display: flex;
flex-wrap: wrap;
width: 70px;
height: 70px;
float: left;
margin-right: 5px;
}
.bigItem {
background: blue;
width: 50px;
height: 200px;
}
.smallItem {
background: teal;
width: 50px;
height: 20px;
}
.hidden { overflow: hidden }
</style>
</head>
<body>
<div class="flexContainer"><!-- (overflow un-set) -->
<div class="smallItem"></div>
<div class="bigItem"></div>
</div>
<div class="flexContainer hidden">
<div class="smallItem"></div>
<div class="bigItem"></div>
</div>
</body>
</html>

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

@ -0,0 +1,50 @@
<!DOCTYPE html>
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/
-->
<html>
<head>
<title>CSS Reftest Reference</title>
<link rel="author" title="Daniel Holbert" href="mailto:dholbert@mozilla.com">
<style>
.flexContainer {
background: purple;
display: flex;
flex-wrap: wrap;
align-content: space-around;
width: 70px;
height: 70px;
float: left;
margin-right: 5px;
}
.bigItem {
background: blue;
flex: none; /* prevent shrinking (so we can intentionally overflow) */
width: 72px;
height: 20px;
}
.smallItem {
background: teal;
width: 20px;
height: 20px;
}
.hidden > .bigItem {
/* To match the testcase's "overflow:hidden"-cropped flex item, we
just use a smaller width that exactly fits our container (and
doesn't overflow). */
width: 70px;
}
</style>
</head>
<body>
<div class="flexContainer"><!-- (overflow un-set) -->
<div class="bigItem"></div>
<div class="smallItem"></div>
</div>
<div class="flexContainer hidden">
<div class="bigItem"></div>
<div class="smallItem"></div>
</div>
</body>
</html>

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

@ -0,0 +1,51 @@
<!DOCTYPE html>
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/
-->
<!-- This testcase checks that we honor "align-content" on a horizontal
flex container that has "overflow:hidden". We use a large flex item,
large enough that it overflows the container in the main axis, to be
sure that "overflow: hidden" is actually applying. -->
<html>
<head>
<title>CSS Test: Testing 'overflow' property on a horizontal flex container, with 'align-content: space-around'</title>
<link rel="author" title="Daniel Holbert" href="mailto:dholbert@mozilla.com">
<link rel="help" href="http://www.w3.org/TR/css3-flexbox/#align-content-property">
<link rel="match" href="flexbox-overflow-horiz-5-ref.html">
<style>
.flexContainer {
background: purple;
display: flex;
flex-wrap: wrap;
align-content: space-around;
width: 70px;
height: 70px;
float: left;
margin-right: 5px;
}
.bigItem {
background: blue;
flex: none; /* prevent shrinking (so we can intentionally overflow) */
width: 72px;
height: 20px;
}
.smallItem {
background: teal;
width: 20px;
height: 20px;
}
.hidden { overflow: hidden }
</style>
</head>
<body>
<div class="flexContainer"><!-- (overflow un-set) -->
<div class="bigItem"></div>
<div class="smallItem"></div>
</div>
<div class="flexContainer hidden">
<div class="bigItem"></div>
<div class="smallItem"></div>
</div>
</body>
</html>

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

@ -0,0 +1,48 @@
<!DOCTYPE html>
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/
-->
<html>
<head>
<title>CSS Reftest Reference</title>
<link rel="author" title="Daniel Holbert" href="mailto:dholbert@mozilla.com">
<style>
.flexContainer {
background: purple;
display: flex;
flex-direction: column;
flex-wrap: wrap;
width: 70px;
height: 70px;
margin-bottom: 5px;
}
.bigItem {
background: blue;
width: 200px;
height: 50px;
}
.smallItem {
background: teal;
width: 20px;
height: 50px;
}
.hidden > .bigItem {
/* To match the testcase's "overflow:hidden"-cropped flex item, we
just use a smaller width that exactly fits the space remaining
in our container, after wrapping */
width: 50px;
}
</style>
</head>
<body>
<div class="flexContainer"><!-- (overflow un-set) -->
<div class="smallItem"></div>
<div class="bigItem"></div>
</div>
<div class="flexContainer hidden">
<div class="smallItem"></div>
<div class="bigItem"></div>
</div>
</body>
</html>

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

@ -0,0 +1,49 @@
<!DOCTYPE html>
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/
-->
<!-- This testcase checks that we honor "flex-wrap" on a vertical
flex container that has "overflow:hidden". We use a large flex item,
large enough that it overflows the container in the cross axis, to be
sure that "overflow: hidden" is actually applying. -->
<html>
<head>
<title>CSS Test: Testing 'overflow' property on a vertical flex container, with 'flex-wrap: wrap'</title>
<link rel="author" title="Daniel Holbert" href="mailto:dholbert@mozilla.com">
<link rel="help" href="http://www.w3.org/TR/css3-flexbox/#flex-wrap-property">
<link rel="match" href="flexbox-overflow-vert-4-ref.html">
<style>
.flexContainer {
background: purple;
display: flex;
flex-direction: column;
flex-wrap: wrap;
width: 70px;
height: 70px;
margin-bottom: 5px;
}
.bigItem {
background: blue;
width: 200px;
height: 50px;
}
.smallItem {
background: teal;
width: 20px;
height: 50px;
}
.hidden { overflow: hidden }
</style>
</head>
<body>
<div class="flexContainer"><!-- (overflow un-set) -->
<div class="smallItem"></div>
<div class="bigItem"></div>
</div>
<div class="flexContainer hidden">
<div class="smallItem"></div>
<div class="bigItem"></div>
</div>
</body>
</html>

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

@ -0,0 +1,50 @@
<!DOCTYPE html>
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/
-->
<html>
<head>
<title>CSS Reftest Reference</title>
<link rel="author" title="Daniel Holbert" href="mailto:dholbert@mozilla.com">
<style>
.flexContainer {
background: purple;
display: flex;
flex-direction: column;
flex-wrap: wrap;
align-content: space-around;
width: 70px;
height: 70px;
margin-bottom: 5px;
}
.bigItem {
background: blue;
flex: none; /* prevent shrinking (so we can intentionally overflow) */
width: 20px;
height: 72px;
}
.smallItem {
background: teal;
width: 20px;
height: 20px;
}
.hidden > .bigItem {
/* To match the testcase's "overflow:hidden"-cropped flex item, we
just use a smaller height that exactly fits our container (and
doesn't overflow). */
height: 70px;
}
</style>
</head>
<body>
<div class="flexContainer"><!-- (overflow un-set) -->
<div class="bigItem"></div>
<div class="smallItem"></div>
</div>
<div class="flexContainer hidden">
<div class="bigItem"></div>
<div class="smallItem"></div>
</div>
</body>
</html>

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

@ -0,0 +1,51 @@
<!DOCTYPE html>
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/
-->
<!-- This testcase checks that we honor "align-content" on a vertical
flex container that has "overflow:hidden". We use a large flex item,
large enough that it overflows the container in the main axis, to be
sure that "overflow: hidden" is actually applying. -->
<html>
<head>
<title>CSS Test: Testing 'overflow' property on a vertical flex container, with 'align-content: space-around'</title>
<link rel="author" title="Daniel Holbert" href="mailto:dholbert@mozilla.com">
<link rel="help" href="http://www.w3.org/TR/css3-flexbox/#align-content-property">
<link rel="match" href="flexbox-overflow-vert-5-ref.html">
<style>
.flexContainer {
background: purple;
display: flex;
flex-direction: column;
flex-wrap: wrap;
align-content: space-around;
width: 70px;
height: 70px;
margin-bottom: 5px;
}
.bigItem {
background: blue;
flex: none; /* prevent shrinking (so we can intentionally overflow) */
width: 20px;
height: 72px;
}
.smallItem {
background: teal;
width: 20px;
height: 20px;
}
.hidden { overflow: hidden }
</style>
</head>
<body>
<div class="flexContainer"><!-- (overflow un-set) -->
<div class="bigItem"></div>
<div class="smallItem"></div>
</div>
<div class="flexContainer hidden">
<div class="bigItem"></div>
<div class="smallItem"></div>
</div>
</body>
</html>

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

@ -106,9 +106,13 @@ fuzzy-if(Android,158,32) == flexbox-align-self-vert-rtl-1.xhtml flexbox-align-s
== flexbox-overflow-horiz-1.html flexbox-overflow-horiz-1-ref.html
== flexbox-overflow-horiz-2.html flexbox-overflow-horiz-2-ref.html
== flexbox-overflow-horiz-3.html flexbox-overflow-horiz-3-ref.html
== flexbox-overflow-horiz-4.html flexbox-overflow-horiz-4-ref.html
== flexbox-overflow-horiz-5.html flexbox-overflow-horiz-5-ref.html
== flexbox-overflow-vert-1.html flexbox-overflow-vert-1-ref.html
== flexbox-overflow-vert-2.html flexbox-overflow-vert-2-ref.html
== flexbox-overflow-vert-3.html flexbox-overflow-vert-3-ref.html
== flexbox-overflow-vert-4.html flexbox-overflow-vert-4-ref.html
== flexbox-overflow-vert-5.html flexbox-overflow-vert-5-ref.html
# Tests for the order in which we paint flex items
== flexbox-paint-ordering-1.xhtml flexbox-paint-ordering-1-ref.xhtml

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

@ -142,10 +142,10 @@
-moz-column-gap: inherit;
-moz-column-rule: inherit;
/* CSS3 flexbox properties that apply to the flex container: */
/* align-content: inherit; FIXME: not yet supported (bug 702508) */
align-content: inherit;
align-items: inherit;
flex-direction: inherit;
/* flex-wrap: inherit; FIXME: not yet supported (bug 702508) */
flex-wrap: inherit;
justify-content: inherit;
/* Do not change these. nsCSSFrameConstructor depends on them to create a good
frame tree. */

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

@ -52,13 +52,6 @@ public class StringHelper {
"Add to Home Screen"
};
public static final String[] CONTEXT_MENU_ITEMS_IN_URL_BAR = new String[] {
"Share",
"Copy Address",
"Edit Site Settings",
"Add to Home Screen"
};
public static final String TITLE_PLACE_HOLDER = "Enter Search or Address";
// Robocop page urls

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

@ -1,17 +1,8 @@
package org.mozilla.gecko.tests;
import android.view.View;
import org.mozilla.gecko.*;
import java.util.ArrayList;
/**
* This patch tests the clear private data options:
* - clear history option by: adding and checking that clear private
* data option removes the history items but not the users bookmarks
* - clear site settings and clear saved password by: checking
* each option present in the doorhanger and clearing the settings from
* the URL bar context menu and settings menu
*/
public class testClearPrivateData extends PixelTest {
private final int TEST_WAIT_MS = 10000;
@ -23,25 +14,21 @@ public class testClearPrivateData extends PixelTest {
public void testClearPrivateData() {
blockForGeckoReady();
clearHistory();
clearSiteSettings();
clearPassword();
}
private void clearHistory() {
// Loading a page and adding a second one as bookmark to have user made bookmarks and history
String blank1 = getAbsoluteUrl(StringHelper.ROBOCOP_BLANK_PAGE_01_URL);
String blank2 = getAbsoluteUrl(StringHelper.ROBOCOP_BLANK_PAGE_02_URL);
String title = StringHelper.ROBOCOP_BLANK_PAGE_01_TITLE;
inputAndLoadUrl(blank1);
verifyPageTitle(title);
loadAndPaint(blank1);
waitForText(StringHelper.ROBOCOP_BLANK_PAGE_01_TITLE);
mDatabaseHelper.addOrUpdateMobileBookmark(StringHelper.ROBOCOP_BLANK_PAGE_02_TITLE, blank2);
// Checking that the history list is not empty
verifyHistoryCount(1);
//clear and check for device
checkDevice(title);
clearPrivateData();
// Checking that history list is empty
verifyHistoryCount(0);
@ -58,60 +45,4 @@ public class testClearPrivateData extends PixelTest {
}, TEST_WAIT_MS);
mAsserter.ok(match, "Checking that the number of history items is correct", String.valueOf(expectedCount) + " history items present in the database");
}
public void clearSiteSettings() {
String shareStrings[] = {"Share your location with", "Share", "Don't share", "There are no settings to clear"};
String titleGeolocation = StringHelper.ROBOCOP_GEOLOCATION_TITLE;
String url = getAbsoluteUrl(StringHelper.ROBOCOP_GEOLOCATION_URL);
loadCheckDismiss(shareStrings[1], url, shareStrings[0]);
checkOption(shareStrings[1], "Clear");
checkOption(shareStrings[3], "Cancel");
loadCheckDismiss(shareStrings[2], url, shareStrings[0]);
checkOption(shareStrings[2], "Cancel");
checkDevice(titleGeolocation);
}
public void clearPassword(){
String passwordStrings[] = {"Save password", "Save", "Don't save"};
String title = StringHelper.ROBOCOP_BLANK_PAGE_01_TITLE;
String loginUrl = getAbsoluteUrl(StringHelper.ROBOCOP_LOGIN_URL);
loadCheckDismiss(passwordStrings[1], loginUrl, passwordStrings[0]);
checkOption(passwordStrings[1], "Clear");
loadCheckDismiss(passwordStrings[2], loginUrl, passwordStrings[0]);
checkDevice(title);
}
// clear private data and verify the device type because for phone there is an extra back action to exit the settings menu
public void checkDevice(String title) {
clearPrivateData();
if (mDevice.type.equals("phone")) {
mActions.sendSpecialKey(Actions.SpecialKey.BACK);
mAsserter.ok(waitForText(StringHelper.PRIVACY_SECTION_LABEL), "waiting to perform one back", "one back");
mActions.sendSpecialKey(Actions.SpecialKey.BACK);
verifyPageTitle(title);
}
else {
mActions.sendSpecialKey(Actions.SpecialKey.BACK);
verifyPageTitle(title);
}
}
// Load a URL, verify that the doorhanger appears and dismiss it
public void loadCheckDismiss(String option, String url, String message) {
inputAndLoadUrl(url);
waitForText(message);
mAsserter.is(mSolo.searchText(message), true, "Doorhanger:" + message + " has been displayed");
mSolo.clickOnButton(option);
mAsserter.is(mSolo.searchText(message), false, "Doorhanger:" + message + " has been hidden");
}
//Verify if there are settings to be clear if so clear them from the URL bar context menu
public void checkOption(String option, String button) {
final View toolbarView = mSolo.getView("browser_toolbar");
mSolo.clickLongOnView(toolbarView);
mAsserter.ok(waitForText(StringHelper.CONTEXT_MENU_ITEMS_IN_URL_BAR[2]), "Waiting for the pop-up to open", "Pop up was openend");
mSolo.clickOnText(StringHelper.CONTEXT_MENU_ITEMS_IN_URL_BAR[2]);
mAsserter.ok(waitForText(option), "Verify that the option: " + option + " is in the list", "The option is in the list. There are settings to clear");
mSolo.clickOnButton(button);
}
}

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

@ -17,6 +17,8 @@ from contextlib import contextmanager
from mach.mixin.logging import LoggingMixin
import mozpack.path as mozpath
from ..preprocessor import Preprocessor
from ..pythonutil import iter_modules_in_path
from ..util import FileAvoidWrite
from ..frontend.data import (
@ -24,6 +26,7 @@ from ..frontend.data import (
SandboxDerived,
)
from .configenvironment import ConfigEnvironment
import mozpack.path as mozpath
class BackendConsumeSummary(object):
@ -128,12 +131,12 @@ class BuildBackend(LoggingMixin):
self._backend_output_files = set()
# Previously generated files.
self._backend_output_list_file = os.path.join(environment.topobjdir,
self._backend_output_list_file = mozpath.join(environment.topobjdir,
'backend.%s' % self.__class__.__name__)
self._backend_output_list = set()
if os.path.exists(self._backend_output_list_file):
self._backend_output_list.update(open(self._backend_output_list_file) \
.read().split('\n'))
l = open(self._backend_output_list_file).read().split('\n')
self._backend_output_list.update(mozpath.normsep(p) for p in l)
# Pull in all loaded Python as dependencies so any Python changes that
# could influence our output result in a rescan.
@ -162,7 +165,7 @@ class BuildBackend(LoggingMixin):
"""
environment = self._environments.get(obj.topobjdir, None)
if not environment:
config_status = os.path.join(obj.topobjdir, 'config.status')
config_status = mozpath.join(obj.topobjdir, 'config.status')
environment = ConfigEnvironment.from_config_status(config_status)
self._environments[obj.topobjdir] = environment
@ -204,12 +207,12 @@ class BuildBackend(LoggingMixin):
delete_files = self._backend_output_list - self._backend_output_files
for path in delete_files:
try:
os.unlink(os.path.join(self.environment.topobjdir, path))
os.unlink(mozpath.join(self.environment.topobjdir, path))
self.summary.deleted_count += 1
except OSError:
pass
# Remove now empty directories
for dir in set(os.path.dirname(d) for d in delete_files):
for dir in set(mozpath.dirname(d) for d in delete_files):
try:
os.removedirs(dir)
except OSError:
@ -263,7 +266,7 @@ class BuildBackend(LoggingMixin):
else:
assert fh is not None
dirname = os.path.dirname(fh.name)
dirname = mozpath.dirname(fh.name)
try:
os.makedirs(dirname)
except OSError as error:
@ -272,7 +275,7 @@ class BuildBackend(LoggingMixin):
yield fh
self._backend_output_files.add(os.path.relpath(fh.name, self.environment.topobjdir))
self._backend_output_files.add(mozpath.relpath(fh.name, self.environment.topobjdir))
existed, updated = fh.close()
if not existed:
self.summary.created_count += 1
@ -280,3 +283,23 @@ class BuildBackend(LoggingMixin):
self.summary.updated_count += 1
else:
self.summary.unchanged_count += 1
@contextmanager
def _get_preprocessor(self, obj):
'''Returns a preprocessor with a few predefined values depending on
the given BaseConfigSubstitution(-like) object, and all the substs
in the current environment.'''
pp = Preprocessor()
srcdir = mozpath.dirname(obj.input_path)
pp.context.update(self.environment.substs)
pp.context.update(
top_srcdir=self.environment.topsrcdir,
srcdir=srcdir,
relativesrcdir=mozpath.relpath(srcdir, self.environment.topsrcdir) or '.',
DEPTH=mozpath.relpath(self.environment.topobjdir, mozpath.dirname(obj.output_path)) or '.',
)
pp.do_filter('attemptSubstitution')
pp.setMarker(None)
with self._write_file(obj.output_path) as fh:
pp.out = fh
yield pp

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

@ -6,12 +6,17 @@ from __future__ import unicode_literals
import json
import os
import re
import mozpack.path as mozpath
from mozbuild.preprocessor import Preprocessor
from .base import BuildBackend
from ..frontend.data import (
ConfigFileSubstitution,
HeaderFileSubstitution,
TestManifest,
XPIDLFile,
)
@ -92,14 +97,69 @@ class CommonBackend(BuildBackend):
self._test_manager.add(test, flavor=obj.flavor,
topsrcdir=obj.topsrcdir)
if isinstance(obj, XPIDLFile):
elif isinstance(obj, XPIDLFile):
self._idl_manager.register_idl(obj.source_path, obj.module)
elif isinstance(obj, ConfigFileSubstitution):
# Do not handle ConfigFileSubstitution for Makefiles. Leave that
# to other
if mozpath.basename(obj.output_path) == 'Makefile':
return
with self._get_preprocessor(obj) as pp:
pp.do_include(obj.input_path)
self.backend_input_files.add(obj.input_path)
elif isinstance(obj, HeaderFileSubstitution):
self._create_config_header(obj)
self.backend_input_files.add(obj.input_path)
else:
return
obj.ack()
def consume_finished(self):
if len(self._idl_manager.idls):
self._handle_idl_manager(self._idl_manager)
# Write out a machine-readable file describing every test.
path = os.path.join(self.environment.topobjdir, 'all-tests.json')
path = mozpath.join(self.environment.topobjdir, 'all-tests.json')
with self._write_file(path) as fh:
json.dump(self._test_manager.tests_by_path, fh, sort_keys=True)
def _create_config_header(self, obj):
'''Creates the given config header. A config header is generated by
taking the corresponding source file and replacing some #define/#undef
occurences:
"#undef NAME" is turned into "#define NAME VALUE"
"#define NAME" is unchanged
"#define NAME ORIGINAL_VALUE" is turned into "#define NAME VALUE"
"#undef UNKNOWN_NAME" is turned into "/* #undef UNKNOWN_NAME */"
Whitespaces are preserved.
'''
with self._write_file(obj.output_path) as fh, \
open(obj.input_path, 'rU') as input:
r = re.compile('^\s*#\s*(?P<cmd>[a-z]+)(?:\s+(?P<name>\S+)(?:\s+(?P<value>\S+))?)?', re.U)
for l in input:
m = r.match(l)
if m:
cmd = m.group('cmd')
name = m.group('name')
value = m.group('value')
if name:
if name in self.environment.defines:
if cmd == 'define' and value:
l = l[:m.start('value')] \
+ str(self.environment.defines[name]) \
+ l[m.end('value'):]
elif cmd == 'undef':
l = l[:m.start('cmd')] \
+ 'define' \
+ l[m.end('cmd'):m.end('name')] \
+ ' ' \
+ str(self.environment.defines[name]) \
+ l[m.end('name'):]
elif cmd == 'undef':
l = '/* ' + l[:m.end('name')] + ' */' + l[m.end('name'):]
fh.write(l)

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

@ -2,21 +2,14 @@
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
import ntpath
import os
import posixpath
import re
import sys
from collections import Iterable
from os.path import relpath
from types import StringTypes
from mozbuild.preprocessor import Preprocessor
import mozpack.path as mozpath
from ..util import (
ensureParentDir,
FileAvoidWrite,
ReadOnlyDict,
shell_quote,
)
@ -110,8 +103,8 @@ class ConfigEnvironment(object):
self.defines = ReadOnlyDict(defines)
self.substs = dict(substs)
self.topsrcdir = topsrcdir
self.topobjdir = topobjdir
self.topsrcdir = mozpath.normsep(topsrcdir)
self.topobjdir = mozpath.normsep(topobjdir)
global_defines = [name for name, value in defines
if not name in non_global_defines]
self.substs['ACDEFINES'] = ' '.join(['-D%s=%s' % (name,
@ -162,132 +155,3 @@ class ConfigEnvironment(object):
return ConfigEnvironment(config.topsrcdir, config.topobjdir,
config.defines, config.non_global_defines, config.substs)
def get_relative_srcdir(self, file):
'''Returns the relative source directory for the given file, always
using / as a path separator.
'''
assert(isinstance(file, basestring))
dir = posixpath.dirname(relpath(file, self.topobjdir).replace(os.sep, '/'))
if dir:
return dir
return '.'
def get_top_srcdir(self, file):
'''Returns a normalized top_srcdir for the given file: if
substs['top_srcdir'] is a relative path, it is relative to the
topobjdir. Adjust it to be relative to the file path.'''
top_srcdir = self.substs['top_srcdir']
if posixpath.isabs(top_srcdir) or ntpath.isabs(top_srcdir):
return top_srcdir
return posixpath.normpath(posixpath.join(self.get_depth(file), top_srcdir))
def get_file_srcdir(self, file):
'''Returns the srcdir for the given file, where srcdir is in msys
format on windows, thus derived from top_srcdir.
'''
dir = self.get_relative_srcdir(file)
top_srcdir = self.get_top_srcdir(file)
return posixpath.normpath(posixpath.join(top_srcdir, dir))
def get_depth(self, file):
'''Returns the DEPTH for the given file, that is, the path to the
object directory relative to the directory containing the given file.
Always uses / as a path separator.
'''
return relpath(self.topobjdir, os.path.dirname(file)).replace(os.sep, '/')
def get_input(self, file):
'''Returns the input file path in the source tree that can be used
to create the given config file or header.
'''
assert(isinstance(file, basestring))
return os.path.normpath(os.path.join(self.topsrcdir, "%s.in" % relpath(file, self.topobjdir)))
def create_config_file(self, output, extra=None):
'''Creates the given config file. A config file is generated by
taking the corresponding source file and replacing occurences of
"@VAR@" by the value corresponding to "VAR" in the substs dict.
Additional substs are defined according to the file being treated:
"srcdir" for its the path to its source directory
"relativesrcdir" for its source directory relative to the top
"DEPTH" for the path to the top object directory
'''
path = output.name
if os.path.basename(path) == 'Makefile':
return self.create_makefile(output, extra=extra)
pp = self._get_preprocessor(output, extra)
pp.do_include(self.get_input(path))
def create_makefile(self, output, stub=False, extra=None):
'''Creates the given makefile. Makefiles are treated the same as
config files, but some additional header and footer is added to the
output.
When the stub argument is True, no source file is used, and a stub
makefile with the default header and footer only is created.
'''
pp = self._get_preprocessor(output, extra)
pp.handleLine('# THIS FILE WAS AUTOMATICALLY GENERATED. DO NOT MODIFY BY HAND.\n');
pp.handleLine('DEPTH := @DEPTH@\n')
pp.handleLine('topsrcdir := @top_srcdir@\n')
pp.handleLine('srcdir := @srcdir@\n')
pp.handleLine('VPATH := @srcdir@\n')
pp.handleLine('relativesrcdir := @relativesrcdir@\n')
pp.handleLine('include $(DEPTH)/config/autoconf.mk\n')
if not stub:
pp.do_include(self.get_input(output.name))
# Empty line to avoid failures when last line in Makefile.in ends
# with a backslash.
pp.handleLine('\n')
pp.handleLine('include $(topsrcdir)/config/recurse.mk\n')
def _get_preprocessor(self, output, extra):
'''Returns a preprocessor for use by create_config_file and
create_makefile.
'''
path = output.name
pp = Preprocessor()
pp.context.update(self.substs)
pp.context.update(top_srcdir = self.get_top_srcdir(path))
pp.context.update(srcdir = self.get_file_srcdir(path))
pp.context.update(relativesrcdir = self.get_relative_srcdir(path))
pp.context.update(DEPTH = self.get_depth(path))
if extra:
pp.context.update(extra)
pp.do_filter('attemptSubstitution')
pp.setMarker(None)
pp.out = output
return pp
def create_config_header(self, output):
'''Creates the given config header. A config header is generated by
taking the corresponding source file and replacing some #define/#undef
occurences:
"#undef NAME" is turned into "#define NAME VALUE"
"#define NAME" is unchanged
"#define NAME ORIGINAL_VALUE" is turned into "#define NAME VALUE"
"#undef UNKNOWN_NAME" is turned into "/* #undef UNKNOWN_NAME */"
Whitespaces are preserved.
'''
with open(self.get_input(output.name), 'rU') as input:
ensureParentDir(output.name)
r = re.compile('^\s*#\s*(?P<cmd>[a-z]+)(?:\s+(?P<name>\S+)(?:\s+(?P<value>\S+))?)?', re.U)
for l in input:
m = r.match(l)
if m:
cmd = m.group('cmd')
name = m.group('name')
value = m.group('value')
if name:
if name in self.defines:
if cmd == 'define' and value:
l = l[:m.start('value')] + str(self.defines[name]) + l[m.end('value'):]
elif cmd == 'undef':
l = l[:m.start('cmd')] + 'define' + l[m.end('cmd'):m.end('name')] + ' ' + str(self.defines[name]) + l[m.end('name'):]
elif cmd == 'undef':
l = '/* ' + l[:m.end('name')] + ' */' + l[m.end('name'):]
output.write(l)

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

@ -28,7 +28,6 @@ from ..frontend.data import (
GeneratedEventWebIDLFile,
GeneratedInclude,
GeneratedWebIDLFile,
HeaderFileSubstitution,
HostProgram,
HostSimpleProgram,
InstallationTarget,
@ -85,7 +84,7 @@ class BackendMakeFile(object):
self.objdir = objdir
self.relobjdir = objdir[len(environment.topobjdir) + 1:]
self.environment = environment
self.name = os.path.join(objdir, 'backend.mk')
self.name = mozpath.join(objdir, 'backend.mk')
# XPIDLFiles attached to this file.
self.idls = []
@ -290,7 +289,7 @@ class RecursiveMakeBackend(CommonBackend):
self._test_manifests = {}
self.backend_input_files.add(os.path.join(self.environment.topobjdir,
self.backend_input_files.add(mozpath.join(self.environment.topobjdir,
'config', 'autoconf.mk'))
self._install_manifests = {
@ -324,29 +323,36 @@ class RecursiveMakeBackend(CommonBackend):
def consume_object(self, obj):
"""Write out build files necessary to build with recursive make."""
CommonBackend.consume_object(self, obj)
if not isinstance(obj, SandboxDerived):
return
if obj.srcdir not in self._backend_files:
self._backend_files[obj.srcdir] = \
if obj.objdir not in self._backend_files:
self._backend_files[obj.objdir] = \
BackendMakeFile(obj.srcdir, obj.objdir, self.get_environment(obj))
backend_file = self._backend_files[obj.srcdir]
backend_file = self._backend_files[obj.objdir]
CommonBackend.consume_object(self, obj)
# CommonBackend handles XPIDLFile and TestManifest, but we want to do
# some extra things for them.
if isinstance(obj, XPIDLFile):
backend_file.idls.append(obj)
backend_file.xpt_name = '%s.xpt' % obj.module
elif isinstance(obj, TestManifest):
self._process_test_manifest(obj, backend_file)
# If CommonBackend acknowledged the object, we're done with it.
if obj._ack:
return
if isinstance(obj, DirectoryTraversal):
self._process_directory_traversal(obj, backend_file)
elif isinstance(obj, ConfigFileSubstitution):
with self._write_file(obj.output_path) as fh:
backend_file.environment.create_config_file(fh)
self.backend_input_files.add(obj.input_path)
elif isinstance(obj, HeaderFileSubstitution):
with self._write_file(obj.output_path) as fh:
backend_file.environment.create_config_header(fh)
self.backend_input_files.add(obj.input_path)
elif isinstance(obj, XPIDLFile):
backend_file.idls.append(obj)
backend_file.xpt_name = '%s.xpt' % obj.module
# Other ConfigFileSubstitution should have been acked by
# CommonBackend.
assert os.path.basename(obj.output_path) == 'Makefile'
self._create_makefile(obj)
elif isinstance(obj, VariablePassthru):
unified_suffixes = dict(
UNIFIED_CSRCS='c',
@ -440,9 +446,6 @@ class RecursiveMakeBackend(CommonBackend):
elif isinstance(obj, HostSimpleProgram):
self._process_host_simple_program(obj.program, backend_file)
elif isinstance(obj, TestManifest):
self._process_test_manifest(obj, backend_file)
elif isinstance(obj, LocalInclude):
self._process_local_include(obj.path, backend_file)
@ -585,11 +588,11 @@ class RecursiveMakeBackend(CommonBackend):
root_mk.add_statement('$(call include_deps,root-deps.mk)')
with self._write_file(
os.path.join(self.environment.topobjdir, 'root.mk')) as root:
mozpath.join(self.environment.topobjdir, 'root.mk')) as root:
root_mk.dump(root, removal_guard=False)
with self._write_file(
os.path.join(self.environment.topobjdir, 'root-deps.mk')) as root_deps:
mozpath.join(self.environment.topobjdir, 'root-deps.mk')) as root_deps:
root_deps_mk.dump(root_deps, removal_guard=False)
def _add_unified_build_rules(self, makefile, files, output_directory,
@ -643,7 +646,7 @@ class RecursiveMakeBackend(CommonBackend):
# blown away and we need to regenerate them. The rule doesn't correctly
# handle source files being added/removed/renamed. Therefore, we
# generate them here also to make sure everything's up-to-date.
with self._write_file(os.path.join(output_directory, unified_file)) as f:
with self._write_file(mozpath.join(output_directory, unified_file)) as f:
f.write('#define MOZ_UNIFIED_BUILD\n')
includeTemplate = '#include "%(cppfile)s"'
if poison_windows_h:
@ -680,10 +683,11 @@ class RecursiveMakeBackend(CommonBackend):
def consume_finished(self):
CommonBackend.consume_finished(self)
for srcdir in sorted(self._backend_files.keys()):
with self._write_file(fh=self._backend_files[srcdir]) as bf:
makefile_in = os.path.join(srcdir, 'Makefile.in')
makefile = os.path.join(bf.objdir, 'Makefile')
for objdir, backend_file in sorted(self._backend_files.items()):
srcdir = backend_file.srcdir
with self._write_file(fh=backend_file) as bf:
makefile_in = mozpath.join(srcdir, 'Makefile.in')
makefile = mozpath.join(objdir, 'Makefile')
# If Makefile.in exists, use it as a template. Otherwise,
# create a stub.
@ -692,13 +696,6 @@ class RecursiveMakeBackend(CommonBackend):
self.log(logging.DEBUG, 'substitute_makefile',
{'path': makefile}, 'Substituting makefile: {path}')
# Adding the Makefile.in here has the desired side-effect
# that if the Makefile.in disappears, this will force
# moz.build traversal. This means that when we remove empty
# Makefile.in files, the old file will get replaced with
# the autogenerated one automatically.
self.backend_input_files.add(makefile_in)
for tier, skiplist in self._may_skip.items():
if tier in ('compile', 'binaries'):
continue
@ -710,22 +707,24 @@ class RecursiveMakeBackend(CommonBackend):
# Can't skip directories with a jar.mn for the 'libs' tier.
if bf.relobjdir in self._may_skip['libs'] and \
os.path.exists(os.path.join(srcdir, 'jar.mn')):
os.path.exists(mozpath.join(srcdir, 'jar.mn')):
self._may_skip['libs'].remove(bf.relobjdir)
with self._write_file(makefile) as fh:
bf.environment.create_makefile(fh, stub=stub)
obj = self.Substitution()
obj.output_path = makefile
obj.input_path = makefile_in
self._create_makefile(obj, stub=stub)
# Write out a master list of all IPDL source files.
ipdl_dir = os.path.join(self.environment.topobjdir, 'ipc', 'ipdl')
ipdl_dir = mozpath.join(self.environment.topobjdir, 'ipc', 'ipdl')
mk = mozmakeutil.Makefile()
sorted_ipdl_sources = list(sorted(self._ipdl_sources))
mk.add_statement('ALL_IPDLSRCS := %s' % ' '.join(sorted_ipdl_sources))
def files_from(ipdl):
base = os.path.basename(ipdl)
root, ext = os.path.splitext(base)
base = mozpath.basename(ipdl)
root, ext = mozpath.splitext(base)
# Both .ipdl and .ipdlh become .cpp files
files = ['%s.cpp' % root]
@ -740,21 +739,21 @@ class RecursiveMakeBackend(CommonBackend):
unified_prefix='UnifiedProtocols',
unified_files_makefile_variable='CPPSRCS')
mk.add_statement('IPDLDIRS := %s' % ' '.join(sorted(set(os.path.dirname(p)
mk.add_statement('IPDLDIRS := %s' % ' '.join(sorted(set(mozpath.dirname(p)
for p in self._ipdl_sources))))
with self._write_file(os.path.join(ipdl_dir, 'ipdlsrcs.mk')) as ipdls:
with self._write_file(mozpath.join(ipdl_dir, 'ipdlsrcs.mk')) as ipdls:
mk.dump(ipdls, removal_guard=False)
self._may_skip['compile'] -= set(['ipc/ipdl'])
# Write out master lists of WebIDL source files.
bindings_dir = os.path.join(self.environment.topobjdir, 'dom', 'bindings')
bindings_dir = mozpath.join(self.environment.topobjdir, 'dom', 'bindings')
mk = mozmakeutil.Makefile()
def write_var(variable, sources):
files = [os.path.basename(f) for f in sorted(sources)]
files = [mozpath.basename(f) for f in sorted(sources)]
mk.add_statement('%s += %s' % (variable, ' '.join(files)))
write_var('webidl_files', self._webidl_sources)
write_var('generated_events_webidl_files', self._generated_events_webidl_sources)
@ -767,7 +766,7 @@ class RecursiveMakeBackend(CommonBackend):
iter(self._generated_events_webidl_sources),
iter(self._generated_webidl_sources),
iter(self._preprocessed_webidl_sources))
all_webidl_files = [os.path.basename(x) for x in all_webidl_files]
all_webidl_files = [mozpath.basename(x) for x in all_webidl_files]
all_webidl_sources = [re.sub(r'\.webidl$', 'Binding.cpp', x) for x in all_webidl_files]
self._add_unified_build_rules(mk, all_webidl_sources,
@ -778,7 +777,7 @@ class RecursiveMakeBackend(CommonBackend):
# Assume that Somebody Else has responsibility for correctly
# specifying removal dependencies for |all_webidl_sources|.
with self._write_file(os.path.join(bindings_dir, 'webidlsrcs.mk')) as webidls:
with self._write_file(mozpath.join(bindings_dir, 'webidlsrcs.mk')) as webidls:
mk.dump(webidls, removal_guard=False)
self._may_skip['compile'] -= set(['dom/bindings', 'dom/bindings/test'])
@ -805,8 +804,8 @@ class RecursiveMakeBackend(CommonBackend):
# Make the master test manifest files.
for flavor, t in self._test_manifests.items():
install_prefix, manifests = t
manifest_stem = os.path.join(install_prefix, '%s.ini' % flavor)
self._write_master_test_manifest(os.path.join(
manifest_stem = mozpath.join(install_prefix, '%s.ini' % flavor)
self._write_master_test_manifest(mozpath.join(
self.environment.topobjdir, '_tests', manifest_stem),
manifests)
@ -818,7 +817,7 @@ class RecursiveMakeBackend(CommonBackend):
self._write_manifests('install', self._install_manifests)
ensureParentDir(os.path.join(self.environment.topobjdir, 'dist', 'foo'))
ensureParentDir(mozpath.join(self.environment.topobjdir, 'dist', 'foo'))
def _process_directory_traversal(self, obj, backend_file):
"""Process a data.DirectoryTraversal instance."""
@ -933,8 +932,8 @@ class RecursiveMakeBackend(CommonBackend):
namespace += '/'
for s in strings:
source = os.path.normpath(os.path.join(obj.srcdir, s))
dest = '%s%s' % (namespace, os.path.basename(s))
source = mozpath.normpath(mozpath.join(obj.srcdir, s))
dest = '%s%s' % (namespace, mozpath.basename(s))
self._install_manifests['dist_include'].add_symlink(source, dest)
if not os.path.exists(source):
@ -1009,18 +1008,15 @@ class RecursiveMakeBackend(CommonBackend):
# some processes (such as PGO at the time this was implemented) wipe
# out dist/include without regard to our install manifests.
out_path = os.path.join(self.environment.topobjdir, 'config',
obj = self.Substitution()
obj.output_path = mozpath.join(self.environment.topobjdir, 'config',
'makefiles', 'xpidl', 'Makefile')
with self._write_file(out_path) as fh:
self.environment.create_config_file(fh, extra=dict(
xpidl_rules='\n'.join(rules),
xpidl_modules=' '.join(xpt_modules),
))
# The Makefile can't regenerate itself because of custom substitution.
# We need to list it here to ensure changes cause regeneration.
self.backend_input_files.add(os.path.join(self.environment.topsrcdir,
'config', 'makefiles', 'xpidl', 'Makefile.in'))
obj.input_path = mozpath.join(self.environment.topsrcdir, 'config',
'makefiles', 'xpidl', 'Makefile.in')
self._create_makefile(obj, extra=dict(
xpidl_rules='\n'.join(rules),
xpidl_modules=' '.join(xpt_modules),
))
def _process_program(self, program, backend_file):
backend_file.write('PROGRAM = %s\n' % program)
@ -1035,12 +1031,12 @@ class RecursiveMakeBackend(CommonBackend):
backend_file.write('HOST_SIMPLE_PROGRAMS += %s\n' % program)
def _process_webidl_basename(self, basename):
header = 'mozilla/dom/%sBinding.h' % os.path.splitext(basename)[0]
header = 'mozilla/dom/%sBinding.h' % mozpath.splitext(basename)[0]
self._install_manifests['dist_include'].add_optional_exists(header)
def _process_test_manifest(self, obj, backend_file):
# Much of the logic in this function could be moved to CommonBackend.
self.backend_input_files.add(os.path.join(obj.topsrcdir,
self.backend_input_files.add(mozpath.join(obj.topsrcdir,
obj.manifest_relpath))
# Duplicate manifests may define the same file. That's OK.
@ -1093,7 +1089,7 @@ class RecursiveMakeBackend(CommonBackend):
(target, ' '.join(jar.sources)))
if jar.generated_sources:
backend_file.write('%s_PP_JAVAFILES := %s\n' %
(target, ' '.join(os.path.join('generated', f) for f in jar.generated_sources)))
(target, ' '.join(mozpath.join('generated', f) for f in jar.generated_sources)))
if jar.extra_jars:
backend_file.write('%s_EXTRA_JARS := %s\n' %
(target, ' '.join(jar.extra_jars)))
@ -1116,7 +1112,7 @@ class RecursiveMakeBackend(CommonBackend):
% (relpath, basename))
def _write_manifests(self, dest, manifests):
man_dir = os.path.join(self.environment.topobjdir, '_build_manifests',
man_dir = mozpath.join(self.environment.topobjdir, '_build_manifests',
dest)
# We have a purger for the manifests themselves to ensure legacy
@ -1126,7 +1122,7 @@ class RecursiveMakeBackend(CommonBackend):
for k, manifest in manifests.items():
purger.add(k)
with self._write_file(os.path.join(man_dir, k)) as fh:
with self._write_file(mozpath.join(man_dir, k)) as fh:
manifest.write(fileobj=fh)
purger.purge(man_dir)
@ -1138,3 +1134,42 @@ class RecursiveMakeBackend(CommonBackend):
for manifest in sorted(manifests):
master.write('[include:%s]\n' % manifest)
class Substitution(object):
"""BaseConfigSubstitution-like class for use with _create_makefile."""
__slots__ = (
'input_path',
'output_path',
)
def _create_makefile(self, obj, stub=False, extra=None):
'''Creates the given makefile. Makefiles are treated the same as
config files, but some additional header and footer is added to the
output.
When the stub argument is True, no source file is used, and a stub
makefile with the default header and footer only is created.
'''
with self._get_preprocessor(obj) as pp:
if extra:
pp.context.update(extra)
pp.handleLine(b'# THIS FILE WAS AUTOMATICALLY GENERATED. DO NOT MODIFY BY HAND.\n');
pp.handleLine(b'DEPTH := @DEPTH@\n')
pp.handleLine(b'topsrcdir := @top_srcdir@\n')
pp.handleLine(b'srcdir := @srcdir@\n')
pp.handleLine(b'VPATH := @srcdir@\n')
pp.handleLine(b'relativesrcdir := @relativesrcdir@\n')
pp.handleLine(b'include $(DEPTH)/config/autoconf.mk\n')
if not stub:
pp.do_include(obj.input_path)
# Empty line to avoid failures when last line in Makefile.in ends
# with a backslash.
pp.handleLine(b'\n')
pp.handleLine(b'include $(topsrcdir)/config/recurse.mk\n')
if not stub:
# Adding the Makefile.in here has the desired side-effect
# that if the Makefile.in disappears, this will force
# moz.build traversal. This means that when we remove empty
# Makefile.in files, the old file will get replaced with
# the autogenerated one automatically.
self.backend_input_files.add(obj.input_path)

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

@ -24,6 +24,7 @@ from mozbuild.util import (
shell_quote,
StrictOrderingOnAppendList,
)
import mozpack.path as mozpath
from .sandbox_symbols import FinalTargetValue
@ -169,7 +170,7 @@ class XPIDLFile(SandboxDerived):
SandboxDerived.__init__(self, sandbox)
self.source_path = source
self.basename = os.path.basename(source)
self.basename = mozpath.basename(source)
self.module = module
class Defines(SandboxDerived):
@ -397,7 +398,7 @@ class TestManifest(SandboxDerived):
SandboxDerived.__init__(self, sandbox)
self.path = path
self.directory = os.path.dirname(path)
self.directory = mozpath.dirname(path)
self.manifest = manifest
self.flavor = flavor
self.install_prefix = install_prefix

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

@ -63,7 +63,7 @@ class TreeMetadataEmitter(LoggingMixin):
self.config = config
# TODO add mozinfo into config or somewhere else.
mozinfo_path = os.path.join(config.topobjdir, 'mozinfo.json')
mozinfo_path = mozpath.join(config.topobjdir, 'mozinfo.json')
if os.path.exists(mozinfo_path):
self.mozinfo = json.load(open(mozinfo_path, 'rt'))
else:
@ -174,7 +174,7 @@ class TreeMetadataEmitter(LoggingMixin):
for symbol in ('SOURCES', 'HOST_SOURCES', 'UNIFIED_SOURCES'):
for src in (sandbox[symbol] or []):
if not os.path.exists(os.path.join(sandbox['SRCDIR'], src)):
if not os.path.exists(mozpath.join(sandbox['SRCDIR'], src)):
raise SandboxValidationError('Reference to a file that '
'doesn\'t exist in %s (%s) in %s'
% (symbol, src, sandbox['RELATIVEDIR']))
@ -247,7 +247,7 @@ class TreeMetadataEmitter(LoggingMixin):
if k in ('SOURCES', 'UNIFIED_SOURCES')))
for variable, mapping in varmap.items():
for f in sandbox[variable]:
ext = os.path.splitext(f)[1]
ext = mozpath.splitext(f)[1]
if ext not in mapping:
raise SandboxValidationError('%s has an unknown file type in %s' % (f, sandbox['RELATIVEDIR']))
l = passthru.variables.setdefault(mapping[ext], [])
@ -369,8 +369,8 @@ class TreeMetadataEmitter(LoggingMixin):
path = path[1:]
sub = cls(sandbox)
sub.input_path = os.path.join(sandbox['SRCDIR'], '%s.in' % path)
sub.output_path = os.path.join(sandbox['OBJDIR'], path)
sub.input_path = mozpath.join(sandbox['SRCDIR'], '%s.in' % path)
sub.output_path = mozpath.join(sandbox['OBJDIR'], path)
sub.relpath = path
return sub
@ -378,7 +378,7 @@ class TreeMetadataEmitter(LoggingMixin):
def _process_test_manifest(self, sandbox, info, manifest_path):
flavor, install_prefix, filter_inactive = info
manifest_path = os.path.normpath(manifest_path)
manifest_path = mozpath.normpath(manifest_path)
path = mozpath.normpath(mozpath.join(sandbox['SRCDIR'], manifest_path))
manifest_dir = mozpath.dirname(path)
manifest_reldir = mozpath.dirname(mozpath.relpath(path,
@ -441,7 +441,7 @@ class TreeMetadataEmitter(LoggingMixin):
obj.installs[full] = mozpath.join(out_dir, pattern)
# We also copy the manifest into the output directory.
out_path = mozpath.join(out_dir, os.path.basename(manifest_path))
out_path = mozpath.join(out_dir, mozpath.basename(manifest_path))
obj.installs[path] = out_path
# Some manifests reference files that are auto generated as

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

@ -40,6 +40,8 @@ from mozbuild.util import (
from mozbuild.backend.configenvironment import ConfigEnvironment
import mozpack.path as mozpath
from .data import (
JavaJarData,
)
@ -82,8 +84,8 @@ def is_read_allowed(path, config):
assert os.path.isabs(path)
assert os.path.isabs(config.topsrcdir)
path = os.path.normpath(path)
topsrcdir = os.path.normpath(config.topsrcdir)
path = mozpath.normpath(path)
topsrcdir = mozpath.normpath(config.topsrcdir)
if path.startswith(topsrcdir):
return True
@ -91,8 +93,8 @@ def is_read_allowed(path, config):
external_dirs = config.substs.get('EXTERNAL_SOURCE_DIR', '').split()
for external in external_dirs:
if not os.path.isabs(external):
external = os.path.join(config.topsrcdir, external)
external = os.path.normpath(external)
external = mozpath.join(config.topsrcdir, external)
external = mozpath.normpath(external)
if path.startswith(external):
return True
@ -128,19 +130,19 @@ class MozbuildSandbox(Sandbox):
self.config = config
self.metadata = dict(metadata)
topobjdir = os.path.abspath(config.topobjdir)
topobjdir = mozpath.abspath(config.topobjdir)
topsrcdir = config.topsrcdir
norm_topsrcdir = os.path.normpath(topsrcdir)
norm_topsrcdir = mozpath.normpath(topsrcdir)
if not path.startswith(norm_topsrcdir):
external_dirs = config.substs.get('EXTERNAL_SOURCE_DIR', '').split()
for external in external_dirs:
external = os.path.normpath(external)
external = mozpath.normpath(external)
if not os.path.isabs(external):
external = os.path.join(config.topsrcdir, external)
external = mozpath.join(config.topsrcdir, external)
external = os.path.normpath(external)
external = mozpath.normpath(external)
if not path.startswith(external):
continue
@ -152,27 +154,27 @@ class MozbuildSandbox(Sandbox):
# is in play that the main build system is built in a
# subdirectory of its topobjdir. Therefore, the topobjdir of
# the external source directory is the parent of our topobjdir.
topobjdir = os.path.dirname(topobjdir)
topobjdir = mozpath.dirname(topobjdir)
# This is suboptimal because we load the config.status multiple
# times. We should consider caching it, possibly by moving this
# code up to the reader.
config = ConfigEnvironment.from_config_status(
os.path.join(topobjdir, 'config.status'))
mozpath.join(topobjdir, 'config.status'))
self.config = config
break
self.topsrcdir = topsrcdir
relpath = os.path.relpath(path, topsrcdir).replace(os.sep, '/')
reldir = os.path.dirname(relpath)
relpath = mozpath.relpath(path, topsrcdir)
reldir = mozpath.dirname(relpath)
with self._globals.allow_all_writes() as d:
d['TOPSRCDIR'] = topsrcdir
d['TOPOBJDIR'] = topobjdir
d['RELATIVEDIR'] = reldir
d['SRCDIR'] = os.path.join(topsrcdir, reldir).replace(os.sep, '/').rstrip('/')
d['OBJDIR'] = os.path.join(topobjdir, reldir).replace(os.sep, '/').rstrip('/')
d['SRCDIR'] = mozpath.join(topsrcdir, reldir).rstrip('/')
d['OBJDIR'] = mozpath.join(topobjdir, reldir).rstrip('/')
d['CONFIG'] = ReadOnlyDefaultDict(self.config.substs_unicode,
global_default=None)
@ -205,21 +207,21 @@ class MozbuildSandbox(Sandbox):
"""
if os.path.isabs(path):
if not filesystem_absolute:
path = os.path.normpath(os.path.join(self.topsrcdir,
path = mozpath.normpath(mozpath.join(self.topsrcdir,
path[1:]))
else:
if len(self._execution_stack):
path = os.path.normpath(os.path.join(
os.path.dirname(self._execution_stack[-1]),
path = mozpath.normpath(mozpath.join(
mozpath.dirname(self._execution_stack[-1]),
path))
else:
path = os.path.normpath(os.path.join(
path = mozpath.normpath(mozpath.join(
self.topsrcdir, path))
# realpath() is needed for true security. But, this isn't for security
# protection, so it is omitted.
normalized_path = os.path.normpath(path)
normalized_path = mozpath.normpath(path)
if not is_read_allowed(normalized_path, self.config):
raise SandboxLoadError(list(self._execution_stack),
sys.exc_info()[2], illegal_path=path)
@ -609,7 +611,7 @@ class BuildReader(object):
This is a generator of Sandbox instances. As each mozbuild file is
read, a new Sandbox is created. Each created Sandbox is returned.
"""
path = os.path.join(self.topsrcdir, 'moz.build')
path = mozpath.join(self.topsrcdir, 'moz.build')
return self.read_mozbuild(path, read_tiers=True,
filesystem_absolute=True, metadata={'tier': None})
@ -672,7 +674,7 @@ class BuildReader(object):
def _read_mozbuild(self, path, read_tiers, filesystem_absolute, descend,
metadata):
path = os.path.normpath(path)
path = mozpath.normpath(path)
log(self._log, logging.DEBUG, 'read_mozbuild', {'path': path},
'Reading file: {path}')
@ -750,15 +752,15 @@ class BuildReader(object):
'parent': sandbox['RELATIVEDIR'],
'var': 'DIRS'}
curdir = os.path.dirname(path)
curdir = mozpath.dirname(path)
for relpath, child_metadata in recurse_info.items():
child_path = os.path.join(curdir, relpath, 'moz.build')
child_path = mozpath.join(curdir, relpath, 'moz.build')
# Ensure we don't break out of the topsrcdir. We don't do realpath
# because it isn't necessary. If there are symlinks in the srcdir,
# that's not our problem. We're not a hosted application: we don't
# need to worry about security too much.
child_path = os.path.normpath(child_path)
child_path = mozpath.normpath(child_path)
if not is_read_allowed(child_path, self.config):
raise SandboxValidationError(
'Attempting to process file outside of allowed paths: %s' %

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

@ -16,13 +16,15 @@ from mozbuild.backend.configenvironment import ConfigEnvironment
from mozbuild.frontend.emitter import TreeMetadataEmitter
from mozbuild.frontend.reader import BuildReader
import mozpack.path as mozpath
log_manager = LoggingManager()
log_manager.add_terminal_logging()
test_data_path = os.path.abspath(os.path.dirname(__file__))
test_data_path = os.path.join(test_data_path, 'data')
test_data_path = mozpath.abspath(mozpath.dirname(__file__))
test_data_path = mozpath.join(test_data_path, 'data')
CONFIGS = {
@ -98,6 +100,16 @@ CONFIGS = {
'non_global_defines': [],
'substs': [],
},
'test_config': {
'defines': [
('foo', 'baz qux'),
('baz', 1)
],
'non_global_defines': [],
'substs': [
('foo', 'bar baz'),
],
},
}
@ -113,7 +125,7 @@ class BackendTester(unittest.TestCase):
objdir = mkdtemp()
self.addCleanup(rmtree, objdir)
srcdir = os.path.join(test_data_path, name)
srcdir = mozpath.join(test_data_path, name)
config['substs'].append(('top_srcdir', srcdir))
return ConfigEnvironment(srcdir, objdir, **config)
@ -135,7 +147,7 @@ class BackendTester(unittest.TestCase):
for dirpath, dirnames, filenames in os.walk(topdir):
for f in filenames:
if f == filename:
yield os.path.relpath(os.path.join(dirpath, f), topdir)
yield mozpath.relpath(mozpath.join(dirpath, f), topdir)
def _mozbuild_paths(self, env):
return self._tree_paths(env.topsrcdir, 'moz.build')

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

@ -0,0 +1,15 @@
/* Comment */
#define foo
#define foo 42
#undef foo
#define bar
#define bar 42
#undef bar
# undef baz
#ifdef foo
# undef foo
# define foo 42
# define foo 42
#endif

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

@ -0,0 +1,3 @@
#ifdef foo
@foo@
@bar@

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

@ -0,0 +1,6 @@
CONFIGURE_SUBST_FILES = [
'file',
]
CONFIGURE_DEFINE_FILES = [
'file.h',
]

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

@ -11,6 +11,8 @@ import mozbuild.backend.configenvironment as ConfigStatus
from mozbuild.util import ReadOnlyDict
import mozpack.path as mozpath
class ConfigEnvironment(ConfigStatus.ConfigEnvironment):
def __init__(self, *args, **kwargs):
@ -20,7 +22,7 @@ class ConfigEnvironment(ConfigStatus.ConfigEnvironment):
if os.path.isabs(self.topsrcdir):
top_srcdir = self.topsrcdir.replace(os.sep, '/')
else:
top_srcdir = os.path.relpath(self.topsrcdir, self.topobjdir).replace(os.sep, '/')
top_srcdir = mozpath.relpath(self.topsrcdir, self.topobjdir).replace(os.sep, '/')
d = dict(self.substs)
d['top_srcdir'] = top_srcdir
@ -62,262 +64,6 @@ zzz = "abc def"''')
self.assertEqual(env.substs['ALLEMPTYSUBSTS'], '''FOOBAR =
qux =''')
def test_config_file(self):
'''Test the creation of config files.
'''
with MockedOpen({'file.in': '''#ifdef foo
@foo@
@bar@
'''}):
env = ConfigEnvironment('.', '.', substs = [ ('foo', 'bar baz') ])
with open('file', 'w') as fh:
env.create_config_file(fh)
self.assertEqual(open('file', 'r').read(), '''#ifdef foo
bar baz
@bar@
''')
def test_config_header(self):
'''Test the creation of config headers.
'''
with MockedOpen({'file.in': '''
/* Comment */
#define foo
#define foo 42
#undef foo
#define bar
#define bar 42
#undef bar
# undef baz
#ifdef foo
# undef foo
# define foo 42
# define foo 42
#endif
'''}):
env = ConfigEnvironment('.', '.', defines = [ ('foo', 'baz qux'), ('baz', 1) ])
with open('file', 'w') as fh:
env.create_config_header(fh)
self.assertEqual(open('file','r').read(), '''
/* Comment */
#define foo
#define foo baz qux
#define foo baz qux
#define bar
#define bar 42
/* #undef bar */
# define baz 1
#ifdef foo
# define foo baz qux
# define foo baz qux
# define foo baz qux
#endif
''')
# Tests for get_relative_srcdir, get_depth, get_input and get_file_srcdir,
# depending on various cases of top source directory and top build
# directory location.
class TestPaths(unittest.TestCase):
def setUp(self):
self.dir = os.path.basename(os.path.abspath(os.curdir))
self.absolute = os.path.normpath('/absolute')
class TestPathsLocalBuildDir(TestPaths):
def get_env(self, topsrcdir):
env = ConfigEnvironment(topsrcdir = topsrcdir, topobjdir = '.')
self.assertEqual(env.get_relative_srcdir('file'), '.')
self.assertEqual(env.get_relative_srcdir('dir/file'), 'dir')
self.assertEqual(env.get_relative_srcdir('deeply/nested/path/to/file'), 'deeply/nested/path/to')
self.assertEqual(env.get_depth('file'), '.')
self.assertEqual(env.get_depth('dir/file'), '..')
self.assertEqual(env.get_depth('deeply/nested/path/to/file'), '../../../..')
return env
def test_paths_local_build_local_src(self):
# topsrcdir = . ; topobjdir = .
env = self.get_env('.')
self.assertEqual(env.get_input('file'), 'file.in')
self.assertEqual(env.get_input('dir/file'), os.path.join('dir', 'file.in'))
self.assertEqual(env.get_top_srcdir('file'), '.')
self.assertEqual(env.get_top_srcdir('dir/file'), '..')
self.assertEqual(env.get_file_srcdir('file'), '.')
self.assertEqual(env.get_file_srcdir('dir/file'), '../dir')
def test_paths_local_build_parent_src(self):
# topsrcdir = .. ; topobjdir = .
env = self.get_env('..')
self.assertEqual(env.get_input('file'), os.path.join('..', 'file.in'))
self.assertEqual(env.get_input('dir/file'), os.path.join('..', 'dir', 'file.in'))
self.assertEqual(env.get_top_srcdir('file'), '..')
self.assertEqual(env.get_top_srcdir('dir/file'), '../..')
self.assertEqual(env.get_file_srcdir('file'), '..')
self.assertEqual(env.get_file_srcdir('dir/file'), '../../dir')
def test_paths_local_build_absolute_src(self):
# topsrcdir = /absolute ; topobjdir = /absolute
env = self.get_env(self.absolute)
self.assertEqual(env.get_input('file'), os.path.join(self.absolute, 'file.in'))
self.assertEqual(env.get_input('dir/file'), os.path.join(self.absolute, 'dir', 'file.in'))
self.assertEqual(env.get_input('%s/file' % self.dir), os.path.join(self.absolute, self.dir, 'file.in'))
self.assertEqual(env.get_top_srcdir('file'), '/absolute')
self.assertEqual(env.get_top_srcdir('dir/file'), '/absolute')
self.assertEqual(env.get_top_srcdir('%s/file' % dir), '/absolute')
self.assertEqual(env.get_file_srcdir('file'), '/absolute')
self.assertEqual(env.get_file_srcdir('dir/file'), '/absolute/dir')
self.assertEqual(env.get_file_srcdir('%s/file' % dir), '/absolute/%s' % dir)
class TestPathsParentBuildDir(TestPaths):
def get_env(self, topsrcdir):
env = ConfigEnvironment(topsrcdir = topsrcdir, topobjdir = '..')
self.assertEqual(env.get_relative_srcdir('..'), '.')
self.assertEqual(env.get_relative_srcdir('file'), self.dir)
self.assertEqual(env.get_relative_srcdir('dir/file'), '%s/dir' % self.dir)
self.assertEqual(env.get_relative_srcdir('deeply/nested/path/to/file'), '%s/deeply/nested/path/to' % self.dir)
self.assertEqual(env.get_depth('../file'), '.')
self.assertEqual(env.get_depth('file'), '..')
self.assertEqual(env.get_depth('dir/file'), '../..')
self.assertEqual(env.get_depth('deeply/nested/path/to/file'), '../../../../..')
return env
def test_paths_parent_build_parent_src(self):
# topsrcdir = .. ; topobjdir = ..
env = self.get_env('..')
self.assertEqual(env.get_input('../file'), os.path.join('..', 'file.in'))
self.assertEqual(env.get_input('file'), os.path.join('..', self.dir, 'file.in'))
self.assertEqual(env.get_input('dir/file'), os.path.join('..', self.dir, 'dir', 'file.in'))
self.assertEqual(env.get_top_srcdir('../file'), '.')
self.assertEqual(env.get_top_srcdir('file'), '..')
self.assertEqual(env.get_top_srcdir('dir/file'), '../..')
self.assertEqual(env.get_file_srcdir('../file'), '.')
self.assertEqual(env.get_file_srcdir('file'), '../%s' % self.dir)
self.assertEqual(env.get_file_srcdir('dir/file'), '../../%s/dir' % self.dir)
def test_paths_parent_build_ancestor_src(self):
# topsrcdir = ../.. ; topobjdir = ..
env = self.get_env('../..')
self.assertEqual(env.get_input('../file'), os.path.join('..', '..', 'file.in'))
self.assertEqual(env.get_input('file'), os.path.join('..', '..', self.dir, 'file.in'))
self.assertEqual(env.get_input('dir/file'), os.path.join('..', '..', self.dir, 'dir', 'file.in'))
self.assertEqual(env.get_top_srcdir('../file'), '..')
self.assertEqual(env.get_top_srcdir('file'), '../..')
self.assertEqual(env.get_top_srcdir('dir/file'), '../../..')
self.assertEqual(env.get_file_srcdir('../file'), '..')
self.assertEqual(env.get_file_srcdir('file'), '../../%s' % self.dir)
self.assertEqual(env.get_file_srcdir('dir/file'), '../../../%s/dir' % self.dir)
def test_paths_parent_build_absolute_src(self):
# topsrcdir = /absolute ; topobjdir = ..
env = self.get_env(self.absolute)
self.assertEqual(env.get_input('../file'), os.path.join(self.absolute, 'file.in'))
self.assertEqual(env.get_input('file'), os.path.join(self.absolute, self.dir, 'file.in'))
self.assertEqual(env.get_input('dir/file'), os.path.join(self.absolute, self.dir, 'dir', 'file.in'))
self.assertEqual(env.get_top_srcdir('../file'), '/absolute')
self.assertEqual(env.get_top_srcdir('file'), '/absolute')
self.assertEqual(env.get_top_srcdir('dir/file'), '/absolute')
self.assertEqual(env.get_file_srcdir('../file'), '/absolute')
self.assertEqual(env.get_file_srcdir('file'), '/absolute/%s' % self.dir)
self.assertEqual(env.get_file_srcdir('dir/file'), '/absolute/%s/dir' % self.dir)
class TestPathsRelativeBuild(TestPaths):
def get_env(self, topsrcdir):
env = ConfigEnvironment(topsrcdir = topsrcdir, topobjdir = 'relative')
self.assertEqual(env.get_relative_srcdir('relative/file'), '.')
self.assertEqual(env.get_relative_srcdir('relative/dir/file'), 'dir')
self.assertEqual(env.get_relative_srcdir('relative/deeply/nested/path/to/file'), 'deeply/nested/path/to')
self.assertEqual(env.get_depth('relative/file'), '.')
self.assertEqual(env.get_depth('relative/dir/file'), '..')
self.assertEqual(env.get_depth('relative/deeply/nested/path/to/file'), '../../../..')
return env
def test_paths_relative_build_relative_src(self):
# topsrcdir = relative ; topobjdir = relative
env = self.get_env('relative')
self.assertEqual(env.get_input('relative/file'), os.path.join('relative', 'file.in'))
self.assertEqual(env.get_input('relative/dir/file'), os.path.join('relative', 'dir', 'file.in'))
self.assertEqual(env.get_top_srcdir('relative/file'), '.')
self.assertEqual(env.get_top_srcdir('relative/dir/file'), '..')
self.assertEqual(env.get_file_srcdir('relative/file'), '.')
self.assertEqual(env.get_file_srcdir('relative/dir/file'), '../dir')
def test_paths_relative_build_local_src(self):
# topsrcdir = . ; topobjdir = relative
env = self.get_env('.')
self.assertEqual(env.get_input('relative/file'), 'file.in')
self.assertEqual(env.get_input('relative/dir/file'), os.path.join('dir', 'file.in'))
self.assertEqual(env.get_top_srcdir('relative/file'), '..')
self.assertEqual(env.get_top_srcdir('relative/dir/file'), '../..')
self.assertEqual(env.get_file_srcdir('relative/file'), '..')
self.assertEqual(env.get_file_srcdir('relative/dir/file'), '../../dir')
def test_paths_relative_build_parent_src(self):
# topsrcdir = .. ; topobjdir = relative
env = self.get_env('..')
self.assertEqual(env.get_input('relative/file'), os.path.join('..', 'file.in'))
self.assertEqual(env.get_input('relative/dir/file'), os.path.join('..', 'dir', 'file.in'))
self.assertEqual(env.get_top_srcdir('relative/file'), '../..')
self.assertEqual(env.get_top_srcdir('relative/dir/file'), '../../..')
self.assertEqual(env.get_file_srcdir('relative/file'), '../..')
self.assertEqual(env.get_file_srcdir('relative/dir/file'), '../../../dir')
def test_paths_relative_build_absolute_src(self):
# topsrcdir = /absolute ; topobjdir = relative
env = self.get_env(self.absolute)
self.assertEqual(env.get_input('relative/file'), os.path.join(self.absolute, 'file.in'))
self.assertEqual(env.get_input('relative/dir/file'), os.path.join(self.absolute, 'dir', 'file.in'))
self.assertEqual(env.get_top_srcdir('relative/file'), '/absolute')
self.assertEqual(env.get_top_srcdir('relative/dir/file'), '/absolute')
self.assertEqual(env.get_file_srcdir('relative/file'), '/absolute')
self.assertEqual(env.get_file_srcdir('relative/dir/file'), '/absolute/dir')
class TestPathsAbsoluteBuild(unittest.TestCase):
def setUp(self):
self.absolute_build = os.path.normpath('/absolute/build')
def get_env(self, topsrcdir):
env = ConfigEnvironment(topsrcdir = topsrcdir, topobjdir = self.absolute_build)
self.assertEqual(env.get_relative_srcdir('/absolute/build/file'), '.')
self.assertEqual(env.get_relative_srcdir('/absolute/build/dir/file'), 'dir')
self.assertEqual(env.get_relative_srcdir('/absolute/build/deeply/nested/path/to/file'), 'deeply/nested/path/to')
self.assertEqual(env.get_depth('/absolute/build/file'), '.')
self.assertEqual(env.get_depth('/absolute/build/dir/file'), '..')
self.assertEqual(env.get_depth('/absolute/build/deeply/nested/path/to/file'), '../../../..')
return env
def test_paths_absolute_build_same_src(self):
# topsrcdir = /absolute/build ; topobjdir = /absolute/build
env = self.get_env(self.absolute_build)
self.assertEqual(env.get_input('/absolute/build/file'), os.path.join(self.absolute_build, 'file.in'))
self.assertEqual(env.get_input('/absolute/build/dir/file'), os.path.join(self.absolute_build, 'dir', 'file.in'))
self.assertEqual(env.get_top_srcdir('/absolute/build/file'), '/absolute/build')
self.assertEqual(env.get_top_srcdir('/absolute/build/dir/file'), '/absolute/build')
self.assertEqual(env.get_file_srcdir('/absolute/build/file'), '/absolute/build')
self.assertEqual(env.get_file_srcdir('/absolute/build/dir/file'), '/absolute/build/dir')
def test_paths_absolute_build_ancestor_src(self):
# topsrcdir = /absolute ; topobjdir = /absolute/build
absolute = os.path.dirname(self.absolute_build)
env = self.get_env(absolute)
self.assertEqual(env.get_input('/absolute/build/file'), os.path.join(absolute, 'file.in'))
self.assertEqual(env.get_input('/absolute/build/dir/file'), os.path.join(absolute, 'dir', 'file.in'))
self.assertEqual(env.get_top_srcdir('/absolute/build/file'), '/absolute')
self.assertEqual(env.get_top_srcdir('/absolute/build/dir/file'), '/absolute')
self.assertEqual(env.get_file_srcdir('/absolute/build/file'), '/absolute')
self.assertEqual(env.get_file_srcdir('/absolute/build/dir/file'), '/absolute/dir')
def test_paths_absolute_build_different_src(self):
# topsrcdir = /some/path ; topobjdir = /absolute/build
absolute = os.path.normpath('/some/path')
env = self.get_env(absolute)
self.assertEqual(env.get_input('/absolute/build/file'), os.path.join(absolute, 'file.in'))
self.assertEqual(env.get_input('/absolute/build/dir/file'), os.path.join(absolute, 'dir', 'file.in'))
self.assertEqual(env.get_top_srcdir('/absolute/build/file'), '/some/path')
self.assertEqual(env.get_top_srcdir('/absolute/build/dir/file'), '/some/path')
self.assertEqual(env.get_file_srcdir('/absolute/build/file'), '/some/path')
self.assertEqual(env.get_file_srcdir('/absolute/build/dir/file'), '/some/path/dir')
if __name__ == "__main__":
main()

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

@ -22,6 +22,8 @@ from mozbuild.frontend.reader import BuildReader
from mozbuild.test.backend.common import BackendTester
import mozpack.path as mozpath
class TestRecursiveMakeTraversal(unittest.TestCase):
def test_traversal(self):
@ -152,9 +154,9 @@ class TestRecursiveMakeBackend(BackendTester):
def test_basic(self):
"""Ensure the RecursiveMakeBackend works without error."""
env = self._consume('stub0', RecursiveMakeBackend)
self.assertTrue(os.path.exists(os.path.join(env.topobjdir,
self.assertTrue(os.path.exists(mozpath.join(env.topobjdir,
'backend.RecursiveMakeBackend')))
self.assertTrue(os.path.exists(os.path.join(env.topobjdir,
self.assertTrue(os.path.exists(mozpath.join(env.topobjdir,
'backend.RecursiveMakeBackend.pp')))
def test_output_files(self):
@ -164,8 +166,8 @@ class TestRecursiveMakeBackend(BackendTester):
expected = ['', 'dir1', 'dir2']
for d in expected:
out_makefile = os.path.join(env.topobjdir, d, 'Makefile')
out_backend = os.path.join(env.topobjdir, d, 'backend.mk')
out_makefile = mozpath.join(env.topobjdir, d, 'Makefile')
out_backend = mozpath.join(env.topobjdir, d, 'backend.mk')
self.assertTrue(os.path.exists(out_makefile))
self.assertTrue(os.path.exists(out_backend))
@ -174,7 +176,7 @@ class TestRecursiveMakeBackend(BackendTester):
"""Ensure Makefile.in is converted properly."""
env = self._consume('stub0', RecursiveMakeBackend)
p = os.path.join(env.topobjdir, 'Makefile')
p = mozpath.join(env.topobjdir, 'Makefile')
lines = [l.strip() for l in open(p, 'rt').readlines()[1:] if not l.startswith('#')]
self.assertEqual(lines, [
@ -194,7 +196,7 @@ class TestRecursiveMakeBackend(BackendTester):
"""Ensure missing Makefile.in results in Makefile creation."""
env = self._consume('stub0', RecursiveMakeBackend)
p = os.path.join(env.topobjdir, 'dir2', 'Makefile')
p = mozpath.join(env.topobjdir, 'dir2', 'Makefile')
self.assertTrue(os.path.exists(p))
lines = [l.strip() for l in open(p, 'rt').readlines()]
@ -206,7 +208,7 @@ class TestRecursiveMakeBackend(BackendTester):
"""Ensure backend.mk file is written out properly."""
env = self._consume('stub0', RecursiveMakeBackend)
p = os.path.join(env.topobjdir, 'backend.mk')
p = mozpath.join(env.topobjdir, 'backend.mk')
lines = [l.strip() for l in open(p, 'rt').readlines()[2:]]
self.assertEqual(lines, [
@ -221,8 +223,8 @@ class TestRecursiveMakeBackend(BackendTester):
env = self._consume('stub0', RecursiveMakeBackend)
makefile_path = os.path.join(env.topobjdir, 'Makefile')
backend_path = os.path.join(env.topobjdir, 'backend.mk')
makefile_path = mozpath.join(env.topobjdir, 'Makefile')
backend_path = mozpath.join(env.topobjdir, 'backend.mk')
makefile_mtime = os.path.getmtime(makefile_path)
backend_mtime = os.path.getmtime(backend_path)
@ -238,7 +240,7 @@ class TestRecursiveMakeBackend(BackendTester):
"""Ensure we have make recursion into external make directories."""
env = self._consume('external_make_dirs', RecursiveMakeBackend)
backend_path = os.path.join(env.topobjdir, 'backend.mk')
backend_path = mozpath.join(env.topobjdir, 'backend.mk')
lines = [l.strip() for l in open(backend_path, 'rt').readlines()[2:]]
self.assertEqual(lines, [
'MOZBUILD_DERIVED := 1',
@ -252,7 +254,7 @@ class TestRecursiveMakeBackend(BackendTester):
"""Ensure substituted config files are produced."""
env = self._consume('substitute_config_files', RecursiveMakeBackend)
p = os.path.join(env.topobjdir, 'foo')
p = mozpath.join(env.topobjdir, 'foo')
self.assertTrue(os.path.exists(p))
lines = [l.strip() for l in open(p, 'rt').readlines()]
self.assertEqual(lines, [
@ -263,7 +265,7 @@ class TestRecursiveMakeBackend(BackendTester):
"""Ensure variable passthru is written out correctly."""
env = self._consume('variable_passthru', RecursiveMakeBackend)
backend_path = os.path.join(env.topobjdir, 'backend.mk')
backend_path = mozpath.join(env.topobjdir, 'backend.mk')
lines = [l.strip() for l in open(backend_path, 'rt').readlines()[2:]]
expected = {
@ -346,7 +348,7 @@ class TestRecursiveMakeBackend(BackendTester):
env = self._consume('exports', RecursiveMakeBackend)
# EXPORTS files should appear in the dist_include install manifest.
m = InstallManifest(path=os.path.join(env.topobjdir,
m = InstallManifest(path=mozpath.join(env.topobjdir,
'_build_manifests', 'install', 'dist_include'))
self.assertEqual(len(m), 7)
self.assertIn('foo.h', m)
@ -357,9 +359,9 @@ class TestRecursiveMakeBackend(BackendTester):
"""Ensure test manifests get turned into files."""
env = self._consume('test-manifests-written', RecursiveMakeBackend)
tests_dir = os.path.join(env.topobjdir, '_tests')
m_master = os.path.join(tests_dir, 'testing', 'mochitest', 'tests', 'mochitest.ini')
x_master = os.path.join(tests_dir, 'xpcshell', 'xpcshell.ini')
tests_dir = mozpath.join(env.topobjdir, '_tests')
m_master = mozpath.join(tests_dir, 'testing', 'mochitest', 'tests', 'mochitest.ini')
x_master = mozpath.join(tests_dir, 'xpcshell', 'xpcshell.ini')
self.assertTrue(os.path.exists(m_master))
self.assertTrue(os.path.exists(x_master))
@ -371,7 +373,7 @@ class TestRecursiveMakeBackend(BackendTester):
'[include:xpcshell.ini]',
])
all_tests_path = os.path.join(env.topobjdir, 'all-tests.json')
all_tests_path = mozpath.join(env.topobjdir, 'all-tests.json')
self.assertTrue(os.path.exists(all_tests_path))
with open(all_tests_path, 'rt') as fh:
@ -385,7 +387,7 @@ class TestRecursiveMakeBackend(BackendTester):
def test_test_manifest_pattern_matches_recorded(self):
"""Pattern matches in test manifests' support-files should be recorded."""
env = self._consume('test-manifests-written', RecursiveMakeBackend)
m = InstallManifest(path=os.path.join(env.topobjdir,
m = InstallManifest(path=mozpath.join(env.topobjdir,
'_build_manifests', 'install', 'tests'))
# This is not the most robust test in the world, but it gets the job
@ -399,34 +401,34 @@ class TestRecursiveMakeBackend(BackendTester):
env = self._consume('xpidl', RecursiveMakeBackend)
# Install manifests should contain entries.
install_dir = os.path.join(env.topobjdir, '_build_manifests',
install_dir = mozpath.join(env.topobjdir, '_build_manifests',
'install')
self.assertTrue(os.path.isfile(os.path.join(install_dir, 'dist_idl')))
self.assertTrue(os.path.isfile(os.path.join(install_dir, 'xpidl')))
self.assertTrue(os.path.isfile(mozpath.join(install_dir, 'dist_idl')))
self.assertTrue(os.path.isfile(mozpath.join(install_dir, 'xpidl')))
m = InstallManifest(path=os.path.join(install_dir, 'dist_idl'))
m = InstallManifest(path=mozpath.join(install_dir, 'dist_idl'))
self.assertEqual(len(m), 2)
self.assertIn('bar.idl', m)
self.assertIn('foo.idl', m)
m = InstallManifest(path=os.path.join(install_dir, 'xpidl'))
m = InstallManifest(path=mozpath.join(install_dir, 'xpidl'))
self.assertIn('.deps/my_module.pp', m)
self.assertIn('xpt/my_module.xpt', m)
m = InstallManifest(path=os.path.join(install_dir, 'dist_include'))
m = InstallManifest(path=mozpath.join(install_dir, 'dist_include'))
self.assertIn('foo.h', m)
p = os.path.join(env.topobjdir, 'config/makefiles/xpidl')
p = mozpath.join(env.topobjdir, 'config/makefiles/xpidl')
self.assertTrue(os.path.isdir(p))
self.assertTrue(os.path.isfile(os.path.join(p, 'Makefile')))
self.assertTrue(os.path.isfile(mozpath.join(p, 'Makefile')))
def test_old_install_manifest_deleted(self):
# Simulate an install manifest from a previous backend version. Ensure
# it is deleted.
env = self._get_environment('stub0')
purge_dir = os.path.join(env.topobjdir, '_build_manifests', 'install')
manifest_path = os.path.join(purge_dir, 'old_manifest')
purge_dir = mozpath.join(env.topobjdir, '_build_manifests', 'install')
manifest_path = mozpath.join(purge_dir, 'old_manifest')
os.makedirs(purge_dir)
m = InstallManifest()
m.write(path=manifest_path)
@ -444,12 +446,12 @@ class TestRecursiveMakeBackend(BackendTester):
m.add_symlink(__file__, 'self')
backend.consume(objs)
man_dir = os.path.join(env.topobjdir, '_build_manifests', 'install')
man_dir = mozpath.join(env.topobjdir, '_build_manifests', 'install')
self.assertTrue(os.path.isdir(man_dir))
expected = ['testing']
for e in expected:
full = os.path.join(man_dir, e)
full = mozpath.join(man_dir, e)
self.assertTrue(os.path.exists(full))
m2 = InstallManifest(path=full)
@ -459,7 +461,7 @@ class TestRecursiveMakeBackend(BackendTester):
"""Test that IPDL_SOURCES are written to ipdlsrcs.mk correctly."""
env = self._consume('ipdl_sources', RecursiveMakeBackend)
manifest_path = os.path.join(env.topobjdir,
manifest_path = mozpath.join(env.topobjdir,
'ipc', 'ipdl', 'ipdlsrcs.mk')
lines = [l.strip() for l in open(manifest_path, 'rt').readlines()]
@ -481,7 +483,7 @@ class TestRecursiveMakeBackend(BackendTester):
"""Test that DEFINES are written to backend.mk correctly."""
env = self._consume('defines', RecursiveMakeBackend)
backend_path = os.path.join(env.topobjdir, 'backend.mk')
backend_path = mozpath.join(env.topobjdir, 'backend.mk')
lines = [l.strip() for l in open(backend_path, 'rt').readlines()[2:]]
var = 'DEFINES'
@ -494,7 +496,7 @@ class TestRecursiveMakeBackend(BackendTester):
"""Test that LOCAL_INCLUDES are written to backend.mk correctly."""
env = self._consume('local_includes', RecursiveMakeBackend)
backend_path = os.path.join(env.topobjdir, 'backend.mk')
backend_path = mozpath.join(env.topobjdir, 'backend.mk')
lines = [l.strip() for l in open(backend_path, 'rt').readlines()[2:]]
expected = [
@ -509,7 +511,7 @@ class TestRecursiveMakeBackend(BackendTester):
"""Test that GENERATED_INCLUDES are written to backend.mk correctly."""
env = self._consume('generated_includes', RecursiveMakeBackend)
backend_path = os.path.join(env.topobjdir, 'backend.mk')
backend_path = mozpath.join(env.topobjdir, 'backend.mk')
lines = [l.strip() for l in open(backend_path, 'rt').readlines()[2:]]
topobjdir = env.topobjdir.replace('\\', '/')
@ -530,30 +532,60 @@ class TestRecursiveMakeBackend(BackendTester):
print([x for x in os.walk(env.topobjdir)])
expected = dict()
expected[env.topobjdir] = []
expected[os.path.join(env.topobjdir, 'both')] = [
expected[mozpath.join(env.topobjdir, 'both')] = [
'XPI_NAME = mycrazyxpi',
'DIST_SUBDIR = asubdir',
final_target_rule
]
expected[os.path.join(env.topobjdir, 'dist-subdir')] = [
expected[mozpath.join(env.topobjdir, 'dist-subdir')] = [
'DIST_SUBDIR = asubdir',
final_target_rule
]
expected[os.path.join(env.topobjdir, 'xpi-name')] = [
expected[mozpath.join(env.topobjdir, 'xpi-name')] = [
'XPI_NAME = mycrazyxpi',
final_target_rule
]
expected[os.path.join(env.topobjdir, 'final-target')] = [
expected[mozpath.join(env.topobjdir, 'final-target')] = [
'FINAL_TARGET = $(DEPTH)/random-final-target'
]
for key, expected_rules in expected.iteritems():
backend_path = os.path.join(key, 'backend.mk')
backend_path = mozpath.join(key, 'backend.mk')
lines = [l.strip() for l in open(backend_path, 'rt').readlines()[2:]]
found = [str for str in lines if
str.startswith('FINAL_TARGET') or str.startswith('XPI_NAME') or
str.startswith('DIST_SUBDIR')]
self.assertEqual(found, expected_rules)
def test_config(self):
"""Test that CONFIGURE_SUBST_FILES and CONFIGURE_DEFINE_FILES are
properly handled."""
env = self._consume('test_config', RecursiveMakeBackend)
self.assertEqual(
open(os.path.join(env.topobjdir, 'file'), 'r').readlines(), [
'#ifdef foo\n',
'bar baz\n',
'@bar@\n',
])
self.assertEqual(
open(os.path.join(env.topobjdir, 'file.h'), 'r').readlines(), [
'/* Comment */\n',
'#define foo\n',
'#define foo baz qux\n',
'#define foo baz qux\n',
'#define bar\n',
'#define bar 42\n',
'/* #undef bar */\n',
'\n',
'# define baz 1\n',
'\n',
'#ifdef foo\n',
'# define foo baz qux\n',
'# define foo baz qux\n',
' # define foo baz qux \n',
'#endif\n',
])
if __name__ == '__main__':
main()

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

@ -31,14 +31,16 @@ from mozbuild.frontend.reader import (
from mozbuild.test.common import MockConfig
import mozpack.path as mozpath
data_path = os.path.abspath(os.path.dirname(__file__))
data_path = os.path.join(data_path, 'data')
data_path = mozpath.abspath(mozpath.dirname(__file__))
data_path = mozpath.join(data_path, 'data')
class TestEmitterBasic(unittest.TestCase):
def reader(self, name):
config = MockConfig(os.path.join(data_path, name), extra_substs=dict(
config = MockConfig(mozpath.join(data_path, name), extra_substs=dict(
ENABLE_TESTS='1',
BIN_SUFFIX='.prog',
))
@ -121,12 +123,12 @@ class TestEmitterBasic(unittest.TestCase):
self.assertIsInstance(objs[1], ConfigFileSubstitution)
self.assertIsInstance(objs[2], ConfigFileSubstitution)
topobjdir = os.path.abspath(reader.config.topobjdir)
topobjdir = mozpath.abspath(reader.config.topobjdir)
self.assertEqual(objs[1].relpath, 'foo')
self.assertEqual(os.path.normpath(objs[1].output_path),
os.path.normpath(os.path.join(topobjdir, 'foo')))
self.assertEqual(os.path.normpath(objs[2].output_path),
os.path.normpath(os.path.join(topobjdir, 'bar')))
self.assertEqual(mozpath.normpath(objs[1].output_path),
mozpath.normpath(mozpath.join(topobjdir, 'foo')))
self.assertEqual(mozpath.normpath(objs[2].output_path),
mozpath.normpath(mozpath.join(topobjdir, 'bar')))
def test_variable_passthru(self):
reader = self.reader('variable-passthru')
@ -300,13 +302,13 @@ class TestEmitterBasic(unittest.TestCase):
}
for o in objs:
m = metadata[os.path.basename(o.manifest_relpath)]
m = metadata[mozpath.basename(o.manifest_relpath)]
self.assertTrue(o.path.startswith(o.directory))
self.assertEqual(o.flavor, m['flavor'])
self.assertEqual(o.dupe_manifest, m.get('dupe', False))
external_normalized = set(os.path.basename(p) for p in
external_normalized = set(mozpath.basename(p) for p in
o.external_installs)
self.assertEqual(external_normalized, m.get('external', set()))
@ -341,7 +343,7 @@ class TestEmitterBasic(unittest.TestCase):
o = objs[0]
self.assertEqual(o.flavor, 'mochitest')
basenames = set(os.path.basename(k) for k in o.installs.keys())
basenames = set(mozpath.basename(k) for k in o.installs.keys())
self.assertEqual(basenames, {'mochitest.ini', 'test_active.html'})
def test_ipdl_sources(self):

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

@ -15,19 +15,21 @@ from mozbuild.frontend.reader import BuildReader
from mozbuild.test.common import MockConfig
import mozpack.path as mozpath
if sys.version_info.major == 2:
text_type = 'unicode'
else:
text_type = 'str'
data_path = os.path.abspath(os.path.dirname(__file__))
data_path = os.path.join(data_path, 'data')
data_path = mozpath.abspath(mozpath.dirname(__file__))
data_path = mozpath.join(data_path, 'data')
class TestBuildReader(unittest.TestCase):
def config(self, name, **kwargs):
path = os.path.join(data_path, name)
path = mozpath.join(data_path, name)
return MockConfig(path, **kwargs)
@ -40,7 +42,7 @@ class TestBuildReader(unittest.TestCase):
return BuildReader(config)
def file_path(self, name, *args):
return os.path.join(data_path, name, *args)
return mozpath.join(data_path, name, *args)
def test_dirs_traversal_simple(self):
reader = self.reader('traversal-simple')
@ -52,7 +54,7 @@ class TestBuildReader(unittest.TestCase):
def test_dirs_traversal_no_descend(self):
reader = self.reader('traversal-simple')
path = os.path.join(reader.topsrcdir, 'moz.build')
path = mozpath.join(reader.topsrcdir, 'moz.build')
self.assertTrue(os.path.exists(path))
sandboxes = list(reader.read_mozbuild(path,

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

@ -28,9 +28,10 @@ from mozbuild.frontend.sandbox_symbols import (
from mozbuild.test.common import MockConfig
import mozpack.path as mozpath
test_data_path = os.path.abspath(os.path.dirname(__file__))
test_data_path = os.path.join(test_data_path, 'data')
test_data_path = mozpath.abspath(mozpath.dirname(__file__))
test_data_path = mozpath.join(test_data_path, 'data')
class TestSandbox(unittest.TestCase):
@ -38,7 +39,7 @@ class TestSandbox(unittest.TestCase):
config = None
if data_path is not None:
config = MockConfig(os.path.join(test_data_path, data_path))
config = MockConfig(mozpath.join(test_data_path, data_path))
else:
config = MockConfig()
@ -50,11 +51,11 @@ class TestSandbox(unittest.TestCase):
self.assertEqual(sandbox['TOPSRCDIR'], config.topsrcdir)
self.assertEqual(sandbox['TOPOBJDIR'],
os.path.abspath(config.topobjdir))
mozpath.abspath(config.topobjdir))
self.assertEqual(sandbox['RELATIVEDIR'], '')
self.assertEqual(sandbox['SRCDIR'], config.topsrcdir)
self.assertEqual(sandbox['OBJDIR'],
os.path.abspath(config.topobjdir).replace(os.sep, '/'))
mozpath.abspath(config.topobjdir).replace(os.sep, '/'))
def test_symbol_presence(self):
# Ensure no discrepancies between the master symbol table and what's in
@ -79,7 +80,7 @@ class TestSandbox(unittest.TestCase):
self.assertEqual(sandbox['SRCDIR'], '/'.join([config.topsrcdir,
'foo/bar']))
self.assertEqual(sandbox['OBJDIR'],
os.path.abspath('/'.join([config.topobjdir, 'foo/bar'])).replace(os.sep, '/'))
mozpath.abspath('/'.join([config.topobjdir, 'foo/bar'])).replace(os.sep, '/'))
def test_config_access(self):
sandbox = self.sandbox()
@ -225,7 +226,7 @@ add_tier_dir('t1', 'bat', static=True)
self.assertEqual(sandbox['DIRS'], ['foo', 'bar'])
self.assertEqual(sandbox.main_path,
os.path.join(sandbox['TOPSRCDIR'], 'moz.build'))
mozpath.join(sandbox['TOPSRCDIR'], 'moz.build'))
self.assertEqual(len(sandbox.all_paths), 2)
def test_include_outside_topsrcdir(self):
@ -234,7 +235,7 @@ add_tier_dir('t1', 'bat', static=True)
with self.assertRaises(SandboxLoadError) as se:
sandbox.exec_file('relative.build')
expected = os.path.join(test_data_path, 'moz.build')
expected = mozpath.join(test_data_path, 'moz.build')
self.assertEqual(se.exception.illegal_path, expected)
def test_include_error_stack(self):
@ -252,7 +253,7 @@ add_tier_dir('t1', 'bat', static=True)
self.assertEqual(args[1], 'set_unknown')
self.assertEqual(args[2], 'ILLEGAL')
expected_stack = [os.path.join(sandbox.config.topsrcdir, p) for p in [
expected_stack = [mozpath.join(sandbox.config.topsrcdir, p) for p in [
'moz.build', 'included-1.build', 'included-2.build']]
self.assertEqual(e.file_stack, expected_stack)

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

@ -28,9 +28,12 @@ def relpath(path, start):
return '' if rel == '.' else rel
def abspath(path):
return normsep(os.path.abspath(path))
def join(*paths):
paths = [normsep(p) for p in paths]
return posixpath.join(*paths)
return normsep(os.path.join(*paths))
def normpath(path):