This commit is contained in:
Ryan VanderMeulen 2013-09-06 20:55:41 -04:00
Родитель 9dd8ba855f bb260232f5
Коммит 4dec0a7644
86 изменённых файлов: 1558 добавлений и 1041 удалений

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

@ -488,9 +488,6 @@ private:
InitDomainPolicy(JSContext* cx, const char* aPolicyName,
DomainPolicy* aDomainPolicy);
// JS strings we need to clean up on shutdown
static jsid sEnabledID;
inline void
ScriptSecurityPrefChanged();

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

@ -77,6 +77,18 @@ nsIStringBundle *nsScriptSecurityManager::sStrBundle = nullptr;
JSRuntime *nsScriptSecurityManager::sRuntime = 0;
bool nsScriptSecurityManager::sStrictFileOriginPolicy = true;
// Lazily initialized. Use the getter below.
static jsid sEnabledID = JSID_VOID;
static jsid
EnabledID()
{
if (sEnabledID != JSID_VOID)
return sEnabledID;
AutoSafeJSContext cx;
sEnabledID = INTERNED_STRING_TO_JSID(cx, JS_InternString(cx, "enabled"));
return sEnabledID;
}
bool
nsScriptSecurityManager::SubjectIsPrivileged()
{
@ -1446,7 +1458,7 @@ nsScriptSecurityManager::CheckLoadURIWithPrincipal(nsIPrincipal* aPrincipal,
ClassInfoData nameData(nullptr, loadURIPrefGroup);
SecurityLevel secLevel;
rv = LookupPolicy(aPrincipal, nameData, sEnabledID,
rv = LookupPolicy(aPrincipal, nameData, EnabledID(),
nsIXPCSecurityManager::ACCESS_GET_PROPERTY,
nullptr, &secLevel);
if (NS_SUCCEEDED(rv) && secLevel.level == SCRIPT_SECURITY_ALL_ACCESS)
@ -1733,7 +1745,7 @@ nsScriptSecurityManager::CanExecuteScripts(JSContext* cx,
ClassInfoData nameData(nullptr, jsPrefGroupName);
SecurityLevel secLevel;
rv = LookupPolicy(aPrincipal, nameData, sEnabledID,
rv = LookupPolicy(aPrincipal, nameData, EnabledID(),
nsIXPCSecurityManager::ACCESS_GET_PROPERTY,
nullptr, &secLevel);
if (NS_FAILED(rv) || secLevel.level == SCRIPT_SECURITY_NO_ACCESS)
@ -2330,14 +2342,6 @@ nsScriptSecurityManager::nsScriptSecurityManager(void)
nsresult nsScriptSecurityManager::Init()
{
JSContext* cx = GetSafeJSContext();
if (!cx) return NS_ERROR_FAILURE; // this can happen of xpt loading fails
::JS_BeginRequest(cx);
if (sEnabledID == JSID_VOID)
sEnabledID = INTERNED_STRING_TO_JSID(cx, ::JS_InternString(cx, "enabled"));
::JS_EndRequest(cx);
InitPrefs();
nsresult rv = CallGetService(NS_IOSERVICE_CONTRACTID, &sIOService);
@ -2378,8 +2382,6 @@ nsresult nsScriptSecurityManager::Init()
static StaticRefPtr<nsScriptSecurityManager> gScriptSecMan;
jsid nsScriptSecurityManager::sEnabledID = JSID_VOID;
nsScriptSecurityManager::~nsScriptSecurityManager(void)
{
Preferences::RemoveObservers(this, kObservedPrefs);

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

@ -9,6 +9,7 @@
#include "nsIProtocolHandler.h"
#include "nsIURI.h"
#include "nsCOMPtr.h"
#include "nsIInputStream.h"
#define BLOBURI_SCHEME "blob"
#define MEDIASTREAMURI_SCHEME "mediastream"
@ -18,7 +19,6 @@
class nsIDOMBlob;
class nsIDOMMediaStream;
class nsIPrincipal;
class nsIInputStream;
namespace mozilla {
namespace dom {

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

@ -67,6 +67,7 @@
#include "nsCharSeparatedTokenizer.h"
#include "nsFormData.h"
#include "nsStreamListenerWrapper.h"
#include "xpcjsid.h"
#include "nsWrapperCacheInlines.h"

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

@ -48,6 +48,7 @@ class nsFormData;
class nsIJARChannel;
class nsILoadGroup;
class nsIUnicodeDecoder;
class nsIJSID;
namespace mozilla {

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

@ -5,4 +5,5 @@
MOCHITEST_FILES = \
test_webgl_conformance.html \
test_webgl_request_mismatch.html \
$(NULL)

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

@ -0,0 +1,36 @@
<!DOCTYPE HTML>
<title>WebGL test: Mismatched 'webgl' and 'experimental-webgl' context requests</title>
<script src="/MochiKit/MochiKit.js"></script>
<script src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" href="/tests/SimpleTest/test.css">
<body>
<canvas id="c1"></canvas>
<canvas id="c2"></canvas>
<canvas id="c3"></canvas>
<canvas id="c4"></canvas>
<script>
function testContextRetrieval(canvasId, creationId, requestId) {
var canvas = document.getElementById(canvasId);
ok(canvas, 'Invalid `canvasId`: ' + canvasId);
var createdGL = canvas.getContext(creationId);
if (!createdGL)
return; // No WebGL on this machine?
var requestedGL = canvas.getContext(requestId);
if (creationId == requestId) {
ok(requestedGL, 'Request for \'' + requestId + '\' on from \'' + creationId + '\' should succeed.');
ok(requestedGL == createdGL, 'Request for \'' + requestId + '\' on from \'' + creationId + '\' should match.');
} else {
ok(!requestedGL, 'Request for \'' + requestId + '\' on from \'' + creationId + '\' should fail.');
}
}
testContextRetrieval('c1', 'experimental-webgl', 'webgl');
testContextRetrieval('c2', 'webgl', 'experimental-webgl');
testContextRetrieval('c3', 'experimental-webgl', 'experimental-webgl');
testContextRetrieval('c4', 'webgl', 'webgl');
</script>

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

@ -18,6 +18,7 @@
#include "AudioChannelCommon.h"
#include <algorithm>
#include "mozilla/Preferences.h"
#include "nsComponentManagerUtils.h"
static bool
IsAudioAPIEnabled()

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

@ -671,6 +671,14 @@ HTMLCanvasElement::GetContext(const nsAString& aContextId,
return rv.ErrorCode();
}
static bool
IsContextIdWebGL(const nsAString& str)
{
return str.EqualsLiteral("webgl") ||
str.EqualsLiteral("experimental-webgl") ||
str.EqualsLiteral("moz-webgl");
}
already_AddRefed<nsISupports>
HTMLCanvasElement::GetContext(JSContext* aCx,
const nsAString& aContextId,
@ -702,6 +710,20 @@ HTMLCanvasElement::GetContext(JSContext* aCx,
}
if (!mCurrentContextId.Equals(aContextId)) {
if (IsContextIdWebGL(aContextId) &&
IsContextIdWebGL(mCurrentContextId))
{
// Warn when we get a request for a webgl context with an id that differs
// from the id it was created with.
nsCString creationId = NS_LossyConvertUTF16toASCII(mCurrentContextId);
nsCString requestId = NS_LossyConvertUTF16toASCII(aContextId);
JS_ReportWarning(aCx, "WebGL: Retrieving a WebGL context from a canvas "
"via a request id ('%s') different from the id used "
"to create the context ('%s') is not allowed.",
requestId.get(),
creationId.get());
}
//XXX eventually allow for more than one active context on a given canvas
return nullptr;
}

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

@ -6,6 +6,7 @@
#include "WebVTTLoadListener.h"
#include "mozilla/dom/TextTrackCue.h"
#include "mozilla/dom/HTMLTrackElement.h"
#include "nsIInputStream.h"
namespace mozilla {
namespace dom {

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

@ -11,6 +11,7 @@
#include "SourceBuffer.h"
#include "SourceBufferList.h"
#include "nsContentTypeParser.h"
#include "nsIInputStream.h"
#ifdef PR_LOGGING
PRLogModuleInfo* gMediaSourceLog;

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

@ -18,6 +18,8 @@
#include "nsWrapperCache.h"
#include "nscore.h"
class nsIInputStream;
namespace mozilla {
namespace dom {

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

@ -190,6 +190,7 @@
#include "mozilla/dom/BindingUtils.h"
#include "mozilla/Likely.h"
#include "WindowNamedPropertiesHandler.h"
#include "nsIInterfaceInfoManager.h"
#ifdef MOZ_TIME_MANAGER
#include "TimeManager.h"

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

@ -15,6 +15,7 @@
#include "nsIDocument.h"
#include "nsString.h"
#include "prprf.h"
#include "nsIException.h"
using namespace mozilla;

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

@ -49,6 +49,7 @@
#include "mozilla/dom/EventTarget.h"
#include "Units.h"
#include "nsComponentManagerUtils.h"
#ifdef MOZ_B2G
#include "nsIDOMWindowB2G.h"

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

@ -55,6 +55,7 @@
#include "StructuredCloneTags.h"
#include "mozilla/dom/ImageData.h"
#include "mozilla/dom/ImageDataBinding.h"
#include "nsAXPCNativeCallContext.h"
#include "nsJSPrincipals.h"

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

@ -17,6 +17,7 @@
#include "mozilla/Likely.h"
#include <algorithm>
#include "mozilla/dom/FunctionBinding.h"
#include "nsAXPCNativeCallContext.h"
static const char kSetIntervalStr[] = "setInterval";
static const char kSetTimeoutStr[] = "setTimeout";

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

@ -28,6 +28,7 @@
#include "nsTraceRefcnt.h"
#include "qsObjectHelper.h"
#include "xpcpublic.h"
#include "nsIVariant.h"
#include "nsWrapperCacheInlines.h"

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

@ -23,6 +23,8 @@
#define DEVICESTORAGE_SDCARD "sdcard"
#define DEVICESTORAGE_CRASHES "crashes"
class nsIInputStream;
namespace mozilla {
namespace dom {
class DeviceStorageEnumerationParameters;

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

@ -17,6 +17,7 @@
#include "nsError.h"
#include "nsStringGlue.h"
#include "nsTArray.h"
#include "nsIInputStream.h"
#define BEGIN_INDEXEDDB_NAMESPACE \
namespace mozilla { namespace dom { namespace indexedDB {
@ -28,7 +29,6 @@
using namespace mozilla::dom::indexedDB;
class nsIDOMBlob;
class nsIInputStream;
BEGIN_INDEXEDDB_NAMESPACE

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

@ -8,26 +8,23 @@ interface nsIDOMGeoPositionCallback;
interface nsIDOMGeoPositionErrorCallback;
%{C++
#include "DictionaryHelpers.h"
namespace mozilla {
namespace dom {
class PositionOptions;
}
}
%}
dictionary GeoPositionOptions
{
boolean enableHighAccuracy;
long timeout;
long maximumAge;
};
[ptr] native NamespacedGeoPositionOptions(mozilla::idl::GeoPositionOptions);
[ptr] native NamespacedPositionOptions(mozilla::dom::PositionOptions);
[builtinclass, uuid(1bc7d103-c7ae-4467-881c-21a8dfa17938)]
interface nsIDOMGeoGeolocation : nsISupports
{
int32_t watchPosition(in nsIDOMGeoPositionCallback callback,
in nsIDOMGeoPositionErrorCallback errorCallback,
in NamespacedGeoPositionOptions options);
in NamespacedPositionOptions options);
void getCurrentPosition(in nsIDOMGeoPositionCallback callback,
in nsIDOMGeoPositionErrorCallback errorCallback,
in NamespacedGeoPositionOptions options);
in NamespacedPositionOptions options);
void clearWatch(in long watchId);
};

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

@ -34,6 +34,7 @@
#include "mozilla/dom/bluetooth/PBluetoothParent.h"
#include "mozilla/dom/PFMRadioParent.h"
#include "mozilla/dom/devicestorage/DeviceStorageRequestParent.h"
#include "mozilla/dom/GeolocationBinding.h"
#include "SmsParent.h"
#include "mozilla/Hal.h"
#include "mozilla/hal_sandbox/PHalParent.h"
@ -148,7 +149,6 @@ using namespace mozilla::dom::indexedDB;
using namespace mozilla::dom::power;
using namespace mozilla::dom::mobilemessage;
using namespace mozilla::hal;
using namespace mozilla::idl;
using namespace mozilla::ipc;
using namespace mozilla::layers;
using namespace mozilla::net;
@ -2621,8 +2621,8 @@ AddGeolocationListener(nsIDOMGeoPositionCallback* watcher, bool highAccuracy)
return -1;
}
GeoPositionOptions* options = new GeoPositionOptions();
options->enableHighAccuracy = highAccuracy;
PositionOptions* options = new PositionOptions();
options->mEnableHighAccuracy = highAccuracy;
int32_t retval = 1;
geo->WatchPosition(watcher, nullptr, options, &retval);
return retval;

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

@ -71,13 +71,13 @@ class nsGeolocationRequest
nsGeolocationRequest(Geolocation* aLocator,
const GeoPositionCallback& aCallback,
const GeoPositionErrorCallback& aErrorCallback,
idl::GeoPositionOptions* aOptions,
PositionOptions* aOptions,
bool aWatchPositionRequest = false,
int32_t aWatchId = 0);
void Shutdown();
void SendLocation(nsIDOMGeoPosition* location);
bool WantsHighAccuracy() {return mOptions && mOptions->enableHighAccuracy;}
bool WantsHighAccuracy() {return mOptions && mOptions->mEnableHighAccuracy;}
void SetTimeoutTimer();
nsIPrincipal* GetPrincipal();
@ -94,7 +94,7 @@ class nsGeolocationRequest
nsCOMPtr<nsITimer> mTimeoutTimer;
GeoPositionCallback mCallback;
GeoPositionErrorCallback mErrorCallback;
nsAutoPtr<idl::GeoPositionOptions> mOptions;
nsAutoPtr<PositionOptions> mOptions;
nsRefPtr<Geolocation> mLocator;
@ -102,15 +102,14 @@ class nsGeolocationRequest
bool mShutdown;
};
static idl::GeoPositionOptions*
GeoPositionOptionsFromPositionOptions(const PositionOptions& aOptions)
static PositionOptions*
CreatePositionOptionsCopy(const PositionOptions& aOptions)
{
nsAutoPtr<idl::GeoPositionOptions> geoOptions(
new idl::GeoPositionOptions());
nsAutoPtr<PositionOptions> geoOptions(new PositionOptions());
geoOptions->enableHighAccuracy = aOptions.mEnableHighAccuracy;
geoOptions->maximumAge = aOptions.mMaximumAge;
geoOptions->timeout = aOptions.mTimeout;
geoOptions->mEnableHighAccuracy = aOptions.mEnableHighAccuracy;
geoOptions->mMaximumAge = aOptions.mMaximumAge;
geoOptions->mTimeout = aOptions.mTimeout;
return geoOptions.forget();
}
@ -336,7 +335,7 @@ PositionError::NotifyCallback(const GeoPositionErrorCallback& aCallback)
nsGeolocationRequest::nsGeolocationRequest(Geolocation* aLocator,
const GeoPositionCallback& aCallback,
const GeoPositionErrorCallback& aErrorCallback,
idl::GeoPositionOptions* aOptions,
PositionOptions* aOptions,
bool aWatchPositionRequest,
int32_t aWatchId)
: mIsWatchPositionRequest(aWatchPositionRequest),
@ -460,11 +459,11 @@ nsGeolocationRequest::Allow()
uint32_t maximumAge = 30 * PR_MSEC_PER_SEC;
if (mOptions) {
if (mOptions->maximumAge >= 0) {
maximumAge = mOptions->maximumAge;
if (mOptions->mMaximumAge >= 0) {
maximumAge = mOptions->mMaximumAge;
}
}
gs->SetHigherAccuracy(mOptions && mOptions->enableHighAccuracy);
gs->SetHigherAccuracy(mOptions && mOptions->mEnableHighAccuracy);
bool canUseCache = lastPosition && maximumAge > 0 &&
(PRTime(PR_Now() / PR_USEC_PER_MSEC) - maximumAge <=
@ -497,7 +496,7 @@ nsGeolocationRequest::SetTimeoutTimer()
}
int32_t timeout;
if (mOptions && (timeout = mOptions->timeout) != 0) {
if (mOptions && (timeout = mOptions->mTimeout) != 0) {
if (timeout < 0) {
timeout = 0;
@ -600,7 +599,7 @@ nsGeolocationRequest::Shutdown()
// This should happen last, to ensure that this request isn't taken into consideration
// when deciding whether existing requests still require high accuracy.
if (mOptions && mOptions->enableHighAccuracy) {
if (mOptions && mOptions->mEnableHighAccuracy) {
nsRefPtr<nsGeolocationService> gs = nsGeolocationService::GetGeolocationService();
if (gs) {
gs->SetHigherAccuracy(false);
@ -1200,9 +1199,8 @@ Geolocation::GetCurrentPosition(PositionCallback& aCallback,
GeoPositionCallback successCallback(&aCallback);
GeoPositionErrorCallback errorCallback(aErrorCallback);
nsresult rv =
GetCurrentPosition(successCallback, errorCallback,
GeoPositionOptionsFromPositionOptions(aOptions));
nsresult rv = GetCurrentPosition(successCallback, errorCallback,
CreatePositionOptionsCopy(aOptions));
if (NS_FAILED(rv)) {
aRv.Throw(rv);
@ -1214,7 +1212,7 @@ Geolocation::GetCurrentPosition(PositionCallback& aCallback,
NS_IMETHODIMP
Geolocation::GetCurrentPosition(nsIDOMGeoPositionCallback* aCallback,
nsIDOMGeoPositionErrorCallback* aErrorCallback,
idl::GeoPositionOptions* aOptions)
PositionOptions* aOptions)
{
NS_ENSURE_ARG_POINTER(aCallback);
@ -1227,7 +1225,7 @@ Geolocation::GetCurrentPosition(nsIDOMGeoPositionCallback* aCallback,
nsresult
Geolocation::GetCurrentPosition(GeoPositionCallback& callback,
GeoPositionErrorCallback& errorCallback,
idl::GeoPositionOptions *options)
PositionOptions *options)
{
if (mPendingCallbacks.Length() > MAX_GEO_REQUESTS_PER_WINDOW) {
return NS_ERROR_NOT_AVAILABLE;
@ -1289,9 +1287,8 @@ Geolocation::WatchPosition(PositionCallback& aCallback,
GeoPositionCallback successCallback(&aCallback);
GeoPositionErrorCallback errorCallback(aErrorCallback);
nsresult rv =
WatchPosition(successCallback, errorCallback,
GeoPositionOptionsFromPositionOptions(aOptions), &ret);
nsresult rv = WatchPosition(successCallback, errorCallback,
CreatePositionOptionsCopy(aOptions), &ret);
if (NS_FAILED(rv)) {
aRv.Throw(rv);
@ -1303,7 +1300,7 @@ Geolocation::WatchPosition(PositionCallback& aCallback,
NS_IMETHODIMP
Geolocation::WatchPosition(nsIDOMGeoPositionCallback *aCallback,
nsIDOMGeoPositionErrorCallback *aErrorCallback,
idl::GeoPositionOptions *aOptions,
PositionOptions *aOptions,
int32_t* aRv)
{
NS_ENSURE_ARG_POINTER(aCallback);
@ -1317,7 +1314,7 @@ Geolocation::WatchPosition(nsIDOMGeoPositionCallback *aCallback,
nsresult
Geolocation::WatchPosition(GeoPositionCallback& aCallback,
GeoPositionErrorCallback& aErrorCallback,
idl::GeoPositionOptions* aOptions,
PositionOptions* aOptions,
int32_t* aRv)
{
if (mWatchingCallbacks.Length() > MAX_GEO_REQUESTS_PER_WINDOW) {

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

@ -176,8 +176,8 @@ private:
~Geolocation();
nsresult GetCurrentPosition(GeoPositionCallback& aCallback, GeoPositionErrorCallback& aErrorCallback, mozilla::idl::GeoPositionOptions* aOptions);
nsresult WatchPosition(GeoPositionCallback& aCallback, GeoPositionErrorCallback& aErrorCallback, mozilla::idl::GeoPositionOptions* aOptions, int32_t* aRv);
nsresult GetCurrentPosition(GeoPositionCallback& aCallback, GeoPositionErrorCallback& aErrorCallback, PositionOptions* aOptions);
nsresult WatchPosition(GeoPositionCallback& aCallback, GeoPositionErrorCallback& aErrorCallback, PositionOptions* aOptions, int32_t* aRv);
bool RegisterRequestWithPrompt(nsGeolocationRequest* request);

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

@ -30,6 +30,7 @@
#include "DOMBindingInlines.h"
#include "mozilla/Attributes.h"
#include "nsComponentManagerUtils.h"
using namespace mozilla;

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

@ -38,6 +38,7 @@
#include "nsFocusManager.h"
#include "mozilla/Services.h"
#include "mozilla/dom/Element.h"
#include "nsISimpleEnumerator.h"
#if DEBUG
#include "nsIWebNavigation.h"

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

@ -477,10 +477,7 @@ jsd_GetValueProperty(JSDContext* jsdc, JSDValue* jsdval, JSString* nameStr)
JSDProperty* jsdprop;
JSDProperty* iter = NULL;
JS::RootedObject obj(cx);
unsigned attrs = 0;
bool found;
const jschar * nameChars;
size_t nameLen;
JS::RootedValue val(cx), nameval(cx);
JS::RootedId nameid(cx);
JS::RootedValue propId(cx);
@ -504,24 +501,28 @@ jsd_GetValueProperty(JSDContext* jsdc, JSDValue* jsdval, JSString* nameStr)
}
/* Not found in property list, look it up explicitly */
nameval = STRING_TO_JSVAL(name);
if(!JS_ValueToId(cx, nameval, nameid.address()))
return NULL;
if(!(obj = JSVAL_TO_OBJECT(jsdval->val)))
return NULL;
if (!(nameChars = JS_GetStringCharsZAndLength(cx, name, &nameLen)))
return NULL;
JS::Rooted<JSPropertyDescriptor> desc(cx);
{
JSAutoCompartment ac(cx, obj);
JS::RootedId id(cx, nameid);
JS_GetUCPropertyAttributes(cx, obj, nameChars, nameLen, &attrs, &found);
if (!found)
{
if(!JS_WrapId(cx, id.address()))
return NULL;
if(!JS_GetOwnPropertyDescriptorById(cx, obj, id, 0, &desc))
return NULL;
if(!desc.object())
return NULL;
}
JS_ClearPendingException(cx);
if(!JS_GetUCProperty(cx, obj, nameChars, nameLen, &val))
if(!JS_GetPropertyById(cx, obj, id, &val))
{
if (JS_IsExceptionPending(cx))
{
@ -543,16 +544,13 @@ jsd_GetValueProperty(JSDContext* jsdc, JSDValue* jsdval, JSString* nameStr)
}
}
nameval = STRING_TO_JSVAL(name);
if (!JS_ValueToId(cx, nameval, nameid.address()) ||
!JS_IdToValue(cx, nameid, propId.address())) {
if (!JS_IdToValue(cx, nameid, propId.address()))
return NULL;
}
propAlias = JSVAL_NULL;
propFlags |= (attrs & JSPROP_ENUMERATE) ? JSPD_ENUMERATE : 0
| (attrs & JSPROP_READONLY) ? JSPD_READONLY : 0
| (attrs & JSPROP_PERMANENT) ? JSPD_PERMANENT : 0;
propFlags |= desc.isEnumerable() ? JSPD_ENUMERATE : 0
| desc.isReadonly() ? JSPD_READONLY : 0
| desc.isPermanent() ? JSPD_PERMANENT : 0;
return _newProperty(jsdc, propId, propValue, propAlias, propFlags, JSDPD_HINTED);
}

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

@ -373,10 +373,6 @@ typedef bool
(* PropertyAttributesOp)(JSContext *cx, JS::HandleObject obj, JS::Handle<PropertyName*> name,
unsigned *attrsp);
typedef bool
(* ElementAttributesOp)(JSContext *cx, JS::HandleObject obj, uint32_t index, unsigned *attrsp);
typedef bool
(* SpecialAttributesOp)(JSContext *cx, JS::HandleObject obj, HandleSpecialId sid, unsigned *attrsp);
typedef bool
(* DeletePropertyOp)(JSContext *cx, JS::HandleObject obj, JS::Handle<PropertyName*> name,
bool *succeeded);
typedef bool
@ -468,13 +464,7 @@ struct ObjectOps
StrictElementIdOp setElement;
StrictSpecialIdOp setSpecial;
GenericAttributesOp getGenericAttributes;
PropertyAttributesOp getPropertyAttributes;
ElementAttributesOp getElementAttributes;
SpecialAttributesOp getSpecialAttributes;
GenericAttributesOp setGenericAttributes;
PropertyAttributesOp setPropertyAttributes;
ElementAttributesOp setElementAttributes;
SpecialAttributesOp setSpecialAttributes;
DeletePropertyOp deleteProperty;
DeleteElementOp deleteElement;
DeleteSpecialOp deleteSpecial;
@ -485,8 +475,7 @@ struct ObjectOps
#define JS_NULL_OBJECT_OPS \
{NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL, \
NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL, \
NULL,NULL,NULL}
NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL}
} // namespace js

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

@ -1664,13 +1664,7 @@ Class BinaryBlock::class_ = {
BinaryBlock::obj_setElement,
BinaryBlock::obj_setSpecial,
BinaryBlock::obj_getGenericAttributes,
BinaryBlock::obj_getPropertyAttributes,
BinaryBlock::obj_getElementAttributes,
BinaryBlock::obj_getSpecialAttributes,
BinaryBlock::obj_setGenericAttributes,
BinaryBlock::obj_setPropertyAttributes,
BinaryBlock::obj_setElementAttributes,
BinaryBlock::obj_setSpecialAttributes,
BinaryBlock::obj_deleteProperty,
BinaryBlock::obj_deleteElement,
BinaryBlock::obj_deleteSpecial,
@ -2204,33 +2198,6 @@ BinaryBlock::obj_getGenericAttributes(JSContext *cx, HandleObject obj,
return JSObject::getGenericAttributes(cx, proto, id, attrsp);
}
bool
BinaryBlock::obj_getPropertyAttributes(JSContext *cx, HandleObject obj,
HandlePropertyName name,
unsigned *attrsp)
{
RootedId id(cx, NameToId(name));
return obj_getGenericAttributes(cx, obj, id, attrsp);
}
bool
BinaryBlock::obj_getElementAttributes(JSContext *cx, HandleObject obj,
uint32_t index, unsigned *attrsp)
{
RootedId id(cx);
if (!IndexToId(cx, index, &id))
return false;
return obj_getGenericAttributes(cx, obj, id, attrsp);
}
bool
BinaryBlock::obj_getSpecialAttributes(JSContext *cx, HandleObject obj,
HandleSpecialId sid, unsigned *attrsp)
{
RootedId id(cx, SPECIALID_TO_JSID(sid));
return obj_getGenericAttributes(cx, obj, id, attrsp);
}
static bool
IsOwnId(JSContext *cx, HandleObject obj, HandleId id)
{
@ -2270,33 +2237,6 @@ BinaryBlock::obj_setGenericAttributes(JSContext *cx, HandleObject obj,
return JSObject::setGenericAttributes(cx, proto, id, attrsp);
}
bool
BinaryBlock::obj_setPropertyAttributes(JSContext *cx, HandleObject obj,
HandlePropertyName name,
unsigned *attrsp)
{
RootedId id(cx, NameToId(name));
return obj_setGenericAttributes(cx, obj, id, attrsp);
}
bool
BinaryBlock::obj_setElementAttributes(JSContext *cx, HandleObject obj,
uint32_t index, unsigned *attrsp)
{
RootedId id(cx);
if (!IndexToId(cx, index, &id))
return false;
return obj_setGenericAttributes(cx, obj, id, attrsp);
}
bool
BinaryBlock::obj_setSpecialAttributes(JSContext *cx, HandleObject obj,
HandleSpecialId sid, unsigned *attrsp)
{
RootedId id(cx, SPECIALID_TO_JSID(sid));
return obj_setGenericAttributes(cx, obj, id, attrsp);
}
bool
BinaryBlock::obj_deleteProperty(JSContext *cx, HandleObject obj,
HandlePropertyName name, bool *succeeded)

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

@ -181,21 +181,8 @@ class BinaryBlock
static bool obj_getGenericAttributes(JSContext *cx, HandleObject obj,
HandleId id, unsigned *attrsp);
static bool obj_getPropertyAttributes(JSContext *cx, HandleObject obj,
HandlePropertyName name, unsigned *attrsp);
static bool obj_getElementAttributes(JSContext *cx, HandleObject obj,
uint32_t index, unsigned *attrsp);
static bool obj_getSpecialAttributes(JSContext *cx, HandleObject obj,
HandleSpecialId sid, unsigned *attrsp);
static bool obj_setGenericAttributes(JSContext *cx, HandleObject obj,
HandleId id, unsigned *attrsp);
static bool obj_setPropertyAttributes(JSContext *cx, HandleObject obj,
HandlePropertyName name, unsigned *attrsp);
static bool obj_setElementAttributes(JSContext *cx, HandleObject obj,
uint32_t index, unsigned *attrsp);
static bool obj_setSpecialAttributes(JSContext *cx, HandleObject obj,
HandleSpecialId sid, unsigned *attrsp);
static bool obj_deleteProperty(JSContext *cx, HandleObject obj, HandlePropertyName name,
bool *succeeded);

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

@ -1652,6 +1652,11 @@ IonCompile(JSContext *cx, JSScript *script,
IonSpewNewFunction(graph, builderScript);
if (!builder->build()) {
if (cx->isExceptionPending()) {
IonSpew(IonSpew_Abort, "Builder raised exception.");
return AbortReason_Error;
}
IonSpew(IonSpew_Abort, "Builder failed to build.");
return builder->abortReason();
}
@ -1832,6 +1837,9 @@ Compile(JSContext *cx, HandleScript script, BaselineFrame *osrFrame, jsbytecode
}
AbortReason reason = IonCompile(cx, script, osrFrame, osrPc, constructing, executionMode);
if (reason == AbortReason_Error)
return Method_Error;
if (reason == AbortReason_Disable)
return Method_CantCompile;

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

@ -255,6 +255,7 @@ enum AbortReason {
AbortReason_Alloc,
AbortReason_Inlining,
AbortReason_Disable,
AbortReason_Error,
AbortReason_NoAbort
};

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

@ -3772,14 +3772,23 @@ IonBuilder::inlineScriptedCall(CallInfo &callInfo, JSFunction *target)
AutoAccumulateExits aae(graph(), saveExits);
// Build the graph.
JS_ASSERT(!cx->isExceptionPending());
IonBuilder inlineBuilder(cx, &temp(), &graph(), &inspector, info, NULL,
inliningDepth_ + 1, loopDepth_);
if (!inlineBuilder.buildInline(this, outerResumePoint, callInfo)) {
JS_ASSERT(calleeScript->hasAnalysis());
if (cx->isExceptionPending()) {
IonSpew(IonSpew_Abort, "Inline builder raised exception.");
abortReason_ = AbortReason_Error;
return false;
}
// Inlining the callee failed. Disable inlining the function
if (inlineBuilder.abortReason_ == AbortReason_Disable)
if (inlineBuilder.abortReason_ == AbortReason_Disable) {
// Only mark callee as un-inlineable only if the inlining was aborted
// for a non-exception reason.
calleeScript->analysis()->setIonUninlineable();
}
abortReason_ = AbortReason_Inlining;
return false;
@ -5565,9 +5574,20 @@ IonBuilder::jsop_initprop(HandlePropertyName name)
if (!res)
return false;
if (!shape || holder != templateObject ||
PropertyWriteNeedsTypeBarrier(cx, current, &obj, name, &value))
if (!shape || holder != templateObject) {
// JSOP_NEWINIT becomes an MNewObject without preconfigured properties.
MInitProp *init = MInitProp::New(obj, name, value);
current->add(init);
return resumeAfter(init);
}
bool writeNeedsBarrier = false;
if (!PropertyWriteNeedsTypeBarrier(cx, current, &obj, name, &value, /* canModify = */ true,
&writeNeedsBarrier))
{
return false;
}
if (writeNeedsBarrier) {
// JSOP_NEWINIT becomes an MNewObject without preconfigured properties.
MInitProp *init = MInitProp::New(obj, name, value);
current->add(init);
@ -6267,7 +6287,12 @@ IonBuilder::getStaticName(HandleObject staticObject, HandlePropertyName name, bo
}
types::StackTypeSet *types = types::TypeScript::BytecodeTypes(script(), pc);
bool barrier = PropertyReadNeedsTypeBarrier(cx, staticType, name, types);
bool barrier;
if (!PropertyReadNeedsTypeBarrier(cx, staticType, name, types, /* updateObserved = */ true,
&barrier))
{
return false;
}
// If the property is permanent, a shape guard isn't necessary.
@ -6791,7 +6816,9 @@ IonBuilder::getElemTryCache(bool *emitted, MDefinition *obj, MDefinition *index)
// Emit GetElementCache.
types::StackTypeSet *types = types::TypeScript::BytecodeTypes(script(), pc);
bool barrier = PropertyReadNeedsTypeBarrier(cx, obj, NULL, types);
bool barrier;
if (!PropertyReadNeedsTypeBarrier(cx, obj, NULL, types, &barrier))
return false;
// Always add a barrier if the index might be a string, so that the cache
// can attach stubs for particular properties.
@ -6835,10 +6862,14 @@ IonBuilder::jsop_getelem_dense(MDefinition *obj, MDefinition *index)
// Indexed call on an element of an array. Populate the observed types
// with any objects that could be in the array, to avoid extraneous
// type barriers.
AddObjectsForPropertyRead(cx, obj, NULL, types);
if (!AddObjectsForPropertyRead(cx, obj, NULL, types))
return false;
}
bool barrier = PropertyReadNeedsTypeBarrier(cx, obj, NULL, types);
bool barrier;
if (!PropertyReadNeedsTypeBarrier(cx, obj, NULL, types, &barrier))
return false;
bool needsHoleCheck = !ElementAccessIsPacked(cx, obj);
// Reads which are on holes in the object do not have to bail out if
@ -7203,7 +7234,13 @@ IonBuilder::setElemTryDense(bool *emitted, MDefinition *object,
if (!ElementAccessIsDenseNative(object, index))
return true;
if (PropertyWriteNeedsTypeBarrier(cx, current, &object, NULL, &value))
bool needsBarrier;
if (!PropertyWriteNeedsTypeBarrier(cx, current, &object, NULL, &value, /* canModify = */ true,
&needsBarrier))
{
return false;
}
if (needsBarrier)
return true;
if (!object->resultTypeSet())
return true;
@ -7263,7 +7300,14 @@ IonBuilder::setElemTryCache(bool *emitted, MDefinition *object,
if (!icInspect.sawDenseWrite())
return true;
if (PropertyWriteNeedsTypeBarrier(cx, current, &object, NULL, &value))
bool needsBarrier;
if (PropertyWriteNeedsTypeBarrier(cx, current, &object, NULL, &value, /* canModify = */ true,
&needsBarrier))
{
return false;
}
if (needsBarrier)
return true;
// Emit SetElementCache.
@ -7283,7 +7327,10 @@ IonBuilder::jsop_setelem_dense(types::StackTypeSet::DoubleConversion conversion,
SetElemSafety safety,
MDefinition *obj, MDefinition *id, MDefinition *value)
{
MIRType elementType = DenseNativeElementType(cx, obj);
MIRType elementType;
if (!DenseNativeElementType(cx, obj, &elementType))
return false;
bool packed = ElementAccessIsPacked(cx, obj);
// Writes which are on holes in the object do not have to bail out if they
@ -8100,7 +8147,9 @@ IonBuilder::jsop_getprop(HandlePropertyName name)
if (!getPropTryArgumentsLength(&emitted) || emitted)
return emitted;
bool barrier = PropertyReadNeedsTypeBarrier(cx, current->peek(-1), name, types);
bool barrier;
if (!PropertyReadNeedsTypeBarrier(cx, current->peek(-1), name, types, &barrier))
return false;
// Try to hardcode known constants.
if (!getPropTryConstant(&emitted, id, types) || emitted)
@ -8405,7 +8454,11 @@ IonBuilder::getPropTryCache(bool *emitted, HandlePropertyName name, HandleId id,
if (obj->type() == MIRType_Object && !invalidatedIdempotentCache() &&
info().executionMode() != ParallelExecution)
{
if (PropertyReadIsIdempotent(cx, obj, name))
bool idempotent;
if (!PropertyReadIsIdempotent(cx, obj, name, &idempotent))
return false;
if (idempotent)
load->setIdempotent();
}
@ -8480,7 +8533,12 @@ IonBuilder::jsop_setprop(HandlePropertyName name)
return emitted;
types::StackTypeSet *objTypes = obj->resultTypeSet();
bool barrier = PropertyWriteNeedsTypeBarrier(cx, current, &obj, name, &value);
bool barrier;
if (!PropertyWriteNeedsTypeBarrier(cx, current, &obj, name, &value,
/* canModify = */ true, &barrier))
{
return false;
}
// Try to emit store from definite slots.
if (!setPropTryDefiniteSlot(&emitted, obj, name, value, barrier, objTypes) || emitted)

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

@ -323,7 +323,10 @@ IonBuilder::inlineArrayPopShift(CallInfo &callInfo, MArrayPopShift::Mode mode)
bool needsHoleCheck = thisTypes->hasObjectFlags(cx, types::OBJECT_FLAG_NON_PACKED);
bool maybeUndefined = returnTypes->hasType(types::Type::UndefinedType());
bool barrier = PropertyReadNeedsTypeBarrier(cx, callInfo.thisArg(), NULL, returnTypes);
bool barrier;
if (!PropertyReadNeedsTypeBarrier(cx, callInfo.thisArg(), NULL, returnTypes, &barrier))
return InliningStatus_Error;
if (barrier)
returnType = MIRType_Value;
@ -350,7 +353,13 @@ IonBuilder::inlineArrayPush(CallInfo &callInfo)
MDefinition *obj = callInfo.thisArg();
MDefinition *value = callInfo.getArg(0);
if (PropertyWriteNeedsTypeBarrier(cx, current, &obj, NULL, &value, /* canModify = */ false))
bool writeNeedsBarrier;
if (!PropertyWriteNeedsTypeBarrier(cx, current, &obj, NULL, &value, /* canModify = */ false,
&writeNeedsBarrier))
{
return InliningStatus_Error;
}
if (writeNeedsBarrier)
return InliningStatus_NotInlined;
JS_ASSERT(obj == callInfo.thisArg() && value == callInfo.getArg(0));
@ -1002,12 +1011,22 @@ IonBuilder::inlineUnsafePutElements(CallInfo &callInfo)
MDefinition *id = callInfo.getArg(idxi);
MDefinition *elem = callInfo.getArg(elemi);
bool isDenseNative = ElementAccessIsDenseNative(obj, id);
bool writeNeedsBarrier = false;
if (isDenseNative) {
if (!PropertyWriteNeedsTypeBarrier(cx, current, &obj, NULL, &elem,
/* canModify = */ false,
&writeNeedsBarrier))
{
return InliningStatus_Error;
}
}
// We can only inline setelem on dense arrays that do not need type
// barriers and on typed arrays.
ScalarTypeRepresentation::Type arrayType;
if ((!ElementAccessIsDenseNative(obj, id) ||
PropertyWriteNeedsTypeBarrier(cx, current, &obj, NULL,
&elem, /* canModify = */ false)) &&
if ((!isDenseNative || writeNeedsBarrier) &&
!ElementAccessIsTypedArray(obj, id, &arrayType))
{
return InliningStatus_NotInlined;

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

@ -2530,48 +2530,61 @@ jit::ElementAccessHasExtraIndexedProperty(JSContext *cx, MDefinition *obj)
return types::TypeCanHaveExtraIndexedProperties(cx, types);
}
MIRType
jit::DenseNativeElementType(JSContext *cx, MDefinition *obj)
bool
jit::DenseNativeElementType(JSContext *cx, MDefinition *obj, MIRType *result)
{
JS_ASSERT(result);
*result = MIRType_None;
types::StackTypeSet *types = obj->resultTypeSet();
MIRType elementType = MIRType_None;
unsigned count = types->getObjectCount();
for (unsigned i = 0; i < count; i++) {
if (types::TypeObject *object = types->getTypeOrSingleObject(cx, i)) {
types::TypeObject *object;
if (!types->getTypeOrSingleObject(cx, i, &object))
return false;
if (!object)
continue;
if (object->unknownProperties())
return MIRType_None;
return true;
types::HeapTypeSet *elementTypes = object->getProperty(cx, JSID_VOID, false);
if (!elementTypes)
return MIRType_None;
return true;
MIRType type = MIRTypeFromValueType(elementTypes->getKnownTypeTag(cx));
if (type == MIRType_None)
return MIRType_None;
return true;
if (elementType == MIRType_None)
elementType = type;
else if (elementType != type)
return MIRType_None;
}
return true;
}
return elementType;
*result = elementType;
return true;
}
bool
jit::PropertyReadNeedsTypeBarrier(JSContext *cx, types::TypeObject *object, PropertyName *name,
types::StackTypeSet *observed, bool updateObserved)
types::StackTypeSet *observed, bool updateObserved, bool *result)
{
// If the object being read from has types for the property which haven't
// been observed at this access site, the read could produce a new type and
// a barrier is needed. Note that this only covers reads from properties
// which are accounted for by type information, i.e. native data properties
// and elements.
JS_ASSERT(result);
*result = false;
if (object->unknownProperties())
if (object->unknownProperties()) {
*result = true;
return true;
}
jsid id = name ? types::IdToTypeId(NameToId(name)) : JSID_VOID;
@ -2596,8 +2609,10 @@ jit::PropertyReadNeedsTypeBarrier(JSContext *cx, types::TypeObject *object, Prop
}
types::HeapTypeSet *property = object->getProperty(cx, id, false);
if (!property)
if (!property) {
*result = true;
return true;
}
// We need to consider possible types for the property both as an 'own'
// property on the object and as inherited from any prototype. Type sets
@ -2606,8 +2621,10 @@ jit::PropertyReadNeedsTypeBarrier(JSContext *cx, types::TypeObject *object, Prop
if (!property->hasPropagatedProperty())
object->getFromPrototypes(cx, id, property);
if (!TypeSetIncludes(observed, MIRType_Value, property))
if (!TypeSetIncludes(observed, MIRType_Value, property)) {
*result = true;
return true;
}
// Type information for singleton objects is not required to reflect the
// initial 'undefined' value for native properties, in particular global
@ -2619,62 +2636,85 @@ jit::PropertyReadNeedsTypeBarrier(JSContext *cx, types::TypeObject *object, Prop
shape->hasDefaultGetter() &&
object->singleton->nativeGetSlot(shape->slot()).isUndefined())
{
*result = true;
return true;
}
}
property->addFreeze(cx);
return false;
*result = false;
return true;
}
bool
jit::PropertyReadNeedsTypeBarrier(JSContext *cx, MDefinition *obj, PropertyName *name,
types::StackTypeSet *observed)
types::StackTypeSet *observed, bool *result)
{
JS_ASSERT(result);
*result = false;
if (observed->unknown())
return false;
return true;
types::TypeSet *types = obj->resultTypeSet();
if (!types || types->unknownObject())
if (!types || types->unknownObject()) {
*result = true;
return true;
}
bool updateObserved = types->getObjectCount() == 1;
for (size_t i = 0; i < types->getObjectCount(); i++) {
types::TypeObject *object = types->getTypeOrSingleObject(cx, i);
if (object && PropertyReadNeedsTypeBarrier(cx, object, name, observed, updateObserved))
types::TypeObject *object;
if (!types->getTypeOrSingleObject(cx, i, &object))
return false;
if (object) {
if (!PropertyReadNeedsTypeBarrier(cx, object, name, observed, updateObserved, result))
return false;
if (*result)
return true;
}
}
*result = false;
return true;
}
return false;
}
bool
jit::PropertyReadIsIdempotent(JSContext *cx, MDefinition *obj, PropertyName *name)
jit::PropertyReadIsIdempotent(JSContext *cx, MDefinition *obj, PropertyName *name, bool *result)
{
JS_ASSERT(result);
*result = false;
// Determine if reading a property from obj is likely to be idempotent.
jsid id = types::IdToTypeId(NameToId(name));
types::TypeSet *types = obj->resultTypeSet();
if (!types || types->unknownObject())
return false;
return true;
for (size_t i = 0; i < types->getObjectCount(); i++) {
if (types::TypeObject *object = types->getTypeOrSingleObject(cx, i)) {
if (object->unknownProperties())
types::TypeObject *object;
if (!types->getTypeOrSingleObject(cx, i, &object))
return false;
if (object) {
if (object->unknownProperties())
return true;
// Check if the property has been reconfigured or is a getter.
types::HeapTypeSet *property = object->getProperty(cx, id, false);
if (!property || property->isOwnProperty(cx, object, true))
return false;
return true;
}
}
*result = true;
return true;
}
void
bool
jit::AddObjectsForPropertyRead(JSContext *cx, MDefinition *obj, PropertyName *name,
types::StackTypeSet *observed)
{
@ -2686,25 +2726,28 @@ jit::AddObjectsForPropertyRead(JSContext *cx, MDefinition *obj, PropertyName *na
types::StackTypeSet *types = obj->resultTypeSet();
if (!types || types->unknownObject()) {
observed->addType(cx, types::Type::AnyObjectType());
return;
return true;
}
jsid id = name ? types::IdToTypeId(NameToId(name)) : JSID_VOID;
for (size_t i = 0; i < types->getObjectCount(); i++) {
types::TypeObject *object = types->getTypeOrSingleObject(cx, i);
types::TypeObject *object;
if (!types->getTypeOrSingleObject(cx, i, &object))
return false;
if (!object)
continue;
if (object->unknownProperties()) {
observed->addType(cx, types::Type::AnyObjectType());
return;
return true;
}
types::HeapTypeSet *property = object->getProperty(cx, id, false);
if (property->unknownObject()) {
observed->addType(cx, types::Type::AnyObjectType());
return;
return true;
}
for (size_t i = 0; i < property->getObjectCount(); i++) {
@ -2714,6 +2757,8 @@ jit::AddObjectsForPropertyRead(JSContext *cx, MDefinition *obj, PropertyName *na
observed->addType(cx, types::Type::ObjectType(object));
}
}
return true;
}
static bool
@ -2730,7 +2775,10 @@ TryAddTypeBarrierForWrite(JSContext *cx, MBasicBlock *current, types::StackTypeS
types::HeapTypeSet *aggregateProperty = NULL;
for (size_t i = 0; i < objTypes->getObjectCount(); i++) {
types::TypeObject *object = objTypes->getTypeOrSingleObject(cx, i);
types::TypeObject *object;
if (!objTypes->getTypeOrSingleObject(cx, i, &object))
return false;
if (!object)
continue;
@ -2808,8 +2856,12 @@ AddTypeGuard(MBasicBlock *current, MDefinition *obj, types::TypeObject *typeObje
bool
jit::PropertyWriteNeedsTypeBarrier(JSContext *cx, MBasicBlock *current, MDefinition **pobj,
PropertyName *name, MDefinition **pvalue, bool canModify)
PropertyName *name, MDefinition **pvalue, bool canModify,
bool *result)
{
JS_ASSERT(result);
*result = false;
// If any value being written is not reflected in the type information for
// objects which obj could represent, a type barrier is needed when writing
// the value. As for propertyReadNeedsTypeBarrier, this only applies for
@ -2817,8 +2869,10 @@ jit::PropertyWriteNeedsTypeBarrier(JSContext *cx, MBasicBlock *current, MDefinit
// properties and elements.
types::StackTypeSet *types = (*pobj)->resultTypeSet();
if (!types || types->unknownObject())
if (!types || types->unknownObject()) {
*result = true;
return true;
}
jsid id = name ? types::IdToTypeId(NameToId(name)) : JSID_VOID;
@ -2829,7 +2883,10 @@ jit::PropertyWriteNeedsTypeBarrier(JSContext *cx, MBasicBlock *current, MDefinit
bool success = true;
for (size_t i = 0; i < types->getObjectCount(); i++) {
types::TypeObject *object = types->getTypeOrSingleObject(cx, i);
types::TypeObject *object;
if (!types->getTypeOrSingleObject(cx, i, &object))
return false;
if (!object || object->unknownProperties())
continue;
@ -2843,43 +2900,54 @@ jit::PropertyWriteNeedsTypeBarrier(JSContext *cx, MBasicBlock *current, MDefinit
// types which the value could have but are not in the property,
// or a VM call is required. A VM call is always required if pobj
// and pvalue cannot be modified.
if (!canModify)
if (!canModify) {
*result = true;
return true;
}
success = TryAddTypeBarrierForWrite(cx, current, types, id, pvalue);
break;
}
}
if (success)
return false;
return true;
// If all of the objects except one have property types which reflect the
// value, and the remaining object has no types at all for the property,
// add a guard that the object does not have that remaining object's type.
if (types->getObjectCount() <= 1)
if (types->getObjectCount() <= 1) {
*result = true;
return true;
}
types::TypeObject *excluded = NULL;
for (size_t i = 0; i < types->getObjectCount(); i++) {
types::TypeObject *object = types->getTypeOrSingleObject(cx, i);
types::TypeObject *object;
if (!types->getTypeOrSingleObject(cx, i, &object))
return false;
if (!object || object->unknownProperties())
continue;
types::HeapTypeSet *property = object->getProperty(cx, id, false);
if (!property)
if (!property) {
*result = true;
return true;
}
if (TypeSetIncludes(property, (*pvalue)->type(), (*pvalue)->resultTypeSet()))
continue;
if (!property->empty() || excluded)
if (!property->empty() || excluded) {
*result = true;
return true;
}
excluded = object;
}
JS_ASSERT(excluded);
*pobj = AddTypeGuard(current, *pobj, excluded, /* bailOnEquality = */ true);
return false;
return true;
}

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

@ -8510,17 +8510,17 @@ bool ElementAccessIsTypedArray(MDefinition *obj, MDefinition *id,
ScalarTypeRepresentation::Type *arrayType);
bool ElementAccessIsPacked(JSContext *cx, MDefinition *obj);
bool ElementAccessHasExtraIndexedProperty(JSContext *cx, MDefinition *obj);
MIRType DenseNativeElementType(JSContext *cx, MDefinition *obj);
bool DenseNativeElementType(JSContext *cx, MDefinition *obj, MIRType *result);
bool PropertyReadNeedsTypeBarrier(JSContext *cx, types::TypeObject *object, PropertyName *name,
types::StackTypeSet *observed, bool updateObserved = true);
types::StackTypeSet *observed, bool updateObserved, bool *result);
bool PropertyReadNeedsTypeBarrier(JSContext *cx, MDefinition *obj, PropertyName *name,
types::StackTypeSet *observed);
bool PropertyReadIsIdempotent(JSContext *cx, MDefinition *obj, PropertyName *name);
void AddObjectsForPropertyRead(JSContext *cx, MDefinition *obj, PropertyName *name,
types::StackTypeSet *observed, bool *result);
bool PropertyReadIsIdempotent(JSContext *cx, MDefinition *obj, PropertyName *name, bool *result);
bool AddObjectsForPropertyRead(JSContext *cx, MDefinition *obj, PropertyName *name,
types::StackTypeSet *observed);
bool PropertyWriteNeedsTypeBarrier(JSContext *cx, MBasicBlock *current, MDefinition **pobj,
PropertyName *name, MDefinition **pvalue,
bool canModify = true);
bool canModify, bool *result);
} // namespace jit
} // namespace js

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

@ -45,14 +45,13 @@ BEGIN_TEST(testDefineGetterSetterNonEnumerable)
JS_DATA_TO_FUNC_PTR(JSStrictPropertyOp, (JSObject*) funSetObj),
JSPROP_GETTER | JSPROP_SETTER | JSPROP_PERMANENT));
bool found = false;
unsigned attrs = 0;
CHECK(JS_GetPropertyAttributes(cx, vObject, PROPERTY_NAME, &attrs, &found));
CHECK(found);
CHECK(attrs & JSPROP_GETTER);
CHECK(attrs & JSPROP_SETTER);
CHECK(attrs & JSPROP_PERMANENT);
CHECK(!(attrs & JSPROP_ENUMERATE));
JS::Rooted<JSPropertyDescriptor> desc(cx);
CHECK(JS_GetOwnPropertyDescriptor(cx, vObject, PROPERTY_NAME, 0, &desc));
CHECK(desc.object());
CHECK(desc.hasGetterObject());
CHECK(desc.hasSetterObject());
CHECK(desc.isPermanent());
CHECK(!desc.isEnumerable());
return true;
}

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

@ -3633,6 +3633,27 @@ GetPropertyDescriptorById(JSContext *cx, HandleObject obj, HandleId id, unsigned
return true;
}
JS_PUBLIC_API(bool)
JS_GetOwnPropertyDescriptorById(JSContext *cx, JSObject *objArg, jsid idArg, unsigned flags,
MutableHandle<JSPropertyDescriptor> desc)
{
RootedObject obj(cx, objArg);
RootedId id(cx, idArg);
AssertHeapIsIdle(cx);
CHECK_REQUEST(cx);
return GetPropertyDescriptorById(cx, obj, id, flags, true, desc);
}
JS_PUBLIC_API(bool)
JS_GetOwnPropertyDescriptor(JSContext *cx, JSObject *objArg, const char *name, unsigned flags,
MutableHandle<JSPropertyDescriptor> desc)
{
RootedObject obj(cx, objArg);
JSAtom *atom = Atomize(cx, name, strlen(name));
return atom && JS_GetOwnPropertyDescriptorById(cx, obj, AtomToId(atom), flags, desc);
}
JS_PUBLIC_API(bool)
JS_GetPropertyDescriptorById(JSContext *cx, JSObject *objArg, jsid idArg, unsigned flags,
MutableHandle<JSPropertyDescriptor> desc)
@ -3643,117 +3664,12 @@ JS_GetPropertyDescriptorById(JSContext *cx, JSObject *objArg, jsid idArg, unsign
}
JS_PUBLIC_API(bool)
JS_GetPropertyAttrsGetterAndSetterById(JSContext *cx, JSObject *objArg, jsid idArg,
unsigned *attrsp, bool *foundp,
JSPropertyOp *getterp, JSStrictPropertyOp *setterp)
{
RootedObject obj(cx, objArg);
RootedId id(cx, idArg);
Rooted<PropertyDescriptor> desc(cx);
if (!GetPropertyDescriptorById(cx, obj, id, 0, false, &desc))
return false;
*attrsp = desc.attributes();
*foundp = !!desc.object();
if (getterp)
*getterp = desc.getter();
if (setterp)
*setterp = desc.setter();
return true;
}
JS_PUBLIC_API(bool)
JS_GetPropertyAttributes(JSContext *cx, JSObject *objArg, const char *name,
unsigned *attrsp, bool *foundp)
JS_GetPropertyDescriptor(JSContext *cx, JSObject *objArg, const char *name, unsigned flags,
MutableHandle<JSPropertyDescriptor> desc)
{
RootedObject obj(cx, objArg);
JSAtom *atom = Atomize(cx, name, strlen(name));
return atom && JS_GetPropertyAttrsGetterAndSetterById(cx, obj, AtomToId(atom),
attrsp, foundp, NULL, NULL);
}
JS_PUBLIC_API(bool)
JS_GetUCPropertyAttributes(JSContext *cx, JSObject *objArg, const jschar *name, size_t namelen,
unsigned *attrsp, bool *foundp)
{
RootedObject obj(cx, objArg);
JSAtom *atom = AtomizeChars<CanGC>(cx, name, AUTO_NAMELEN(name, namelen));
return atom && JS_GetPropertyAttrsGetterAndSetterById(cx, obj, AtomToId(atom),
attrsp, foundp, NULL, NULL);
}
JS_PUBLIC_API(bool)
JS_GetPropertyAttrsGetterAndSetter(JSContext *cx, JSObject *objArg, const char *name,
unsigned *attrsp, bool *foundp,
JSPropertyOp *getterp, JSStrictPropertyOp *setterp)
{
RootedObject obj(cx, objArg);
JSAtom *atom = Atomize(cx, name, strlen(name));
return atom && JS_GetPropertyAttrsGetterAndSetterById(cx, obj, AtomToId(atom),
attrsp, foundp, getterp, setterp);
}
JS_PUBLIC_API(bool)
JS_GetUCPropertyAttrsGetterAndSetter(JSContext *cx, JSObject *objArg,
const jschar *name, size_t namelen,
unsigned *attrsp, bool *foundp,
JSPropertyOp *getterp, JSStrictPropertyOp *setterp)
{
RootedObject obj(cx, objArg);
JSAtom *atom = AtomizeChars<CanGC>(cx, name, AUTO_NAMELEN(name, namelen));
return atom && JS_GetPropertyAttrsGetterAndSetterById(cx, obj, AtomToId(atom),
attrsp, foundp, getterp, setterp);
}
JS_PUBLIC_API(bool)
JS_GetOwnPropertyDescriptor(JSContext *cx, JSObject *objArg, jsid idArg, MutableHandleValue vp)
{
RootedObject obj(cx, objArg);
RootedId id(cx, idArg);
AssertHeapIsIdle(cx);
CHECK_REQUEST(cx);
return GetOwnPropertyDescriptor(cx, obj, id, vp);
}
static bool
SetPropertyAttributesById(JSContext *cx, HandleObject obj, HandleId id, unsigned attrs, bool *foundp)
{
RootedObject obj2(cx);
RootedShape shape(cx);
if (!LookupPropertyById(cx, obj, id, 0, &obj2, &shape))
return false;
if (!shape || obj != obj2) {
*foundp = false;
return true;
}
bool ok = obj->isNative()
? JSObject::changePropertyAttributes(cx, obj, shape, attrs)
: JSObject::setGenericAttributes(cx, obj, id, &attrs);
if (ok)
*foundp = true;
return ok;
}
JS_PUBLIC_API(bool)
JS_SetPropertyAttributes(JSContext *cx, JSObject *objArg, const char *name,
unsigned attrs, bool *foundp)
{
RootedObject obj(cx, objArg);
JSAtom *atom = Atomize(cx, name, strlen(name));
RootedId id(cx, AtomToId(atom));
return atom && SetPropertyAttributesById(cx, obj, id, attrs, foundp);
}
JS_PUBLIC_API(bool)
JS_SetUCPropertyAttributes(JSContext *cx, JSObject *objArg, const jschar *name, size_t namelen,
unsigned attrs, bool *foundp)
{
RootedObject obj(cx, objArg);
JSAtom *atom = AtomizeChars<CanGC>(cx, name, AUTO_NAMELEN(name, namelen));
RootedId id(cx, AtomToId(atom));
return atom && SetPropertyAttributesById(cx, obj, id, attrs, foundp);
return atom && JS_GetPropertyDescriptorById(cx, obj, AtomToId(atom), flags, desc);
}
JS_PUBLIC_API(bool)
@ -6664,4 +6580,3 @@ JS_PreventExtensions(JSContext *cx, JS::HandleObject obj)
return true;
return JSObject::preventExtensions(cx, obj);
}

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

@ -2791,45 +2791,6 @@ JS_DefinePropertyById(JSContext *cx, JSObject *obj, jsid id, jsval value,
extern JS_PUBLIC_API(bool)
JS_DefineOwnProperty(JSContext *cx, JSObject *obj, jsid id, jsval descriptor, bool *bp);
/*
* Determine the attributes (JSPROP_* flags) of a property on a given object.
*
* If the object does not have a property by that name, *foundp will be
* false and the value of *attrsp is undefined.
*/
extern JS_PUBLIC_API(bool)
JS_GetPropertyAttributes(JSContext *cx, JSObject *obj, const char *name,
unsigned *attrsp, bool *foundp);
/*
* The same, but if the property is native, return its getter and setter via
* *getterp and *setterp, respectively (and only if the out parameter pointer
* is not null).
*/
extern JS_PUBLIC_API(bool)
JS_GetPropertyAttrsGetterAndSetter(JSContext *cx, JSObject *obj,
const char *name,
unsigned *attrsp, bool *foundp,
JSPropertyOp *getterp,
JSStrictPropertyOp *setterp);
extern JS_PUBLIC_API(bool)
JS_GetPropertyAttrsGetterAndSetterById(JSContext *cx, JSObject *obj,
jsid id,
unsigned *attrsp, bool *foundp,
JSPropertyOp *getterp,
JSStrictPropertyOp *setterp);
/*
* Set the attributes of a property on a given object.
*
* If the object does not have a property by that name, *foundp will be
* false and nothing will be altered.
*/
extern JS_PUBLIC_API(bool)
JS_SetPropertyAttributes(JSContext *cx, JSObject *obj, const char *name,
unsigned attrs, bool *foundp);
extern JS_PUBLIC_API(bool)
JS_DefinePropertyWithTinyId(JSContext *cx, JSObject *obj, const char *name,
int8_t tinyid, jsval value,
@ -3013,9 +2974,17 @@ class MutableHandleBase<JSPropertyDescriptor>
} /* namespace js */
extern JS_PUBLIC_API(bool)
JS_GetOwnPropertyDescriptorById(JSContext *cx, JSObject *objArg, jsid id, unsigned flags,
JS::MutableHandle<JSPropertyDescriptor> desc);
extern JS_PUBLIC_API(bool)
JS_GetOwnPropertyDescriptor(JSContext *cx, JSObject *objArg, const char *name, unsigned flags,
JS::MutableHandle<JSPropertyDescriptor> desc);
/*
* Like JS_GetPropertyAttrsGetterAndSetterById but will return a property on
* an object on the prototype chain (returned in objp). If data->obj is null,
* Like JS_GetOwnPropertyDescriptorById but will return a property on
* an object on the prototype chain (returned in desc->obj). If desc->obj is null,
* then this property was not found on the prototype chain.
*/
extern JS_PUBLIC_API(bool)
@ -3023,7 +2992,8 @@ JS_GetPropertyDescriptorById(JSContext *cx, JSObject *obj, jsid id, unsigned fla
JS::MutableHandle<JSPropertyDescriptor> desc);
extern JS_PUBLIC_API(bool)
JS_GetOwnPropertyDescriptor(JSContext *cx, JSObject *obj, jsid id, JS::MutableHandle<JS::Value> vp);
JS_GetPropertyDescriptor(JSContext *cx, JSObject *obj, const char *name, unsigned flags,
JS::MutableHandle<JSPropertyDescriptor> desc);
extern JS_PUBLIC_API(bool)
JS_GetProperty(JSContext *cx, JSObject *obj, const char *name, JS::MutableHandle<JS::Value> vp);
@ -3067,41 +3037,6 @@ JS_DefineUCProperty(JSContext *cx, JSObject *obj,
JSPropertyOp getter, JSStrictPropertyOp setter,
unsigned attrs);
/*
* Determine the attributes (JSPROP_* flags) of a property on a given object.
*
* If the object does not have a property by that name, *foundp will be
* false and the value of *attrsp is undefined.
*/
extern JS_PUBLIC_API(bool)
JS_GetUCPropertyAttributes(JSContext *cx, JSObject *obj,
const jschar *name, size_t namelen,
unsigned *attrsp, bool *foundp);
/*
* The same, but if the property is native, return its getter and setter via
* *getterp and *setterp, respectively (and only if the out parameter pointer
* is not null).
*/
extern JS_PUBLIC_API(bool)
JS_GetUCPropertyAttrsGetterAndSetter(JSContext *cx, JSObject *obj,
const jschar *name, size_t namelen,
unsigned *attrsp, bool *foundp,
JSPropertyOp *getterp,
JSStrictPropertyOp *setterp);
/*
* Set the attributes of a property on a given object.
*
* If the object does not have a property by that name, *foundp will be
* false and nothing will be altered.
*/
extern JS_PUBLIC_API(bool)
JS_SetUCPropertyAttributes(JSContext *cx, JSObject *obj,
const jschar *name, size_t namelen,
unsigned attrs, bool *foundp);
extern JS_PUBLIC_API(bool)
JS_DefineUCPropertyWithTinyId(JSContext *cx, JSObject *obj,
const jschar *name, size_t namelen,

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

@ -511,7 +511,7 @@ class TypeSet
inline TypeObjectKey *getObject(unsigned i) const;
inline JSObject *getSingleObject(unsigned i) const;
inline TypeObject *getTypeObject(unsigned i) const;
inline TypeObject *getTypeOrSingleObject(JSContext *cx, unsigned i) const;
inline bool getTypeOrSingleObject(JSContext *cx, unsigned i, TypeObject **obj) const;
void setOwnProperty(bool configurable) {
flags |= TYPE_FLAG_OWN_PROPERTY;

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

@ -1407,20 +1407,28 @@ TypeSet::getTypeObject(unsigned i) const
return (key && !(uintptr_t(key) & 1)) ? (TypeObject *) key : NULL;
}
inline TypeObject *
TypeSet::getTypeOrSingleObject(JSContext *cx, unsigned i) const
inline bool
TypeSet::getTypeOrSingleObject(JSContext *cx, unsigned i, TypeObject **result) const
{
JS_ASSERT(result);
JS_ASSERT(cx->compartment()->activeAnalysis);
*result = NULL;
TypeObject *type = getTypeObject(i);
if (!type) {
JSObject *singleton = getSingleObject(i);
if (!singleton)
return NULL;
return true;
type = singleton->uninlinedGetType(cx);
if (!type)
if (!type) {
cx->compartment()->types.setPendingNukeTypes(cx);
return false;
}
return type;
}
*result = type;
return true;
}
/////////////////////////////////////////////////////////////////////

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

@ -4775,24 +4775,6 @@ baseops::GetAttributes(JSContext *cx, HandleObject obj, HandleId id, unsigned *a
return true;
}
bool
baseops::GetElementAttributes(JSContext *cx, HandleObject obj, uint32_t index, unsigned *attrsp)
{
RootedObject nobj(cx);
RootedShape shape(cx);
if (!baseops::LookupElement(cx, obj, index, &nobj, &shape))
return false;
if (!shape) {
*attrsp = 0;
return true;
}
if (!nobj->isNative())
return JSObject::getElementAttributes(cx, nobj, index, attrsp);
*attrsp = GetShapeAttributes(shape);
return true;
}
bool
baseops::SetAttributes(JSContext *cx, HandleObject obj, HandleId id, unsigned *attrsp)
{
@ -4812,26 +4794,6 @@ baseops::SetAttributes(JSContext *cx, HandleObject obj, HandleId id, unsigned *a
: JSObject::setGenericAttributes(cx, nobj, id, attrsp);
}
bool
baseops::SetElementAttributes(JSContext *cx, HandleObject obj, uint32_t index, unsigned *attrsp)
{
RootedObject nobj(cx);
RootedShape shape(cx);
if (!baseops::LookupElement(cx, obj, index, &nobj, &shape))
return false;
if (!shape)
return true;
if (nobj->isNative() && IsImplicitDenseElement(shape)) {
if (!JSObject::sparsifyDenseElement(cx, obj, index))
return false;
jsid id = INT_TO_JSID(index);
shape = obj->nativeLookup(cx, HandleId::fromMarkedLocation(&id)); // not a gcthing
}
return nobj->isNative()
? JSObject::changePropertyAttributes(cx, nobj, shape, *attrsp)
: JSObject::setElementAttributes(cx, nobj, index, attrsp);
}
bool
baseops::DeleteGeneric(JSContext *cx, HandleObject obj, HandleId id, bool *succeeded)
{

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

@ -143,12 +143,6 @@ GetAttributes(JSContext *cx, HandleObject obj, HandleId id, unsigned *attrsp);
extern bool
SetAttributes(JSContext *cx, HandleObject obj, HandleId id, unsigned *attrsp);
extern bool
GetElementAttributes(JSContext *cx, HandleObject obj, uint32_t index, unsigned *attrsp);
extern bool
SetElementAttributes(JSContext *cx, HandleObject obj, uint32_t index, unsigned *attrsp);
extern bool
DeleteProperty(JSContext *cx, HandleObject obj, HandlePropertyName name, bool *succeeded);
@ -881,31 +875,8 @@ class JSObject : public js::ObjectImpl
return (op ? op : js::baseops::GetAttributes)(cx, obj, id, attrsp);
}
static bool getPropertyAttributes(JSContext *cx, js::HandleObject obj,
js::PropertyName *name, unsigned *attrsp)
{
JS::RootedId id(cx, js::NameToId(name));
return getGenericAttributes(cx, obj, id, attrsp);
}
static inline bool getElementAttributes(JSContext *cx, js::HandleObject obj,
uint32_t index, unsigned *attrsp);
static bool getSpecialAttributes(JSContext *cx, js::HandleObject obj,
js::SpecialId sid, unsigned *attrsp)
{
JS::RootedId id(cx, SPECIALID_TO_JSID(sid));
return getGenericAttributes(cx, obj, id, attrsp);
}
static inline bool setGenericAttributes(JSContext *cx, js::HandleObject obj,
js::HandleId id, unsigned *attrsp);
static inline bool setPropertyAttributes(JSContext *cx, js::HandleObject obj,
js::PropertyName *name, unsigned *attrsp);
static inline bool setElementAttributes(JSContext *cx, js::HandleObject obj,
uint32_t index, unsigned *attrsp);
static inline bool setSpecialAttributes(JSContext *cx, js::HandleObject obj,
js::SpecialId sid, unsigned *attrsp);
static inline bool deleteProperty(JSContext *cx, js::HandleObject obj,
js::HandlePropertyName name,

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

@ -31,30 +31,6 @@ JSObject::setGenericAttributes(JSContext *cx, js::HandleObject obj,
return (op ? op : js::baseops::SetAttributes)(cx, obj, id, attrsp);
}
/* static */ inline bool
JSObject::setPropertyAttributes(JSContext *cx, js::HandleObject obj,
js::PropertyName *name, unsigned *attrsp)
{
JS::RootedId id(cx, js::NameToId(name));
return setGenericAttributes(cx, obj, id, attrsp);
}
/* static */ inline bool
JSObject::setElementAttributes(JSContext *cx, js::HandleObject obj,
uint32_t index, unsigned *attrsp)
{
js::ElementAttributesOp op = obj->getOps()->setElementAttributes;
return (op ? op : js::baseops::SetElementAttributes)(cx, obj, index, attrsp);
}
/* static */ inline bool
JSObject::setSpecialAttributes(JSContext *cx, js::HandleObject obj,
js::SpecialId sid, unsigned *attrsp)
{
JS::RootedId id(cx, SPECIALID_TO_JSID(sid));
return setGenericAttributes(cx, obj, id, attrsp);
}
/* static */ inline bool
JSObject::changePropertyAttributes(JSContext *cx, js::HandleObject obj,
js::HandleShape shape, unsigned attrs)
@ -747,16 +723,6 @@ JSObject::getElementIfPresent(JSContext *cx, js::HandleObject obj, js::HandleObj
return getGeneric(cx, obj, receiver, id, vp);
}
/* static */ inline bool
JSObject::getElementAttributes(JSContext *cx, js::HandleObject obj,
uint32_t index, unsigned *attrsp)
{
JS::RootedId id(cx);
if (!js::IndexToId(cx, index, &id))
return false;
return getGenericAttributes(cx, obj, id, attrsp);
}
inline js::GlobalObject &
JSObject::global() const
{

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

@ -2892,29 +2892,6 @@ proxy_GetGenericAttributes(JSContext *cx, HandleObject obj, HandleId id, unsigne
return true;
}
static bool
proxy_GetPropertyAttributes(JSContext *cx, HandleObject obj, HandlePropertyName name, unsigned *attrsp)
{
Rooted<jsid> id(cx, NameToId(name));
return proxy_GetGenericAttributes(cx, obj, id, attrsp);
}
static bool
proxy_GetElementAttributes(JSContext *cx, HandleObject obj, uint32_t index, unsigned *attrsp)
{
RootedId id(cx);
if (!IndexToId(cx, index, &id))
return false;
return proxy_GetGenericAttributes(cx, obj, id, attrsp);
}
static bool
proxy_GetSpecialAttributes(JSContext *cx, HandleObject obj, HandleSpecialId sid, unsigned *attrsp)
{
Rooted<jsid> id(cx, SPECIALID_TO_JSID(sid));
return proxy_GetGenericAttributes(cx, obj, id, attrsp);
}
static bool
proxy_SetGenericAttributes(JSContext *cx, HandleObject obj, HandleId id, unsigned *attrsp)
{
@ -2926,29 +2903,6 @@ proxy_SetGenericAttributes(JSContext *cx, HandleObject obj, HandleId id, unsigne
return Proxy::defineProperty(cx, obj, id, &desc);
}
static bool
proxy_SetPropertyAttributes(JSContext *cx, HandleObject obj, HandlePropertyName name, unsigned *attrsp)
{
Rooted<jsid> id(cx, NameToId(name));
return proxy_SetGenericAttributes(cx, obj, id, attrsp);
}
static bool
proxy_SetElementAttributes(JSContext *cx, HandleObject obj, uint32_t index, unsigned *attrsp)
{
RootedId id(cx);
if (!IndexToId(cx, index, &id))
return false;
return proxy_SetGenericAttributes(cx, obj, id, attrsp);
}
static bool
proxy_SetSpecialAttributes(JSContext *cx, HandleObject obj, HandleSpecialId sid, unsigned *attrsp)
{
Rooted<jsid> id(cx, SPECIALID_TO_JSID(sid));
return proxy_SetGenericAttributes(cx, obj, id, attrsp);
}
static bool
proxy_DeleteGeneric(JSContext *cx, HandleObject obj, HandleId id, bool *succeeded)
{
@ -3103,13 +3057,7 @@ Class js::ObjectProxyObject::class_ = {
proxy_SetElement,
proxy_SetSpecial,
proxy_GetGenericAttributes,
proxy_GetPropertyAttributes,
proxy_GetElementAttributes,
proxy_GetSpecialAttributes,
proxy_SetGenericAttributes,
proxy_SetPropertyAttributes,
proxy_SetElementAttributes,
proxy_SetSpecialAttributes,
proxy_DeleteProperty,
proxy_DeleteElement,
proxy_DeleteSpecial,
@ -3162,13 +3110,7 @@ Class js::OuterWindowProxyObject::class_ = {
proxy_SetElement,
proxy_SetSpecial,
proxy_GetGenericAttributes,
proxy_GetPropertyAttributes,
proxy_GetElementAttributes,
proxy_GetSpecialAttributes,
proxy_SetGenericAttributes,
proxy_SetPropertyAttributes,
proxy_SetElementAttributes,
proxy_SetSpecialAttributes,
proxy_DeleteProperty,
proxy_DeleteElement,
proxy_DeleteSpecial,
@ -3233,13 +3175,7 @@ Class js::FunctionProxyObject::class_ = {
proxy_SetElement,
proxy_SetSpecial,
proxy_GetGenericAttributes,
proxy_GetPropertyAttributes,
proxy_GetElementAttributes,
proxy_GetSpecialAttributes,
proxy_SetGenericAttributes,
proxy_SetPropertyAttributes,
proxy_SetElementAttributes,
proxy_SetSpecialAttributes,
proxy_DeleteProperty,
proxy_DeleteElement,
proxy_DeleteSpecial,

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

@ -275,15 +275,16 @@ DefVarOrConstOperation(JSContext *cx, HandleObject varobj, HandlePropertyName dn
JS_StrictPropertyStub, attrs)) {
return false;
}
} else {
} else if (attrs & JSPROP_READONLY) {
/*
* Extension: ordinarily we'd be done here -- but for |const|. If we
* see a redeclaration that's |const|, we consider it a conflict.
*/
unsigned oldAttrs;
if (!JSObject::getPropertyAttributes(cx, varobj, dn, &oldAttrs))
RootedId id(cx, NameToId(dn));
if (!JSObject::getGenericAttributes(cx, varobj, id, &oldAttrs))
return false;
if (attrs & JSPROP_READONLY) {
JSAutoByteString bytes;
if (AtomToPrintableString(cx, dn, &bytes)) {
JS_ALWAYS_FALSE(JS_ReportErrorFlagsAndNumber(cx, JSREPORT_ERROR,
@ -296,7 +297,6 @@ DefVarOrConstOperation(JSContext *cx, HandleObject varobj, HandlePropertyName dn
}
return false;
}
}
return true;
}

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

@ -511,27 +511,6 @@ with_GetGenericAttributes(JSContext *cx, HandleObject obj, HandleId id, unsigned
return JSObject::getGenericAttributes(cx, actual, id, attrsp);
}
static bool
with_GetPropertyAttributes(JSContext *cx, HandleObject obj, HandlePropertyName name, unsigned *attrsp)
{
RootedObject actual(cx, &obj->as<WithObject>().object());
return JSObject::getPropertyAttributes(cx, actual, name, attrsp);
}
static bool
with_GetElementAttributes(JSContext *cx, HandleObject obj, uint32_t index, unsigned *attrsp)
{
RootedObject actual(cx, &obj->as<WithObject>().object());
return JSObject::getElementAttributes(cx, actual, index, attrsp);
}
static bool
with_GetSpecialAttributes(JSContext *cx, HandleObject obj, HandleSpecialId sid, unsigned *attrsp)
{
RootedObject actual(cx, &obj->as<WithObject>().object());
return JSObject::getSpecialAttributes(cx, actual, sid, attrsp);
}
static bool
with_SetGenericAttributes(JSContext *cx, HandleObject obj, HandleId id, unsigned *attrsp)
{
@ -539,27 +518,6 @@ with_SetGenericAttributes(JSContext *cx, HandleObject obj, HandleId id, unsigned
return JSObject::setGenericAttributes(cx, actual, id, attrsp);
}
static bool
with_SetPropertyAttributes(JSContext *cx, HandleObject obj, HandlePropertyName name, unsigned *attrsp)
{
RootedObject actual(cx, &obj->as<WithObject>().object());
return JSObject::setPropertyAttributes(cx, actual, name, attrsp);
}
static bool
with_SetElementAttributes(JSContext *cx, HandleObject obj, uint32_t index, unsigned *attrsp)
{
RootedObject actual(cx, &obj->as<WithObject>().object());
return JSObject::setElementAttributes(cx, actual, index, attrsp);
}
static bool
with_SetSpecialAttributes(JSContext *cx, HandleObject obj, HandleSpecialId sid, unsigned *attrsp)
{
RootedObject actual(cx, &obj->as<WithObject>().object());
return JSObject::setSpecialAttributes(cx, actual, sid, attrsp);
}
static bool
with_DeleteProperty(JSContext *cx, HandleObject obj, HandlePropertyName name,
bool *succeeded)
@ -635,13 +593,7 @@ Class WithObject::class_ = {
with_SetElement,
with_SetSpecial,
with_GetGenericAttributes,
with_GetPropertyAttributes,
with_GetElementAttributes,
with_GetSpecialAttributes,
with_SetGenericAttributes,
with_SetPropertyAttributes,
with_SetElementAttributes,
with_SetSpecialAttributes,
with_DeleteProperty,
with_DeleteElement,
with_DeleteSpecial,
@ -1408,7 +1360,7 @@ class DebugScopeProxy : public BaseProxyHandler
return true;
}
return JS_GetPropertyDescriptorById(cx, scope, id, 0, desc);
return JS_GetOwnPropertyDescriptorById(cx, scope, id, flags, desc);
}
bool get(JSContext *cx, HandleObject proxy, HandleObject receiver, HandleId id,

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

@ -1020,32 +1020,6 @@ ArrayBufferObject::obj_getGenericAttributes(JSContext *cx, HandleObject obj,
return baseops::GetAttributes(cx, delegate, id, attrsp);
}
bool
ArrayBufferObject::obj_getPropertyAttributes(JSContext *cx, HandleObject obj,
HandlePropertyName name, unsigned *attrsp)
{
Rooted<jsid> id(cx, NameToId(name));
return obj_getGenericAttributes(cx, obj, id, attrsp);
}
bool
ArrayBufferObject::obj_getElementAttributes(JSContext *cx, HandleObject obj,
uint32_t index, unsigned *attrsp)
{
RootedObject delegate(cx, ArrayBufferDelegate(cx, obj));
if (!delegate)
return false;
return baseops::GetElementAttributes(cx, delegate, index, attrsp);
}
bool
ArrayBufferObject::obj_getSpecialAttributes(JSContext *cx, HandleObject obj,
HandleSpecialId sid, unsigned *attrsp)
{
Rooted<jsid> id(cx, SPECIALID_TO_JSID(sid));
return obj_getGenericAttributes(cx, obj, id, attrsp);
}
bool
ArrayBufferObject::obj_setGenericAttributes(JSContext *cx, HandleObject obj,
HandleId id, unsigned *attrsp)
@ -1056,32 +1030,6 @@ ArrayBufferObject::obj_setGenericAttributes(JSContext *cx, HandleObject obj,
return baseops::SetAttributes(cx, delegate, id, attrsp);
}
bool
ArrayBufferObject::obj_setPropertyAttributes(JSContext *cx, HandleObject obj,
HandlePropertyName name, unsigned *attrsp)
{
Rooted<jsid> id(cx, NameToId(name));
return obj_setGenericAttributes(cx, obj, id, attrsp);
}
bool
ArrayBufferObject::obj_setElementAttributes(JSContext *cx, HandleObject obj,
uint32_t index, unsigned *attrsp)
{
RootedObject delegate(cx, ArrayBufferDelegate(cx, obj));
if (!delegate)
return false;
return baseops::SetElementAttributes(cx, delegate, index, attrsp);
}
bool
ArrayBufferObject::obj_setSpecialAttributes(JSContext *cx, HandleObject obj,
HandleSpecialId sid, unsigned *attrsp)
{
Rooted<jsid> id(cx, SPECIALID_TO_JSID(sid));
return obj_setGenericAttributes(cx, obj, id, attrsp);
}
bool
ArrayBufferObject::obj_deleteProperty(JSContext *cx, HandleObject obj, HandlePropertyName name,
bool *succeeded)
@ -1231,30 +1179,6 @@ TypedArrayObject::obj_getGenericAttributes(JSContext *cx, HandleObject obj, Hand
return true;
}
bool
TypedArrayObject::obj_getPropertyAttributes(JSContext *cx, HandleObject obj,
HandlePropertyName name, unsigned *attrsp)
{
*attrsp = JSPROP_PERMANENT | JSPROP_ENUMERATE;
return true;
}
bool
TypedArrayObject::obj_getElementAttributes(JSContext *cx, HandleObject obj, uint32_t index,
unsigned *attrsp)
{
*attrsp = JSPROP_PERMANENT | JSPROP_ENUMERATE;
return true;
}
bool
TypedArrayObject::obj_getSpecialAttributes(JSContext *cx, HandleObject obj, HandleSpecialId sid,
unsigned *attrsp)
{
Rooted<jsid> id(cx, SPECIALID_TO_JSID(sid));
return obj_getGenericAttributes(cx, obj, id, attrsp);
}
bool
TypedArrayObject::obj_setGenericAttributes(JSContext *cx, HandleObject obj, HandleId id,
unsigned *attrsp)
@ -1263,30 +1187,6 @@ TypedArrayObject::obj_setGenericAttributes(JSContext *cx, HandleObject obj, Hand
return false;
}
bool
TypedArrayObject::obj_setPropertyAttributes(JSContext *cx, HandleObject obj,
HandlePropertyName name, unsigned *attrsp)
{
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CANT_SET_ARRAY_ATTRS);
return false;
}
bool
TypedArrayObject::obj_setElementAttributes(JSContext *cx, HandleObject obj, uint32_t index,
unsigned *attrsp)
{
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CANT_SET_ARRAY_ATTRS);
return false;
}
bool
TypedArrayObject::obj_setSpecialAttributes(JSContext *cx, HandleObject obj, HandleSpecialId sid,
unsigned *attrsp)
{
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CANT_SET_ARRAY_ATTRS);
return false;
}
/* static */ int
TypedArrayObject::lengthOffset()
{
@ -3494,13 +3394,7 @@ Class ArrayBufferObject::class_ = {
ArrayBufferObject::obj_setElement,
ArrayBufferObject::obj_setSpecial,
ArrayBufferObject::obj_getGenericAttributes,
ArrayBufferObject::obj_getPropertyAttributes,
ArrayBufferObject::obj_getElementAttributes,
ArrayBufferObject::obj_getSpecialAttributes,
ArrayBufferObject::obj_setGenericAttributes,
ArrayBufferObject::obj_setPropertyAttributes,
ArrayBufferObject::obj_setElementAttributes,
ArrayBufferObject::obj_setSpecialAttributes,
ArrayBufferObject::obj_deleteProperty,
ArrayBufferObject::obj_deleteElement,
ArrayBufferObject::obj_deleteSpecial,
@ -3662,13 +3556,7 @@ IMPL_TYPED_ARRAY_COMBINED_UNWRAPPERS(Float64, double, double)
_typedArray##Object::obj_setElement, \
_typedArray##Object::obj_setSpecial, \
_typedArray##Object::obj_getGenericAttributes, \
_typedArray##Object::obj_getPropertyAttributes, \
_typedArray##Object::obj_getElementAttributes, \
_typedArray##Object::obj_getSpecialAttributes, \
_typedArray##Object::obj_setGenericAttributes, \
_typedArray##Object::obj_setPropertyAttributes, \
_typedArray##Object::obj_setElementAttributes, \
_typedArray##Object::obj_setSpecialAttributes, \
_typedArray##Object::obj_deleteProperty, \
_typedArray##Object::obj_deleteElement, \
_typedArray##Object::obj_deleteSpecial, \

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

@ -124,21 +124,8 @@ class ArrayBufferObject : public JSObject
static bool obj_getGenericAttributes(JSContext *cx, HandleObject obj,
HandleId id, unsigned *attrsp);
static bool obj_getPropertyAttributes(JSContext *cx, HandleObject obj,
HandlePropertyName name, unsigned *attrsp);
static bool obj_getElementAttributes(JSContext *cx, HandleObject obj,
uint32_t index, unsigned *attrsp);
static bool obj_getSpecialAttributes(JSContext *cx, HandleObject obj,
HandleSpecialId sid, unsigned *attrsp);
static bool obj_setGenericAttributes(JSContext *cx, HandleObject obj,
HandleId id, unsigned *attrsp);
static bool obj_setPropertyAttributes(JSContext *cx, HandleObject obj,
HandlePropertyName name, unsigned *attrsp);
static bool obj_setElementAttributes(JSContext *cx, HandleObject obj,
uint32_t index, unsigned *attrsp);
static bool obj_setSpecialAttributes(JSContext *cx, HandleObject obj,
HandleSpecialId sid, unsigned *attrsp);
static bool obj_deleteProperty(JSContext *cx, HandleObject obj, HandlePropertyName name,
bool *succeeded);
@ -295,21 +282,8 @@ class TypedArrayObject : public ArrayBufferViewObject
static bool obj_getGenericAttributes(JSContext *cx, HandleObject obj,
HandleId id, unsigned *attrsp);
static bool obj_getPropertyAttributes(JSContext *cx, HandleObject obj,
HandlePropertyName name, unsigned *attrsp);
static bool obj_getElementAttributes(JSContext *cx, HandleObject obj,
uint32_t index, unsigned *attrsp);
static bool obj_getSpecialAttributes(JSContext *cx, HandleObject obj,
HandleSpecialId sid, unsigned *attrsp);
static bool obj_setGenericAttributes(JSContext *cx, HandleObject obj,
HandleId id, unsigned *attrsp);
static bool obj_setPropertyAttributes(JSContext *cx, HandleObject obj,
HandlePropertyName name, unsigned *attrsp);
static bool obj_setElementAttributes(JSContext *cx, HandleObject obj,
uint32_t index, unsigned *attrsp);
static bool obj_setSpecialAttributes(JSContext *cx, HandleObject obj,
HandleSpecialId sid, unsigned *attrsp);
static Value bufferValue(TypedArrayObject *tarr) {
return tarr->getFixedSlot(BUFFER_SLOT);

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

@ -6,6 +6,7 @@
#include "nsISupports.idl"
#include "nsIXPConnect.idl"
#include "nsIClassInfo.idl"
%{C++
#ifdef XP_WIN

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

@ -7,26 +7,15 @@
/* The core XPConnect public interfaces. */
#include "nsISupports.idl"
#include "nsIClassInfo.idl"
#include "xpccomponents.idl"
#include "xpcjsid.idl"
#include "xpcexception.idl"
#include "nsIInterfaceInfo.idl"
#include "nsIInterfaceInfoManager.idl"
#include "nsIExceptionService.idl"
#include "nsIVariant.idl"
#include "nsIObjectOutputStream.idl"
#include "nsIObjectInputStream.idl"
%{ C++
#include "jspubtd.h"
#include "js/TypeDecls.h"
#include "xptinfo.h"
#include "nsAXPCNativeCallContext.h"
struct JSFreeOp;
class nsWrapperCache;
class nsAXPCNativeCallContext;
%}
/***************************************************************************/
@ -58,6 +47,11 @@ interface nsIXPConnectWrappedNative;
interface nsIInterfaceInfo;
interface nsIXPCSecurityManager;
interface nsIPrincipal;
interface nsIClassInfo;
interface nsIVariant;
interface nsIStackFrame;
interface nsIObjectInputStream;
interface nsIObjectOutputStream;
/***************************************************************************/
[uuid(909e8641-7c54-4dff-9b94-ba631f057b33)]

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

@ -1676,6 +1676,11 @@ main(int argc, char **argv, char **envp)
return 1;
}
// Force the SafeJSContext to be created. This is a workaround for our
// implicit dependency on keeping at least one JSContext alive until the
// end of shutdown. This can go away when we get bug 905926 landed.
xpc->GetSafeJSContext();
nsCOMPtr<nsIPrincipal> systemprincipal;
// Fetch the system principal and store it away in a global, to use for
// script compilation in Load() and ProcessFile() (including interactive

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

@ -1170,14 +1170,13 @@ XPCConvert::JSValToXPCException(MutableHandleValue s,
}
unsigned ignored;
bool found;
// heuristic to see if it might be usable as an xpcexception
if (!JS_GetPropertyAttributes(cx, obj, "message", &ignored, &found))
if (!JS_HasProperty(cx, obj, "message", &found))
return NS_ERROR_FAILURE;
if (found && !JS_GetPropertyAttributes(cx, obj, "result", &ignored, &found))
if (found && !JS_HasProperty(cx, obj, "result", &found))
return NS_ERROR_FAILURE;
if (found) {

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

@ -125,7 +125,7 @@ SafeFinalize(JSFreeOp *fop, JSObject* obj)
DestroyProtoAndIfaceCache(obj);
}
static JSClass global_class = {
JSClass xpc::SafeJSContextGlobalClass = {
"global_for_XPCJSContextStack_SafeJSContext",
XPCONNECT_GLOBAL_FLAGS,
JS_PropertyStub, JS_DeletePropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
@ -161,7 +161,7 @@ XPCJSContextStack::GetSafeJSContext()
JS::CompartmentOptions options;
options.setZone(JS::SystemZone);
glob = xpc::CreateGlobalObject(mSafeJSContext, &global_class, principal, options);
glob = xpc::CreateGlobalObject(mSafeJSContext, &SafeJSContextGlobalClass, principal, options);
if (!glob)
MOZ_CRASH();

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

@ -735,13 +735,7 @@ XPCWrappedNativeJSClass XPC_WN_NoHelper_JSClass = {
nullptr, // setElement
nullptr, // setSpecial
nullptr, // getGenericAttributes
nullptr, // getAttributes
nullptr, // getElementAttributes
nullptr, // getSpecialAttributes
nullptr, // setGenericAttributes
nullptr, // setAttributes
nullptr, // setElementAttributes
nullptr, // setSpecialAttributes
nullptr, // deleteProperty
nullptr, // deleteElement
nullptr, // deleteSpecial

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

@ -18,6 +18,7 @@
using namespace mozilla;
using namespace xpc;
using namespace JS;
/***************************************************************************/
@ -97,17 +98,24 @@ XPCWrappedNativeScope::GetNewOrUsed(JSContext *cx, JS::HandleObject aGlobal)
}
static bool
RemoteXULForbidsXBLScope(nsIPrincipal *aPrincipal)
RemoteXULForbidsXBLScope(nsIPrincipal *aPrincipal, HandleObject aGlobal)
{
// We end up getting called during SSM bootstrapping to create the
// SafeJSContext. In that case, nsContentUtils isn't ready for us.
//
// Also check for random JSD scopes that don't have a principal.
if (!nsContentUtils::IsInitialized() || !aPrincipal)
// Check for random JSD scopes that don't have a principal.
if (!aPrincipal)
return false;
// The SafeJSContext is lazily created, and tends to be created at really
// weird times, at least for xpcshell (often very early in startup or late
// in shutdown). Its scope isn't system principal, so if we proceeded we'd
// end up calling into AllowXULXBLForPrincipal, which depends on all kinds
// of persistent storage and permission machinery that may or not be running.
// We know the answer to the question here, so just short-circuit.
if (JS_GetClass(aGlobal) == &SafeJSContextGlobalClass)
return false;
// AllowXULXBLForPrincipal will return true for system principal, but we
// don't want that here.
MOZ_ASSERT(nsContentUtils::IsInitialized());
if (nsContentUtils::IsSystemPrincipal(aPrincipal))
return false;
@ -161,7 +169,7 @@ XPCWrappedNativeScope::XPCWrappedNativeScope(JSContext *cx,
// In addition to being pref-controlled, we also disable XBL scopes for
// remote XUL domains, _except_ if we have an additional pref override set.
nsIPrincipal *principal = GetPrincipal();
mAllowXBLScope = !RemoteXULForbidsXBLScope(principal);
mAllowXBLScope = !RemoteXULForbidsXBLScope(principal, aGlobal);
// Determine whether to use an XBL scope.
mUseXBLScope = mAllowXBLScope;

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

@ -4,7 +4,6 @@
# Dictionary interface name, interface file name
dictionaries = [
[ 'GeoPositionOptions', 'nsIDOMGeoGeolocation.idl' ],
[ 'DOMFileMetadataParameters', 'nsIDOMLockedFile.idl' ],
[ 'CameraSize', 'nsIDOMCameraManager.idl' ],
[ 'CameraRegion', 'nsIDOMCameraManager.idl' ],

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

@ -53,6 +53,8 @@
#include "nsICycleCollectorListener.h"
#include "nsThread.h"
#include "mozilla/XPTInterfaceInfoManager.h"
#include "nsIObjectInputStream.h"
#include "nsIObjectOutputStream.h"
using namespace mozilla;
using namespace mozilla::dom;

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

@ -97,7 +97,6 @@
#include "nsXPCOM.h"
#include "nsAutoPtr.h"
#include "nsCycleCollectionParticipant.h"
#include "mozilla/CycleCollectedJSRuntime.h"
#include "nsDebug.h"
#include "nsISupports.h"
#include "nsIServiceManager.h"
@ -160,6 +159,7 @@
#include "SandboxPrivate.h"
#include "BackstagePass.h"
#include "nsCxPusher.h"
#include "nsAXPCNativeCallContext.h"
#ifdef XP_WIN
// Nasty MS defines
@ -1203,13 +1203,7 @@ XPC_WN_JSOp_ThisObject(JSContext *cx, JS::HandleObject obj);
nullptr, /* setElement */ \
nullptr, /* setSpecial */ \
nullptr, /* getGenericAttributes */ \
nullptr, /* getAttributes */ \
nullptr, /* getElementAttributes */ \
nullptr, /* getSpecialAttributes */ \
nullptr, /* setGenericAttributes */ \
nullptr, /* setAttributes */ \
nullptr, /* setElementAttributes */ \
nullptr, /* setSpecialAttributes */ \
nullptr, /* deleteProperty */ \
nullptr, /* deleteElement */ \
nullptr, /* deleteSpecial */ \
@ -1237,13 +1231,7 @@ XPC_WN_JSOp_ThisObject(JSContext *cx, JS::HandleObject obj);
nullptr, /* setElement */ \
nullptr, /* setSpecial */ \
nullptr, /* getGenericAttributes */ \
nullptr, /* getAttributes */ \
nullptr, /* getElementAttributes */ \
nullptr, /* getSpecialAttributes */ \
nullptr, /* setGenericAttributes */ \
nullptr, /* setAttributes */ \
nullptr, /* setElementAttributes */ \
nullptr, /* setSpecialAttributes */ \
nullptr, /* deleteProperty */ \
nullptr, /* deleteElement */ \
nullptr, /* deleteSpecial */ \
@ -3869,6 +3857,8 @@ GetObjectScope(JSObject *obj)
extern bool gDebugMode;
extern bool gDesiredDebugMode;
extern JSClass SafeJSContextGlobalClass;
JSObject* NewOutObject(JSContext* cx, JSObject* scope);
bool IsOutObject(JSContext* cx, JSObject* obj);

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

@ -1168,7 +1168,6 @@ nsRefreshDriver::Tick(int64_t aNowEpoch, TimeStamp aNowTime)
for (uint32_t i = 0; i < imagesToRefresh.Length(); i++) {
imagesToRefresh[i]->RequestRefresh(aNowTime);
}
imagesToRefresh.Clear();
}
for (uint32_t i = 0; i < mPresShellsToInvalidateIfHidden.Length(); i++) {

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

@ -3,7 +3,7 @@ test-pref(layout.css.sticky.enabled,true) == pref-1.html pref-1-enabled-ref.html
default-preferences pref(layout.css.sticky.enabled,true)
== top-1.html top-1-ref.html
fuzzy-if(Android,4,914) == top-2.html top-2-ref.html
fuzzy-if(Android,6,914) == top-2.html top-2-ref.html
fuzzy-if(Android,4,2729) == top-3.html top-3-ref.html
== top-4.html top-4-ref.html
== top-5.html top-5-ref.html

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

@ -40,6 +40,7 @@
#include "nsDOMClassInfoID.h"
#include "mozilla/Likely.h"
#include "mozilla/dom/CSSStyleSheetBinding.h"
#include "nsComponentManagerUtils.h"
using namespace mozilla;
using namespace mozilla::dom;

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

@ -23,6 +23,7 @@
#include "nsISupportsPrimitives.h"
#include "nsSupportsPrimitives.h"
#include "mozilla/dom/Element.h"
#include "nsComponentManagerUtils.h"
using namespace mozilla::dom;

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

@ -18,6 +18,7 @@
#include "nsAsyncDOMEvent.h"
#include "nsEventDispatcher.h"
#include "nsAutoPtr.h"
#include "nsComponentManagerUtils.h"
// A helper class for managing our ranges of selection.
struct nsTreeRange

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

@ -69,11 +69,13 @@ int VcmSIPCCBinding::gAudioCodecMask = 0;
int VcmSIPCCBinding::gVideoCodecMask = 0;
nsIThread *VcmSIPCCBinding::gMainThread = NULL;
static mozilla::RefPtr<TransportFlow> vcmCreateTransportFlow(sipcc::PeerConnectionImpl *pc,
int level, bool rtcp,
static mozilla::RefPtr<TransportFlow> vcmCreateTransportFlow(
sipcc::PeerConnectionImpl *pc,
int level,
bool rtcp,
sdp_setup_type_e setup_type,
const char *fingerprint_alg,
const char *fingerprint
);
const char *fingerprint);
// Convenience macro to acquire PC
@ -1349,6 +1351,7 @@ int vcmRxStart(cc_mcapid_t mcap_id,
* @param[in] peerconnection - the peerconnection in use
* @param[in] num_payloads - number of negotiated payloads
* @param[in] payloads - negotiated codec details list
* @param[in] setup - whether playing client or server role
* @param[in] fingerprint_alg - the DTLS fingerprint algorithm
* @param[in] fingerprint - the DTLS fingerprint
* @param[in] attrs - media attributes
@ -1366,6 +1369,7 @@ static int vcmRxStartICE_m(cc_mcapid_t mcap_id,
const char *peerconnection,
int num_payloads,
const vcm_payload_info_t* payloads,
sdp_setup_type_e setup_type,
const char *fingerprint_alg,
const char *fingerprint,
vcm_mediaAttrs_t *attrs)
@ -1378,7 +1382,7 @@ static int vcmRxStartICE_m(cc_mcapid_t mcap_id,
// Datachannel will use this though not for RTP
mozilla::RefPtr<TransportFlow> rtp_flow =
vcmCreateTransportFlow(pc.impl(), level, false,
vcmCreateTransportFlow(pc.impl(), level, false, setup_type,
fingerprint_alg, fingerprint);
if (!rtp_flow) {
CSFLogError( logTag, "Could not create RTP flow");
@ -1407,7 +1411,7 @@ static int vcmRxStartICE_m(cc_mcapid_t mcap_id,
mozilla::RefPtr<TransportFlow> rtcp_flow = nullptr;
if(!attrs->rtcp_mux) {
rtcp_flow = vcmCreateTransportFlow(pc.impl(), level, true,
rtcp_flow = vcmCreateTransportFlow(pc.impl(), level, true, setup_type,
fingerprint_alg, fingerprint);
if (!rtcp_flow) {
CSFLogError( logTag, "Could not create RTCP flow");
@ -1535,6 +1539,7 @@ static int vcmRxStartICE_m(cc_mcapid_t mcap_id,
* @param[in] peerconnection - the peerconnection in use
* @param[in] num_payloads - number of negotiated payloads
* @param[in] payloads - negotiated codec details list
* @param[in] setup_type - whether playing client or server role
* @param[in] fingerprint_alg - the DTLS fingerprint algorithm
* @param[in] fingerprint - the DTLS fingerprint
* @param[in] attrs - media attributes
@ -1552,6 +1557,7 @@ int vcmRxStartICE(cc_mcapid_t mcap_id,
const char *peerconnection,
int num_payloads,
const vcm_payload_info_t* payloads,
sdp_setup_type_e setup_type,
const char *fingerprint_alg,
const char *fingerprint,
vcm_mediaAttrs_t *attrs)
@ -1570,6 +1576,7 @@ int vcmRxStartICE(cc_mcapid_t mcap_id,
peerconnection,
num_payloads,
payloads,
setup_type,
fingerprint_alg,
fingerprint,
attrs,
@ -2009,6 +2016,7 @@ int vcmTxStart(cc_mcapid_t mcap_id,
* @param[in] peerconnection - the peerconnection in use
* @param[in] payload - payload information
* @param[in] tos - bit marking
* @param[in] setup_type - whether playing the client or server role
* @param[in] fingerprint_alg - the DTLS fingerprint algorithm
* @param[in] fingerprint - the DTLS fingerprint
* @param[in] attrs - media attributes
@ -2028,6 +2036,7 @@ static int vcmTxStartICE_m(cc_mcapid_t mcap_id,
const char *peerconnection,
const vcm_payload_info_t *payload,
short tos,
sdp_setup_type_e setup_type,
const char *fingerprint_alg,
const char *fingerprint,
vcm_mediaAttrs_t *attrs)
@ -2042,7 +2051,7 @@ static int vcmTxStartICE_m(cc_mcapid_t mcap_id,
// Create the transport flows
mozilla::RefPtr<TransportFlow> rtp_flow =
vcmCreateTransportFlow(pc.impl(), level, false,
vcmCreateTransportFlow(pc.impl(), level, false, setup_type,
fingerprint_alg, fingerprint);
if (!rtp_flow) {
CSFLogError( logTag, "Could not create RTP flow");
@ -2050,7 +2059,7 @@ static int vcmTxStartICE_m(cc_mcapid_t mcap_id,
}
mozilla::RefPtr<TransportFlow> rtcp_flow = nullptr;
if(!attrs->rtcp_mux) {
rtcp_flow = vcmCreateTransportFlow(pc.impl(), level, true,
rtcp_flow = vcmCreateTransportFlow(pc.impl(), level, true, setup_type,
fingerprint_alg, fingerprint);
if (!rtcp_flow) {
CSFLogError( logTag, "Could not create RTCP flow");
@ -2166,6 +2175,7 @@ static int vcmTxStartICE_m(cc_mcapid_t mcap_id,
* @param[in] peerconnection - the peerconnection in use
* @param[in] payload - payload type
* @param[in] tos - bit marking
* @param[in] setup_type - whether playing client or server role.
* @param[in] fingerprint_alg - the DTLS fingerprint algorithm
* @param[in] fingerprint - the DTLS fingerprint
* @param[in] attrs - media attributes
@ -2185,6 +2195,7 @@ int vcmTxStartICE(cc_mcapid_t mcap_id,
const char *peerconnection,
const vcm_payload_info_t *payload,
short tos,
sdp_setup_type_e setup_type,
const char *fingerprint_alg,
const char *fingerprint,
vcm_mediaAttrs_t *attrs)
@ -2203,6 +2214,7 @@ int vcmTxStartICE(cc_mcapid_t mcap_id,
peerconnection,
payload,
tos,
setup_type,
fingerprint_alg,
fingerprint,
attrs,
@ -2700,7 +2712,7 @@ int vcmGetILBCMode()
static mozilla::RefPtr<TransportFlow>
vcmCreateTransportFlow(sipcc::PeerConnectionImpl *pc, int level, bool rtcp,
const char *fingerprint_alg,
sdp_setup_type_e setup_type, const char *fingerprint_alg,
const char *fingerprint) {
// TODO(ekr@rtfm.com): Check that if the flow already exists the digest
@ -2743,12 +2755,13 @@ vcmCreateTransportFlow(sipcc::PeerConnectionImpl *pc, int level, bool rtcp,
// party is active MUST initiate a DTLS handshake by sending a
// ClientHello over each flow (host/port quartet).
//
// Currently we just hardwire the roles to be that the offerer is the
// server, which is what you would expect from the "recommended"
// behavior above.
//
// TODO(ekr@rtfm.com): implement the actpass logic above.
dtls->SetRole(pc->GetRole() == sipcc::PeerConnectionImpl::kRoleOfferer ?
// setup_type should at this point be either PASSIVE or ACTIVE
// other a=setup values should have been negotiated out.
MOZ_ASSERT(setup_type == SDP_SETUP_PASSIVE ||
setup_type == SDP_SETUP_ACTIVE);
dtls->SetRole(
setup_type == SDP_SETUP_PASSIVE ?
TransportLayerDtls::SERVER : TransportLayerDtls::CLIENT);
mozilla::RefPtr<DtlsIdentity> pcid = pc->GetIdentity();
if (!pcid) {
@ -2859,4 +2872,52 @@ int vcmOnSdpParseError(const char *peerconnection, const char *message) {
return 0;
}
/**
* vcmDisableRtcpComponent_m
*
* If we are doing rtcp-mux we need to disable component number 2 in the ICE
* layer. Otherwise we will wait for it to connect when it is unused
*/
static int vcmDisableRtcpComponent_m(const char *peerconnection, int level) {
#ifdef MOZILLA_INTERNAL_API
MOZ_ASSERT(NS_IsMainThread());
#endif
MOZ_ASSERT(level > 0);
sipcc::PeerConnectionWrapper pc(peerconnection);
ENSURE_PC(pc, VCM_ERROR);
CSFLogDebug( logTag, "%s: disabling rtcp component %d", __FUNCTION__, level);
mozilla::RefPtr<NrIceMediaStream> stream = pc.impl()->media()->
ice_media_stream(level-1);
MOZ_ASSERT(stream);
if (!stream) {
return VCM_ERROR;
}
// The second component is for RTCP
nsresult res = stream->DisableComponent(2);
MOZ_ASSERT(NS_SUCCEEDED(res));
if (!NS_SUCCEEDED(res)) {
return VCM_ERROR;
}
return 0;
}
/**
* vcmDisableRtcpComponent
*
* If we are doing rtcp-mux we need to disable component number 2 in the ICE
* layer. Otherwise we will wait for it to connect when it is unused
*/
int vcmDisableRtcpComponent(const char *peerconnection, int level) {
int ret;
mozilla::SyncRunnable::DispatchToThread(VcmSIPCCBinding::getMainThread(),
WrapRunnableNMRet(&vcmDisableRtcpComponent_m,
peerconnection,
level,
&ret));
return ret;
}

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

@ -335,7 +335,6 @@ NS_IMPL_ISUPPORTS1(PeerConnectionImpl, IPeerConnection)
PeerConnectionImpl::PeerConnectionImpl()
: mTimeCard(PR_LOG_TEST(signalingLogInfo(),PR_LOG_ERROR) ?
create_timecard() : nullptr)
, mRole(kRoleUnknown)
, mCall(NULL)
, mReadyState(kNew)
, mSignalingState(kSignalingStable)
@ -1022,8 +1021,6 @@ PeerConnectionImpl::CreateOffer(MediaConstraints& constraints)
mTimeCard = nullptr;
STAMP_TIMECARD(tc, "Create Offer");
mRole = kRoleOfferer; // TODO(ekr@rtfm.com): Interrogate SIPCC here?
cc_media_constraints_t* cc_constraints = nullptr;
constraints.buildArray(&cc_constraints);
@ -1054,8 +1051,6 @@ PeerConnectionImpl::CreateAnswer(MediaConstraints& constraints)
mTimeCard = nullptr;
STAMP_TIMECARD(tc, "Create Answer");
mRole = kRoleAnswerer; // TODO(ekr@rtfm.com): Interrogate SIPCC here?
cc_media_constraints_t* cc_constraints = nullptr;
constraints.buildArray(&cc_constraints);

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

@ -165,12 +165,6 @@ public:
kIceFailed
};
enum Role {
kRoleUnknown,
kRoleOfferer,
kRoleAnswerer
};
enum Error {
kNoError = 0,
kInvalidConstraintsType = 1,
@ -195,11 +189,6 @@ public:
static already_AddRefed<DOMMediaStream> MakeMediaStream(nsPIDOMWindow* aWindow,
uint32_t aHint);
Role GetRole() const {
PC_AUTO_ENTER_API_CALL_NO_CHECK();
return mRole;
}
nsresult CreateRemoteSourceStreamInfo(nsRefPtr<RemoteSourceStreamInfo>* aInfo);
// Implementation of the only observer we need
@ -339,9 +328,6 @@ private:
// any other attributes of this class.
Timecard *mTimeCard;
// The role we are adopting
Role mRole;
// The call
CSF::CC_CallPtr mCall;
ReadyState mReadyState;

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

@ -528,6 +528,9 @@ gsmsdp_init_media (fsmdef_media_t *media)
media->candidate_ct = 0;
media->rtcp_mux = FALSE;
/* ACTPASS is the value we put in every offer */
media->setup = SDP_SETUP_ACTPASS;
media->local_datachannel_port = 0;
media->remote_datachannel_port = 0;
media->datachannel_streams = WEBRTC_DATACHANNEL_STREAMS_DEFAULT;
@ -1821,6 +1824,71 @@ gsmsdp_set_rtcp_mux_attribute (sdp_attr_e sdp_attr, uint16_t level, void *sdp_p,
}
}
/*
* gsmsdp_set_setup_attribute
*
* Description:
*
* Adds a setup attribute to the specified SDP.
*
* Parameters:
*
* level - The media level of the SDP where the media attribute exists.
* sdp_p - Pointer to the SDP to set the ice candidate attribute against.
* setup_type - Value for the a=setup line
*/
static void
gsmsdp_set_setup_attribute(uint16_t level,
void *sdp_p, sdp_setup_type_e setup_type) {
uint16_t a_instance = 0;
sdp_result_e result;
result = sdp_add_new_attr(sdp_p, level, 0, SDP_ATTR_SETUP, &a_instance);
if (result != SDP_SUCCESS) {
GSM_ERR_MSG("Failed to add attribute");
return;
}
result = sdp_attr_set_setup_attribute(sdp_p, level, 0,
a_instance, setup_type);
if (result != SDP_SUCCESS) {
GSM_ERR_MSG("Failed to set attribute");
}
}
/*
* gsmsdp_set_connection_attribute
*
* Description:
*
* Adds a connection attribute to the specified SDP.
*
* Parameters:
*
* level - The media level of the SDP where the media attribute exists.
* sdp_p - Pointer to the SDP to set the ice candidate attribute against.
* connection_type - Value for the a=connection line
*/
static void
gsmsdp_set_connection_attribute(uint16_t level,
void *sdp_p, sdp_connection_type_e connection_type) {
uint16_t a_instance = 0;
sdp_result_e result;
result = sdp_add_new_attr(sdp_p, level, 0, SDP_ATTR_CONNECTION,
&a_instance);
if (result != SDP_SUCCESS) {
GSM_ERR_MSG("Failed to add attribute");
return;
}
result = sdp_attr_set_connection_attribute(sdp_p, level, 0,
a_instance, connection_type);
if (result != SDP_SUCCESS) {
GSM_ERR_MSG("Failed to set attribute");
}
}
/*
* gsmsdp_set_dtls_fingerprint_attribute
*
@ -4641,6 +4709,7 @@ gsmsdp_negotiate_media_lines (fsm_fcb_t *fcb_p, cc_sdp_t *sdp_p, boolean initial
sdp_result_e sdp_res;
boolean created_media_stream = FALSE;
int lsm_rc;
sdp_setup_type_e remote_setup_type;
config_get_value(CFGID_SDPMODE, &sdpmode, sizeof(sdpmode));
@ -4939,6 +5008,40 @@ gsmsdp_negotiate_media_lines (fsm_fcb_t *fcb_p, cc_sdp_t *sdp_p, boolean initial
if (sdpmode) {
int j;
/* Find the remote a=setup value */
sdp_res = sdp_attr_get_setup_attribute(
sdp_p->dest_sdp, i, 0, 1, &remote_setup_type);
/* setup attribute
We are setting our local SDP to be ACTIVE if the value
in the remote SDP is missing, PASSIVE or ACTPASS.
If the remote value is ACTIVE, then we will respond
with PASSIVE.
If the remote value is HOLDCONN we will respond with
HOLDCONN and set the direction to INACTIVE
The DTLS role will then be set when the TransportFlow
is created */
media->setup = SDP_SETUP_ACTIVE;
if (sdp_res == SDP_SUCCESS) {
if (remote_setup_type == SDP_SETUP_ACTIVE) {
media->setup = SDP_SETUP_PASSIVE;
} else if (remote_setup_type == SDP_SETUP_HOLDCONN) {
media->setup = SDP_SETUP_HOLDCONN;
media->direction = SDP_DIRECTION_INACTIVE;
}
}
gsmsdp_set_setup_attribute(media->level, dcb_p->sdp->src_sdp,
media->setup);
/* TODO(ehugg) we are not yet supporting existing connections
See bug 857115. We currently always respond with
connection:new */
gsmsdp_set_connection_attribute(media->level,
dcb_p->sdp->src_sdp, SDP_CONNECTION_NEW);
/* Set ICE */
for (j=0; j<media->candidate_ct; j++) {
gsmsdp_set_ice_attribute (SDP_ATTR_ICE_CANDIDATE, media->level,
@ -5456,6 +5559,13 @@ gsmsdp_add_media_line (fsmdef_dcb_t *dcb_p, const cc_media_cap_t *media_cap,
SDP_RTCP_FB_CCM_TO_BITMAP(SDP_RTCP_FB_CCM_FIR));
}
/* setup and connection attributes */
gsmsdp_set_setup_attribute(level, dcb_p->sdp->src_sdp, media->setup);
/* This is a new media line so we should send connection:new */
gsmsdp_set_connection_attribute(level, dcb_p->sdp->src_sdp,
SDP_CONNECTION_NEW);
/*
* wait until here to set ICE candidates as SDP is now initialized
*/
@ -6834,6 +6944,17 @@ gsmsdp_install_peer_ice_attributes(fsm_fcb_t *fcb_p)
if (!GSMSDP_MEDIA_ENABLED(media))
continue;
/* If we are muxing, disable the second
component of the ICE stream */
if (media->rtcp_mux) {
vcm_res = vcmDisableRtcpComponent(dcb_p->peerconnection,
media->level);
if (vcm_res) {
return (CC_CAUSE_SETTING_ICE_SESSION_PARAMETERS_FAILED);
}
}
sdp_res = sdp_attr_get_ice_attribute(sdp_p->dest_sdp, media->level, 0,
SDP_ATTR_ICE_UFRAG, 1, &ufrag);
if (sdp_res != SDP_SUCCESS)

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

@ -207,6 +207,11 @@ typedef struct fsmdef_media_t_ {
*/
boolean rtcp_mux;
/*
* The value of the a=setup line
*/
sdp_setup_type_e setup;
/*
* port number used in m= data channel line
*/

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

@ -1006,6 +1006,7 @@ lsm_rx_start (lsm_lcb_t *lcb, const char *fname, fsmdef_media_t *media)
dcb->peerconnection,
media->num_payloads,
media->payloads,
media->setup,
FSM_NEGOTIATED_CRYPTO_DIGEST_ALGORITHM(media),
FSM_NEGOTIATED_CRYPTO_DIGEST(media),
&attrs);
@ -1276,6 +1277,7 @@ lsm_tx_start (lsm_lcb_t *lcb, const char *fname, fsmdef_media_t *media)
dcb->peerconnection,
media->payloads,
(short)dscp,
media->setup,
FSM_NEGOTIATED_CRYPTO_DIGEST_ALGORITHM(media),
FSM_NEGOTIATED_CRYPTO_DIGEST(media),
&attrs) == -1)

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

@ -179,7 +179,7 @@ static const int gDscpCallControl = 1;
static const int gSpeakerEnabled = 1;
static const char gExternalNumberMask[] = "";
static const char gVersion[] = "0.1";
static const boolean gRTCPMUX = FALSE;
static const boolean gRTCPMUX = TRUE;
static boolean gRTPSAVPF = TRUE; /* TRUE = RTP/SAVPF , FALSE = RTP/SAVP */
static const boolean gMAXAVBITRATE = FALSE; /* Following six are OPUS fmtp options */
static const boolean gMAXCODEDAUDIOBW = FALSE;

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

@ -519,6 +519,14 @@ typedef enum {
SDP_RTCP_FB_CCM_UNKNOWN
} sdp_rtcp_fb_ccm_type_e;
typedef enum {
SDP_CONNECTION_NOT_FOUND = -1,
SDP_CONNECTION_NEW = 0,
SDP_CONNECTION_EXISTING,
SDP_MAX_CONNECTION,
SDP_CONNECTION_UNKNOWN
} sdp_connection_type_e;
#define SDP_RTCP_FB_NACK_TO_BITMAP(type) (1 << (type))
#define SDP_RTCP_FB_ACK_TO_BITMAP(type) (1 << (SDP_MAX_RTCP_FB_NACK + (type)))
#define SDP_RTCP_FB_CCM_TO_BITMAP(type) (1 << (SDP_MAX_RTCP_FB_NACK + \
@ -1017,6 +1025,8 @@ typedef struct sdp_attr {
char unknown[SDP_MAX_STRING_LEN+1];
sdp_source_filter_t source_filter;
sdp_fmtp_fb_t rtcp_fb;
sdp_setup_type_e setup;
sdp_connection_type_e connection;
} attr;
struct sdp_attr *next_p;
} sdp_attr_t;
@ -2069,6 +2079,23 @@ sdp_result_e
sdp_attr_set_rtcp_mux_attribute(void *sdp_ptr, u16 level,
u8 cap_num, sdp_attr_e sdp_attr, u16 inst_num, const tinybool rtcp_mux);
sdp_result_e
sdp_attr_get_setup_attribute (void *sdp_ptr, u16 level,
u8 cap_num, u16 inst_num, sdp_setup_type_e *setup_type);
sdp_result_e
sdp_attr_set_setup_attribute(void *sdp_ptr, u16 level,
u8 cap_num, u16 inst_num, sdp_setup_type_e setup_type);
sdp_result_e
sdp_attr_get_connection_attribute (void *sdp_ptr, u16 level,
u8 cap_num, u16 inst_num, sdp_connection_type_e *connection_type);
sdp_result_e
sdp_attr_set_connection_attribute(void *sdp_ptr, u16 level,
u8 cap_num, u16 inst_num, sdp_connection_type_e connection_type);
sdp_result_e
sdp_attr_get_dtls_fingerprint_attribute (void *sdp_ptr, u16 level,
u8 cap_num, sdp_attr_e sdp_attr, u16 inst_num,

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

@ -4986,3 +4986,127 @@ sdp_result_e sdp_parse_attr_rtcp_fb (sdp_t *sdp_p,
return SDP_SUCCESS;
}
sdp_result_e sdp_build_attr_setup(sdp_t *sdp_p,
sdp_attr_t *attr_p,
flex_string *fs)
{
switch (attr_p->attr.setup) {
case SDP_SETUP_ACTIVE:
case SDP_SETUP_PASSIVE:
case SDP_SETUP_ACTPASS:
case SDP_SETUP_HOLDCONN:
flex_string_sprintf(fs, "a=%s:%s\r\n",
sdp_attr[attr_p->type].name,
sdp_setup_type_val[attr_p->attr.setup].name);
break;
default:
CSFLogError(logTag, "%s Error: Invalid setup enum (%d)",
sdp_p->debug_str, attr_p->attr.setup);
return SDP_FAILURE;
}
return SDP_SUCCESS;
}
sdp_result_e sdp_parse_attr_setup(sdp_t *sdp_p,
sdp_attr_t *attr_p,
const char *ptr)
{
int i = find_token_enum("setup attribute", sdp_p, &ptr,
sdp_setup_type_val,
SDP_MAX_SETUP, SDP_SETUP_UNKNOWN);
if (i < 0) {
sdp_parse_error(sdp_p->peerconnection,
"%s Warning: could not parse setup attribute",
sdp_p->debug_str);
sdp_p->conf_p->num_invalid_param++;
return SDP_INVALID_PARAMETER;
}
attr_p->attr.setup = (sdp_setup_type_e) i;
switch (attr_p->attr.setup) {
case SDP_SETUP_ACTIVE:
case SDP_SETUP_PASSIVE:
case SDP_SETUP_ACTPASS:
case SDP_SETUP_HOLDCONN:
/* All these values are OK */
break;
case SDP_SETUP_UNKNOWN:
sdp_parse_error(sdp_p->peerconnection,
"%s Warning: Unknown setup attribute",
sdp_p->debug_str);
return SDP_INVALID_PARAMETER;
break;
default:
/* This is an internal error, not a parsing error */
CSFLogError(logTag, "%s Error: Invalid setup enum (%d)",
sdp_p->debug_str, attr_p->attr.setup);
return SDP_FAILURE;
break;
}
return SDP_SUCCESS;
}
sdp_result_e sdp_build_attr_connection(sdp_t *sdp_p,
sdp_attr_t *attr_p,
flex_string *fs)
{
switch (attr_p->attr.connection) {
case SDP_CONNECTION_NEW:
case SDP_CONNECTION_EXISTING:
flex_string_sprintf(fs, "a=%s:%s\r\n",
sdp_attr[attr_p->type].name,
sdp_connection_type_val[attr_p->attr.connection].name);
break;
default:
CSFLogError(logTag, "%s Error: Invalid connection enum (%d)",
sdp_p->debug_str, attr_p->attr.connection);
return SDP_FAILURE;
}
return SDP_SUCCESS;
}
sdp_result_e sdp_parse_attr_connection(sdp_t *sdp_p,
sdp_attr_t *attr_p,
const char *ptr)
{
int i = find_token_enum("connection attribute", sdp_p, &ptr,
sdp_connection_type_val,
SDP_MAX_CONNECTION, SDP_CONNECTION_UNKNOWN);
if (i < 0) {
sdp_parse_error(sdp_p->peerconnection,
"%s Warning: could not parse connection attribute",
sdp_p->debug_str);
sdp_p->conf_p->num_invalid_param++;
return SDP_INVALID_PARAMETER;
}
attr_p->attr.connection = (sdp_connection_type_e) i;
switch (attr_p->attr.connection) {
case SDP_CONNECTION_NEW:
case SDP_CONNECTION_EXISTING:
/* All these values are OK */
break;
case SDP_CONNECTION_UNKNOWN:
sdp_parse_error(sdp_p->peerconnection,
"%s Warning: Unknown connection attribute",
sdp_p->debug_str);
return SDP_INVALID_PARAMETER;
break;
default:
/* This is an internal error, not a parsing error */
CSFLogError(logTag, "%s Error: Invalid connection enum (%d)",
sdp_p->debug_str, attr_p->attr.connection);
return SDP_FAILURE;
break;
}
return SDP_SUCCESS;
}

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

@ -4084,6 +4084,163 @@ sdp_result_e sdp_attr_set_rtcp_mux_attribute(void *sdp_ptr, u16 level,
return (SDP_SUCCESS);
}
/* Function: sdp_attr_get_setup_attribute
* Description: Returns the value of a setup attribute at a given level
*
* Parameters: sdp_ptr The SDP handle returned by sdp_init_description.
* level The level to check for the attribute.
* cap_num The capability number associated with the
* attribute if any. If none, should be zero.
* inst_num The attribute instance number to check.
* setup_type Returns sdp_setup_type_e enum
* Returns:
* SDP_SUCCESS Attribute param was set successfully.
* SDP_INVALID_SDP_PTR SDP pointer invalid
* SDP_INVALID_PARAMETER Specified attribute is not defined.
*/
sdp_result_e sdp_attr_get_setup_attribute (void *sdp_ptr, u16 level,
u8 cap_num, u16 inst_num, sdp_setup_type_e *setup_type)
{
sdp_t *sdp_p = (sdp_t *)sdp_ptr;
sdp_attr_t *attr_p;
if (!sdp_verify_sdp_ptr(sdp_p)) {
return SDP_INVALID_SDP_PTR;
}
attr_p = sdp_find_attr(sdp_p, level, cap_num, SDP_ATTR_SETUP, inst_num);
if (!attr_p) {
if (sdp_p->debug_flag[SDP_DEBUG_ERRORS]) {
CSFLogError(logTag,
"%s setup attribute, level %u instance %u not found.",
sdp_p->debug_str, level, inst_num);
}
sdp_p->conf_p->num_invalid_param++;
return SDP_INVALID_PARAMETER;
}
*setup_type = attr_p->attr.setup;
return SDP_SUCCESS;
}
/* Function: sdp_attr_set_setup_attribute
* Description: Sets the value of a setup attribute parameter
*
* Parameters: sdp_ptr The SDP handle returned by sdp_init_description.
* level The level to set the attribute.
* cap_num The capability number associated with the
* attribute if any. If none, should be zero.
* inst_num The attribute instance number to check.
* setup_type setup attribute value to set
* Returns: SDP_SUCCESS Attribute param was set successfully.
* SDP_INVALID_SDP_PTR SDP ptr invalid
* SDP_INVALID_PARAMETER Specified attribute is not defined.
*/
sdp_result_e
sdp_attr_set_setup_attribute(void *sdp_ptr, u16 level,
u8 cap_num, u16 inst_num, sdp_setup_type_e setup_type)
{
sdp_t *sdp_p = (sdp_t *)sdp_ptr;
sdp_attr_t *attr_p;
if (!sdp_verify_sdp_ptr(sdp_p)) {
return SDP_INVALID_SDP_PTR;
}
attr_p = sdp_find_attr(sdp_p, level, cap_num, SDP_ATTR_SETUP, inst_num);
if (!attr_p) {
if (sdp_p->debug_flag[SDP_DEBUG_ERRORS]) {
CSFLogError(logTag, "%s setup attribute, level %u instance %u "
"not found.", sdp_p->debug_str, level, inst_num);
}
sdp_p->conf_p->num_invalid_param++;
return SDP_INVALID_PARAMETER;
}
attr_p->attr.setup = setup_type;
return SDP_SUCCESS;
}
/* Function: sdp_attr_get_connection_attribute
* Description: Returns the value of a connection attribute at a given level
*
* Parameters: sdp_ptr The SDP handle returned by sdp_init_description.
* level The level to check for the attribute.
* cap_num The capability number associated with the
* attribute if any. If none, should be zero.
* inst_num The attribute instance number to check.
* connection_type Returns sdp_connection_type_e enum
* Returns:
* SDP_SUCCESS Attribute param was set successfully.
* SDP_INVALID_SDP_PTR SDP pointer invalid
* SDP_INVALID_PARAMETER Specified attribute is not defined.
*/
sdp_result_e sdp_attr_get_connection_attribute (void *sdp_ptr, u16 level,
u8 cap_num, u16 inst_num, sdp_connection_type_e *connection_type)
{
sdp_t *sdp_p = (sdp_t *)sdp_ptr;
sdp_attr_t *attr_p;
if (!sdp_verify_sdp_ptr(sdp_p)) {
return SDP_INVALID_SDP_PTR;
}
attr_p = sdp_find_attr(sdp_p, level, cap_num, SDP_ATTR_CONNECTION,
inst_num);
if (!attr_p) {
if (sdp_p->debug_flag[SDP_DEBUG_ERRORS]) {
CSFLogError(logTag,
"%s setup attribute, level %u instance %u not found.",
sdp_p->debug_str, level, inst_num);
}
sdp_p->conf_p->num_invalid_param++;
return SDP_INVALID_PARAMETER;
}
*connection_type = attr_p->attr.connection;
return SDP_SUCCESS;
}
/* Function: sdp_attr_set_connection_attribute
* Description: Sets the value of a connection attribute parameter
*
* Parameters: sdp_ptr The SDP handle returned by sdp_init_description.
* level The level to set the attribute.
* cap_num The capability number associated with the
* attribute if any. If none, should be zero.
* inst_num The attribute instance number to check.
* connection_type connection attribute value to set
* Returns: SDP_SUCCESS Attribute param was set successfully.
* SDP_INVALID_SDP_PTR SDP ptr invalid
* SDP_INVALID_PARAMETER Specified attribute is not defined.
*/
sdp_result_e
sdp_attr_set_connection_attribute(void *sdp_ptr, u16 level,
u8 cap_num, u16 inst_num, sdp_connection_type_e connection_type)
{
sdp_t *sdp_p = (sdp_t *)sdp_ptr;
sdp_attr_t *attr_p;
if (!sdp_verify_sdp_ptr(sdp_p)) {
return SDP_INVALID_SDP_PTR;
}
attr_p = sdp_find_attr(sdp_p, level, cap_num, SDP_ATTR_CONNECTION,
inst_num);
if (!attr_p) {
if (sdp_p->debug_flag[SDP_DEBUG_ERRORS]) {
CSFLogError(logTag, "%s connection attribute, level %u instance %u "
"not found.", sdp_p->debug_str, level, inst_num);
}
sdp_p->conf_p->num_invalid_param++;
return SDP_INVALID_PARAMETER;
}
attr_p->attr.connection = connection_type;
return SDP_SUCCESS;
}
/* Function: sdp_attr_get_dtls_fingerprint_attribute
* Description: Returns the value of dtls fingerprint attribute at a given level
*

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

@ -169,7 +169,11 @@ const sdp_attrarray_t sdp_attr[SDP_MAX_ATTR_TYPES] =
{"maxptime", sizeof("maxptime"),
sdp_parse_attr_simple_u32, sdp_build_attr_simple_u32},
{"rtcp-fb", sizeof("rtcp-fb"),
sdp_parse_attr_rtcp_fb, sdp_build_attr_rtcp_fb}
sdp_parse_attr_rtcp_fb, sdp_build_attr_rtcp_fb},
{"setup", sizeof("setup"),
sdp_parse_attr_setup, sdp_build_attr_setup},
{"connection", sizeof("connection"),
sdp_parse_attr_connection, sdp_build_attr_connection},
};
/* Note: These *must* be in the same order as the enum types. */
@ -483,6 +487,21 @@ const sdp_namearray_t sdp_rtcp_fb_ccm_type_val[SDP_MAX_RTCP_FB_CCM] =
SDP_NAME("vbcm")
};
/* Maintain the same order as defined in typedef sdp_setup_type_e */
const sdp_namearray_t sdp_setup_type_val[SDP_MAX_SETUP] =
{
SDP_NAME("active"),
SDP_NAME("passive"),
SDP_NAME("actpass"),
SDP_NAME("holdconn")
};
/* Maintain the same order as defined in typedef sdp_connection_type_e */
const sdp_namearray_t sdp_connection_type_val[SDP_MAX_CONNECTION] =
{
SDP_NAME("new"),
SDP_NAME("existing")
};
/* Maintain same order as defined in typedef sdp_srtp_crypto_suite_t */
const sdp_srtp_crypto_suite_list sdp_srtp_crypto_suite_array[SDP_SRTP_MAX_NUM_CRYPTO_SUITES] =

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

@ -37,6 +37,8 @@ extern const sdp_namearray_t sdp_rtcp_fb_type_val[];
extern const sdp_namearray_t sdp_rtcp_fb_nack_type_val[];
extern const sdp_namearray_t sdp_rtcp_fb_ack_type_val[];
extern const sdp_namearray_t sdp_rtcp_fb_ccm_type_val[];
extern const sdp_namearray_t sdp_setup_type_val[];
extern const sdp_namearray_t sdp_connection_type_val[];
extern const sdp_srtp_crypto_suite_list sdp_srtp_crypto_suite_array[];
@ -149,6 +151,18 @@ extern sdp_result_e sdp_parse_attr_rtcp_fb(sdp_t *sdp_p,
extern sdp_result_e sdp_build_attr_rtcp_fb(sdp_t *sdp_p,
sdp_attr_t *attr_p,
flex_string *fs);
extern sdp_result_e sdp_parse_attr_setup(sdp_t *sdp_p,
sdp_attr_t *attr_p,
const char *ptr);
extern sdp_result_e sdp_build_attr_setup(sdp_t *sdp_p,
sdp_attr_t *attr_p,
flex_string *fs);
extern sdp_result_e sdp_parse_attr_connection(sdp_t *sdp_p,
sdp_attr_t *attr_p,
const char *ptr);
extern sdp_result_e sdp_build_attr_connection(sdp_t *sdp_p,
sdp_attr_t *attr_p,
flex_string *fs);
extern sdp_result_e sdp_parse_attr_mptime(
sdp_t *sdp_p, sdp_attr_t *attr_p, const char *ptr);
extern sdp_result_e sdp_build_attr_mptime(

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

@ -242,10 +242,23 @@ typedef enum {
SDP_ATTR_DTLS_FINGERPRINT,
SDP_ATTR_MAXPTIME,
SDP_ATTR_RTCP_FB, /* RFC 4585 */
SDP_ATTR_SETUP,
SDP_ATTR_CONNECTION,
SDP_MAX_ATTR_TYPES,
SDP_ATTR_INVALID
} sdp_attr_e;
/* This is here so that it can be used in the VcmSIPCCBinding interface */
typedef enum {
SDP_SETUP_NOT_FOUND = -1,
SDP_SETUP_ACTIVE = 0,
SDP_SETUP_PASSIVE,
SDP_SETUP_ACTPASS,
SDP_SETUP_HOLDCONN,
SDP_MAX_SETUP,
SDP_SETUP_UNKNOWN
} sdp_setup_type_e;
/**
* Gets the value of the fmtp attribute- parameter-sets parameter for H.264 codec
*

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

@ -585,6 +585,7 @@ int vcmRxStart(cc_mcapid_t mcap_id,
* @param[in] peerconnection - the peerconnection in use
* @param[in] num_payloads - number of codecs negotiated
* @param[in] payloads - list of negotiated codec details
* @param[in] setup_t - whether playing client or server role
* @param[in] fingerprint_alg - the DTLS fingerprint algorithm
* @param[in] fingerprint - the DTLS fingerprint
* @param[in] attrs - media attributes
@ -603,6 +604,7 @@ int vcmRxStartICE(cc_mcapid_t mcap_id,
const char *peerconnection,
int num_payloads,
const vcm_payload_info_t* payloads,
sdp_setup_type_e setup_type,
const char *fingerprint_alg,
const char *fingerprint,
vcm_mediaAttrs_t *attrs);
@ -663,6 +665,7 @@ int vcmTxStart(cc_mcapid_t mcap_id,
* @param[in] peerconnection - the peerconnection in use
* @param[in] payload - payload information
* @param[in] tos - bit marking
* @param[in] setup_type - whether playing client or server role
* @param[in] fingerprint_alg - the DTLS fingerprint algorithm
* @param[in] fingerprint - the DTLS fingerprint
* @param[in] attrs - media attributes
@ -681,6 +684,7 @@ int vcmTxStart(cc_mcapid_t mcap_id,
const char *peerconnection,
const vcm_payload_info_t *payload,
short tos,
sdp_setup_type_e setup_type,
const char *fingerprint_alg,
const char *fingerprint,
vcm_mediaAttrs_t *attrs);
@ -1035,6 +1039,14 @@ int vcmGetILBCMode();
*/
int vcmOnSdpParseError(const char *peercconnection, const char *message);
/**
* vcmDisableRtcpComponent
*
* If we are doing rtcp-mux we need to disable component number 2 in the ICE
* layer. Otherwise we will wait for it to connect when it is unused
*/
int vcmDisableRtcpComponent(const char *peerconnection, int level);
//Using C++ for gips. This is the end of extern "C" above.
#ifdef __cplusplus
}

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

@ -37,7 +37,7 @@ MtransportTestUtils *test_utils;
nsCOMPtr<nsIThread> gThread;
static int kDefaultTimeout = 5000;
static bool fRtcpMux = false;
static bool fRtcpMux = true;
static std::string callerName = "caller";
static std::string calleeName = "callee";
@ -2472,6 +2472,352 @@ TEST_F(SignalingTest, FullCallAudioNoMuxVideoMux)
PIPELINE_VIDEO);
}
// In this test we will change the offer SDP's a=setup value
// from actpass to passive. This will make the answer do active.
TEST_F(SignalingTest, AudioCallForceDtlsRoles)
{
sipcc::MediaConstraints constraints;
size_t match;
a1_.CreateOffer(constraints, OFFER_AUDIO, SHOULD_SENDRECV_AUDIO);
// By default the offer should give actpass
std::string offer(a1_.offer());
match = offer.find("\r\na=setup:actpass");
ASSERT_NE(match, std::string::npos);
// Now replace the actpass with passive so that the answer will
// return active
offer.replace(match, strlen("\r\na=setup:actpass"),
"\r\na=setup:passive");
std::cout << "Modified SDP " << std::endl
<< indent(offer) << std::endl;
a1_.SetLocal(TestObserver::OFFER, offer.c_str(), false);
a2_.SetRemote(TestObserver::OFFER, offer.c_str(), false);
a2_.CreateAnswer(constraints, offer.c_str(), OFFER_AUDIO | ANSWER_AUDIO);
// Now the answer should contain a=setup:active
std::string answer(a2_.answer());
match = answer.find("\r\na=setup:active");
ASSERT_NE(match, std::string::npos);
// This should setup the DTLS with the same roles
// as the regular tests above.
a2_.SetLocal(TestObserver::ANSWER, a2_.answer(), false);
a1_.SetRemote(TestObserver::ANSWER, a2_.answer(), false);
ASSERT_TRUE_WAIT(a1_.IceCompleted() == true, kDefaultTimeout);
ASSERT_TRUE_WAIT(a2_.IceCompleted() == true, kDefaultTimeout);
// Wait for some data to get written
ASSERT_TRUE_WAIT(a1_.GetPacketsSent(0) >= 40 &&
a2_.GetPacketsReceived(0) >= 40, kDefaultTimeout * 2);
a1_.CloseSendStreams();
a2_.CloseReceiveStreams();
ASSERT_GE(a1_.GetPacketsSent(0), 40);
ASSERT_GE(a2_.GetPacketsReceived(0), 40);
}
// In this test we will change the offer SDP's a=setup value
// from actpass to active. This will make the answer do passive
TEST_F(SignalingTest, AudioCallReverseDtlsRoles)
{
sipcc::MediaConstraints constraints;
size_t match;
a1_.CreateOffer(constraints, OFFER_AUDIO, SHOULD_SENDRECV_AUDIO);
// By default the offer should give actpass
std::string offer(a1_.offer());
match = offer.find("\r\na=setup:actpass");
ASSERT_NE(match, std::string::npos);
// Now replace the actpass with active so that the answer will
// return passive
offer.replace(match, strlen("\r\na=setup:actpass"),
"\r\na=setup:active");
std::cout << "Modified SDP " << std::endl
<< indent(offer) << std::endl;
a1_.SetLocal(TestObserver::OFFER, offer.c_str(), false);
a2_.SetRemote(TestObserver::OFFER, offer.c_str(), false);
a2_.CreateAnswer(constraints, offer.c_str(), OFFER_AUDIO | ANSWER_AUDIO);
// Now the answer should contain a=setup:passive
std::string answer(a2_.answer());
match = answer.find("\r\na=setup:passive");
ASSERT_NE(match, std::string::npos);
// This should setup the DTLS with the opposite roles
// than the regular tests above.
a2_.SetLocal(TestObserver::ANSWER, a2_.answer(), false);
a1_.SetRemote(TestObserver::ANSWER, a2_.answer(), false);
ASSERT_TRUE_WAIT(a1_.IceCompleted() == true, kDefaultTimeout);
ASSERT_TRUE_WAIT(a2_.IceCompleted() == true, kDefaultTimeout);
// Wait for some data to get written
ASSERT_TRUE_WAIT(a1_.GetPacketsSent(0) >= 40 &&
a2_.GetPacketsReceived(0) >= 40, kDefaultTimeout * 2);
a1_.CloseSendStreams();
a2_.CloseReceiveStreams();
ASSERT_GE(a1_.GetPacketsSent(0), 40);
ASSERT_GE(a2_.GetPacketsReceived(0), 40);
}
// In this test we will change the answer SDP's a=setup value
// from active to passive. This will make both sides do
// active and should not connect.
TEST_F(SignalingTest, AudioCallMismatchDtlsRoles)
{
sipcc::MediaConstraints constraints;
size_t match;
a1_.CreateOffer(constraints, OFFER_AUDIO, SHOULD_SENDRECV_AUDIO);
// By default the offer should give actpass
std::string offer(a1_.offer());
match = offer.find("\r\na=setup:actpass");
ASSERT_NE(match, std::string::npos);
a1_.SetLocal(TestObserver::OFFER, offer.c_str(), false);
a2_.SetRemote(TestObserver::OFFER, offer.c_str(), false);
a2_.CreateAnswer(constraints, offer.c_str(), OFFER_AUDIO | ANSWER_AUDIO);
// Now the answer should contain a=setup:active
std::string answer(a2_.answer());
match = answer.find("\r\na=setup:active");
ASSERT_NE(match, std::string::npos);
// Now replace the active with passive so that the offerer will
// also do active.
answer.replace(match, strlen("\r\na=setup:active"),
"\r\na=setup:passive");
std::cout << "Modified SDP " << std::endl
<< indent(answer) << std::endl;
// This should setup the DTLS with both sides playing active
a2_.SetLocal(TestObserver::ANSWER, answer.c_str(), false);
a1_.SetRemote(TestObserver::ANSWER, answer.c_str(), false);
ASSERT_TRUE_WAIT(a1_.IceCompleted() == true, kDefaultTimeout);
ASSERT_TRUE_WAIT(a2_.IceCompleted() == true, kDefaultTimeout);
// Not using ASSERT_TRUE_WAIT here because we expect failure
PR_Sleep(kDefaultTimeout * 2); // Wait for some data to get written
a1_.CloseSendStreams();
a2_.CloseReceiveStreams();
ASSERT_GE(a1_.GetPacketsSent(0), 40);
// In this case we should receive nothing.
ASSERT_EQ(a2_.GetPacketsReceived(0), 0);
}
// In this test we will change the offer SDP's a=setup value
// from actpass to garbage. It should ignore the garbage value
// and respond with setup:active
TEST_F(SignalingTest, AudioCallGarbageSetup)
{
sipcc::MediaConstraints constraints;
size_t match;
a1_.CreateOffer(constraints, OFFER_AUDIO, SHOULD_SENDRECV_AUDIO);
// By default the offer should give actpass
std::string offer(a1_.offer());
match = offer.find("\r\na=setup:actpass");
ASSERT_NE(match, std::string::npos);
// Now replace the actpass with a garbage value
offer.replace(match, strlen("\r\na=setup:actpass"),
"\r\na=setup:G4rb4g3V4lu3");
std::cout << "Modified SDP " << std::endl
<< indent(offer) << std::endl;
a1_.SetLocal(TestObserver::OFFER, offer.c_str(), false);
a2_.SetRemote(TestObserver::OFFER, offer.c_str(), false);
a2_.CreateAnswer(constraints, offer.c_str(), OFFER_AUDIO | ANSWER_AUDIO);
// Now the answer should contain a=setup:active
std::string answer(a2_.answer());
match = answer.find("\r\na=setup:active");
ASSERT_NE(match, std::string::npos);
// This should setup the DTLS with the same roles
// as the regular tests above.
a2_.SetLocal(TestObserver::ANSWER, a2_.answer(), false);
a1_.SetRemote(TestObserver::ANSWER, a2_.answer(), false);
ASSERT_TRUE_WAIT(a1_.IceCompleted() == true, kDefaultTimeout);
ASSERT_TRUE_WAIT(a2_.IceCompleted() == true, kDefaultTimeout);
// Wait for some data to get written
ASSERT_TRUE_WAIT(a1_.GetPacketsSent(0) >= 40 &&
a2_.GetPacketsReceived(0) >= 40, kDefaultTimeout * 2);
a1_.CloseSendStreams();
a2_.CloseReceiveStreams();
ASSERT_GE(a1_.GetPacketsSent(0), 40);
ASSERT_GE(a2_.GetPacketsReceived(0), 40);
}
// In this test we will change the offer SDP's a=connection value
// from new to garbage. It should ignore the garbage value
// and respond with connection:new
TEST_F(SignalingTest, AudioCallGarbageConnection)
{
sipcc::MediaConstraints constraints;
size_t match;
a1_.CreateOffer(constraints, OFFER_AUDIO, SHOULD_SENDRECV_AUDIO);
// By default the offer should give connection:new
std::string offer(a1_.offer());
match = offer.find("\r\na=connection:new");
ASSERT_NE(match, std::string::npos);
// Now replace the 'new' with a garbage value
offer.replace(match, strlen("\r\na=connection:new"),
"\r\na=connection:G4rb4g3V4lu3");
std::cout << "Modified SDP " << std::endl
<< indent(offer) << std::endl;
a1_.SetLocal(TestObserver::OFFER, offer.c_str(), false);
a2_.SetRemote(TestObserver::OFFER, offer.c_str(), false);
a2_.CreateAnswer(constraints, offer.c_str(), OFFER_AUDIO | ANSWER_AUDIO);
// Now the answer should contain a=connection:new
std::string answer(a2_.answer());
match = answer.find("\r\na=connection:new");
ASSERT_NE(match, std::string::npos);
// This should setup the DTLS with the same roles
// as the regular tests above.
a2_.SetLocal(TestObserver::ANSWER, a2_.answer(), false);
a1_.SetRemote(TestObserver::ANSWER, a2_.answer(), false);
ASSERT_TRUE_WAIT(a1_.IceCompleted() == true, kDefaultTimeout);
ASSERT_TRUE_WAIT(a2_.IceCompleted() == true, kDefaultTimeout);
// Wait for some data to get written
ASSERT_TRUE_WAIT(a1_.GetPacketsSent(0) >= 40 &&
a2_.GetPacketsReceived(0) >= 40, kDefaultTimeout * 2);
a1_.CloseSendStreams();
a2_.CloseReceiveStreams();
ASSERT_GE(a1_.GetPacketsSent(0), 40);
ASSERT_GE(a2_.GetPacketsReceived(0), 40);
}
// In this test we will change the offer SDP to remove the
// a=setup and a=connection lines. Answer should respond with
// a=setup:active and a=connection:new
TEST_F(SignalingTest, AudioCallOfferNoSetupOrConnection)
{
sipcc::MediaConstraints constraints;
size_t match;
a1_.CreateOffer(constraints, OFFER_AUDIO, SHOULD_SENDRECV_AUDIO);
// By default the offer should give setup:actpass and connection:new
std::string offer(a1_.offer());
match = offer.find("\r\na=setup:actpass");
ASSERT_NE(match, std::string::npos);
// Remove the a=setup line
offer.replace(match, strlen("\r\na=setup:actpass"), "");
match = offer.find("\r\na=connection:new");
ASSERT_NE(match, std::string::npos);
// Remove the a=connection line
offer.replace(match, strlen("\r\na=connection:new"), "");
std::cout << "Modified SDP " << std::endl
<< indent(offer) << std::endl;
a1_.SetLocal(TestObserver::OFFER, offer.c_str(), false);
a2_.SetRemote(TestObserver::OFFER, offer.c_str(), false);
a2_.CreateAnswer(constraints, offer.c_str(), OFFER_AUDIO | ANSWER_AUDIO);
// Now the answer should contain a=setup:active and a=connection:new
std::string answer(a2_.answer());
match = answer.find("\r\na=setup:active");
ASSERT_NE(match, std::string::npos);
match = answer.find("\r\na=connection:new");
ASSERT_NE(match, std::string::npos);
// This should setup the DTLS with the same roles
// as the regular tests above.
a2_.SetLocal(TestObserver::ANSWER, a2_.answer(), false);
a1_.SetRemote(TestObserver::ANSWER, a2_.answer(), false);
ASSERT_TRUE_WAIT(a1_.IceCompleted() == true, kDefaultTimeout);
ASSERT_TRUE_WAIT(a2_.IceCompleted() == true, kDefaultTimeout);
// Wait for some data to get written
ASSERT_TRUE_WAIT(a1_.GetPacketsSent(0) >= 40 &&
a2_.GetPacketsReceived(0) >= 40, kDefaultTimeout * 2);
a1_.CloseSendStreams();
a2_.CloseReceiveStreams();
ASSERT_GE(a1_.GetPacketsSent(0), 40);
ASSERT_GE(a2_.GetPacketsReceived(0), 40);
}
// In this test we will change the answer SDP to remove the
// a=setup and a=connection lines. ICE should still connect
// since active will be assumed.
TEST_F(SignalingTest, AudioCallAnswerNoSetupOrConnection)
{
sipcc::MediaConstraints constraints;
size_t match;
a1_.CreateOffer(constraints, OFFER_AUDIO, SHOULD_SENDRECV_AUDIO);
// By default the offer should give setup:actpass and connection:new
std::string offer(a1_.offer());
match = offer.find("\r\na=setup:actpass");
ASSERT_NE(match, std::string::npos);
match = offer.find("\r\na=connection:new");
ASSERT_NE(match, std::string::npos);
a1_.SetLocal(TestObserver::OFFER, offer.c_str(), false);
a2_.SetRemote(TestObserver::OFFER, offer.c_str(), false);
a2_.CreateAnswer(constraints, offer.c_str(), OFFER_AUDIO | ANSWER_AUDIO);
// Now the answer should contain a=setup:active and a=connection:new
std::string answer(a2_.answer());
match = answer.find("\r\na=setup:active");
ASSERT_NE(match, std::string::npos);
// Remove the a=setup line
answer.replace(match, strlen("\r\na=setup:active"), "");
match = answer.find("\r\na=connection:new");
ASSERT_NE(match, std::string::npos);
// Remove the a=connection line
answer.replace(match, strlen("\r\na=connection:new"), "");
std::cout << "Modified SDP " << std::endl
<< indent(answer) << std::endl;
// This should setup the DTLS with the same roles
// as the regular tests above.
a2_.SetLocal(TestObserver::ANSWER, a2_.answer(), false);
a1_.SetRemote(TestObserver::ANSWER, a2_.answer(), false);
ASSERT_TRUE_WAIT(a1_.IceCompleted() == true, kDefaultTimeout);
ASSERT_TRUE_WAIT(a2_.IceCompleted() == true, kDefaultTimeout);
// Wait for some data to get written
ASSERT_TRUE_WAIT(a1_.GetPacketsSent(0) >= 40 &&
a2_.GetPacketsReceived(0) >= 40, kDefaultTimeout * 2);
a1_.CloseSendStreams();
a2_.CloseReceiveStreams();
ASSERT_GE(a1_.GetPacketsSent(0), 40);
ASSERT_GE(a2_.GetPacketsReceived(0), 40);
}
} // End namespace test.
bool is_color_terminal(const char *terminal) {

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

@ -68,18 +68,18 @@ class RefCounted
public:
// Compatibility with nsRefPtr.
void AddRef() {
void AddRef() const {
MOZ_ASSERT(refCnt >= 0);
++refCnt;
}
void Release() {
void Release() const {
MOZ_ASSERT(refCnt > 0);
if (0 == --refCnt) {
#ifdef DEBUG
refCnt = detail::DEAD;
#endif
delete static_cast<T*>(this);
delete static_cast<const T*>(this);
}
}
@ -93,7 +93,7 @@ class RefCounted
}
private:
typename Conditional<Atomicity == AtomicRefCount, Atomic<int>, int>::Type refCnt;
mutable typename Conditional<Atomicity == AtomicRefCount, Atomic<int>, int>::Type refCnt;
};
}

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

@ -2347,7 +2347,10 @@ abstract public class GeckoApp
try {
obj.put("lac", gcl.getLac());
obj.put("cid", gcl.getCid());
obj.put("psc", gcl.getPsc());
int psc = (Build.VERSION.SDK_INT >= 9) ? gcl.getPsc() : -1;
obj.put("psc", psc);
switch(tm.getNetworkType()) {
case TelephonyManager.NETWORK_TYPE_GPRS:
case TelephonyManager.NETWORK_TYPE_EDGE:

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

@ -70,7 +70,7 @@ class LibHandle;
namespace mozilla {
namespace detail {
template <> inline void RefCounted<LibHandle, AtomicRefCount>::Release();
template <> inline void RefCounted<LibHandle, AtomicRefCount>::Release() const;
template <> inline RefCounted<LibHandle, AtomicRefCount>::~RefCounted()
{
@ -215,7 +215,7 @@ private:
namespace mozilla {
namespace detail {
template <> inline void RefCounted<LibHandle, AtomicRefCount>::Release() {
template <> inline void RefCounted<LibHandle, AtomicRefCount>::Release() const {
#ifdef DEBUG
if (refCnt > 0x7fff0000)
MOZ_ASSERT(refCnt > 0x7fffdead);
@ -228,7 +228,7 @@ template <> inline void RefCounted<LibHandle, AtomicRefCount>::Release() {
#else
refCnt = 1;
#endif
delete static_cast<LibHandle*>(this);
delete static_cast<const LibHandle*>(this);
}
}
}

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

@ -38,7 +38,7 @@
<![CDATA[
if (!this._remoteWebNavigation) {
let jsm = "resource://gre/modules/RemoteWebNavigation.jsm";
let RemoteWebNavigation = Components.utils.import(jsm, {}).RemoteWebNavigation;
let RemoteWebNavigation = Cu.import(jsm, {}).RemoteWebNavigation;
this._remoteWebNavigation = new RemoteWebNavigation(this);
}
return this._remoteWebNavigation;
@ -53,8 +53,9 @@
<![CDATA[
if (!this._remoteWebProgress) {
let jsm = "resource://gre/modules/RemoteWebProgress.jsm";
let RemoteWebProgress = Components.utils.import(jsm, {}).RemoteWebProgress;
this._remoteWebProgress = new RemoteWebProgress(this);
let RemoteWebProgressManager = Cu.import(jsm, {}).RemoteWebProgressManager;
this._remoteWebProgress = new RemoteWebProgressManager(this)
.topLevelWebProgress;
}
return this._remoteWebProgress;
]]>
@ -107,8 +108,6 @@
this.messageManager.loadFrameScript("chrome://global/content/select-child.js", true);
}
this.webProgress._init();
let jsm = "resource://gre/modules/RemoteController.jsm";
let RemoteController = Components.utils.import(jsm, {}).RemoteController;
this._controller = new RemoteController(this);

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

@ -13,36 +13,22 @@ Cu.import("resource://gre/modules/XPCOMUtils.jsm");
function RemoteSecurityUI()
{
this._state = 0;
this._SSLStatus = null;
this._state = 0;
}
RemoteSecurityUI.prototype = {
QueryInterface: XPCOMUtils.generateQI([Ci.nsISSLStatusProvider, Ci.nsISecureBrowserUI]),
// nsISSLStatusProvider
get SSLStatus() { return this._SSLStatus; },
// nsISecureBrowserUI
get state() { return this._state; },
get tooltipText() { return ""; },
// nsISSLStatusProvider
get SSLStatus() { return this._SSLStatus; },
_update: function (state, status) {
let deserialized = null;
if (status) {
let helper = Cc["@mozilla.org/network/serialization-helper;1"]
.getService(Components.interfaces.nsISerializationHelper);
deserialized = helper.deserializeObject(status)
deserialized.QueryInterface(Ci.nsISSLStatus);
}
// We must check the Extended Validation (EV) state here, on the chrome
// process, because NSS is needed for that determination.
if (deserialized && deserialized.isExtendedValidation)
state |= Ci.nsIWebProgressListener.STATE_IDENTITY_EV_TOPLEVEL;
this._state = state;
this._SSLStatus = deserialized;
_update: function (aStatus, aState) {
this._SSLStatus = aStatus;
this._state = aState;
}
};

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

@ -3,7 +3,7 @@
// 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/.
this.EXPORTED_SYMBOLS = ["RemoteWebProgress"];
this.EXPORTED_SYMBOLS = ["RemoteWebProgressManager"];
const Ci = Components.interfaces;
const Cc = Components.classes;
@ -28,14 +28,13 @@ RemoteWebProgressRequest.prototype = {
get URI() { return this.uri.clone(); }
};
function RemoteWebProgress(browser)
{
this._browser = browser;
function RemoteWebProgress(aManager, aIsTopLevel) {
this._manager = aManager;
this._isLoadingDocument = false;
this._DOMWindow = null;
this._isTopLevel = null;
this._isTopLevel = aIsTopLevel;
this._loadType = 0;
this._progressListeners = [];
}
RemoteWebProgress.prototype = {
@ -51,101 +50,132 @@ RemoteWebProgress.prototype = {
NOTIFY_REFRESH: 0x00000100,
NOTIFY_ALL: 0x000001ff,
_init: function WP_Init() {
get isLoadingDocument() { return this._isLoadingDocument },
get DOMWindow() { return this._DOMWindow; },
get DOMWindowID() { return 0; },
get isTopLevel() { return this._isTopLevel },
get loadType() { return this._loadType; },
addProgressListener: function (aListener) {
this._manager.addProgressListener(aListener);
},
removeProgressListener: function (aListener) {
this._manager.removeProgressListener(aListener);
}
};
function RemoteWebProgressManager (aBrowser) {
this._browser = aBrowser;
this._topLevelWebProgress = new RemoteWebProgress(this, true);
this._progressListeners = [];
this._browser.messageManager.addMessageListener("Content:StateChange", this);
this._browser.messageManager.addMessageListener("Content:LocationChange", this);
this._browser.messageManager.addMessageListener("Content:SecurityChange", this);
this._browser.messageManager.addMessageListener("Content:StatusChange", this);
}
RemoteWebProgressManager.prototype = {
get topLevelWebProgress() {
return this._topLevelWebProgress;
},
_destroy: function WP_Destroy() {
this._browser = null;
},
get isLoadingDocument() { return this._isLoadingDocument },
get DOMWindow() { return this._DOMWindow; },
get DOMWindowID() { return 0; },
get isTopLevel() {
// When this object is accessed directly, it's usually obtained
// through browser.webProgress and thus represents the top-level
// document.
// However, during message handling it temporarily represents
// the webProgress that generated the notification, which may or
// may not be a toplevel frame.
return this._isTopLevel === null ? true : this._isTopLevel;
},
get loadType() { return this._loadType; },
addProgressListener: function WP_AddProgressListener (aListener) {
addProgressListener: function (aListener) {
let listener = aListener.QueryInterface(Ci.nsIWebProgressListener);
this._progressListeners.push(listener);
},
removeProgressListener: function WP_RemoveProgressListener (aListener) {
removeProgressListener: function (aListener) {
this._progressListeners =
this._progressListeners.filter(function (l) l != aListener);
this._progressListeners.filter(l => l != aListener);
},
_uriSpec: function (spec) {
if (!spec)
return null;
return new RemoteWebProgressRequest(spec);
_fixSSLStatusAndState: function (aStatus, aState) {
let deserialized = null;
if (aStatus) {
let helper = Cc["@mozilla.org/network/serialization-helper;1"]
.getService(Components.interfaces.nsISerializationHelper);
deserialized = helper.deserializeObject(aStatus)
deserialized.QueryInterface(Ci.nsISSLStatus);
}
// We must check the Extended Validation (EV) state here, on the chrome
// process, because NSS is needed for that determination.
if (deserialized && deserialized.isExtendedValidation)
aState |= Ci.nsIWebProgressListener.STATE_IDENTITY_EV_TOPLEVEL;
return [deserialized, aState];
},
receiveMessage: function WP_ReceiveMessage(aMessage) {
this._isLoadingDocument = aMessage.json.isLoadingDocument;
this._DOMWindow = aMessage.objects.DOMWindow;
this._isTopLevel = aMessage.json.isTopLevel;
this._loadType = aMessage.json.loadType;
receiveMessage: function (aMessage) {
let json = aMessage.json;
let objects = aMessage.objects;
this._browser._contentWindow = aMessage.objects.contentWindow;
// The top-level WebProgress is always the same, but because we don't
// really have a concept of subframes/content we always creat a new object
// for those.
let webProgress = json.isTopLevel ? this._topLevelWebProgress
: new RemoteWebProgress(this, false);
// The WebProgressRequest object however is always dynamic.
let request = json.requestURI ? new RemoteWebProgressRequest(json.requestURI)
: null;
// Update the actual WebProgress fields.
webProgress._isLoadingDocument = json.isLoadingDocument;
webProgress._DOMWindow = objects.DOMWindow;
webProgress._loadType = json.loadType;
if (json.isTopLevel)
this._browser._contentWindow = objects.contentWindow;
let req = this._uriSpec(aMessage.json.requestURI);
switch (aMessage.name) {
case "Content:StateChange":
for each (let p in this._progressListeners) {
p.onStateChange(this, req, aMessage.json.stateFlags, aMessage.json.status);
for (let p of this._progressListeners) {
p.onStateChange(webProgress, request, json.stateFlags, json.status);
}
break;
case "Content:LocationChange":
let location = newURI(aMessage.json.location);
let location = newURI(json.location);
if (aMessage.json.isTopLevel) {
if (json.isTopLevel) {
this._browser.webNavigation._currentURI = location;
this._browser.webNavigation.canGoBack = aMessage.json.canGoBack;
this._browser.webNavigation.canGoForward = aMessage.json.canGoForward;
this._browser._characterSet = aMessage.json.charset;
this._browser._documentURI = newURI(aMessage.json.documentURI);
this._browser.webNavigation.canGoBack = json.canGoBack;
this._browser.webNavigation.canGoForward = json.canGoForward;
this._browser._characterSet = json.charset;
this._browser._documentURI = newURI(json.documentURI);
this._browser._imageDocument = null;
}
for each (let p in this._progressListeners) {
p.onLocationChange(this, req, location);
for (let p of this._progressListeners) {
p.onLocationChange(webProgress, request, location);
}
break;
case "Content:SecurityChange":
let [status, state] = this._fixSSLStatusAndState(json.status, json.state);
if (json.isTopLevel) {
// Invoking this getter triggers the generation of the underlying object,
// which we need to access with ._securityUI, because .securityUI returns
// a wrapper that makes _update inaccessible.
void this._browser.securityUI;
this._browser._securityUI._update(aMessage.json.state, aMessage.json.status);
this._browser._securityUI._update(status, state);
}
// The state passed might not be correct due to checks performed
// on the chrome side. _update fixes that.
for each (let p in this._progressListeners) {
p.onSecurityChange(this, req, this._browser.securityUI.state);
for (let p of this._progressListeners) {
p.onSecurityChange(webProgress, request, state);
}
break;
case "Content:StatusChange":
for each (let p in this._progressListeners) {
p.onStatusChange(this, req, aMessage.json.status, aMessage.json.message);
for (let p of this._progressListeners) {
p.onStatusChange(webProgress, request, json.status, json.message);
}
break;
}
this._isTopLevel = null;
}
};

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

@ -105,7 +105,6 @@
#include "mozilla/CycleCollectedJSRuntime.h"
#include "nsCycleCollectionParticipant.h"
#include "nsCycleCollectionNoteRootCallback.h"
#include "nsBaseHashtable.h"
#include "nsHashKeys.h"
#include "nsDeque.h"
#include "nsCycleCollector.h"
@ -841,7 +840,7 @@ public:
};
static bool
AddPurpleRoot(GCGraphBuilder &builder, void *root, nsCycleCollectionParticipant *cp);
AddPurpleRoot(GCGraphBuilder &aBuilder, void *aRoot, nsCycleCollectionParticipant *aParti);
struct SelectPointersVisitor
{
@ -893,6 +892,7 @@ class nsCycleCollector
friend class GCGraphBuilder;
bool mCollectionInProgress;
// mScanInProgress should be false when we're collecting white objects.
bool mScanInProgress;
nsCycleCollectorResults *mResults;
TimeStamp mCollectionStart;
@ -936,16 +936,17 @@ public:
void SetBeforeUnlinkCallback(CC_BeforeUnlinkCallback aBeforeUnlinkCB)
{
CheckThreadSafety();
mBeforeUnlinkCB = aBeforeUnlinkCB;
}
void SetForgetSkippableCallback(CC_ForgetSkippableCallback aForgetSkippableCB)
{
CheckThreadSafety();
mForgetSkippableCB = aForgetSkippableCB;
}
void SelectPurple(GCGraphBuilder &builder);
void MarkRoots(GCGraphBuilder &builder);
void MarkRoots(GCGraphBuilder &aBuilder);
void ScanRoots();
void ScanWeakMaps();
@ -978,7 +979,7 @@ public:
void CleanupAfterCollection();
// Start and finish an individual collection.
bool BeginCollection(ccType aCCType, nsICycleCollectorListener *aListener);
void BeginCollection(ccType aCCType, nsICycleCollectorListener *aListener);
bool FinishCollection(nsICycleCollectorListener *aListener);
bool FreeSnowWhite(bool aUntilNoSWInPurpleBuffer);
@ -1563,7 +1564,6 @@ public:
nsICycleCollectorListener *aListener,
bool aMergeZones);
~GCGraphBuilder();
bool Initialized();
bool WantAllTraces() const
{
@ -1657,8 +1657,7 @@ GCGraphBuilder::GCGraphBuilder(nsCycleCollector *aCollector,
{
if (!PL_DHashTableInit(&mPtrToNodeMap, &PtrNodeOps, nullptr,
sizeof(PtrToNodeEntry), 32768)) {
mPtrToNodeMap.ops = nullptr;
mRanOutOfMemory = true;
MOZ_CRASH();
}
if (aJSRuntime) {
@ -1691,12 +1690,6 @@ GCGraphBuilder::~GCGraphBuilder()
PL_DHashTableFinish(&mPtrToNodeMap);
}
bool
GCGraphBuilder::Initialized()
{
return !!mPtrToNodeMap.ops;
}
PtrInfo*
GCGraphBuilder::AddNode(void *s, nsCycleCollectionParticipant *aParticipant)
{
@ -1896,12 +1889,12 @@ GCGraphBuilder::NoteWeakMapping(void *map, void *key, void *kdelegate, void *val
}
static bool
AddPurpleRoot(GCGraphBuilder &builder, void *root, nsCycleCollectionParticipant *cp)
AddPurpleRoot(GCGraphBuilder &aBuilder, void *aRoot, nsCycleCollectionParticipant *aParti)
{
CanonicalizeParticipant(&root, &cp);
CanonicalizeParticipant(&aRoot, &aParti);
if (builder.WantAllTraces() || !cp->CanSkipInCC(root)) {
PtrInfo *pinfo = builder.AddNode(root, cp);
if (aBuilder.WantAllTraces() || !aParti->CanSkipInCC(aRoot)) {
PtrInfo *pinfo = aBuilder.AddNode(aRoot, aParti);
if (!pinfo) {
return false;
}
@ -2020,7 +2013,7 @@ public:
}
}
bool HasSnowWhiteObjects()
bool HasSnowWhiteObjects() const
{
return mObjects.Length() > 0;
}
@ -2099,6 +2092,8 @@ nsPurpleBuffer::RemoveSkippable(nsCycleCollector* aCollector,
bool
nsCycleCollector::FreeSnowWhite(bool aUntilNoSWInPurpleBuffer)
{
CheckThreadSafety();
bool hadSnowWhiteObjects = false;
do {
SnowWhiteKiller visitor(mPurpleBuf.Count());
@ -2112,16 +2107,11 @@ nsCycleCollector::FreeSnowWhite(bool aUntilNoSWInPurpleBuffer)
return hadSnowWhiteObjects;
}
void
nsCycleCollector::SelectPurple(GCGraphBuilder &builder)
{
mPurpleBuf.SelectPointers(builder);
}
void
nsCycleCollector::ForgetSkippable(bool aRemoveChildlessNodes,
bool aAsyncSnowWhiteFreeing)
{
CheckThreadSafety();
if (mJSRuntime) {
mJSRuntime->PrepareForForgetSkippable();
}
@ -2130,23 +2120,25 @@ nsCycleCollector::ForgetSkippable(bool aRemoveChildlessNodes,
}
MOZ_NEVER_INLINE void
nsCycleCollector::MarkRoots(GCGraphBuilder &builder)
nsCycleCollector::MarkRoots(GCGraphBuilder &aBuilder)
{
mGraph.mRootCount = builder.Count();
mGraph.mRootCount = aBuilder.Count();
// read the PtrInfo out of the graph that we are building
NodePool::Enumerator queue(mGraph.mNodes);
while (!queue.IsDone()) {
PtrInfo *pi = queue.GetNext();
CC_AbortIfNull(pi);
builder.Traverse(pi);
if (queue.AtBlockEnd())
builder.SetLastChild();
aBuilder.Traverse(pi);
if (queue.AtBlockEnd()) {
aBuilder.SetLastChild();
}
}
if (mGraph.mRootCount > 0) {
aBuilder.SetLastChild();
}
if (mGraph.mRootCount > 0)
builder.SetLastChild();
if (builder.RanOutOfMemory()) {
if (aBuilder.RanOutOfMemory()) {
NS_ASSERTION(false,
"Ran out of memory while building cycle collector graph");
Telemetry::Accumulate(Telemetry::CYCLE_COLLECTOR_OOM, true);
@ -2596,10 +2588,6 @@ nsCycleCollector::FixGrayBits(bool aForceGC)
}
TimeLog timeLog;
// mJSRuntime->Collect() must be called from the main thread,
// because it invokes XPCJSRuntime::GCCallback(cx, JSGC_BEGIN)
// which returns false if not in the main thread.
mJSRuntime->Collect(aForceGC ? JS::gcreason::SHUTDOWN_CC : JS::gcreason::CC_FORCED);
timeLog.Checkpoint("GC()");
}
@ -2685,10 +2673,11 @@ nsCycleCollector::ShutdownCollect(nsICycleCollectorListener *aListener)
if (aListener && NS_FAILED(aListener->Begin()))
aListener = nullptr;
FreeSnowWhite(true);
if (!(BeginCollection(ShutdownCC, aListener) &&
FinishCollection(aListener)))
BeginCollection(ShutdownCC, aListener);
if (!FinishCollection(aListener)) {
break;
}
}
CleanupAfterCollection();
}
@ -2720,10 +2709,7 @@ nsCycleCollector::Collect(ccType aCCType,
aListener = nullptr;
}
if (!BeginCollection(aCCType, aListener)) {
return;
}
BeginCollection(aCCType, aListener);
FinishCollection(aListener);
CleanupAfterCollection();
}
@ -2763,7 +2749,7 @@ nsCycleCollector::ShouldMergeZones(ccType aCCType)
}
}
bool
void
nsCycleCollector::BeginCollection(ccType aCCType,
nsICycleCollectorListener *aListener)
{
@ -2777,11 +2763,6 @@ nsCycleCollector::BeginCollection(ccType aCCType,
GCGraphBuilder builder(this, mGraph, mJSRuntime, aListener,
mergeZones);
if (!builder.Initialized()) {
NS_ASSERTION(false, "Failed to initialize GCGraphBuilder, will probably leak.");
Telemetry::Accumulate(Telemetry::CYCLE_COLLECTOR_OOM, true);
return false;
}
if (mJSRuntime) {
mJSRuntime->BeginCycleCollection(builder);
@ -2789,9 +2770,8 @@ nsCycleCollector::BeginCollection(ccType aCCType,
}
mScanInProgress = true;
SelectPurple(builder);
timeLog.Checkpoint("SelectPurple()");
mPurpleBuf.SelectPointers(builder);
timeLog.Checkpoint("SelectPointers()");
if (builder.Count() > 0) {
// The main Bacon & Rajan collection algorithm.
@ -2821,8 +2801,6 @@ nsCycleCollector::BeginCollection(ccType aCCType,
} else {
mScanInProgress = false;
}
return true;
}
bool
@ -2842,12 +2820,15 @@ nsCycleCollector::FinishCollection(nsICycleCollectorListener *aListener)
uint32_t
nsCycleCollector::SuspectedCount()
{
CheckThreadSafety();
return mPurpleBuf.Count();
}
void
nsCycleCollector::Shutdown()
{
CheckThreadSafety();
// Always delete snow white objects.
FreeSnowWhite(true);
@ -3214,7 +3195,6 @@ nsCycleCollector_shutdown()
if (data) {
MOZ_ASSERT(data->mCollector);
PROFILER_LABEL("CC", "nsCycleCollector_shutdown");
data->mCollector->CheckThreadSafety();
data->mCollector->Shutdown();
delete data->mCollector;
data->mCollector = nullptr;