зеркало из https://github.com/mozilla/gecko-dev.git
merge mozilla-central to fx-team
This commit is contained in:
Коммит
1815ec2ba1
|
@ -1,4 +1,4 @@
|
|||
{
|
||||
"revision": "3014a433e3b78fa04aacb919c853fa220d309d70",
|
||||
"revision": "e3d925b497f5b996c9c397c200805fbcc62bc823",
|
||||
"repo_path": "/integration/gaia-central"
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* -*- Mode: js2; js2-basic-offset: 2; indent-tabs-mode: nil; -*- */
|
||||
/* -*- js2-basic-offset: 2; indent-tabs-mode: nil; -*- */
|
||||
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* -*- Mode: js2; js2-basic-offset: 2; indent-tabs-mode: nil; -*- */
|
||||
/* -*- js2-basic-offset: 2; indent-tabs-mode: nil; -*- */
|
||||
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* -*- Mode: js2; js2-basic-offset: 2; indent-tabs-mode: nil; -*- */
|
||||
/* -*- js2-basic-offset: 2; indent-tabs-mode: nil; -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
|
|
|
@ -44,7 +44,6 @@ public class CodeGenerator {
|
|||
"\n" +
|
||||
"using namespace mozilla;\n" +
|
||||
"void AndroidBridge::InitStubs(JNIEnv *jEnv) {\n" +
|
||||
" ALOG_BRIDGE(\"%s\", __PRETTY_FUNCTION__);\n" +
|
||||
" initInit();\n");
|
||||
// Now we write the various GetStaticMethodID calls here...
|
||||
|
||||
|
@ -124,8 +123,7 @@ public class CodeGenerator {
|
|||
wrapperMethodBodies.append('\n');
|
||||
wrapperMethodBodies.append(methodSignature);
|
||||
|
||||
wrapperMethodBodies.append(" {\n" +
|
||||
" ALOG_BRIDGE(\"%s\", __PRETTY_FUNCTION__);\n");
|
||||
wrapperMethodBodies.append(" {\n");
|
||||
|
||||
// Static stubs check the bridge instance has been created before trying to run.
|
||||
if (aIsStaticBridgeMethod) {
|
||||
|
@ -267,18 +265,15 @@ public class CodeGenerator {
|
|||
wrapperMethodBodies.append(" ");
|
||||
wrapperMethodBodies.append(Utils.getCReturnType(returnType));
|
||||
wrapperMethodBodies.append(" ret = static_cast<").append(Utils.getCReturnType(returnType)).append(">(env->PopLocalFrame(temp));\n" +
|
||||
" ALOG_BRIDGE(\"Exit of: %s\", __PRETTY_FUNCTION__);\n" +
|
||||
" return ret;\n");
|
||||
} else if (!returnType.getCanonicalName().equals("void")) {
|
||||
// If we're a primitive-returning function, just return the directly-obtained primative
|
||||
// from the call to Java.
|
||||
wrapperMethodBodies.append(" env->PopLocalFrame(NULL);\n" +
|
||||
" ALOG_BRIDGE(\"Exit of: %s\", __PRETTY_FUNCTION__);\n" +
|
||||
" return temp;\n");
|
||||
} else {
|
||||
// If we don't return anything, just pop the stack frame and move on with life.
|
||||
wrapperMethodBodies.append(" ALOG_BRIDGE(\"Exit of: %s\", __PRETTY_FUNCTION__);\n" +
|
||||
" env->PopLocalFrame(NULL);\n");
|
||||
wrapperMethodBodies.append(" env->PopLocalFrame(NULL);\n");
|
||||
}
|
||||
wrapperMethodBodies.append("}\n");
|
||||
}
|
||||
|
|
|
@ -10,12 +10,12 @@
|
|||
#include "nsDOMEventTargetHelper.h"
|
||||
#include "nsError.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "nsIDOMBlobEvent.h"
|
||||
#include "nsIDOMRecordErrorEvent.h"
|
||||
#include "nsTArray.h"
|
||||
#include "DOMMediaStream.h"
|
||||
#include "EncodedBufferCache.h"
|
||||
#include "nsIDOMFile.h"
|
||||
#include "mozilla/dom/BlobEvent.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
|
@ -310,20 +310,14 @@ MediaRecorder::CreateAndDispatchBlobEvent()
|
|||
return NS_ERROR_DOM_SECURITY_ERR;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDOMBlob> blob;
|
||||
blob = mEncodedBufferCache->ExtractBlob(mMimeType);
|
||||
|
||||
// create an event that uses the MessageEvent interface,
|
||||
// which does not bubble, is not cancelable, and has no default action
|
||||
nsCOMPtr<nsIDOMEvent> event;
|
||||
nsresult rv = NS_NewDOMBlobEvent(getter_AddRefs(event), this, nullptr, nullptr);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIDOMBlobEvent> blobEvent = do_QueryInterface(event);
|
||||
rv = blobEvent->InitBlobEvent(NS_LITERAL_STRING("dataavailable"),
|
||||
false, false, blob);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
BlobEventInitInitializer init;
|
||||
init.mBubbles = false;
|
||||
init.mCancelable = false;
|
||||
init.mData = mEncodedBufferCache->ExtractBlob(mMimeType);
|
||||
nsRefPtr<BlobEvent> event =
|
||||
BlobEvent::Constructor(this,
|
||||
NS_LITERAL_STRING("dataavailable"),
|
||||
init);
|
||||
event->SetTrusted(true);
|
||||
return DispatchDOMEvent(nullptr, event, nullptr, nullptr);
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include "DirectShowUtils.h"
|
||||
#include "MP3FrameParser.h"
|
||||
#include "prlog.h"
|
||||
#include <algorithm>
|
||||
|
||||
using namespace mozilla::media;
|
||||
|
||||
|
|
|
@ -39,14 +39,8 @@ NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(DOMSVGPathSeg)
|
|||
NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(DOMSVGPathSeg)
|
||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(DOMSVGPathSeg)
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(DOMSVGPathSeg)
|
||||
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
|
||||
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(DOMSVGPathSeg, AddRef)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(DOMSVGPathSeg, Release)
|
||||
|
||||
DOMSVGPathSeg::DOMSVGPathSeg(DOMSVGPathSegList *aList,
|
||||
uint32_t aListIndex,
|
||||
|
|
|
@ -15,14 +15,6 @@
|
|||
|
||||
class nsSVGElement;
|
||||
|
||||
// We make DOMSVGPathSeg a pseudo-interface to allow us to QI to it in order to
|
||||
// check that the objects that scripts pass to DOMSVGPathSegList methods are
|
||||
// our *native* path seg objects.
|
||||
//
|
||||
// {494A7566-DC26-40C8-9122-52ABD76870C4}
|
||||
#define MOZILLA_DOMSVGPATHSEG_IID \
|
||||
{ 0x494A7566, 0xDC26, 0x40C8, { 0x91, 0x22, 0x52, 0xAB, 0xD7, 0x68, 0x70, 0xC4 } }
|
||||
|
||||
#define MOZ_SVG_LIST_INDEX_BIT_COUNT 31
|
||||
|
||||
namespace mozilla {
|
||||
|
@ -92,13 +84,11 @@ namespace mozilla {
|
|||
* sub-classes (it does not), and the "internal counterpart" that we provide a
|
||||
* DOM wrapper for is a list of floats, not an instance of an internal class.
|
||||
*/
|
||||
class DOMSVGPathSeg : public nsISupports,
|
||||
public nsWrapperCache
|
||||
class DOMSVGPathSeg : public nsWrapperCache
|
||||
{
|
||||
public:
|
||||
NS_DECLARE_STATIC_IID_ACCESSOR(MOZILLA_DOMSVGPATHSEG_IID)
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(DOMSVGPathSeg)
|
||||
NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(DOMSVGPathSeg)
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(DOMSVGPathSeg)
|
||||
|
||||
/**
|
||||
* Unlike the other list classes, we hide our ctor (because no one should be
|
||||
|
@ -233,8 +223,6 @@ protected:
|
|||
uint32_t mIsAnimValItem:1; // uint32_t because MSVC won't pack otherwise
|
||||
};
|
||||
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(DOMSVGPathSeg, MOZILLA_DOMSVGPATHSEG_IID)
|
||||
|
||||
class DOMSVGPathSegClosePath
|
||||
: public DOMSVGPathSeg
|
||||
{
|
||||
|
|
|
@ -2579,10 +2579,11 @@ NotifyOffThreadScriptCompletedRunnable::Run()
|
|||
nsCOMPtr<nsIJSRuntimeService> svc = do_GetService("@mozilla.org/js/xpc/RuntimeService;1");
|
||||
NS_ENSURE_TRUE(svc, NS_ERROR_FAILURE);
|
||||
|
||||
JSRuntime *rt;
|
||||
svc->GetRuntime(&rt);
|
||||
NS_ENSURE_TRUE(svc, NS_ERROR_FAILURE);
|
||||
JSScript *script = JS::FinishOffThreadScript(NULL, rt, mToken);
|
||||
JSScript *script;
|
||||
{
|
||||
AutoSafeJSContext cx;
|
||||
script = JS::FinishOffThreadScript(cx, JS_GetRuntime(cx), mToken);
|
||||
}
|
||||
|
||||
return mReceiver->OnScriptCompileComplete(script, script ? NS_OK : NS_ERROR_FAILURE);
|
||||
}
|
||||
|
|
|
@ -1100,7 +1100,7 @@ Navigator::GetBattery(ErrorResult& aRv)
|
|||
return mBatteryManager;
|
||||
}
|
||||
|
||||
nsIDOMMozPowerManager*
|
||||
power::PowerManager*
|
||||
Navigator::GetMozPower(ErrorResult& aRv)
|
||||
{
|
||||
if (!mPowerManager) {
|
||||
|
|
|
@ -199,7 +199,7 @@ public:
|
|||
{
|
||||
aRv = GetBuildID(aBuildID);
|
||||
}
|
||||
nsIDOMMozPowerManager* GetMozPower(ErrorResult& aRv);
|
||||
power::PowerManager* GetMozPower(ErrorResult& aRv);
|
||||
bool JavaEnabled(ErrorResult& aRv);
|
||||
bool TaintEnabled()
|
||||
{
|
||||
|
|
|
@ -158,7 +158,6 @@
|
|||
#include "nsWrapperCacheInlines.h"
|
||||
#include "mozilla/dom/HTMLCollectionBinding.h"
|
||||
|
||||
#include "nsIDOMPowerManager.h"
|
||||
#include "nsIDOMWakeLock.h"
|
||||
#include "nsIDOMMobileMessageManager.h"
|
||||
#include "nsIDOMMozSmsMessage.h"
|
||||
|
@ -464,9 +463,6 @@ static nsDOMClassInfoData sClassInfoData[] = {
|
|||
DEFAULT_SCRIPTABLE_FLAGS |
|
||||
WINDOW_SCRIPTABLE_FLAGS)
|
||||
|
||||
NS_DEFINE_CLASSINFO_DATA(MozPowerManager, nsDOMGenericSH,
|
||||
DOM_DEFAULT_SCRIPTABLE_FLAGS)
|
||||
|
||||
NS_DEFINE_CLASSINFO_DATA(MozWakeLock, nsDOMGenericSH,
|
||||
DOM_DEFAULT_SCRIPTABLE_FLAGS)
|
||||
|
||||
|
@ -1280,10 +1276,6 @@ nsDOMClassInfo::Init()
|
|||
#endif
|
||||
DOM_CLASSINFO_MAP_END
|
||||
|
||||
DOM_CLASSINFO_MAP_BEGIN(MozPowerManager, nsIDOMMozPowerManager)
|
||||
DOM_CLASSINFO_MAP_ENTRY(nsIDOMMozPowerManager)
|
||||
DOM_CLASSINFO_MAP_END
|
||||
|
||||
DOM_CLASSINFO_MAP_BEGIN(MozWakeLock, nsIDOMMozWakeLock)
|
||||
DOM_CLASSINFO_MAP_ENTRY(nsIDOMMozWakeLock)
|
||||
DOM_CLASSINFO_MAP_END
|
||||
|
|
|
@ -88,7 +88,6 @@ DOMCI_CLASS(File)
|
|||
// DOM modal content window class, almost identical to Window
|
||||
DOMCI_CLASS(ModalContentWindow)
|
||||
|
||||
DOMCI_CLASS(MozPowerManager)
|
||||
DOMCI_CLASS(MozWakeLock)
|
||||
|
||||
DOMCI_CLASS(MozMobileMessageManager)
|
||||
|
|
|
@ -8266,7 +8266,7 @@ void
|
|||
nsGlobalWindow::ActivateOrDeactivate(bool aActivate)
|
||||
{
|
||||
// Set / unset mIsActive on the top level window, which is used for the
|
||||
// :-moz-window-inactive pseudoclass.
|
||||
// :-moz-window-inactive pseudoclass, and its sheet (if any).
|
||||
nsCOMPtr<nsIWidget> mainWidget = GetMainWidget();
|
||||
if (!mainWidget)
|
||||
return;
|
||||
|
@ -8278,15 +8278,19 @@ nsGlobalWindow::ActivateOrDeactivate(bool aActivate)
|
|||
topLevelWidget = mainWidget;
|
||||
}
|
||||
|
||||
// Get the top level widget's nsGlobalWindow
|
||||
nsCOMPtr<nsIDOMWindow> topLevelWindow;
|
||||
if (topLevelWidget == mainWidget) {
|
||||
topLevelWindow = static_cast<nsIDOMWindow*>(this);
|
||||
} else {
|
||||
nsCOMPtr<nsPIDOMWindow> piMainWindow(
|
||||
do_QueryInterface(static_cast<nsIDOMWindow*>(this)));
|
||||
piMainWindow->SetActive(aActivate);
|
||||
|
||||
if (mainWidget != topLevelWidget) {
|
||||
// This is a workaround for the following problem:
|
||||
// When a window with an open sheet loses focus, only the sheet window
|
||||
// receives the NS_DEACTIVATE event. However, it's not the sheet that
|
||||
// should lose the active styling, but the containing top level window.
|
||||
// When a window with an open sheet gains or loses focus, only the sheet
|
||||
// window receives the NS_ACTIVATE/NS_DEACTIVATE event. However the
|
||||
// styling of the containing top level window also needs to change. We
|
||||
// get around this by calling nsPIDOMWindow::SetActive() on both windows.
|
||||
|
||||
// Get the top level widget's nsGlobalWindow
|
||||
nsCOMPtr<nsIDOMWindow> topLevelWindow;
|
||||
|
||||
// widgetListener should be a nsXULWindow
|
||||
nsIWidgetListener* listener = topLevelWidget->GetWidgetListener();
|
||||
|
@ -8295,10 +8299,11 @@ nsGlobalWindow::ActivateOrDeactivate(bool aActivate)
|
|||
nsCOMPtr<nsIInterfaceRequestor> req(do_QueryInterface(window));
|
||||
topLevelWindow = do_GetInterface(req);
|
||||
}
|
||||
}
|
||||
if (topLevelWindow) {
|
||||
nsCOMPtr<nsPIDOMWindow> piWin(do_QueryInterface(topLevelWindow));
|
||||
piWin->SetActive(aActivate);
|
||||
|
||||
if (topLevelWindow) {
|
||||
nsCOMPtr<nsPIDOMWindow> piWin(do_QueryInterface(topLevelWindow));
|
||||
piWin->SetActive(aActivate);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -5,13 +5,14 @@
|
|||
import os
|
||||
import cPickle
|
||||
from Configuration import Configuration
|
||||
from Codegen import CGBindingRoot, replaceFileIfChanged
|
||||
from Codegen import CGBindingRoot, replaceFileIfChanged, CGEventRoot
|
||||
from mozbuild.makeutil import Makefile
|
||||
from mozbuild.pythonutil import iter_modules_in_path
|
||||
from buildconfig import topsrcdir
|
||||
|
||||
|
||||
def generate_binding_files(config, outputprefix, srcprefix, webidlfile):
|
||||
def generate_binding_files(config, outputprefix, srcprefix, webidlfile,
|
||||
generatedEventsWebIDLFiles):
|
||||
"""
|
||||
|config| Is the configuration object.
|
||||
|outputprefix| is a prefix to use for the header guards and filename.
|
||||
|
@ -22,6 +23,12 @@ def generate_binding_files(config, outputprefix, srcprefix, webidlfile):
|
|||
replaceFileIfChanged(outputprefix + ".h", root.declare())
|
||||
replaceFileIfChanged(outputprefix + ".cpp", root.define())
|
||||
|
||||
if webidlfile in generatedEventsWebIDLFiles:
|
||||
eventName = webidlfile[:-len(".webidl")]
|
||||
generatedEvent = CGEventRoot(config, eventName)
|
||||
replaceFileIfChanged(eventName + ".h", generatedEvent.declare())
|
||||
replaceFileIfChanged(eventName + ".cpp", generatedEvent.define())
|
||||
|
||||
mk = Makefile()
|
||||
# NOTE: it's VERY important that we output dependencies for the FooBinding
|
||||
# file here, not for the header or generated cpp file. These dependencies
|
||||
|
@ -59,7 +66,8 @@ def main():
|
|||
file.close()
|
||||
return contents
|
||||
allWebIDLFiles = readFile(args[2]).split()
|
||||
changedDeps = readFile(args[3]).split()
|
||||
generatedEventsWebIDLFiles = readFile(args[3]).split()
|
||||
changedDeps = readFile(args[4]).split()
|
||||
|
||||
if all(f.endswith("Binding") or f == "ParserResults.pkl" for f in changedDeps):
|
||||
toRegenerate = filter(lambda f: f.endswith("Binding"), changedDeps)
|
||||
|
@ -83,7 +91,8 @@ def main():
|
|||
for webIDLFile in toRegenerate:
|
||||
assert webIDLFile.endswith(".webidl")
|
||||
outputPrefix = webIDLFile[:-len(".webidl")] + "Binding"
|
||||
generate_binding_files(config, outputPrefix, srcPrefix, webIDLFile);
|
||||
generate_binding_files(config, outputPrefix, srcPrefix, webIDLFile,
|
||||
generatedEventsWebIDLFiles);
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
|
|
@ -1792,7 +1792,9 @@ GlobalObject::GlobalObject(JSContext* aCx, JSObject* aObject)
|
|||
nsISupports*
|
||||
GlobalObject::GetAsSupports() const
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
if (!NS_IsMainThread()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (mGlobalObject) {
|
||||
return mGlobalObject;
|
||||
|
|
|
@ -1395,7 +1395,7 @@ WantsQueryInterface<T, true>
|
|||
{
|
||||
static bool Enabled(JSContext* aCx, JSObject* aGlobal)
|
||||
{
|
||||
return IsChromeOrXBL(aCx, aGlobal);
|
||||
return NS_IsMainThread() && IsChromeOrXBL(aCx, aGlobal);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -776,8 +776,8 @@ DOMInterfaces = {
|
|||
'nativeType': 'nsDOMAttributeMap',
|
||||
},
|
||||
|
||||
'MozTimeManager': {
|
||||
'nativeType': 'mozilla::dom::time::TimeManager',
|
||||
'MozPowerManager': {
|
||||
'nativeType': 'mozilla::dom::power::PowerManager',
|
||||
},
|
||||
|
||||
'MozStkCommandEvent' : {
|
||||
|
@ -785,6 +785,10 @@ DOMInterfaces = {
|
|||
'headerFile': 'StkCommandEvent.h',
|
||||
},
|
||||
|
||||
'MozTimeManager': {
|
||||
'nativeType': 'mozilla::dom::time::TimeManager',
|
||||
},
|
||||
|
||||
'MozVoicemail': {
|
||||
'nativeType': 'mozilla::dom::Voicemail',
|
||||
},
|
||||
|
@ -1799,7 +1803,6 @@ addExternalIface('MozMediaStreamOptions', nativeType='nsIMediaStreamOptions',
|
|||
addExternalIface('MozMobileConnection', headerFile='nsIDOMMobileConnection.h')
|
||||
addExternalIface('MozMobileMessageManager', headerFile='nsIDOMMobileMessageManager.h')
|
||||
addExternalIface('MozObserver', nativeType='nsIObserver', notflattened=True)
|
||||
addExternalIface('MozPowerManager', headerFile='nsIDOMPowerManager.h')
|
||||
addExternalIface('MozRDFCompositeDataSource', nativeType='nsIRDFCompositeDataSource',
|
||||
notflattened=True)
|
||||
addExternalIface('MozRDFResource', nativeType='nsIRDFResource', notflattened=True)
|
||||
|
@ -1810,6 +1813,7 @@ addExternalIface('MozTreeColumn', nativeType='nsITreeColumn',
|
|||
headerFile='nsITreeColumns.h')
|
||||
addExternalIface('MozVoicemailStatus')
|
||||
addExternalIface('MozWakeLock', headerFile='nsIDOMWakeLock.h')
|
||||
addExternalIface('MozWakeLockListener', headerFile='nsIDOMWakeLockListener.h')
|
||||
addExternalIface('MozXULTemplateBuilder', nativeType='nsIXULTemplateBuilder')
|
||||
addExternalIface('nsIControllers', nativeType='nsIControllers')
|
||||
addExternalIface('nsIInputStreamCallback', nativeType='nsIInputStreamCallback',
|
||||
|
|
|
@ -9289,7 +9289,7 @@ class CGBindingImplClass(CGClass):
|
|||
"""
|
||||
Common codegen for generating a C++ implementation of a WebIDL interface
|
||||
"""
|
||||
def __init__(self, descriptor, cgMethod, cgGetter, cgSetter):
|
||||
def __init__(self, descriptor, cgMethod, cgGetter, cgSetter, wantGetParent=True):
|
||||
"""
|
||||
cgMethod, cgGetter and cgSetter are classes used to codegen methods,
|
||||
getters and setters.
|
||||
|
@ -9404,12 +9404,13 @@ class CGBindingImplClass(CGClass):
|
|||
breakAfterReturnDecl=" ",
|
||||
override=descriptor.wrapperCache,
|
||||
body=self.getWrapObjectBody()))
|
||||
self.methodDecls.insert(0,
|
||||
ClassMethod("GetParentObject",
|
||||
self.getGetParentObjectReturnType(),
|
||||
[], const=True,
|
||||
breakAfterReturnDecl=" ",
|
||||
body=self.getGetParentObjectBody()))
|
||||
if wantGetParent:
|
||||
self.methodDecls.insert(0,
|
||||
ClassMethod("GetParentObject",
|
||||
self.getGetParentObjectReturnType(),
|
||||
[], const=True,
|
||||
breakAfterReturnDecl=" ",
|
||||
body=self.getGetParentObjectBody()))
|
||||
|
||||
# Invoke CGClass.__init__ in any subclasses afterwards to do the actual codegen.
|
||||
|
||||
|
@ -10607,3 +10608,370 @@ struct PrototypeTraits;
|
|||
# Done.
|
||||
return curr
|
||||
|
||||
# Code generator for simple events
|
||||
|
||||
class CGEventGetter(CGNativeMember):
|
||||
def __init__(self, descriptor, attr):
|
||||
ea = descriptor.getExtendedAttributes(attr, getter=True)
|
||||
ea.append('resultNotAddRefed')
|
||||
CGNativeMember.__init__(self, descriptor, attr,
|
||||
CGSpecializedGetter.makeNativeName(descriptor,
|
||||
attr),
|
||||
(attr.type, []),
|
||||
ea)
|
||||
|
||||
def retval(self, type):
|
||||
if type.isPrimitive() and type.tag() in builtinNames:
|
||||
result = CGGeneric(builtinNames[type.tag()])
|
||||
if type.nullable():
|
||||
result = CGTemplatedType("Nullable", result)
|
||||
return result.define()
|
||||
if type.isDOMString():
|
||||
return "void"
|
||||
if type.isByteString():
|
||||
return "void"
|
||||
if type.isEnum():
|
||||
enumName = type.unroll().inner.identifier.name
|
||||
if type.nullable():
|
||||
enumName = CGTemplatedType("Nullable",
|
||||
CGGeneric(enumName)).define()
|
||||
return enumName
|
||||
if type.isGeckoInterface():
|
||||
iface = type.unroll().inner;
|
||||
nativeType = self.descriptorProvider.getDescriptor(
|
||||
iface.identifier.name).nativeType
|
||||
# Now trim off unnecessary namespaces
|
||||
nativeType = nativeType.split("::")
|
||||
if nativeType[0] == "mozilla":
|
||||
nativeType.pop(0)
|
||||
if nativeType[0] == "dom":
|
||||
nativeType.pop(0)
|
||||
return CGWrapper(CGGeneric("::".join(nativeType)), post="*").define()
|
||||
if type.isAny():
|
||||
return "JS::Value"
|
||||
if type.isObject():
|
||||
return "JSObject*"
|
||||
if type.isSpiderMonkeyInterface():
|
||||
return "JSObject*"
|
||||
raise TypeError("Don't know how to declare return value for %s" %
|
||||
type)
|
||||
|
||||
def getArgs(self, returnType, argList):
|
||||
args = [self.getArg(arg) for arg in argList]
|
||||
if returnType.isDOMString():
|
||||
args.append(Argument("nsString&", "aRetVal"))
|
||||
elif returnType.isByteString():
|
||||
args.append(Argument("nsCString&", "aRetVal"))
|
||||
if needCx(returnType, argList, self.extendedAttrs,
|
||||
self.descriptorProvider, True):
|
||||
args.insert(0, Argument("JSContext*", "aCx"))
|
||||
if not 'infallible' in self.extendedAttrs:
|
||||
raise TypeError("Event code generator does not support [Throws]!")
|
||||
return args
|
||||
|
||||
def getMethodBody(self):
|
||||
type = self.member.type
|
||||
memberName = CGDictionary.makeMemberName(self.member.identifier.name)
|
||||
if (type.isPrimitive() and type.tag() in builtinNames) or type.isEnum() or type.isGeckoInterface():
|
||||
return " return " + memberName + ";"
|
||||
if type.isDOMString() or type.isByteString():
|
||||
return " aRetVal = " + memberName + ";";
|
||||
if type.isSpiderMonkeyInterface() or type.isObject():
|
||||
ret = " if (%s) {\n" % memberName
|
||||
ret += " JS::ExposeObjectToActiveJS(%s);\n" % memberName
|
||||
ret += " }\n"
|
||||
ret += " return " + memberName + ";"
|
||||
return ret;
|
||||
if type.isAny():
|
||||
ret = " JS::ExposeValueToActiveJS("+ memberName + ");\n"
|
||||
ret += " return " + memberName + ";"
|
||||
return ret;
|
||||
raise TypeError("Event code generator does not support this type!")
|
||||
|
||||
def define(self, cgClass):
|
||||
ret = self.retval(self.member.type);
|
||||
methodName = self.descriptorProvider.name + '::' + self.name
|
||||
args = (', '.join([a.declare() for a in self.args]))
|
||||
body = self.getMethodBody()
|
||||
return ret + "\n" + methodName + '(' + args + ') const\n{\n' + body + "\n}\n"
|
||||
|
||||
class CGEventSetter(CGNativeMember):
|
||||
def __init__(self):
|
||||
raise TypeError("Event code generator does not support setters!")
|
||||
|
||||
class CGEventMethod(CGNativeMember):
|
||||
def __init__(self, descriptor, method, signature, isConstructor, breakAfter=True):
|
||||
if not isConstructor:
|
||||
raise TypeError("Event code generator does not support methods!")
|
||||
self.wantsConstructorForNativeCaller = True
|
||||
CGNativeMember.__init__(self, descriptor, method,
|
||||
CGSpecializedMethod.makeNativeName(descriptor,
|
||||
method),
|
||||
signature,
|
||||
descriptor.getExtendedAttributes(method),
|
||||
breakAfter=breakAfter,
|
||||
variadicIsSequence=True)
|
||||
self.originalArgs = list(self.args)
|
||||
|
||||
def getArgs(self, returnType, argList):
|
||||
args = [self.getArg(arg) for arg in argList]
|
||||
return args
|
||||
|
||||
def getArg(self, arg):
|
||||
(decl, ref) = self.getArgType(arg.type,
|
||||
arg.optional and not arg.defaultValue,
|
||||
"Variadic" if arg.variadic else False)
|
||||
if ref:
|
||||
decl = CGWrapper(decl, pre="const ", post="&")
|
||||
|
||||
name = arg.identifier.name
|
||||
name = "a" + name[0].upper() + name[1:]
|
||||
return Argument(decl.define(), name)
|
||||
|
||||
def declare(self, cgClass):
|
||||
self.args = list(self.originalArgs)
|
||||
self.args.insert(0, Argument("mozilla::dom::EventTarget*", "aOwner"))
|
||||
constructorForNativeCaller = CGNativeMember.declare(self, cgClass) + "\n"
|
||||
self.args = list(self.originalArgs)
|
||||
if needCx(None, self.descriptorProvider.interface.members, [], self.descriptorProvider, True):
|
||||
self.args.insert(0, Argument("JSContext*", "aCx"))
|
||||
self.args.insert(0, Argument("const GlobalObject&", "aGlobal"))
|
||||
self.args.append(Argument('ErrorResult&', 'aRv'))
|
||||
return constructorForNativeCaller + CGNativeMember.declare(self, cgClass)
|
||||
|
||||
def define(self, cgClass):
|
||||
self.args = list(self.originalArgs)
|
||||
members = ""
|
||||
holdJS = ""
|
||||
for m in self.descriptorProvider.interface.members:
|
||||
if m.isAttr():
|
||||
name = CGDictionary.makeMemberName(m.identifier.name)
|
||||
members += "e->%s = %s.%s;\n" % (name, self.args[1].name, name)
|
||||
if m.type.isAny() or m.type.isObject() or m.type.isSpiderMonkeyInterface():
|
||||
holdJS = "mozilla::HoldJSObjects(e.get());\n"
|
||||
|
||||
self.body = (
|
||||
"nsRefPtr<${nativeType}> e = new ${nativeType}(aOwner);\n"
|
||||
"bool trusted = e->Init(aOwner);\n"
|
||||
"e->InitEvent(${eventType}, ${eventInit}.mBubbles, ${eventInit}.mCancelable);\n"
|
||||
"${members}"
|
||||
"e->SetTrusted(trusted);\n"
|
||||
"${holdJS}"
|
||||
"return e.forget();"
|
||||
)
|
||||
self.body = string.Template(self.body).substitute(
|
||||
{
|
||||
"nativeType": self.descriptorProvider.nativeType.split('::')[-1],
|
||||
"eventType": self.args[0].name,
|
||||
"eventInit": self.args[1].name,
|
||||
"members": members,
|
||||
"holdJS": holdJS
|
||||
})
|
||||
|
||||
self.args.insert(0, Argument("mozilla::dom::EventTarget*", "aOwner"))
|
||||
constructorForNativeCaller = CGNativeMember.define(self, cgClass) + "\n"
|
||||
self.args = list(self.originalArgs)
|
||||
self.body = (
|
||||
"nsCOMPtr<mozilla::dom::EventTarget> owner = do_QueryInterface(aGlobal.GetAsSupports());\n"
|
||||
"return Constructor(owner, %s, %s);" % (self.args[0].name, self.args[1].name)
|
||||
)
|
||||
if needCx(None, self.descriptorProvider.interface.members, [], self.descriptorProvider, True):
|
||||
self.args.insert(0, Argument("JSContext*", "aCx"))
|
||||
self.args.insert(0, Argument("const GlobalObject&", "aGlobal"))
|
||||
self.args.append(Argument('ErrorResult&', 'aRv'))
|
||||
return constructorForNativeCaller + CGNativeMember.define(self, cgClass)
|
||||
|
||||
class CGEventClass(CGBindingImplClass):
|
||||
"""
|
||||
Codegen for the actual Event class implementation for this descriptor
|
||||
"""
|
||||
def __init__(self, descriptor):
|
||||
CGBindingImplClass.__init__(self, descriptor, CGEventMethod, CGEventGetter, CGEventSetter, False)
|
||||
members = []
|
||||
for m in descriptor.interface.members:
|
||||
if m.isAttr():
|
||||
if m.type.isPrimitive() and m.type.tag() in builtinNames:
|
||||
nativeType = CGGeneric(builtinNames[m.type.tag()])
|
||||
if m.type.nullable():
|
||||
nativeType = CGTemplatedType("Nullable", nativeType)
|
||||
nativeType = nativeType.define()
|
||||
elif m.type.isEnum():
|
||||
nativeType = m.type.unroll().inner.identifier.name
|
||||
if m.type.nullable():
|
||||
nativeType = CGTemplatedType("Nullable",
|
||||
CGGeneric(nativeType)).define()
|
||||
elif m.type.isDOMString():
|
||||
nativeType = "nsString"
|
||||
elif m.type.isByteString():
|
||||
nativeType = "nsCString"
|
||||
elif m.type.isGeckoInterface():
|
||||
iface = m.type.unroll().inner;
|
||||
nativeType = self.descriptor.getDescriptor(
|
||||
iface.identifier.name).nativeType
|
||||
# Now trim off unnecessary namespaces
|
||||
nativeType = nativeType.split("::")
|
||||
if nativeType[0] == "mozilla":
|
||||
nativeType.pop(0)
|
||||
if nativeType[0] == "dom":
|
||||
nativeType.pop(0)
|
||||
nativeType = CGWrapper(CGGeneric("::".join(nativeType)), pre="nsRefPtr<", post=">").define()
|
||||
elif m.type.isAny():
|
||||
nativeType = "JS::Heap<JS::Value>"
|
||||
elif m.type.isObject() or m.type.isSpiderMonkeyInterface():
|
||||
nativeType = "JS::Heap<JSObject*>"
|
||||
members.append(ClassMember(CGDictionary.makeMemberName(m.identifier.name),
|
||||
nativeType,
|
||||
visibility="private",
|
||||
body="body"))
|
||||
|
||||
baseDeclarations=(
|
||||
"public:\n"
|
||||
" NS_DECL_ISUPPORTS_INHERITED\n"
|
||||
" NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(${nativeType}, nsDOMEvent)\n"
|
||||
" virtual ~${nativeType}();\n"
|
||||
"protected:\n"
|
||||
" ${nativeType}(mozilla::dom::EventTarget* aOwner);\n\n")
|
||||
|
||||
baseDeclarations = string.Template(baseDeclarations).substitute(
|
||||
{
|
||||
"nativeType": self.descriptor.nativeType.split('::')[-1]
|
||||
})
|
||||
|
||||
CGClass.__init__(self, descriptor.nativeType.split('::')[-1],
|
||||
bases=[ClassBase("nsDOMEvent")],
|
||||
methods=self.methodDecls,
|
||||
members=members,
|
||||
extradeclarations=baseDeclarations)
|
||||
|
||||
def getWrapObjectBody(self):
|
||||
return "return %sBinding::Wrap(aCx, aScope, this);" % self.descriptor.name
|
||||
|
||||
def implTraverse(self):
|
||||
retVal = ""
|
||||
for m in self.descriptor.interface.members:
|
||||
if m.isAttr() and m.type.isGeckoInterface():
|
||||
retVal += (" NS_IMPL_CYCLE_COLLECTION_TRAVERSE(" +
|
||||
CGDictionary.makeMemberName(m.identifier.name) +
|
||||
")\n")
|
||||
return retVal
|
||||
|
||||
def implUnlink(self):
|
||||
retVal = ""
|
||||
for m in self.descriptor.interface.members:
|
||||
if m.isAttr():
|
||||
name = CGDictionary.makeMemberName(m.identifier.name)
|
||||
if m.type.isGeckoInterface():
|
||||
retVal += " NS_IMPL_CYCLE_COLLECTION_UNLINK(" + name + ")\n"
|
||||
elif m.type.isAny():
|
||||
retVal += " tmp->" + name + ".setUndefined();\n"
|
||||
elif m.type.isObject() or m.type.isSpiderMonkeyInterface():
|
||||
retVal += " tmp->" + name + " = nullptr;\n"
|
||||
return retVal
|
||||
|
||||
def implTrace(self):
|
||||
retVal = ""
|
||||
for m in self.descriptor.interface.members:
|
||||
if m.isAttr():
|
||||
name = CGDictionary.makeMemberName(m.identifier.name)
|
||||
if m.type.isAny():
|
||||
retVal += " NS_IMPL_CYCLE_COLLECTION_TRACE_JSVAL_MEMBER_CALLBACK(" + name + ")\n"
|
||||
elif m.type.isObject() or m.type.isSpiderMonkeyInterface():
|
||||
retVal += " NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(" + name + ")\n"
|
||||
return retVal
|
||||
|
||||
def define(self):
|
||||
dropJS = ""
|
||||
for m in self.descriptor.interface.members:
|
||||
if m.isAttr():
|
||||
member = CGDictionary.makeMemberName(m.identifier.name);
|
||||
if m.type.isAny():
|
||||
dropJS += " " + member + " = JS::UndefinedValue();\n"
|
||||
elif m.type.isObject() or m.type.isSpiderMonkeyInterface():
|
||||
dropJS += " " + member + " = nullptr;\n"
|
||||
if dropJS != "":
|
||||
dropJS += " mozilla::DropJSObjects(this);\n"
|
||||
# Just override CGClass and do our own thing
|
||||
classImpl = """
|
||||
NS_IMPL_CYCLE_COLLECTION_CLASS(${nativeType})
|
||||
|
||||
NS_IMPL_ADDREF_INHERITED(${nativeType}, nsDOMEvent)
|
||||
NS_IMPL_RELEASE_INHERITED(${nativeType}, nsDOMEvent)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(${nativeType}, nsDOMEvent)
|
||||
${traverse}NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(${nativeType}, nsDOMEvent)
|
||||
${trace}NS_IMPL_CYCLE_COLLECTION_TRACE_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(${nativeType}, nsDOMEvent)
|
||||
${unlink}NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(${nativeType})
|
||||
NS_INTERFACE_MAP_END_INHERITING(nsDOMEvent)
|
||||
|
||||
${nativeType}::${nativeType}(mozilla::dom::EventTarget* aOwner)
|
||||
: nsDOMEvent(aOwner, nullptr, nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
${nativeType}::~${nativeType}()
|
||||
{
|
||||
${dropJS}}
|
||||
|
||||
"""
|
||||
return string.Template(classImpl).substitute(
|
||||
{ "ifaceName": self.descriptor.name,
|
||||
"nativeType": self.descriptor.nativeType.split('::')[-1],
|
||||
"traverse": self.implTraverse(),
|
||||
"unlink": self.implUnlink(),
|
||||
"trace": self.implTrace(),
|
||||
"dropJS": dropJS}
|
||||
) + CGBindingImplClass.define(self)
|
||||
|
||||
|
||||
class CGEventRoot(CGThing):
|
||||
def __init__(self, config, interfaceName):
|
||||
# Let's assume we're not doing workers stuff, for now
|
||||
descriptor = config.getDescriptor(interfaceName, False)
|
||||
|
||||
self.root = CGWrapper(CGEventClass(descriptor),
|
||||
pre="\n", post="\n")
|
||||
|
||||
self.root = CGNamespace.build(["mozilla", "dom"], self.root)
|
||||
|
||||
self.root = CGList([CGClassForwardDeclare("JSContext", isStruct=True),
|
||||
self.root], "\n")
|
||||
|
||||
# Throw in our #includes
|
||||
self.root = CGHeaders([descriptor], [], [], [],
|
||||
[ "nsDOMEvent.h",
|
||||
"mozilla/Attributes.h",
|
||||
"mozilla/ErrorResult.h" ,
|
||||
"mozilla/dom/%sBinding.h" % interfaceName,
|
||||
'mozilla/dom/BindingUtils.h',
|
||||
],
|
||||
[ "%s.h" % interfaceName,
|
||||
"js/GCAPI.h",
|
||||
'mozilla/dom/Nullable.h',
|
||||
'nsDOMQS.h'
|
||||
], "", self.root);
|
||||
|
||||
# And now some include guards
|
||||
self.root = CGIncludeGuard(interfaceName, self.root)
|
||||
|
||||
self.root = CGWrapper(self.root, pre=AUTOGENERATED_WARNING_COMMENT)
|
||||
|
||||
self.root = CGWrapper(self.root, pre="""/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim:set ts=2 sw=2 sts=2 et cindent: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
""")
|
||||
|
||||
def declare(self):
|
||||
return self.root.declare()
|
||||
|
||||
def define(self):
|
||||
return self.root.define()
|
||||
|
||||
|
|
|
@ -12,11 +12,16 @@ webidl_base = $(topsrcdir)/dom/webidl
|
|||
include webidlsrcs.mk
|
||||
|
||||
binding_include_path := mozilla/dom
|
||||
webidl_files += $(generated_events_webidl_files)
|
||||
all_webidl_files = $(webidl_files) $(generated_webidl_files) $(preprocessed_webidl_files)
|
||||
|
||||
# Set exported_binding_headers before adding the test IDL to the mix
|
||||
exported_binding_headers := $(subst .webidl,Binding.h,$(all_webidl_files))
|
||||
exported_generated_events_headers := $(subst .webidl,.h,$(generated_events_webidl_files))
|
||||
|
||||
# Set linked_binding_cpp_files before adding the test IDL to the mix
|
||||
linked_binding_cpp_files := $(subst .webidl,Binding.cpp,$(all_webidl_files))
|
||||
linked_generated_events_cpp_files := $(subst .webidl,.cpp,$(generated_events_webidl_files))
|
||||
|
||||
all_webidl_files += $(test_webidl_files)
|
||||
|
||||
|
@ -56,6 +61,7 @@ globalgen_targets := \
|
|||
ifneq (export TestExampleInterface-example TestExampleProxyInterface-example,$(MAKECMDGOALS))
|
||||
CPPSRCS = \
|
||||
$(linked_binding_cpp_files) \
|
||||
$(linked_generated_events_cpp_files) \
|
||||
$(filter %.cpp, $(globalgen_targets)) \
|
||||
BindingUtils.cpp \
|
||||
CallbackInterface.cpp \
|
||||
|
@ -97,7 +103,7 @@ endif
|
|||
|
||||
EXTRA_EXPORT_MDDEPEND_FILES := $(addsuffix .pp,$(binding_dependency_trackers))
|
||||
|
||||
EXPORTS_GENERATED_FILES := $(exported_binding_headers)
|
||||
EXPORTS_GENERATED_FILES := $(exported_binding_headers) $(exported_generated_events_headers)
|
||||
EXPORTS_GENERATED_DEST := $(DIST)/include/$(binding_include_path)
|
||||
EXPORTS_GENERATED_TARGET := export
|
||||
INSTALL_TARGETS += EXPORTS_GENERATED
|
||||
|
@ -229,6 +235,7 @@ $(globalgen_headers_FILES): ParserResults.pkl
|
|||
$(info Generating WebIDL bindings)
|
||||
$(MKDIR) -p .deps
|
||||
echo $(all_webidl_files) > .all-webidl-file-list
|
||||
echo $(generated_events_webidl_files) > .generated-events-webidl-files
|
||||
echo $? > .changed-dependency-list
|
||||
PYTHONDONTWRITEBYTECODE=1 $(PYTHON) $(topsrcdir)/config/pythonpath.py \
|
||||
$(PLY_INCLUDE) -I$(srcdir)/parser \
|
||||
|
@ -236,6 +243,7 @@ $(globalgen_headers_FILES): ParserResults.pkl
|
|||
$(srcdir)/Bindings.conf \
|
||||
$(CURDIR) \
|
||||
.all-webidl-file-list \
|
||||
.generated-events-webidl-files \
|
||||
.changed-dependency-list
|
||||
@$(TOUCH) $@
|
||||
|
||||
|
@ -246,6 +254,7 @@ GARBAGE += \
|
|||
$(wildcard *-example.cpp) \
|
||||
.BindingGen \
|
||||
.all-webidl-file-list \
|
||||
.generated-events-webidl-files \
|
||||
.changed-dependency-list \
|
||||
$(binding_dependency_trackers) \
|
||||
$(NULL)
|
||||
|
|
|
@ -85,5 +85,4 @@ interface nsIDOMFontFace;
|
|||
interface nsIDOMFontFaceList;
|
||||
|
||||
// Power
|
||||
interface nsIDOMMozPowerManager;
|
||||
interface nsIDOMMozWakeLock;
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
XPIDL_SOURCES += [
|
||||
'nsIDOMAnimationEvent.idl',
|
||||
'nsIDOMBeforeUnloadEvent.idl',
|
||||
'nsIDOMBlobEvent.idl',
|
||||
'nsIDOMClipboardEvent.idl',
|
||||
'nsIDOMCloseEvent.idl',
|
||||
'nsIDOMCommandEvent.idl',
|
||||
|
|
|
@ -1,31 +0,0 @@
|
|||
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsIDOMEvent.idl"
|
||||
interface nsIDOMBlob;
|
||||
/**
|
||||
* The nsIDOMBlobEvent interface is used for server-sent events
|
||||
*
|
||||
* For more information on this interface, please see
|
||||
* https://dvcs.w3.org/hg/dap/raw-file/tip/media-stream-capture/RecordingProposal.html
|
||||
*/
|
||||
[scriptable, builtinclass, uuid(84293ee0-68f5-11e2-9906-cf63ba8c6e43)]
|
||||
interface nsIDOMBlobEvent : nsIDOMEvent
|
||||
{
|
||||
/**
|
||||
* Custom blob data associated with this event.
|
||||
*/
|
||||
readonly attribute nsIDOMBlob data;
|
||||
|
||||
[noscript]
|
||||
void initBlobEvent(in DOMString aType,
|
||||
in boolean aCanBubble,
|
||||
in boolean aCancelable,
|
||||
in nsIDOMBlob aData);
|
||||
};
|
||||
|
||||
dictionary BlobEventInit : EventInit {
|
||||
nsIDOMBlob data;
|
||||
};
|
|
@ -20,7 +20,7 @@ var gData = [
|
|||
{
|
||||
perm: ["power"],
|
||||
obj: "mozPower",
|
||||
idl: "nsIDOMMozPowerManager",
|
||||
webidl: "MozPowerManager",
|
||||
},
|
||||
]
|
||||
</script>
|
||||
|
|
|
@ -15,29 +15,33 @@
|
|||
#include "nsPIDOMWindow.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "nsError.h"
|
||||
|
||||
DOMCI_DATA(MozPowerManager, mozilla::dom::power::PowerManager)
|
||||
#include "mozilla/dom/MozPowerManagerBinding.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
namespace power {
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(PowerManager)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIDOMMozPowerManager)
|
||||
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMMozPowerManager)
|
||||
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
|
||||
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIDOMMozWakeLockListener)
|
||||
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(MozPowerManager)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_1(PowerManager, mListeners)
|
||||
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_2(PowerManager, mListeners, mWindow)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(PowerManager)
|
||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(PowerManager)
|
||||
|
||||
/* virtual */ JSObject*
|
||||
PowerManager::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope)
|
||||
{
|
||||
return MozPowerManagerBinding::Wrap(aCx, aScope, this);
|
||||
}
|
||||
|
||||
nsresult
|
||||
PowerManager::Init(nsIDOMWindow *aWindow)
|
||||
{
|
||||
mWindow = do_GetWeakReference(aWindow);
|
||||
mWindow = aWindow;
|
||||
|
||||
nsCOMPtr<nsIPowerManagerService> pmService =
|
||||
do_GetService(POWERMANAGERSERVICE_CONTRACTID);
|
||||
|
@ -60,63 +64,62 @@ PowerManager::Shutdown()
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
PowerManager::Reboot()
|
||||
void
|
||||
PowerManager::Reboot(ErrorResult& aRv)
|
||||
{
|
||||
nsCOMPtr<nsIPowerManagerService> pmService =
|
||||
do_GetService(POWERMANAGERSERVICE_CONTRACTID);
|
||||
NS_ENSURE_STATE(pmService);
|
||||
|
||||
pmService->Reboot();
|
||||
|
||||
return NS_OK;
|
||||
if (pmService) {
|
||||
pmService->Reboot();
|
||||
} else {
|
||||
aRv.Throw(NS_ERROR_UNEXPECTED);
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
void
|
||||
PowerManager::FactoryReset()
|
||||
{
|
||||
hal::FactoryReset();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
PowerManager::PowerOff()
|
||||
void
|
||||
PowerManager::PowerOff(ErrorResult& aRv)
|
||||
{
|
||||
nsCOMPtr<nsIPowerManagerService> pmService =
|
||||
do_GetService(POWERMANAGERSERVICE_CONTRACTID);
|
||||
NS_ENSURE_STATE(pmService);
|
||||
|
||||
pmService->PowerOff();
|
||||
|
||||
return NS_OK;
|
||||
if (pmService) {
|
||||
pmService->PowerOff();
|
||||
} else {
|
||||
aRv.Throw(NS_ERROR_UNEXPECTED);
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
void
|
||||
PowerManager::AddWakeLockListener(nsIDOMMozWakeLockListener *aListener)
|
||||
{
|
||||
// already added? bail out.
|
||||
if (mListeners.Contains(aListener))
|
||||
return NS_OK;
|
||||
|
||||
mListeners.AppendElement(aListener);
|
||||
return NS_OK;
|
||||
if (!mListeners.Contains(aListener)) {
|
||||
mListeners.AppendElement(aListener);
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
void
|
||||
PowerManager::RemoveWakeLockListener(nsIDOMMozWakeLockListener *aListener)
|
||||
{
|
||||
mListeners.RemoveElement(aListener);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
PowerManager::GetWakeLockState(const nsAString &aTopic, nsAString &aState)
|
||||
void
|
||||
PowerManager::GetWakeLockState(const nsAString& aTopic,
|
||||
nsAString& aState,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
nsCOMPtr<nsIPowerManagerService> pmService =
|
||||
do_GetService(POWERMANAGERSERVICE_CONTRACTID);
|
||||
NS_ENSURE_STATE(pmService);
|
||||
|
||||
return pmService->GetWakeLockState(aTopic, aState);
|
||||
if (pmService) {
|
||||
aRv = pmService->GetWakeLockState(aTopic, aState);
|
||||
} else {
|
||||
aRv.Throw(NS_ERROR_UNEXPECTED);
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -138,47 +141,44 @@ PowerManager::Callback(const nsAString &aTopic, const nsAString &aState)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
PowerManager::GetScreenEnabled(bool *aEnabled)
|
||||
bool
|
||||
PowerManager::ScreenEnabled()
|
||||
{
|
||||
*aEnabled = hal::GetScreenEnabled();
|
||||
return NS_OK;
|
||||
return hal::GetScreenEnabled();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
void
|
||||
PowerManager::SetScreenEnabled(bool aEnabled)
|
||||
{
|
||||
hal::SetScreenEnabled(aEnabled);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
PowerManager::GetScreenBrightness(double *aBrightness)
|
||||
double
|
||||
PowerManager::ScreenBrightness()
|
||||
{
|
||||
*aBrightness = hal::GetScreenBrightness();
|
||||
return NS_OK;
|
||||
return hal::GetScreenBrightness();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
PowerManager::SetScreenBrightness(double aBrightness)
|
||||
void
|
||||
PowerManager::SetScreenBrightness(double aBrightness, ErrorResult& aRv)
|
||||
{
|
||||
NS_ENSURE_TRUE(0 <= aBrightness && aBrightness <= 1, NS_ERROR_INVALID_ARG);
|
||||
hal::SetScreenBrightness(aBrightness);
|
||||
return NS_OK;
|
||||
if (0 <= aBrightness && aBrightness <= 1) {
|
||||
hal::SetScreenBrightness(aBrightness);
|
||||
} else {
|
||||
aRv.Throw(NS_ERROR_INVALID_ARG);
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
PowerManager::GetCpuSleepAllowed(bool *aAllowed)
|
||||
bool
|
||||
PowerManager::CpuSleepAllowed()
|
||||
{
|
||||
*aAllowed = hal::GetCpuSleepAllowed();
|
||||
return NS_OK;
|
||||
return hal::GetCpuSleepAllowed();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
void
|
||||
PowerManager::SetCpuSleepAllowed(bool aAllowed)
|
||||
{
|
||||
hal::SetCpuSleepAllowed(aAllowed);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
|
@ -7,30 +7,32 @@
|
|||
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsTArray.h"
|
||||
#include "nsIDOMPowerManager.h"
|
||||
#include "nsIDOMWakeLockListener.h"
|
||||
#include "nsIDOMWindow.h"
|
||||
#include "nsWeakReference.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "nsWrapperCache.h"
|
||||
|
||||
class nsPIDOMWindow;
|
||||
|
||||
namespace mozilla {
|
||||
class ErrorResult;
|
||||
|
||||
namespace dom {
|
||||
namespace power {
|
||||
|
||||
class PowerManager
|
||||
: public nsIDOMMozPowerManager
|
||||
, public nsIDOMMozWakeLockListener
|
||||
class PowerManager MOZ_FINAL : public nsIDOMMozWakeLockListener
|
||||
, public nsWrapperCache
|
||||
{
|
||||
public:
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(PowerManager, nsIDOMMozPowerManager)
|
||||
NS_DECL_NSIDOMMOZPOWERMANAGER
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(PowerManager)
|
||||
NS_DECL_NSIDOMMOZWAKELOCKLISTENER
|
||||
|
||||
PowerManager() {};
|
||||
virtual ~PowerManager() {};
|
||||
PowerManager()
|
||||
{
|
||||
SetIsDOMBinding();
|
||||
}
|
||||
|
||||
nsresult Init(nsIDOMWindow *aWindow);
|
||||
nsresult Shutdown();
|
||||
|
@ -39,9 +41,28 @@ public:
|
|||
|
||||
static already_AddRefed<PowerManager> CreateInstance(nsPIDOMWindow*);
|
||||
|
||||
private:
|
||||
// WebIDL
|
||||
nsIDOMWindow* GetParentObject() const
|
||||
{
|
||||
return mWindow;
|
||||
}
|
||||
virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope) MOZ_OVERRIDE;
|
||||
void Reboot(ErrorResult& aRv);
|
||||
void FactoryReset();
|
||||
void PowerOff(ErrorResult& aRv);
|
||||
void AddWakeLockListener(nsIDOMMozWakeLockListener* aListener);
|
||||
void RemoveWakeLockListener(nsIDOMMozWakeLockListener* aListener);
|
||||
void GetWakeLockState(const nsAString& aTopic, nsAString& aState,
|
||||
ErrorResult& aRv);
|
||||
bool ScreenEnabled();
|
||||
void SetScreenEnabled(bool aEnabled);
|
||||
double ScreenBrightness();
|
||||
void SetScreenBrightness(double aBrightness, ErrorResult& aRv);
|
||||
bool CpuSleepAllowed();
|
||||
void SetCpuSleepAllowed(bool aAllowed);
|
||||
|
||||
nsWeakPtr mWindow;
|
||||
private:
|
||||
nsCOMPtr<nsIDOMWindow> mWindow;
|
||||
nsTArray<nsCOMPtr<nsIDOMMozWakeLockListener> > mListeners;
|
||||
};
|
||||
|
||||
|
|
|
@ -8,7 +8,6 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
|
|||
TEST_DIRS += ['test']
|
||||
|
||||
XPIDL_SOURCES += [
|
||||
'nsIDOMPowerManager.idl',
|
||||
'nsIDOMWakeLock.idl',
|
||||
'nsIDOMWakeLockListener.idl',
|
||||
'nsIPowerManagerService.idl',
|
||||
|
@ -17,6 +16,7 @@ XPIDL_SOURCES += [
|
|||
XPIDL_MODULE = 'dom_power'
|
||||
|
||||
EXPORTS.mozilla.dom.power += [
|
||||
'PowerManager.h',
|
||||
'PowerManagerService.h',
|
||||
'Types.h',
|
||||
]
|
||||
|
|
|
@ -606,7 +606,7 @@ NetworkManager.prototype = {
|
|||
dns2_str: this.active.dns2
|
||||
};
|
||||
this.worker.postMessage(options);
|
||||
this.setNetworkProxy();
|
||||
this.setNetworkProxy(this.active);
|
||||
},
|
||||
|
||||
removeDefaultRoute: function removeDefaultRoute(ifname) {
|
||||
|
@ -689,9 +689,9 @@ NetworkManager.prototype = {
|
|||
this.worker.postMessage(options);
|
||||
},
|
||||
|
||||
setNetworkProxy: function setNetworkProxy() {
|
||||
setNetworkProxy: function setNetworkProxy(network) {
|
||||
try {
|
||||
if (!this.active.httpProxyHost || this.active.httpProxyHost == "") {
|
||||
if (!network.httpProxyHost || network.httpProxyHost == "") {
|
||||
// Sets direct connection to internet.
|
||||
Services.prefs.clearUserPref("network.proxy.type");
|
||||
Services.prefs.clearUserPref("network.proxy.share_proxy_settings");
|
||||
|
@ -699,23 +699,23 @@ NetworkManager.prototype = {
|
|||
Services.prefs.clearUserPref("network.proxy.http_port");
|
||||
Services.prefs.clearUserPref("network.proxy.ssl");
|
||||
Services.prefs.clearUserPref("network.proxy.ssl_port");
|
||||
debug("No proxy support for " + this.active.name + " network interface.");
|
||||
debug("No proxy support for " + network.name + " network interface.");
|
||||
return;
|
||||
}
|
||||
|
||||
debug("Going to set proxy settings for " + this.active.name + " network interface.");
|
||||
debug("Going to set proxy settings for " + network.name + " network interface.");
|
||||
// Sets manual proxy configuration.
|
||||
Services.prefs.setIntPref("network.proxy.type", MANUAL_PROXY_CONFIGURATION);
|
||||
// Do not use this proxy server for all protocols.
|
||||
Services.prefs.setBoolPref("network.proxy.share_proxy_settings", false);
|
||||
Services.prefs.setCharPref("network.proxy.http", this.active.httpProxyHost);
|
||||
Services.prefs.setCharPref("network.proxy.ssl", this.active.httpProxyHost);
|
||||
let port = this.active.httpProxyPort == "" ? 8080 : this.active.httpProxyPort;
|
||||
Services.prefs.setCharPref("network.proxy.http", network.httpProxyHost);
|
||||
Services.prefs.setCharPref("network.proxy.ssl", network.httpProxyHost);
|
||||
let port = network.httpProxyPort == 0 ? 8080 : network.httpProxyPort;
|
||||
Services.prefs.setIntPref("network.proxy.http_port", port);
|
||||
Services.prefs.setIntPref("network.proxy.ssl_port", port);
|
||||
} catch (ex) {
|
||||
debug("Exception " + ex + ". Unable to set proxy setting for "
|
||||
+ this.active.name + " network interface.");
|
||||
+ network.name + " network interface.");
|
||||
return;
|
||||
}
|
||||
},
|
||||
|
|
|
@ -119,7 +119,7 @@ interface nsIWifiOperationModeCallback : nsISupports
|
|||
/**
|
||||
* Manage network interfaces.
|
||||
*/
|
||||
[scriptable, uuid(5b22c620-f8b9-11e2-b778-0800200c9a66)]
|
||||
[scriptable, uuid(fad3fb08-664f-48e3-bba3-423186988c61)]
|
||||
interface nsINetworkManager : nsISupports
|
||||
{
|
||||
/**
|
||||
|
@ -231,4 +231,12 @@ interface nsINetworkManager : nsISupports
|
|||
* Callback to notify Wifi firmware reload result.
|
||||
*/
|
||||
void setWifiOperationMode(in DOMString interfaceName, in DOMString mode, in nsIWifiOperationModeCallback callback);
|
||||
|
||||
/**
|
||||
* Set http proxy for specific network
|
||||
*
|
||||
* @param network
|
||||
* Network interface to register.
|
||||
*/
|
||||
void setNetworkProxy(in nsINetworkInterface network);
|
||||
};
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
*/
|
||||
interface Blob;
|
||||
|
||||
[Constructor(DOMString type, optional BlobEventInit eventInitDict), HeaderFile="GeneratedEventClasses.h"]
|
||||
[Constructor(DOMString type, optional BlobEventInit eventInitDict)]
|
||||
interface BlobEvent : Event
|
||||
{
|
||||
readonly attribute Blob? data;
|
||||
|
|
|
@ -3,17 +3,16 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsISupports.idl"
|
||||
|
||||
interface nsIDOMMozWakeLockListener;
|
||||
interface MozWakeLockListener;
|
||||
|
||||
/**
|
||||
* This interface implements navigator.mozPower
|
||||
*/
|
||||
[scriptable, uuid(7b181fef-2757-4198-89a0-8c426b8439ea)]
|
||||
interface nsIDOMMozPowerManager : nsISupports
|
||||
interface MozPowerManager
|
||||
{
|
||||
[Throws]
|
||||
void powerOff();
|
||||
[Throws]
|
||||
void reboot();
|
||||
void factoryReset();
|
||||
|
||||
|
@ -23,8 +22,8 @@ interface nsIDOMMozPowerManager : nsISupports
|
|||
* - locked but not visible
|
||||
* - locked and visible
|
||||
*/
|
||||
void addWakeLockListener(in nsIDOMMozWakeLockListener aListener);
|
||||
void removeWakeLockListener(in nsIDOMMozWakeLockListener aListener);
|
||||
void addWakeLockListener(MozWakeLockListener aListener);
|
||||
void removeWakeLockListener(MozWakeLockListener aListener);
|
||||
|
||||
/**
|
||||
* Query the wake lock state of the topic.
|
||||
|
@ -41,7 +40,8 @@ interface nsIDOMMozPowerManager : nsISupports
|
|||
*
|
||||
* @param aTopic The resource name related to the wake lock.
|
||||
*/
|
||||
DOMString getWakeLockState(in DOMString aTopic);
|
||||
[Throws]
|
||||
DOMString getWakeLockState(DOMString aTopic);
|
||||
|
||||
/**
|
||||
* Is the device's screen currently enabled? This attribute controls the
|
||||
|
@ -64,6 +64,7 @@ interface nsIDOMMozPowerManager : nsISupports
|
|||
*
|
||||
* @throw NS_ERROR_INVALID_ARG if brightness is not in the range [0, 1].
|
||||
*/
|
||||
[SetterThrows]
|
||||
attribute double screenBrightness;
|
||||
|
||||
/**
|
|
@ -17,7 +17,6 @@
|
|||
* and create derivative works of this document.
|
||||
*/
|
||||
|
||||
interface MozPowerManager;
|
||||
interface MozWakeLock;
|
||||
|
||||
// http://www.whatwg.org/specs/web-apps/current-work/#the-navigator-object
|
||||
|
|
|
@ -211,6 +211,7 @@ WEBIDL_FILES = [
|
|||
'MozActivity.webidl',
|
||||
'MozMmsMessage.webidl',
|
||||
'MozNamedAttrMap.webidl',
|
||||
'MozPowerManager.webidl',
|
||||
'MozTimeManager.webidl',
|
||||
'MutationEvent.webidl',
|
||||
'MutationObserver.webidl',
|
||||
|
@ -453,7 +454,6 @@ if CONFIG['MOZ_B2G_RIL']:
|
|||
]
|
||||
|
||||
WEBIDL_FILES += [
|
||||
'BlobEvent.webidl',
|
||||
'CloseEvent.webidl',
|
||||
'CustomEvent.webidl',
|
||||
'DeviceLightEvent.webidl',
|
||||
|
@ -537,3 +537,7 @@ if CONFIG['MOZ_B2G']:
|
|||
WEBIDL_FILES += [
|
||||
'InputMethod.webidl',
|
||||
]
|
||||
|
||||
GENERATED_EVENTS_WEBIDL_FILES = [
|
||||
'BlobEvent.webidl',
|
||||
]
|
||||
|
|
|
@ -87,6 +87,7 @@ DOMWifiManager.prototype = {
|
|||
"WifiManager:forget:Return:OK", "WifiManager:forget:Return:NO",
|
||||
"WifiManager:wps:Return:OK", "WifiManager:wps:Return:NO",
|
||||
"WifiManager:setPowerSavingMode:Return:OK", "WifiManager:setPowerSavingMode:Return:NO",
|
||||
"WifiManager:setHttpProxy:Return:OK", "WifiManager:setHttpProxy:Return:NO",
|
||||
"WifiManager:setStaticIpMode:Return:OK", "WifiManager:setStaticIpMode:Return:NO",
|
||||
"WifiManager:wifiDown", "WifiManager:wifiUp",
|
||||
"WifiManager:onconnecting", "WifiManager:onassociate",
|
||||
|
@ -194,6 +195,16 @@ DOMWifiManager.prototype = {
|
|||
Services.DOMRequest.fireError(request, msg.data);
|
||||
break;
|
||||
|
||||
case "WifiManager:setHttpProxy:Return:OK":
|
||||
request = this.takeRequest(msg.rid);
|
||||
Services.DOMRequest.fireSuccess(request, exposeReadOnly(msg.data));
|
||||
break;
|
||||
|
||||
case "WifiManager:setHttpProxy:Return:NO":
|
||||
request = this.takeRequest(msg.rid);
|
||||
Services.DOMRequest.fireError(request, msg.data);
|
||||
break;
|
||||
|
||||
case "WifiManager:setStaticIpMode:Return:OK":
|
||||
request = this.takeRequest(msg.rid);
|
||||
Services.DOMRequest.fireSuccess(request, exposeReadOnly(msg.data));
|
||||
|
@ -360,6 +371,14 @@ DOMWifiManager.prototype = {
|
|||
return request;
|
||||
},
|
||||
|
||||
setHttpProxy: function nsIDOMWifiManager_setHttpProxy(network, info) {
|
||||
if (!this._hasPrivileges)
|
||||
throw new Components.Exception("Denied", Cr.NS_ERROR_FAILURE);
|
||||
var request = this.createRequest();
|
||||
this._sendMessageForRequest("WifiManager:setHttpProxy", {network:network, info:info}, request);
|
||||
return request;
|
||||
},
|
||||
|
||||
setStaticIpMode: function nsIDOMWifiManager_setStaticIpMode(network, info) {
|
||||
if (!this._hasPrivileges)
|
||||
throw new Components.Exception("Denied", Cr.NS_ERROR_FAILURE);
|
||||
|
|
|
@ -647,6 +647,48 @@ var WifiManager = (function() {
|
|||
});
|
||||
}
|
||||
|
||||
var httpProxyConfig = Object.create(null);
|
||||
|
||||
/**
|
||||
* Given a network, configure http proxy when using wifi.
|
||||
* @param network A network object to update http proxy
|
||||
* @param info Info should have following field:
|
||||
* - httpProxyHost ip address of http proxy.
|
||||
* - httpProxyPort port of http proxy, set 0 to use default port 8080.
|
||||
* @param callback callback function.
|
||||
*/
|
||||
function configureHttpProxy(network, info, callback) {
|
||||
if (!network)
|
||||
return;
|
||||
|
||||
let networkKey = getNetworkKey(network);
|
||||
|
||||
if (!info || info.httpProxyHost === "") {
|
||||
delete httpProxyConfig[networkKey];
|
||||
} else {
|
||||
httpProxyConfig[networkKey] = network;
|
||||
httpProxyConfig[networkKey].httpProxyHost = info.httpProxyHost;
|
||||
httpProxyConfig[networkKey].httpProxyPort = info.httpProxyPort;
|
||||
}
|
||||
|
||||
callback(true);
|
||||
}
|
||||
|
||||
function getHttpProxyNetwork(network) {
|
||||
if (!network)
|
||||
return null;
|
||||
|
||||
let networkKey = getNetworkKey(network);
|
||||
return ((networkKey in httpProxyConfig) ? httpProxyConfig : null);
|
||||
}
|
||||
|
||||
function setHttpProxy(network) {
|
||||
if (!network)
|
||||
return;
|
||||
|
||||
gNetworkManager.setNetworkProxy(network);
|
||||
}
|
||||
|
||||
var staticIpConfig = Object.create(null);
|
||||
function setStaticIpMode(network, info, callback) {
|
||||
let setNetworkKey = getNetworkKey(network);
|
||||
|
@ -1548,6 +1590,9 @@ var WifiManager = (function() {
|
|||
manager.setPowerMode = (sdkVersion >= 16)
|
||||
? setPowerModeCommandJB
|
||||
: setPowerModeCommandICS;
|
||||
manager.getHttpProxyNetwork = getHttpProxyNetwork;
|
||||
manager.setHttpProxy = setHttpProxy;
|
||||
manager.configureHttpProxy = configureHttpProxy;
|
||||
manager.setSuspendOptimizations = setSuspendOptimizationsCommand;
|
||||
manager.setStaticIpMode = setStaticIpMode;
|
||||
manager.getRssiApprox = getRssiApproxCommand;
|
||||
|
@ -1851,6 +1896,7 @@ function WifiWorker() {
|
|||
"WifiManager:associate", "WifiManager:forget",
|
||||
"WifiManager:wps", "WifiManager:getState",
|
||||
"WifiManager:setPowerSavingMode",
|
||||
"WifiManager:setHttpProxy",
|
||||
"WifiManager:setStaticIpMode",
|
||||
"child-process-shutdown"];
|
||||
|
||||
|
@ -2160,6 +2206,11 @@ function WifiWorker() {
|
|||
WifiManager.getNetworkConfiguration(self.currentNetwork, function(){});
|
||||
}
|
||||
|
||||
// Update http proxy when connected to network.
|
||||
let netConnect = WifiManager.getHttpProxyNetwork(self.currentNetwork);
|
||||
if (netConnect)
|
||||
WifiManager.setHttpProxy(netConnect);
|
||||
|
||||
// The full authentication process is completed, reset the count.
|
||||
WifiManager.authenticationFailuresCount = 0;
|
||||
WifiManager.loopDetectionCount = 0;
|
||||
|
@ -2182,6 +2233,23 @@ function WifiWorker() {
|
|||
}
|
||||
|
||||
self._fireEvent("ondisconnect", {});
|
||||
|
||||
// When disconnected, clear the http proxy setting if it exists.
|
||||
// Temporarily set http proxy to empty and restore user setting after setHttpProxy.
|
||||
let netDisconnect = WifiManager.getHttpProxyNetwork(self.currentNetwork);
|
||||
if (netDisconnect) {
|
||||
let prehttpProxyHostSetting = netDisconnect.httpProxyHost;
|
||||
let prehttpProxyPortSetting = netDisconnect.httpProxyPort;
|
||||
|
||||
netDisconnect.httpProxyHost = "";
|
||||
netDisconnect.httpProxyPort = 0;
|
||||
|
||||
WifiManager.setHttpProxy(netDisconnect);
|
||||
|
||||
netDisconnect.httpProxyHost = prehttpProxyHostSetting;
|
||||
netDisconnect.httpProxyPort = prehttpProxyPortSetting;
|
||||
}
|
||||
|
||||
self.currentNetwork = null;
|
||||
self.ipAddress = "";
|
||||
|
||||
|
@ -2716,6 +2784,9 @@ WifiWorker.prototype = {
|
|||
case "WifiManager:setPowerSavingMode":
|
||||
this.setPowerSavingMode(msg);
|
||||
break;
|
||||
case "WifiManager:setHttpProxy":
|
||||
this.setHttpProxy(msg);
|
||||
break;
|
||||
case "WifiManager:setStaticIpMode":
|
||||
this.setStaticIpMode(msg);
|
||||
break;
|
||||
|
@ -3210,6 +3281,30 @@ WifiWorker.prototype = {
|
|||
});
|
||||
},
|
||||
|
||||
setHttpProxy: function(msg) {
|
||||
const message = "WifiManager:setHttpProxy:Return";
|
||||
let self = this;
|
||||
let network = msg.data.network;
|
||||
let info = msg.data.info;
|
||||
|
||||
netFromDOM(network, null);
|
||||
|
||||
WifiManager.configureHttpProxy(network, info, function(ok) {
|
||||
if (ok) {
|
||||
// If configured network is current connected network
|
||||
// need update http proxy immediately.
|
||||
let setNetworkKey = getNetworkKey(network);
|
||||
let curNetworkKey = self.currentNetwork ? getNetworkKey(self.currentNetwork) : null;
|
||||
if (setNetworkKey === curNetworkKey)
|
||||
WifiManager.setHttpProxy(network);
|
||||
|
||||
self._sendMessage(message, true, true, msg);
|
||||
} else {
|
||||
self._sendMessage(message, false, "Set http proxy failed", msg);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
setStaticIpMode: function(msg) {
|
||||
const message = "WifiManager:setStaticMode:Return";
|
||||
let self = this;
|
||||
|
|
|
@ -59,7 +59,7 @@ interface nsIWifi : nsISupports
|
|||
void getWifiScanResults(in nsIWifiScanResultsReady callback);
|
||||
};
|
||||
|
||||
[scriptable, uuid(3f21012d-6e75-4632-b87c-acdd7c57fbf3)]
|
||||
[scriptable, uuid(e5a72295-1c5f-4848-9cbb-f1d3785c16c1)]
|
||||
interface nsIDOMWifiManager : nsISupports
|
||||
{
|
||||
/**
|
||||
|
@ -145,6 +145,19 @@ interface nsIDOMWifiManager : nsISupports
|
|||
nsIDOMDOMRequest setStaticIpMode(in jsval network,
|
||||
in jsval info);
|
||||
|
||||
/**
|
||||
* Given a network, configure http proxy when using wifi.
|
||||
* @param network A network object with the SSID of the network to set http proxy.
|
||||
* @param info info should have following field:
|
||||
* - httpProxyHost ip address of http proxy.
|
||||
* - httpProxyPort port of http proxy, set 0 to use default port 8080.
|
||||
* set info to null to clear http proxy.
|
||||
* onsuccess: We have successfully configure http proxy.
|
||||
* onerror: We have failed to configure http proxy.
|
||||
*/
|
||||
nsIDOMDOMRequest setHttpProxy(in jsval network,
|
||||
in jsval info);
|
||||
|
||||
/**
|
||||
* Returns whether or not wifi is currently enabled.
|
||||
*/
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include "js/OldDebugAPI.h"
|
||||
#include "mozilla/Util.h"
|
||||
#include "mozilla/dom/DOMJSClass.h"
|
||||
#include "mozilla/dom/EventBinding.h"
|
||||
#include "mozilla/dom/EventTargetBinding.h"
|
||||
#include "mozilla/dom/BindingUtils.h"
|
||||
#include "mozilla/dom/DOMExceptionBinding.h"
|
||||
|
@ -1097,6 +1098,7 @@ CreateDedicatedWorkerGlobalScope(JSContext* aCx)
|
|||
|
||||
// Init other paris-bindings.
|
||||
if (!DOMExceptionBinding::GetConstructorObject(aCx, global) ||
|
||||
!EventBinding::GetConstructorObject(aCx, global) ||
|
||||
!FileReaderSyncBinding_workers::GetConstructorObject(aCx, global) ||
|
||||
!ImageDataBinding::GetConstructorObject(aCx, global) ||
|
||||
!TextDecoderBinding::GetConstructorObject(aCx, global) ||
|
||||
|
|
|
@ -4,6 +4,9 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef GFXTEXTURESREPORTER_H_
|
||||
#define GFXTEXTURESREPORTER_H_
|
||||
|
||||
#include "nsIMemoryReporter.h"
|
||||
#include "GLTypes.h"
|
||||
|
||||
|
@ -45,4 +48,6 @@ private:
|
|||
};
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // GFXTEXTURESREPORTER_H_
|
||||
|
|
|
@ -4,6 +4,9 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef TEXTUREGARBAGEBIN_H_
|
||||
#define TEXTUREGARBAGEBIN_H_
|
||||
|
||||
#include <stack>
|
||||
|
||||
#include "mozilla/Mutex.h"
|
||||
|
@ -35,3 +38,5 @@ public:
|
|||
|
||||
}
|
||||
}
|
||||
|
||||
#endif // TEXTUREGARBAGEBIN_H_
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
# include <android/log.h>
|
||||
# include "AndroidBridge.h"
|
||||
#endif
|
||||
#include "GeckoProfiler.h"
|
||||
|
||||
struct nsCSSValueList;
|
||||
|
||||
|
@ -639,6 +640,7 @@ AsyncCompositionManager::TransformScrollableLayer(Layer* aLayer, const LayoutDev
|
|||
bool
|
||||
AsyncCompositionManager::TransformShadowTree(TimeStamp aCurrentFrame)
|
||||
{
|
||||
PROFILER_LABEL("AsyncCompositionManager", "TransformShadowTree");
|
||||
Layer* root = mLayerManager->GetRoot();
|
||||
if (!root) {
|
||||
return false;
|
||||
|
|
|
@ -51,6 +51,7 @@
|
|||
#ifdef MOZ_WIDGET_ANDROID
|
||||
#include <android/log.h>
|
||||
#endif
|
||||
#include "GeckoProfiler.h"
|
||||
|
||||
class gfxASurface;
|
||||
class gfxContext;
|
||||
|
@ -323,8 +324,10 @@ LayerManagerComposite::Render()
|
|||
return;
|
||||
}
|
||||
|
||||
|
||||
mCompositor->GetWidget()->PreRender(this);
|
||||
{
|
||||
PROFILER_LABEL("LayerManagerComposite", "PreRender");
|
||||
mCompositor->GetWidget()->PreRender(this);
|
||||
}
|
||||
|
||||
nsIntRect clipRect;
|
||||
Rect bounds(mRenderBounds.x, mRenderBounds.y, mRenderBounds.width, mRenderBounds.height);
|
||||
|
@ -362,7 +365,10 @@ LayerManagerComposite::Render()
|
|||
// Debugging
|
||||
RenderDebugOverlay(actualBounds);
|
||||
|
||||
mCompositor->EndFrame();
|
||||
{
|
||||
PROFILER_LABEL("LayerManagerComposite", "EndFrame");
|
||||
mCompositor->EndFrame();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include "nsSize.h" // for nsIntSize
|
||||
#include "nsString.h" // for nsAutoCString
|
||||
#include "nsTraceRefcnt.h" // for MOZ_COUNT_CTOR, etc
|
||||
#include "GeckoProfiler.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
@ -100,6 +101,7 @@ ThebesLayerComposite::RenderLayer(const nsIntPoint& aOffset,
|
|||
if (!mBuffer || !mBuffer->IsAttached()) {
|
||||
return;
|
||||
}
|
||||
PROFILER_LABEL("ThebesLayerComposite", "RenderLayer");
|
||||
|
||||
MOZ_ASSERT(mBuffer->GetCompositor() == mCompositeManager->GetCompositor() &&
|
||||
mBuffer->GetLayer() == this,
|
||||
|
|
|
@ -47,6 +47,7 @@
|
|||
#include "mozilla/layers/CompositorD3D11.h"
|
||||
#include "mozilla/layers/CompositorD3D9.h"
|
||||
#endif
|
||||
#include "GeckoProfiler.h"
|
||||
|
||||
using namespace base;
|
||||
using namespace mozilla;
|
||||
|
@ -491,6 +492,7 @@ CompositorParent::ScheduleComposition()
|
|||
void
|
||||
CompositorParent::Composite()
|
||||
{
|
||||
PROFILER_LABEL("CompositorParent", "Composite");
|
||||
NS_ABORT_IF_FALSE(CompositorThreadID() == PlatformThread::CurrentId(),
|
||||
"Composite can only be called on the compositor thread");
|
||||
mCurrentCompositeTask = nullptr;
|
||||
|
@ -541,6 +543,7 @@ CompositorParent::Composite()
|
|||
void
|
||||
CompositorParent::ComposeToTarget(gfxContext* aTarget)
|
||||
{
|
||||
PROFILER_LABEL("CompositorParent", "ComposeToTarget");
|
||||
AutoRestore<bool> override(mOverrideComposeReadiness);
|
||||
mOverrideComposeReadiness = true;
|
||||
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
#include "nsPoint.h" // for nsPoint
|
||||
#include "nsTArray.h" // for nsTArray, nsTArray_Impl, etc
|
||||
#include "nsTraceRefcnt.h" // for MOZ_COUNT_CTOR, etc
|
||||
#include "GeckoProfiler.h"
|
||||
|
||||
typedef std::vector<mozilla::layers::EditReply> EditReplyVector;
|
||||
|
||||
|
@ -186,6 +187,7 @@ LayerTransactionParent::RecvUpdate(const InfallibleTArray<Edit>& cset,
|
|||
const bool& isFirstPaint,
|
||||
InfallibleTArray<EditReply>* reply)
|
||||
{
|
||||
PROFILER_LABEL("LayerTransactionParent", "RecvUpdate");
|
||||
#ifdef COMPOSITOR_PERFORMANCE_WARNING
|
||||
TimeStamp updateStart = TimeStamp::Now();
|
||||
#endif
|
||||
|
|
|
@ -44,6 +44,7 @@
|
|||
#if MOZ_ANDROID_OMTC
|
||||
#include "TexturePoolOGL.h"
|
||||
#endif
|
||||
#include "GeckoProfiler.h"
|
||||
|
||||
|
||||
namespace mozilla {
|
||||
|
@ -780,6 +781,7 @@ CompositorOGL::BeginFrame(const Rect *aClipRectIn, const gfxMatrix& aTransform,
|
|||
const Rect& aRenderBounds, Rect *aClipRectOut,
|
||||
Rect *aRenderBoundsOut)
|
||||
{
|
||||
PROFILER_LABEL("CompositorOGL", "BeginFrame");
|
||||
MOZ_ASSERT(!mFrameInProgress, "frame still in progress (should have called EndFrame or AbortFrame");
|
||||
|
||||
mVBOs.Reset();
|
||||
|
@ -1010,6 +1012,7 @@ CompositorOGL::DrawQuad(const Rect& aRect, const Rect& aClipRect,
|
|||
Float aOpacity, const gfx::Matrix4x4 &aTransform,
|
||||
const Point& aOffset)
|
||||
{
|
||||
PROFILER_LABEL("CompositorOGL", "DrawQuad");
|
||||
MOZ_ASSERT(mFrameInProgress, "frame not started");
|
||||
|
||||
IntRect intClipRect;
|
||||
|
@ -1274,6 +1277,7 @@ CompositorOGL::DrawQuad(const Rect& aRect, const Rect& aClipRect,
|
|||
void
|
||||
CompositorOGL::EndFrame()
|
||||
{
|
||||
PROFILER_LABEL("CompositorOGL", "BeginFrame");
|
||||
MOZ_ASSERT(mCurrentRenderTarget == mWindowRenderTarget, "Rendering target not properly restored");
|
||||
|
||||
#ifdef MOZ_DUMP_PAINTING
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#ifdef XP_MACOSX
|
||||
#include "SharedSurfaceIO.h"
|
||||
#endif
|
||||
#include "GeckoProfiler.h"
|
||||
|
||||
using namespace mozilla::gl;
|
||||
using namespace mozilla::gfx;
|
||||
|
@ -1090,6 +1091,7 @@ GrallocDeprecatedTextureHostOGL::gl() const
|
|||
|
||||
void GrallocDeprecatedTextureHostOGL::BindTexture(GLenum aTextureUnit)
|
||||
{
|
||||
PROFILER_LABEL("Gralloc", "BindTexture");
|
||||
/*
|
||||
* The job of this function is to ensure that the texture is tied to the
|
||||
* android::GraphicBuffer, so that texturing will source the GraphicBuffer.
|
||||
|
|
|
@ -2958,7 +2958,9 @@ gfxFont::GetShapedWord(gfxContext *aContext,
|
|||
uint32_t aFlags)
|
||||
{
|
||||
// if the cache is getting too big, flush it and start over
|
||||
if (mWordCache->Count() > 10000) {
|
||||
uint32_t wordCacheMaxEntries =
|
||||
gfxPlatform::GetPlatform()->WordCacheMaxEntries();
|
||||
if (mWordCache->Count() > wordCacheMaxEntries) {
|
||||
NS_WARNING("flushing shaped-word cache");
|
||||
ClearCachedWords();
|
||||
}
|
||||
|
@ -3242,6 +3244,8 @@ gfxFont::SplitAndInitTextRun(gfxContext *aContext,
|
|||
}
|
||||
|
||||
InitWordCache();
|
||||
uint32_t wordCacheCharLimit =
|
||||
gfxPlatform::GetPlatform()->WordCacheCharLimit();
|
||||
|
||||
// the only flags we care about for ShapedWord construction/caching
|
||||
uint32_t flags = aTextRun->GetFlags();
|
||||
|
@ -3279,9 +3283,9 @@ gfxFont::SplitAndInitTextRun(gfxContext *aContext,
|
|||
|
||||
// We've decided to break here (i.e. we're at the end of a "word");
|
||||
// shape the word and add it to the textrun.
|
||||
// For words longer than gfxShapedWord::kMaxLength, we don't use the
|
||||
// For words longer than the limit, we don't use the
|
||||
// font's word cache but just shape directly into the textrun.
|
||||
if (length > gfxShapedWord::kMaxLength) {
|
||||
if (length > wordCacheCharLimit) {
|
||||
bool ok = ShapeFragmentWithoutWordCache(aContext,
|
||||
text + wordStart,
|
||||
aRunStart + wordStart,
|
||||
|
|
|
@ -2467,8 +2467,6 @@ protected:
|
|||
class gfxShapedWord : public gfxShapedText
|
||||
{
|
||||
public:
|
||||
static const uint32_t kMaxLength = 32;
|
||||
|
||||
// Create a ShapedWord that can hold glyphs for aLength characters,
|
||||
// with mCharacterGlyphs sized appropriately.
|
||||
//
|
||||
|
@ -2482,7 +2480,8 @@ public:
|
|||
int32_t aRunScript,
|
||||
int32_t aAppUnitsPerDevUnit,
|
||||
uint32_t aFlags) {
|
||||
NS_ASSERTION(aLength <= kMaxLength, "excessive length for gfxShapedWord!");
|
||||
NS_ASSERTION(aLength <= gfxPlatform::GetPlatform()->WordCacheCharLimit(),
|
||||
"excessive length for gfxShapedWord!");
|
||||
|
||||
// Compute size needed including the mCharacterGlyphs array
|
||||
// and a copy of the original text
|
||||
|
@ -2503,7 +2502,8 @@ public:
|
|||
int32_t aRunScript,
|
||||
int32_t aAppUnitsPerDevUnit,
|
||||
uint32_t aFlags) {
|
||||
NS_ASSERTION(aLength <= kMaxLength, "excessive length for gfxShapedWord!");
|
||||
NS_ASSERTION(aLength <= gfxPlatform::GetPlatform()->WordCacheCharLimit(),
|
||||
"excessive length for gfxShapedWord!");
|
||||
|
||||
// In the 16-bit version of Create, if the TEXT_IS_8BIT flag is set,
|
||||
// then we convert the text to an 8-bit version and call the 8-bit
|
||||
|
|
|
@ -150,6 +150,9 @@ SRGBOverrideObserver::Observe(nsISupports *aSubject,
|
|||
|
||||
#define GFX_PREF_OPENTYPE_SVG "gfx.font_rendering.opentype_svg.enabled"
|
||||
|
||||
#define GFX_PREF_WORD_CACHE_CHARLIMIT "gfx.font_rendering.wordcache.charlimit"
|
||||
#define GFX_PREF_WORD_CACHE_MAXENTRIES "gfx.font_rendering.wordcache.maxentries"
|
||||
|
||||
#define GFX_PREF_GRAPHITE_SHAPING "gfx.font_rendering.graphite.enabled"
|
||||
|
||||
#define BIDI_NUMERAL_PREF "bidi.numeral"
|
||||
|
@ -257,6 +260,8 @@ gfxPlatform::gfxPlatform()
|
|||
mAllowDownloadableFonts = UNINITIALIZED_VALUE;
|
||||
mFallbackUsesCmaps = UNINITIALIZED_VALUE;
|
||||
|
||||
mWordCacheCharLimit = UNINITIALIZED_VALUE;
|
||||
mWordCacheMaxEntries = UNINITIALIZED_VALUE;
|
||||
mGraphiteShapingEnabled = UNINITIALIZED_VALUE;
|
||||
mOpenTypeSVGEnabled = UNINITIALIZED_VALUE;
|
||||
mBidiNumeralOption = UNINITIALIZED_VALUE;
|
||||
|
@ -963,6 +968,34 @@ gfxPlatform::OpenTypeSVGEnabled()
|
|||
return mOpenTypeSVGEnabled > 0;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
gfxPlatform::WordCacheCharLimit()
|
||||
{
|
||||
if (mWordCacheCharLimit == UNINITIALIZED_VALUE) {
|
||||
mWordCacheCharLimit =
|
||||
Preferences::GetInt(GFX_PREF_WORD_CACHE_CHARLIMIT, 32);
|
||||
if (mWordCacheCharLimit < 0) {
|
||||
mWordCacheCharLimit = 32;
|
||||
}
|
||||
}
|
||||
|
||||
return uint32_t(mWordCacheCharLimit);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
gfxPlatform::WordCacheMaxEntries()
|
||||
{
|
||||
if (mWordCacheMaxEntries == UNINITIALIZED_VALUE) {
|
||||
mWordCacheMaxEntries =
|
||||
Preferences::GetInt(GFX_PREF_WORD_CACHE_MAXENTRIES, 10000);
|
||||
if (mWordCacheMaxEntries < 0) {
|
||||
mWordCacheMaxEntries = 10000;
|
||||
}
|
||||
}
|
||||
|
||||
return uint32_t(mWordCacheMaxEntries);
|
||||
}
|
||||
|
||||
bool
|
||||
gfxPlatform::UseGraphiteShaping()
|
||||
{
|
||||
|
@ -1762,6 +1795,16 @@ gfxPlatform::GetBidiNumeralOption()
|
|||
return mBidiNumeralOption;
|
||||
}
|
||||
|
||||
static void
|
||||
FlushFontAndWordCaches()
|
||||
{
|
||||
gfxFontCache *fontCache = gfxFontCache::GetCache();
|
||||
if (fontCache) {
|
||||
fontCache->AgeAllGenerations();
|
||||
fontCache->FlushShapedWordCaches();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gfxPlatform::FontsPrefsChanged(const char *aPref)
|
||||
{
|
||||
|
@ -1770,20 +1813,18 @@ gfxPlatform::FontsPrefsChanged(const char *aPref)
|
|||
mAllowDownloadableFonts = UNINITIALIZED_VALUE;
|
||||
} else if (!strcmp(GFX_PREF_FALLBACK_USE_CMAPS, aPref)) {
|
||||
mFallbackUsesCmaps = UNINITIALIZED_VALUE;
|
||||
} else if (!strcmp(GFX_PREF_WORD_CACHE_CHARLIMIT, aPref)) {
|
||||
mWordCacheCharLimit = UNINITIALIZED_VALUE;
|
||||
FlushFontAndWordCaches();
|
||||
} else if (!strcmp(GFX_PREF_WORD_CACHE_MAXENTRIES, aPref)) {
|
||||
mWordCacheMaxEntries = UNINITIALIZED_VALUE;
|
||||
FlushFontAndWordCaches();
|
||||
} else if (!strcmp(GFX_PREF_GRAPHITE_SHAPING, aPref)) {
|
||||
mGraphiteShapingEnabled = UNINITIALIZED_VALUE;
|
||||
gfxFontCache *fontCache = gfxFontCache::GetCache();
|
||||
if (fontCache) {
|
||||
fontCache->AgeAllGenerations();
|
||||
fontCache->FlushShapedWordCaches();
|
||||
}
|
||||
FlushFontAndWordCaches();
|
||||
} else if (!strcmp(GFX_PREF_HARFBUZZ_SCRIPTS, aPref)) {
|
||||
mUseHarfBuzzScripts = UNINITIALIZED_VALUE;
|
||||
gfxFontCache *fontCache = gfxFontCache::GetCache();
|
||||
if (fontCache) {
|
||||
fontCache->AgeAllGenerations();
|
||||
fontCache->FlushShapedWordCaches();
|
||||
}
|
||||
FlushFontAndWordCaches();
|
||||
} else if (!strcmp(BIDI_NUMERAL_PREF, aPref)) {
|
||||
mBidiNumeralOption = UNINITIALIZED_VALUE;
|
||||
} else if (!strcmp(GFX_PREF_OPENTYPE_SVG, aPref)) {
|
||||
|
|
|
@ -403,6 +403,16 @@ public:
|
|||
*/
|
||||
bool OpenTypeSVGEnabled();
|
||||
|
||||
/**
|
||||
* Max character length of words in the word cache
|
||||
*/
|
||||
uint32_t WordCacheCharLimit();
|
||||
|
||||
/**
|
||||
* Max number of entries in word cache
|
||||
*/
|
||||
uint32_t WordCacheMaxEntries();
|
||||
|
||||
/**
|
||||
* Whether to use the SIL Graphite rendering engine
|
||||
* (for fonts that include Graphite tables)
|
||||
|
@ -672,6 +682,12 @@ protected:
|
|||
// which scripts should be shaped with harfbuzz
|
||||
int32_t mUseHarfBuzzScripts;
|
||||
|
||||
// max character limit for words in word cache
|
||||
int32_t mWordCacheCharLimit;
|
||||
|
||||
// max number of entries in word cache
|
||||
int32_t mWordCacheMaxEntries;
|
||||
|
||||
private:
|
||||
/**
|
||||
* Start up Thebes.
|
||||
|
|
|
@ -2024,7 +2024,8 @@ IsCacheableSetPropCallNative(HandleObject obj, HandleObject holder, HandleShape
|
|||
if (!shape || !IsCacheableProtoChain(obj, holder))
|
||||
return false;
|
||||
|
||||
return shape->hasSetterValue() && shape->setterObject()->is<JSFunction>() &&
|
||||
return shape->hasSetterValue() && shape->setterObject() &&
|
||||
shape->setterObject()->is<JSFunction>() &&
|
||||
shape->setterObject()->as<JSFunction>().isNative();
|
||||
}
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include "frontend/BytecodeCompiler.h"
|
||||
#include "jit/ExecutionModeInlines.h"
|
||||
#include "jit/IonBuilder.h"
|
||||
#include "vm/Debugger.h"
|
||||
|
||||
#include "jscntxtinlines.h"
|
||||
#include "jscompartmentinlines.h"
|
||||
|
@ -499,12 +500,40 @@ WorkerThreadState::canStartCompressionTask()
|
|||
return !compressionWorklist.empty();
|
||||
}
|
||||
|
||||
static void
|
||||
CallNewScriptHookForAllScripts(JSContext *cx, HandleScript script)
|
||||
{
|
||||
// We should never hit this, since nested scripts are also constructed via
|
||||
// BytecodeEmitter instances on the stack.
|
||||
JS_CHECK_RECURSION(cx, return);
|
||||
|
||||
// Recurse to any nested scripts.
|
||||
if (script->hasObjects()) {
|
||||
ObjectArray *objects = script->objects();
|
||||
for (size_t i = 0; i < objects->length; i++) {
|
||||
JSObject *obj = objects->vector[i];
|
||||
if (obj->is<JSFunction>()) {
|
||||
JSFunction *fun = &obj->as<JSFunction>();
|
||||
if (fun->hasScript()) {
|
||||
RootedScript nested(cx, fun->nonLazyScript());
|
||||
CallNewScriptHookForAllScripts(cx, nested);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The global new script hook is called on every script that was compiled.
|
||||
RootedFunction function(cx, script->function());
|
||||
CallNewScriptHook(cx, script, function);
|
||||
}
|
||||
|
||||
JSScript *
|
||||
WorkerThreadState::finishParseTask(JSContext *maybecx, JSRuntime *rt, void *token)
|
||||
{
|
||||
ParseTask *parseTask = NULL;
|
||||
|
||||
// The token is a ParseTask* which should be in the finished list.
|
||||
// Find and remove its entry.
|
||||
{
|
||||
AutoLockWorkerThreadState lock(*rt->workerThreadState);
|
||||
for (size_t i = 0; i < parseFinishedList.length(); i++) {
|
||||
|
@ -548,15 +577,27 @@ WorkerThreadState::finishParseTask(JSContext *maybecx, JSRuntime *rt, void *toke
|
|||
// Move the parsed script and all its contents into the desired compartment.
|
||||
gc::MergeCompartments(parseTask->cx->compartment(), parseTask->scopeChain->compartment());
|
||||
|
||||
RootedScript script(rt, parseTask->script);
|
||||
|
||||
// If we have a context, report any error or warnings generated during the
|
||||
// parse.
|
||||
// parse, and inform the debugger about the compiled scripts.
|
||||
if (maybecx) {
|
||||
AutoCompartment ac(maybecx, parseTask->scopeChain);
|
||||
for (size_t i = 0; i < parseTask->errors.length(); i++)
|
||||
parseTask->errors[i]->throwError(maybecx);
|
||||
|
||||
if (script) {
|
||||
// The Debugger only needs to be told about the topmost script that was compiled.
|
||||
GlobalObject *compileAndGoGlobal = NULL;
|
||||
if (script->compileAndGo)
|
||||
compileAndGoGlobal = &script->global();
|
||||
Debugger::onNewScript(maybecx, script, compileAndGoGlobal);
|
||||
|
||||
// The NewScript hook needs to be called for all compiled scripts.
|
||||
CallNewScriptHookForAllScripts(maybecx, script);
|
||||
}
|
||||
}
|
||||
|
||||
JSScript *script = parseTask->script;
|
||||
js_delete(parseTask);
|
||||
return script;
|
||||
}
|
||||
|
|
|
@ -51,7 +51,6 @@ simple_events = [
|
|||
#endif
|
||||
'DeviceStorageChangeEvent',
|
||||
'PopupBlockedEvent',
|
||||
'BlobEvent',
|
||||
'RecordErrorEvent',
|
||||
#ifdef MOZ_GAMEPAD
|
||||
'GamepadEvent',
|
||||
|
|
|
@ -435,7 +435,7 @@ typedef uint32_t nsReflowStatus;
|
|||
#define NS_FRAME_IS_FULLY_COMPLETE(status) \
|
||||
(NS_FRAME_IS_COMPLETE(status) && !NS_FRAME_OVERFLOW_IS_INCOMPLETE(status))
|
||||
|
||||
// These macros set or switch incompete statuses without touching th
|
||||
// These macros set or switch incomplete statuses without touching the
|
||||
// NS_FRAME_REFLOW_NEXTINFLOW bit.
|
||||
#define NS_FRAME_SET_INCOMPLETE(status) \
|
||||
status = (status & ~NS_FRAME_OVERFLOW_INCOMPLETE) | NS_FRAME_NOT_COMPLETE
|
||||
|
|
|
@ -73,8 +73,8 @@ load 645142.html
|
|||
load 611922-1.html
|
||||
== 645951-1.html 645951-1-ref.html
|
||||
load 665209-1.html
|
||||
asserts(2) load 671799-1.html
|
||||
asserts(2) load 671799-2.html
|
||||
load 671799-1.html
|
||||
load 671799-2.html
|
||||
load 690990-1.html
|
||||
load 696188-1.html
|
||||
load 700116.html
|
||||
|
|
|
@ -622,7 +622,12 @@ nsUserFontSet::InsertRule(nsCSSFontFaceRule *aRule, uint8_t aSheetType,
|
|||
case eCSSUnit_URL:
|
||||
face->mIsLocal = false;
|
||||
face->mURI = val.GetURLValue();
|
||||
NS_ASSERTION(face->mURI, "null url in @font-face rule");
|
||||
if (!face->mURI) {
|
||||
// if URI not valid, omit from src array
|
||||
srcArray.RemoveElementAt(srcArray.Length() - 1);
|
||||
NS_WARNING("null url in @font-face rule");
|
||||
continue;
|
||||
}
|
||||
face->mReferrer = val.GetURLStructValue()->mReferrer;
|
||||
face->mOriginPrincipal = val.GetURLStructValue()->mOriginPrincipal;
|
||||
NS_ASSERTION(face->mOriginPrincipal, "null origin principal in @font-face rule");
|
||||
|
|
|
@ -404,6 +404,17 @@ static int nr_stun_client_get_password(void *arg, nr_stun_message *msg, Data **p
|
|||
return(0);
|
||||
}
|
||||
|
||||
int nr_stun_transport_addr_check(nr_transport_addr* addr)
|
||||
{
|
||||
if(nr_transport_addr_is_wildcard(addr))
|
||||
return(R_BAD_DATA);
|
||||
|
||||
if (nr_transport_addr_is_loopback(addr))
|
||||
return(R_BAD_DATA);
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
int nr_stun_client_process_response(nr_stun_client_ctx *ctx, UCHAR *msg, int len, nr_transport_addr *peer_addr)
|
||||
{
|
||||
int r,_status;
|
||||
|
@ -622,6 +633,9 @@ int nr_stun_client_process_response(nr_stun_client_ctx *ctx, UCHAR *msg, int len
|
|||
if (!nr_stun_message_has_attribute(ctx->response, NR_STUN_ATTR_XOR_RELAY_ADDRESS, &attr))
|
||||
ABORT(R_BAD_DATA);
|
||||
|
||||
if ((r=nr_stun_transport_addr_check(&attr->u.relay_address.unmasked)))
|
||||
ABORT(r);
|
||||
|
||||
if ((r=nr_transport_addr_copy(
|
||||
&ctx->results.allocate_response.relay_addr,
|
||||
&attr->u.relay_address.unmasked)))
|
||||
|
@ -663,10 +677,16 @@ int nr_stun_client_process_response(nr_stun_client_ctx *ctx, UCHAR *msg, int len
|
|||
|
||||
if (mapped_addr) {
|
||||
if (nr_stun_message_has_attribute(ctx->response, NR_STUN_ATTR_XOR_MAPPED_ADDRESS, &attr)) {
|
||||
if ((r=nr_stun_transport_addr_check(&attr->u.xor_mapped_address.unmasked)))
|
||||
ABORT(r);
|
||||
|
||||
if ((r=nr_transport_addr_copy(mapped_addr, &attr->u.xor_mapped_address.unmasked)))
|
||||
ABORT(r);
|
||||
}
|
||||
else if (nr_stun_message_has_attribute(ctx->response, NR_STUN_ATTR_MAPPED_ADDRESS, &attr)) {
|
||||
if ((r=nr_stun_transport_addr_check(&attr->u.mapped_address)))
|
||||
ABORT(r);
|
||||
|
||||
if ((r=nr_transport_addr_copy(mapped_addr, &attr->u.mapped_address)))
|
||||
ABORT(r);
|
||||
}
|
||||
|
|
|
@ -188,6 +188,7 @@ int nr_stun_client_restart(nr_stun_client_ctx *ctx);
|
|||
int nr_stun_client_force_retransmit(nr_stun_client_ctx *ctx);
|
||||
int nr_stun_client_reset(nr_stun_client_ctx *ctx);
|
||||
int nr_stun_client_ctx_destroy(nr_stun_client_ctx **ctxp);
|
||||
int nr_stun_transport_addr_check(nr_transport_addr* addr);
|
||||
int nr_stun_client_process_response(nr_stun_client_ctx *ctx, UCHAR *msg, int len, nr_transport_addr *peer_addr);
|
||||
int nr_stun_client_cancel(nr_stun_client_ctx *ctx);
|
||||
|
||||
|
|
|
@ -15,8 +15,8 @@ import java.util.HashMap;
|
|||
* default values for them
|
||||
*/
|
||||
public class testSettingsMenuItems extends PixelTest {
|
||||
int midWidth;
|
||||
int midHeight;
|
||||
int mMidWidth;
|
||||
int mMidHeight;
|
||||
String BRAND_NAME = "(Fennec|Nightly|Aurora|Firefox|Firefox Beta)";
|
||||
|
||||
/**
|
||||
|
@ -91,8 +91,8 @@ public class testSettingsMenuItems extends PixelTest {
|
|||
|
||||
public void testSettingsMenuItems() {
|
||||
blockForGeckoReady();
|
||||
midWidth = mDriver.getGeckoWidth()/2;
|
||||
midHeight = mDriver.getGeckoHeight()/2;
|
||||
mMidWidth = mDriver.getGeckoWidth()/2;
|
||||
mMidHeight = mDriver.getGeckoHeight()/2;
|
||||
|
||||
Map<String, List<String[]>> settingsMenuItems = new HashMap<String, List<String[]>>();
|
||||
setupSettingsMap(settingsMenuItems);
|
||||
|
@ -212,40 +212,35 @@ public class testSettingsMenuItems extends PixelTest {
|
|||
|
||||
// Check item title.
|
||||
String itemTitle = "^" + item[0] + "$";
|
||||
if (!waitForText(itemTitle)) {
|
||||
// If we don't see the item, scroll down once in case it's off-screen.
|
||||
scrollDown();
|
||||
}
|
||||
mAsserter.ok(mSolo.waitForText(itemTitle), "Waiting for settings item " + itemTitle + " in section " + section,
|
||||
boolean foundText = waitExtraForText(itemTitle);
|
||||
mAsserter.ok(foundText, "Waiting for settings item " + itemTitle + " in section " + section,
|
||||
"The " + itemTitle + " option is present in section " + section);
|
||||
// Check item default, if it exists.
|
||||
if (itemLen > 1) {
|
||||
String itemDefault = "^" + item[1] + "$";
|
||||
mAsserter.ok(mSolo.waitForText(itemDefault), "Waiting for settings item default " + itemDefault
|
||||
foundText = waitExtraForText(itemDefault);
|
||||
mAsserter.ok(foundText, "Waiting for settings item default " + itemDefault
|
||||
+ " in section " + section,
|
||||
"The " + itemDefault + " default is present in section " + section);
|
||||
}
|
||||
// Check item choices, if they exist.
|
||||
if (itemLen > 2) {
|
||||
waitForEnabledText(itemTitle);
|
||||
mSolo.clickOnText(itemTitle);
|
||||
for (int i = 2; i < itemLen; i++) {
|
||||
String itemChoice = "^" + item[i] + "$";
|
||||
if (!waitForText(itemChoice)) {
|
||||
// If we don't see the item, scroll down once in case it's off-screen.
|
||||
scrollDown();
|
||||
}
|
||||
mAsserter.ok(mSolo.waitForText(itemChoice), "Waiting for settings item choice " + itemChoice
|
||||
+ " in section " + section,
|
||||
"The " + itemChoice + " choice is present in section " + section);
|
||||
}
|
||||
// Leave submenu after checking.
|
||||
if (waitForText("^Cancel$")) {
|
||||
mSolo.clickOnText("^Cancel$");
|
||||
} else {
|
||||
// Some submenus aren't dialogs, but are nested screens; exit using "back".
|
||||
mActions.sendSpecialKey(Actions.SpecialKey.BACK);
|
||||
}
|
||||
waitForEnabledText(itemTitle);
|
||||
mSolo.clickOnText(itemTitle);
|
||||
for (int i = 2; i < itemLen; i++) {
|
||||
String itemChoice = "^" + item[i] + "$";
|
||||
foundText = waitExtraForText(itemChoice);
|
||||
mAsserter.ok(foundText, "Waiting for settings item choice " + itemChoice
|
||||
+ " in section " + section,
|
||||
"The " + itemChoice + " choice is present in section " + section);
|
||||
}
|
||||
// Leave submenu after checking.
|
||||
if (waitForText("^Cancel$")) {
|
||||
mSolo.clickOnText("^Cancel$");
|
||||
} else {
|
||||
// Some submenus aren't dialogs, but are nested screens; exit using "back".
|
||||
mActions.sendSpecialKey(Actions.SpecialKey.BACK);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Navigate back a screen if on a phone.
|
||||
|
@ -256,13 +251,19 @@ public class testSettingsMenuItems extends PixelTest {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Hacky way to scroll down.
|
||||
*
|
||||
* solo.scroll* does not work in dialogs.
|
||||
*/
|
||||
private void scrollDown() {
|
||||
MotionEventHelper meh = new MotionEventHelper(getInstrumentation(), mDriver.getGeckoLeft(), mDriver.getGeckoTop());
|
||||
meh.dragSync(midWidth, midHeight+100, midWidth, midHeight-100);
|
||||
// Solo.waitForText usually scrolls down in a view when text is not visible.
|
||||
// In this test, Solo.waitForText scrolling does not work, so we use this
|
||||
// hack to do the same thing.
|
||||
private boolean waitExtraForText(String txt) {
|
||||
boolean foundText = waitForText(txt);
|
||||
if (!foundText) {
|
||||
// If we don't see the item, scroll down once in case it's off-screen.
|
||||
// Hacky way to scroll down. solo.scroll* does not work in dialogs.
|
||||
MotionEventHelper meh = new MotionEventHelper(getInstrumentation(), mDriver.getGeckoLeft(), mDriver.getGeckoTop());
|
||||
meh.dragSync(mMidWidth, mMidHeight+100, mMidWidth, mMidHeight-100);
|
||||
|
||||
foundText = mSolo.waitForText(txt);
|
||||
}
|
||||
return foundText;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -73,7 +73,7 @@ var FeedHandler = {
|
|||
let feedIndex = -1;
|
||||
if (feeds.length > 1) {
|
||||
let p = new Prompt({
|
||||
window: browser.contentWindow,
|
||||
window: browser.contentWindow
|
||||
}).setSingleChoiceItems(feeds.map(function(feed) {
|
||||
return { label: feed.title || feed.href }
|
||||
})).show((function(data) {
|
||||
|
@ -91,29 +91,28 @@ var FeedHandler = {
|
|||
},
|
||||
|
||||
loadFeed: function fh_loadFeed(aFeed, aBrowser) {
|
||||
let feedURL = aFeed.href;
|
||||
let feedURL = aFeed.href;
|
||||
|
||||
// Next, we decide on which service to send the feed
|
||||
let handlers = this.getContentHandlers(this.TYPE_MAYBE_FEED);
|
||||
if (handlers.length == 0)
|
||||
// Next, we decide on which service to send the feed
|
||||
let handlers = this.getContentHandlers(this.TYPE_MAYBE_FEED);
|
||||
if (handlers.length == 0)
|
||||
return;
|
||||
|
||||
// JSON for Prompt
|
||||
let p = new Prompt({
|
||||
window: aBrowser.contentWindow
|
||||
}).setSingleChoiceItems(handlers.map(function(handler) {
|
||||
return { label: handler.name };
|
||||
})).show(function(data) {
|
||||
if (data.button == -1)
|
||||
return;
|
||||
|
||||
// JSON for Prompt
|
||||
let p = new Prompt({
|
||||
window: aBrowser.contentWindow
|
||||
}).setSingleChoiceItems(handlers.map(function(handler) {
|
||||
return { label: handler.name };
|
||||
})).show(function(data) {
|
||||
if (data.button == -1)
|
||||
return;
|
||||
|
||||
// Merge the handler URL and the feed URL
|
||||
let readerURL = handlers[data.button].uri;
|
||||
readerURL = readerURL.replace(/%s/gi, encodeURIComponent(feedURL));
|
||||
|
||||
// Open the resultant URL in a new tab
|
||||
BrowserApp.addTab(readerURL, { parentId: BrowserApp.selectedTab.id });
|
||||
});
|
||||
// Merge the handler URL and the feed URL
|
||||
let readerURL = handlers[data.button].uri;
|
||||
readerURL = readerURL.replace(/%s/gi, encodeURIComponent(feedURL));
|
||||
|
||||
// Open the resultant URL in a new tab
|
||||
BrowserApp.addTab(readerURL, { parentId: BrowserApp.selectedTab.id });
|
||||
});
|
||||
}
|
||||
};
|
||||
|
|
|
@ -29,5 +29,3 @@ gecko.handlerService.schemes.mailto.1.uriTemplate=https://mail.google.com/mail/?
|
|||
# selection UI
|
||||
browser.contentHandlers.types.0.title=My Yahoo!
|
||||
browser.contentHandlers.types.0.uri=http://add.my.yahoo.com/rss?url=%s
|
||||
browser.contentHandlers.types.1.title=Google
|
||||
browser.contentHandlers.types.1.uri=http://fusion.google.com/add?feedurl=%s
|
||||
|
|
|
@ -292,6 +292,12 @@ pref("gfx.font_loader.interval", 50); // run every 50 ms
|
|||
// whether to always search all font cmaps during system font fallback
|
||||
pref("gfx.font_rendering.fallback.always_use_cmaps", false);
|
||||
|
||||
// cache shaped word results
|
||||
pref("gfx.font_rendering.wordcache.charlimit", 32);
|
||||
|
||||
// cache shaped word results
|
||||
pref("gfx.font_rendering.wordcache.maxentries", 10000);
|
||||
|
||||
pref("gfx.font_rendering.graphite.enabled", true);
|
||||
|
||||
// Check intl/unicharutil/util/nsUnicodeProperties.h for definitions of script bits
|
||||
|
|
|
@ -195,15 +195,19 @@ class OSXBootstrapper(BaseBootstrapper):
|
|||
packages = [
|
||||
# We need to install Python because Mercurial requires the Python
|
||||
# development headers which are missing from OS X (at least on
|
||||
# 10.8).
|
||||
# 10.8) and because the build system wants a version newer than
|
||||
# what Apple ships.
|
||||
('python', 'python'),
|
||||
('mercurial', 'mercurial'),
|
||||
('git', 'git'),
|
||||
('yasm', 'yasm'),
|
||||
('autoconf213', HOMEBREW_AUTOCONF213),
|
||||
('terminal-notifier', 'terminal-notifier'),
|
||||
]
|
||||
|
||||
# terminal-notifier is only available in Mountain Lion or newer.
|
||||
if self.os_version >= StrictVersion('10.8'):
|
||||
packages.append(('terminal-notifier', 'terminal-notifier'))
|
||||
|
||||
printed = False
|
||||
|
||||
for name, package in packages:
|
||||
|
|
|
@ -21,6 +21,7 @@ from ..frontend.data import (
|
|||
ConfigFileSubstitution,
|
||||
DirectoryTraversal,
|
||||
Exports,
|
||||
GeneratedEventWebIDLFile,
|
||||
GeneratedWebIDLFile,
|
||||
IPDLFile,
|
||||
LocalInclude,
|
||||
|
@ -127,6 +128,7 @@ class RecursiveMakeBackend(CommonBackend):
|
|||
self._backend_files = {}
|
||||
self._ipdl_sources = set()
|
||||
self._webidl_sources = set()
|
||||
self._generated_events_webidl_sources = set()
|
||||
self._test_webidl_sources = set()
|
||||
self._preprocessed_webidl_sources = set()
|
||||
self._generated_webidl_sources = set()
|
||||
|
@ -209,18 +211,25 @@ class RecursiveMakeBackend(CommonBackend):
|
|||
|
||||
elif isinstance(obj, WebIDLFile):
|
||||
self._webidl_sources.add(mozpath.join(obj.srcdir, obj.basename))
|
||||
self._process_webidl_basename(obj.basename)
|
||||
|
||||
elif isinstance(obj, GeneratedEventWebIDLFile):
|
||||
self._generated_events_webidl_sources.add(mozpath.join(obj.srcdir, obj.basename))
|
||||
|
||||
elif isinstance(obj, TestWebIDLFile):
|
||||
self._test_webidl_sources.add(mozpath.join(obj.srcdir,
|
||||
obj.basename))
|
||||
# Test WebIDL files are not exported.
|
||||
|
||||
elif isinstance(obj, GeneratedWebIDLFile):
|
||||
self._generated_webidl_sources.add(mozpath.join(obj.srcdir,
|
||||
obj.basename))
|
||||
self._process_webidl_basename(obj.basename)
|
||||
|
||||
elif isinstance(obj, PreprocessedWebIDLFile):
|
||||
self._preprocessed_webidl_sources.add(mozpath.join(obj.srcdir,
|
||||
obj.basename))
|
||||
self._process_webidl_basename(obj.basename)
|
||||
|
||||
elif isinstance(obj, Program):
|
||||
self._process_program(obj.program, backend_file)
|
||||
|
@ -301,6 +310,8 @@ class RecursiveMakeBackend(CommonBackend):
|
|||
|
||||
for webidl in sorted(self._webidl_sources):
|
||||
webidls.write('webidl_files += %s\n' % os.path.basename(webidl))
|
||||
for webidl in sorted(self._generated_events_webidl_sources):
|
||||
webidls.write('generated_events_webidl_files += %s\n' % os.path.basename(webidl))
|
||||
for webidl in sorted(self._test_webidl_sources):
|
||||
webidls.write('test_webidl_files += %s\n' % os.path.basename(webidl))
|
||||
for webidl in sorted(self._generated_webidl_sources):
|
||||
|
@ -470,6 +481,10 @@ class RecursiveMakeBackend(CommonBackend):
|
|||
def _process_program(self, program, backend_file):
|
||||
backend_file.write('PROGRAM = %s\n' % program)
|
||||
|
||||
def _process_webidl_basename(self, basename):
|
||||
header = 'mozilla/dom/%sBinding.h' % os.path.splitext(basename)[0]
|
||||
self._install_manifests['dist_include'].add_optional_exists(header)
|
||||
|
||||
def _process_xpcshell_manifests(self, obj, backend_file, namespace=""):
|
||||
manifest = obj.xpcshell_manifests
|
||||
backend_file.write('XPCSHELL_TESTS += %s\n' % os.path.dirname(manifest))
|
||||
|
|
|
@ -193,6 +193,18 @@ class WebIDLFile(SandboxDerived):
|
|||
|
||||
self.basename = path
|
||||
|
||||
class GeneratedEventWebIDLFile(SandboxDerived):
|
||||
"""Describes an individual .webidl source file."""
|
||||
|
||||
__slots__ = (
|
||||
'basename',
|
||||
)
|
||||
|
||||
def __init__(self, sandbox, path):
|
||||
SandboxDerived.__init__(self, sandbox)
|
||||
|
||||
self.basename = path
|
||||
|
||||
class TestWebIDLFile(SandboxDerived):
|
||||
"""Describes an individual test-only .webidl source file."""
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@ from .data import (
|
|||
ConfigFileSubstitution,
|
||||
DirectoryTraversal,
|
||||
Exports,
|
||||
GeneratedEventWebIDLFile,
|
||||
GeneratedWebIDLFile,
|
||||
IPDLFile,
|
||||
LocalInclude,
|
||||
|
@ -178,6 +179,9 @@ class TreeMetadataEmitter(LoggingMixin):
|
|||
for webidl in sandbox.get('WEBIDL_FILES', []):
|
||||
yield WebIDLFile(sandbox, webidl)
|
||||
|
||||
for webidl in sandbox.get('GENERATED_EVENTS_WEBIDL_FILES', []):
|
||||
yield GeneratedEventWebIDLFile(sandbox, webidl)
|
||||
|
||||
for webidl in sandbox.get('TEST_WEBIDL_FILES', []):
|
||||
yield TestWebIDLFile(sandbox, webidl)
|
||||
|
||||
|
|
|
@ -399,6 +399,12 @@ VARIABLES = {
|
|||
These will be parsed and converted to .cpp and .h files.
|
||||
"""),
|
||||
|
||||
'GENERATED_EVENTS_WEBIDL_FILES': (StrictOrderingOnAppendList, list, [],
|
||||
"""WebIDL source files for generated events.
|
||||
|
||||
These will be parsed and converted to .cpp and .h files.
|
||||
"""),
|
||||
|
||||
'TEST_WEBIDL_FILES': (StrictOrderingOnAppendList, list, [],
|
||||
"""Test WebIDL source files.
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@ class Makefile(object):
|
|||
'''
|
||||
|
||||
def __init__(self):
|
||||
self._rules = []
|
||||
self._statements = []
|
||||
|
||||
def create_rule(self, targets=[]):
|
||||
'''
|
||||
|
@ -23,9 +23,16 @@ class Makefile(object):
|
|||
Returns the corresponding Rule instance.
|
||||
'''
|
||||
rule = Rule(targets)
|
||||
self._rules.append(rule)
|
||||
self._statements.append(rule)
|
||||
return rule
|
||||
|
||||
def add_statement(self, statement):
|
||||
'''
|
||||
Add a raw statement in the makefile. Meant to be used for
|
||||
simple variable assignments.
|
||||
'''
|
||||
self._statements.append(statement)
|
||||
|
||||
def dump(self, fh, removal_guard=True):
|
||||
'''
|
||||
Dump all the rules to the given file handle. Optionally (and by
|
||||
|
@ -34,12 +41,15 @@ class Makefile(object):
|
|||
'''
|
||||
all_deps = set()
|
||||
all_targets = set()
|
||||
for rule in self._rules:
|
||||
rule.dump(fh)
|
||||
all_deps.update(rule.dependencies())
|
||||
all_targets.update(rule.targets())
|
||||
for statement in self._statements:
|
||||
if isinstance(statement, Rule):
|
||||
statement.dump(fh)
|
||||
all_deps.update(statement.dependencies())
|
||||
all_targets.update(statement.targets())
|
||||
else:
|
||||
fh.write('%s\n' % statement)
|
||||
if removal_guard:
|
||||
guard = Rule(all_deps - all_targets)
|
||||
guard = Rule(sorted(all_deps - all_targets))
|
||||
guard.dump(fh)
|
||||
|
||||
|
||||
|
@ -51,21 +61,23 @@ class Rule(object):
|
|||
...
|
||||
'''
|
||||
def __init__(self, targets=[]):
|
||||
self._targets = set()
|
||||
self._dependencies = set()
|
||||
self._targets = []
|
||||
self._dependencies = []
|
||||
self._commands = []
|
||||
self.add_targets(targets)
|
||||
|
||||
def add_targets(self, targets):
|
||||
'''Add additional targets to the rule.'''
|
||||
assert isinstance(targets, Iterable) and not isinstance(targets, StringTypes)
|
||||
self._targets.update(t.replace(os.sep, '/') for t in targets)
|
||||
self._targets.extend(t.replace(os.sep, '/') for t in targets
|
||||
if not t in self._targets)
|
||||
return self
|
||||
|
||||
def add_dependencies(self, deps):
|
||||
'''Add dependencies to the rule.'''
|
||||
assert isinstance(deps, Iterable) and not isinstance(deps, StringTypes)
|
||||
self._dependencies.update(d.replace(os.sep, '/') for d in deps)
|
||||
self._dependencies.extend(d.replace(os.sep, '/') for d in deps
|
||||
if not d in self._dependencies)
|
||||
return self
|
||||
|
||||
def add_commands(self, commands):
|
||||
|
@ -94,9 +106,9 @@ class Rule(object):
|
|||
'''
|
||||
if not self._targets:
|
||||
return
|
||||
fh.write('%s:' % ' '.join(sorted(self._targets)))
|
||||
fh.write('%s:' % ' '.join(self._targets))
|
||||
if self._dependencies:
|
||||
fh.write(' %s' % ' '.join(sorted(self._dependencies)))
|
||||
fh.write(' %s' % ' '.join(self._dependencies))
|
||||
fh.write('\n')
|
||||
for cmd in self._commands:
|
||||
fh.write('\t%s\n' % cmd)
|
||||
|
|
|
@ -22,19 +22,13 @@ class TestMakefile(unittest.TestCase):
|
|||
|
||||
rule.add_targets(['foo', 'bar'])
|
||||
rule.dump(out)
|
||||
self.assertEqual(out.getvalue(), 'bar foo:\n')
|
||||
self.assertEqual(out.getvalue(), 'foo bar:\n')
|
||||
out.truncate(0)
|
||||
|
||||
rule.add_targets(['baz'])
|
||||
rule.add_dependencies(['qux', 'hoge', 'piyo'])
|
||||
rule.dump(out)
|
||||
self.assertEqual(out.getvalue(), 'bar baz foo: hoge piyo qux\n')
|
||||
out.truncate(0)
|
||||
|
||||
rule.add_targets(['baz'])
|
||||
rule.add_dependencies(['qux', 'hoge', 'piyo'])
|
||||
rule.dump(out)
|
||||
self.assertEqual(out.getvalue(), 'bar baz foo: hoge piyo qux\n')
|
||||
self.assertEqual(out.getvalue(), 'foo bar baz: qux hoge piyo\n')
|
||||
out.truncate(0)
|
||||
|
||||
rule = Rule(['foo', 'bar'])
|
||||
|
@ -43,7 +37,7 @@ class TestMakefile(unittest.TestCase):
|
|||
rule.add_commands(['$(BAZ) -o $@ $<', '$(TOUCH) $@'])
|
||||
rule.dump(out)
|
||||
self.assertEqual(out.getvalue(),
|
||||
'bar foo: baz\n' +
|
||||
'foo bar: baz\n' +
|
||||
'\techo $@\n' +
|
||||
'\t$(BAZ) -o $@ $<\n' +
|
||||
'\t$(TOUCH) $@\n')
|
||||
|
@ -73,6 +67,21 @@ class TestMakefile(unittest.TestCase):
|
|||
'\techo $@\n' +
|
||||
'hoge qux:\n')
|
||||
|
||||
def test_statement(self):
|
||||
out = StringIO()
|
||||
mk = Makefile()
|
||||
mk.create_rule(['foo']).add_dependencies(['bar']) \
|
||||
.add_commands(['echo foo'])
|
||||
mk.add_statement('BAR = bar')
|
||||
mk.create_rule(['$(BAR)']).add_commands(['echo $@'])
|
||||
mk.dump(out, removal_guard=False)
|
||||
self.assertEqual(out.getvalue(),
|
||||
'foo: bar\n' +
|
||||
'\techo foo\n' +
|
||||
'BAR = bar\n' +
|
||||
'$(BAR):\n' +
|
||||
'\techo $@\n')
|
||||
|
||||
@unittest.skipIf(os.name != 'nt', 'Test only applicable on Windows.')
|
||||
def test_path_normalization(self):
|
||||
out = StringIO()
|
||||
|
|
|
@ -9,7 +9,9 @@ Maintainers
|
|||
Brian Rosner
|
||||
Carl Meyer
|
||||
Jannis Leidel
|
||||
Paul Moore
|
||||
Paul Nasrat
|
||||
Marcus Smith
|
||||
|
||||
Contributors
|
||||
------------
|
||||
|
@ -17,42 +19,73 @@ Contributors
|
|||
Alex Grönholm
|
||||
Anatoly Techtonik
|
||||
Antonio Cuni
|
||||
Antonio Valentino
|
||||
Armin Ronacher
|
||||
Barry Warsaw
|
||||
Benjamin Root
|
||||
Bradley Ayers
|
||||
Branden Rolston
|
||||
Brandon Carl
|
||||
Brian Kearns
|
||||
Cap Petschulat
|
||||
CBWhiz
|
||||
Chris Adams
|
||||
Chris McDonough
|
||||
Christos Kontas
|
||||
Christian Hudon
|
||||
Christian Stefanescu
|
||||
Christopher Nilsson
|
||||
Cliff Xuan
|
||||
Curt Micol
|
||||
Damien Nozay
|
||||
Dan Sully
|
||||
Daniel Hahler
|
||||
Daniel Holth
|
||||
David Schoonover
|
||||
Denis Costa
|
||||
Doug Hellmann
|
||||
Doug Napoleone
|
||||
Douglas Creager
|
||||
Eduard-Cristian Stefan
|
||||
Erik M. Bray
|
||||
Ethan Jucovy
|
||||
Gabriel de Perthuis
|
||||
Gunnlaugur Thor Briem
|
||||
Graham Dennis
|
||||
Greg Haskins
|
||||
Jason Penney
|
||||
Jason R. Coombs
|
||||
Jeff Hammel
|
||||
Jeremy Orem
|
||||
Jason Penney
|
||||
Jason R. Coombs
|
||||
John Kleint
|
||||
Jonathan Griffin
|
||||
Jonathan Hitchcock
|
||||
Jorge Vargas
|
||||
Josh Bronson
|
||||
Kamil Kisiel
|
||||
Kyle Gibson
|
||||
Konstantin Zemlyak
|
||||
Kumar McMillan
|
||||
Lars Francke
|
||||
Marc Abramowitz
|
||||
Mika Laitio
|
||||
Mike Hommey
|
||||
Miki Tebeka
|
||||
Paul Moore
|
||||
Philip Jenvey
|
||||
Philippe Ombredanne
|
||||
Piotr Dobrogost
|
||||
Preston Holmes
|
||||
Ralf Schmitt
|
||||
Raul Leal
|
||||
Ronny Pfannschmidt
|
||||
Satrajit Ghosh
|
||||
Sergio de Carvalho
|
||||
Stefano Rivera
|
||||
Tarek Ziadé
|
||||
Thomas Aglassinger
|
||||
Vinay Sajip
|
||||
Vitaly Babiy
|
||||
Vladimir Rutsky
|
||||
Wang Xuerui
|
|
@ -1,6 +1,6 @@
|
|||
Copyright (c) 2007 Ian Bicking and Contributors
|
||||
Copyright (c) 2009 Ian Bicking, The Open Planning Project
|
||||
Copyright (c) 2011-2012 The virtualenv developers
|
||||
Copyright (c) 2011-2013 The virtualenv developers
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
Metadata-Version: 1.1
|
||||
Name: virtualenv
|
||||
Version: 1.8.4
|
||||
Version: 1.10.1
|
||||
Summary: Virtual Python Environment builder
|
||||
Home-page: http://www.virtualenv.org
|
||||
Author: Jannis Leidel, Carl Meyer and Brian Rosner
|
||||
|
@ -8,28 +8,15 @@ Author-email: python-virtualenv@groups.google.com
|
|||
License: MIT
|
||||
Description:
|
||||
|
||||
Installation
|
||||
------------
|
||||
|
||||
You can install virtualenv with ``pip install virtualenv``, or the `latest
|
||||
development version <https://github.com/pypa/virtualenv/tarball/develop>`_
|
||||
with ``pip install https://github.com/pypa/virtualenv/tarball/develop``.
|
||||
|
||||
You can also use ``easy_install``, or if you have no Python package manager
|
||||
available at all, you can just grab the single file `virtualenv.py`_ and run
|
||||
it with ``python virtualenv.py``.
|
||||
|
||||
.. _virtualenv.py: https://raw.github.com/pypa/virtualenv/master/virtualenv.py
|
||||
|
||||
What It Does
|
||||
------------
|
||||
|
||||
``virtualenv`` is a tool to create isolated Python environments.
|
||||
|
||||
The basic problem being addressed is one of dependencies and versions,
|
||||
and indirectly permissions. Imagine you have an application that
|
||||
and indirectly permissions. Imagine you have an application that
|
||||
needs version 1 of LibFoo, but another application requires version
|
||||
2. How can you use both these applications? If you install
|
||||
2. How can you use both these applications? If you install
|
||||
everything into ``/usr/lib/python2.7/site-packages`` (or whatever your
|
||||
platform's standard location is), it's easy to end up in a situation
|
||||
where you unintentionally upgrade an application that shouldn't be
|
||||
|
@ -42,39 +29,99 @@ Description:
|
|||
Also, what if you can't install packages into the global
|
||||
``site-packages`` directory? For instance, on a shared host.
|
||||
|
||||
In all these cases, ``virtualenv`` can help you. It creates an
|
||||
In all these cases, ``virtualenv`` can help you. It creates an
|
||||
environment that has its own installation directories, that doesn't
|
||||
share libraries with other virtualenv environments (and optionally
|
||||
doesn't access the globally installed libraries either).
|
||||
|
||||
|
||||
Installation
|
||||
------------
|
||||
|
||||
.. warning::
|
||||
|
||||
We advise installing virtualenv-1.9 or greater. Prior to version 1.9, the
|
||||
pip included in virtualenv did not not download from PyPI over SSL.
|
||||
|
||||
.. warning::
|
||||
|
||||
When using pip to install virtualenv, we advise using pip 1.3 or greater.
|
||||
Prior to version 1.3, pip did not not download from PyPI over SSL.
|
||||
|
||||
.. warning::
|
||||
|
||||
We advise against using easy_install to install virtualenv when using
|
||||
setuptools < 0.9.7, because easy_install didn't download from PyPI over SSL
|
||||
and was broken in some subtle ways.
|
||||
|
||||
To install globally with `pip` (if you have pip 1.3 or greater installed globally):
|
||||
|
||||
::
|
||||
|
||||
$ [sudo] pip install virtualenv
|
||||
|
||||
Or to get the latest unreleased dev version:
|
||||
|
||||
::
|
||||
|
||||
$ [sudo] pip install https://github.com/pypa/virtualenv/tarball/develop
|
||||
|
||||
|
||||
To install globally from source:
|
||||
|
||||
::
|
||||
|
||||
$ curl -O https://pypi.python.org/packages/source/v/virtualenv/virtualenv-X.X.tar.gz
|
||||
$ tar xvfz virtualenv-X.X.tar.gz
|
||||
$ cd virtualenv-X.X
|
||||
$ [sudo] python setup.py install
|
||||
|
||||
|
||||
To *use* locally from source:
|
||||
|
||||
::
|
||||
|
||||
$ curl -O https://pypi.python.org/packages/source/v/virtualenv/virtualenv-X.X.tar.gz
|
||||
$ tar xvfz virtualenv-X.X.tar.gz
|
||||
$ cd virtualenv-X.X
|
||||
$ python virtualenv.py myVE
|
||||
|
||||
.. note::
|
||||
|
||||
The ``virtualenv.py`` script is *not* supported if run without the
|
||||
necessary pip/setuptools/virtualenv distributions available locally. All
|
||||
of the installation methods above include a ``virtualenv_support``
|
||||
directory alongside ``virtualenv.py`` which contains a complete set of
|
||||
pip and setuptools distributions, and so are fully supported.
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
The basic usage is::
|
||||
|
||||
$ python virtualenv.py ENV
|
||||
|
||||
If you install it you can also just do ``virtualenv ENV``.
|
||||
$ virtualenv ENV
|
||||
|
||||
This creates ``ENV/lib/pythonX.X/site-packages``, where any libraries you
|
||||
install will go. It also creates ``ENV/bin/python``, which is a Python
|
||||
interpreter that uses this environment. Anytime you use that interpreter
|
||||
install will go. It also creates ``ENV/bin/python``, which is a Python
|
||||
interpreter that uses this environment. Anytime you use that interpreter
|
||||
(including when a script has ``#!/path/to/ENV/bin/python`` in it) the libraries
|
||||
in that environment will be used.
|
||||
|
||||
It also installs either `Setuptools
|
||||
<http://peak.telecommunity.com/DevCenter/setuptools>`_ or `distribute
|
||||
<http://pypi.python.org/pypi/distribute>`_ into the environment. To use
|
||||
Distribute instead of setuptools, just call virtualenv like this::
|
||||
<http://peak.telecommunity.com/DevCenter/setuptools>`_ into the environment.
|
||||
|
||||
$ python virtualenv.py --distribute ENV
|
||||
.. note::
|
||||
|
||||
You can also set the environment variable VIRTUALENV_DISTRIBUTE.
|
||||
Virtualenv (<1.10) used to provide a ``--distribute`` option to use the
|
||||
setuptools fork Distribute_. Since Distribute has been merged back into
|
||||
setuptools this option is now no-op, it will always use the improved
|
||||
setuptools releases.
|
||||
|
||||
A new virtualenv also includes the `pip <http://pypi.python.org/pypi/pip>`_
|
||||
installer, so you can use ``ENV/bin/pip`` to install additional packages into
|
||||
the environment.
|
||||
|
||||
.. _Distribute: https://pypi.python.org/pypi/distribute
|
||||
|
||||
activate script
|
||||
~~~~~~~~~~~~~~~
|
||||
|
@ -88,10 +135,10 @@ Description:
|
|||
$ source bin/activate
|
||||
|
||||
This will change your ``$PATH`` so its first entry is the virtualenv's
|
||||
``bin/`` directory. (You have to use ``source`` because it changes your
|
||||
``bin/`` directory. (You have to use ``source`` because it changes your
|
||||
shell environment in-place.) This is all it does; it's purely a
|
||||
convenience. If you directly run a script or the python interpreter
|
||||
from the virtualenv's ``bin/`` directory (e.g. ``path/to/env/bin/pip``
|
||||
convenience. If you directly run a script or the python interpreter
|
||||
from the virtualenv's ``bin/`` directory (e.g. ``path/to/env/bin/pip``
|
||||
or ``/path/to/env/bin/python script.py``) there's no need for
|
||||
activation.
|
||||
|
||||
|
@ -99,9 +146,9 @@ Description:
|
|||
undo the changes to your ``$PATH``.
|
||||
|
||||
The ``activate`` script will also modify your shell prompt to indicate
|
||||
which environment is currently active. You can disable this behavior,
|
||||
which environment is currently active. You can disable this behavior,
|
||||
which can be useful if you have your own custom prompt that already
|
||||
displays the active environment name. To do so, set the
|
||||
displays the active environment name. To do so, set the
|
||||
``VIRTUAL_ENV_DISABLE_PROMPT`` environment variable to any non-empty
|
||||
value before running the ``activate`` script.
|
||||
|
||||
|
@ -175,7 +222,7 @@ Description:
|
|||
(or wherever your global site-packages directory is).
|
||||
|
||||
This can be used if you have control over the global site-packages directory,
|
||||
and you want to depend on the packages there. If you want isolation from the
|
||||
and you want to depend on the packages there. If you want isolation from the
|
||||
global system, do not use this flag.
|
||||
|
||||
|
||||
|
@ -183,7 +230,7 @@ Description:
|
|||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
virtualenv can not only be configured by passing command line options such as
|
||||
``--distribute`` but also by two other means:
|
||||
``--python`` but also by two other means:
|
||||
|
||||
- Environment variables
|
||||
|
||||
|
@ -192,15 +239,15 @@ Description:
|
|||
the name of the command line options are capitalized and have dashes
|
||||
(``'-'``) replaced with underscores (``'_'``).
|
||||
|
||||
For example, to automatically install Distribute instead of setuptools
|
||||
you can also set an environment variable::
|
||||
For example, to automatically use a custom Python binary instead of the
|
||||
one virtualenv is run with you can also set an environment variable::
|
||||
|
||||
$ export VIRTUALENV_DISTRIBUTE=true
|
||||
$ python virtualenv.py ENV
|
||||
$ export VIRTUALENV_PYTHON=/opt/python-3.3/bin/python
|
||||
$ virtualenv ENV
|
||||
|
||||
It's the same as passing the option to virtualenv directly::
|
||||
|
||||
$ python virtualenv.py --distribute ENV
|
||||
$ virtualenv --python=/opt/python-3.3/bin/python ENV
|
||||
|
||||
This also works for appending command line options, like ``--find-links``.
|
||||
Just leave an empty space between the passsed values, e.g.::
|
||||
|
@ -210,7 +257,7 @@ Description:
|
|||
|
||||
is the same as calling::
|
||||
|
||||
$ python virtualenv.py --extra-search-dir=/path/to/dists --extra-search-dir=/path/to/other/dists ENV
|
||||
$ virtualenv --extra-search-dir=/path/to/dists --extra-search-dir=/path/to/other/dists ENV
|
||||
|
||||
- Config files
|
||||
|
||||
|
@ -219,10 +266,10 @@ Description:
|
|||
``%APPDATA%\virtualenv\virtualenv.ini``.
|
||||
|
||||
The names of the settings are derived from the long command line option,
|
||||
e.g. the option ``--distribute`` would look like this::
|
||||
e.g. the option ``--python`` would look like this::
|
||||
|
||||
[virtualenv]
|
||||
distribute = true
|
||||
python = /opt/python-3.3/bin/python
|
||||
|
||||
Appending options like ``--extra-search-dir`` can be written on multiple
|
||||
lines::
|
||||
|
@ -256,20 +303,20 @@ Description:
|
|||
-----------------------------------
|
||||
|
||||
While this creates an environment, it doesn't put anything into the
|
||||
environment. Developers may find it useful to distribute a script
|
||||
environment. Developers may find it useful to distribute a script
|
||||
that sets up a particular environment, for example a script that
|
||||
installs a particular web application.
|
||||
|
||||
To create a script like this, call
|
||||
``virtualenv.create_bootstrap_script(extra_text)``, and write the
|
||||
result to your new bootstrapping script. Here's the documentation
|
||||
result to your new bootstrapping script. Here's the documentation
|
||||
from the docstring:
|
||||
|
||||
Creates a bootstrap script, which is like this script but with
|
||||
extend_parser, adjust_options, and after_install hooks.
|
||||
|
||||
This returns a string that (written to disk of course) can be used
|
||||
as a bootstrap script with your own customizations. The script
|
||||
as a bootstrap script with your own customizations. The script
|
||||
will be the standard virtualenv.py script, with your extra text
|
||||
added (your extra text should be Python code).
|
||||
|
||||
|
@ -285,8 +332,8 @@ Description:
|
|||
|
||||
``after_install(options, home_dir)``:
|
||||
|
||||
After everything is installed, this function is called. This
|
||||
is probably the function you are most likely to use. An
|
||||
After everything is installed, this function is called. This
|
||||
is probably the function you are most likely to use. An
|
||||
example would be::
|
||||
|
||||
def after_install(options, home_dir):
|
||||
|
@ -332,23 +379,23 @@ Description:
|
|||
---------------------------------------
|
||||
|
||||
Sometimes you can't or don't want to use the Python interpreter
|
||||
created by the virtualenv. For instance, in a `mod_python
|
||||
created by the virtualenv. For instance, in a `mod_python
|
||||
<http://www.modpython.org/>`_ or `mod_wsgi <http://www.modwsgi.org/>`_
|
||||
environment, there is only one interpreter.
|
||||
|
||||
Luckily, it's easy. You must use the custom Python interpreter to
|
||||
*install* libraries. But to *use* libraries, you just have to be sure
|
||||
the path is correct. A script is available to correct the path. You
|
||||
Luckily, it's easy. You must use the custom Python interpreter to
|
||||
*install* libraries. But to *use* libraries, you just have to be sure
|
||||
the path is correct. A script is available to correct the path. You
|
||||
can setup the environment like::
|
||||
|
||||
activate_this = '/path/to/env/bin/activate_this.py'
|
||||
execfile(activate_this, dict(__file__=activate_this))
|
||||
|
||||
This will change ``sys.path`` and even change ``sys.prefix``, but also allow
|
||||
you to use an existing interpreter. Items in your environment will show up
|
||||
first on ``sys.path``, before global items. However, global items will
|
||||
you to use an existing interpreter. Items in your environment will show up
|
||||
first on ``sys.path``, before global items. However, global items will
|
||||
always be accessible (as if the ``--system-site-packages`` flag had been used
|
||||
in creating the environment, whether it was or not). Also, this cannot undo
|
||||
in creating the environment, whether it was or not). Also, this cannot undo
|
||||
the activation of other environments, or modules that have been imported.
|
||||
You shouldn't try to, for instance, activate an environment before a web
|
||||
request; you should activate *one* environment as early as possible, and not
|
||||
|
@ -358,29 +405,39 @@ Description:
|
|||
-------------------------------
|
||||
|
||||
Note: this option is somewhat experimental, and there are probably
|
||||
caveats that have not yet been identified. Also this does not
|
||||
currently work on Windows.
|
||||
caveats that have not yet been identified.
|
||||
|
||||
Normally environments are tied to a specific path. That means that
|
||||
.. warning::
|
||||
|
||||
The ``--relocatable`` option currently has a number of issues,
|
||||
and is not guaranteed to work in all circumstances. It is possible
|
||||
that the option will be deprecated in a future version of ``virtualenv``.
|
||||
|
||||
Normally environments are tied to a specific path. That means that
|
||||
you cannot move an environment around or copy it to another computer.
|
||||
You can fix up an environment to make it relocatable with the
|
||||
command::
|
||||
|
||||
$ virtualenv --relocatable ENV
|
||||
|
||||
This will make some of the files created by setuptools or distribute
|
||||
use relative paths, and will change all the scripts to use ``activate_this.py``
|
||||
instead of using the location of the Python interpreter to select the
|
||||
environment.
|
||||
This will make some of the files created by setuptools use relative paths,
|
||||
and will change all the scripts to use ``activate_this.py`` instead of using
|
||||
the location of the Python interpreter to select the environment.
|
||||
|
||||
**Note:** scripts which have been made relocatable will only work if
|
||||
the virtualenv is activated, specifically the python executable from
|
||||
the virtualenv must be the first one on the system PATH. Also note that
|
||||
the activate scripts are not currently made relocatable by
|
||||
``virtualenv --relocatable``.
|
||||
|
||||
**Note:** you must run this after you've installed *any* packages into
|
||||
the environment. If you make an environment relocatable, then
|
||||
the environment. If you make an environment relocatable, then
|
||||
install a new package, you must run ``virtualenv --relocatable``
|
||||
again.
|
||||
|
||||
Also, this **does not make your packages cross-platform**. You can
|
||||
Also, this **does not make your packages cross-platform**. You can
|
||||
move the directory around, but it can only be used on other similar
|
||||
computers. Some known environmental differences that can cause
|
||||
computers. Some known environmental differences that can cause
|
||||
incompatibilities: a different version of Python, when one platform
|
||||
uses UCS2 for its internal unicode representation and another uses
|
||||
UCS4 (a compile-time option), obvious platform changes like Windows
|
||||
|
@ -395,50 +452,38 @@ Description:
|
|||
The ``--extra-search-dir`` option
|
||||
---------------------------------
|
||||
|
||||
When it creates a new environment, virtualenv installs either setuptools
|
||||
or distribute, and pip. In normal operation when virtualenv is
|
||||
installed, the bundled version of these packages included in the
|
||||
``virtualenv_support`` directory is used. When ``virtualenv.py`` is run
|
||||
standalone and ``virtualenv_support`` is not available, the latest
|
||||
releases of these packages are fetched from the `Python Package Index
|
||||
<http://pypi.python.org>`_ (PyPI).
|
||||
.. note::
|
||||
|
||||
As an alternative, you can provide your own versions of setuptools,
|
||||
distribute and/or pip on the filesystem, and tell virtualenv to use
|
||||
those distributions instead of downloading them from the Internet. To
|
||||
use this feature, pass one or more ``--extra-search-dir`` options to
|
||||
Currently, this feature only partially works for pip, and not at
|
||||
all for setuptools. For details,
|
||||
see `Issue #327 <https://github.com/pypa/virtualenv/issues/327>`_
|
||||
|
||||
This option allows you to provide your own versions of setuptools
|
||||
and/or pip on the filesystem, and tell virtualenv to use those distributions
|
||||
instead of the ones in ``virtualenv_support``.
|
||||
|
||||
To use this feature, pass one or more ``--extra-search-dir`` options to
|
||||
virtualenv like this::
|
||||
|
||||
$ virtualenv --extra-search-dir=/path/to/distributions ENV
|
||||
|
||||
The ``/path/to/distributions`` path should point to a directory that
|
||||
contains setuptools, distribute and/or pip distributions. Setuptools
|
||||
distributions must be ``.egg`` files; pip distributions should be
|
||||
`.tar.gz` source distributions, and distribute distributions may be
|
||||
either (if found an egg will be used preferentially).
|
||||
contains setuptools and/or pip distributions. Setuptools distributions
|
||||
must be ``.egg`` files; pip distributions should be `.tar.gz` source
|
||||
distributions.
|
||||
|
||||
Virtualenv will still download these packages if no satisfactory local
|
||||
distributions are found.
|
||||
If no satisfactory local distributions are found, virtualenv will fail. Virtualenv will never download packages.
|
||||
|
||||
If you are really concerned about virtualenv fetching these packages
|
||||
from the Internet and want to ensure that it never will, you can also
|
||||
provide an option ``--never-download`` like so::
|
||||
The distribution lookup is done in the following locations, with the most
|
||||
recent version found used:
|
||||
|
||||
$ virtualenv --extra-search-dir=/path/to/distributions --never-download ENV
|
||||
|
||||
If this option is provided, virtualenv will never try to download
|
||||
setuptools/distribute or pip. Instead, it will exit with status code 1
|
||||
if it fails to find local distributions for any of these required
|
||||
packages. The local distribution lookup is done in the following
|
||||
locations, with the most recent version found used:
|
||||
|
||||
#. The current directory.
|
||||
#. The directory where virtualenv.py is located.
|
||||
#. A ``virtualenv_support`` directory relative to the directory where
|
||||
virtualenv.py is located.
|
||||
#. If the file being executed is not named virtualenv.py (i.e. is a boot
|
||||
script), a ``virtualenv_support`` directory relative to wherever
|
||||
virtualenv.py is actually installed.
|
||||
#. The current directory.
|
||||
#. The directory where virtualenv.py is located.
|
||||
#. A ``virtualenv_support`` directory relative to the directory where
|
||||
virtualenv.py is located.
|
||||
#. If the file being executed is not named virtualenv.py (i.e. is a boot
|
||||
script), a ``virtualenv_support`` directory relative to wherever
|
||||
virtualenv.py is actually installed.
|
||||
|
||||
|
||||
Compare & Contrast with Alternatives
|
||||
|
@ -447,33 +492,33 @@ Description:
|
|||
There are several alternatives that create isolated environments:
|
||||
|
||||
* ``workingenv`` (which I do not suggest you use anymore) is the
|
||||
predecessor to this library. It used the main Python interpreter,
|
||||
predecessor to this library. It used the main Python interpreter,
|
||||
but relied on setting ``$PYTHONPATH`` to activate the environment.
|
||||
This causes problems when running Python scripts that aren't part of
|
||||
the environment (e.g., a globally installed ``hg`` or ``bzr``). It
|
||||
the environment (e.g., a globally installed ``hg`` or ``bzr``). It
|
||||
also conflicted a lot with Setuptools.
|
||||
|
||||
* `virtual-python
|
||||
<http://peak.telecommunity.com/DevCenter/EasyInstall#creating-a-virtual-python>`_
|
||||
is also a predecessor to this library. It uses only symlinks, so it
|
||||
couldn't work on Windows. It also symlinks over the *entire*
|
||||
standard library and global ``site-packages``. As a result, it
|
||||
is also a predecessor to this library. It uses only symlinks, so it
|
||||
couldn't work on Windows. It also symlinks over the *entire*
|
||||
standard library and global ``site-packages``. As a result, it
|
||||
won't see new additions to the global ``site-packages``.
|
||||
|
||||
This script only symlinks a small portion of the standard library
|
||||
into the environment, and so on Windows it is feasible to simply
|
||||
copy these files over. Also, it creates a new/empty
|
||||
copy these files over. Also, it creates a new/empty
|
||||
``site-packages`` and also adds the global ``site-packages`` to the
|
||||
path, so updates are tracked separately. This script also installs
|
||||
path, so updates are tracked separately. This script also installs
|
||||
Setuptools automatically, saving a step and avoiding the need for
|
||||
network access.
|
||||
|
||||
* `zc.buildout <http://pypi.python.org/pypi/zc.buildout>`_ doesn't
|
||||
create an isolated Python environment in the same style, but
|
||||
achieves similar results through a declarative config file that sets
|
||||
up scripts with very particular packages. As a declarative system,
|
||||
up scripts with very particular packages. As a declarative system,
|
||||
it is somewhat easier to repeat and manage, but more difficult to
|
||||
experiment with. ``zc.buildout`` includes the ability to setup
|
||||
experiment with. ``zc.buildout`` includes the ability to setup
|
||||
non-Python systems (e.g., a database server or an Apache instance).
|
||||
|
||||
I *strongly* recommend anyone doing application development or
|
||||
|
@ -539,7 +584,7 @@ Description:
|
|||
using virtualenv (virtualenvwrapper)
|
||||
<http://www.doughellmann.com/articles/CompletelyDifferent-2008-05-virtualenvwrapper/index.html>`_
|
||||
including some handy scripts to make working with multiple
|
||||
environments easier. He also wrote `an example of using virtualenv
|
||||
environments easier. He also wrote `an example of using virtualenv
|
||||
to try IPython
|
||||
<http://www.doughellmann.com/articles/CompletelyDifferent-2008-02-ipython-and-virtualenv/index.html>`_.
|
||||
|
||||
|
@ -583,6 +628,68 @@ Description:
|
|||
``$ENV/bin/python`` and re-running virtualenv on the same target directory
|
||||
with the upgraded Python.
|
||||
|
||||
1.10.1 (2013-08-07)
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
* **New Signing Key** Release 1.10.1 is using a different key than normal with
|
||||
fingerprint: 7C6B 7C5D 5E2B 6356 A926 F04F 6E3C BCE9 3372 DCFA
|
||||
* Upgraded pip to v1.4.1
|
||||
* Upgraded setuptools to v0.9.8
|
||||
|
||||
|
||||
1.10 (2013-07-23)
|
||||
~~~~~~~~~~~~~~~~~
|
||||
|
||||
* **BACKWARDS INCOMPATIBLE** Dropped support for Python 2.5. The minimum
|
||||
supported Python version is now Python 2.6.
|
||||
|
||||
* **BACKWARDS INCOMPATIBLE** Using ``virtualenv.py`` as an isolated script
|
||||
(i.e. without an associated ``virtualenv_support`` directory) is no longer
|
||||
supported for security reasons and will fail with an error.
|
||||
|
||||
Along with this, ``--never-download`` is now always pinned to ``True``, and
|
||||
is only being maintained in the short term for backward compatibility
|
||||
(Pull #412).
|
||||
|
||||
* **IMPORTANT** Switched to the new setuptools (v0.9.7) which has been merged
|
||||
with Distribute_ again and works for Python 2 and 3 with one codebase.
|
||||
The ``--distribute`` and ``--setuptools`` options are now no-op.
|
||||
|
||||
* Updated to pip 1.4.
|
||||
|
||||
* Added support for PyPy3k
|
||||
|
||||
* Added the option to use a version number with the ``-p`` option to get the
|
||||
system copy of that Python version (Windows only)
|
||||
|
||||
* Removed embedded ``ez_setup.py``, ``distribute_setup.py`` and
|
||||
``distribute_from_egg.py`` files as part of switching to merged setuptools.
|
||||
|
||||
* Fixed ``--relocatable`` to work better on Windows.
|
||||
|
||||
* Fixed issue with readline on Windows.
|
||||
|
||||
.. _Distribute: https://pypi.python.org/pypi/distribute
|
||||
|
||||
1.9.1 (2013-03-08)
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
||||
* Updated to pip 1.3.1 that fixed a major backward incompatible change of
|
||||
parsing URLs to externally hosted packages that got accidentily included
|
||||
in pip 1.3.
|
||||
|
||||
1.9 (2013-03-07)
|
||||
~~~~~~~~~~~~~~~~
|
||||
|
||||
* Unset VIRTUAL_ENV environment variable in deactivate.bat (Pull #364)
|
||||
* Upgraded distribute to 0.6.34.
|
||||
* Added ``--no-setuptools`` and ``--no-pip`` options (Pull #336).
|
||||
* Fixed Issue #373. virtualenv-1.8.4 was failing in cygwin (Pull #382).
|
||||
* Fixed Issue #378. virtualenv is now "multiarch" aware on debian/ubuntu (Pull #379).
|
||||
* Fixed issue with readline module path on pypy and OSX (Pull #374).
|
||||
* Made 64bit detection compatible with Python 2.5 (Pull #393).
|
||||
|
||||
|
||||
1.8.4 (2012-11-25)
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
@ -595,6 +702,9 @@ Description:
|
|||
|
||||
* Added some more integration tests.
|
||||
|
||||
* Removed the unsupported embedded setuptools egg for Python 2.4 to reduce
|
||||
file size.
|
||||
|
||||
1.8.3 (2012-11-21)
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
@ -1196,7 +1306,7 @@ Description:
|
|||
|
||||
Keywords: setuptools deployment installation distutils
|
||||
Platform: UNKNOWN
|
||||
Classifier: Development Status :: 4 - Beta
|
||||
Classifier: Development Status :: 5 - Production/Stable
|
||||
Classifier: Intended Audience :: Developers
|
||||
Classifier: License :: OSI Approved :: MIT License
|
||||
Classifier: Programming Language :: Python :: 2
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
virtualenv
|
||||
==========
|
||||
|
||||
.. image:: https://pypip.in/v/virtualenv/badge.png
|
||||
:target: https://pypi.python.org/pypi/virtualenv
|
||||
|
||||
.. image:: https://secure.travis-ci.org/pypa/virtualenv.png?branch=develop
|
||||
:target: http://travis-ci.org/pypa/virtualenv
|
||||
|
||||
|
|
|
@ -1,59 +0,0 @@
|
|||
#!/usr/bin/env python
|
||||
"""
|
||||
Refresh any files in ../virtualenv_support/ that come from elsewhere
|
||||
"""
|
||||
|
||||
import os
|
||||
try:
|
||||
from urllib.request import urlopen
|
||||
except ImportError:
|
||||
from urllib2 import urlopen
|
||||
import sys
|
||||
|
||||
here = os.path.dirname(__file__)
|
||||
support_location = os.path.join(here, '..', 'virtualenv_support')
|
||||
embedded_location = os.path.join(here, '..', 'virtualenv_embedded')
|
||||
|
||||
embedded_files = [
|
||||
('http://peak.telecommunity.com/dist/ez_setup.py', 'ez_setup.py'),
|
||||
('http://python-distribute.org/distribute_setup.py', 'distribute_setup.py'),
|
||||
]
|
||||
|
||||
support_files = [
|
||||
('http://pypi.python.org/packages/2.6/s/setuptools/setuptools-0.6c11-py2.6.egg', 'setuptools-0.6c11-py2.6.egg'),
|
||||
('http://pypi.python.org/packages/2.5/s/setuptools/setuptools-0.6c11-py2.5.egg', 'setuptools-0.6c11-py2.5.egg'),
|
||||
('http://pypi.python.org/packages/source/d/distribute/distribute-0.6.31.tar.gz', 'distribute-0.6.31.tar.gz'),
|
||||
('http://pypi.python.org/packages/source/p/pip/pip-1.2.1.tar.gz', 'pip-1.2.1.tar.gz'),
|
||||
]
|
||||
|
||||
|
||||
def refresh_files(files, location):
|
||||
for url, filename in files:
|
||||
sys.stdout.write('fetching %s ... ' % url)
|
||||
sys.stdout.flush()
|
||||
f = urlopen(url)
|
||||
content = f.read()
|
||||
f.close()
|
||||
print('done.')
|
||||
filename = os.path.join(location, filename)
|
||||
if os.path.exists(filename):
|
||||
f = open(filename, 'rb')
|
||||
cur_content = f.read()
|
||||
f.close()
|
||||
else:
|
||||
cur_content = ''
|
||||
if cur_content == content:
|
||||
print(' %s up-to-date' % filename)
|
||||
else:
|
||||
print(' overwriting %s' % filename)
|
||||
f = open(filename, 'wb')
|
||||
f.write(content)
|
||||
f.close()
|
||||
|
||||
|
||||
def main():
|
||||
refresh_files(embedded_files, embedded_location)
|
||||
refresh_files(support_files, support_location)
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
|
@ -11,10 +11,11 @@
|
|||
# All configuration values have a default value; values that are commented out
|
||||
# serve to show the default value.
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
# If your extensions are in another directory, add it here.
|
||||
#sys.path.append('some/directory')
|
||||
sys.path.insert(0, os.path.abspath(os.pardir))
|
||||
|
||||
# General configuration
|
||||
# ---------------------
|
||||
|
@ -28,14 +29,14 @@ extensions = ['sphinx.ext.autodoc']
|
|||
#templates_path = ['_templates']
|
||||
|
||||
# The suffix of source filenames.
|
||||
source_suffix = '.txt'
|
||||
source_suffix = '.rst'
|
||||
|
||||
# The master toctree document.
|
||||
master_doc = 'index'
|
||||
|
||||
# General substitutions.
|
||||
project = 'virtualenv'
|
||||
copyright = '2007-2012, Ian Bicking, The Open Planning Project, The virtualenv developers'
|
||||
copyright = '2007-2013, Ian Bicking, The Open Planning Project, The virtualenv developers'
|
||||
|
||||
# The default replacements for |version| and |release|, also used in various
|
||||
# other places throughout the built documents.
|
||||
|
|
|
@ -1,40 +1,24 @@
|
|||
virtualenv
|
||||
==========
|
||||
|
||||
* `Discussion list <http://groups.google.com/group/python-virtualenv/>`_
|
||||
* `Bugs <https://github.com/pypa/virtualenv/issues/>`_
|
||||
|
||||
.. contents::
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
news
|
||||
`Changes & News <news.html>`_ `|`
|
||||
`Mailing list <http://groups.google.com/group/python-virtualenv>`_ `|`
|
||||
`Issues <https://github.com/pypa/virtualenv/issues>`_ `|`
|
||||
`Github <https://github.com/pypa/virtualenv>`_ `|`
|
||||
`PyPI <https://pypi.python.org/pypi/virtualenv/>`_ `|`
|
||||
IRC: #pip on Freenode
|
||||
|
||||
.. comment: split here
|
||||
|
||||
Installation
|
||||
------------
|
||||
|
||||
You can install virtualenv with ``pip install virtualenv``, or the `latest
|
||||
development version <https://github.com/pypa/virtualenv/tarball/develop>`_
|
||||
with ``pip install https://github.com/pypa/virtualenv/tarball/develop``.
|
||||
|
||||
You can also use ``easy_install``, or if you have no Python package manager
|
||||
available at all, you can just grab the single file `virtualenv.py`_ and run
|
||||
it with ``python virtualenv.py``.
|
||||
|
||||
.. _virtualenv.py: https://raw.github.com/pypa/virtualenv/master/virtualenv.py
|
||||
|
||||
What It Does
|
||||
------------
|
||||
|
||||
``virtualenv`` is a tool to create isolated Python environments.
|
||||
|
||||
The basic problem being addressed is one of dependencies and versions,
|
||||
and indirectly permissions. Imagine you have an application that
|
||||
and indirectly permissions. Imagine you have an application that
|
||||
needs version 1 of LibFoo, but another application requires version
|
||||
2. How can you use both these applications? If you install
|
||||
2. How can you use both these applications? If you install
|
||||
everything into ``/usr/lib/python2.7/site-packages`` (or whatever your
|
||||
platform's standard location is), it's easy to end up in a situation
|
||||
where you unintentionally upgrade an application that shouldn't be
|
||||
|
@ -47,39 +31,99 @@ the versions of those libraries can break the application.
|
|||
Also, what if you can't install packages into the global
|
||||
``site-packages`` directory? For instance, on a shared host.
|
||||
|
||||
In all these cases, ``virtualenv`` can help you. It creates an
|
||||
In all these cases, ``virtualenv`` can help you. It creates an
|
||||
environment that has its own installation directories, that doesn't
|
||||
share libraries with other virtualenv environments (and optionally
|
||||
doesn't access the globally installed libraries either).
|
||||
|
||||
|
||||
Installation
|
||||
------------
|
||||
|
||||
.. warning::
|
||||
|
||||
We advise installing virtualenv-1.9 or greater. Prior to version 1.9, the
|
||||
pip included in virtualenv did not not download from PyPI over SSL.
|
||||
|
||||
.. warning::
|
||||
|
||||
When using pip to install virtualenv, we advise using pip 1.3 or greater.
|
||||
Prior to version 1.3, pip did not not download from PyPI over SSL.
|
||||
|
||||
.. warning::
|
||||
|
||||
We advise against using easy_install to install virtualenv when using
|
||||
setuptools < 0.9.7, because easy_install didn't download from PyPI over SSL
|
||||
and was broken in some subtle ways.
|
||||
|
||||
To install globally with `pip` (if you have pip 1.3 or greater installed globally):
|
||||
|
||||
::
|
||||
|
||||
$ [sudo] pip install virtualenv
|
||||
|
||||
Or to get the latest unreleased dev version:
|
||||
|
||||
::
|
||||
|
||||
$ [sudo] pip install https://github.com/pypa/virtualenv/tarball/develop
|
||||
|
||||
|
||||
To install globally from source:
|
||||
|
||||
::
|
||||
|
||||
$ curl -O https://pypi.python.org/packages/source/v/virtualenv/virtualenv-X.X.tar.gz
|
||||
$ tar xvfz virtualenv-X.X.tar.gz
|
||||
$ cd virtualenv-X.X
|
||||
$ [sudo] python setup.py install
|
||||
|
||||
|
||||
To *use* locally from source:
|
||||
|
||||
::
|
||||
|
||||
$ curl -O https://pypi.python.org/packages/source/v/virtualenv/virtualenv-X.X.tar.gz
|
||||
$ tar xvfz virtualenv-X.X.tar.gz
|
||||
$ cd virtualenv-X.X
|
||||
$ python virtualenv.py myVE
|
||||
|
||||
.. note::
|
||||
|
||||
The ``virtualenv.py`` script is *not* supported if run without the
|
||||
necessary pip/setuptools/virtualenv distributions available locally. All
|
||||
of the installation methods above include a ``virtualenv_support``
|
||||
directory alongside ``virtualenv.py`` which contains a complete set of
|
||||
pip and setuptools distributions, and so are fully supported.
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
The basic usage is::
|
||||
|
||||
$ python virtualenv.py ENV
|
||||
|
||||
If you install it you can also just do ``virtualenv ENV``.
|
||||
$ virtualenv ENV
|
||||
|
||||
This creates ``ENV/lib/pythonX.X/site-packages``, where any libraries you
|
||||
install will go. It also creates ``ENV/bin/python``, which is a Python
|
||||
interpreter that uses this environment. Anytime you use that interpreter
|
||||
install will go. It also creates ``ENV/bin/python``, which is a Python
|
||||
interpreter that uses this environment. Anytime you use that interpreter
|
||||
(including when a script has ``#!/path/to/ENV/bin/python`` in it) the libraries
|
||||
in that environment will be used.
|
||||
|
||||
It also installs either `Setuptools
|
||||
<http://peak.telecommunity.com/DevCenter/setuptools>`_ or `distribute
|
||||
<http://pypi.python.org/pypi/distribute>`_ into the environment. To use
|
||||
Distribute instead of setuptools, just call virtualenv like this::
|
||||
<http://peak.telecommunity.com/DevCenter/setuptools>`_ into the environment.
|
||||
|
||||
$ python virtualenv.py --distribute ENV
|
||||
.. note::
|
||||
|
||||
You can also set the environment variable VIRTUALENV_DISTRIBUTE.
|
||||
Virtualenv (<1.10) used to provide a ``--distribute`` option to use the
|
||||
setuptools fork Distribute_. Since Distribute has been merged back into
|
||||
setuptools this option is now no-op, it will always use the improved
|
||||
setuptools releases.
|
||||
|
||||
A new virtualenv also includes the `pip <http://pypi.python.org/pypi/pip>`_
|
||||
installer, so you can use ``ENV/bin/pip`` to install additional packages into
|
||||
the environment.
|
||||
|
||||
.. _Distribute: https://pypi.python.org/pypi/distribute
|
||||
|
||||
activate script
|
||||
~~~~~~~~~~~~~~~
|
||||
|
@ -93,10 +137,10 @@ On Posix systems you can do::
|
|||
$ source bin/activate
|
||||
|
||||
This will change your ``$PATH`` so its first entry is the virtualenv's
|
||||
``bin/`` directory. (You have to use ``source`` because it changes your
|
||||
``bin/`` directory. (You have to use ``source`` because it changes your
|
||||
shell environment in-place.) This is all it does; it's purely a
|
||||
convenience. If you directly run a script or the python interpreter
|
||||
from the virtualenv's ``bin/`` directory (e.g. ``path/to/env/bin/pip``
|
||||
convenience. If you directly run a script or the python interpreter
|
||||
from the virtualenv's ``bin/`` directory (e.g. ``path/to/env/bin/pip``
|
||||
or ``/path/to/env/bin/python script.py``) there's no need for
|
||||
activation.
|
||||
|
||||
|
@ -104,9 +148,9 @@ After activating an environment you can use the function ``deactivate`` to
|
|||
undo the changes to your ``$PATH``.
|
||||
|
||||
The ``activate`` script will also modify your shell prompt to indicate
|
||||
which environment is currently active. You can disable this behavior,
|
||||
which environment is currently active. You can disable this behavior,
|
||||
which can be useful if you have your own custom prompt that already
|
||||
displays the active environment name. To do so, set the
|
||||
displays the active environment name. To do so, set the
|
||||
``VIRTUAL_ENV_DISABLE_PROMPT`` environment variable to any non-empty
|
||||
value before running the ``activate`` script.
|
||||
|
||||
|
@ -180,7 +224,7 @@ environment will inherit packages from ``/usr/lib/python2.7/site-packages``
|
|||
(or wherever your global site-packages directory is).
|
||||
|
||||
This can be used if you have control over the global site-packages directory,
|
||||
and you want to depend on the packages there. If you want isolation from the
|
||||
and you want to depend on the packages there. If you want isolation from the
|
||||
global system, do not use this flag.
|
||||
|
||||
|
||||
|
@ -188,7 +232,7 @@ Environment variables and configuration files
|
|||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
virtualenv can not only be configured by passing command line options such as
|
||||
``--distribute`` but also by two other means:
|
||||
``--python`` but also by two other means:
|
||||
|
||||
- Environment variables
|
||||
|
||||
|
@ -197,15 +241,15 @@ virtualenv can not only be configured by passing command line options such as
|
|||
the name of the command line options are capitalized and have dashes
|
||||
(``'-'``) replaced with underscores (``'_'``).
|
||||
|
||||
For example, to automatically install Distribute instead of setuptools
|
||||
you can also set an environment variable::
|
||||
For example, to automatically use a custom Python binary instead of the
|
||||
one virtualenv is run with you can also set an environment variable::
|
||||
|
||||
$ export VIRTUALENV_DISTRIBUTE=true
|
||||
$ python virtualenv.py ENV
|
||||
$ export VIRTUALENV_PYTHON=/opt/python-3.3/bin/python
|
||||
$ virtualenv ENV
|
||||
|
||||
It's the same as passing the option to virtualenv directly::
|
||||
|
||||
$ python virtualenv.py --distribute ENV
|
||||
$ virtualenv --python=/opt/python-3.3/bin/python ENV
|
||||
|
||||
This also works for appending command line options, like ``--find-links``.
|
||||
Just leave an empty space between the passsed values, e.g.::
|
||||
|
@ -215,7 +259,7 @@ virtualenv can not only be configured by passing command line options such as
|
|||
|
||||
is the same as calling::
|
||||
|
||||
$ python virtualenv.py --extra-search-dir=/path/to/dists --extra-search-dir=/path/to/other/dists ENV
|
||||
$ virtualenv --extra-search-dir=/path/to/dists --extra-search-dir=/path/to/other/dists ENV
|
||||
|
||||
- Config files
|
||||
|
||||
|
@ -224,10 +268,10 @@ virtualenv can not only be configured by passing command line options such as
|
|||
``%APPDATA%\virtualenv\virtualenv.ini``.
|
||||
|
||||
The names of the settings are derived from the long command line option,
|
||||
e.g. the option ``--distribute`` would look like this::
|
||||
e.g. the option ``--python`` would look like this::
|
||||
|
||||
[virtualenv]
|
||||
distribute = true
|
||||
python = /opt/python-3.3/bin/python
|
||||
|
||||
Appending options like ``--extra-search-dir`` can be written on multiple
|
||||
lines::
|
||||
|
@ -261,20 +305,20 @@ Creating Your Own Bootstrap Scripts
|
|||
-----------------------------------
|
||||
|
||||
While this creates an environment, it doesn't put anything into the
|
||||
environment. Developers may find it useful to distribute a script
|
||||
environment. Developers may find it useful to distribute a script
|
||||
that sets up a particular environment, for example a script that
|
||||
installs a particular web application.
|
||||
|
||||
To create a script like this, call
|
||||
``virtualenv.create_bootstrap_script(extra_text)``, and write the
|
||||
result to your new bootstrapping script. Here's the documentation
|
||||
result to your new bootstrapping script. Here's the documentation
|
||||
from the docstring:
|
||||
|
||||
Creates a bootstrap script, which is like this script but with
|
||||
extend_parser, adjust_options, and after_install hooks.
|
||||
|
||||
This returns a string that (written to disk of course) can be used
|
||||
as a bootstrap script with your own customizations. The script
|
||||
as a bootstrap script with your own customizations. The script
|
||||
will be the standard virtualenv.py script, with your extra text
|
||||
added (your extra text should be Python code).
|
||||
|
||||
|
@ -290,8 +334,8 @@ If you include these functions, they will be called:
|
|||
|
||||
``after_install(options, home_dir)``:
|
||||
|
||||
After everything is installed, this function is called. This
|
||||
is probably the function you are most likely to use. An
|
||||
After everything is installed, this function is called. This
|
||||
is probably the function you are most likely to use. An
|
||||
example would be::
|
||||
|
||||
def after_install(options, home_dir):
|
||||
|
@ -337,23 +381,23 @@ Using Virtualenv without ``bin/python``
|
|||
---------------------------------------
|
||||
|
||||
Sometimes you can't or don't want to use the Python interpreter
|
||||
created by the virtualenv. For instance, in a `mod_python
|
||||
created by the virtualenv. For instance, in a `mod_python
|
||||
<http://www.modpython.org/>`_ or `mod_wsgi <http://www.modwsgi.org/>`_
|
||||
environment, there is only one interpreter.
|
||||
|
||||
Luckily, it's easy. You must use the custom Python interpreter to
|
||||
*install* libraries. But to *use* libraries, you just have to be sure
|
||||
the path is correct. A script is available to correct the path. You
|
||||
Luckily, it's easy. You must use the custom Python interpreter to
|
||||
*install* libraries. But to *use* libraries, you just have to be sure
|
||||
the path is correct. A script is available to correct the path. You
|
||||
can setup the environment like::
|
||||
|
||||
activate_this = '/path/to/env/bin/activate_this.py'
|
||||
execfile(activate_this, dict(__file__=activate_this))
|
||||
|
||||
This will change ``sys.path`` and even change ``sys.prefix``, but also allow
|
||||
you to use an existing interpreter. Items in your environment will show up
|
||||
first on ``sys.path``, before global items. However, global items will
|
||||
you to use an existing interpreter. Items in your environment will show up
|
||||
first on ``sys.path``, before global items. However, global items will
|
||||
always be accessible (as if the ``--system-site-packages`` flag had been used
|
||||
in creating the environment, whether it was or not). Also, this cannot undo
|
||||
in creating the environment, whether it was or not). Also, this cannot undo
|
||||
the activation of other environments, or modules that have been imported.
|
||||
You shouldn't try to, for instance, activate an environment before a web
|
||||
request; you should activate *one* environment as early as possible, and not
|
||||
|
@ -363,29 +407,39 @@ Making Environments Relocatable
|
|||
-------------------------------
|
||||
|
||||
Note: this option is somewhat experimental, and there are probably
|
||||
caveats that have not yet been identified. Also this does not
|
||||
currently work on Windows.
|
||||
caveats that have not yet been identified.
|
||||
|
||||
Normally environments are tied to a specific path. That means that
|
||||
.. warning::
|
||||
|
||||
The ``--relocatable`` option currently has a number of issues,
|
||||
and is not guaranteed to work in all circumstances. It is possible
|
||||
that the option will be deprecated in a future version of ``virtualenv``.
|
||||
|
||||
Normally environments are tied to a specific path. That means that
|
||||
you cannot move an environment around or copy it to another computer.
|
||||
You can fix up an environment to make it relocatable with the
|
||||
command::
|
||||
|
||||
$ virtualenv --relocatable ENV
|
||||
|
||||
This will make some of the files created by setuptools or distribute
|
||||
use relative paths, and will change all the scripts to use ``activate_this.py``
|
||||
instead of using the location of the Python interpreter to select the
|
||||
environment.
|
||||
This will make some of the files created by setuptools use relative paths,
|
||||
and will change all the scripts to use ``activate_this.py`` instead of using
|
||||
the location of the Python interpreter to select the environment.
|
||||
|
||||
**Note:** scripts which have been made relocatable will only work if
|
||||
the virtualenv is activated, specifically the python executable from
|
||||
the virtualenv must be the first one on the system PATH. Also note that
|
||||
the activate scripts are not currently made relocatable by
|
||||
``virtualenv --relocatable``.
|
||||
|
||||
**Note:** you must run this after you've installed *any* packages into
|
||||
the environment. If you make an environment relocatable, then
|
||||
the environment. If you make an environment relocatable, then
|
||||
install a new package, you must run ``virtualenv --relocatable``
|
||||
again.
|
||||
|
||||
Also, this **does not make your packages cross-platform**. You can
|
||||
Also, this **does not make your packages cross-platform**. You can
|
||||
move the directory around, but it can only be used on other similar
|
||||
computers. Some known environmental differences that can cause
|
||||
computers. Some known environmental differences that can cause
|
||||
incompatibilities: a different version of Python, when one platform
|
||||
uses UCS2 for its internal unicode representation and another uses
|
||||
UCS4 (a compile-time option), obvious platform changes like Windows
|
||||
|
@ -400,50 +454,38 @@ If you use this flag to create an environment, currently, the
|
|||
The ``--extra-search-dir`` option
|
||||
---------------------------------
|
||||
|
||||
When it creates a new environment, virtualenv installs either setuptools
|
||||
or distribute, and pip. In normal operation when virtualenv is
|
||||
installed, the bundled version of these packages included in the
|
||||
``virtualenv_support`` directory is used. When ``virtualenv.py`` is run
|
||||
standalone and ``virtualenv_support`` is not available, the latest
|
||||
releases of these packages are fetched from the `Python Package Index
|
||||
<http://pypi.python.org>`_ (PyPI).
|
||||
.. note::
|
||||
|
||||
As an alternative, you can provide your own versions of setuptools,
|
||||
distribute and/or pip on the filesystem, and tell virtualenv to use
|
||||
those distributions instead of downloading them from the Internet. To
|
||||
use this feature, pass one or more ``--extra-search-dir`` options to
|
||||
Currently, this feature only partially works for pip, and not at
|
||||
all for setuptools. For details,
|
||||
see `Issue #327 <https://github.com/pypa/virtualenv/issues/327>`_
|
||||
|
||||
This option allows you to provide your own versions of setuptools
|
||||
and/or pip on the filesystem, and tell virtualenv to use those distributions
|
||||
instead of the ones in ``virtualenv_support``.
|
||||
|
||||
To use this feature, pass one or more ``--extra-search-dir`` options to
|
||||
virtualenv like this::
|
||||
|
||||
$ virtualenv --extra-search-dir=/path/to/distributions ENV
|
||||
|
||||
The ``/path/to/distributions`` path should point to a directory that
|
||||
contains setuptools, distribute and/or pip distributions. Setuptools
|
||||
distributions must be ``.egg`` files; pip distributions should be
|
||||
`.tar.gz` source distributions, and distribute distributions may be
|
||||
either (if found an egg will be used preferentially).
|
||||
contains setuptools and/or pip distributions. Setuptools distributions
|
||||
must be ``.egg`` files; pip distributions should be `.tar.gz` source
|
||||
distributions.
|
||||
|
||||
Virtualenv will still download these packages if no satisfactory local
|
||||
distributions are found.
|
||||
If no satisfactory local distributions are found, virtualenv will fail. Virtualenv will never download packages.
|
||||
|
||||
If you are really concerned about virtualenv fetching these packages
|
||||
from the Internet and want to ensure that it never will, you can also
|
||||
provide an option ``--never-download`` like so::
|
||||
The distribution lookup is done in the following locations, with the most
|
||||
recent version found used:
|
||||
|
||||
$ virtualenv --extra-search-dir=/path/to/distributions --never-download ENV
|
||||
|
||||
If this option is provided, virtualenv will never try to download
|
||||
setuptools/distribute or pip. Instead, it will exit with status code 1
|
||||
if it fails to find local distributions for any of these required
|
||||
packages. The local distribution lookup is done in the following
|
||||
locations, with the most recent version found used:
|
||||
|
||||
#. The current directory.
|
||||
#. The directory where virtualenv.py is located.
|
||||
#. A ``virtualenv_support`` directory relative to the directory where
|
||||
virtualenv.py is located.
|
||||
#. If the file being executed is not named virtualenv.py (i.e. is a boot
|
||||
script), a ``virtualenv_support`` directory relative to wherever
|
||||
virtualenv.py is actually installed.
|
||||
#. The current directory.
|
||||
#. The directory where virtualenv.py is located.
|
||||
#. A ``virtualenv_support`` directory relative to the directory where
|
||||
virtualenv.py is located.
|
||||
#. If the file being executed is not named virtualenv.py (i.e. is a boot
|
||||
script), a ``virtualenv_support`` directory relative to wherever
|
||||
virtualenv.py is actually installed.
|
||||
|
||||
|
||||
Compare & Contrast with Alternatives
|
||||
|
@ -452,33 +494,33 @@ Compare & Contrast with Alternatives
|
|||
There are several alternatives that create isolated environments:
|
||||
|
||||
* ``workingenv`` (which I do not suggest you use anymore) is the
|
||||
predecessor to this library. It used the main Python interpreter,
|
||||
predecessor to this library. It used the main Python interpreter,
|
||||
but relied on setting ``$PYTHONPATH`` to activate the environment.
|
||||
This causes problems when running Python scripts that aren't part of
|
||||
the environment (e.g., a globally installed ``hg`` or ``bzr``). It
|
||||
the environment (e.g., a globally installed ``hg`` or ``bzr``). It
|
||||
also conflicted a lot with Setuptools.
|
||||
|
||||
* `virtual-python
|
||||
<http://peak.telecommunity.com/DevCenter/EasyInstall#creating-a-virtual-python>`_
|
||||
is also a predecessor to this library. It uses only symlinks, so it
|
||||
couldn't work on Windows. It also symlinks over the *entire*
|
||||
standard library and global ``site-packages``. As a result, it
|
||||
is also a predecessor to this library. It uses only symlinks, so it
|
||||
couldn't work on Windows. It also symlinks over the *entire*
|
||||
standard library and global ``site-packages``. As a result, it
|
||||
won't see new additions to the global ``site-packages``.
|
||||
|
||||
This script only symlinks a small portion of the standard library
|
||||
into the environment, and so on Windows it is feasible to simply
|
||||
copy these files over. Also, it creates a new/empty
|
||||
copy these files over. Also, it creates a new/empty
|
||||
``site-packages`` and also adds the global ``site-packages`` to the
|
||||
path, so updates are tracked separately. This script also installs
|
||||
path, so updates are tracked separately. This script also installs
|
||||
Setuptools automatically, saving a step and avoiding the need for
|
||||
network access.
|
||||
|
||||
* `zc.buildout <http://pypi.python.org/pypi/zc.buildout>`_ doesn't
|
||||
create an isolated Python environment in the same style, but
|
||||
achieves similar results through a declarative config file that sets
|
||||
up scripts with very particular packages. As a declarative system,
|
||||
up scripts with very particular packages. As a declarative system,
|
||||
it is somewhat easier to repeat and manage, but more difficult to
|
||||
experiment with. ``zc.buildout`` includes the ability to setup
|
||||
experiment with. ``zc.buildout`` includes the ability to setup
|
||||
non-Python systems (e.g., a database server or an Apache instance).
|
||||
|
||||
I *strongly* recommend anyone doing application development or
|
||||
|
@ -544,7 +586,7 @@ Other Documentation and Links
|
|||
using virtualenv (virtualenvwrapper)
|
||||
<http://www.doughellmann.com/articles/CompletelyDifferent-2008-05-virtualenvwrapper/index.html>`_
|
||||
including some handy scripts to make working with multiple
|
||||
environments easier. He also wrote `an example of using virtualenv
|
||||
environments easier. He also wrote `an example of using virtualenv
|
||||
to try IPython
|
||||
<http://www.doughellmann.com/articles/CompletelyDifferent-2008-02-ipython-and-virtualenv/index.html>`_.
|
||||
|
|
@ -14,6 +14,68 @@ Changes & News
|
|||
``$ENV/bin/python`` and re-running virtualenv on the same target directory
|
||||
with the upgraded Python.
|
||||
|
||||
1.10.1 (2013-08-07)
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
* **New Signing Key** Release 1.10.1 is using a different key than normal with
|
||||
fingerprint: 7C6B 7C5D 5E2B 6356 A926 F04F 6E3C BCE9 3372 DCFA
|
||||
* Upgraded pip to v1.4.1
|
||||
* Upgraded setuptools to v0.9.8
|
||||
|
||||
|
||||
1.10 (2013-07-23)
|
||||
~~~~~~~~~~~~~~~~~
|
||||
|
||||
* **BACKWARDS INCOMPATIBLE** Dropped support for Python 2.5. The minimum
|
||||
supported Python version is now Python 2.6.
|
||||
|
||||
* **BACKWARDS INCOMPATIBLE** Using ``virtualenv.py`` as an isolated script
|
||||
(i.e. without an associated ``virtualenv_support`` directory) is no longer
|
||||
supported for security reasons and will fail with an error.
|
||||
|
||||
Along with this, ``--never-download`` is now always pinned to ``True``, and
|
||||
is only being maintained in the short term for backward compatibility
|
||||
(Pull #412).
|
||||
|
||||
* **IMPORTANT** Switched to the new setuptools (v0.9.7) which has been merged
|
||||
with Distribute_ again and works for Python 2 and 3 with one codebase.
|
||||
The ``--distribute`` and ``--setuptools`` options are now no-op.
|
||||
|
||||
* Updated to pip 1.4.
|
||||
|
||||
* Added support for PyPy3k
|
||||
|
||||
* Added the option to use a version number with the ``-p`` option to get the
|
||||
system copy of that Python version (Windows only)
|
||||
|
||||
* Removed embedded ``ez_setup.py``, ``distribute_setup.py`` and
|
||||
``distribute_from_egg.py`` files as part of switching to merged setuptools.
|
||||
|
||||
* Fixed ``--relocatable`` to work better on Windows.
|
||||
|
||||
* Fixed issue with readline on Windows.
|
||||
|
||||
.. _Distribute: https://pypi.python.org/pypi/distribute
|
||||
|
||||
1.9.1 (2013-03-08)
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
||||
* Updated to pip 1.3.1 that fixed a major backward incompatible change of
|
||||
parsing URLs to externally hosted packages that got accidentily included
|
||||
in pip 1.3.
|
||||
|
||||
1.9 (2013-03-07)
|
||||
~~~~~~~~~~~~~~~~
|
||||
|
||||
* Unset VIRTUAL_ENV environment variable in deactivate.bat (Pull #364)
|
||||
* Upgraded distribute to 0.6.34.
|
||||
* Added ``--no-setuptools`` and ``--no-pip`` options (Pull #336).
|
||||
* Fixed Issue #373. virtualenv-1.8.4 was failing in cygwin (Pull #382).
|
||||
* Fixed Issue #378. virtualenv is now "multiarch" aware on debian/ubuntu (Pull #379).
|
||||
* Fixed issue with readline module path on pypy and OSX (Pull #374).
|
||||
* Made 64bit detection compatible with Python 2.5 (Pull #393).
|
||||
|
||||
|
||||
1.8.4 (2012-11-25)
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
@ -26,6 +88,9 @@ Changes & News
|
|||
|
||||
* Added some more integration tests.
|
||||
|
||||
* Removed the unsupported embedded setuptools egg for Python 2.4 to reduce
|
||||
file size.
|
||||
|
||||
1.8.3 (2012-11-21)
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
|
@ -30,11 +30,11 @@ except ImportError:
|
|||
here = os.path.dirname(os.path.abspath(__file__))
|
||||
|
||||
## Get long_description from index.txt:
|
||||
f = open(os.path.join(here, 'docs', 'index.txt'))
|
||||
f = open(os.path.join(here, 'docs', 'index.rst'))
|
||||
long_description = f.read().strip()
|
||||
long_description = long_description.split('split here', 1)[1]
|
||||
f.close()
|
||||
f = open(os.path.join(here, 'docs', 'news.txt'))
|
||||
f = open(os.path.join(here, 'docs', 'news.rst'))
|
||||
long_description += "\n\n" + f.read()
|
||||
f.close()
|
||||
|
||||
|
@ -61,13 +61,11 @@ except ImportError:
|
|||
|
||||
setup(
|
||||
name='virtualenv',
|
||||
# If you change the version here, change it in virtualenv.py and
|
||||
# docs/conf.py as well
|
||||
version=get_version(),
|
||||
description="Virtual Python Environment builder",
|
||||
long_description=long_description,
|
||||
classifiers=[
|
||||
'Development Status :: 4 - Beta',
|
||||
'Development Status :: 5 - Production/Stable',
|
||||
'Intended Audience :: Developers',
|
||||
'License :: OSI Approved :: MIT License',
|
||||
'Programming Language :: Python :: 2',
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -1,5 +1,7 @@
|
|||
@echo off
|
||||
|
||||
set VIRTUAL_ENV=
|
||||
|
||||
if defined _OLD_VIRTUAL_PROMPT (
|
||||
set "PROMPT=%_OLD_VIRTUAL_PROMPT%"
|
||||
set _OLD_VIRTUAL_PROMPT=
|
||||
|
|
|
@ -1,8 +0,0 @@
|
|||
# Called from virtualenv with parameters:
|
||||
# [--always-unzip] [-v] egg_name
|
||||
# So, the distribute egg is always the last argument.
|
||||
import sys
|
||||
eggname = sys.argv[-1]
|
||||
sys.path.insert(0, eggname)
|
||||
from setuptools.command.easy_install import main
|
||||
main(sys.argv[1:])
|
|
@ -1,541 +0,0 @@
|
|||
#!python
|
||||
"""Bootstrap distribute installation
|
||||
|
||||
If you want to use setuptools in your package's setup.py, just include this
|
||||
file in the same directory with it, and add this to the top of your setup.py::
|
||||
|
||||
from distribute_setup import use_setuptools
|
||||
use_setuptools()
|
||||
|
||||
If you want to require a specific version of setuptools, set a download
|
||||
mirror, or use an alternate download directory, you can do so by supplying
|
||||
the appropriate options to ``use_setuptools()``.
|
||||
|
||||
This file can also be run as a script to install or upgrade setuptools.
|
||||
"""
|
||||
import os
|
||||
import shutil
|
||||
import sys
|
||||
import time
|
||||
import fnmatch
|
||||
import tempfile
|
||||
import tarfile
|
||||
import optparse
|
||||
|
||||
from distutils import log
|
||||
|
||||
try:
|
||||
from site import USER_SITE
|
||||
except ImportError:
|
||||
USER_SITE = None
|
||||
|
||||
try:
|
||||
import subprocess
|
||||
|
||||
def _python_cmd(*args):
|
||||
args = (sys.executable,) + args
|
||||
return subprocess.call(args) == 0
|
||||
|
||||
except ImportError:
|
||||
# will be used for python 2.3
|
||||
def _python_cmd(*args):
|
||||
args = (sys.executable,) + args
|
||||
# quoting arguments if windows
|
||||
if sys.platform == 'win32':
|
||||
def quote(arg):
|
||||
if ' ' in arg:
|
||||
return '"%s"' % arg
|
||||
return arg
|
||||
args = [quote(arg) for arg in args]
|
||||
return os.spawnl(os.P_WAIT, sys.executable, *args) == 0
|
||||
|
||||
DEFAULT_VERSION = "0.6.31"
|
||||
DEFAULT_URL = "http://pypi.python.org/packages/source/d/distribute/"
|
||||
SETUPTOOLS_FAKED_VERSION = "0.6c11"
|
||||
|
||||
SETUPTOOLS_PKG_INFO = """\
|
||||
Metadata-Version: 1.0
|
||||
Name: setuptools
|
||||
Version: %s
|
||||
Summary: xxxx
|
||||
Home-page: xxx
|
||||
Author: xxx
|
||||
Author-email: xxx
|
||||
License: xxx
|
||||
Description: xxx
|
||||
""" % SETUPTOOLS_FAKED_VERSION
|
||||
|
||||
|
||||
def _install(tarball, install_args=()):
|
||||
# extracting the tarball
|
||||
tmpdir = tempfile.mkdtemp()
|
||||
log.warn('Extracting in %s', tmpdir)
|
||||
old_wd = os.getcwd()
|
||||
try:
|
||||
os.chdir(tmpdir)
|
||||
tar = tarfile.open(tarball)
|
||||
_extractall(tar)
|
||||
tar.close()
|
||||
|
||||
# going in the directory
|
||||
subdir = os.path.join(tmpdir, os.listdir(tmpdir)[0])
|
||||
os.chdir(subdir)
|
||||
log.warn('Now working in %s', subdir)
|
||||
|
||||
# installing
|
||||
log.warn('Installing Distribute')
|
||||
if not _python_cmd('setup.py', 'install', *install_args):
|
||||
log.warn('Something went wrong during the installation.')
|
||||
log.warn('See the error message above.')
|
||||
# exitcode will be 2
|
||||
return 2
|
||||
finally:
|
||||
os.chdir(old_wd)
|
||||
shutil.rmtree(tmpdir)
|
||||
|
||||
|
||||
def _build_egg(egg, tarball, to_dir):
|
||||
# extracting the tarball
|
||||
tmpdir = tempfile.mkdtemp()
|
||||
log.warn('Extracting in %s', tmpdir)
|
||||
old_wd = os.getcwd()
|
||||
try:
|
||||
os.chdir(tmpdir)
|
||||
tar = tarfile.open(tarball)
|
||||
_extractall(tar)
|
||||
tar.close()
|
||||
|
||||
# going in the directory
|
||||
subdir = os.path.join(tmpdir, os.listdir(tmpdir)[0])
|
||||
os.chdir(subdir)
|
||||
log.warn('Now working in %s', subdir)
|
||||
|
||||
# building an egg
|
||||
log.warn('Building a Distribute egg in %s', to_dir)
|
||||
_python_cmd('setup.py', '-q', 'bdist_egg', '--dist-dir', to_dir)
|
||||
|
||||
finally:
|
||||
os.chdir(old_wd)
|
||||
shutil.rmtree(tmpdir)
|
||||
# returning the result
|
||||
log.warn(egg)
|
||||
if not os.path.exists(egg):
|
||||
raise IOError('Could not build the egg.')
|
||||
|
||||
|
||||
def _do_download(version, download_base, to_dir, download_delay):
|
||||
egg = os.path.join(to_dir, 'distribute-%s-py%d.%d.egg'
|
||||
% (version, sys.version_info[0], sys.version_info[1]))
|
||||
if not os.path.exists(egg):
|
||||
tarball = download_setuptools(version, download_base,
|
||||
to_dir, download_delay)
|
||||
_build_egg(egg, tarball, to_dir)
|
||||
sys.path.insert(0, egg)
|
||||
import setuptools
|
||||
setuptools.bootstrap_install_from = egg
|
||||
|
||||
|
||||
def use_setuptools(version=DEFAULT_VERSION, download_base=DEFAULT_URL,
|
||||
to_dir=os.curdir, download_delay=15, no_fake=True):
|
||||
# making sure we use the absolute path
|
||||
to_dir = os.path.abspath(to_dir)
|
||||
was_imported = 'pkg_resources' in sys.modules or \
|
||||
'setuptools' in sys.modules
|
||||
try:
|
||||
try:
|
||||
import pkg_resources
|
||||
if not hasattr(pkg_resources, '_distribute'):
|
||||
if not no_fake:
|
||||
_fake_setuptools()
|
||||
raise ImportError
|
||||
except ImportError:
|
||||
return _do_download(version, download_base, to_dir, download_delay)
|
||||
try:
|
||||
pkg_resources.require("distribute>=" + version)
|
||||
return
|
||||
except pkg_resources.VersionConflict:
|
||||
e = sys.exc_info()[1]
|
||||
if was_imported:
|
||||
sys.stderr.write(
|
||||
"The required version of distribute (>=%s) is not available,\n"
|
||||
"and can't be installed while this script is running. Please\n"
|
||||
"install a more recent version first, using\n"
|
||||
"'easy_install -U distribute'."
|
||||
"\n\n(Currently using %r)\n" % (version, e.args[0]))
|
||||
sys.exit(2)
|
||||
else:
|
||||
del pkg_resources, sys.modules['pkg_resources'] # reload ok
|
||||
return _do_download(version, download_base, to_dir,
|
||||
download_delay)
|
||||
except pkg_resources.DistributionNotFound:
|
||||
return _do_download(version, download_base, to_dir,
|
||||
download_delay)
|
||||
finally:
|
||||
if not no_fake:
|
||||
_create_fake_setuptools_pkg_info(to_dir)
|
||||
|
||||
|
||||
def download_setuptools(version=DEFAULT_VERSION, download_base=DEFAULT_URL,
|
||||
to_dir=os.curdir, delay=15):
|
||||
"""Download distribute from a specified location and return its filename
|
||||
|
||||
`version` should be a valid distribute version number that is available
|
||||
as an egg for download under the `download_base` URL (which should end
|
||||
with a '/'). `to_dir` is the directory where the egg will be downloaded.
|
||||
`delay` is the number of seconds to pause before an actual download
|
||||
attempt.
|
||||
"""
|
||||
# making sure we use the absolute path
|
||||
to_dir = os.path.abspath(to_dir)
|
||||
try:
|
||||
from urllib.request import urlopen
|
||||
except ImportError:
|
||||
from urllib2 import urlopen
|
||||
tgz_name = "distribute-%s.tar.gz" % version
|
||||
url = download_base + tgz_name
|
||||
saveto = os.path.join(to_dir, tgz_name)
|
||||
src = dst = None
|
||||
if not os.path.exists(saveto): # Avoid repeated downloads
|
||||
try:
|
||||
log.warn("Downloading %s", url)
|
||||
src = urlopen(url)
|
||||
# Read/write all in one block, so we don't create a corrupt file
|
||||
# if the download is interrupted.
|
||||
data = src.read()
|
||||
dst = open(saveto, "wb")
|
||||
dst.write(data)
|
||||
finally:
|
||||
if src:
|
||||
src.close()
|
||||
if dst:
|
||||
dst.close()
|
||||
return os.path.realpath(saveto)
|
||||
|
||||
|
||||
def _no_sandbox(function):
|
||||
def __no_sandbox(*args, **kw):
|
||||
try:
|
||||
from setuptools.sandbox import DirectorySandbox
|
||||
if not hasattr(DirectorySandbox, '_old'):
|
||||
def violation(*args):
|
||||
pass
|
||||
DirectorySandbox._old = DirectorySandbox._violation
|
||||
DirectorySandbox._violation = violation
|
||||
patched = True
|
||||
else:
|
||||
patched = False
|
||||
except ImportError:
|
||||
patched = False
|
||||
|
||||
try:
|
||||
return function(*args, **kw)
|
||||
finally:
|
||||
if patched:
|
||||
DirectorySandbox._violation = DirectorySandbox._old
|
||||
del DirectorySandbox._old
|
||||
|
||||
return __no_sandbox
|
||||
|
||||
|
||||
def _patch_file(path, content):
|
||||
"""Will backup the file then patch it"""
|
||||
existing_content = open(path).read()
|
||||
if existing_content == content:
|
||||
# already patched
|
||||
log.warn('Already patched.')
|
||||
return False
|
||||
log.warn('Patching...')
|
||||
_rename_path(path)
|
||||
f = open(path, 'w')
|
||||
try:
|
||||
f.write(content)
|
||||
finally:
|
||||
f.close()
|
||||
return True
|
||||
|
||||
_patch_file = _no_sandbox(_patch_file)
|
||||
|
||||
|
||||
def _same_content(path, content):
|
||||
return open(path).read() == content
|
||||
|
||||
|
||||
def _rename_path(path):
|
||||
new_name = path + '.OLD.%s' % time.time()
|
||||
log.warn('Renaming %s to %s', path, new_name)
|
||||
os.rename(path, new_name)
|
||||
return new_name
|
||||
|
||||
|
||||
def _remove_flat_installation(placeholder):
|
||||
if not os.path.isdir(placeholder):
|
||||
log.warn('Unkown installation at %s', placeholder)
|
||||
return False
|
||||
found = False
|
||||
for file in os.listdir(placeholder):
|
||||
if fnmatch.fnmatch(file, 'setuptools*.egg-info'):
|
||||
found = True
|
||||
break
|
||||
if not found:
|
||||
log.warn('Could not locate setuptools*.egg-info')
|
||||
return
|
||||
|
||||
log.warn('Moving elements out of the way...')
|
||||
pkg_info = os.path.join(placeholder, file)
|
||||
if os.path.isdir(pkg_info):
|
||||
patched = _patch_egg_dir(pkg_info)
|
||||
else:
|
||||
patched = _patch_file(pkg_info, SETUPTOOLS_PKG_INFO)
|
||||
|
||||
if not patched:
|
||||
log.warn('%s already patched.', pkg_info)
|
||||
return False
|
||||
# now let's move the files out of the way
|
||||
for element in ('setuptools', 'pkg_resources.py', 'site.py'):
|
||||
element = os.path.join(placeholder, element)
|
||||
if os.path.exists(element):
|
||||
_rename_path(element)
|
||||
else:
|
||||
log.warn('Could not find the %s element of the '
|
||||
'Setuptools distribution', element)
|
||||
return True
|
||||
|
||||
_remove_flat_installation = _no_sandbox(_remove_flat_installation)
|
||||
|
||||
|
||||
def _after_install(dist):
|
||||
log.warn('After install bootstrap.')
|
||||
placeholder = dist.get_command_obj('install').install_purelib
|
||||
_create_fake_setuptools_pkg_info(placeholder)
|
||||
|
||||
|
||||
def _create_fake_setuptools_pkg_info(placeholder):
|
||||
if not placeholder or not os.path.exists(placeholder):
|
||||
log.warn('Could not find the install location')
|
||||
return
|
||||
pyver = '%s.%s' % (sys.version_info[0], sys.version_info[1])
|
||||
setuptools_file = 'setuptools-%s-py%s.egg-info' % \
|
||||
(SETUPTOOLS_FAKED_VERSION, pyver)
|
||||
pkg_info = os.path.join(placeholder, setuptools_file)
|
||||
if os.path.exists(pkg_info):
|
||||
log.warn('%s already exists', pkg_info)
|
||||
return
|
||||
|
||||
log.warn('Creating %s', pkg_info)
|
||||
try:
|
||||
f = open(pkg_info, 'w')
|
||||
except EnvironmentError:
|
||||
log.warn("Don't have permissions to write %s, skipping", pkg_info)
|
||||
return
|
||||
try:
|
||||
f.write(SETUPTOOLS_PKG_INFO)
|
||||
finally:
|
||||
f.close()
|
||||
|
||||
pth_file = os.path.join(placeholder, 'setuptools.pth')
|
||||
log.warn('Creating %s', pth_file)
|
||||
f = open(pth_file, 'w')
|
||||
try:
|
||||
f.write(os.path.join(os.curdir, setuptools_file))
|
||||
finally:
|
||||
f.close()
|
||||
|
||||
_create_fake_setuptools_pkg_info = _no_sandbox(
|
||||
_create_fake_setuptools_pkg_info
|
||||
)
|
||||
|
||||
|
||||
def _patch_egg_dir(path):
|
||||
# let's check if it's already patched
|
||||
pkg_info = os.path.join(path, 'EGG-INFO', 'PKG-INFO')
|
||||
if os.path.exists(pkg_info):
|
||||
if _same_content(pkg_info, SETUPTOOLS_PKG_INFO):
|
||||
log.warn('%s already patched.', pkg_info)
|
||||
return False
|
||||
_rename_path(path)
|
||||
os.mkdir(path)
|
||||
os.mkdir(os.path.join(path, 'EGG-INFO'))
|
||||
pkg_info = os.path.join(path, 'EGG-INFO', 'PKG-INFO')
|
||||
f = open(pkg_info, 'w')
|
||||
try:
|
||||
f.write(SETUPTOOLS_PKG_INFO)
|
||||
finally:
|
||||
f.close()
|
||||
return True
|
||||
|
||||
_patch_egg_dir = _no_sandbox(_patch_egg_dir)
|
||||
|
||||
|
||||
def _before_install():
|
||||
log.warn('Before install bootstrap.')
|
||||
_fake_setuptools()
|
||||
|
||||
|
||||
def _under_prefix(location):
|
||||
if 'install' not in sys.argv:
|
||||
return True
|
||||
args = sys.argv[sys.argv.index('install') + 1:]
|
||||
for index, arg in enumerate(args):
|
||||
for option in ('--root', '--prefix'):
|
||||
if arg.startswith('%s=' % option):
|
||||
top_dir = arg.split('root=')[-1]
|
||||
return location.startswith(top_dir)
|
||||
elif arg == option:
|
||||
if len(args) > index:
|
||||
top_dir = args[index + 1]
|
||||
return location.startswith(top_dir)
|
||||
if arg == '--user' and USER_SITE is not None:
|
||||
return location.startswith(USER_SITE)
|
||||
return True
|
||||
|
||||
|
||||
def _fake_setuptools():
|
||||
log.warn('Scanning installed packages')
|
||||
try:
|
||||
import pkg_resources
|
||||
except ImportError:
|
||||
# we're cool
|
||||
log.warn('Setuptools or Distribute does not seem to be installed.')
|
||||
return
|
||||
ws = pkg_resources.working_set
|
||||
try:
|
||||
setuptools_dist = ws.find(
|
||||
pkg_resources.Requirement.parse('setuptools', replacement=False)
|
||||
)
|
||||
except TypeError:
|
||||
# old distribute API
|
||||
setuptools_dist = ws.find(
|
||||
pkg_resources.Requirement.parse('setuptools')
|
||||
)
|
||||
|
||||
if setuptools_dist is None:
|
||||
log.warn('No setuptools distribution found')
|
||||
return
|
||||
# detecting if it was already faked
|
||||
setuptools_location = setuptools_dist.location
|
||||
log.warn('Setuptools installation detected at %s', setuptools_location)
|
||||
|
||||
# if --root or --preix was provided, and if
|
||||
# setuptools is not located in them, we don't patch it
|
||||
if not _under_prefix(setuptools_location):
|
||||
log.warn('Not patching, --root or --prefix is installing Distribute'
|
||||
' in another location')
|
||||
return
|
||||
|
||||
# let's see if its an egg
|
||||
if not setuptools_location.endswith('.egg'):
|
||||
log.warn('Non-egg installation')
|
||||
res = _remove_flat_installation(setuptools_location)
|
||||
if not res:
|
||||
return
|
||||
else:
|
||||
log.warn('Egg installation')
|
||||
pkg_info = os.path.join(setuptools_location, 'EGG-INFO', 'PKG-INFO')
|
||||
if (os.path.exists(pkg_info) and
|
||||
_same_content(pkg_info, SETUPTOOLS_PKG_INFO)):
|
||||
log.warn('Already patched.')
|
||||
return
|
||||
log.warn('Patching...')
|
||||
# let's create a fake egg replacing setuptools one
|
||||
res = _patch_egg_dir(setuptools_location)
|
||||
if not res:
|
||||
return
|
||||
log.warn('Patching complete.')
|
||||
_relaunch()
|
||||
|
||||
|
||||
def _relaunch():
|
||||
log.warn('Relaunching...')
|
||||
# we have to relaunch the process
|
||||
# pip marker to avoid a relaunch bug
|
||||
_cmd1 = ['-c', 'install', '--single-version-externally-managed']
|
||||
_cmd2 = ['-c', 'install', '--record']
|
||||
if sys.argv[:3] == _cmd1 or sys.argv[:3] == _cmd2:
|
||||
sys.argv[0] = 'setup.py'
|
||||
args = [sys.executable] + sys.argv
|
||||
sys.exit(subprocess.call(args))
|
||||
|
||||
|
||||
def _extractall(self, path=".", members=None):
|
||||
"""Extract all members from the archive to the current working
|
||||
directory and set owner, modification time and permissions on
|
||||
directories afterwards. `path' specifies a different directory
|
||||
to extract to. `members' is optional and must be a subset of the
|
||||
list returned by getmembers().
|
||||
"""
|
||||
import copy
|
||||
import operator
|
||||
from tarfile import ExtractError
|
||||
directories = []
|
||||
|
||||
if members is None:
|
||||
members = self
|
||||
|
||||
for tarinfo in members:
|
||||
if tarinfo.isdir():
|
||||
# Extract directories with a safe mode.
|
||||
directories.append(tarinfo)
|
||||
tarinfo = copy.copy(tarinfo)
|
||||
tarinfo.mode = 448 # decimal for oct 0700
|
||||
self.extract(tarinfo, path)
|
||||
|
||||
# Reverse sort directories.
|
||||
if sys.version_info < (2, 4):
|
||||
def sorter(dir1, dir2):
|
||||
return cmp(dir1.name, dir2.name)
|
||||
directories.sort(sorter)
|
||||
directories.reverse()
|
||||
else:
|
||||
directories.sort(key=operator.attrgetter('name'), reverse=True)
|
||||
|
||||
# Set correct owner, mtime and filemode on directories.
|
||||
for tarinfo in directories:
|
||||
dirpath = os.path.join(path, tarinfo.name)
|
||||
try:
|
||||
self.chown(tarinfo, dirpath)
|
||||
self.utime(tarinfo, dirpath)
|
||||
self.chmod(tarinfo, dirpath)
|
||||
except ExtractError:
|
||||
e = sys.exc_info()[1]
|
||||
if self.errorlevel > 1:
|
||||
raise
|
||||
else:
|
||||
self._dbg(1, "tarfile: %s" % e)
|
||||
|
||||
|
||||
def _build_install_args(options):
|
||||
"""
|
||||
Build the arguments to 'python setup.py install' on the distribute package
|
||||
"""
|
||||
install_args = []
|
||||
if options.user_install:
|
||||
if sys.version_info < (2, 6):
|
||||
log.warn("--user requires Python 2.6 or later")
|
||||
raise SystemExit(1)
|
||||
install_args.append('--user')
|
||||
return install_args
|
||||
|
||||
def _parse_args():
|
||||
"""
|
||||
Parse the command line for options
|
||||
"""
|
||||
parser = optparse.OptionParser()
|
||||
parser.add_option(
|
||||
'--user', dest='user_install', action='store_true', default=False,
|
||||
help='install in user site package (requires Python 2.6 or later)')
|
||||
parser.add_option(
|
||||
'--download-base', dest='download_base', metavar="URL",
|
||||
default=DEFAULT_URL,
|
||||
help='alternative URL from where to download the distribute package')
|
||||
options, args = parser.parse_args()
|
||||
# positional arguments are ignored
|
||||
return options
|
||||
|
||||
def main(version=DEFAULT_VERSION):
|
||||
"""Install or upgrade setuptools and EasyInstall"""
|
||||
options = _parse_args()
|
||||
tarball = download_setuptools(download_base=options.download_base)
|
||||
return _install(tarball, _build_install_args(options))
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main())
|
|
@ -1,284 +0,0 @@
|
|||
#!python
|
||||
"""Bootstrap setuptools installation
|
||||
|
||||
If you want to use setuptools in your package's setup.py, just include this
|
||||
file in the same directory with it, and add this to the top of your setup.py::
|
||||
|
||||
from ez_setup import use_setuptools
|
||||
use_setuptools()
|
||||
|
||||
If you want to require a specific version of setuptools, set a download
|
||||
mirror, or use an alternate download directory, you can do so by supplying
|
||||
the appropriate options to ``use_setuptools()``.
|
||||
|
||||
This file can also be run as a script to install or upgrade setuptools.
|
||||
"""
|
||||
import sys
|
||||
DEFAULT_VERSION = "0.6c11"
|
||||
DEFAULT_URL = "http://pypi.python.org/packages/%s/s/setuptools/" % sys.version[:3]
|
||||
|
||||
md5_data = {
|
||||
'setuptools-0.6b1-py2.3.egg': '8822caf901250d848b996b7f25c6e6ca',
|
||||
'setuptools-0.6b1-py2.4.egg': 'b79a8a403e4502fbb85ee3f1941735cb',
|
||||
'setuptools-0.6b2-py2.3.egg': '5657759d8a6d8fc44070a9d07272d99b',
|
||||
'setuptools-0.6b2-py2.4.egg': '4996a8d169d2be661fa32a6e52e4f82a',
|
||||
'setuptools-0.6b3-py2.3.egg': 'bb31c0fc7399a63579975cad9f5a0618',
|
||||
'setuptools-0.6b3-py2.4.egg': '38a8c6b3d6ecd22247f179f7da669fac',
|
||||
'setuptools-0.6b4-py2.3.egg': '62045a24ed4e1ebc77fe039aa4e6f7e5',
|
||||
'setuptools-0.6b4-py2.4.egg': '4cb2a185d228dacffb2d17f103b3b1c4',
|
||||
'setuptools-0.6c1-py2.3.egg': 'b3f2b5539d65cb7f74ad79127f1a908c',
|
||||
'setuptools-0.6c1-py2.4.egg': 'b45adeda0667d2d2ffe14009364f2a4b',
|
||||
'setuptools-0.6c10-py2.3.egg': 'ce1e2ab5d3a0256456d9fc13800a7090',
|
||||
'setuptools-0.6c10-py2.4.egg': '57d6d9d6e9b80772c59a53a8433a5dd4',
|
||||
'setuptools-0.6c10-py2.5.egg': 'de46ac8b1c97c895572e5e8596aeb8c7',
|
||||
'setuptools-0.6c10-py2.6.egg': '58ea40aef06da02ce641495523a0b7f5',
|
||||
'setuptools-0.6c11-py2.3.egg': '2baeac6e13d414a9d28e7ba5b5a596de',
|
||||
'setuptools-0.6c11-py2.4.egg': 'bd639f9b0eac4c42497034dec2ec0c2b',
|
||||
'setuptools-0.6c11-py2.5.egg': '64c94f3bf7a72a13ec83e0b24f2749b2',
|
||||
'setuptools-0.6c11-py2.6.egg': 'bfa92100bd772d5a213eedd356d64086',
|
||||
'setuptools-0.6c2-py2.3.egg': 'f0064bf6aa2b7d0f3ba0b43f20817c27',
|
||||
'setuptools-0.6c2-py2.4.egg': '616192eec35f47e8ea16cd6a122b7277',
|
||||
'setuptools-0.6c3-py2.3.egg': 'f181fa125dfe85a259c9cd6f1d7b78fa',
|
||||
'setuptools-0.6c3-py2.4.egg': 'e0ed74682c998bfb73bf803a50e7b71e',
|
||||
'setuptools-0.6c3-py2.5.egg': 'abef16fdd61955514841c7c6bd98965e',
|
||||
'setuptools-0.6c4-py2.3.egg': 'b0b9131acab32022bfac7f44c5d7971f',
|
||||
'setuptools-0.6c4-py2.4.egg': '2a1f9656d4fbf3c97bf946c0a124e6e2',
|
||||
'setuptools-0.6c4-py2.5.egg': '8f5a052e32cdb9c72bcf4b5526f28afc',
|
||||
'setuptools-0.6c5-py2.3.egg': 'ee9fd80965da04f2f3e6b3576e9d8167',
|
||||
'setuptools-0.6c5-py2.4.egg': 'afe2adf1c01701ee841761f5bcd8aa64',
|
||||
'setuptools-0.6c5-py2.5.egg': 'a8d3f61494ccaa8714dfed37bccd3d5d',
|
||||
'setuptools-0.6c6-py2.3.egg': '35686b78116a668847237b69d549ec20',
|
||||
'setuptools-0.6c6-py2.4.egg': '3c56af57be3225019260a644430065ab',
|
||||
'setuptools-0.6c6-py2.5.egg': 'b2f8a7520709a5b34f80946de5f02f53',
|
||||
'setuptools-0.6c7-py2.3.egg': '209fdf9adc3a615e5115b725658e13e2',
|
||||
'setuptools-0.6c7-py2.4.egg': '5a8f954807d46a0fb67cf1f26c55a82e',
|
||||
'setuptools-0.6c7-py2.5.egg': '45d2ad28f9750e7434111fde831e8372',
|
||||
'setuptools-0.6c8-py2.3.egg': '50759d29b349db8cfd807ba8303f1902',
|
||||
'setuptools-0.6c8-py2.4.egg': 'cba38d74f7d483c06e9daa6070cce6de',
|
||||
'setuptools-0.6c8-py2.5.egg': '1721747ee329dc150590a58b3e1ac95b',
|
||||
'setuptools-0.6c9-py2.3.egg': 'a83c4020414807b496e4cfbe08507c03',
|
||||
'setuptools-0.6c9-py2.4.egg': '260a2be2e5388d66bdaee06abec6342a',
|
||||
'setuptools-0.6c9-py2.5.egg': 'fe67c3e5a17b12c0e7c541b7ea43a8e6',
|
||||
'setuptools-0.6c9-py2.6.egg': 'ca37b1ff16fa2ede6e19383e7b59245a',
|
||||
}
|
||||
|
||||
import sys, os
|
||||
try: from hashlib import md5
|
||||
except ImportError: from md5 import md5
|
||||
|
||||
def _validate_md5(egg_name, data):
|
||||
if egg_name in md5_data:
|
||||
digest = md5(data).hexdigest()
|
||||
if digest != md5_data[egg_name]:
|
||||
print >>sys.stderr, (
|
||||
"md5 validation of %s failed! (Possible download problem?)"
|
||||
% egg_name
|
||||
)
|
||||
sys.exit(2)
|
||||
return data
|
||||
|
||||
def use_setuptools(
|
||||
version=DEFAULT_VERSION, download_base=DEFAULT_URL, to_dir=os.curdir,
|
||||
download_delay=15
|
||||
):
|
||||
"""Automatically find/download setuptools and make it available on sys.path
|
||||
|
||||
`version` should be a valid setuptools version number that is available
|
||||
as an egg for download under the `download_base` URL (which should end with
|
||||
a '/'). `to_dir` is the directory where setuptools will be downloaded, if
|
||||
it is not already available. If `download_delay` is specified, it should
|
||||
be the number of seconds that will be paused before initiating a download,
|
||||
should one be required. If an older version of setuptools is installed,
|
||||
this routine will print a message to ``sys.stderr`` and raise SystemExit in
|
||||
an attempt to abort the calling script.
|
||||
"""
|
||||
was_imported = 'pkg_resources' in sys.modules or 'setuptools' in sys.modules
|
||||
def do_download():
|
||||
egg = download_setuptools(version, download_base, to_dir, download_delay)
|
||||
sys.path.insert(0, egg)
|
||||
import setuptools; setuptools.bootstrap_install_from = egg
|
||||
try:
|
||||
import pkg_resources
|
||||
except ImportError:
|
||||
return do_download()
|
||||
try:
|
||||
pkg_resources.require("setuptools>="+version); return
|
||||
except pkg_resources.VersionConflict, e:
|
||||
if was_imported:
|
||||
print >>sys.stderr, (
|
||||
"The required version of setuptools (>=%s) is not available, and\n"
|
||||
"can't be installed while this script is running. Please install\n"
|
||||
" a more recent version first, using 'easy_install -U setuptools'."
|
||||
"\n\n(Currently using %r)"
|
||||
) % (version, e.args[0])
|
||||
sys.exit(2)
|
||||
except pkg_resources.DistributionNotFound:
|
||||
pass
|
||||
|
||||
del pkg_resources, sys.modules['pkg_resources'] # reload ok
|
||||
return do_download()
|
||||
|
||||
def download_setuptools(
|
||||
version=DEFAULT_VERSION, download_base=DEFAULT_URL, to_dir=os.curdir,
|
||||
delay = 15
|
||||
):
|
||||
"""Download setuptools from a specified location and return its filename
|
||||
|
||||
`version` should be a valid setuptools version number that is available
|
||||
as an egg for download under the `download_base` URL (which should end
|
||||
with a '/'). `to_dir` is the directory where the egg will be downloaded.
|
||||
`delay` is the number of seconds to pause before an actual download attempt.
|
||||
"""
|
||||
import urllib2, shutil
|
||||
egg_name = "setuptools-%s-py%s.egg" % (version,sys.version[:3])
|
||||
url = download_base + egg_name
|
||||
saveto = os.path.join(to_dir, egg_name)
|
||||
src = dst = None
|
||||
if not os.path.exists(saveto): # Avoid repeated downloads
|
||||
try:
|
||||
from distutils import log
|
||||
if delay:
|
||||
log.warn("""
|
||||
---------------------------------------------------------------------------
|
||||
This script requires setuptools version %s to run (even to display
|
||||
help). I will attempt to download it for you (from
|
||||
%s), but
|
||||
you may need to enable firewall access for this script first.
|
||||
I will start the download in %d seconds.
|
||||
|
||||
(Note: if this machine does not have network access, please obtain the file
|
||||
|
||||
%s
|
||||
|
||||
and place it in this directory before rerunning this script.)
|
||||
---------------------------------------------------------------------------""",
|
||||
version, download_base, delay, url
|
||||
); from time import sleep; sleep(delay)
|
||||
log.warn("Downloading %s", url)
|
||||
src = urllib2.urlopen(url)
|
||||
# Read/write all in one block, so we don't create a corrupt file
|
||||
# if the download is interrupted.
|
||||
data = _validate_md5(egg_name, src.read())
|
||||
dst = open(saveto,"wb"); dst.write(data)
|
||||
finally:
|
||||
if src: src.close()
|
||||
if dst: dst.close()
|
||||
return os.path.realpath(saveto)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
def main(argv, version=DEFAULT_VERSION):
|
||||
"""Install or upgrade setuptools and EasyInstall"""
|
||||
try:
|
||||
import setuptools
|
||||
except ImportError:
|
||||
egg = None
|
||||
try:
|
||||
egg = download_setuptools(version, delay=0)
|
||||
sys.path.insert(0,egg)
|
||||
from setuptools.command.easy_install import main
|
||||
return main(list(argv)+[egg]) # we're done here
|
||||
finally:
|
||||
if egg and os.path.exists(egg):
|
||||
os.unlink(egg)
|
||||
else:
|
||||
if setuptools.__version__ == '0.0.1':
|
||||
print >>sys.stderr, (
|
||||
"You have an obsolete version of setuptools installed. Please\n"
|
||||
"remove it from your system entirely before rerunning this script."
|
||||
)
|
||||
sys.exit(2)
|
||||
|
||||
req = "setuptools>="+version
|
||||
import pkg_resources
|
||||
try:
|
||||
pkg_resources.require(req)
|
||||
except pkg_resources.VersionConflict:
|
||||
try:
|
||||
from setuptools.command.easy_install import main
|
||||
except ImportError:
|
||||
from easy_install import main
|
||||
main(list(argv)+[download_setuptools(delay=0)])
|
||||
sys.exit(0) # try to force an exit
|
||||
else:
|
||||
if argv:
|
||||
from setuptools.command.easy_install import main
|
||||
main(argv)
|
||||
else:
|
||||
print "Setuptools version",version,"or greater has been installed."
|
||||
print '(Run "ez_setup.py -U setuptools" to reinstall or upgrade.)'
|
||||
|
||||
def update_md5(filenames):
|
||||
"""Update our built-in md5 registry"""
|
||||
|
||||
import re
|
||||
|
||||
for name in filenames:
|
||||
base = os.path.basename(name)
|
||||
f = open(name,'rb')
|
||||
md5_data[base] = md5(f.read()).hexdigest()
|
||||
f.close()
|
||||
|
||||
data = [" %r: %r,\n" % it for it in md5_data.items()]
|
||||
data.sort()
|
||||
repl = "".join(data)
|
||||
|
||||
import inspect
|
||||
srcfile = inspect.getsourcefile(sys.modules[__name__])
|
||||
f = open(srcfile, 'rb'); src = f.read(); f.close()
|
||||
|
||||
match = re.search("\nmd5_data = {\n([^}]+)}", src)
|
||||
if not match:
|
||||
print >>sys.stderr, "Internal error!"
|
||||
sys.exit(2)
|
||||
|
||||
src = src[:match.start(1)] + repl + src[match.end(1):]
|
||||
f = open(srcfile,'w')
|
||||
f.write(src)
|
||||
f.close()
|
||||
|
||||
|
||||
if __name__=='__main__':
|
||||
if len(sys.argv)>2 and sys.argv[1]=='--md5update':
|
||||
update_md5(sys.argv[2:])
|
||||
else:
|
||||
main(sys.argv[1:])
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -83,6 +83,7 @@ ENABLE_USER_SITE = None
|
|||
USER_SITE = None
|
||||
USER_BASE = None
|
||||
|
||||
_is_64bit = (getattr(sys, 'maxsize', None) or getattr(sys, 'maxint')) > 2**32
|
||||
_is_pypy = hasattr(sys, 'pypy_version_info')
|
||||
_is_jython = sys.platform[:4] == 'java'
|
||||
if _is_jython:
|
||||
|
@ -236,9 +237,9 @@ def addsitepackages(known_paths, sys_prefix=sys.prefix, exec_prefix=sys.exec_pre
|
|||
os.path.join(prefix, "lib", "site-python"),
|
||||
os.path.join(prefix, "python" + sys.version[:3], "lib-dynload")]
|
||||
lib64_dir = os.path.join(prefix, "lib64", "python" + sys.version[:3], "site-packages")
|
||||
if (os.path.exists(lib64_dir) and
|
||||
if (os.path.exists(lib64_dir) and
|
||||
os.path.realpath(lib64_dir) not in [os.path.realpath(p) for p in sitedirs]):
|
||||
if sys.maxsize > 2**32:
|
||||
if _is_64bit:
|
||||
sitedirs.insert(0, lib64_dir)
|
||||
else:
|
||||
sitedirs.append(lib64_dir)
|
||||
|
@ -559,13 +560,17 @@ def virtual_install_main_packages():
|
|||
if _is_jython:
|
||||
paths = [os.path.join(sys.real_prefix, 'Lib')]
|
||||
elif _is_pypy:
|
||||
if sys.pypy_version_info >= (1, 5):
|
||||
if sys.version_info > (3, 2):
|
||||
cpyver = '%d' % sys.version_info[0]
|
||||
elif sys.pypy_version_info >= (1, 5):
|
||||
cpyver = '%d.%d' % sys.version_info[:2]
|
||||
else:
|
||||
cpyver = '%d.%d.%d' % sys.version_info[:3]
|
||||
paths = [os.path.join(sys.real_prefix, 'lib_pypy'),
|
||||
os.path.join(sys.real_prefix, 'lib-python', 'modified-%s' % cpyver),
|
||||
os.path.join(sys.real_prefix, 'lib-python', cpyver)]
|
||||
if sys.pypy_version_info < (1, 9):
|
||||
paths.insert(1, os.path.join(sys.real_prefix,
|
||||
'lib-python', 'modified-%s' % cpyver))
|
||||
hardcoded_relative_dirs = paths[:] # for the special 'darwin' case below
|
||||
#
|
||||
# This is hardcoded in the Python executable, but relative to sys.prefix:
|
||||
|
@ -580,7 +585,7 @@ def virtual_install_main_packages():
|
|||
hardcoded_relative_dirs = paths[:] # for the special 'darwin' case below
|
||||
lib64_path = os.path.join(sys.real_prefix, 'lib64', 'python'+sys.version[:3])
|
||||
if os.path.exists(lib64_path):
|
||||
if sys.maxsize > 2**32:
|
||||
if _is_64bit:
|
||||
paths.insert(0, lib64_path)
|
||||
else:
|
||||
paths.append(lib64_path)
|
||||
|
@ -594,7 +599,7 @@ def virtual_install_main_packages():
|
|||
except AttributeError:
|
||||
# This is a non-multiarch aware Python. Fallback to the old way.
|
||||
arch = sys.platform
|
||||
plat_path = os.path.join(sys.real_prefix, 'lib',
|
||||
plat_path = os.path.join(sys.real_prefix, 'lib',
|
||||
'python'+sys.version[:3],
|
||||
'plat-%s' % arch)
|
||||
if os.path.exists(plat_path):
|
||||
|
@ -626,14 +631,14 @@ def force_global_eggs_after_local_site_packages():
|
|||
maintains the "least surprise" result that packages in the
|
||||
virtualenv always mask global packages, never the other way
|
||||
around.
|
||||
|
||||
|
||||
"""
|
||||
egginsert = getattr(sys, '__egginsert', 0)
|
||||
for i, path in enumerate(sys.path):
|
||||
if i > egginsert and path.startswith(sys.prefix):
|
||||
egginsert = i
|
||||
sys.__egginsert = egginsert + 1
|
||||
|
||||
|
||||
def virtual_addsitepackages(known_paths):
|
||||
force_global_eggs_after_local_site_packages()
|
||||
return addsitepackages(known_paths, sys_prefix=sys.real_prefix)
|
||||
|
|
Двоичные данные
python/virtualenv/virtualenv_support/distribute-0.6.31.tar.gz
Двоичные данные
python/virtualenv/virtualenv_support/distribute-0.6.31.tar.gz
Двоичный файл не отображается.
Двоичные данные
python/virtualenv/virtualenv_support/pip-1.2.1.tar.gz
Двоичные данные
python/virtualenv/virtualenv_support/pip-1.2.1.tar.gz
Двоичный файл не отображается.
Двоичный файл не отображается.
Двоичные данные
python/virtualenv/virtualenv_support/setuptools-0.6c11-py2.5.egg
Двоичные данные
python/virtualenv/virtualenv_support/setuptools-0.6c11-py2.5.egg
Двоичный файл не отображается.
Двоичные данные
python/virtualenv/virtualenv_support/setuptools-0.6c11-py2.6.egg
Двоичные данные
python/virtualenv/virtualenv_support/setuptools-0.6c11-py2.6.egg
Двоичный файл не отображается.
Двоичные данные
python/virtualenv/virtualenv_support/setuptools-0.6c11-py2.7.egg
Двоичные данные
python/virtualenv/virtualenv_support/setuptools-0.6c11-py2.7.egg
Двоичный файл не отображается.
Двоичный файл не отображается.
|
@ -1,4 +1,4 @@
|
|||
/* -*- Mode: js2; js2-basic-offset: 2; indent-tabs-mode: nil; -*- */
|
||||
/* -*- js2-basic-offset: 2; indent-tabs-mode: nil; -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* -*- Mode: js2; js2-basic-offset: 2; indent-tabs-mode: nil; -*- */
|
||||
/* -*- js2-basic-offset: 2; indent-tabs-mode: nil; -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* -*- Mode: js2; js2-basic-offset: 2; indent-tabs-mode: nil; -*- */
|
||||
/* -*- js2-basic-offset: 2; indent-tabs-mode: nil; -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* -*- Mode: js2; js2-basic-offset: 2; indent-tabs-mode: nil; -*- */
|
||||
/* -*- js2-basic-offset: 2; indent-tabs-mode: nil; -*- */
|
||||
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -922,10 +922,8 @@ class nsCycleCollector
|
|||
|
||||
nsIThread* mThread;
|
||||
|
||||
public:
|
||||
nsCycleCollectorParams mParams;
|
||||
|
||||
private:
|
||||
nsTArray<PtrInfo*> *mWhiteNodes;
|
||||
uint32_t mWhiteNodeCount;
|
||||
|
||||
|
@ -971,7 +969,7 @@ public:
|
|||
bool Collect(ccType aCCType,
|
||||
nsTArray<PtrInfo*> *aWhiteNodes,
|
||||
nsCycleCollectorResults *aResults,
|
||||
nsICycleCollectorListener *aListener);
|
||||
nsICycleCollectorListener *aManualListener);
|
||||
void Shutdown();
|
||||
|
||||
void SizeOfIncludingThis(MallocSizeOf aMallocSizeOf,
|
||||
|
@ -984,20 +982,20 @@ public:
|
|||
|
||||
private:
|
||||
void CheckThreadSafety();
|
||||
void ShutdownCollect(nsICycleCollectorListener *aListener);
|
||||
void ShutdownCollect();
|
||||
|
||||
void PrepareForCollection(nsCycleCollectorResults *aResults,
|
||||
nsTArray<PtrInfo*> *aWhiteNodes);
|
||||
void FixGrayBits(bool aForceGC);
|
||||
bool ShouldMergeZones(ccType aCCType);
|
||||
|
||||
void BeginCollection(ccType aCCType, nsICycleCollectorListener *aListener);
|
||||
void BeginCollection(ccType aCCType, nsICycleCollectorListener *aManualListener);
|
||||
void MarkRoots(GCGraphBuilder &aBuilder);
|
||||
void ScanRoots();
|
||||
void ScanRoots(nsICycleCollectorListener *aListener);
|
||||
void ScanWeakMaps();
|
||||
|
||||
// returns whether anything was collected
|
||||
bool CollectWhite(nsICycleCollectorListener *aListener);
|
||||
bool CollectWhite();
|
||||
|
||||
void CleanupAfterCollection();
|
||||
};
|
||||
|
@ -2263,7 +2261,7 @@ nsCycleCollector::ScanWeakMaps()
|
|||
}
|
||||
|
||||
void
|
||||
nsCycleCollector::ScanRoots()
|
||||
nsCycleCollector::ScanRoots(nsICycleCollectorListener *aListener)
|
||||
{
|
||||
mWhiteNodeCount = 0;
|
||||
|
||||
|
@ -2279,6 +2277,33 @@ nsCycleCollector::ScanRoots()
|
|||
}
|
||||
|
||||
ScanWeakMaps();
|
||||
|
||||
if (aListener) {
|
||||
aListener->BeginResults();
|
||||
|
||||
NodePool::Enumerator etor(mGraph.mNodes);
|
||||
while (!etor.IsDone()) {
|
||||
PtrInfo *pi = etor.GetNext();
|
||||
switch (pi->mColor) {
|
||||
case black:
|
||||
if (pi->mRefCount > 0 && pi->mRefCount < UINT32_MAX &&
|
||||
pi->mInternalRefs != pi->mRefCount) {
|
||||
aListener->DescribeRoot((uint64_t)pi->mPointer,
|
||||
pi->mInternalRefs);
|
||||
}
|
||||
break;
|
||||
case white:
|
||||
aListener->DescribeGarbage((uint64_t)pi->mPointer);
|
||||
break;
|
||||
case grey:
|
||||
// With incremental CC, we can end up with a grey object after
|
||||
// scanning if it is only reachable from an object that gets freed.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
aListener->End();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -2287,7 +2312,7 @@ nsCycleCollector::ScanRoots()
|
|||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool
|
||||
nsCycleCollector::CollectWhite(nsICycleCollectorListener *aListener)
|
||||
nsCycleCollector::CollectWhite()
|
||||
{
|
||||
// Explanation of "somewhat modified": we have no way to collect the
|
||||
// set of whites "all at once", we have to ask each of them to drop
|
||||
|
@ -2344,14 +2369,6 @@ nsCycleCollector::CollectWhite(nsICycleCollectorListener *aListener)
|
|||
timeLog.Checkpoint("CollectWhite::BeforeUnlinkCB");
|
||||
}
|
||||
|
||||
if (aListener) {
|
||||
for (uint32_t i = 0; i < count; ++i) {
|
||||
PtrInfo *pinfo = mWhiteNodes->ElementAt(i);
|
||||
aListener->DescribeGarbage((uint64_t)pinfo->mPointer);
|
||||
}
|
||||
aListener->End();
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < count; ++i) {
|
||||
PtrInfo *pinfo = mWhiteNodes->ElementAt(i);
|
||||
#ifdef DEBUG
|
||||
|
@ -2661,13 +2678,13 @@ nsCycleCollector::CleanupAfterCollection()
|
|||
}
|
||||
|
||||
void
|
||||
nsCycleCollector::ShutdownCollect(nsICycleCollectorListener *aListener)
|
||||
nsCycleCollector::ShutdownCollect()
|
||||
{
|
||||
nsAutoTArray<PtrInfo*, 4000> whiteNodes;
|
||||
|
||||
for (uint32_t i = 0; i < DEFAULT_SHUTDOWN_COLLECTIONS; ++i) {
|
||||
NS_ASSERTION(i < NORMAL_SHUTDOWN_COLLECTIONS, "Extra shutdown CC");
|
||||
if (!Collect(ShutdownCC, &whiteNodes, nullptr, aListener)) {
|
||||
if (!Collect(ShutdownCC, &whiteNodes, nullptr, nullptr)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -2677,7 +2694,7 @@ bool
|
|||
nsCycleCollector::Collect(ccType aCCType,
|
||||
nsTArray<PtrInfo*> *aWhiteNodes,
|
||||
nsCycleCollectorResults *aResults,
|
||||
nsICycleCollectorListener *aListener)
|
||||
nsICycleCollectorListener *aManualListener)
|
||||
{
|
||||
CheckThreadSafety();
|
||||
|
||||
|
@ -2687,23 +2704,8 @@ nsCycleCollector::Collect(ccType aCCType,
|
|||
}
|
||||
|
||||
PrepareForCollection(aResults, aWhiteNodes);
|
||||
|
||||
bool forceGC = (aCCType == ShutdownCC);
|
||||
if (!forceGC && aListener) {
|
||||
// On a WantAllTraces CC, force a synchronous global GC to prevent
|
||||
// hijinks from ForgetSkippable and compartmental GCs.
|
||||
aListener->GetWantAllTraces(&forceGC);
|
||||
}
|
||||
FixGrayBits(forceGC);
|
||||
|
||||
FreeSnowWhite(true);
|
||||
|
||||
if (aListener && NS_FAILED(aListener->Begin())) {
|
||||
aListener = nullptr;
|
||||
}
|
||||
|
||||
BeginCollection(aCCType, aListener);
|
||||
bool collectedAny = CollectWhite(aListener);
|
||||
BeginCollection(aCCType, aManualListener);
|
||||
bool collectedAny = CollectWhite();
|
||||
CleanupAfterCollection();
|
||||
return collectedAny;
|
||||
}
|
||||
|
@ -2745,17 +2747,46 @@ nsCycleCollector::ShouldMergeZones(ccType aCCType)
|
|||
|
||||
void
|
||||
nsCycleCollector::BeginCollection(ccType aCCType,
|
||||
nsICycleCollectorListener *aListener)
|
||||
nsICycleCollectorListener *aManualListener)
|
||||
{
|
||||
// aListener should be Begin()'d before this
|
||||
TimeLog timeLog;
|
||||
bool isShutdown = (aCCType == ShutdownCC);
|
||||
|
||||
// Set up the listener for this CC.
|
||||
MOZ_ASSERT_IF(isShutdown, !aManualListener);
|
||||
nsCOMPtr<nsICycleCollectorListener> listener(aManualListener);
|
||||
aManualListener = nullptr;
|
||||
if (!listener) {
|
||||
if (mParams.mLogAll || (isShutdown && mParams.mLogShutdown)) {
|
||||
nsRefPtr<nsCycleCollectorLogger> logger = new nsCycleCollectorLogger();
|
||||
if (isShutdown && mParams.mAllTracesAtShutdown) {
|
||||
logger->SetAllTraces();
|
||||
}
|
||||
listener = logger.forget();
|
||||
}
|
||||
}
|
||||
|
||||
bool forceGC = isShutdown;
|
||||
if (!forceGC && listener) {
|
||||
// On a WantAllTraces CC, force a synchronous global GC to prevent
|
||||
// hijinks from ForgetSkippable and compartmental GCs.
|
||||
listener->GetWantAllTraces(&forceGC);
|
||||
}
|
||||
FixGrayBits(forceGC);
|
||||
|
||||
FreeSnowWhite(true);
|
||||
|
||||
if (listener && NS_FAILED(listener->Begin())) {
|
||||
listener = nullptr;
|
||||
}
|
||||
|
||||
// Set up the data structures for building the graph.
|
||||
bool mergeZones = ShouldMergeZones(aCCType);
|
||||
if (mResults) {
|
||||
mResults->mMergedZones = mergeZones;
|
||||
}
|
||||
|
||||
GCGraphBuilder builder(this, mGraph, mJSRuntime, aListener,
|
||||
GCGraphBuilder builder(this, mGraph, mJSRuntime, listener,
|
||||
mergeZones);
|
||||
|
||||
if (mJSRuntime) {
|
||||
|
@ -2771,25 +2802,10 @@ nsCycleCollector::BeginCollection(ccType aCCType,
|
|||
MarkRoots(builder);
|
||||
timeLog.Checkpoint("MarkRoots()");
|
||||
|
||||
ScanRoots();
|
||||
ScanRoots(listener);
|
||||
timeLog.Checkpoint("ScanRoots()");
|
||||
|
||||
mScanInProgress = false;
|
||||
|
||||
if (aListener) {
|
||||
aListener->BeginResults();
|
||||
|
||||
NodePool::Enumerator etor(mGraph.mNodes);
|
||||
while (!etor.IsDone()) {
|
||||
PtrInfo *pi = etor.GetNext();
|
||||
if (pi->mColor == black &&
|
||||
pi->mRefCount > 0 && pi->mRefCount < UINT32_MAX &&
|
||||
pi->mInternalRefs != pi->mRefCount) {
|
||||
aListener->DescribeRoot((uint64_t)pi->mPointer,
|
||||
pi->mInternalRefs);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t
|
||||
|
@ -2811,14 +2827,7 @@ nsCycleCollector::Shutdown()
|
|||
if (PR_GetEnv("XPCOM_CC_RUN_DURING_SHUTDOWN"))
|
||||
#endif
|
||||
{
|
||||
nsCOMPtr<nsCycleCollectorLogger> listener;
|
||||
if (mParams.mLogAll || mParams.mLogShutdown) {
|
||||
listener = new nsCycleCollectorLogger();
|
||||
if (mParams.mAllTracesAtShutdown) {
|
||||
listener->SetAllTraces();
|
||||
}
|
||||
}
|
||||
ShutdownCollect(listener);
|
||||
ShutdownCollect();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3147,7 +3156,7 @@ nsCycleCollector_doDeferredDeletion()
|
|||
void
|
||||
nsCycleCollector_collect(bool aManuallyTriggered,
|
||||
nsCycleCollectorResults *aResults,
|
||||
nsICycleCollectorListener *aListener)
|
||||
nsICycleCollectorListener *aManualListener)
|
||||
{
|
||||
CollectorData *data = sCollectorData.get();
|
||||
|
||||
|
@ -3156,14 +3165,11 @@ nsCycleCollector_collect(bool aManuallyTriggered,
|
|||
MOZ_ASSERT(data->mCollector);
|
||||
|
||||
PROFILER_LABEL("CC", "nsCycleCollector_collect");
|
||||
nsCOMPtr<nsICycleCollectorListener> listener(aListener);
|
||||
if (!aListener && data->mCollector->mParams.mLogAll) {
|
||||
listener = new nsCycleCollectorLogger();
|
||||
}
|
||||
|
||||
MOZ_ASSERT_IF(aManualListener, aManuallyTriggered);
|
||||
nsAutoTArray<PtrInfo*, 4000> whiteNodes;
|
||||
data->mCollector->Collect(aManuallyTriggered ? ManualCC : ScheduledCC,
|
||||
&whiteNodes, aResults, listener);
|
||||
&whiteNodes, aResults, aManualListener);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -57,7 +57,7 @@ bool nsCycleCollector_doDeferredDeletion();
|
|||
|
||||
void nsCycleCollector_collect(bool aManuallyTriggered,
|
||||
nsCycleCollectorResults *aResults,
|
||||
nsICycleCollectorListener *aListener);
|
||||
nsICycleCollectorListener *aManualListener);
|
||||
uint32_t nsCycleCollector_suspectedCount();
|
||||
void nsCycleCollector_shutdown();
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче