Merge m-c to fx-team.

This commit is contained in:
Ryan VanderMeulen 2013-08-23 17:53:27 -04:00
commit 9888e14228
145 changed files with 2000 additions and 743 deletions

View File

@ -1,4 +1,4 @@
{
"revision": "a96d83d7e0bbd6b3fb8ecb78712c924ba8094659",
"revision": "4f6313014c286e7940eb23dc8637395dc1eb0bd7",
"repo_path": "/integration/gaia-central"
}

View File

@ -218,7 +218,7 @@ class Automation(object):
startupinfo=None,
creationflags=0):
args = automationutils.wrapCommand(args)
print "args: %s" % args
_log.info("INFO | automation.py | Launching: %s", subprocess.list2cmdline(args))
subprocess.Popen.__init__(self, args, bufsize, executable,
stdin, stdout, stderr,
preexec_fn, close_fds,

View File

@ -48,6 +48,22 @@ public interface Actions {
*/
void sendGeckoEvent(String geckoEvent, String data);
/**
* Sends a preferences get event to Gecko.
*
* @param requestId The id of this request.
* @param prefNames The preferences being requested.
*/
void sendPreferencesGetEvent(int requestId, String[] prefNames);
/**
* Sends a preferences observe event to Gecko.
*
* @param requestId The id of this request.
* @param prefNames The preferences being requested.
*/
void sendPreferencesObserveEvent(int requestId, String[] prefNames);
/**
* Listens for a gecko event to be sent from the Gecko instance.
* The returned object can be used to test if the event has been

View File

@ -71,11 +71,13 @@ public class FennecMochitestAssert implements Assert {
public String mName;
public String mDiag;
public boolean mTodo;
public testInfo(boolean r, String n, String d, boolean t) {
public boolean mInfo;
public testInfo(boolean r, String n, String d, boolean t, boolean i) {
mResult = r;
mName = n;
mDiag = d;
mTodo = t;
mInfo = i;
}
}
@ -96,7 +98,9 @@ public class FennecMochitestAssert implements Assert {
String message = Integer.toString(mLineNumber++) + " INFO " + resultString + " | " + mLogTestName + " | " + diag;
dumpLog(message);
if (test.mTodo) {
if (test.mInfo) {
// do not count TEST-INFO messages
} else if (test.mTodo) {
mTodo++;
} else if (isError) {
mFailed++;
@ -132,7 +136,7 @@ public class FennecMochitestAssert implements Assert {
}
public void ok(boolean condition, String name, String diag) {
testInfo test = new testInfo(condition, name, diag, false);
testInfo test = new testInfo(condition, name, diag, false, false);
_logMochitestResult(test, "TEST-PASS", "TEST-UNEXPECTED-FAIL");
mTestList.add(test);
}
@ -189,7 +193,7 @@ public class FennecMochitestAssert implements Assert {
}
public void todo(boolean condition, String name, String diag) {
testInfo test = new testInfo(condition, name, diag, true);
testInfo test = new testInfo(condition, name, diag, true, false);
_logMochitestResult(test, "TEST-UNEXPECTED-PASS", "TEST-KNOWN-FAIL");
mTestList.add(test);
}
@ -242,7 +246,7 @@ public class FennecMochitestAssert implements Assert {
}
public void info(String name, String message) {
testInfo test = new testInfo(true, name, message, false);
testInfo test = new testInfo(true, name, message, false, true);
_logMochitestResult(test, "TEST-INFO", "INFO FAILED?");
}
}

View File

@ -44,6 +44,8 @@ public class FennecNativeActions implements Actions {
private Method mRegisterEventListener;
private Method mUnregisterEventListener;
private Method mBroadcastEvent;
private Method mPreferencesGetEvent;
private Method mPreferencesObserveEvent;
private Method mSetDrawListener;
private Method mQuerySql;
private Object mRobocopApi;
@ -66,6 +68,8 @@ public class FennecNativeActions implements Actions {
mRegisterEventListener = mApiClass.getMethod("registerEventListener", String.class, mEventListenerClass);
mUnregisterEventListener = mApiClass.getMethod("unregisterEventListener", String.class, mEventListenerClass);
mBroadcastEvent = mApiClass.getMethod("broadcastEvent", String.class, String.class);
mPreferencesGetEvent = mApiClass.getMethod("preferencesGetEvent", Integer.TYPE, String[].class);
mPreferencesObserveEvent = mApiClass.getMethod("preferencesObserveEvent", Integer.TYPE, String[].class);
mSetDrawListener = mApiClass.getMethod("setDrawListener", mDrawListenerClass);
mQuerySql = mApiClass.getMethod("querySql", String.class, String.class);
@ -265,6 +269,24 @@ public class FennecNativeActions implements Actions {
}
}
private void sendPreferencesEvent(Method method, int requestId, String[] prefNames) {
try {
method.invoke(mRobocopApi, requestId, prefNames);
} catch (IllegalAccessException e) {
FennecNativeDriver.log(LogLevel.ERROR, e);
} catch (InvocationTargetException e) {
FennecNativeDriver.log(LogLevel.ERROR, e);
}
}
public void sendPreferencesGetEvent(int requestId, String[] prefNames) {
sendPreferencesEvent(mPreferencesGetEvent, requestId, prefNames);
}
public void sendPreferencesObserveEvent(int requestId, String[] prefNames) {
sendPreferencesEvent(mPreferencesObserveEvent, requestId, prefNames);
}
class DrawListenerProxy implements InvocationHandler {
private final PaintExpecter mPaintExpecter;

View File

@ -8,9 +8,7 @@
#include "nsIDOMNodeList.h"
#include "nsWrapperCache.h"
class nsINode;
class nsIContent;
#include "nsIContent.h"
// IID for the nsINodeList interface
#define NS_INODELIST_IID \

View File

@ -23,12 +23,6 @@ class nsIAtom;
class nsINodeInfo;
class nsIDocument;
namespace mozilla {
namespace dom {
class Element;
} // namespace dom
} // namespace mozilla
/**
* Structure used as a key for caching Attrs in nsDOMAttributeMap's mAttributeCache.
*/
@ -211,5 +205,9 @@ private:
already_AddRefed<Attr> RemoveAttribute(nsINodeInfo* aNodeInfo);
};
// XXX khuey yes this is crazy. The bindings code needs to see this include,
// but if we pull it in at the top of the file we get a circular include
// problem.
#include "mozilla/dom/Element.h"
#endif /* nsDOMAttributeMap_h */

View File

@ -14,6 +14,7 @@
#include "nsIURI.h"
#include "nsIHttpChannel.h"
#include "nsIDocument.h"
#include "nsIContent.h"
#include "nsIStreamListener.h"
#include "nsWeakReference.h"
#include "jsapi.h"

View File

@ -19,8 +19,8 @@
#include "nsIHTMLCollection.h"
#include "nsHashKeys.h"
#include "nsRefPtrHashtable.h"
#include "nsGenericHTMLElement.h"
class nsGenericHTMLElement;
class nsIDocument;
class nsINode;

View File

@ -11,8 +11,8 @@
#include "mozilla/Attributes.h"
#include "mozilla/ErrorResult.h"
#include "nsWrapperCache.h"
#include "nsSVGElement.h"
class nsSVGElement;
class nsSVGViewBox;
namespace mozilla {

View File

@ -11,8 +11,7 @@
#include "nsAutoPtr.h"
#include "nsCycleCollectionParticipant.h"
#include "mozilla/ErrorResult.h"
class nsSVGElement;
#include "nsSVGElement.h"
namespace mozilla {
// Alignment Types

View File

@ -549,9 +549,15 @@ nsXULElement::IsFocusable(int32_t *aTabIndex, bool aWithMouse)
bool shouldFocus = false;
#ifdef XP_MACOSX
// on Mac, mouse interactions only focus the element if it's a list
if (aWithMouse && IsNonList(mNodeInfo))
// on Mac, mouse interactions only focus the element if it's a list,
// or if it's a remote target, since the remote target must handle
// the focus.
if (aWithMouse &&
IsNonList(mNodeInfo) &&
!nsEventStateManager::IsRemoteTarget(this))
{
return false;
}
#endif
nsCOMPtr<nsIDOMXULControlElement> xulControl = do_QueryObject(this);

View File

@ -69,6 +69,12 @@ this.PermissionsTable = { geolocation: {
certified: ALLOW_ACTION,
access: ["read"]
},
"device-storage:crashes": {
app: DENY_ACTION,
privileged: DENY_ACTION,
certified: ALLOW_ACTION,
access: ["read"]
},
"device-storage:pictures": {
app: DENY_ACTION,
privileged: PROMPT_ACTION,

View File

@ -16,10 +16,10 @@
#include "nsCycleCollectionParticipant.h"
#include "nsWrapperCache.h"
#include "nsAutoPtr.h"
#include "nsPIDOMWindow.h"
class nsGlobalWindow;
class nsIWebBrowserChrome;
class nsPIDOMWindow;
namespace mozilla {

View File

@ -11,13 +11,13 @@
class nsIDOMCRMFObject;
#endif
#include "nsPIDOMWindow.h"
#include "nsWrapperCache.h"
#include "mozilla/dom/TypedArray.h"
#define NS_DOMCRYPTO_CID \
{0x929d9320, 0x251e, 0x11d4, { 0x8a, 0x7c, 0x00, 0x60, 0x08, 0xc8, 0x44, 0xc3} }
class nsPIDOMWindow;
namespace mozilla {
class ErrorResult;

View File

@ -11,8 +11,7 @@
#include "nsWrapperCache.h"
#include "nsCOMPtr.h"
#include "nsString.h"
class nsPIDOMWindow;
#include "nsPIDOMWindow.h"
namespace mozilla {

View File

@ -102,9 +102,6 @@ nsDOMScriptObjectFactory::Observe(nsISupports *aSubject,
if (cache)
cache->Flush();
#endif
nsGlobalWindow::ShutDown();
nsDOMClassInfo::ShutDown();
}
return NS_OK;

View File

@ -12,8 +12,8 @@
#include "nsWrapperCache.h"
#include "nsIWeakReferenceUtils.h"
#include "nsAutoPtr.h"
#include "nsPIDOMWindow.h"
class nsPIDOMWindow;
class nsMimeType;
class nsPluginElement;

View File

@ -11,9 +11,9 @@
#include "nsWrapperCache.h"
#include "nsDOMNavigationTiming.h"
#include "nsContentUtils.h"
#include "nsIDOMWindow.h"
class nsITimedChannel;
class nsIDOMWindow;
class nsPerformance;
class JSObject;
struct JSContext;

View File

@ -6097,9 +6097,11 @@ class CGUnionStruct(CGThing):
if self.type.hasNullableType:
enumValues.append("eNull")
methods.append(ClassMethod("IsNull", "bool", [], const=True, inline=True,
body="return mType == eNull;"))
body="return mType == eNull;",
bodyInHeader=True))
methods.append(ClassMethod("SetNull", "void", [], inline=True,
body="mType = eNull;"))
body="mType = eNull;",
bodyInHeader=True))
destructorCases.append(CGCase("eNull", None))
toJSValCases.append(CGCase("eNull", CGGeneric("rval.setNull();\n"
"return true;")))
@ -8618,6 +8620,26 @@ class CGBindingRoot(CGThing):
jsImplemented = config.getDescriptors(webIDLFile=webIDLFile,
isJSImplemented=True)
# Python can't modify closed-over variables directly, so sneak
# our mutable value in as an entry in a dictionary.
needsDOMQS = { "value": any(d.hasXPConnectImpls for d in descriptors) }
# Only mainthread things can have hasXPConnectImpls
provider = config.getDescriptorProvider(False)
def checkForXPConnectImpls(type, descriptor=None, dictionary=None):
if needsDOMQS["value"]:
return
type = type.unroll()
if not type.isInterface() or not type.isGeckoInterface():
return
try:
typeDesc = provider.getDescriptor(type.inner.identifier.name)
except NoSuchDescriptorError:
return
needsDOMQS["value"] = typeDesc.hasXPConnectImpls
callForEachType(descriptors + callbackDescriptors, dictionaries,
mainCallbacks, checkForXPConnectImpls)
descriptorsWithPrototype = filter(lambda d: d.interface.hasInterfacePrototypeObject(),
descriptors)
traitsClasses = [CGPrototypeTraitsClass(d) for d in descriptorsWithPrototype]
@ -8703,9 +8725,6 @@ class CGBindingRoot(CGThing):
'mozilla/dom/Nullable.h',
'PrimitiveConversions.h',
'WrapperFactory.h',
# Have to include nsDOMQS.h to get fast arg unwrapping
# for old-binding things with castability.
'nsDOMQS.h'
] + (['WorkerPrivate.h',
'nsThreadUtils.h'] if hasWorkerStuff else [])
+ (['mozilla/Preferences.h'] if requiresPreferences else [])
@ -8714,6 +8733,8 @@ class CGBindingRoot(CGThing):
+ (['nsCxPusher.h'] if dictionaries else [])
+ (['AccessCheck.h'] if hasChromeOnly else [])
+ (['xpcprivate.h'] if isEventTarget else [])
+ (['nsPIDOMWindow.h'] if len(jsImplemented) != 0 else [])
+ (['nsDOMQS.h'] if needsDOMQS["value"] else [])
+ (['AtomList.h'] if requiresAtoms else []),
prefix,
curr,

View File

@ -20,8 +20,7 @@
#include "nsIDOMCameraManager.h"
#include "nsCycleCollectionParticipant.h"
#include "mozilla/Attributes.h"
class nsPIDOMWindow;
#include "nsPIDOMWindow.h"
namespace mozilla {
class ErrorResult;

View File

@ -21,6 +21,7 @@
#define DEVICESTORAGE_MUSIC "music"
#define DEVICESTORAGE_APPS "apps"
#define DEVICESTORAGE_SDCARD "sdcard"
#define DEVICESTORAGE_CRASHES "crashes"
namespace mozilla {
namespace dom {

View File

@ -181,9 +181,10 @@ public:
nsCOMPtr<nsIFile> pictures;
nsCOMPtr<nsIFile> videos;
nsCOMPtr<nsIFile> music;
nsCOMPtr<nsIFile> apps;
nsCOMPtr<nsIFile> sdcard;
#endif
nsCOMPtr<nsIFile> apps;
nsCOMPtr<nsIFile> crashes;
nsCOMPtr<nsIFile> temp;
};
@ -268,8 +269,9 @@ DeviceStorageTypeChecker::Check(const nsAString& aType, nsIDOMBlob* aBlob)
}
if (aType.EqualsLiteral(DEVICESTORAGE_APPS) ||
aType.EqualsLiteral(DEVICESTORAGE_SDCARD)) {
// Apps and sdcard have no restriction on mime types
aType.EqualsLiteral(DEVICESTORAGE_SDCARD) ||
aType.EqualsLiteral(DEVICESTORAGE_CRASHES)) {
// Apps, crashes and sdcard have no restriction on mime types
return true;
}
@ -282,8 +284,9 @@ DeviceStorageTypeChecker::Check(const nsAString& aType, nsIFile* aFile)
NS_ASSERTION(aFile, "Calling Check without a file");
if (aType.EqualsLiteral(DEVICESTORAGE_APPS) ||
aType.EqualsLiteral(DEVICESTORAGE_SDCARD)) {
// apps have no restrictions on what file extensions used.
aType.EqualsLiteral(DEVICESTORAGE_SDCARD) ||
aType.EqualsLiteral(DEVICESTORAGE_CRASHES)) {
// Apps, crashes and sdcard have no restrictions on what file extensions used.
return true;
}
@ -362,7 +365,8 @@ DeviceStorageTypeChecker::GetPermissionForType(const nsAString& aType,
!aType.EqualsLiteral(DEVICESTORAGE_VIDEOS) &&
!aType.EqualsLiteral(DEVICESTORAGE_MUSIC) &&
!aType.EqualsLiteral(DEVICESTORAGE_APPS) &&
!aType.EqualsLiteral(DEVICESTORAGE_SDCARD)) {
!aType.EqualsLiteral(DEVICESTORAGE_SDCARD) &&
!aType.EqualsLiteral(DEVICESTORAGE_CRASHES)) {
// unknown type
return NS_ERROR_FAILURE;
}
@ -402,11 +406,12 @@ bool
DeviceStorageTypeChecker::IsVolumeBased(const nsAString& aType)
{
#ifdef MOZ_WIDGET_GONK
// The apps aren't stored in the same place as the media, so
// The apps and crashes aren't stored in the same place as the media, so
// we only ever return a single apps object, and not an array
// with one per volume (as is the case for the remaining
// storage types).
return !aType.EqualsLiteral(DEVICESTORAGE_APPS);
return !aType.EqualsLiteral(DEVICESTORAGE_APPS) &&
!aType.EqualsLiteral(DEVICESTORAGE_CRASHES);
#else
return false;
#endif
@ -571,6 +576,9 @@ DeviceStorageFile::Init()
NS_ASSERTION(typeChecker, "DeviceStorageTypeChecker is null");
}
// Directories which don't depend on a volume should be calculated once
// here. Directories which depend on the root directory of a volume
// should be calculated in DeviceStorageFile::GetRootDirectoryForType.
static void
InitDirs()
{
@ -619,11 +627,17 @@ InitDirs()
getter_AddRefs(sDirs->music));
#endif
#ifdef MOZ_WIDGET_GONK
NS_NewLocalFile(NS_LITERAL_STRING("/data"),
false,
getter_AddRefs(sDirs->apps));
#else
dirService->Get(NS_APP_USER_PROFILE_50_DIR, NS_GET_IID(nsIFile),
getter_AddRefs(sDirs->apps));
if (sDirs->apps) {
sDirs->apps->AppendRelativeNativePath(NS_LITERAL_CSTRING("webapps"));
}
#endif
// Eventually, on desktop, we want to do something smarter -- for example,
// detect when an sdcard is inserted, and use that instead of this.
@ -634,6 +648,21 @@ InitDirs()
}
#endif // !MOZ_WIDGET_GONK
if (XRE_GetProcessType() == GeckoProcessType_Default) {
NS_GetSpecialDirectory("UAppData", getter_AddRefs(sDirs->crashes));
if (sDirs->crashes) {
sDirs->crashes->Append(NS_LITERAL_STRING("Crash Reports"));
}
} else {
// NS_GetSpecialDirectory("UAppData") fails in content processes because
// gAppData from toolkit/xre/nsAppRunner.cpp is not initialized.
#ifdef MOZ_WIDGET_GONK
NS_NewLocalFile(NS_LITERAL_STRING("/data/b2g/mozilla/Crash Reports"),
false,
getter_AddRefs(sDirs->crashes));
#endif
}
if (mozilla::Preferences::GetBool("device.storage.testing", false)) {
dirService->Get(NS_OS_TEMP_DIR, NS_GET_IID(nsIFile),
getter_AddRefs(sDirs->temp));
@ -663,6 +692,9 @@ DeviceStorageFile::GetFullPath(nsAString &aFullPath)
}
// Directories which don't depend on a volume should be calculated once
// in InitDirs. Directories which depend on the root directory of a volume
// should be calculated in this method.
void
DeviceStorageFile::GetRootDirectoryForType(const nsAString& aStorageType,
const nsAString& aStorageName,
@ -715,11 +747,7 @@ DeviceStorageFile::GetRootDirectoryForType(const nsAString& aStorageType,
// Apps directory
else if (aStorageType.EqualsLiteral(DEVICESTORAGE_APPS)) {
#ifdef MOZ_WIDGET_GONK
NS_NewLocalFile(NS_LITERAL_STRING("/data"), false, getter_AddRefs(f));
#else
f = sDirs->apps;
#endif
}
// default SDCard
@ -731,6 +759,11 @@ DeviceStorageFile::GetRootDirectoryForType(const nsAString& aStorageType,
#endif
}
// crash reports directory.
else if (aStorageType.EqualsLiteral(DEVICESTORAGE_CRASHES)) {
f = sDirs->crashes;
}
// in testing, we default all device storage types to a temp directory
if (f && mozilla::Preferences::GetBool("device.storage.testing", false)) {
f = sDirs->temp;
@ -2489,7 +2522,7 @@ nsDOMDeviceStorage::Init(nsPIDOMWindow* aWindow, const nsAString &aType,
// the 'apps' type is special. We only want this exposed
// if the caller has the "webapps-manage" permission.
if (aType.EqualsLiteral("apps")) {
if (aType.EqualsLiteral(DEVICESTORAGE_APPS)) {
nsCOMPtr<nsIPermissionManager> permissionManager
= do_GetService(NS_PERMISSIONMANAGER_CONTRACTID);
NS_ENSURE_TRUE(permissionManager, NS_ERROR_FAILURE);

View File

@ -88,7 +88,8 @@ TextEncoder::Encode(JSContext* aCx,
JSObject* outView = nullptr;
if (NS_SUCCEEDED(rv)) {
buf[dstLen] = '\0';
outView = CreateUint8Array(aCx, aObj, buf, dstLen);
outView = Uint8Array::Create(aCx, aObj, dstLen,
reinterpret_cast<uint8_t*>(buf.get()));
if (!outView) {
aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
return nullptr;

View File

@ -100,15 +100,6 @@ public:
const bool aStream,
ErrorResult& aRv);
protected:
JSObject*
CreateUint8Array(JSContext* aCx, JS::Handle<JSObject*> aObj,
char* aBuf, uint32_t aLen) const
{
return Uint8Array::Create(aCx, aObj, aLen,
reinterpret_cast<uint8_t*>(aBuf));
}
private:
nsCString mEncoding;
nsCOMPtr<nsIUnicodeEncoder> mEncoder;

View File

@ -134,7 +134,7 @@ RTCIceCandidate.prototype = {
__init: function(dict) {
this.candidate = dict.candidate;
this.sdpMid = dict.sdpMid;
this.sdpMLineIndex = ("sdpMLineIndex" in dict)? dict.sdpMLineIndex+1 : null;
this.sdpMLineIndex = ("sdpMLineIndex" in dict)? dict.sdpMLineIndex : null;
}
};
@ -691,7 +691,8 @@ RTCPeerConnection.prototype = {
this._queueOrRun({
func: this._getPC().addIceCandidate,
args: [cand.candidate, cand.sdpMid || "", cand.sdpMLineIndex],
args: [cand.candidate, cand.sdpMid || "",
(cand.sdpMLineIndex === null)? 0 : cand.sdpMLineIndex + 1],
wait: true
});
},

View File

@ -14,9 +14,9 @@
#include "mozilla/dom/PromiseBinding.h"
#include "nsWrapperCache.h"
#include "nsAutoPtr.h"
#include "nsPIDOMWindow.h"
struct JSContext;
class nsPIDOMWindow;
namespace mozilla {
namespace dom {

View File

@ -31,12 +31,12 @@
#include "nsIGeolocationProvider.h"
#include "nsIContentPermissionPrompt.h"
#include "nsIDOMWindow.h"
#include "DictionaryHelpers.h"
#include "PCOMContentPermissionRequestChild.h"
#include "mozilla/Attributes.h"
class nsGeolocationService;
class nsIDOMWindow;
namespace mozilla {
namespace dom {

View File

@ -19,6 +19,7 @@
#include "AudioManager.h"
#include "nsIObserverService.h"
#include "nsISettingsService.h"
#include "nsPrintfCString.h"
#include "mozilla/Hal.h"
@ -40,11 +41,12 @@ using namespace mozilla::dom::bluetooth;
#define LOG(args...) __android_log_print(ANDROID_LOG_INFO, "AudioManager" , ## args)
#define HEADPHONES_STATUS_CHANGED "headphones-status-changed"
#define HEADPHONES_STATUS_HEADSET NS_LITERAL_STRING("headset").get()
#define HEADPHONES_STATUS_HEADPHONE NS_LITERAL_STRING("headphone").get()
#define HEADPHONES_STATUS_OFF NS_LITERAL_STRING("off").get()
#define HEADPHONES_STATUS_UNKNOWN NS_LITERAL_STRING("unknown").get()
#define HEADPHONES_STATUS_CHANGED "headphones-status-changed"
#define MOZ_SETTINGS_CHANGE_ID "mozsettings-changed"
static void BinderDeadCallback(status_t aErr);
static void InternalSetAudioRoutes(SwitchState aState);
@ -105,6 +107,49 @@ public:
return NS_OK;
}
};
class AudioChannelVolInitCallback MOZ_FINAL : public nsISettingsServiceCallback
{
public:
NS_DECL_ISUPPORTS
AudioChannelVolInitCallback() {}
NS_IMETHOD Handle(const nsAString& aName, const JS::Value& aResult)
{
nsCOMPtr<nsIAudioManager> audioManager =
do_GetService(NS_AUDIOMANAGER_CONTRACTID);
NS_ENSURE_TRUE(JSVAL_IS_INT(aResult), NS_OK);
int32_t volIndex = JSVAL_TO_INT(aResult);
if (aName.EqualsLiteral("audio.volume.content")) {
audioManager->SetAudioChannelVolume(AUDIO_CHANNEL_CONTENT, volIndex);
} else if (aName.EqualsLiteral("audio.volume.notification")) {
audioManager->SetAudioChannelVolume(AUDIO_CHANNEL_NOTIFICATION,
volIndex);
} else if (aName.EqualsLiteral("audio.volume.alarm")) {
audioManager->SetAudioChannelVolume(AUDIO_CHANNEL_ALARM, volIndex);
} else if (aName.EqualsLiteral("audio.volume.telephony")) {
audioManager->SetAudioChannelVolume(AUDIO_CHANNEL_TELEPHONY, volIndex);
} else if (aName.EqualsLiteral("audio.volume.bt_sco")) {
static_cast<AudioManager *>(audioManager.get())->SetStreamVolumeIndex(
AUDIO_STREAM_BLUETOOTH_SCO, volIndex);
} else {
MOZ_ASSERT("unexpected audio channel for volume control");
}
return NS_OK;
}
NS_IMETHOD HandleError(const nsAString& aName)
{
LOG("AudioChannelVolInitCallback::HandleError: %s\n",
NS_ConvertUTF16toUTF8(aName).get());
return NS_OK;
}
};
NS_IMPL_ISUPPORTS1(AudioChannelVolInitCallback, nsISettingsServiceCallback)
} /* namespace gonk */
} /* namespace dom */
} /* namespace mozilla */
@ -245,7 +290,7 @@ AudioManager::Observe(nsISupports* aSubject,
// To process the volume control on each audio channel according to
// change of settings
else if (!strcmp(aTopic, "mozsettings-changed")) {
else if (!strcmp(aTopic, MOZ_SETTINGS_CHANGE_ID)) {
AutoSafeJSContext cx;
nsDependentString dataStr(aData);
JS::Rooted<JS::Value> val(cx);
@ -327,21 +372,6 @@ AudioManager::AudioManager() : mPhoneState(PHONE_STATE_CURRENT),
InternalSetAudioRoutes(GetCurrentSwitchState(SWITCH_HEADPHONES));
NotifyHeadphonesStatus(GetCurrentSwitchState(SWITCH_HEADPHONES));
nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
NS_ENSURE_TRUE_VOID(obs);
if (NS_FAILED(obs->AddObserver(this, BLUETOOTH_SCO_STATUS_CHANGED_ID, false))) {
NS_WARNING("Failed to add bluetooth sco status changed observer!");
}
if (NS_FAILED(obs->AddObserver(this, BLUETOOTH_A2DP_STATUS_CHANGED_ID, false))) {
NS_WARNING("Failed to add bluetooth a2dp status changed observer!");
}
if (NS_FAILED(obs->AddObserver(this, "mozsettings-changed", false))) {
NS_WARNING("Failed to add mozsettings-changed oberver!");
}
if (NS_FAILED(obs->AddObserver(this, BLUETOOTH_HFP_STATUS_CHANGED_ID, false))) {
NS_WARNING("Failed to add bluetooth hfp status changed observer!");
}
for (int loop = 0; loop < AUDIO_STREAM_CNT; loop++) {
AudioSystem::initStreamVolume(static_cast<audio_stream_type_t>(loop), 0,
sMaxStreamVolumeTbl[loop]);
@ -350,11 +380,41 @@ AudioManager::AudioManager() : mPhoneState(PHONE_STATE_CURRENT),
// Force publicnotification to output at maximal volume
SetStreamVolumeIndex(AUDIO_STREAM_ENFORCED_AUDIBLE,
sMaxStreamVolumeTbl[AUDIO_STREAM_ENFORCED_AUDIBLE]);
// Get the initial volume index from settings DB during boot up.
nsCOMPtr<nsISettingsService> settingsService =
do_GetService("@mozilla.org/settingsService;1");
NS_ENSURE_TRUE_VOID(settingsService);
nsCOMPtr<nsISettingsServiceLock> lock;
nsresult rv = settingsService->CreateLock(getter_AddRefs(lock));
NS_ENSURE_SUCCESS_VOID(rv);
nsCOMPtr<nsISettingsServiceCallback> callback = new AudioChannelVolInitCallback();
NS_ENSURE_TRUE_VOID(callback);
lock->Get("audio.volume.content", callback);
lock->Get("audio.volume.notification", callback);
lock->Get("audio.volume.alarm", callback);
lock->Get("audio.volume.telephony", callback);
lock->Get("audio.volume.bt_sco", callback);
// Gecko only control stream volume not master so set to default value
// directly.
AudioSystem::setMasterVolume(1.0);
AudioSystem::setErrorCallback(BinderDeadCallback);
nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
NS_ENSURE_TRUE_VOID(obs);
if (NS_FAILED(obs->AddObserver(this, BLUETOOTH_SCO_STATUS_CHANGED_ID, false))) {
NS_WARNING("Failed to add bluetooth sco status changed observer!");
}
if (NS_FAILED(obs->AddObserver(this, BLUETOOTH_A2DP_STATUS_CHANGED_ID, false))) {
NS_WARNING("Failed to add bluetooth a2dp status changed observer!");
}
if (NS_FAILED(obs->AddObserver(this, BLUETOOTH_HFP_STATUS_CHANGED_ID, false))) {
NS_WARNING("Failed to add bluetooth hfp status changed observer!");
}
if (NS_FAILED(obs->AddObserver(this, MOZ_SETTINGS_CHANGE_ID, false))) {
NS_WARNING("Failed to add mozsettings-changed observer!");
}
}
AudioManager::~AudioManager() {
@ -371,6 +431,9 @@ AudioManager::~AudioManager() {
if (NS_FAILED(obs->RemoveObserver(this, BLUETOOTH_HFP_STATUS_CHANGED_ID))) {
NS_WARNING("Failed to remove bluetooth hfp status changed observer!");
}
if (NS_FAILED(obs->RemoveObserver(this, MOZ_SETTINGS_CHANGE_ID))) {
NS_WARNING("Failed to remove mozsettings-changed observer!");
}
}
NS_IMETHODIMP

View File

@ -39,6 +39,7 @@ typedef Observer<SwitchEvent> SwitchObserver;
namespace dom {
namespace gonk {
class RecoverTask;
class AudioChannelVolInitCallback;
class AudioManager : public nsIAudioManager
, public nsIObserver
{
@ -53,6 +54,7 @@ public:
// When audio backend is dead, recovery task needs to read all volume
// settings then set back into audio backend.
friend class RecoverTask;
friend class AudioChannelVolInitCallback;
protected:
int32_t mPhoneState;

View File

@ -2487,6 +2487,7 @@ RadioInterface.prototype = {
this._updateCallingLineIdRestrictionPref(response.clirMode);
}
target.sendAsyncMessage("RIL:SetCallingLineIdRestriction", response);
return false;
}).bind(this));
},

36
gfx/gl/VBOArena.cpp Normal file
View File

@ -0,0 +1,36 @@
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "VBOArena.h"
using namespace mozilla::gl;
GLuint VBOArena::Allocate(GLContext *aGLContext)
{
if (!mAvailableVBOs.size()) {
GLuint vbo;
aGLContext->fGenBuffers(1, &vbo);
mAllocatedVBOs.push_back(vbo);
return vbo;
}
GLuint vbo = mAvailableVBOs.back();
mAvailableVBOs.pop_back();
return vbo;
}
void VBOArena::Reset()
{
mAvailableVBOs = mAllocatedVBOs;
}
void VBOArena::Flush(GLContext *aGLContext)
{
if (mAvailableVBOs.size()) {
#ifdef DEBUG
printf_stderr("VBOArena::Flush for %u VBOs\n", mAvailableVBOs.size());
#endif
aGLContext->fDeleteBuffers(mAvailableVBOs.size(), &mAvailableVBOs[0]);
}
}

33
gfx/gl/VBOArena.h Normal file
View File

@ -0,0 +1,33 @@
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef VBOARENA_H_
#define VBOARENA_H_
#include "GLContext.h"
#include <vector>
namespace mozilla {
namespace gl {
class VBOArena {
public:
// Allocate a new VBO.
GLuint Allocate(GLContext *aGLContext);
// Re-use previously allocated VBOs.
void Reset();
// Throw away all allocated VBOs.
void Flush(GLContext *aGLContext);
private:
std::vector<GLuint> mAllocatedVBOs;
std::vector<GLuint> mAvailableVBOs;
};
}
}
#endif

View File

@ -53,6 +53,7 @@ EXPORTS += [
'SurfaceFactory.h',
'SurfaceStream.h',
'SurfaceTypes.h',
'VBOArena.h',
]
if CONFIG['MOZ_X11']:
@ -112,6 +113,7 @@ CPP_SOURCES += [
'SharedSurfaceGL.cpp',
'SurfaceFactory.cpp',
'SurfaceStream.cpp',
'VBOArena.cpp',
]
FAIL_ON_WARNINGS = True

View File

@ -9,6 +9,7 @@
#include <stdlib.h> // for free, malloc
#include "FPSCounter.h" // for FPSState, FPSCounter
#include "GLContextProvider.h" // for GLContextProvider
#include "LayerManagerOGL.h" // for BUFFER_OFFSET
#include "Layers.h" // for WriteSnapshotToDumpFile
#include "gfx2DGlue.h" // for ThebesFilter
#include "gfx3DMatrix.h" // for gfx3DMatrix
@ -56,6 +57,51 @@ static inline IntSize ns2gfxSize(const nsIntSize& s) {
return IntSize(s.width, s.height);
}
// Draw the supplied geometry with the already selected shader. Both aArray1
// and aArray2 are expected to have a stride of 2 * sizeof(GLfloat).
static void
DrawWithVertexBuffer2(GLContext *aGLContext, VBOArena &aVBOs,
GLenum aMode, GLsizei aElements,
GLint aAttr1, GLfloat *aArray1,
GLint aAttr2, GLfloat *aArray2)
{
GLsizei bytes = aElements * 2 * sizeof(GLfloat);
aGLContext->fBindBuffer(LOCAL_GL_ARRAY_BUFFER,
aVBOs.Allocate(aGLContext));
aGLContext->fBufferData(LOCAL_GL_ARRAY_BUFFER,
2 * bytes,
nullptr,
LOCAL_GL_STREAM_DRAW);
aGLContext->fBufferSubData(LOCAL_GL_ARRAY_BUFFER,
0,
bytes,
aArray1);
aGLContext->fBufferSubData(LOCAL_GL_ARRAY_BUFFER,
bytes,
bytes,
aArray2);
aGLContext->fEnableVertexAttribArray(aAttr1);
aGLContext->fEnableVertexAttribArray(aAttr2);
aGLContext->fVertexAttribPointer(aAttr1,
2, LOCAL_GL_FLOAT,
LOCAL_GL_FALSE,
0, BUFFER_OFFSET(0));
aGLContext->fVertexAttribPointer(aAttr2,
2, LOCAL_GL_FLOAT,
LOCAL_GL_FALSE,
0, BUFFER_OFFSET(bytes));
aGLContext->fDrawArrays(aMode, 0, aElements);
aGLContext->fDisableVertexAttribArray(aAttr1);
aGLContext->fDisableVertexAttribArray(aAttr2);
aGLContext->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, 0);
}
void
FPSState::DrawFPS(TimeStamp aNow,
@ -98,6 +144,8 @@ FPSState::DrawFPS(TimeStamp aNow,
free(buf);
}
mVBOs.Reset();
struct Vertex2D {
float x,y;
};
@ -191,44 +239,21 @@ FPSState::DrawFPS(TimeStamp aNow,
copyprog->Activate();
copyprog->SetTextureUnit(0);
// we're going to use client-side vertex arrays for this.
context->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, 0);
// "COPY"
context->fBlendFuncSeparate(LOCAL_GL_ONE, LOCAL_GL_ZERO,
LOCAL_GL_ONE, LOCAL_GL_ZERO);
// enable our vertex attribs; we'll call glVertexPointer below
// to fill with the correct data.
GLint vcattr = copyprog->AttribLocation(ShaderProgramOGL::VertexCoordAttrib);
GLint tcattr = copyprog->AttribLocation(ShaderProgramOGL::TexCoordAttrib);
context->fEnableVertexAttribArray(vcattr);
context->fEnableVertexAttribArray(tcattr);
context->fVertexAttribPointer(vcattr,
2, LOCAL_GL_FLOAT,
LOCAL_GL_FALSE,
0, vertices);
context->fVertexAttribPointer(tcattr,
2, LOCAL_GL_FLOAT,
LOCAL_GL_FALSE,
0, texCoords);
context->fDrawArrays(LOCAL_GL_TRIANGLE_STRIP, 0, 12);
context->fVertexAttribPointer(vcattr,
2, LOCAL_GL_FLOAT,
LOCAL_GL_FALSE,
0, vertices2);
context->fVertexAttribPointer(tcattr,
2, LOCAL_GL_FLOAT,
LOCAL_GL_FALSE,
0, texCoords2);
context->fDrawArrays(LOCAL_GL_TRIANGLE_STRIP, 0, 12);
DrawWithVertexBuffer2(context, mVBOs,
LOCAL_GL_TRIANGLE_STRIP, 12,
vcattr, (GLfloat *) vertices,
tcattr, (GLfloat *) texCoords);
DrawWithVertexBuffer2(context, mVBOs,
LOCAL_GL_TRIANGLE_STRIP, 12,
vcattr, (GLfloat *) vertices2,
tcattr, (GLfloat *) texCoords2);
}
#ifdef CHECK_CURRENT_PROGRAM
@ -312,9 +337,17 @@ CompositorOGL::GetTemporaryTexture(GLenum aTextureUnit)
void
CompositorOGL::Destroy()
{
if (gl() && mTextures.Length() > 0) {
if (gl()) {
gl()->MakeCurrent();
gl()->fDeleteTextures(mTextures.Length(), &mTextures[0]);
if (mTextures.Length() > 0) {
gl()->fDeleteTextures(mTextures.Length(), &mTextures[0]);
}
mVBOs.Flush(gl());
if (mFPS) {
if (mFPS->mTexture > 0)
gl()->fDeleteTextures(1, &mFPS->mTexture);
mFPS->mVBOs.Flush(gl());
}
}
mTextures.SetLength(0);
if (!mDestroyed) {
@ -557,10 +590,6 @@ CompositorOGL::BindAndDrawQuadWithTextureRect(ShaderProgramOGL *aProg,
aProg->AttribLocation(ShaderProgramOGL::TexCoordAttrib);
NS_ASSERTION(texCoordAttribIndex != GLuint(-1), "no texture coords?");
// clear any bound VBO so that glVertexAttribPointer() goes back to
// "pointer mode"
mGLContext->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, 0);
// Given what we know about these textures and coordinates, we can
// compute fmod(t, 1.0f) to get the same texture coordinate out. If
// the texCoordRect dimension is < 0 or > width/height, then we have
@ -614,25 +643,10 @@ CompositorOGL::BindAndDrawQuadWithTextureRect(ShaderProgramOGL *aProg,
rects, flipped);
}
mGLContext->fVertexAttribPointer(vertAttribIndex, 2,
LOCAL_GL_FLOAT, LOCAL_GL_FALSE, 0,
rects.vertexPointer());
mGLContext->fVertexAttribPointer(texCoordAttribIndex, 2,
LOCAL_GL_FLOAT, LOCAL_GL_FALSE, 0,
rects.texCoordPointer());
{
mGLContext->fEnableVertexAttribArray(texCoordAttribIndex);
{
mGLContext->fEnableVertexAttribArray(vertAttribIndex);
mGLContext->fDrawArrays(LOCAL_GL_TRIANGLES, 0, rects.elements());
mGLContext->fDisableVertexAttribArray(vertAttribIndex);
}
mGLContext->fDisableVertexAttribArray(texCoordAttribIndex);
}
DrawWithVertexBuffer2(mGLContext, mVBOs,
LOCAL_GL_TRIANGLES, rects.elements(),
vertAttribIndex, rects.vertexPointer(),
texCoordAttribIndex, rects.texCoordPointer());
}
void
@ -769,6 +783,8 @@ CompositorOGL::BeginFrame(const Rect *aClipRectIn, const gfxMatrix& aTransform,
{
MOZ_ASSERT(!mFrameInProgress, "frame still in progress (should have called EndFrame or AbortFrame");
mVBOs.Reset();
mFrameInProgress = true;
gfxRect rect;
if (mUseExternalSurfaceSize) {

View File

@ -35,6 +35,8 @@
#include "nsTraceRefcnt.h" // for MOZ_COUNT_CTOR, etc
#include "nsXULAppAPI.h" // for XRE_GetProcessType
#include "nscore.h" // for NS_IMETHOD
#include "VBOArena.h" // for gl::VBOArena
class gfx3DMatrix;
class nsIWidget;
struct gfxMatrix;
@ -234,6 +236,11 @@ private:
* flipped and unflipped textures */
GLuint mQuadVBO;
/**
* When we can't use mQuadVBO, we allocate VBOs from this arena instead.
*/
gl::VBOArena mVBOs;
bool mHasBGRA;
/**

View File

@ -8,6 +8,7 @@
#include "GLDefs.h" // for GLuint
#include "mozilla/TimeStamp.h" // for TimeStamp, TimeDuration
#include "nsTArray.h" // for nsAutoTArray, nsTArray_Impl, etc
#include "VBOArena.h" // for gl::VBOArena
namespace mozilla {
namespace gl {
@ -70,6 +71,7 @@ struct FPSState {
GLuint mTexture;
FPSCounter mCompositionFps;
FPSCounter mTransactionFps;
gl::VBOArena mVBOs;
FPSState() : mTexture(0) { }

View File

@ -9,9 +9,10 @@
#include <gfxTypes.h>
#include <gfxPoint3D.h>
#include <gfxPointH3D.h>
#include <gfxMatrix.h>
#include <gfxQuad.h>
class gfxMatrix;
/**
* This class represents a 3D transformation. The matrix is laid
* out as follows:

View File

@ -7,6 +7,7 @@
#define GFX_QUAD_H
#include "gfxTypes.h"
#include "gfxRect.h"
#include "gfxLineSegment.h"
#include <algorithm>

View File

@ -239,8 +239,8 @@ jsd_GetValueFunctionId(JSDContext* jsdc, JSDValue* jsdval)
JSDValue*
jsd_NewValue(JSDContext* jsdc, jsval value)
{
JS::RootedValue val(jsdc->jsrt, value);
AutoSafeJSContext cx;
JS::RootedValue val(cx, value);
JSDValue* jsdval;
if(!(jsdval = (JSDValue*) calloc(1, sizeof(JSDValue))))
@ -309,8 +309,9 @@ jsd_GetValueWrappedJSVal(JSDContext* jsdc, JSDValue* jsdval)
return val;
}
static JSDProperty* _newProperty(JSDContext* jsdc, JSPropertyDesc* pd,
unsigned additionalFlags)
static JSDProperty* _newProperty(JSDContext* jsdc, JS::HandleValue propId,
JS::HandleValue propValue, JS::HandleValue propAlias,
uint8_t propFlags, unsigned additionalFlags)
{
JSDProperty* jsdprop;
@ -319,16 +320,16 @@ static JSDProperty* _newProperty(JSDContext* jsdc, JSPropertyDesc* pd,
JS_INIT_CLIST(&jsdprop->links);
jsdprop->nref = 1;
jsdprop->flags = pd->flags | additionalFlags;
jsdprop->flags = propFlags | additionalFlags;
if(!(jsdprop->name = jsd_NewValue(jsdc, pd->id)))
if(!(jsdprop->name = jsd_NewValue(jsdc, propId)))
goto new_prop_fail;
if(!(jsdprop->val = jsd_NewValue(jsdc, pd->value)))
if(!(jsdprop->val = jsd_NewValue(jsdc, propValue)))
goto new_prop_fail;
if((jsdprop->flags & JSDPD_ALIAS) &&
!(jsdprop->alias = jsd_NewValue(jsdc, pd->alias)))
!(jsdprop->alias = jsd_NewValue(jsdc, propAlias)))
goto new_prop_fail;
return jsdprop;
@ -374,9 +375,17 @@ static bool _buildProps(JSDContext* jsdc, JSDValue* jsdval)
return false;
}
JS::RootedValue propId(cx);
JS::RootedValue propValue(cx);
JS::RootedValue propAlias(cx);
uint8_t propFlags;
for(i = 0; i < pda.length; i++)
{
JSDProperty* prop = _newProperty(jsdc, &pda.array[i], 0);
propId = pda.array[i].id;
propValue = pda.array[i].value;
propAlias = pda.array[i].alias;
propFlags = pda.array[i].flags;
JSDProperty* prop = _newProperty(jsdc, propId, propValue, propAlias, propFlags, 0);
if(!prop)
{
_freeProps(jsdc, jsdval);
@ -462,19 +471,22 @@ jsd_IterateProperties(JSDContext* jsdc, JSDValue* jsdval, JSDProperty **iterp)
JSDProperty*
jsd_GetValueProperty(JSDContext* jsdc, JSDValue* jsdval, JSString* nameStr)
{
JS::RootedString name(jsdc->jsrt, nameStr);
AutoSafeJSContext cx;
JSAutoCompartment acBase(cx, jsdc->glob);
JSDProperty* jsdprop;
JSDProperty* iter = NULL;
JS::RootedObject obj(cx);
JS::RootedString name(cx, nameStr);
unsigned attrs = 0;
bool found;
JSPropertyDesc pd;
const jschar * nameChars;
size_t nameLen;
JS::RootedValue val(cx), nameval(cx);
JS::RootedId nameid(cx);
JS::RootedValue propId(cx);
JS::RootedValue propValue(cx);
JS::RootedValue propAlias(cx);
uint8_t propFlags;
if(!jsd_IsValueObject(jsdc, jsdval))
return NULL;
@ -513,37 +525,36 @@ jsd_GetValueProperty(JSDContext* jsdc, JSDValue* jsdval, JSString* nameStr)
{
if (JS_IsExceptionPending(cx))
{
if (!JS_GetPendingException(cx, &pd.value))
if (!JS_GetPendingException(cx, propValue.address()))
{
return NULL;
}
pd.flags = JSPD_EXCEPTION;
propFlags = JSPD_EXCEPTION;
}
else
{
pd.flags = JSPD_ERROR;
pd.value = JSVAL_VOID;
propFlags = JSPD_ERROR;
propValue = JSVAL_VOID;
}
}
else
{
pd.value = val;
propValue = val;
}
}
nameval = STRING_TO_JSVAL(name);
if (!JS_ValueToId(cx, nameval, nameid.address()) ||
!JS_IdToValue(cx, nameid, &pd.id)) {
!JS_IdToValue(cx, nameid, propId.address())) {
return NULL;
}
pd.spare = 0;
pd.alias = JSVAL_NULL;
pd.flags |= (attrs & JSPROP_ENUMERATE) ? JSPD_ENUMERATE : 0
propAlias = JSVAL_NULL;
propFlags |= (attrs & JSPROP_ENUMERATE) ? JSPD_ENUMERATE : 0
| (attrs & JSPROP_READONLY) ? JSPD_READONLY : 0
| (attrs & JSPROP_PERMANENT) ? JSPD_PERMANENT : 0;
return _newProperty(jsdc, &pd, JSDPD_HINTED);
return _newProperty(jsdc, propId, propValue, propAlias, propFlags, JSDPD_HINTED);
}
/*
@ -655,8 +666,8 @@ jsd_GetValueClassName(JSDContext* jsdc, JSDValue* jsdval)
jsval val = jsdval->val;
if(!jsdval->className && !JSVAL_IS_PRIMITIVE(val))
{
JS::RootedObject obj(jsdc->jsrt, JSVAL_TO_OBJECT(val));
AutoSafeJSContext cx;
JS::RootedObject obj(cx, JSVAL_TO_OBJECT(val));
JSAutoCompartment ac(cx, obj);
jsdval->className = JS_GetDebugClassName(obj);
}

View File

@ -897,12 +897,13 @@ jsdProperty::GetValue(jsdIValue **_rval)
NS_IMPL_ISUPPORTS2(jsdScript, jsdIScript, jsdIEphemeral)
static NS_IMETHODIMP
AssignToJSString(JSDContext *aCx, nsACString *x, JSString *str)
AssignToJSString(JSDContext *aCx, nsACString *x, JSString *str_)
{
if (!str) {
if (!str_) {
x->SetLength(0);
return NS_OK;
}
JS::RootedString str(JSD_GetJSRuntime(aCx), str_);
AutoSafeJSContext cx;
JSAutoCompartment ac(cx, JSD_GetDefaultGlobal(aCx)); // Just in case.
size_t length = JS_GetStringEncodingLength(cx, str);
@ -1261,7 +1262,7 @@ jsdScript::GetParameterNames(uint32_t* count, PRUnichar*** paramNames)
NS_IMETHODIMP
jsdScript::GetFunctionObject(jsdIValue **_rval)
{
JSFunction *fun = JSD_GetJSFunction(mCx, mScript);
JS::RootedFunction fun(JSD_GetJSRuntime(mCx), JSD_GetJSFunction(mCx, mScript));
if (!fun)
return NS_ERROR_NOT_AVAILABLE;
@ -2114,10 +2115,8 @@ NS_IMETHODIMP
jsdValue::GetJsType (uint32_t *_rval)
{
ASSERT_VALID_EPHEMERAL;
jsval val;
JS::RootedValue val(JSD_GetJSRuntime(mCx), JSD_GetValueWrappedJSVal (mCx, mValue));
val = JSD_GetValueWrappedJSVal (mCx, mValue);
if (JSVAL_IS_NULL(val))
*_rval = TYPE_NULL;
else if (JSVAL_IS_BOOLEAN(val))

View File

@ -337,8 +337,12 @@ endif
endif
DIST_GARBAGE = config.cache config.log config.status* \
config/autoconf.mk \
$(JS_CONFIG_NAME) js-config.h js-confdefs.h
config/autoconf.mk config/emptyvars.mk \
$(JS_CONFIG_NAME) js-config.h js-confdefs.h \
backend.mk config/backend.mk devtools/backend.mk editline/backend.mk \
gdb/backend.mk jsapi-tests/backend.mk shell/backend.mk tests/backend.mk \
backend.RecursiveMakeBackend.built backend.RecursiveMakeBackend.built.pp \
devtools/rootAnalysis/Makefile
distclean::
$(RM) $(DIST_GARBAGE)
@ -665,3 +669,30 @@ endif
#
# END kludges for the Nitro assembler
###############################################
###############################################
# Generating source package tarballs
# (only possible when tar is found)
ifneq (,$(TAR))
source-package:
SRCDIR=$(srcdir) \
DIST=$(DIST) \
MAKE=$(MAKE) \
MKDIR=$(MKDIR) \
TAR=$(TAR) \
MOZJS_MAJOR_VERSION=$(MOZJS_MAJOR_VERSION) \
MOZJS_MINOR_VERSION=$(MOZJS_MINOR_VERSION) \
MOZJS_PATCH_VERSION=$(MOZJS_PATCH_VERSION) \
MOZJS_ALPHA=$(MOZJS_ALPHA) \
$(srcdir)/make-source-package.sh
clean::
DIST=$(DIST) \
MOZJS_MAJOR_VERSION=$(MOZJS_MAJOR_VERSION) \
MOZJS_MINOR_VERSION=$(MOZJS_MINOR_VERSION) \
MOZJS_PATCH_VERSION=$(MOZJS_PATCH_VERSION) \
MOZJS_ALPHA=$(MOZJS_ALPHA) \
$(srcdir)/make-source-package.sh clean
endif

View File

@ -87,8 +87,8 @@ obj_propertyIsEnumerable(JSContext *cx, unsigned argc, Value *vp)
}
#if JS_HAS_TOSOURCE
static bool
obj_toSource(JSContext *cx, unsigned argc, Value *vp)
bool
js::obj_toSource(JSContext *cx, unsigned argc, Value *vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
JS_CHECK_RECURSION(cx, return false);

View File

@ -14,10 +14,14 @@ namespace js {
extern const JSFunctionSpec object_methods[];
extern const JSFunctionSpec object_static_methods[];
/* Object constructor native. Exposed only so the JIT can know its address. */
// Object constructor native. Exposed only so the JIT can know its address.
extern bool
obj_construct(JSContext *cx, unsigned argc, js::Value *vp);
// Object.prototype.toSource. Exposed so that Function.prototype.toSource can chain up.
extern bool
obj_toSource(JSContext *cx, unsigned argc, js::Value *vp);
} /* namespace js */
#endif /* builtin_Object_h */

View File

@ -571,6 +571,14 @@ dnl ========================================================
AC_PROG_INSTALL
AC_PROG_LN_S
AC_MSG_CHECKING([for tar archiver])
AC_CHECK_PROGS(TAR, gnutar gtar tar, "")
if test -z "$TAR"; then
AC_MSG_WARN([no tar archiver found in \$PATH])
fi
AC_MSG_RESULT([$TAR])
AC_SUBST(TAR)
if test -z "$TINDERBOX_SKIP_PERL_VERSION_CHECK"; then
AC_MSG_CHECKING([for minimum required perl version >= $PERL_VERSION])
_perl_version=`PERL_VERSION=$PERL_VERSION $PERL -e 'print "$]"; if ($] >= $ENV{PERL_VERSION}) { exit(0); } else { exit(1); }' 2>&5`

View File

@ -451,9 +451,10 @@ frontend::CompileLazyFunction(JSContext *cx, LazyScript *lazy, const jschar *cha
// Compile a JS function body, which might appear as the value of an event
// handler attribute in an HTML <INPUT> tag, or in a Function() constructor.
bool
frontend::CompileFunctionBody(JSContext *cx, MutableHandleFunction fun, CompileOptions options,
const AutoNameVector &formals, const jschar *chars, size_t length)
static bool
CompileFunctionBody(JSContext *cx, MutableHandleFunction fun, CompileOptions options,
const AutoNameVector &formals, const jschar *chars, size_t length,
GeneratorKind generatorKind)
{
#if JS_TRACE_LOGGING
js::AutoTraceLog logger(js::TraceLogging::defaultLogger(),
@ -520,7 +521,7 @@ frontend::CompileFunctionBody(JSContext *cx, MutableHandleFunction fun, CompileO
ParseNode *fn;
while (true) {
Directives newDirectives = directives;
fn = parser.standaloneFunctionBody(fun, formals, NotGenerator, directives, &newDirectives);
fn = parser.standaloneFunctionBody(fun, formals, generatorKind, directives, &newDirectives);
if (fn)
break;
@ -585,3 +586,18 @@ frontend::CompileFunctionBody(JSContext *cx, MutableHandleFunction fun, CompileO
return true;
}
bool
frontend::CompileFunctionBody(JSContext *cx, MutableHandleFunction fun, CompileOptions options,
const AutoNameVector &formals, const jschar *chars, size_t length)
{
return CompileFunctionBody(cx, fun, options, formals, chars, length, NotGenerator);
}
bool
frontend::CompileStarGeneratorBody(JSContext *cx, MutableHandleFunction fun,
CompileOptions options, const AutoNameVector &formals,
const jschar *chars, size_t length)
{
return CompileFunctionBody(cx, fun, options, formals, chars, length, StarGenerator);
}

View File

@ -33,6 +33,9 @@ CompileLazyFunction(JSContext *cx, LazyScript *lazy, const jschar *chars, size_t
bool
CompileFunctionBody(JSContext *cx, MutableHandleFunction fun, CompileOptions options,
const AutoNameVector &formals, const jschar *chars, size_t length);
bool
CompileStarGeneratorBody(JSContext *cx, MutableHandleFunction fun, CompileOptions options,
const AutoNameVector &formals, const jschar *chars, size_t length);
/*
* This should be called while still on the main thread if compilation will

View File

@ -1244,7 +1244,7 @@ struct BindData
template <typename ParseHandler>
JSFunction *
Parser<ParseHandler>::newFunction(GenericParseContext *pc, HandleAtom atom,
FunctionSyntaxKind kind)
FunctionSyntaxKind kind, JSObject *proto)
{
JS_ASSERT_IF(kind == Statement, atom != NULL);
@ -1267,8 +1267,8 @@ Parser<ParseHandler>::newFunction(GenericParseContext *pc, HandleAtom atom,
: (kind == Arrow)
? JSFunction::INTERPRETED_LAMBDA_ARROW
: JSFunction::INTERPRETED;
fun = NewFunction(context, NullPtr(), NULL, 0, flags, parent, atom,
JSFunction::FinalizeKind, MaybeSingletonObject);
fun = NewFunctionWithProto(context, NullPtr(), NULL, 0, flags, parent, atom, proto,
JSFunction::FinalizeKind, MaybeSingletonObject);
if (!fun)
return NULL;
if (options().selfHostingMode)
@ -1999,7 +1999,17 @@ Parser<ParseHandler>::functionDef(HandlePropertyName funName, const TokenStream:
if (bodyProcessed)
return pn;
RootedFunction fun(context, newFunction(pc, funName, kind));
RootedObject proto(context);
if (generatorKind == StarGenerator) {
// If we are off the main thread, the generator meta-objects have
// already been created by js::StartOffThreadParseScript, so cx will not
// be necessary.
JSContext *cx = context->maybeJSContext();
proto = context->global()->getOrCreateStarGeneratorFunctionPrototype(cx);
if (!proto)
return null();
}
RootedFunction fun(context, newFunction(pc, funName, kind, proto));
if (!fun)
return null();

View File

@ -407,7 +407,8 @@ class Parser : private AutoGCRooter, public StrictModeGetter
* Create a new function object given parse context (pc) and a name (which
* is optional if this is a function expression).
*/
JSFunction *newFunction(GenericParseContext *pc, HandleAtom atom, FunctionSyntaxKind kind);
JSFunction *newFunction(GenericParseContext *pc, HandleAtom atom, FunctionSyntaxKind kind,
JSObject *proto = NULL);
void trace(JSTracer *trc);

View File

@ -195,18 +195,15 @@ struct Zone : private JS::shadow::Zone,
void scheduleGC() {
JS_ASSERT(!runtimeFromMainThread()->isHeapBusy());
// Ignore attempts to schedule GCs on zones which can't be collected.
if (canCollect())
gcScheduled = true;
gcScheduled = true;
}
void unscheduleGC() {
gcScheduled = false;
}
bool isGCScheduled() const {
return gcScheduled;
bool isGCScheduled() {
return gcScheduled && canCollect();
}
void setPreservingCode(bool preserving) {

View File

@ -207,7 +207,10 @@ IsNullOrUndefined(MIRType type)
// Make sure registers are not modified between an instruction and
// its OsiPoint.
# ifdef JS_ION
//
// Skip this check in rooting analysis builds, which poison unrooted
// pointers on the stack.
# if defined(JS_ION) && !defined(JSGC_ROOT_ANALYSIS)
# define CHECK_OSIPOINT_REGISTERS 1
# endif
#endif

View File

@ -2904,7 +2904,7 @@ struct JSClass {
* with the following flags. Failure to use JSCLASS_GLOBAL_FLAGS was
* prevously allowed, but is now an ES5 violation and thus unsupported.
*/
#define JSCLASS_GLOBAL_SLOT_COUNT (JSProto_LIMIT * 3 + 25)
#define JSCLASS_GLOBAL_SLOT_COUNT (JSProto_LIMIT * 3 + 26)
#define JSCLASS_GLOBAL_FLAGS_WITH_SLOTS(n) \
(JSCLASS_IS_GLOBAL | JSCLASS_HAS_RESERVED_SLOTS(JSCLASS_GLOBAL_SLOT_COUNT + (n)))
#define JSCLASS_GLOBAL_FLAGS \

View File

@ -27,6 +27,7 @@
#include "jswrapper.h"
#include "builtin/Eval.h"
#include "builtin/Object.h"
#include "frontend/BytecodeCompiler.h"
#include "frontend/TokenStream.h"
#include "gc/Marking.h"
@ -195,40 +196,51 @@ ResolveInterpretedFunctionPrototype(JSContext *cx, HandleObject obj)
JS_ASSERT(!fun->isFunctionPrototype());
#endif
/*
* Assert that fun is not a compiler-created function object, which
* must never leak to script or embedding code and then be mutated.
* Also assert that obj is not bound, per the ES5 15.3.4.5 ref above.
*/
// Assert that fun is not a compiler-created function object, which
// must never leak to script or embedding code and then be mutated.
// Also assert that obj is not bound, per the ES5 15.3.4.5 ref above.
JS_ASSERT(!IsInternalFunctionObject(obj));
JS_ASSERT(!obj->isBoundFunction());
/*
* Make the prototype object an instance of Object with the same parent
* as the function object itself.
*/
JSObject *objProto = obj->global().getOrCreateObjectPrototype(cx);
// Make the prototype object an instance of Object with the same parent as
// the function object itself, unless the function is an ES6 generator. In
// that case, per the 15 July 2013 ES6 draft, section 15.19.3, its parent is
// the GeneratorObjectPrototype singleton.
bool isStarGenerator = obj->as<JSFunction>().isStarGenerator();
JSObject *objProto;
if (isStarGenerator)
objProto = obj->global().getOrCreateStarGeneratorObjectPrototype(cx);
else
objProto = obj->global().getOrCreateObjectPrototype(cx);
if (!objProto)
return NULL;
RootedObject proto(cx, NewObjectWithGivenProto(cx, &JSObject::class_, objProto, NULL, SingletonObject));
Class *clasp = &JSObject::class_;
RootedObject proto(cx, NewObjectWithGivenProto(cx, clasp, objProto, NULL, SingletonObject));
if (!proto)
return NULL;
/*
* Per ES5 15.3.5.2 a user-defined function's .prototype property is
* initially non-configurable, non-enumerable, and writable. Per ES5 13.2
* the prototype's .constructor property is configurable, non-enumerable,
* and writable.
*/
// Per ES5 15.3.5.2 a user-defined function's .prototype property is
// initially non-configurable, non-enumerable, and writable.
RootedValue protoVal(cx, ObjectValue(*proto));
RootedValue objVal(cx, ObjectValue(*obj));
if (!JSObject::defineProperty(cx, obj, cx->names().classPrototype,
protoVal, JS_PropertyStub, JS_StrictPropertyStub,
JSPROP_PERMANENT) ||
!JSObject::defineProperty(cx, proto, cx->names().constructor,
objVal, JS_PropertyStub, JS_StrictPropertyStub, 0))
JSPROP_PERMANENT))
{
return NULL;
return NULL;
}
// Per ES5 13.2 the prototype's .constructor property is configurable,
// non-enumerable, and writable. However, per the 15 July 2013 ES6 draft,
// section 15.19.3, the .prototype of a generator function does not link
// back with a .constructor.
if (!isStarGenerator) {
RootedValue objVal(cx, ObjectValue(*obj));
if (!JSObject::defineProperty(cx, proto, cx->names().constructor,
objVal, JS_PropertyStub, JS_StrictPropertyStub, 0))
{
return NULL;
}
}
return proto;
@ -327,12 +339,15 @@ bool
js::XDRInterpretedFunction(XDRState<mode> *xdr, HandleObject enclosingScope, HandleScript enclosingScript,
MutableHandleObject objp)
{
enum FirstWordFlag {
HasAtom = 0x1,
IsStarGenerator = 0x2
};
/* NB: Keep this in sync with CloneFunctionAndScript. */
RootedAtom atom(xdr->cx());
uint32_t firstword; /* flag telling whether fun->atom is non-null,
plus for fun->u.i.skipmin, fun->u.i.wrapper,
and 14 bits reserved for future use */
uint32_t flagsword; /* word for argument count and fun->flags */
uint32_t firstword = 0; /* bitmask of FirstWordFlag */
uint32_t flagsword = 0; /* word for argument count and fun->flags */
JSContext *cx = xdr->cx();
RootedFunction fun(cx);
@ -347,24 +362,38 @@ js::XDRInterpretedFunction(XDRState<mode> *xdr, HandleObject enclosingScope, Han
}
return false;
}
firstword = !!fun->atom();
if (fun->atom())
firstword |= HasAtom;
if (fun->isStarGenerator())
firstword |= IsStarGenerator;
script = fun->getOrCreateScript(cx);
if (!script)
return false;
atom = fun->atom();
flagsword = (fun->nargs << 16) | fun->flags;
if (!xdr->codeUint32(&firstword))
return false;
} else {
fun = NewFunction(cx, NullPtr(), NULL, 0, JSFunction::INTERPRETED, NullPtr(), NullPtr(),
JSFunction::FinalizeKind, TenuredObject);
if (!xdr->codeUint32(&firstword))
return false;
JSObject *proto = NULL;
if (firstword & IsStarGenerator) {
proto = cx->global()->getOrCreateStarGeneratorFunctionPrototype(cx);
if (!proto)
return false;
}
fun = NewFunctionWithProto(cx, NullPtr(), NULL, 0, JSFunction::INTERPRETED,
NullPtr(), NullPtr(), proto,
JSFunction::FinalizeKind, TenuredObject);
if (!fun)
return false;
atom = NULL;
script = NULL;
}
if (!xdr->codeUint32(&firstword))
return false;
if ((firstword & 1U) && !XDRAtom(xdr, &atom))
if ((firstword & HasAtom) && !XDRAtom(xdr, &atom))
return false;
if (!xdr->codeUint32(&flagsword))
return false;
@ -399,10 +428,15 @@ JSObject *
js::CloneFunctionAndScript(JSContext *cx, HandleObject enclosingScope, HandleFunction srcFun)
{
/* NB: Keep this in sync with XDRInterpretedFunction. */
RootedFunction clone(cx, NewFunction(cx, NullPtr(), NULL, 0,
JSFunction::INTERPRETED, NullPtr(), NullPtr(),
JSFunction::FinalizeKind, TenuredObject));
JSObject *cloneProto = NULL;
if (srcFun->isStarGenerator()) {
cloneProto = cx->global()->getOrCreateStarGeneratorFunctionPrototype(cx);
if (!cloneProto)
return NULL;
}
RootedFunction clone(cx, NewFunctionWithProto(cx, NullPtr(), NULL, 0, JSFunction::INTERPRETED,
NullPtr(), NullPtr(), cloneProto,
JSFunction::FinalizeKind, TenuredObject));
if (!clone)
return NULL;
@ -605,7 +639,7 @@ js::FunctionToString(JSContext *cx, HandleFunction fun, bool bodyOnly, bool lamb
return NULL;
}
if (!fun->isArrow()) {
if (!out.append("function "))
if (!(fun->isStarGenerator() ? out.append("function* ") : out.append("function ")))
return NULL;
}
if (fun->atom()) {
@ -795,6 +829,9 @@ fun_toSource(JSContext *cx, unsigned argc, Value *vp)
if (!obj)
return false;
if (!obj->is<JSFunction>() && !obj->is<FunctionProxyObject>())
return obj_toSource(cx, argc, vp);
RootedString str(cx, fun_toStringHelper(cx, obj, JS_DONT_PRETTY_PRINT));
if (!str)
return false;
@ -1327,8 +1364,8 @@ const JSFunctionSpec js::function_methods[] = {
JS_FS_END
};
bool
js::Function(JSContext *cx, unsigned argc, Value *vp)
static bool
FunctionConstructor(JSContext *cx, unsigned argc, Value *vp, GeneratorKind generatorKind)
{
CallArgs args = CallArgsFromVp(argc, vp);
RootedString arg(cx); // used multiple times below
@ -1345,6 +1382,9 @@ js::Function(JSContext *cx, unsigned argc, Value *vp)
bool hasRest = false;
bool isStarGenerator = generatorKind == StarGenerator;
JS_ASSERT(generatorKind != LegacyGenerator);
const char *filename;
unsigned lineno;
JSPrincipals *originPrincipals;
@ -1437,6 +1477,7 @@ js::Function(JSContext *cx, unsigned argc, Value *vp)
*/
TokenStream ts(cx, options, collected_args.get(), args_length,
/* strictModeGetter = */ NULL);
bool yieldIsValidName = ts.versionNumber() < JSVERSION_1_7 && !isStarGenerator;
/* The argument string may be empty or contain no tokens. */
TokenKind tt = ts.getToken();
@ -1451,14 +1492,14 @@ js::Function(JSContext *cx, unsigned argc, Value *vp)
return false;
}
if (tt == TOK_YIELD && ts.versionNumber() < JSVERSION_1_7)
if (tt == TOK_YIELD && yieldIsValidName)
tt = TOK_NAME;
if (tt != TOK_NAME) {
if (tt == TOK_TRIPLEDOT) {
hasRest = true;
tt = ts.getToken();
if (tt == TOK_YIELD && ts.versionNumber() < JSVERSION_1_7)
if (tt == TOK_YIELD && yieldIsValidName)
tt = TOK_NAME;
if (tt != TOK_NAME) {
if (tt != TOK_ERROR)
@ -1519,24 +1560,47 @@ js::Function(JSContext *cx, unsigned argc, Value *vp)
* and so would a call to f from another top-level's script or function.
*/
RootedAtom anonymousAtom(cx, cx->names().anonymous);
RootedFunction fun(cx, NewFunction(cx, NullPtr(), NULL, 0, JSFunction::INTERPRETED_LAMBDA,
global, anonymousAtom, JSFunction::FinalizeKind,
TenuredObject));
JSObject *proto = NULL;
if (isStarGenerator) {
proto = global->getOrCreateStarGeneratorFunctionPrototype(cx);
if (!proto)
return false;
}
RootedFunction fun(cx, NewFunctionWithProto(cx, NullPtr(), NULL, 0,
JSFunction::INTERPRETED_LAMBDA, global,
anonymousAtom, proto,
JSFunction::FinalizeKind, TenuredObject));
if (!fun)
return false;
if (hasRest)
fun->setHasRest();
bool ok = frontend::CompileFunctionBody(cx, &fun, options, formals, chars, length);
bool ok;
if (isStarGenerator)
ok = frontend::CompileStarGeneratorBody(cx, &fun, options, formals, chars, length);
else
ok = frontend::CompileFunctionBody(cx, &fun, options, formals, chars, length);
args.rval().setObject(*fun);
return ok;
}
bool
js::Function(JSContext *cx, unsigned argc, Value *vp)
{
return FunctionConstructor(cx, argc, vp, NotGenerator);
}
bool
js::Generator(JSContext *cx, unsigned argc, Value *vp)
{
return FunctionConstructor(cx, argc, vp, StarGenerator);
}
bool
JSFunction::isBuiltinFunctionConstructor()
{
return maybeNative() == Function;
return maybeNative() == Function || maybeNative() == Generator;
}
JSFunction *
@ -1544,6 +1608,17 @@ js::NewFunction(ExclusiveContext *cx, HandleObject funobjArg, Native native, uns
JSFunction::Flags flags, HandleObject parent, HandleAtom atom,
gc::AllocKind allocKind /* = JSFunction::FinalizeKind */,
NewObjectKind newKind /* = GenericObject */)
{
return NewFunctionWithProto(cx, funobjArg, native, nargs, flags, parent, atom, NULL,
allocKind, newKind);
}
JSFunction *
js::NewFunctionWithProto(ExclusiveContext *cx, HandleObject funobjArg, Native native,
unsigned nargs, JSFunction::Flags flags, HandleObject parent,
HandleAtom atom, JSObject *proto,
gc::AllocKind allocKind /* = JSFunction::FinalizeKind */,
NewObjectKind newKind /* = GenericObject */)
{
JS_ASSERT(allocKind == JSFunction::FinalizeKind || allocKind == JSFunction::ExtendedFinalizeKind);
JS_ASSERT(sizeof(JSFunction) <= gc::Arena::thingSize(JSFunction::FinalizeKind));
@ -1560,7 +1635,7 @@ js::NewFunction(ExclusiveContext *cx, HandleObject funobjArg, Native native, uns
// that hasSingletonType implies isInterpreted.
if (native && !IsAsmJSModuleNative(native))
newKind = SingletonObject;
funobj = NewObjectWithClassProto(cx, &JSFunction::class_, NULL,
funobj = NewObjectWithClassProto(cx, &JSFunction::class_, proto,
SkipScopeParent(parent), allocKind, newKind);
if (!funobj)
return NULL;
@ -1603,7 +1678,13 @@ js::CloneFunctionObject(JSContext *cx, HandleFunction fun, HandleObject parent,
return NULL;
NewObjectKind newKind = useSameScript ? newKindArg : SingletonObject;
JSObject *cloneobj = NewObjectWithClassProto(cx, &JSFunction::class_, NULL,
JSObject *cloneProto = NULL;
if (fun->isStarGenerator()) {
cloneProto = cx->global()->getOrCreateStarGeneratorFunctionPrototype(cx);
if (!cloneProto)
return NULL;
}
JSObject *cloneobj = NewObjectWithClassProto(cx, &JSFunction::class_, cloneProto,
SkipScopeParent(parent), allocKind, newKind);
if (!cloneobj)
return NULL;

View File

@ -410,12 +410,22 @@ namespace js {
extern bool
Function(JSContext *cx, unsigned argc, Value *vp);
extern bool
Generator(JSContext *cx, unsigned argc, Value *vp);
extern JSFunction *
NewFunction(ExclusiveContext *cx, HandleObject funobj, JSNative native, unsigned nargs,
JSFunction::Flags flags, HandleObject parent, HandleAtom atom,
gc::AllocKind allocKind = JSFunction::FinalizeKind,
NewObjectKind newKind = GenericObject);
// If proto is NULL, Function.prototype is used instead.
extern JSFunction *
NewFunctionWithProto(ExclusiveContext *cx, HandleObject funobj, JSNative native, unsigned nargs,
JSFunction::Flags flags, HandleObject parent, HandleAtom atom,
JSObject *proto, gc::AllocKind allocKind = JSFunction::FinalizeKind,
NewObjectKind newKind = GenericObject);
extern JSFunction *
DefineFunction(JSContext *cx, HandleObject obj, HandleId id, JSNative native,
unsigned nargs, unsigned flags,

View File

@ -4445,11 +4445,6 @@ GCCycle(JSRuntime *rt, bool incremental, int64_t budget, JSGCInvocationKind gcki
/* If we attempt to invoke the GC while we are running in the GC, assert. */
JS_ASSERT(!rt->isHeapBusy());
#ifdef DEBUG
for (ZonesIter zone(rt); !zone.done(); zone.next())
JS_ASSERT_IF(rt->gcMode == JSGC_MODE_GLOBAL, zone->isGCScheduled());
#endif
AutoGCSession gcsession(rt);
/*

View File

@ -958,7 +958,7 @@ const JSFunctionSpec ElementIteratorObject::methods[] = {
};
static bool
CloseGenerator(JSContext *cx, HandleObject genobj);
CloseLegacyGenerator(JSContext *cx, HandleObject genobj);
bool
js::ValueToIterator(JSContext *cx, unsigned flags, MutableHandleValue vp)
@ -999,6 +999,30 @@ js::ValueToIterator(JSContext *cx, unsigned flags, MutableHandleValue vp)
return GetIterator(cx, obj, flags, vp);
}
bool
IsGenerator(HandleValue v)
{
return v.isObject() && v.toObject().is<GeneratorObject>();
}
static bool
IsLegacyGenerator(HandleObject obj)
{
if (!obj->is<GeneratorObject>())
return false;
JSGenerator *gen = obj->as<GeneratorObject>().getGenerator();
return gen->regs.fp()->script()->isLegacyGenerator();
}
bool
IsLegacyGenerator(HandleValue v)
{
if (!IsGenerator(v))
return false;
JSGenerator *gen = v.toObject().as<GeneratorObject>().getGenerator();
return gen->regs.fp()->script()->isLegacyGenerator();
}
bool
js::CloseIterator(JSContext *cx, HandleObject obj)
{
@ -1020,9 +1044,8 @@ js::CloseIterator(JSContext *cx, HandleObject obj)
*/
ni->props_cursor = ni->props_array;
}
} else if (obj->is<GeneratorObject>()) {
// FIXME: Only close legacy generators.
return CloseGenerator(cx, obj);
} else if (IsLegacyGenerator(obj)) {
return CloseLegacyGenerator(cx, obj);
}
return true;
}
@ -1477,15 +1500,25 @@ js_NewGenerator(JSContext *cx, const FrameRegs &stackRegs)
JS_ASSERT(stackfp->script()->isGenerator());
if (stackfp->script()->isStarGenerator()) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_ES6_UNIMPLEMENTED);
return NULL;
}
Rooted<GlobalObject*> global(cx, &stackfp->global());
RootedObject obj(cx);
{
JSObject *proto = global->getOrCreateGeneratorPrototype(cx);
if (stackfp->script()->isStarGenerator()) {
RootedValue pval(cx);
RootedObject fun(cx, stackfp->fun());
// FIXME: This would be faster if we could avoid doing a lookup to get
// the prototype for the instance. Bug 906600.
if (!JSObject::getProperty(cx, fun, fun, cx->names().classPrototype, &pval))
return NULL;
JSObject *proto = pval.isObject() ? &pval.toObject() : NULL;
if (!proto) {
proto = global->getOrCreateStarGeneratorObjectPrototype(cx);
if (!proto)
return NULL;
}
obj = NewObjectWithGivenProto(cx, &GeneratorObject::class_, proto, global);
} else {
JS_ASSERT(stackfp->script()->isLegacyGenerator());
JSObject *proto = global->getOrCreateLegacyGeneratorObjectPrototype(cx);
if (!proto)
return NULL;
obj = NewObjectWithGivenProto(cx, &GeneratorObject::class_, proto, global);
@ -1623,66 +1656,17 @@ SendToGenerator(JSContext *cx, JSGeneratorOp op, HandleObject obj,
}
static bool
CloseGenerator(JSContext *cx, HandleObject obj)
CloseLegacyGenerator(JSContext *cx, HandleObject obj)
{
JS_ASSERT(IsLegacyGenerator(obj));
JSGenerator *gen = obj->as<GeneratorObject>().getGenerator();
if (!gen) {
/* Generator prototype object. */
return true;
}
// FIXME: Assert that gen is a legacy generator.
if (gen->state == JSGEN_CLOSED)
return true;
return SendToGenerator(cx, JSGENOP_CLOSE, obj, gen, JS::UndefinedHandleValue);
}
JS_ALWAYS_INLINE bool
IsGenerator(HandleValue v)
{
return v.isObject() && v.toObject().is<GeneratorObject>();
}
JS_ALWAYS_INLINE bool
generator_send_impl(JSContext *cx, CallArgs args)
{
// FIXME: Change assertion to IsLegacyGenerator().
JS_ASSERT(IsGenerator(args.thisv()));
RootedObject thisObj(cx, &args.thisv().toObject());
JSGenerator *gen = thisObj->as<GeneratorObject>().getGenerator();
if (!gen || gen->state == JSGEN_CLOSED) {
/* This happens when obj is the generator prototype. See bug 352885. */
return js_ThrowStopIteration(cx);
}
if (gen->state == JSGEN_NEWBORN && args.hasDefined(0)) {
RootedValue val(cx, args[0]);
js_ReportValueError(cx, JSMSG_BAD_GENERATOR_SEND,
JSDVG_SEARCH_STACK, val, NullPtr());
return false;
}
// FIXME: next() takes the send value as an optional argument in ES6
// generator objects.
if (!SendToGenerator(cx, JSGENOP_SEND, thisObj, gen, args.get(0)))
return false;
args.rval().set(gen->fp->returnValue());
return true;
}
bool
generator_send(JSContext *cx, unsigned argc, Value *vp)
{
// FIXME: send() is only a method on legacy generator objects.
CallArgs args = CallArgsFromVp(argc, vp);
return CallNonGenericMethod<IsGenerator, generator_send_impl>(cx, args);
}
JS_ALWAYS_INLINE bool
generator_next_impl(JSContext *cx, CallArgs args)
{
@ -1691,12 +1675,17 @@ generator_next_impl(JSContext *cx, CallArgs args)
RootedObject thisObj(cx, &args.thisv().toObject());
JSGenerator *gen = thisObj->as<GeneratorObject>().getGenerator();
if (!gen || gen->state == JSGEN_CLOSED) {
/* This happens when obj is the generator prototype. See bug 352885. */
if (gen->state == JSGEN_CLOSED)
return js_ThrowStopIteration(cx);
if (gen->state == JSGEN_NEWBORN && args.hasDefined(0)) {
RootedValue val(cx, args[0]);
js_ReportValueError(cx, JSMSG_BAD_GENERATOR_SEND,
JSDVG_SEARCH_STACK, val, NullPtr());
return false;
}
if (!SendToGenerator(cx, JSGENOP_NEXT, thisObj, gen, JS::UndefinedHandleValue))
if (!SendToGenerator(cx, JSGENOP_SEND, thisObj, gen, args.get(0)))
return false;
args.rval().set(gen->fp->returnValue());
@ -1718,8 +1707,7 @@ generator_throw_impl(JSContext *cx, CallArgs args)
RootedObject thisObj(cx, &args.thisv().toObject());
JSGenerator *gen = thisObj->as<GeneratorObject>().getGenerator();
if (!gen || gen->state == JSGEN_CLOSED) {
/* This happens when obj is the generator prototype. See bug 352885. */
if (gen->state == JSGEN_CLOSED) {
cx->setPendingException(args.length() >= 1 ? args[0] : UndefinedValue());
return false;
}
@ -1741,14 +1729,12 @@ generator_throw(JSContext *cx, unsigned argc, Value *vp)
JS_ALWAYS_INLINE bool
generator_close_impl(JSContext *cx, CallArgs args)
{
// FIXME: Change assertion to IsLegacyGenerator().
JS_ASSERT(IsGenerator(args.thisv()));
JS_ASSERT(IsLegacyGenerator(args.thisv()));
RootedObject thisObj(cx, &args.thisv().toObject());
JSGenerator *gen = thisObj->as<GeneratorObject>().getGenerator();
if (!gen || gen->state == JSGEN_CLOSED) {
/* This happens when obj is the generator prototype. See bug 352885. */
if (gen->state == JSGEN_CLOSED) {
args.rval().setUndefined();
return true;
}
@ -1769,22 +1755,47 @@ generator_close_impl(JSContext *cx, CallArgs args)
bool
generator_close(JSContext *cx, unsigned argc, Value *vp)
{
// FIXME: close() is only a method on legacy generator objects.
CallArgs args = CallArgsFromVp(argc, vp);
return CallNonGenericMethod<IsGenerator, generator_close_impl>(cx, args);
return CallNonGenericMethod<IsLegacyGenerator, generator_close_impl>(cx, args);
}
#define JSPROP_ROPERM (JSPROP_READONLY | JSPROP_PERMANENT)
static const JSFunctionSpec generator_methods[] = {
static const JSFunctionSpec legacy_generator_methods[] = {
JS_FN("iterator", iterator_iterator, 0, 0),
JS_FN("next", generator_next, 0,JSPROP_ROPERM),
JS_FN("send", generator_send, 1,JSPROP_ROPERM),
JS_FN("next", generator_next, 1,JSPROP_ROPERM),
// Send is exactly the same as next.
JS_FN("send", generator_next, 1,JSPROP_ROPERM),
JS_FN("throw", generator_throw, 1,JSPROP_ROPERM),
JS_FN("close", generator_close, 0,JSPROP_ROPERM),
JS_FS_END
};
static const JSFunctionSpec star_generator_methods[] = {
JS_FN("iterator", iterator_iterator, 0, 0),
JS_FN("next", generator_next, 1,JSPROP_ROPERM),
JS_FN("throw", generator_throw, 1,JSPROP_ROPERM),
JS_FS_END
};
static JSObject*
NewObjectWithObjectPrototype(JSContext *cx, Handle<GlobalObject *> global)
{
JSObject *proto = global->getOrCreateObjectPrototype(cx);
if (!proto)
return NULL;
return NewObjectWithGivenProto(cx, &JSObject::class_, proto, global);
}
static JSObject*
NewObjectWithFunctionPrototype(JSContext *cx, Handle<GlobalObject *> global)
{
JSObject *proto = global->getOrCreateFunctionPrototype(cx);
if (!proto)
return NULL;
return NewObjectWithGivenProto(cx, &JSObject::class_, proto, global);
}
/* static */ bool
GlobalObject::initIteratorClasses(JSContext *cx, Handle<GlobalObject *> global)
{
@ -1826,11 +1837,41 @@ GlobalObject::initIteratorClasses(JSContext *cx, Handle<GlobalObject *> global)
global->setReservedSlot(ELEMENT_ITERATOR_PROTO, ObjectValue(*proto));
}
if (global->getSlot(GENERATOR_PROTO).isUndefined()) {
proto = global->createBlankPrototype(cx, &GeneratorObject::class_);
if (!proto || !DefinePropertiesAndBrand(cx, proto, NULL, generator_methods))
if (global->getSlot(LEGACY_GENERATOR_OBJECT_PROTO).isUndefined()) {
proto = NewObjectWithObjectPrototype(cx, global);
if (!proto || !DefinePropertiesAndBrand(cx, proto, NULL, legacy_generator_methods))
return false;
global->setReservedSlot(GENERATOR_PROTO, ObjectValue(*proto));
global->setReservedSlot(LEGACY_GENERATOR_OBJECT_PROTO, ObjectValue(*proto));
}
if (global->getSlot(STAR_GENERATOR_OBJECT_PROTO).isUndefined()) {
RootedObject genObjectProto(cx, NewObjectWithObjectPrototype(cx, global));
if (!genObjectProto)
return false;
if (!DefinePropertiesAndBrand(cx, genObjectProto, NULL, star_generator_methods))
return false;
RootedObject genFunctionProto(cx, NewObjectWithFunctionPrototype(cx, global));
if (!genFunctionProto)
return false;
if (!LinkConstructorAndPrototype(cx, genFunctionProto, genObjectProto))
return false;
RootedValue function(cx, global->getConstructor(JSProto_Function));
if (!function.toObjectOrNull())
return false;
RootedAtom name(cx, cx->names().GeneratorFunction);
RootedObject genFunction(cx, NewFunctionWithProto(cx, NullPtr(), Generator, 1,
JSFunction::NATIVE_CTOR, global, name,
&function.toObject()));
if (!genFunction)
return false;
if (!LinkConstructorAndPrototype(cx, genFunction, genFunctionProto))
return false;
global->setSlot(STAR_GENERATOR_OBJECT_PROTO, ObjectValue(*genObjectProto));
global->setSlot(JSProto_GeneratorFunction, ObjectValue(*genFunction));
global->setSlot(JSProto_GeneratorFunction + JSProto_LIMIT, ObjectValue(*genFunctionProto));
}
if (global->getPrototype(JSProto_StopIteration).isUndefined()) {

View File

@ -69,5 +69,6 @@
macro(ArrayType, 50, js_InitBinaryDataClasses) \
macro(StructType, 51, js_InitBinaryDataClasses) \
macro(ArrayTypeObject, 52, js_InitBinaryDataClasses) \
macro(GeneratorFunction, 53, js_InitIteratorClasses) \
#endif /* jsprototypes_h */

View File

@ -236,7 +236,8 @@ js::StartOffThreadParseScript(JSContext *cx, const CompileOptions &options,
// pointers can be changed infallibly after parsing finishes.
if (!js_GetClassObject(cx, cx->global(), JSProto_Function, &obj) ||
!js_GetClassObject(cx, cx->global(), JSProto_Array, &obj) ||
!js_GetClassObject(cx, cx->global(), JSProto_RegExp, &obj))
!js_GetClassObject(cx, cx->global(), JSProto_RegExp, &obj) ||
!js_GetClassObject(cx, cx->global(), JSProto_GeneratorFunction, &obj))
{
return false;
}
@ -244,7 +245,8 @@ js::StartOffThreadParseScript(JSContext *cx, const CompileOptions &options,
AutoCompartment ac(cx, global);
if (!js_GetClassObject(cx, global, JSProto_Function, &obj) ||
!js_GetClassObject(cx, global, JSProto_Array, &obj) ||
!js_GetClassObject(cx, global, JSProto_RegExp, &obj))
!js_GetClassObject(cx, global, JSProto_RegExp, &obj) ||
!js_GetClassObject(cx, global, JSProto_GeneratorFunction, &obj))
{
return false;
}

123
js/src/make-source-package.sh Executable file
View File

@ -0,0 +1,123 @@
#!/bin/sh
# need these environment vars:
echo "Environment:"
echo " MAKE = $MAKE"
echo " MKDIR = $MKDIR"
echo " TAR = $TAR"
echo " DIST = $DIST"
echo " SRCDIR = $SRCDIR"
echo " MOZJS_MAJOR_VERSION = $MOZJS_MAJOR_VERSION"
echo " MOZJS_MINOR_VERSION = $MOZJS_MINOR_VERSION"
echo " MOZJS_PATCH_VERSION = $MOZJS_PATCH_VERSION"
echo " MOZJS_ALPHA = $MOZJS_ALPHA"
cmd=${1:-build}
pkg="mozjs-${MOZJS_MAJOR_VERSION}.${MOZJS_MINOR_VERSION}.${MOZJS_PATCH_VERSION:-${MOZJS_ALPHA:-0}}.tar.bz2"
pkgpath=${pkg%.tar*}
tgtpath=${DIST}/${pkgpath}
taropts="-jcf"
case $cmd in
"clean")
echo "Cleaning ${pkg} and ${tgtpath} ..."
rm -rf ${pkg} ${tgtpath}
;;
"build")
echo "Packaging source tarball ${pkg}..."
if [ -d ${tgtpath} ]; then
echo "WARNING - dist tree ${tgtpath} already exists!"
fi
${MKDIR} -p ${tgtpath}/js/src
# copy the embedded icu
${MKDIR} -p ${tgtpath}/intl
cp -t ${tgtpath}/intl -dRp ${SRCDIR}/../../intl/icu
# put in js itself
cp -t ${tgtpath} -dRp ${SRCDIR}/../../mfbt
cp -t ${tgtpath}/js -dRp ${SRCDIR}/../jsd ${SRCDIR}/../public
find ${SRCDIR} -mindepth 1 -maxdepth 1 -not -path ${DIST} -a -not -name ${pkg} \
-exec cp -t ${tgtpath}/js/src -dRp {} +
# distclean if necessary
if [ -e ${tgtpath}/js/src/Makefile ]; then
${MAKE} -C ${tgtpath}/js/src distclean
fi
# put in the virtualenv and supporting files if it doesnt already exist
if [ ! -e ${SRCDIR}/build/virtualenv ]; then
cp -t ${tgtpath}/js/src/build -dRp \
${SRCDIR}/../../build/virtualenv \
${SRCDIR}/../../build/buildconfig.py
fi
if [ ! -e ${SRCDIR}/python ]; then
cp -t ${tgtpath}/js/src -dRp \
${SRCDIR}/../../python
fi
if [ ! -e ${SRCDIR}/testing ]; then
${MKDIR} -p ${tgtpath}/js/src/testing
cp -t ${tgtpath}/js/src/testing -dRp \
${SRCDIR}/../../testing/mozbase
fi
# end of virtualenv injection
# remove *.pyc and *.pyo files if any
find ${tgtpath} -type f -name "*.pyc" -o -name "*.pyo" |xargs rm -f
# copy or create INSTALL
if [ -e {DIST}/INSTALL ]; then
cp -t ${tgtpath} ${DIST}/INSTALL
else
cat <<INSTALL_EOF >${tgtpath}/INSTALL
Full build documentation for SpiderMonkey is hosted on MDN:
https://developer.mozilla.org/en-US/docs/SpiderMonkey/Build_Documentation
Note that the libraries produced by the build system include symbols,
causing the binaries to be extremely large. It is highly suggested that \`strip\`
be run over the binaries before deploying them.
Building with default options may be performed as follows:
cd js/src
./configure
make
INSTALL_EOF
fi
# copy or create README
if [ -e ${DIST}/README ]; then
cp -t ${tgtpath} ${DIST}/README
else
cat <<README_EOF >${tgtpath}/README
This directory contains SpiderMonkey ${MOZJS_MAJOR_VERSION}.
This release is based on a revision of Mozilla ${MOZJS_MAJOR_VERSION}:
http://hg.mozilla.org/releases/
The changes in the patches/ directory were applied.
MDN hosts the latest SpiderMonkey ${MOZJS_MAJOR_VERSION} release notes:
https://developer.mozilla.org/en-US/docs/SpiderMonkey/${MOZJS_MAJOR_VERSION}
README_EOF
fi
# copy LICENSE
if [ -e ${SRCDIR}/../../b2g/LICENSE ]; then
cp ${SRCDIR}/../../b2g/LICENSE ${tgtpath}/
else
cp ${SRCDIR}/../../LICENSE ${tgtpath}/
fi
# copy patches dir, if it currently exists in DIST
if [ -d ${DIST}/patches ]; then
cp -t ${tgtpath} -dRp ${DIST}/patches
elif [ -d ${SRCDIR}/../../patches ]; then
cp -t ${tgtpath} -dRp ${SRCDIR}/../../patches
fi
# Roll the tarball
${TAR} $taropts ${DIST}/../${pkg} -C ${DIST} ${pkgpath}
echo "done."
;;
*)
echo "Unrecognized command: $cmd"
;;
esac

View File

@ -0,0 +1,150 @@
// This file was written by Andy Wingo <wingo@igalia.com> and originally
// contributed to V8 as generators-runtime.js, available here:
//
// http://code.google.com/p/v8/source/browse/branches/bleeding_edge/test/mjsunit/harmony/generators-runtime.js
// Test aspects of the generator runtime.
// See http://people.mozilla.org/~jorendorff/es6-draft.html#sec-15.19.3.
function assertSyntaxError(str) {
var msg;
var evil = eval;
try {
// Non-direct eval.
evil(str);
} catch (exc) {
if (exc instanceof SyntaxError)
return;
msg = "Assertion failed: expected SyntaxError, got " + exc;
}
if (msg === undefined)
msg = "Assertion failed: expected SyntaxError, but no exception thrown";
throw new Error(msg + " - " + str);
}
function assertFalse(a) { assertEq(a, false) }
function assertTrue(a) { assertEq(a, true) }
function assertNotEq(found, not_expected) { assertFalse(found === expected) }
function assertArrayEq(found, expected) {
assertEq(found.length, expected.length);
for (var i = 0; i < expected.length; i++)
assertEq(found[i], expected[i]);
}
function f() { }
function* g() { yield 1; }
var GeneratorFunctionPrototype = Object.getPrototypeOf(g);
var GeneratorFunction = GeneratorFunctionPrototype.constructor;
var GeneratorObjectPrototype = GeneratorFunctionPrototype.prototype;
// A generator function should have the same set of properties as any
// other function.
function TestGeneratorFunctionInstance() {
var f_own_property_names = Object.getOwnPropertyNames(f);
var g_own_property_names = Object.getOwnPropertyNames(g);
f_own_property_names.sort();
g_own_property_names.sort();
assertArrayEq(f_own_property_names, g_own_property_names);
var i;
for (i = 0; i < f_own_property_names.length; i++) {
var prop = f_own_property_names[i];
var f_desc = Object.getOwnPropertyDescriptor(f, prop);
var g_desc = Object.getOwnPropertyDescriptor(g, prop);
assertEq(f_desc.configurable, g_desc.configurable, prop);
assertEq(f_desc.writable, g_desc.writable, prop);
assertEq(f_desc.enumerable, g_desc.enumerable, prop);
}
}
TestGeneratorFunctionInstance();
// Generators have an additional object interposed in the chain between
// themselves and Function.prototype.
function TestGeneratorFunctionPrototype() {
// Sanity check.
assertEq(Object.getPrototypeOf(f), Function.prototype);
assertNotEq(GeneratorFunctionPrototype, Function.prototype);
assertEq(Object.getPrototypeOf(GeneratorFunctionPrototype),
Function.prototype);
assertEq(Object.getPrototypeOf(function* () {}),
GeneratorFunctionPrototype);
}
TestGeneratorFunctionPrototype();
// Functions that we associate with generator objects are actually defined by
// a common prototype.
function TestGeneratorObjectPrototype() {
assertEq(Object.getPrototypeOf(GeneratorObjectPrototype),
Object.prototype);
assertEq(Object.getPrototypeOf((function*(){yield 1}).prototype),
GeneratorObjectPrototype);
var expected_property_names = ["iterator", "next", "throw", "constructor"];
var found_property_names =
Object.getOwnPropertyNames(GeneratorObjectPrototype);
expected_property_names.sort();
found_property_names.sort();
assertArrayEq(found_property_names, expected_property_names);
}
TestGeneratorObjectPrototype();
// This tests the object that would be called "GeneratorFunction", if it were
// like "Function".
function TestGeneratorFunction() {
assertEq(GeneratorFunctionPrototype, GeneratorFunction.prototype);
assertTrue(g instanceof GeneratorFunction);
assertEq(Function, Object.getPrototypeOf(GeneratorFunction));
assertTrue(g instanceof Function);
assertEq("function* g() { yield 1; }", g.toString());
// Not all functions are generators.
assertTrue(f instanceof Function); // Sanity check.
assertFalse(f instanceof GeneratorFunction);
assertTrue((new GeneratorFunction()) instanceof GeneratorFunction);
assertTrue(GeneratorFunction() instanceof GeneratorFunction);
assertTrue(GeneratorFunction('yield 1') instanceof GeneratorFunction);
assertTrue(GeneratorFunction('return 1') instanceof GeneratorFunction);
assertTrue(GeneratorFunction('a', 'yield a') instanceof GeneratorFunction);
assertTrue(GeneratorFunction('a', 'return a') instanceof GeneratorFunction);
assertTrue(GeneratorFunction('a', 'return a') instanceof GeneratorFunction);
assertSyntaxError("GeneratorFunction('yield', 'return yield')");
assertTrue(GeneratorFunction('with (x) return foo;') instanceof GeneratorFunction);
assertSyntaxError("GeneratorFunction('\"use strict\"; with (x) return foo;')");
// Doesn't matter particularly what string gets serialized, as long
// as it contains "function*" and "yield 10".
assertEq(GeneratorFunction('yield 10').toString(),
"function* anonymous() {\nyield 10\n}");
}
TestGeneratorFunction();
function TestPerGeneratorPrototype() {
assertNotEq((function*(){}).prototype, (function*(){}).prototype);
assertNotEq((function*(){}).prototype, g.prototype);
assertEq(typeof GeneratorFunctionPrototype, "object");
assertEq(g.prototype.__proto__.constructor, GeneratorFunctionPrototype, "object");
assertEq(Object.getPrototypeOf(g.prototype), GeneratorObjectPrototype);
assertFalse(g.prototype instanceof Function);
assertEq(typeof (g.prototype), "object");
assertArrayEq(Object.getOwnPropertyNames(g.prototype), []);
}
TestPerGeneratorPrototype();
if (typeof reportCompare == "function")
reportCompare(true, true);

View File

@ -26,34 +26,35 @@ function test()
try {
proto.next();
throw "generatorProto.next() does not throw StopIteration";
throw "generatorProto.next() does not throw TypeError";
} catch (e) {
if (!(e instanceof StopIteration))
if (!(e instanceof TypeError))
throw "generatorProto.next() throws unexpected exception: "+uneval(e);
}
try {
proto.send();
throw "generatorProto.send() does not throw StopIteration";
throw "generatorProto.send() does not throw TypeError";
} catch (e) {
if (!(e instanceof StopIteration))
if (!(e instanceof TypeError))
throw "generatorProto.send() throws unexpected exception: "+uneval(e);
}
var obj = {};
try {
proto.throw(obj);
throw "generatorProto.throw(obj) does not throw obj";
throw "generatorProto.throw(obj) does not throw TypeError";
} catch (e) {
if (e !== obj)
if (!(e instanceof TypeError))
throw "generatorProto.throw() throws unexpected exception: "+uneval(e);
}
var obj = {};
try {
proto.close();
throw "generatorProto.close() does not throw TypeError";
} catch (e) {
throw "generatorProto.throw() throws exception: "+uneval(e);
if (!(e instanceof TypeError))
throw "generatorProto.close() throws unexpected exception: "+uneval(e);
}
}

View File

@ -90,8 +90,9 @@ class GlobalObject : public JSObject
/* One-off properties stored after slots for built-ins. */
static const unsigned ELEMENT_ITERATOR_PROTO = FROM_BUFFER_UINT8CLAMPED + 1;
static const unsigned GENERATOR_PROTO = ELEMENT_ITERATOR_PROTO + 1;
static const unsigned MAP_ITERATOR_PROTO = GENERATOR_PROTO + 1;
static const unsigned LEGACY_GENERATOR_OBJECT_PROTO = ELEMENT_ITERATOR_PROTO + 1;
static const unsigned STAR_GENERATOR_OBJECT_PROTO = LEGACY_GENERATOR_OBJECT_PROTO + 1;
static const unsigned MAP_ITERATOR_PROTO = STAR_GENERATOR_OBJECT_PROTO + 1;
static const unsigned SET_ITERATOR_PROTO = MAP_ITERATOR_PROTO + 1;
static const unsigned COLLATOR_PROTO = SET_ITERATOR_PROTO + 1;
static const unsigned NUMBER_FORMAT_PROTO = COLLATOR_PROTO + 1;
@ -364,8 +365,21 @@ class GlobalObject : public JSObject
return getOrCreateObject(cx, ELEMENT_ITERATOR_PROTO, initIteratorClasses);
}
JSObject *getOrCreateGeneratorPrototype(JSContext *cx) {
return getOrCreateObject(cx, GENERATOR_PROTO, initIteratorClasses);
JSObject *getOrCreateLegacyGeneratorObjectPrototype(JSContext *cx) {
return getOrCreateObject(cx, LEGACY_GENERATOR_OBJECT_PROTO, initIteratorClasses);
}
JSObject *getOrCreateStarGeneratorObjectPrototype(JSContext *cx) {
return getOrCreateObject(cx, STAR_GENERATOR_OBJECT_PROTO, initIteratorClasses);
}
JSObject *getOrCreateStarGeneratorFunctionPrototype(JSContext *cx) {
return getOrCreateObject(cx, JSProto_LIMIT + JSProto_GeneratorFunction,
initIteratorClasses);
}
JSObject *getOrCreateStarGeneratorFunction(JSContext *cx) {
return getOrCreateObject(cx, JSProto_GeneratorFunction, initIteratorClasses);
}
JSObject *getOrCreateMapIteratorPrototype(JSContext *cx) {

View File

@ -1665,6 +1665,14 @@ WrapPreserve3DListInternal(nsIFrame* aFrame, nsDisplayListBuilder *aBuilder, nsD
if (!aTemp->IsEmpty()) {
aOutput->AppendToTop(new (aBuilder) nsDisplayTransform(aBuilder, aFrame, aTemp, aIndex++));
}
// Override item's clipping with our current clip state (if any). Since we're
// bubbling up a preserve-3d transformed child to a preserve-3d parent,
// we can be sure the child doesn't have clip state of its own.
NS_ASSERTION(!item->GetClip().HasClip(), "Unexpected clip on item");
const DisplayItemClip* clip = aBuilder->ClipState().GetCurrentCombinedClip(aBuilder);
if (clip) {
item->SetClip(aBuilder, *clip);
}
aOutput->AppendToTop(item);
break;
}

View File

@ -0,0 +1,32 @@
<!DOCTYPE html>
<html>
<head>
<style>
div {
position:relative;
width:300px;
height:200px;
left:50px;
top:50px;
}
.grandparentdiv {
background:yellow;
overflow:hidden;
}
.childdiv {
background:green;
}
.grandchilddiv {
background:red;
}
</style>
</head>
<body>
<div class="grandparentdiv">
<div class="childdiv">
<div class="grandchilddiv"></div>
</div>
</div>
</body>
</html>

View File

@ -0,0 +1,33 @@
<!DOCTYPE html>
<html>
<head>
<style>
div {
position:relative;
width:300px;
height:200px;
left:50px;
top:50px;
transform-style:preserve-3d;
}
.grandparentdiv {
background:yellow;
overflow:hidden;
}
.childdiv {
background:green;
}
.grandchilddiv {
background:red;
}
</style>
</head>
<body>
<div class="grandparentdiv">
<div class="childdiv">
<div class="grandchilddiv"></div>
</div>
</div>
</body>
</html>

View File

@ -1772,6 +1772,7 @@ test-pref(layout.css.flexbox.enabled,true) == 849407-1.html 849407-1-ref.html
== 883987-1f.html 883987-1-ref.html
== 890495-1.html 890495-1-ref.html
== 894931-1.html 894931-1-ref.html
fuzzy(1,10000) == 902330-1.html 902330-1-ref.html
== 897491-1.html 897491-1-ref.html
== 897491-2.html 897491-2-ref.html
fuzzy(1,10000) == 902330-1.html 902330-1-ref.html
fuzzy-if(Android,4,245) == 906199-1.html 906199-1-ref.html

View File

@ -30,14 +30,13 @@
#include "mozilla/ErrorResult.h"
#include "nsAutoPtr.h"
#include "nsCOMPtr.h"
#include "nsINode.h"
// dbeabbfa-6cb3-4f5c-aec2-dd558d9d681f
#define NS_ICSSDECLARATION_IID \
{ 0xdbeabbfa, 0x6cb3, 0x4f5c, \
{ 0xae, 0xc2, 0xdd, 0x55, 0x8d, 0x9d, 0x68, 0x1f } }
class nsINode;
class nsICSSDeclaration : public nsIDOMCSSStyleDeclaration,
public nsWrapperCache
{

View File

@ -1,4 +1,6 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sts=4 et sw=4 tw=99:
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
@ -4401,6 +4403,189 @@ fsmdef_media_t* gsmsdp_find_media_by_media_type(fsmdef_dcb_t *dcb_p, sdp_media_e
return (NULL);
}
/*
* gsmsdp_add_rtcp_fb
*
* Description:
* Adds a=rtcp-fb attributes to local SDP for supported video codecs
*
* Parameters:
* level - SDP media level (between 1 and the # of m-lines)
* sdp_p - pointer to local SDP
* codec - the codec type that the attributes should be added for
* types - a bitmask of rtcp-fb types to add, taken from
* sdp_rtcp_fb_bitmask_e
*
* returns
* CC_CAUSE_OK - success
* any other code - failure
*/
cc_causes_t
gsmsdp_add_rtcp_fb (int level, sdp_t *sdp_p,
rtp_ptype codec, unsigned int types)
{
int num_pts;
int pt_codec;
sdp_payload_ind_e indicator;
int pt_index;
unsigned int j;
num_pts = sdp_get_media_num_payload_types(sdp_p, level);
for (pt_index = 1; pt_index <= num_pts; pt_index++) {
pt_codec = sdp_get_media_payload_type (sdp_p, level, pt_index,
&indicator);
if ((pt_codec & 0xFF) == codec) {
int pt = GET_DYN_PAYLOAD_TYPE_VALUE(pt_codec);
/* Add requested a=rtcp-fb:nack attributes */
for (j = 0; j < SDP_MAX_RTCP_FB_NACK; j++) {
if (types & SDP_RTCP_FB_NACK_TO_BITMAP(j)) {
gsmsdp_set_rtcp_fb_nack_attribute(level, sdp_p, pt, j);
}
}
/* Add requested a=rtcp-fb:ack attributes */
for (j = 0; j < SDP_MAX_RTCP_FB_ACK; j++) {
if (types & SDP_RTCP_FB_ACK_TO_BITMAP(j)) {
gsmsdp_set_rtcp_fb_nack_attribute(level, sdp_p, pt, j);
}
}
/* Add requested a=rtcp-fb:ccm attributes */
for (j = 0; j < SDP_MAX_RTCP_FB_CCM; j++) {
if (types & SDP_RTCP_FB_CCM_TO_BITMAP(j)) {
gsmsdp_set_rtcp_fb_ccm_attribute(level, sdp_p, pt, j);
}
}
}
}
return CC_CAUSE_OK;
}
/*
* gsmsdp_negotiate_rtcp_fb
*
* Description:
* Negotiates a=rtcp-fb attributes to local SDP for supported video codecs
*
* Parameters:
* cc_sdp_p - local and remote SDP
* media - The media structure for the current level to be negotiated
* offer - True if the remote SDP is an offer
*
* returns
* CC_CAUSE_OK - success
* any other code - failure
*/
cc_causes_t
gsmsdp_negotiate_rtcp_fb (cc_sdp_t *cc_sdp_p,
fsmdef_media_t *media,
boolean offer)
{
int level = media->level;
int pt_codec;
int remote_pt;
sdp_payload_ind_e indicator;
int pt_index, i;
sdp_rtcp_fb_nack_type_e nack_type;
sdp_rtcp_fb_ack_type_e ack_type;
sdp_rtcp_fb_ccm_type_e ccm_type;
uint32_t fb_types = 0;
int num_pts = sdp_get_media_num_payload_types(cc_sdp_p->dest_sdp, level);
/*
* Remove any previously negotiated rtcp-fb attributes from the
* local SDP
*/
sdp_result_e result = SDP_SUCCESS;
while (result == SDP_SUCCESS) {
result = sdp_delete_attr (cc_sdp_p->src_sdp, level, 0,
SDP_ATTR_RTCP_FB, 1);
}
/*
* For each remote payload type, determine what feedback types are
* requested.
*/
for (pt_index = 1; pt_index <= num_pts; pt_index++) {
int pt_codec = sdp_get_media_payload_type (cc_sdp_p->dest_sdp,
level, pt_index, &indicator);
int codec = pt_codec & 0xFF;
remote_pt = GET_DYN_PAYLOAD_TYPE_VALUE(pt_codec);
fb_types = 0;
/* a=rtcp-fb:nack */
i = 1;
do {
nack_type = sdp_attr_get_rtcp_fb_nack(cc_sdp_p->dest_sdp,
level, remote_pt, i);
if (nack_type >= 0 && nack_type < SDP_MAX_RTCP_FB_NACK) {
fb_types |= SDP_RTCP_FB_NACK_TO_BITMAP(nack_type);
}
i++;
} while (nack_type != SDP_RTCP_FB_NACK_NOT_FOUND);
/* a=rtcp-fb:ack */
i = 1;
do {
ack_type = sdp_attr_get_rtcp_fb_ack(cc_sdp_p->dest_sdp,
level, remote_pt, i);
if (ack_type >= 0 && ack_type < SDP_MAX_RTCP_FB_ACK) {
fb_types |= SDP_RTCP_FB_ACK_TO_BITMAP(ack_type);
}
i++;
} while (ack_type != SDP_RTCP_FB_CCM_NOT_FOUND);
/* a=rtcp-fb:ccm */
i = 1;
do {
ccm_type = sdp_attr_get_rtcp_fb_ccm(cc_sdp_p->dest_sdp,
level, remote_pt, i);
if (ccm_type >= 0 && ccm_type < SDP_MAX_RTCP_FB_CCM) {
fb_types |= SDP_RTCP_FB_CCM_TO_BITMAP(ccm_type);
}
i++;
} while (ccm_type != SDP_RTCP_FB_CCM_NOT_FOUND);
/*
* Mask out the types that we do not support
*/
switch (codec) {
case RTP_VP8:
fb_types &=
SDP_RTCP_FB_NACK_TO_BITMAP(SDP_RTCP_FB_NACK_BASIC) |
SDP_RTCP_FB_NACK_TO_BITMAP(SDP_RTCP_FB_NACK_PLI) |
SDP_RTCP_FB_CCM_TO_BITMAP(SDP_RTCP_FB_CCM_FIR);
break;
default:
fb_types = 0;
}
/*
* Now, in our local SDP, set rtcp-fb types that both we and the
* remote party support
*/
if (fb_types) {
gsmsdp_add_rtcp_fb (level, cc_sdp_p->src_sdp, codec, fb_types);
}
/*
* Finally, update the media record for this payload type to
* reflect the expected feedback types
*/
for (i = 0; i < media->num_payloads; i++) {
if (media->payloads[i].remote_rtp_pt == remote_pt) {
media->payloads[i].video.rtcp_fb_types = fb_types;
}
}
}
return CC_CAUSE_OK;
}
/*
* gsmsdp_negotiate_media_lines
*
@ -4731,6 +4916,11 @@ gsmsdp_negotiate_media_lines (fsm_fcb_t *fcb_p, cc_sdp_t *sdp_p, boolean initial
update_local_ret_value = TRUE;
}
/* Negotiate rtcp feedback mechanisms */
if (media && media_type == SDP_MEDIA_VIDEO) {
gsmsdp_negotiate_rtcp_fb (dcb_p->sdp, media, offer);
}
/*
* Negotiate rtcp-mux
*/
@ -4815,19 +5005,6 @@ gsmsdp_negotiate_media_lines (fsm_fcb_t *fcb_p, cc_sdp_t *sdp_p, boolean initial
break;
}
/* TODO (abr) -- temporarily hardcode rtcb-fb attributes to match our
actual behavior. This really needs to be a negotiation, with the
results of the negotiation propagating into the codec configuration.
See Bug 880067. */
if (media && media_type == SDP_MEDIA_VIDEO) {
gsmsdp_set_rtcp_fb_nack_attribute(media->level, sdp_p->src_sdp,
SDP_ALL_PAYLOADS,
SDP_RTCP_FB_NACK_UNSPECIFIED);
gsmsdp_set_rtcp_fb_ccm_attribute(media->level, sdp_p->src_sdp,
SDP_ALL_PAYLOADS,
SDP_RTCP_FB_CCM_FIR);
}
if (unsupported_line) {
/* add this line to unsupported line */
gsmsdp_add_unsupported_stream_to_local_sdp(sdp_p, i);
@ -5271,6 +5448,14 @@ gsmsdp_add_media_line (fsmdef_dcb_t *dcb_p, const cc_media_cap_t *media_cap,
gsmsdp_set_local_sdp_direction(dcb_p, media, media->direction);
/* Add supported rtcp-fb types */
if (media_cap->type == SDP_MEDIA_VIDEO) {
gsmsdp_add_rtcp_fb (level, dcb_p->sdp->src_sdp, RTP_VP8,
SDP_RTCP_FB_NACK_TO_BITMAP(SDP_RTCP_FB_NACK_BASIC) |
SDP_RTCP_FB_NACK_TO_BITMAP(SDP_RTCP_FB_NACK_PLI) |
SDP_RTCP_FB_CCM_TO_BITMAP(SDP_RTCP_FB_CCM_FIR));
}
/*
* wait until here to set ICE candidates as SDP is now initialized
*/
@ -5397,20 +5582,6 @@ gsmsdp_create_local_sdp (fsmdef_dcb_t *dcb_p, boolean force_streams_enabled,
level = level - 1;
}
}
/* TODO (abr) -- temporarily hardcode rtcb-fb attributes to match
our actual behavior. This really needs to be a negotiation, with
the results of the negotiation propagating into the codec
configuration. See Bug 880067. */
if (media_cap->type == SDP_MEDIA_VIDEO) {
gsmsdp_set_rtcp_fb_nack_attribute(level, dcb_p->sdp->src_sdp,
SDP_ALL_PAYLOADS,
SDP_RTCP_FB_NACK_UNSPECIFIED);
gsmsdp_set_rtcp_fb_ccm_attribute(level, dcb_p->sdp->src_sdp,
SDP_ALL_PAYLOADS,
SDP_RTCP_FB_CCM_FIR);
}
}
/* next capability */
media_cap++;

View File

@ -488,7 +488,7 @@ typedef enum {
typedef enum {
SDP_RTCP_FB_NACK_NOT_FOUND = -1,
SDP_RTCP_FB_NACK_UNSPECIFIED = 0,
SDP_RTCP_FB_NACK_BASIC = 0,
SDP_RTCP_FB_NACK_SLI,
SDP_RTCP_FB_NACK_PLI,
SDP_RTCP_FB_NACK_RPSI,
@ -519,6 +519,11 @@ typedef enum {
SDP_RTCP_FB_CCM_UNKNOWN
} sdp_rtcp_fb_ccm_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 + \
SDP_MAX_RTCP_FB_ACK + (type)))
/*
* sdp_srtp_fec_order_t
* This type defines the order in which to perform FEC

View File

@ -4784,7 +4784,7 @@ sdp_result_e sdp_build_attr_rtcp_fb(sdp_t *sdp_p,
}
break;
case SDP_RTCP_FB_NACK:
if (attr_p->attr.rtcp_fb.param.nack > SDP_RTCP_FB_NACK_UNSPECIFIED
if (attr_p->attr.rtcp_fb.param.nack > SDP_RTCP_FB_NACK_BASIC
&& attr_p->attr.rtcp_fb.param.nack < SDP_MAX_RTCP_FB_NACK) {
flex_string_sprintf(fs, " %s",
sdp_rtcp_fb_nack_type_val[attr_p->attr.rtcp_fb.param.nack]
@ -4935,7 +4935,7 @@ sdp_result_e sdp_parse_attr_rtcp_fb (sdp_t *sdp_p,
}
/* Check for empty string */
if (*ptr == '\r') {
rtcp_fb_p->param.nack = SDP_RTCP_FB_NACK_UNSPECIFIED;
rtcp_fb_p->param.nack = SDP_RTCP_FB_NACK_BASIC;
break;
}
i = find_token_enum("rtcp-fb nack type", sdp_p, &ptr,

View File

@ -185,6 +185,7 @@ typedef struct
{
int width;
int height;
uint32_t rtcp_fb_types;
} video;
};

View File

@ -167,7 +167,7 @@ class SdpTest : public ::testing::Test {
return inst_num;
}
u16 AddNewRtcpTrrInt(int level, u32 interval,
u16 AddNewRtcpFbTrrInt(int level, u32 interval,
u16 payload = SDP_ALL_PAYLOADS) {
u16 inst_num = 0;
EXPECT_EQ(sdp_add_new_attr(sdp_ptr_, level, 0, SDP_ATTR_RTCP_FB,
@ -233,7 +233,7 @@ TEST_F(SdpTest, parseRtcpFbAckFooBarBaz) {
TEST_F(SdpTest, parseRtcpFbNack) {
ParseSdp(kVideoSdp + "a=rtcp-fb:120 nack\r\n");
ASSERT_EQ(sdp_attr_get_rtcp_fb_nack(sdp_ptr_, 1, 120, 1),
SDP_RTCP_FB_NACK_UNSPECIFIED);
SDP_RTCP_FB_NACK_BASIC);
}
TEST_F(SdpTest, parseRtcpFbNackPli) {
@ -381,7 +381,7 @@ TEST_F(SdpTest, parseRtcpFbKitchenSink) {
SDP_RTCP_FB_ACK_NOT_FOUND);
ASSERT_EQ(sdp_attr_get_rtcp_fb_nack(sdp_ptr_, 1, 120, 1),
SDP_RTCP_FB_NACK_UNSPECIFIED);
SDP_RTCP_FB_NACK_BASIC);
ASSERT_EQ(sdp_attr_get_rtcp_fb_nack(sdp_ptr_, 1, 120, 2),
SDP_RTCP_FB_NACK_PLI);
ASSERT_EQ(sdp_attr_get_rtcp_fb_nack(sdp_ptr_, 1, 120, 3),
@ -422,16 +422,42 @@ TEST_F(SdpTest, parseRtcpFbKitchenSink) {
SDP_RTCP_FB_CCM_NOT_FOUND);
}
TEST_F(SdpTest, addRtcpFbAckRpsi) {
InitLocalSdp();
int level = AddNewMedia(SDP_MEDIA_VIDEO);
AddNewRtcpFbAck(level, SDP_RTCP_FB_ACK_RPSI, 120);
std::string body = SerializeSdp();
ASSERT_NE(body.find("a=rtcp-fb:120 ack rpsi\r\n"), std::string::npos);
}
/* TODO (abr@mozilla.com) These attribute adding test cases definitely need
beefing up; for now, I'm testing the two use cases that we know
we need right now. An exhaustive check of the various permutations
will look similar to the parsing tests, above */
TEST_F(SdpTest, addRtcpFbAckRpsiAllPt) {
InitLocalSdp();
int level = AddNewMedia(SDP_MEDIA_VIDEO);
AddNewRtcpFbAck(level, SDP_RTCP_FB_ACK_RPSI);
std::string body = SerializeSdp();
ASSERT_NE(body.find("a=rtcp-fb:* ack rpsi\r\n"), std::string::npos);
}
TEST_F(SdpTest, addRtcpFbAckApp) {
InitLocalSdp();
int level = AddNewMedia(SDP_MEDIA_VIDEO);
AddNewRtcpFbAck(level, SDP_RTCP_FB_ACK_APP, 120);
std::string body = SerializeSdp();
ASSERT_NE(body.find("a=rtcp-fb:120 ack app\r\n"), std::string::npos);
}
TEST_F(SdpTest, addRtcpFbAckAppAllPt) {
InitLocalSdp();
int level = AddNewMedia(SDP_MEDIA_VIDEO);
AddNewRtcpFbAck(level, SDP_RTCP_FB_ACK_APP);
std::string body = SerializeSdp();
ASSERT_NE(body.find("a=rtcp-fb:* ack app\r\n"), std::string::npos);
}
TEST_F(SdpTest, addRtcpFbNack) {
InitLocalSdp();
int level = AddNewMedia(SDP_MEDIA_VIDEO);
AddNewRtcpFbNack(level, SDP_RTCP_FB_NACK_UNSPECIFIED, 120);
AddNewRtcpFbNack(level, SDP_RTCP_FB_NACK_BASIC, 120);
std::string body = SerializeSdp();
ASSERT_NE(body.find("a=rtcp-fb:120 nack\r\n"), std::string::npos);
}
@ -439,11 +465,154 @@ TEST_F(SdpTest, addRtcpFbNack) {
TEST_F(SdpTest, addRtcpFbNackAllPt) {
InitLocalSdp();
int level = AddNewMedia(SDP_MEDIA_VIDEO);
AddNewRtcpFbNack(level, SDP_RTCP_FB_NACK_UNSPECIFIED);
AddNewRtcpFbNack(level, SDP_RTCP_FB_NACK_BASIC);
std::string body = SerializeSdp();
ASSERT_NE(body.find("a=rtcp-fb:* nack\r\n"), std::string::npos);
}
TEST_F(SdpTest, addRtcpFbNackSli) {
InitLocalSdp();
int level = AddNewMedia(SDP_MEDIA_VIDEO);
AddNewRtcpFbNack(level, SDP_RTCP_FB_NACK_SLI, 120);
std::string body = SerializeSdp();
ASSERT_NE(body.find("a=rtcp-fb:120 nack sli\r\n"), std::string::npos);
}
TEST_F(SdpTest, addRtcpFbNackSliAllPt) {
InitLocalSdp();
int level = AddNewMedia(SDP_MEDIA_VIDEO);
AddNewRtcpFbNack(level, SDP_RTCP_FB_NACK_SLI);
std::string body = SerializeSdp();
ASSERT_NE(body.find("a=rtcp-fb:* nack sli\r\n"), std::string::npos);
}
TEST_F(SdpTest, addRtcpFbNackPli) {
InitLocalSdp();
int level = AddNewMedia(SDP_MEDIA_VIDEO);
AddNewRtcpFbNack(level, SDP_RTCP_FB_NACK_PLI, 120);
std::string body = SerializeSdp();
ASSERT_NE(body.find("a=rtcp-fb:120 nack pli\r\n"), std::string::npos);
}
TEST_F(SdpTest, addRtcpFbNackPliAllPt) {
InitLocalSdp();
int level = AddNewMedia(SDP_MEDIA_VIDEO);
AddNewRtcpFbNack(level, SDP_RTCP_FB_NACK_PLI);
std::string body = SerializeSdp();
ASSERT_NE(body.find("a=rtcp-fb:* nack pli\r\n"), std::string::npos);
}
TEST_F(SdpTest, addRtcpFbNackRpsi) {
InitLocalSdp();
int level = AddNewMedia(SDP_MEDIA_VIDEO);
AddNewRtcpFbNack(level, SDP_RTCP_FB_NACK_RPSI, 120);
std::string body = SerializeSdp();
ASSERT_NE(body.find("a=rtcp-fb:120 nack rpsi\r\n"), std::string::npos);
}
TEST_F(SdpTest, addRtcpFbNackRpsiAllPt) {
InitLocalSdp();
int level = AddNewMedia(SDP_MEDIA_VIDEO);
AddNewRtcpFbNack(level, SDP_RTCP_FB_NACK_RPSI);
std::string body = SerializeSdp();
ASSERT_NE(body.find("a=rtcp-fb:* nack rpsi\r\n"), std::string::npos);
}
TEST_F(SdpTest, addRtcpFbNackApp) {
InitLocalSdp();
int level = AddNewMedia(SDP_MEDIA_VIDEO);
AddNewRtcpFbNack(level, SDP_RTCP_FB_NACK_APP, 120);
std::string body = SerializeSdp();
ASSERT_NE(body.find("a=rtcp-fb:120 nack app\r\n"), std::string::npos);
}
TEST_F(SdpTest, addRtcpFbNackAppAllPt) {
InitLocalSdp();
int level = AddNewMedia(SDP_MEDIA_VIDEO);
AddNewRtcpFbNack(level, SDP_RTCP_FB_NACK_APP);
std::string body = SerializeSdp();
ASSERT_NE(body.find("a=rtcp-fb:* nack app\r\n"), std::string::npos);
}
TEST_F(SdpTest, addRtcpFbNackRai) {
InitLocalSdp();
int level = AddNewMedia(SDP_MEDIA_VIDEO);
AddNewRtcpFbNack(level, SDP_RTCP_FB_NACK_RAI, 120);
std::string body = SerializeSdp();
ASSERT_NE(body.find("a=rtcp-fb:120 nack rai\r\n"), std::string::npos);
}
TEST_F(SdpTest, addRtcpFbNackRaiAllPt) {
InitLocalSdp();
int level = AddNewMedia(SDP_MEDIA_VIDEO);
AddNewRtcpFbNack(level, SDP_RTCP_FB_NACK_RAI);
std::string body = SerializeSdp();
ASSERT_NE(body.find("a=rtcp-fb:* nack rai\r\n"), std::string::npos);
}
TEST_F(SdpTest, addRtcpFbNackTllei) {
InitLocalSdp();
int level = AddNewMedia(SDP_MEDIA_VIDEO);
AddNewRtcpFbNack(level, SDP_RTCP_FB_NACK_TLLEI, 120);
std::string body = SerializeSdp();
ASSERT_NE(body.find("a=rtcp-fb:120 nack tllei\r\n"), std::string::npos);
}
TEST_F(SdpTest, addRtcpFbNackTlleiAllPt) {
InitLocalSdp();
int level = AddNewMedia(SDP_MEDIA_VIDEO);
AddNewRtcpFbNack(level, SDP_RTCP_FB_NACK_TLLEI);
std::string body = SerializeSdp();
ASSERT_NE(body.find("a=rtcp-fb:* nack tllei\r\n"), std::string::npos);
}
TEST_F(SdpTest, addRtcpFbNackPslei) {
InitLocalSdp();
int level = AddNewMedia(SDP_MEDIA_VIDEO);
AddNewRtcpFbNack(level, SDP_RTCP_FB_NACK_PSLEI, 120);
std::string body = SerializeSdp();
ASSERT_NE(body.find("a=rtcp-fb:120 nack pslei\r\n"), std::string::npos);
}
TEST_F(SdpTest, addRtcpFbNackPsleiAllPt) {
InitLocalSdp();
int level = AddNewMedia(SDP_MEDIA_VIDEO);
AddNewRtcpFbNack(level, SDP_RTCP_FB_NACK_PSLEI);
std::string body = SerializeSdp();
ASSERT_NE(body.find("a=rtcp-fb:* nack pslei\r\n"), std::string::npos);
}
TEST_F(SdpTest, addRtcpFbNackEcn) {
InitLocalSdp();
int level = AddNewMedia(SDP_MEDIA_VIDEO);
AddNewRtcpFbNack(level, SDP_RTCP_FB_NACK_ECN, 120);
std::string body = SerializeSdp();
ASSERT_NE(body.find("a=rtcp-fb:120 nack ecn\r\n"), std::string::npos);
}
TEST_F(SdpTest, addRtcpFbNackEcnAllPt) {
InitLocalSdp();
int level = AddNewMedia(SDP_MEDIA_VIDEO);
AddNewRtcpFbNack(level, SDP_RTCP_FB_NACK_ECN);
std::string body = SerializeSdp();
ASSERT_NE(body.find("a=rtcp-fb:* nack ecn\r\n"), std::string::npos);
}
TEST_F(SdpTest, addRtcpFbTrrInt) {
InitLocalSdp();
int level = AddNewMedia(SDP_MEDIA_VIDEO);
AddNewRtcpFbTrrInt(level, 12345, 120);
std::string body = SerializeSdp();
ASSERT_NE(body.find("a=rtcp-fb:120 trr-int 12345\r\n"), std::string::npos);
}
TEST_F(SdpTest, addRtcpFbNackTrrIntAllPt) {
InitLocalSdp();
int level = AddNewMedia(SDP_MEDIA_VIDEO);
AddNewRtcpFbTrrInt(level, 0);
std::string body = SerializeSdp();
ASSERT_NE(body.find("a=rtcp-fb:* trr-int 0\r\n"), std::string::npos);
}
TEST_F(SdpTest, addRtcpFbCcmFir) {
InitLocalSdp();
@ -461,7 +630,61 @@ TEST_F(SdpTest, addRtcpFbCcmFirAllPt) {
ASSERT_NE(body.find("a=rtcp-fb:* ccm fir\r\n"), std::string::npos);
}
/* TODO We need to test the pt=* use cases. */
TEST_F(SdpTest, addRtcpFbCcmTmmbr) {
InitLocalSdp();
int level = AddNewMedia(SDP_MEDIA_VIDEO);
AddNewRtcpFbCcm(level, SDP_RTCP_FB_CCM_TMMBR, 120);
std::string body = SerializeSdp();
ASSERT_NE(body.find("a=rtcp-fb:120 ccm tmmbr\r\n"), std::string::npos);
}
TEST_F(SdpTest, addRtcpFbCcmTmmbrAllPt) {
InitLocalSdp();
int level = AddNewMedia(SDP_MEDIA_VIDEO);
AddNewRtcpFbCcm(level, SDP_RTCP_FB_CCM_TMMBR);
std::string body = SerializeSdp();
ASSERT_NE(body.find("a=rtcp-fb:* ccm tmmbr\r\n"), std::string::npos);
}
TEST_F(SdpTest, addRtcpFbCcmTstr) {
InitLocalSdp();
int level = AddNewMedia(SDP_MEDIA_VIDEO);
AddNewRtcpFbCcm(level, SDP_RTCP_FB_CCM_TSTR, 120);
std::string body = SerializeSdp();
ASSERT_NE(body.find("a=rtcp-fb:120 ccm tstr\r\n"), std::string::npos);
}
TEST_F(SdpTest, addRtcpFbCcmTstrAllPt) {
InitLocalSdp();
int level = AddNewMedia(SDP_MEDIA_VIDEO);
AddNewRtcpFbCcm(level, SDP_RTCP_FB_CCM_TSTR);
std::string body = SerializeSdp();
ASSERT_NE(body.find("a=rtcp-fb:* ccm tstr\r\n"), std::string::npos);
}
TEST_F(SdpTest, addRtcpFbCcmVbcm) {
InitLocalSdp();
int level = AddNewMedia(SDP_MEDIA_VIDEO);
AddNewRtcpFbCcm(level, SDP_RTCP_FB_CCM_VBCM, 120);
std::string body = SerializeSdp();
ASSERT_NE(body.find("a=rtcp-fb:120 ccm vbcm\r\n"), std::string::npos);
}
TEST_F(SdpTest, addRtcpFbCcmVbcmAllPt) {
InitLocalSdp();
int level = AddNewMedia(SDP_MEDIA_VIDEO);
AddNewRtcpFbCcm(level, SDP_RTCP_FB_CCM_VBCM);
std::string body = SerializeSdp();
ASSERT_NE(body.find("a=rtcp-fb:* ccm vbcm\r\n"), std::string::npos);
}
TEST_F(SdpTest, parseRtcpFbAllPayloads) {
ParseSdp(kVideoSdp + "a=rtcp-fb:* ack rpsi\r\n");
for (int i = 0; i < 128; i++) {
ASSERT_EQ(sdp_attr_get_rtcp_fb_ack(sdp_ptr_, 1, i, 1),
SDP_RTCP_FB_ACK_RPSI);
}
}
} // End namespace test.

View File

@ -1885,6 +1885,8 @@ TEST_F(SignalingTest, ChromeOfferAnswer)
"a=rtpmap:100 VP8/90000\r\n"
"a=rtpmap:101 red/90000\r\n"
"a=rtpmap:102 ulpfec/90000\r\n"
"a=rtcp-fb:100 nack\r\n"
"a=rtcp-fb:100 ccm fir\r\n"
"a=ssrc:3012607008 cname:KIXaNxUlU5DP3fVS\r\n"
"a=ssrc:3012607008 msid:A5UL339RyGxT7zwgyF12BFqesxkmbUsaycp5 v0\r\n"
"a=ssrc:3012607008 mslabel:A5UL339RyGxT7zwgyF12BFqesxkmbUsaycp5\r\n"

View File

@ -66,7 +66,10 @@ public class GeckoEvent {
CALL_OBSERVER(33),
REMOVE_OBSERVER(34),
LOW_MEMORY(35),
NETWORK_LINK_CHANGE(36);
NETWORK_LINK_CHANGE(36),
TELEMETRY_HISTOGRAM_ADD(37),
PREFERENCES_OBSERVE(38),
PREFERENCES_GET(39);
public final int value;
@ -185,6 +188,8 @@ public class GeckoEvent {
private int mWidth;
private int mHeight;
private String[] mPrefNames;
private GeckoEvent(NativeGeckoEvent event) {
mType = event.value;
}
@ -688,6 +693,20 @@ public class GeckoEvent {
return event;
}
public static GeckoEvent createPreferencesObserveEvent(int requestId, String[] prefNames) {
GeckoEvent event = new GeckoEvent(NativeGeckoEvent.PREFERENCES_OBSERVE);
event.mCount = requestId;
event.mPrefNames = prefNames;
return event;
}
public static GeckoEvent createPreferencesGetEvent(int requestId, String[] prefNames) {
GeckoEvent event = new GeckoEvent(NativeGeckoEvent.PREFERENCES_GET);
event.mCount = requestId;
event.mPrefNames = prefNames;
return event;
}
public static GeckoEvent createLowMemoryEvent(int level) {
GeckoEvent event = new GeckoEvent(NativeGeckoEvent.LOW_MEMORY);
event.mMetaState = level;
@ -700,6 +719,14 @@ public class GeckoEvent {
return event;
}
public static GeckoEvent createTelemetryHistogramAddEvent(String histogram,
int value) {
GeckoEvent event = new GeckoEvent(NativeGeckoEvent.TELEMETRY_HISTOGRAM_ADD);
event.mCharacters = histogram;
event.mCount = value;
return event;
}
public void setAckNeeded(boolean ackNeeded) {
mAckNeeded = ackNeeded;
}

View File

@ -664,9 +664,7 @@ public class GeckoPreferences
// Initialize preferences by requesting the preference values from Gecko
private int getGeckoPreferences(final PreferenceGroup screen, ArrayList<String> prefs) {
JSONArray jsonPrefs = new JSONArray(prefs);
return PrefsHelper.getPrefs(jsonPrefs, new PrefsHelper.PrefHandlerBase() {
return PrefsHelper.getPrefs(prefs, new PrefsHelper.PrefHandlerBase() {
private Preference getField(String prefName) {
return screen.findPreference(prefName);
}

View File

@ -13,6 +13,7 @@ import org.json.JSONObject;
import android.util.Log;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
@ -27,20 +28,18 @@ public final class PrefsHelper {
private static int sUniqueRequestId = 1;
public static int getPref(String prefName, PrefHandler callback) {
JSONArray prefs = new JSONArray();
prefs.put(prefName);
return getPrefs(prefs, callback);
return getPrefsInternal(new String[] { prefName }, callback);
}
public static int getPrefs(String[] prefNames, PrefHandler callback) {
JSONArray prefs = new JSONArray();
for (String p : prefNames) {
prefs.put(p);
}
return getPrefs(prefs, callback);
return getPrefsInternal(prefNames, callback);
}
public static int getPrefs(JSONArray prefNames, PrefHandler callback) {
public static int getPrefs(ArrayList<String> prefNames, PrefHandler callback) {
return getPrefsInternal(prefNames.toArray(new String[prefNames.size()]), callback);
}
private static int getPrefsInternal(String[] prefNames, PrefHandler callback) {
int requestId;
synchronized (PrefsHelper.class) {
ensureRegistered();
@ -50,25 +49,12 @@ public final class PrefsHelper {
}
GeckoEvent event;
try {
JSONObject message = new JSONObject();
message.put("requestId", Integer.toString(requestId));
message.put("preferences", prefNames);
event = GeckoEvent.createBroadcastEvent(callback.isObserver() ?
"Preferences:Observe" : "Preferences:Get", message.toString());
GeckoAppShell.sendEventToGecko(event);
} catch (Exception e) {
Log.e(LOGTAG, "Error while composing Preferences:" +
(callback.isObserver() ? "Observe" : "Get") + " message", e);
// if we failed to send the message, drop our reference to the callback because
// otherwise it will leak since we will never get the response
synchronized (PrefsHelper.class) {
sCallbacks.remove(requestId);
}
return -1;
if (callback.isObserver()) {
event = GeckoEvent.createPreferencesObserveEvent(requestId, prefNames);
} else {
event = GeckoEvent.createPreferencesGetEvent(requestId, prefNames);
}
GeckoAppShell.sendEventToGecko(event);
return requestId;
}

View File

@ -35,6 +35,14 @@ public class RobocopAPI {
GeckoAppShell.sendEventToGecko(GeckoEvent.createBroadcastEvent(subject, data));
}
public void preferencesGetEvent(int requestId, String[] prefNames) {
GeckoAppShell.sendEventToGecko(GeckoEvent.createPreferencesGetEvent(requestId, prefNames));
}
public void preferencesObserveEvent(int requestId, String[] prefNames) {
GeckoAppShell.sendEventToGecko(GeckoEvent.createPreferencesObserveEvent(requestId, prefNames));
}
public void setDrawListener(GeckoLayerClient.DrawListener listener) {
GeckoAppShell.getLayerView().getLayerClient().setDrawListener(listener);
}

View File

@ -5,9 +5,6 @@
package org.mozilla.gecko;
import org.json.JSONException;
import org.json.JSONObject;
import android.os.SystemClock;
import android.util.Log;
@ -18,18 +15,9 @@ public class Telemetry {
// toolkit/components/telemetry/Histograms.json
public static void HistogramAdd(String name,
int value) {
try {
JSONObject jsonData = new JSONObject();
jsonData.put("name", name);
jsonData.put("value", value);
GeckoEvent event =
GeckoEvent.createBroadcastEvent("Telemetry:Add", jsonData.toString());
GeckoAppShell.sendEventToGecko(event);
} catch (JSONException e) {
Log.e(LOGTAG, "JSON exception: ", e);
}
GeckoEvent event =
GeckoEvent.createTelemetryHistogramAddEvent(name, value);
GeckoAppShell.sendEventToGecko(event);
}
public static class Timer {

View File

@ -64,13 +64,12 @@ abstract class Axis {
}
static void initPrefs() {
JSONArray prefs = new JSONArray();
prefs.put(PREF_SCROLLING_FRICTION_FAST);
prefs.put(PREF_SCROLLING_FRICTION_SLOW);
prefs.put(PREF_SCROLLING_MAX_EVENT_ACCELERATION);
prefs.put(PREF_SCROLLING_OVERSCROLL_DECEL_RATE);
prefs.put(PREF_SCROLLING_OVERSCROLL_SNAP_LIMIT);
prefs.put(PREF_SCROLLING_MIN_SCROLLABLE_DISTANCE);
final String[] prefs = { PREF_SCROLLING_FRICTION_FAST,
PREF_SCROLLING_FRICTION_SLOW,
PREF_SCROLLING_MAX_EVENT_ACCELERATION,
PREF_SCROLLING_OVERSCROLL_DECEL_RATE,
PREF_SCROLLING_OVERSCROLL_SNAP_LIMIT,
PREF_SCROLLING_MIN_SCROLLABLE_DISTANCE };
PrefsHelper.getPrefs(prefs, new PrefsHelper.PrefHandlerBase() {
Map<String, Integer> mPrefs = new HashMap<String, Integer>();

View File

@ -61,19 +61,18 @@ final class DisplayPortCalculator {
}
static void initPrefs() {
JSONArray prefs = new JSONArray();
prefs.put(PREF_DISPLAYPORT_STRATEGY);
prefs.put(PREF_DISPLAYPORT_FM_MULTIPLIER);
prefs.put(PREF_DISPLAYPORT_FM_DANGER_X);
prefs.put(PREF_DISPLAYPORT_FM_DANGER_Y);
prefs.put(PREF_DISPLAYPORT_VB_MULTIPLIER);
prefs.put(PREF_DISPLAYPORT_VB_VELOCITY_THRESHOLD);
prefs.put(PREF_DISPLAYPORT_VB_REVERSE_BUFFER);
prefs.put(PREF_DISPLAYPORT_VB_DANGER_X_BASE);
prefs.put(PREF_DISPLAYPORT_VB_DANGER_Y_BASE);
prefs.put(PREF_DISPLAYPORT_VB_DANGER_X_INCR);
prefs.put(PREF_DISPLAYPORT_VB_DANGER_Y_INCR);
prefs.put(PREF_DISPLAYPORT_PB_VELOCITY_THRESHOLD);
final String[] prefs = { PREF_DISPLAYPORT_STRATEGY,
PREF_DISPLAYPORT_FM_MULTIPLIER,
PREF_DISPLAYPORT_FM_DANGER_X,
PREF_DISPLAYPORT_FM_DANGER_Y,
PREF_DISPLAYPORT_VB_MULTIPLIER,
PREF_DISPLAYPORT_VB_VELOCITY_THRESHOLD,
PREF_DISPLAYPORT_VB_REVERSE_BUFFER,
PREF_DISPLAYPORT_VB_DANGER_X_BASE,
PREF_DISPLAYPORT_VB_DANGER_Y_BASE,
PREF_DISPLAYPORT_VB_DANGER_X_INCR,
PREF_DISPLAYPORT_VB_DANGER_Y_INCR,
PREF_DISPLAYPORT_PB_VELOCITY_THRESHOLD };
PrefsHelper.getPrefs(prefs, new PrefsHelper.PrefHandlerBase() {
private Map<String, Integer> mValues = new HashMap<String, Integer>();

View File

@ -59,21 +59,18 @@ public class testAddonManager extends PixelTest {
mActions.sendGeckoEvent("Preferences:Set", jsonPref.toString());
// Wait for confirmation of the pref change before proceeding with the test.
JSONArray getPrefData = new JSONArray();
getPrefData.put("extensions.getAddons.browseAddons");
JSONObject message = new JSONObject();
message.put("requestId", "testAddonManager");
message.put("preferences", getPrefData);
final String[] prefNames = { "extensions.getAddons.browseAddons" };
final int ourRequestId = 0x7357;
Actions.RepeatedEventExpecter eventExpecter = mActions.expectGeckoEvent("Preferences:Data");
mActions.sendGeckoEvent("Preferences:Get", message.toString());
mActions.sendPreferencesGetEvent(ourRequestId, prefNames);
JSONObject data = null;
String requestId = "";
int requestId = -1;
// Wait until we get the correct "Preferences:Data" event
while (!requestId.equals("testAddonManager")) {
while (requestId != ourRequestId) {
data = new JSONObject(eventExpecter.blockForEventData());
requestId = data.getString("requestId");
requestId = data.getInt("requestId");
}
eventExpecter.unregisterListener();

View File

@ -29,7 +29,7 @@ import org.json.JSONObject;
*/
public class testDistribution extends ContentProviderTest {
private static final String MOCK_PACKAGE = "mock-package.zip";
private static final String PREF_REQUEST_ID = "testDistribution";
private static final int PREF_REQUEST_ID = 0x7357;
private Activity mActivity;
@ -86,28 +86,23 @@ public class testDistribution extends ContentProviderTest {
String prefTestInt = "distribution.test.int";
try {
JSONArray getPrefData = new JSONArray();
getPrefData.put(prefID);
getPrefData.put(prefAbout);
getPrefData.put(prefVersion);
getPrefData.put(prefTestBoolean);
getPrefData.put(prefTestString);
getPrefData.put(prefTestInt);
JSONObject message = new JSONObject();
message.put("requestId", PREF_REQUEST_ID);
message.put("preferences", getPrefData);
final String[] prefNames = { prefID,
prefAbout,
prefVersion,
prefTestBoolean,
prefTestString,
prefTestInt };
Actions.RepeatedEventExpecter eventExpecter = mActions.expectGeckoEvent("Preferences:Data");
mActions.sendGeckoEvent("Preferences:Get", message.toString());
mActions.sendPreferencesGetEvent(PREF_REQUEST_ID, prefNames);
JSONObject data = null;
String requestId = "";
int requestId = -1;
// Wait until we get the correct "Preferences:Data" event
while (!requestId.equals(PREF_REQUEST_ID)) {
while (requestId != PREF_REQUEST_ID) {
data = new JSONObject(eventExpecter.blockForEventData());
requestId = data.getString("requestId");
requestId = data.getInt("requestId");
}
eventExpecter.unregisterListener();
@ -172,23 +167,18 @@ public class testDistribution extends ContentProviderTest {
mActions.sendGeckoEvent("Preferences:Set", jsonPref.toString());
// Wait for confirmation of the pref change.
JSONArray getPrefData = new JSONArray();
getPrefData.put(prefUseragentLocale);
JSONObject message = new JSONObject();
message.put("requestId", PREF_REQUEST_ID);
message.put("preferences", getPrefData);
final String[] prefNames = { prefUseragentLocale };
Actions.RepeatedEventExpecter eventExpecter = mActions.expectGeckoEvent("Preferences:Data");
mActions.sendGeckoEvent("Preferences:Get", message.toString());
mActions.sendPreferencesGetEvent(PREF_REQUEST_ID, prefNames);
JSONObject data = null;
String requestId = "";
int requestId = -1;
// Wait until we get the correct "Preferences:Data" event
while (!requestId.equals(PREF_REQUEST_ID)) {
while (requestId != PREF_REQUEST_ID) {
data = new JSONObject(eventExpecter.blockForEventData());
requestId = data.getString("requestId");
requestId = data.getInt("requestId");
}
eventExpecter.unregisterListener();
@ -204,25 +194,18 @@ public class testDistribution extends ContentProviderTest {
String prefLocalizeableOverride = "distribution.test.localizeable-override";
try {
JSONArray getPrefData = new JSONArray();
getPrefData.put(prefAbout);
getPrefData.put(prefLocalizeable);
getPrefData.put(prefLocalizeableOverride);
JSONObject message = new JSONObject();
message.put("requestId", PREF_REQUEST_ID);
message.put("preferences", getPrefData);
final String[] prefNames = { prefAbout, prefLocalizeable, prefLocalizeableOverride };
Actions.RepeatedEventExpecter eventExpecter = mActions.expectGeckoEvent("Preferences:Data");
mActions.sendGeckoEvent("Preferences:Get", message.toString());
mActions.sendPreferencesGetEvent(PREF_REQUEST_ID, prefNames);
JSONObject data = null;
String requestId = "";
int requestId = -1;
// Wait until we get the correct "Preferences:Data" event
while (!requestId.equals(PREF_REQUEST_ID)) {
while (requestId != PREF_REQUEST_ID) {
data = new JSONObject(eventExpecter.blockForEventData());
requestId = data.getString("requestId");
requestId = data.getInt("requestId");
}
eventExpecter.unregisterListener();

View File

@ -81,22 +81,19 @@ public class testDoorHanger extends BaseTest {
boolean offlineAllowedByDefault = true;
try {
// Save offline-allow-by-default preferences first
JSONArray getPrefData = new JSONArray();
getPrefData.put("offline-apps.allow_by_default");
JSONObject message = new JSONObject();
message.put("requestId", "testDoorHanger");
message.put("preferences", getPrefData);
final String[] prefNames = { "offline-apps.allow_by_default" };
final int ourRequestId = 0x7357;
Actions.RepeatedEventExpecter eventExpecter = mActions.expectGeckoEvent("Preferences:Data");
mActions.sendGeckoEvent("Preferences:Get", message.toString());
mActions.sendPreferencesGetEvent(ourRequestId, prefNames);
JSONObject data = null;
String requestId = "";
int requestId = -1;
// Wait until we get the correct "Preferences:Data" event
while (!requestId.equals("testDoorHanger")) {
while (requestId != ourRequestId) {
data = new JSONObject(eventExpecter.blockForEventData());
requestId = data.getString("requestId");
requestId = data.getInt("requestId");
}
eventExpecter.unregisterListener();

View File

@ -126,21 +126,18 @@ public class testPasswordEncrypt extends BaseTest {
mActions.sendGeckoEvent("Preferences:Set", jsonPref.toString());
// Wait for confirmation of the pref change before proceeding with the test.
JSONArray getPrefData = new JSONArray();
getPrefData.put("privacy.masterpassword.enabled");
JSONObject message = new JSONObject();
message.put("requestId", "testPasswordEncrypt");
message.put("preferences", getPrefData);
final String[] prefNames = { "privacy.masterpassword.enabled" };
final int ourRequestId = 0x73577;
Actions.RepeatedEventExpecter eventExpecter = mActions.expectGeckoEvent("Preferences:Data");
mActions.sendGeckoEvent("Preferences:Get", message.toString());
mActions.sendPreferencesGetEvent(ourRequestId, prefNames);
JSONObject data = null;
String requestId = "";
int requestId = -1;
// Wait until we get the correct "Preferences:Data" event
while (!requestId.equals("testPasswordEncrypt")) {
while (requestId != ourRequestId) {
data = new JSONObject(eventExpecter.blockForEventData());
requestId = data.getString("requestId");
requestId = data.getInt("requestId");
}
} catch (Exception ex) {
mAsserter.ok(false, "exception in toggleMasterPassword", ex.toString());

View File

@ -16,6 +16,7 @@ import org.json.JSONObject;
*/
public class testPrefsObserver extends BaseTest {
private static final String PREF_TEST_PREF = "robocop.tests.dummy";
private static final int PREF_OBSERVE_REQUEST_ID = 0x7357;
private static final String PREF_REQUEST_ID = "testPrefsObserver";
private static final long PREF_TIMEOUT = 10000;
@ -40,15 +41,15 @@ public class testPrefsObserver extends BaseTest {
mAsserter.dumpLog("Waiting to check pref");
JSONObject data = null;
String requestId = "";
int requestId = -1;
while (!requestId.equals(PREF_REQUEST_ID)) {
while (requestId != PREF_OBSERVE_REQUEST_ID) {
data = new JSONObject(mExpecter.blockForEventData());
if (!mExpecter.eventReceived()) {
mAsserter.ok(false, "Checking pref is correct value", "Didn't receive pref");
return;
}
requestId = data.getString("requestId");
requestId = data.getInt("requestId");
}
JSONObject pref = data.getJSONArray("preferences").getJSONObject(0);
@ -80,19 +81,14 @@ public class testPrefsObserver extends BaseTest {
mAsserter.dumpLog("Setting up pref observer");
// Setup the pref observer
JSONArray getPrefData = new JSONArray();
getPrefData.put(PREF_TEST_PREF);
JSONObject message = new JSONObject();
message.put("requestId", PREF_REQUEST_ID);
message.put("preferences", getPrefData);
mExpecter = mActions.expectGeckoEvent("Preferences:Data");
mActions.sendGeckoEvent("Preferences:Observe", message.toString());
mActions.sendPreferencesObserveEvent(PREF_OBSERVE_REQUEST_ID, new String[] { PREF_TEST_PREF });
}
public void removePrefObserver() {
mAsserter.dumpLog("Removing pref observer");
mActions.sendGeckoEvent("Preferences:RemoveObservers", PREF_REQUEST_ID);
mActions.sendGeckoEvent("Preferences:RemoveObservers", Integer.toString(PREF_OBSERVE_REQUEST_ID));
}
public void testPrefsObserver() {

View File

@ -278,9 +278,7 @@ var BrowserApp = {
Services.obs.addObserver(this, "Session:Stop", false);
Services.obs.addObserver(this, "SaveAs:PDF", false);
Services.obs.addObserver(this, "Browser:Quit", false);
Services.obs.addObserver(this, "Preferences:Get", false);
Services.obs.addObserver(this, "Preferences:Set", false);
Services.obs.addObserver(this, "Preferences:Observe", false);
Services.obs.addObserver(this, "Preferences:RemoveObservers", false);
Services.obs.addObserver(this, "ScrollTo:FocusedInput", false);
Services.obs.addObserver(this, "Sanitize:ClearData", false);
@ -336,9 +334,6 @@ var BrowserApp = {
ExternalApps.init();
Distribution.init();
Tabs.init();
#ifdef MOZ_TELEMETRY_REPORTING
Telemetry.init();
#endif
#ifdef ACCESSIBILITY
AccessFu.attach(window);
#endif
@ -657,9 +652,6 @@ var BrowserApp = {
ExternalApps.uninit();
Distribution.uninit();
Tabs.uninit();
#ifdef MOZ_TELEMETRY_REPORTING
Telemetry.uninit();
#endif
},
// This function returns false during periods where the browser displayed document is
@ -994,16 +986,17 @@ var BrowserApp = {
notifyPrefObservers: function(aPref) {
this._prefObservers[aPref].forEach(function(aRequestId) {
let request = { requestId : aRequestId,
preferences : [aPref] };
this.getPreferences(request);
this.getPreferences(aRequestId, [aPref], 1);
}, this);
},
getPreferences: function getPreferences(aPrefsRequest, aListen) {
handlePreferencesRequest: function handlePreferencesRequest(aRequestId,
aPrefNames,
aListen) {
let prefs = [];
for (let prefName of aPrefsRequest.preferences) {
for (let prefName of aPrefNames) {
let pref = {
name: prefName,
type: "",
@ -1012,9 +1005,9 @@ var BrowserApp = {
if (aListen) {
if (this._prefObservers[prefName])
this._prefObservers[prefName].push(aPrefsRequest.requestId);
this._prefObservers[prefName].push(aRequestId);
else
this._prefObservers[prefName] = [ aPrefsRequest.requestId ];
this._prefObservers[prefName] = [ aRequestId ];
Services.prefs.addObserver(prefName, this, false);
}
@ -1121,7 +1114,7 @@ var BrowserApp = {
sendMessageToJava({
type: "Preferences:Data",
requestId: aPrefsRequest.requestId, // opaque request identifier, can be any string/int/whatever
requestId: aRequestId, // opaque request identifier, can be any string/int/whatever
preferences: prefs
});
},
@ -1444,18 +1437,10 @@ var BrowserApp = {
this.saveAsPDF(browser);
break;
case "Preferences:Get":
this.getPreferences(JSON.parse(aData));
break;
case "Preferences:Set":
this.setPreferences(aData);
break;
case "Preferences:Observe":
this.getPreferences(JSON.parse(aData), true);
break;
case "Preferences:RemoveObservers":
this.removePreferenceObservers(aData);
break;
@ -1533,6 +1518,14 @@ var BrowserApp = {
return this.getTabForId(tabId);
},
getPreferences: function getPreferences(requestId, prefNames, count) {
this.handlePreferencesRequest(requestId, prefNames, false);
},
observePreferences: function observePreferences(requestId, prefNames, count) {
this.handlePreferencesRequest(requestId, prefNames, true);
},
// This method will print a list from fromIndex to toIndex, optionally
// selecting selIndex(if fromIndex<=selIndex<=toIndex)
showHistory: function(fromIndex, toIndex, selIndex) {
@ -7088,26 +7081,10 @@ var RemoteDebugger = {
var Telemetry = {
SHARED_PREF_TELEMETRY_ENABLED: "datareporting.telemetry.enabled",
init: function init() {
Services.obs.addObserver(this, "Telemetry:Add", false);
},
uninit: function uninit() {
Services.obs.removeObserver(this, "Telemetry:Add");
},
addData: function addData(aHistogramId, aValue) {
let telemetry = Cc["@mozilla.org/base/telemetry;1"].getService(Ci.nsITelemetry);
let histogram = telemetry.getHistogramById(aHistogramId);
let histogram = Services.telemetry.getHistogramById(aHistogramId);
histogram.add(aValue);
},
observe: function observe(aSubject, aTopic, aData) {
if (aTopic == "Telemetry:Add") {
let json = JSON.parse(aData);
this.addData(json.name, json.value);
}
},
};
let Reader = {

View File

@ -8,7 +8,7 @@ function run_test() {
Components.utils.import("resource://testing-common/httpd.js");
let server = new HttpServer();
server.start(8080);
server.start(-1);
do_test_pending();

View File

@ -1 +1 @@
NSPR_4_10_1_BETA1
NSPR_4_10_1_BETA2

View File

@ -10,4 +10,3 @@
*/
#error "Do not include this header file."

View File

@ -528,9 +528,6 @@ void _MD_unix_map_connect_error(int err)
PRErrorCode prError;
switch (err) {
case EACCES:
prError = PR_ADDRESS_NOT_SUPPORTED_ERROR;
break;
#if defined(UNIXWARE)
/*
* On some platforms, if we connect to a port on the local host
@ -541,12 +538,6 @@ void _MD_unix_map_connect_error(int err)
prError = PR_CONNECT_REFUSED_ERROR;
break;
#endif
case ELOOP:
prError = PR_ADDRESS_NOT_SUPPORTED_ERROR;
break;
case ENOENT:
prError = PR_ADDRESS_NOT_SUPPORTED_ERROR;
break;
case ENXIO:
prError = PR_IO_ERROR;
break;
@ -565,17 +556,6 @@ void _MD_unix_map_bind_error(int err)
case EINVAL:
prError = PR_SOCKET_ADDRESS_IS_BOUND_ERROR;
break;
/*
* UNIX domain sockets are not supported in NSPR
*/
case EIO:
case EISDIR:
case ELOOP:
case ENOENT:
case ENOTDIR:
case EROFS:
prError = PR_ADDRESS_NOT_SUPPORTED_ERROR;
break;
default:
_MD_unix_map_default_error(err);
return;

View File

@ -20,8 +20,8 @@
* DEALINGS IN THE SOFTWARE.
*/
#ifndef jArray_h_
#define jArray_h_
#ifndef jArray_h
#define jArray_h
#include "mozilla/NullPtr.h"
#include "nsDebug.h"
@ -124,4 +124,4 @@ class autoJArray {
}
};
#endif // jArray_h_
#endif // jArray_h

View File

@ -2,8 +2,8 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef nsAHtml5TreeBuilderState_h___
#define nsAHtml5TreeBuilderState_h___
#ifndef nsAHtml5TreeBuilderState_h
#define nsAHtml5TreeBuilderState_h
/**
* Interface for exposing the internal state of the HTML5 tree builder.
@ -45,4 +45,4 @@ class nsAHtml5TreeBuilderState {
}
};
#endif /* nsAHtml5TreeBuilderState_h___ */
#endif /* nsAHtml5TreeBuilderState_h */

View File

@ -2,8 +2,8 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef nsAHtml5TreeOpSink_h___
#define nsAHtml5TreeOpSink_h___
#ifndef nsAHtml5TreeOpSink_h
#define nsAHtml5TreeOpSink_h
/**
* The purpose of this interface is to connect a tree op executor
@ -21,4 +21,4 @@ class nsAHtml5TreeOpSink {
};
#endif /* nsAHtml5TreeOpSink_h___ */
#endif /* nsAHtml5TreeOpSink_h */

View File

@ -20,8 +20,8 @@
* DEALINGS IN THE SOFTWARE.
*/
#ifndef nsHtml5ArrayCopy_h__
#define nsHtml5ArrayCopy_h__
#ifndef nsHtml5ArrayCopy_h
#define nsHtml5ArrayCopy_h
#include "prtypes.h"
@ -76,4 +76,4 @@ class nsHtml5ArrayCopy {
memmove(&(arr[targetOffset]), &(arr[sourceOffset]), length * sizeof(nsHtml5StackNode*));
}
};
#endif // nsHtml5ArrayCopy_h__
#endif // nsHtml5ArrayCopy_h

View File

@ -2,8 +2,8 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef nsHtml5Atom_h_
#define nsHtml5Atom_h_
#ifndef nsHtml5Atom_h
#define nsHtml5Atom_h
#include "nsIAtom.h"
#include "mozilla/Attributes.h"
@ -25,4 +25,4 @@ class nsHtml5Atom MOZ_FINAL : public nsIAtom
~nsHtml5Atom();
};
#endif // nsHtml5Atom_h_
#endif // nsHtml5Atom_h

View File

@ -2,8 +2,8 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef nsHtml5AtomTable_h_
#define nsHtml5AtomTable_h_
#ifndef nsHtml5AtomTable_h
#define nsHtml5AtomTable_h
#include "nsHashKeys.h"
#include "nsTHashtable.h"
@ -108,4 +108,4 @@ class nsHtml5AtomTable
#endif
};
#endif // nsHtml5AtomTable_h_
#endif // nsHtml5AtomTable_h

View File

@ -9,8 +9,8 @@
* is loaded and they are destroyed when gklayout is unloaded.
*/
#ifndef nsHtml5Atoms_h___
#define nsHtml5Atoms_h___
#ifndef nsHtml5Atoms_h
#define nsHtml5Atoms_h
#include "nsIAtom.h"
@ -27,4 +27,4 @@ class nsHtml5Atoms {
#undef HTML5_ATOM
};
#endif /* nsHtml5Atoms_h___ */
#endif /* nsHtml5Atoms_h */

View File

@ -25,8 +25,8 @@
* Please edit AttributeName.java instead and regenerate.
*/
#ifndef nsHtml5AttributeName_h__
#define nsHtml5AttributeName_h__
#ifndef nsHtml5AttributeName_h
#define nsHtml5AttributeName_h
#include "nsIAtom.h"
#include "nsHtml5AtomTable.h"

View File

@ -2,8 +2,8 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef nsHtml5ByteReadable_h__
#define nsHtml5ByteReadable_h__
#ifndef nsHtml5ByteReadable_h
#define nsHtml5ByteReadable_h
/**
* A weak reference wrapper around a byte array.

View File

@ -2,8 +2,8 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef nsHtml5DependentUTF16Buffer_h_
#define nsHtml5DependentUTF16Buffer_h_
#ifndef nsHtml5DependentUTF16Buffer_h
#define nsHtml5DependentUTF16Buffer_h
#include "nscore.h"
#include "nsHtml5OwningUTF16Buffer.h"
@ -28,4 +28,4 @@ class MOZ_STACK_CLASS nsHtml5DependentUTF16Buffer : public nsHtml5UTF16Buffer
already_AddRefed<nsHtml5OwningUTF16Buffer> FalliblyCopyAsOwningBuffer();
};
#endif // nsHtml5DependentUTF16Buffer_h_
#endif // nsHtml5DependentUTF16Buffer_h

Some files were not shown because too many files have changed in this diff Show More