Merge inbound to m-c

This commit is contained in:
Wes Kocher 2013-11-06 18:10:46 -08:00
commit 723c3d7877
99 changed files with 1612 additions and 587 deletions

View File

@ -735,6 +735,12 @@ var Input = {
case 'swipeleft1':
this.moveCursor('movePrevious', 'Simple', 'gesture');
break;
case 'swipeup1':
this.contextAction('backward');
break;
case 'swipedown1':
this.contextAction('forward');
break;
case 'exploreend1':
this.activateCurrent(null, true);
break;
@ -859,6 +865,12 @@ var Input = {
origin: 'top', inputType: aInputType});
},
contextAction: function contextAction(aDirection) {
// XXX: For now, the only supported context action is adjusting a range.
let mm = Utils.getMessageManager(Utils.CurrentBrowser);
mm.sendAsyncMessage('AccessFu:AdjustRange', {direction: aDirection});
},
moveByGranularity: function moveByGranularity(aDetails) {
const MOVEMENT_GRANULARITY_PARAGRAPH = 8;

View File

@ -331,6 +331,23 @@ function scroll(aMessage) {
}
}
function adjustRange(aMessage) {
function sendUpDownKey(aAccessible) {
let evt = content.document.createEvent('KeyboardEvent');
let keycode = aMessage.json.direction == 'forward' ?
content.KeyEvent.DOM_VK_DOWN : content.KeyEvent.DOM_VK_UP;
evt.initKeyEvent(
"keypress", false, true, null, false, false, false, false, keycode, 0);
if (aAccessible.DOMNode) {
aAccessible.DOMNode.dispatchEvent(evt);
}
}
let position = Utils.getVirtualCursor(content.document).position;
if (!forwardToChild(aMessage, adjustRange, position)) {
sendUpDownKey(position);
}
}
addMessageListener(
'AccessFu:Start',
function(m) {
@ -344,6 +361,7 @@ addMessageListener(
addMessageListener('AccessFu:Activate', activateCurrent);
addMessageListener('AccessFu:ContextMenu', activateContextMenu);
addMessageListener('AccessFu:Scroll', scroll);
addMessageListener('AccessFu:AdjustRange', adjustRange);
addMessageListener('AccessFu:MoveCaret', moveCaret);
addMessageListener('AccessFu:MoveByGranularity', moveByGranularity);

View File

@ -9,6 +9,7 @@ interface nsIDOMDOMStringList;
interface nsIDOMWindow;
interface nsIDocShell;
interface nsIContent;
interface nsIPrincipal;
/**
* Message managers provide a way for chrome-privileged JS code to
@ -156,14 +157,15 @@ interface nsIMessageListener : nsISupports
* receiveMessage is called with one parameter, which has the following
* properties:
* {
* target: %the target of the message. Either an element owning
* the message manager, or message manager itself if no
* element owns it%
* name: %message name%,
* sync: %true or false%.
* data: %structured clone of the sent message data%,
* json: %same as .data, deprecated%,
* objects: %named table of jsvals/objects, or null%
* target: %the target of the message. Either an element owning
* the message manager, or message manager itself if no
* element owns it%
* name: %message name%,
* sync: %true or false%.
* data: %structured clone of the sent message data%,
* json: %same as .data, deprecated%,
* objects: %named table of jsvals/objects, or null%
* principal: %principal for the window app
* }
*
* Each listener is invoked with its own copy of the message
@ -231,7 +233,7 @@ interface nsIMessageListenerManager : nsISupports
* messages that are only delivered to its one parent-process message
* manager.
*/
[scriptable, builtinclass, uuid(7f23767d-0f39-40c1-a22d-d3ab8a481f9d)]
[scriptable, builtinclass, uuid(d6b0d851-43e6-426d-9f13-054bc0198175)]
interface nsIMessageSender : nsIMessageListenerManager
{
/**
@ -252,7 +254,8 @@ interface nsIMessageSender : nsIMessageListenerManager
[implicit_jscontext, optional_argc]
void sendAsyncMessage([optional] in AString messageName,
[optional] in jsval obj,
[optional] in jsval objects);
[optional] in jsval objects,
[optional] in nsIPrincipal principal);
};
/**
@ -289,7 +292,7 @@ interface nsIMessageBroadcaster : nsIMessageListenerManager
nsIMessageListenerManager getChildAt(in unsigned long aIndex);
};
[scriptable, builtinclass, uuid(79eeb70f-58e3-4d32-b46f-106f42ada12b)]
[scriptable, builtinclass, uuid(7fda0941-9dcc-448b-bd39-16373c5b4003)]
interface nsISyncMessageSender : nsIMessageSender
{
/**
@ -300,7 +303,8 @@ interface nsISyncMessageSender : nsIMessageSender
[implicit_jscontext, optional_argc]
jsval sendSyncMessage([optional] in AString messageName,
[optional] in jsval obj,
[optional] in jsval objects);
[optional] in jsval objects,
[optional] in nsIPrincipal principal);
/**
* Like |sendSyncMessage()|, except re-entrant. New RPC messages may be
@ -314,7 +318,8 @@ interface nsISyncMessageSender : nsIMessageSender
[implicit_jscontext, optional_argc]
jsval sendRpcMessage([optional] in AString messageName,
[optional] in jsval obj,
[optional] in jsval objects);
[optional] in jsval objects,
[optional] in nsIPrincipal principal);
};
[scriptable, builtinclass, uuid(894ff2d4-39a3-4df8-9d76-8ee329975488)]

View File

@ -2215,8 +2215,10 @@ public:
nsFrameLoader* aFrameLoader,
const nsAString& aMessage,
const StructuredCloneData& aData,
JS::Handle<JSObject *> aCpows)
: mRuntime(js::GetRuntime(aCx)), mFrameLoader(aFrameLoader), mMessage(aMessage), mCpows(aCpows)
JS::Handle<JSObject *> aCpows,
nsIPrincipal* aPrincipal)
: mRuntime(js::GetRuntime(aCx)), mFrameLoader(aFrameLoader)
, mMessage(aMessage), mCpows(aCpows), mPrincipal(aPrincipal)
{
if (aData.mDataLength && !mData.copy(aData.mData, aData.mDataLength)) {
NS_RUNTIMEABORT("OOM");
@ -2249,7 +2251,7 @@ public:
nsRefPtr<nsFrameMessageManager> mm = tabChild->GetInnerManager();
mm->ReceiveMessage(static_cast<EventTarget*>(tabChild), mMessage,
false, &data, &cpows, nullptr);
false, &data, &cpows, mPrincipal, nullptr);
}
return NS_OK;
}
@ -2259,13 +2261,15 @@ public:
JSAutoStructuredCloneBuffer mData;
StructuredCloneClosure mClosure;
JSObject* mCpows;
nsCOMPtr<nsIPrincipal> mPrincipal;
};
bool
nsFrameLoader::DoSendAsyncMessage(JSContext* aCx,
const nsAString& aMessage,
const StructuredCloneData& aData,
JS::Handle<JSObject *> aCpows)
JS::Handle<JSObject *> aCpows,
nsIPrincipal* aPrincipal)
{
TabParent* tabParent = mRemoteBrowser;
if (tabParent) {
@ -2278,11 +2282,14 @@ nsFrameLoader::DoSendAsyncMessage(JSContext* aCx,
if (aCpows && !cp->GetCPOWManager()->Wrap(aCx, aCpows, &cpows)) {
return false;
}
return tabParent->SendAsyncMessage(nsString(aMessage), data, cpows);
return tabParent->SendAsyncMessage(nsString(aMessage), data, cpows,
aPrincipal);
}
if (mChildMessageManager) {
nsRefPtr<nsIRunnable> ev = new nsAsyncMessageToChild(aCx, this, aMessage, aData, aCpows);
nsRefPtr<nsIRunnable> ev = new nsAsyncMessageToChild(aCx, this, aMessage,
aData, aCpows,
aPrincipal);
NS_DispatchToCurrentThread(ev);
return true;
}

View File

@ -184,7 +184,8 @@ public:
virtual bool DoSendAsyncMessage(JSContext* aCx,
const nsAString& aMessage,
const mozilla::dom::StructuredCloneData& aData,
JS::Handle<JSObject *> aCpows);
JS::Handle<JSObject *> aCpows,
nsIPrincipal* aPrincipal) MOZ_OVERRIDE;
virtual bool CheckPermission(const nsAString& aPermission) MOZ_OVERRIDE;
virtual bool CheckManifestURL(const nsAString& aManifestURL) MOZ_OVERRIDE;
virtual bool CheckAppHasPermission(const nsAString& aPermission) MOZ_OVERRIDE;

View File

@ -500,28 +500,33 @@ NS_IMETHODIMP
nsFrameMessageManager::SendSyncMessage(const nsAString& aMessageName,
const JS::Value& aJSON,
const JS::Value& aObjects,
nsIPrincipal* aPrincipal,
JSContext* aCx,
uint8_t aArgc,
JS::Value* aRetval)
{
return SendMessage(aMessageName, aJSON, aObjects, aCx, aArgc, aRetval, true);
return SendMessage(aMessageName, aJSON, aObjects, aPrincipal, aCx, aArgc,
aRetval, true);
}
NS_IMETHODIMP
nsFrameMessageManager::SendRpcMessage(const nsAString& aMessageName,
const JS::Value& aJSON,
const JS::Value& aObjects,
nsIPrincipal* aPrincipal,
JSContext* aCx,
uint8_t aArgc,
JS::Value* aRetval)
{
return SendMessage(aMessageName, aJSON, aObjects, aCx, aArgc, aRetval, false);
return SendMessage(aMessageName, aJSON, aObjects, aPrincipal, aCx, aArgc,
aRetval, false);
}
nsresult
nsFrameMessageManager::SendMessage(const nsAString& aMessageName,
const JS::Value& aJSON,
const JS::Value& aObjects,
nsIPrincipal* aPrincipal,
JSContext* aCx,
uint8_t aArgc,
JS::Value* aRetval,
@ -556,7 +561,8 @@ nsFrameMessageManager::SendMessage(const nsAString& aMessageName,
InfallibleTArray<nsString> retval;
sSendingSyncMessage |= aIsSync;
bool rv = mCallback->DoSendBlockingMessage(aCx, aMessageName, data, objects, &retval, aIsSync);
bool rv = mCallback->DoSendBlockingMessage(aCx, aMessageName, data, objects,
aPrincipal, &retval, aIsSync);
if (aIsSync) {
sSendingSyncMessage = false;
}
@ -591,19 +597,20 @@ nsresult
nsFrameMessageManager::DispatchAsyncMessageInternal(JSContext* aCx,
const nsAString& aMessage,
const StructuredCloneData& aData,
JS::Handle<JSObject *> aCpows)
JS::Handle<JSObject *> aCpows,
nsIPrincipal* aPrincipal)
{
if (mIsBroadcaster) {
int32_t len = mChildManagers.Count();
for (int32_t i = 0; i < len; ++i) {
static_cast<nsFrameMessageManager*>(mChildManagers[i])->
DispatchAsyncMessageInternal(aCx, aMessage, aData, aCpows);
DispatchAsyncMessageInternal(aCx, aMessage, aData, aCpows, aPrincipal);
}
return NS_OK;
}
NS_ENSURE_TRUE(mCallback, NS_ERROR_NOT_INITIALIZED);
if (!mCallback->DoSendAsyncMessage(aCx, aMessage, aData, aCpows)) {
if (!mCallback->DoSendAsyncMessage(aCx, aMessage, aData, aCpows, aPrincipal)) {
return NS_ERROR_FAILURE;
}
return NS_OK;
@ -613,6 +620,7 @@ nsresult
nsFrameMessageManager::DispatchAsyncMessage(const nsAString& aMessageName,
const JS::Value& aJSON,
const JS::Value& aObjects,
nsIPrincipal* aPrincipal,
JSContext* aCx,
uint8_t aArgc)
{
@ -632,7 +640,8 @@ nsFrameMessageManager::DispatchAsyncMessage(const nsAString& aMessageName,
data.mData = buffer.data();
data.mDataLength = buffer.nbytes();
return DispatchAsyncMessageInternal(aCx, aMessageName, data, objects);
return DispatchAsyncMessageInternal(aCx, aMessageName, data, objects,
aPrincipal);
}
@ -642,10 +651,12 @@ NS_IMETHODIMP
nsFrameMessageManager::SendAsyncMessage(const nsAString& aMessageName,
const JS::Value& aJSON,
const JS::Value& aObjects,
nsIPrincipal* aPrincipal,
JSContext* aCx,
uint8_t aArgc)
{
return DispatchAsyncMessage(aMessageName, aJSON, aObjects, aCx, aArgc);
return DispatchAsyncMessage(aMessageName, aJSON, aObjects, aPrincipal, aCx,
aArgc);
}
@ -658,7 +669,8 @@ nsFrameMessageManager::BroadcastAsyncMessage(const nsAString& aMessageName,
JSContext* aCx,
uint8_t aArgc)
{
return DispatchAsyncMessage(aMessageName, aJSON, aObjects, aCx, aArgc);
return DispatchAsyncMessage(aMessageName, aJSON, aObjects, nullptr, aCx,
aArgc);
}
NS_IMETHODIMP
@ -841,6 +853,7 @@ nsFrameMessageManager::ReceiveMessage(nsISupports* aTarget,
bool aIsSync,
const StructuredCloneData* aCloneData,
CpowHolder* aCpows,
nsIPrincipal* aPrincipal,
InfallibleTArray<nsString>* aJSONRetVal)
{
AutoSafeJSContext ctx;
@ -926,6 +939,42 @@ nsFrameMessageManager::ReceiveMessage(nsISupports* aTarget,
JS_DefineProperty(ctx, param, "data", json, nullptr, nullptr, JSPROP_ENUMERATE);
JS_DefineProperty(ctx, param, "objects", cpowsv, nullptr, nullptr, JSPROP_ENUMERATE);
// message.principal == null
if (!aPrincipal) {
JS::Rooted<JS::Value> nullValue(ctx);
JS_DefineProperty(ctx, param, "principal", nullValue, nullptr, nullptr, JSPROP_ENUMERATE);
}
// message.principal = { appId: <id>, origin: <origin>, isInBrowserElement: <something> }
else {
JS::Rooted<JSObject*> principalObj(ctx,
JS_NewObject(ctx, nullptr, nullptr, nullptr));
uint32_t appId;
nsresult rv = aPrincipal->GetAppId(&appId);
NS_ENSURE_SUCCESS(rv, rv);
JS::Rooted<JS::Value> appIdValue(ctx, INT_TO_JSVAL(appId));
JS_DefineProperty(ctx, principalObj, "appId", appIdValue, nullptr, nullptr, JSPROP_ENUMERATE);
nsCString origin;
rv = aPrincipal->GetOrigin(getter_Copies(origin));
NS_ENSURE_SUCCESS(rv, rv);
JS::Rooted<JSString*> originValue(ctx, JS_InternString(ctx, origin.get()));
JS_DefineProperty(ctx, principalObj, "origin", STRING_TO_JSVAL(originValue), nullptr, nullptr, JSPROP_ENUMERATE);
bool browser;
rv = aPrincipal->GetIsInBrowserElement(&browser);
NS_ENSURE_SUCCESS(rv, rv);
JS::Rooted<JS::Value> browserValue(ctx, BOOLEAN_TO_JSVAL(browser));
JS_DefineProperty(ctx, principalObj, "isInBrowserElement", browserValue, nullptr, nullptr, JSPROP_ENUMERATE);
JS::RootedValue principalValue(ctx, JS::ObjectValue(*principalObj));
JS_DefineProperty(ctx, param, "principal", principalValue, nullptr, nullptr, JSPROP_ENUMERATE);
}
JS::Rooted<JS::Value> thisValue(ctx, JS::UndefinedValue());
JS::Rooted<JS::Value> funval(ctx);
@ -981,7 +1030,7 @@ nsFrameMessageManager::ReceiveMessage(nsISupports* aTarget,
nsRefPtr<nsFrameMessageManager> kungfuDeathGrip = mParentManager;
return mParentManager ? mParentManager->ReceiveMessage(aTarget, aMessage,
aIsSync, aCloneData,
aCpows,
aCpows, aPrincipal,
aJSONRetVal) : NS_OK;
}
@ -1452,10 +1501,12 @@ public:
nsAsyncMessageToSameProcessChild(JSContext* aCx,
const nsAString& aMessage,
const StructuredCloneData& aData,
JS::Handle<JSObject *> aCpows)
JS::Handle<JSObject *> aCpows,
nsIPrincipal* aPrincipal)
: mRuntime(js::GetRuntime(aCx)),
mMessage(aMessage),
mCpows(aCpows)
mCpows(aCpows),
mPrincipal(aPrincipal)
{
if (aData.mDataLength && !mData.copy(aData.mData, aData.mDataLength)) {
NS_RUNTIMEABORT("OOM");
@ -1485,7 +1536,7 @@ public:
nsRefPtr<nsFrameMessageManager> ppm = nsFrameMessageManager::sChildProcessManager;
ppm->ReceiveMessage(static_cast<nsIContentFrameMessageManager*>(ppm.get()), mMessage,
false, &data, &cpows, nullptr);
false, &data, &cpows, mPrincipal, nullptr);
}
return NS_OK;
}
@ -1494,6 +1545,7 @@ public:
JSAutoStructuredCloneBuffer mData;
StructuredCloneClosure mClosure;
JSObject* mCpows;
nsCOMPtr<nsIPrincipal> mPrincipal;
};
@ -1515,10 +1567,12 @@ public:
virtual bool DoSendAsyncMessage(JSContext* aCx,
const nsAString& aMessage,
const StructuredCloneData& aData,
JS::Handle<JSObject *> aCpows)
JS::Handle<JSObject *> aCpows,
nsIPrincipal* aPrincipal)
{
nsRefPtr<nsIRunnable> ev =
new nsAsyncMessageToSameProcessChild(aCx, aMessage, aData, aCpows);
new nsAsyncMessageToSameProcessChild(aCx, aMessage, aData, aCpows,
aPrincipal);
NS_DispatchToCurrentThread(ev);
return true;
}
@ -1562,6 +1616,7 @@ public:
const nsAString& aMessage,
const mozilla::dom::StructuredCloneData& aData,
JS::Handle<JSObject *> aCpows,
nsIPrincipal* aPrincipal,
InfallibleTArray<nsString>* aJSONRetVal,
bool aIsSync) MOZ_OVERRIDE
{
@ -1579,15 +1634,18 @@ public:
return false;
}
if (aIsSync) {
return cc->SendSyncMessage(nsString(aMessage), data, cpows, aJSONRetVal);
return cc->SendSyncMessage(nsString(aMessage), data, cpows, aPrincipal,
aJSONRetVal);
}
return cc->CallRpcMessage(nsString(aMessage), data, cpows, aJSONRetVal);
return cc->CallRpcMessage(nsString(aMessage), data, cpows, aPrincipal,
aJSONRetVal);
}
virtual bool DoSendAsyncMessage(JSContext* aCx,
const nsAString& aMessage,
const mozilla::dom::StructuredCloneData& aData,
JS::Handle<JSObject *> aCpows) MOZ_OVERRIDE
JS::Handle<JSObject *> aCpows,
nsIPrincipal* aPrincipal) MOZ_OVERRIDE
{
mozilla::dom::ContentChild* cc =
mozilla::dom::ContentChild::GetSingleton();
@ -1602,7 +1660,7 @@ public:
if (!cc->GetCPOWManager()->Wrap(aCx, aCpows, &cpows)) {
return false;
}
return cc->SendAsyncMessage(nsString(aMessage), data, cpows);
return cc->SendAsyncMessage(nsString(aMessage), data, cpows, aPrincipal);
}
};
@ -1614,10 +1672,12 @@ public:
nsAsyncMessageToSameProcessParent(JSContext* aCx,
const nsAString& aMessage,
const StructuredCloneData& aData,
JS::Handle<JSObject *> aCpows)
JS::Handle<JSObject *> aCpows,
nsIPrincipal* aPrincipal)
: mRuntime(js::GetRuntime(aCx)),
mMessage(aMessage),
mCpows(aCpows)
mCpows(aCpows),
mPrincipal(aPrincipal)
{
if (aData.mDataLength && !mData.copy(aData.mData, aData.mDataLength)) {
NS_RUNTIMEABORT("OOM");
@ -1651,7 +1711,7 @@ public:
nsRefPtr<nsFrameMessageManager> ppm =
nsFrameMessageManager::sSameProcessParentManager;
ppm->ReceiveMessage(static_cast<nsIContentFrameMessageManager*>(ppm.get()),
mMessage, false, &data, &cpows, nullptr);
mMessage, false, &data, &cpows, mPrincipal, nullptr);
}
return NS_OK;
}
@ -1660,6 +1720,7 @@ public:
JSAutoStructuredCloneBuffer mData;
StructuredCloneClosure mClosure;
JSObject* mCpows;
nsCOMPtr<nsIPrincipal> mPrincipal;
};
/**
@ -1681,6 +1742,7 @@ public:
const nsAString& aMessage,
const mozilla::dom::StructuredCloneData& aData,
JS::Handle<JSObject *> aCpows,
nsIPrincipal* aPrincipal,
InfallibleTArray<nsString>* aJSONRetVal,
bool aIsSync) MOZ_OVERRIDE
{
@ -1697,7 +1759,7 @@ public:
SameProcessCpowHolder cpows(js::GetRuntime(aCx), aCpows);
nsRefPtr<nsFrameMessageManager> ppm = nsFrameMessageManager::sSameProcessParentManager;
ppm->ReceiveMessage(static_cast<nsIContentFrameMessageManager*>(ppm.get()), aMessage,
true, &aData, &cpows, aJSONRetVal);
true, &aData, &cpows, aPrincipal, aJSONRetVal);
}
return true;
}
@ -1705,13 +1767,14 @@ public:
virtual bool DoSendAsyncMessage(JSContext* aCx,
const nsAString& aMessage,
const mozilla::dom::StructuredCloneData& aData,
JS::Handle<JSObject *> aCpows)
JS::Handle<JSObject *> aCpows,
nsIPrincipal* aPrincipal)
{
if (!nsFrameMessageManager::sPendingSameProcessAsyncMessages) {
nsFrameMessageManager::sPendingSameProcessAsyncMessages = new nsTArray<nsCOMPtr<nsIRunnable> >;
}
nsCOMPtr<nsIRunnable> ev =
new nsAsyncMessageToSameProcessParent(aCx, aMessage, aData, aCpows);
new nsAsyncMessageToSameProcessParent(aCx, aMessage, aData, aCpows, aPrincipal);
nsFrameMessageManager::sPendingSameProcessAsyncMessages->AppendElement(ev);
NS_DispatchToCurrentThread(ev);
return true;

View File

@ -61,6 +61,7 @@ public:
const nsAString& aMessage,
const mozilla::dom::StructuredCloneData& aData,
JS::Handle<JSObject *> aCpows,
nsIPrincipal* aPrincipal,
InfallibleTArray<nsString>* aJSONRetVal,
bool aIsSync)
{
@ -70,7 +71,8 @@ public:
virtual bool DoSendAsyncMessage(JSContext* aCx,
const nsAString& aMessage,
const mozilla::dom::StructuredCloneData& aData,
JS::Handle<JSObject *> aCpows)
JS::Handle<JSObject *> aCpows,
nsIPrincipal* aPrincipal)
{
return true;
}
@ -218,7 +220,7 @@ public:
nsresult ReceiveMessage(nsISupports* aTarget, const nsAString& aMessage,
bool aIsSync, const StructuredCloneData* aCloneData,
CpowHolder* aCpows,
CpowHolder* aCpows, nsIPrincipal* aPrincipal,
InfallibleTArray<nsString>* aJSONRetVal);
void AddChildManager(nsFrameMessageManager* aManager,
@ -239,12 +241,14 @@ public:
nsresult DispatchAsyncMessage(const nsAString& aMessageName,
const JS::Value& aJSON,
const JS::Value& aObjects,
nsIPrincipal* aPrincipal,
JSContext* aCx,
uint8_t aArgc);
nsresult DispatchAsyncMessageInternal(JSContext* aCx,
const nsAString& aMessage,
const StructuredCloneData& aData,
JS::Handle<JSObject *> aCpows);
JS::Handle<JSObject *> aCpows,
nsIPrincipal* aPrincipal);
void RemoveFromParent();
nsFrameMessageManager* GetParentManager() { return mParentManager; }
void SetParentManager(nsFrameMessageManager* aParent)
@ -268,6 +272,7 @@ private:
nsresult SendMessage(const nsAString& aMessageName,
const JS::Value& aJSON,
const JS::Value& aObjects,
nsIPrincipal* aPrincipal,
JSContext* aCx,
uint8_t aArgc,
JS::Value* aRetval,

View File

@ -30,6 +30,7 @@ nsInProcessTabChildGlobal::DoSendBlockingMessage(JSContext* aCx,
const nsAString& aMessage,
const mozilla::dom::StructuredCloneData& aData,
JS::Handle<JSObject *> aCpows,
nsIPrincipal* aPrincipal,
InfallibleTArray<nsString>* aJSONRetVal,
bool aIsSync)
{
@ -43,7 +44,8 @@ nsInProcessTabChildGlobal::DoSendBlockingMessage(JSContext* aCx,
if (mChromeMessageManager) {
SameProcessCpowHolder cpows(js::GetRuntime(aCx), aCpows);
nsRefPtr<nsFrameMessageManager> mm = mChromeMessageManager;
mm->ReceiveMessage(mOwner, aMessage, true, &aData, &cpows, aJSONRetVal);
mm->ReceiveMessage(mOwner, aMessage, true, &aData, &cpows, aPrincipal,
aJSONRetVal);
}
return true;
}
@ -55,11 +57,13 @@ public:
nsInProcessTabChildGlobal* aTabChild,
const nsAString& aMessage,
const StructuredCloneData& aData,
JS::Handle<JSObject *> aCpows)
JS::Handle<JSObject *> aCpows,
nsIPrincipal* aPrincipal)
: mRuntime(js::GetRuntime(aCx)),
mTabChild(aTabChild),
mMessage(aMessage),
mCpows(aCpows),
mPrincipal(aPrincipal),
mRun(false)
{
if (aData.mDataLength && !mData.copy(aData.mData, aData.mDataLength)) {
@ -95,7 +99,8 @@ public:
SameProcessCpowHolder cpows(mRuntime, JS::Handle<JSObject *>::fromMarkedLocation(&mCpows));
nsRefPtr<nsFrameMessageManager> mm = mTabChild->mChromeMessageManager;
mm->ReceiveMessage(mTabChild->mOwner, mMessage, false, &data, &cpows, nullptr);
mm->ReceiveMessage(mTabChild->mOwner, mMessage, false, &data, &cpows,
mPrincipal, nullptr);
}
return NS_OK;
}
@ -105,6 +110,7 @@ public:
JSAutoStructuredCloneBuffer mData;
StructuredCloneClosure mClosure;
JSObject* mCpows;
nsCOMPtr<nsIPrincipal> mPrincipal;
// True if this runnable has already been called. This can happen if DoSendSyncMessage
// is called while waiting for an asynchronous message send.
bool mRun;
@ -114,10 +120,11 @@ bool
nsInProcessTabChildGlobal::DoSendAsyncMessage(JSContext* aCx,
const nsAString& aMessage,
const StructuredCloneData& aData,
JS::Handle<JSObject *> aCpows)
JS::Handle<JSObject *> aCpows,
nsIPrincipal* aPrincipal)
{
nsCOMPtr<nsIRunnable> ev =
new nsAsyncMessageToParent(aCx, this, aMessage, aData, aCpows);
new nsAsyncMessageToParent(aCx, this, aMessage, aData, aCpows, aPrincipal);
mASyncMessages.AppendElement(ev);
NS_DispatchToCurrentThread(ev);
return true;

View File

@ -43,23 +43,27 @@ public:
NS_IMETHOD SendSyncMessage(const nsAString& aMessageName,
const JS::Value& aObject,
const JS::Value& aRemote,
nsIPrincipal* aPrincipal,
JSContext* aCx,
uint8_t aArgc,
JS::Value* aRetval)
{
return mMessageManager
? mMessageManager->SendSyncMessage(aMessageName, aObject, aRemote, aCx, aArgc, aRetval)
? mMessageManager->SendSyncMessage(aMessageName, aObject, aRemote,
aPrincipal, aCx, aArgc, aRetval)
: NS_ERROR_NULL_POINTER;
}
NS_IMETHOD SendRpcMessage(const nsAString& aMessageName,
const JS::Value& aObject,
const JS::Value& aRemote,
nsIPrincipal* aPrincipal,
JSContext* aCx,
uint8_t aArgc,
JS::Value* aRetval)
{
return mMessageManager
? mMessageManager->SendRpcMessage(aMessageName, aObject, aRemote, aCx, aArgc, aRetval)
? mMessageManager->SendRpcMessage(aMessageName, aObject, aRemote,
aPrincipal, aCx, aArgc, aRetval)
: NS_ERROR_NULL_POINTER;
}
NS_IMETHOD GetContent(nsIDOMWindow** aContent) MOZ_OVERRIDE;
@ -83,12 +87,14 @@ public:
const nsAString& aMessage,
const mozilla::dom::StructuredCloneData& aData,
JS::Handle<JSObject *> aCpows,
nsIPrincipal* aPrincipal,
InfallibleTArray<nsString>* aJSONRetVal,
bool aIsSync) MOZ_OVERRIDE;
virtual bool DoSendAsyncMessage(JSContext* aCx,
const nsAString& aMessage,
const mozilla::dom::StructuredCloneData& aData,
JS::Handle<JSObject *> aCpows);
JS::Handle<JSObject *> aCpows,
nsIPrincipal* aPrincipal) MOZ_OVERRIDE;
virtual nsresult PreHandleEvent(nsEventChainPreVisitor& aVisitor) MOZ_OVERRIDE;
NS_IMETHOD AddEventListener(const nsAString& aType,

View File

@ -2,3 +2,4 @@
[test_bug357450.js]
[test_copypaste.xul]
[test_messagemanager_principal.html]

View File

@ -0,0 +1,94 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Test for Principal in MessageManager</title>
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?>
</head>
<body>
<script type="application/javascript;version=1.7">
"use strict";
const Ci = Components.interfaces;
const Cc = Components.classes;
const Cu = Components.utils;
var permManager = Cc["@mozilla.org/permissionmanager;1"]
.getService(Ci.nsIPermissionManager);
SimpleTest.waitForExplicitFinish();
const childFrameURL =
"data:text/html,<!DOCTYPE HTML><html><body></body></html>";
function childFrameScript() {
"use strict";
addMessageListener("test:ipcMessage", function(message) {
sendAsyncMessage(message.name, "principal: " + (message.principal ? "OK" : "KO"));
sendAsyncMessage(message.name, "principal.appId: " +
("appId" in message.principal ? "OK" : "KO"));
sendAsyncMessage(message.name, "principal.origin: " +
("origin" in message.principal ? "OK" : "KO"));
sendAsyncMessage(message.name, "principal.isInBrowserElement: " +
("isInBrowserElement" in message.principal ? "OK" : "KO"));
sendAsyncMessage(message.name, "DONE");
});
}
function runTests() {
ok("Browser prefs set.");
let iframe = document.createElement("iframe");
SpecialPowers.wrap(iframe).mozbrowser = true;
iframe.id = "iframe";
iframe.src = childFrameURL;
iframe.addEventListener("mozbrowserloadend", function() {
ok(true, "Got iframe load event.");
let mm = SpecialPowers.getBrowserFrameMessageManager(iframe);
mm.addMessageListener("test:ipcMessage", function(message) {
// We need to wrap to access message.json, and unwrap to do the
// identity check.
var msg = SpecialPowers.unwrap(SpecialPowers.wrap(message).json);
if (/OK$/.exec(msg)) {
ok(true, msg);
} else if(/KO$/.exec(msg)) {
ok(true, false);
} else if (/DONE/.exec(msg)) {
permManager.removeFromPrincipal(window.document.nodePrincipal, "browser",
Ci.nsIPermissionManager.ALLOW_ACTION);
SimpleTest.finish();
}
});
mm.loadFrameScript("data:,(" + childFrameScript.toString() + ")();",
false);
mm.sendAsyncMessage("test:ipcMessage", 42, null, window.document.nodePrincipal);
});
document.body.appendChild(iframe);
}
addEventListener("load", function() {
info("Got load event.");
permManager.addFromPrincipal(window.document.nodePrincipal, "browser",
Ci.nsIPermissionManager.ALLOW_ACTION);
SpecialPowers.pushPrefEnv({
"set": [
["dom.mozBrowserFramesEnabled", true],
["browser.pagethumbnails.capturing_disabled", true]
]
}, runTests);
});
</script>
</body>
</html>

View File

@ -211,7 +211,8 @@ HTMLOptionElement::BeforeSetAttr(int32_t aNamespaceID, nsIAtom* aName,
int32_t index = Index();
uint32_t mask = HTMLSelectElement::SET_DISABLED;
if (aValue) {
bool defaultSelected = aValue;
if (defaultSelected) {
mask |= HTMLSelectElement::IS_SELECTED;
}
@ -227,8 +228,10 @@ HTMLOptionElement::BeforeSetAttr(int32_t aNamespaceID, nsIAtom* aName,
// Now reset our members; when we finish the attr set we'll end up with the
// rigt selected state.
mIsInSetDefaultSelected = inSetDefaultSelected;
mSelectedChanged = false;
// mIsSelected doesn't matter while mSelectedChanged is false
// mIsSelected has already been set by SetOptionsSelectedByIndex.
// Possibly more than once; make sure our mSelectedChanged state is
// set correctly.
mSelectedChanged = mIsSelected != defaultSelected;
return NS_OK;
}

View File

@ -402,6 +402,7 @@ support-files =
[test_object_attributes_reflection.html]
[test_object_plugin_nav.html]
[test_ol_attributes_reflection.html]
[test_option_defaultSelected.html]
[test_param_attributes_reflection.html]
[test_q_attributes_reflection.html]
[test_restore_from_parser_fragment.html]

View File

@ -0,0 +1,47 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=927796
-->
<head>
<meta charset="utf-8">
<title>Test for Bug 927796</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=927796">Mozilla Bug 927796</a>
<p id="display">
<select id="s1">
<option selected>one</option>
<option>two</option>
</select>
<select id="s2" size="5">
<option selected>one</option>
<option>two</option>
</select>
</p>
<div id="content" style="display: none">
</div>
<pre id="test">
</pre>
<script type="application/javascript">
/** Test for Bug 927796 **/
var s1 = $("s1");
s1.options[0].defaultSelected = false;
is(s1.options[0].selected, true,
"First option in combobox should still be selected");
is(s1.options[1].selected, false,
"Second option in combobox should not be selected");
var s2 = $("s2");
s2.options[0].defaultSelected = false;
is(s2.options[0].selected, false,
"First option in listbox should not be selected");
is(s2.options[1].selected, false,
"Second option in listbox should not be selected");
</script>
</body>
</html>

View File

@ -3651,6 +3651,14 @@ NS_IMETHODIMP
nsWindowSH::Finalize(nsIXPConnectWrappedNative *wrapper, JSFreeOp *fop,
JSObject *obj)
{
// Since this call is virtual, the exact rooting hazard static analysis is
// not able to determine that it happens during finalization and should be
// ignored. Moreover, the analysis cannot discover and validate the
// potential targets of the virtual call to OnFinalize below because of the
// indirection through nsCOMMPtr. Thus, we annotate the analysis here so
// that it does not report OnFinalize as GCing with |obj| on stack.
JS::AutoAssertNoGC nogc;
nsCOMPtr<nsIScriptGlobalObject> sgo(do_QueryWrappedNative(wrapper));
NS_ENSURE_TRUE(sgo, NS_ERROR_UNEXPECTED);

View File

@ -25,7 +25,12 @@ using namespace mozilla::dom;
using namespace mozilla::hal_sandbox;
using namespace mozilla::services;
#else
namespace mozilla {
namespace dom {
class PContentParent;
}
}
class nsIPrincipal;
#endif
@ -280,16 +285,16 @@ AssertAppProcess(mozilla::hal_sandbox::PHalParent* aActor,
}
bool
AssertAppPrincipal(PContentParent* aActor,
AssertAppPrincipal(mozilla::dom::PContentParent* aActor,
nsIPrincipal* aPrincipal)
{
return true;
}
uint32_t
CheckPermission(PContentParent*,
nsIPrincipal*,
const char*)
CheckPermission(mozilla::dom::PContentParent* aActor,
nsIPrincipal* aPrincipal,
const char* aPermission)
{
return nsIPermissionManager::ALLOW_ACTION;
}

View File

@ -72,6 +72,8 @@
#include "nsPermissionManager.h"
#endif
#include "PermissionMessageUtils.h"
#if defined(MOZ_WIDGET_ANDROID)
#include "APKOpen.h"
#endif
@ -1172,14 +1174,15 @@ ContentChild::RecvNotifyVisited(const URIParams& aURI)
bool
ContentChild::RecvAsyncMessage(const nsString& aMsg,
const ClonedMessageData& aData,
const InfallibleTArray<CpowEntry>& aCpows)
const InfallibleTArray<CpowEntry>& aCpows,
const IPC::Principal& aPrincipal)
{
nsRefPtr<nsFrameMessageManager> cpm = nsFrameMessageManager::sChildProcessManager;
if (cpm) {
StructuredCloneData cloneData = ipc::UnpackClonedMessageDataForChild(aData);
CpowIdHolder cpows(GetCPOWManager(), aCpows);
cpm->ReceiveMessage(static_cast<nsIContentFrameMessageManager*>(cpm.get()),
aMsg, false, &cloneData, &cpows, nullptr);
aMsg, false, &cloneData, &cpows, aPrincipal, nullptr);
}
return true;
}

View File

@ -188,7 +188,8 @@ public:
virtual bool RecvAsyncMessage(const nsString& aMsg,
const ClonedMessageData& aData,
const InfallibleTArray<CpowEntry>& aCpows);
const InfallibleTArray<CpowEntry>& aCpows,
const IPC::Principal& aPrincipal);
virtual bool RecvGeolocationUpdate(const GeoPosition& somewhere);

View File

@ -1139,7 +1139,7 @@ ContentParent::ActorDestroy(ActorDestroyReason why)
if (ppm) {
ppm->ReceiveMessage(static_cast<nsIContentFrameMessageManager*>(ppm.get()),
CHILD_PROCESS_SHUTDOWN_MESSAGE, false,
nullptr, nullptr, nullptr);
nullptr, nullptr, nullptr, nullptr);
}
nsCOMPtr<nsIThreadObserver>
kungFuDeathGrip(static_cast<nsIThreadObserver*>(this));
@ -2865,14 +2865,21 @@ bool
ContentParent::RecvSyncMessage(const nsString& aMsg,
const ClonedMessageData& aData,
const InfallibleTArray<CpowEntry>& aCpows,
const IPC::Principal& aPrincipal,
InfallibleTArray<nsString>* aRetvals)
{
nsIPrincipal* principal = aPrincipal;
if (principal && !AssertAppPrincipal(this, principal)) {
return false;
}
nsRefPtr<nsFrameMessageManager> ppm = mMessageManager;
if (ppm) {
StructuredCloneData cloneData = ipc::UnpackClonedMessageDataForParent(aData);
CpowIdHolder cpows(GetCPOWManager(), aCpows);
ppm->ReceiveMessage(static_cast<nsIContentFrameMessageManager*>(ppm.get()),
aMsg, true, &cloneData, &cpows, aRetvals);
aMsg, true, &cloneData, &cpows, aPrincipal, aRetvals);
}
return true;
}
@ -2881,14 +2888,20 @@ bool
ContentParent::AnswerRpcMessage(const nsString& aMsg,
const ClonedMessageData& aData,
const InfallibleTArray<CpowEntry>& aCpows,
const IPC::Principal& aPrincipal,
InfallibleTArray<nsString>* aRetvals)
{
nsIPrincipal* principal = aPrincipal;
if (principal && !AssertAppPrincipal(this, principal)) {
return false;
}
nsRefPtr<nsFrameMessageManager> ppm = mMessageManager;
if (ppm) {
StructuredCloneData cloneData = ipc::UnpackClonedMessageDataForParent(aData);
CpowIdHolder cpows(GetCPOWManager(), aCpows);
ppm->ReceiveMessage(static_cast<nsIContentFrameMessageManager*>(ppm.get()),
aMsg, true, &cloneData, &cpows, aRetvals);
aMsg, true, &cloneData, &cpows, aPrincipal, aRetvals);
}
return true;
}
@ -2896,14 +2909,20 @@ ContentParent::AnswerRpcMessage(const nsString& aMsg,
bool
ContentParent::RecvAsyncMessage(const nsString& aMsg,
const ClonedMessageData& aData,
const InfallibleTArray<CpowEntry>& aCpows)
const InfallibleTArray<CpowEntry>& aCpows,
const IPC::Principal& aPrincipal)
{
nsIPrincipal* principal = aPrincipal;
if (principal && !AssertAppPrincipal(this, principal)) {
return false;
}
nsRefPtr<nsFrameMessageManager> ppm = mMessageManager;
if (ppm) {
StructuredCloneData cloneData = ipc::UnpackClonedMessageDataForParent(aData);
CpowIdHolder cpows(GetCPOWManager(), aCpows);
ppm->ReceiveMessage(static_cast<nsIContentFrameMessageManager*>(ppm.get()),
aMsg, false, &cloneData, &cpows, nullptr);
aMsg, false, &cloneData, &cpows, aPrincipal, nullptr);
}
return true;
}
@ -3110,7 +3129,8 @@ bool
ContentParent::DoSendAsyncMessage(JSContext* aCx,
const nsAString& aMessage,
const mozilla::dom::StructuredCloneData& aData,
JS::Handle<JSObject *> aCpows)
JS::Handle<JSObject *> aCpows,
nsIPrincipal* aPrincipal)
{
ClonedMessageData data;
if (!BuildClonedMessageDataForParent(this, aData, data)) {
@ -3120,7 +3140,7 @@ ContentParent::DoSendAsyncMessage(JSContext* aCx,
if (!GetCPOWManager()->Wrap(aCx, aCpows, &cpows)) {
return false;
}
return SendAsyncMessage(nsString(aMessage), data, cpows);
return SendAsyncMessage(nsString(aMessage), data, cpows, aPrincipal);
}
bool

View File

@ -117,7 +117,8 @@ public:
virtual bool DoSendAsyncMessage(JSContext* aCx,
const nsAString& aMessage,
const mozilla::dom::StructuredCloneData& aData,
JS::Handle<JSObject *> aCpows) MOZ_OVERRIDE;
JS::Handle<JSObject *> aCpows,
nsIPrincipal* aPrincipal) MOZ_OVERRIDE;
virtual bool CheckPermission(const nsAString& aPermission) MOZ_OVERRIDE;
virtual bool CheckManifestURL(const nsAString& aManifestURL) MOZ_OVERRIDE;
virtual bool CheckAppHasPermission(const nsAString& aPermission) MOZ_OVERRIDE;
@ -420,14 +421,17 @@ private:
virtual bool RecvSyncMessage(const nsString& aMsg,
const ClonedMessageData& aData,
const InfallibleTArray<CpowEntry>& aCpows,
const IPC::Principal& aPrincipal,
InfallibleTArray<nsString>* aRetvals);
virtual bool AnswerRpcMessage(const nsString& aMsg,
const ClonedMessageData& aData,
const InfallibleTArray<CpowEntry>& aCpows,
const IPC::Principal& aPrincipal,
InfallibleTArray<nsString>* aRetvals);
virtual bool RecvAsyncMessage(const nsString& aMsg,
const ClonedMessageData& aData,
const InfallibleTArray<CpowEntry>& aCpows);
const InfallibleTArray<CpowEntry>& aCpows,
const IPC::Principal& aPrincipal);
virtual bool RecvFilePathUpdateNotify(const nsString& aType,
const nsString& aStorageName,

View File

@ -61,7 +61,8 @@ intr protocol PBrowser
manages PIndexedDB;
both:
AsyncMessage(nsString aMessage, ClonedMessageData aData, CpowEntry[] aCpows);
AsyncMessage(nsString aMessage, ClonedMessageData aData, CpowEntry[] aCpows,
Principal aPrincipal);
parent:
/**
@ -74,10 +75,12 @@ parent:
intr CreateWindow() returns (PBrowser window);
sync SyncMessage(nsString aMessage, ClonedMessageData aData, CpowEntry[] aCpows)
sync SyncMessage(nsString aMessage, ClonedMessageData aData,
CpowEntry[] aCpows, Principal aPrincipal)
returns (nsString[] retval);
rpc RpcMessage(nsString aMessage, ClonedMessageData aData, CpowEntry[] aCpows)
rpc RpcMessage(nsString aMessage, ClonedMessageData aData,
CpowEntry[] aCpows, Principal aPrincipal)
returns (nsString[] retval);
/**

View File

@ -375,10 +375,12 @@ parent:
sync ReadFontList() returns (FontListEntry[] retValue);
sync SyncMessage(nsString aMessage, ClonedMessageData aData, CpowEntry[] aCpows)
sync SyncMessage(nsString aMessage, ClonedMessageData aData,
CpowEntry[] aCpows, Principal aPrincipal)
returns (nsString[] retval);
rpc RpcMessage(nsString aMessage, ClonedMessageData aData, CpowEntry[] aCpows)
rpc RpcMessage(nsString aMessage, ClonedMessageData aData,
CpowEntry[] aCpows, Principal aPrincipal)
returns (nsString[] retval);
ShowAlertNotification(nsString imageUrl,
@ -469,7 +471,8 @@ parent:
returns (OptionalInputStreamParams postData, OptionalURIParams uri);
both:
AsyncMessage(nsString aMessage, ClonedMessageData aData, CpowEntry[] aCpows);
AsyncMessage(nsString aMessage, ClonedMessageData aData,
CpowEntry[] aCpows, Principal aPrincipal);
};
}

View File

@ -62,6 +62,7 @@
#include "nsPrintfCString.h"
#include "nsThreadUtils.h"
#include "nsWeakReference.h"
#include "PermissionMessageUtils.h"
#include "PCOMContentPermissionRequestChild.h"
#include "PuppetWidget.h"
#include "StructuredCloneUtils.h"
@ -1506,7 +1507,7 @@ TabChild::DispatchMessageManagerMessage(const nsAString& aMessageName,
nsRefPtr<nsFrameMessageManager> mm =
static_cast<nsFrameMessageManager*>(mTabChildGlobal->mMessageManager.get());
mm->ReceiveMessage(static_cast<EventTarget*>(mTabChildGlobal),
aMessageName, false, &cloneData, nullptr, nullptr);
aMessageName, false, &cloneData, nullptr, nullptr, nullptr);
}
bool
@ -2071,7 +2072,8 @@ TabChild::RecvLoadRemoteScript(const nsString& aURL)
bool
TabChild::RecvAsyncMessage(const nsString& aMessage,
const ClonedMessageData& aData,
const InfallibleTArray<CpowEntry>& aCpows)
const InfallibleTArray<CpowEntry>& aCpows,
const IPC::Principal& aPrincipal)
{
if (mTabChildGlobal) {
nsCOMPtr<nsIXPConnectJSObjectHolder> kungFuDeathGrip(GetGlobal());
@ -2080,7 +2082,7 @@ TabChild::RecvAsyncMessage(const nsString& aMessage,
static_cast<nsFrameMessageManager*>(mTabChildGlobal->mMessageManager.get());
CpowIdHolder cpows(static_cast<ContentChild*>(Manager())->GetCPOWManager(), aCpows);
mm->ReceiveMessage(static_cast<EventTarget*>(mTabChildGlobal),
aMessage, false, &cloneData, &cpows, nullptr);
aMessage, false, &cloneData, &cpows, aPrincipal, nullptr);
}
return true;
}
@ -2404,6 +2406,7 @@ TabChild::DoSendBlockingMessage(JSContext* aCx,
const nsAString& aMessage,
const StructuredCloneData& aData,
JS::Handle<JSObject *> aCpows,
nsIPrincipal* aPrincipal,
InfallibleTArray<nsString>* aJSONRetVal,
bool aIsSync)
{
@ -2418,16 +2421,21 @@ TabChild::DoSendBlockingMessage(JSContext* aCx,
return false;
}
}
if (aIsSync)
return SendSyncMessage(nsString(aMessage), data, cpows, aJSONRetVal);
return CallRpcMessage(nsString(aMessage), data, cpows, aJSONRetVal);
if (aIsSync) {
return SendSyncMessage(nsString(aMessage), data, cpows, aPrincipal,
aJSONRetVal);
}
return CallRpcMessage(nsString(aMessage), data, cpows, aPrincipal,
aJSONRetVal);
}
bool
TabChild::DoSendAsyncMessage(JSContext* aCx,
const nsAString& aMessage,
const StructuredCloneData& aData,
JS::Handle<JSObject *> aCpows)
JS::Handle<JSObject *> aCpows,
nsIPrincipal* aPrincipal)
{
ContentChild* cc = Manager();
ClonedMessageData data;
@ -2440,7 +2448,8 @@ TabChild::DoSendAsyncMessage(JSContext* aCx,
return false;
}
}
return SendAsyncMessage(nsString(aMessage), data, cpows);
return SendAsyncMessage(nsString(aMessage), data, cpows,
aPrincipal);
}
TabChild*

View File

@ -63,23 +63,27 @@ public:
NS_IMETHOD SendSyncMessage(const nsAString& aMessageName,
const JS::Value& aObject,
const JS::Value& aRemote,
nsIPrincipal* aPrincipal,
JSContext* aCx,
uint8_t aArgc,
JS::Value* aRetval)
{
return mMessageManager
? mMessageManager->SendSyncMessage(aMessageName, aObject, aRemote, aCx, aArgc, aRetval)
? mMessageManager->SendSyncMessage(aMessageName, aObject, aRemote,
aPrincipal, aCx, aArgc, aRetval)
: NS_ERROR_NULL_POINTER;
}
NS_IMETHOD SendRpcMessage(const nsAString& aMessageName,
const JS::Value& aObject,
const JS::Value& aRemote,
nsIPrincipal* aPrincipal,
JSContext* aCx,
uint8_t aArgc,
JS::Value* aRetval)
{
return mMessageManager
? mMessageManager->SendRpcMessage(aMessageName, aObject, aRemote, aCx, aArgc, aRetval)
? mMessageManager->SendRpcMessage(aMessageName, aObject, aRemote,
aPrincipal, aCx, aArgc, aRetval)
: NS_ERROR_NULL_POINTER;
}
NS_IMETHOD GetContent(nsIDOMWindow** aContent) MOZ_OVERRIDE;
@ -194,12 +198,14 @@ public:
const nsAString& aMessage,
const mozilla::dom::StructuredCloneData& aData,
JS::Handle<JSObject *> aCpows,
nsIPrincipal* aPrincipal,
InfallibleTArray<nsString>* aJSONRetVal,
bool aIsSync) MOZ_OVERRIDE;
virtual bool DoSendAsyncMessage(JSContext* aCx,
const nsAString& aMessage,
const mozilla::dom::StructuredCloneData& aData,
JS::Handle<JSObject *> aCpows) MOZ_OVERRIDE;
JS::Handle<JSObject *> aCpows,
nsIPrincipal* aPrincipal) MOZ_OVERRIDE;
virtual bool RecvLoadURL(const nsCString& uri);
virtual bool RecvCacheFileDescriptor(const nsString& aPath,
@ -237,7 +243,8 @@ public:
virtual bool RecvLoadRemoteScript(const nsString& aURL);
virtual bool RecvAsyncMessage(const nsString& aMessage,
const ClonedMessageData& aData,
const InfallibleTArray<CpowEntry>& aCpows);
const InfallibleTArray<CpowEntry>& aCpows,
const IPC::Principal& aPrincipal) MOZ_OVERRIDE;
virtual PDocumentRendererChild*
AllocPDocumentRendererChild(const nsRect& documentRect, const gfxMatrix& transform,

View File

@ -8,6 +8,7 @@
#include "TabParent.h"
#include "AppProcessChecker.h"
#include "IDBFactory.h"
#include "IndexedDBParent.h"
#include "mozIApplication.h"
@ -52,6 +53,7 @@
#include "nsServiceManagerUtils.h"
#include "nsThreadUtils.h"
#include "private/pprio.h"
#include "PermissionMessageUtils.h"
#include "StructuredCloneUtils.h"
#include "JavaScriptParent.h"
#include "TabChild.h"
@ -299,7 +301,8 @@ TabParent::ActorDestroy(ActorDestroyReason why)
if (frameLoader) {
fmm = frameLoader->GetFrameMessageManager();
nsCOMPtr<Element> frameElement(mFrameElement);
ReceiveMessage(CHILD_PROCESS_SHUTDOWN_MESSAGE, false, nullptr, nullptr);
ReceiveMessage(CHILD_PROCESS_SHUTDOWN_MESSAGE, false, nullptr, nullptr,
nullptr);
frameLoader->DestroyChild();
if (why == AbnormalShutdown && os) {
@ -765,32 +768,53 @@ bool
TabParent::RecvSyncMessage(const nsString& aMessage,
const ClonedMessageData& aData,
const InfallibleTArray<CpowEntry>& aCpows,
const IPC::Principal& aPrincipal,
InfallibleTArray<nsString>* aJSONRetVal)
{
nsIPrincipal* principal = aPrincipal;
ContentParent* parent = static_cast<ContentParent*>(Manager());
if (principal && !AssertAppPrincipal(parent, principal)) {
return false;
}
StructuredCloneData cloneData = ipc::UnpackClonedMessageDataForParent(aData);
CpowIdHolder cpows(static_cast<ContentParent*>(Manager())->GetCPOWManager(), aCpows);
return ReceiveMessage(aMessage, true, &cloneData, &cpows, aJSONRetVal);
CpowIdHolder cpows(parent->GetCPOWManager(), aCpows);
return ReceiveMessage(aMessage, true, &cloneData, &cpows, aPrincipal, aJSONRetVal);
}
bool
TabParent::AnswerRpcMessage(const nsString& aMessage,
const ClonedMessageData& aData,
const InfallibleTArray<CpowEntry>& aCpows,
const IPC::Principal& aPrincipal,
InfallibleTArray<nsString>* aJSONRetVal)
{
nsIPrincipal* principal = aPrincipal;
ContentParent* parent = static_cast<ContentParent*>(Manager());
if (principal && !AssertAppPrincipal(parent, principal)) {
return false;
}
StructuredCloneData cloneData = ipc::UnpackClonedMessageDataForParent(aData);
CpowIdHolder cpows(static_cast<ContentParent*>(Manager())->GetCPOWManager(), aCpows);
return ReceiveMessage(aMessage, true, &cloneData, &cpows, aJSONRetVal);
CpowIdHolder cpows(parent->GetCPOWManager(), aCpows);
return ReceiveMessage(aMessage, true, &cloneData, &cpows, aPrincipal, aJSONRetVal);
}
bool
TabParent::RecvAsyncMessage(const nsString& aMessage,
const ClonedMessageData& aData,
const InfallibleTArray<CpowEntry>& aCpows)
const InfallibleTArray<CpowEntry>& aCpows,
const IPC::Principal& aPrincipal)
{
nsIPrincipal* principal = aPrincipal;
ContentParent* parent = static_cast<ContentParent*>(Manager());
if (principal && !AssertAppPrincipal(parent, principal)) {
return false;
}
StructuredCloneData cloneData = ipc::UnpackClonedMessageDataForParent(aData);
CpowIdHolder cpows(static_cast<ContentParent*>(Manager())->GetCPOWManager(), aCpows);
return ReceiveMessage(aMessage, false, &cloneData, &cpows, nullptr);
CpowIdHolder cpows(parent->GetCPOWManager(), aCpows);
return ReceiveMessage(aMessage, false, &cloneData, &cpows, aPrincipal, nullptr);
}
bool
@ -1214,6 +1238,7 @@ TabParent::ReceiveMessage(const nsString& aMessage,
bool aSync,
const StructuredCloneData* aCloneData,
CpowHolder* aCpows,
nsIPrincipal* aPrincipal,
InfallibleTArray<nsString>* aJSONRetVal)
{
nsRefPtr<nsFrameLoader> frameLoader = GetFrameLoader();
@ -1226,6 +1251,7 @@ TabParent::ReceiveMessage(const nsString& aMessage,
aSync,
aCloneData,
aCpows,
aPrincipal,
aJSONRetVal);
}
return true;

View File

@ -23,6 +23,7 @@
struct gfxMatrix;
class nsFrameLoader;
class nsIContent;
class nsIPrincipal;
class nsIURI;
class nsIWidget;
class CpowHolder;
@ -121,14 +122,17 @@ public:
virtual bool RecvSyncMessage(const nsString& aMessage,
const ClonedMessageData& aData,
const InfallibleTArray<CpowEntry>& aCpows,
const IPC::Principal& aPrincipal,
InfallibleTArray<nsString>* aJSONRetVal);
virtual bool AnswerRpcMessage(const nsString& aMessage,
const ClonedMessageData& aData,
const InfallibleTArray<CpowEntry>& aCpows,
const IPC::Principal& aPrincipal,
InfallibleTArray<nsString>* aJSONRetVal);
virtual bool RecvAsyncMessage(const nsString& aMessage,
const ClonedMessageData& aData,
const InfallibleTArray<CpowEntry>& aCpows);
const InfallibleTArray<CpowEntry>& aCpows,
const IPC::Principal& aPrincipal);
virtual bool RecvNotifyIMEFocus(const bool& aFocus,
nsIMEUpdatePreference* aPreference,
uint32_t* aSeqno);
@ -254,6 +258,7 @@ protected:
bool aSync,
const StructuredCloneData* aCloneData,
CpowHolder* aCpows,
nsIPrincipal* aPrincipal,
InfallibleTArray<nsString>* aJSONRetVal = nullptr);
virtual bool Recv__delete__() MOZ_OVERRIDE;

View File

@ -1662,6 +1662,7 @@ NS_IMETHODIMP nsWebBrowser::EnsureDocShellTreeOwner()
static void DrawThebesLayer(ThebesLayer* aLayer,
gfxContext* aContext,
const nsIntRegion& aRegionToDraw,
DrawRegionClip aClip,
const nsIntRegion& aRegionToInvalidate,
void* aCallbackData)
{

View File

@ -265,6 +265,7 @@ public:
typedef void (* DrawThebesLayerCallback)(ThebesLayer* aLayer,
gfxContext* aContext,
const nsIntRegion& aRegionToDraw,
DrawRegionClip aClip,
const nsIntRegion& aRegionToInvalidate,
void* aCallbackData);

View File

@ -58,6 +58,12 @@ enum BufferMode {
BUFFER_BUFFERED
};
enum DrawRegionClip {
CLIP_DRAW,
CLIP_DRAW_SNAPPED,
CLIP_NONE,
};
// LayerRenderState for Composer2D
// We currently only support Composer2D using gralloc. If we want to be backed
// by other surfaces we will need a more generic LayerRenderState.

View File

@ -856,6 +856,7 @@ ThebesLayerBuffer::BeginPaint(ThebesLayer* aLayer, ContentType aContentType,
nsIntPoint topLeft;
result.mContext = GetContextForQuadrantUpdate(drawBounds, BUFFER_BOTH, &topLeft);
result.mClip = CLIP_DRAW_SNAPPED;
if (mode == Layer::SURFACE_COMPONENT_ALPHA) {
if (IsAzureBuffer()) {
@ -873,7 +874,6 @@ ThebesLayerBuffer::BeginPaint(ThebesLayer* aLayer, ContentType aContentType,
FillSurface(mBuffer, result.mRegionToDraw, topLeft, gfxRGBA(0.0, 0.0, 0.0, 1.0));
FillSurface(mBufferOnWhite, result.mRegionToDraw, topLeft, gfxRGBA(1.0, 1.0, 1.0, 1.0));
}
gfxUtils::ClipToRegionSnapped(result.mContext, result.mRegionToDraw);
} else if (contentType == GFX_CONTENT_COLOR_ALPHA && !isClear) {
if (IsAzureBuffer()) {
nsIntRegionRectIterator iter(result.mRegionToDraw);
@ -883,16 +883,14 @@ ThebesLayerBuffer::BeginPaint(ThebesLayer* aLayer, ContentType aContentType,
}
// Clear will do something expensive with a complex clip pushed, so clip
// here.
gfxUtils::ClipToRegionSnapped(result.mContext, result.mRegionToDraw);
} else {
MOZ_ASSERT(result.mContext->IsCairo());
result.mContext->Save();
gfxUtils::ClipToRegionSnapped(result.mContext, result.mRegionToDraw);
result.mContext->SetOperator(gfxContext::OPERATOR_CLEAR);
result.mContext->Paint();
result.mContext->SetOperator(gfxContext::OPERATOR_OVER);
result.mContext->Restore();
}
} else {
gfxUtils::ClipToRegionSnapped(result.mContext, result.mRegionToDraw);
}
return result;

View File

@ -21,6 +21,7 @@
#include "nsRect.h" // for nsIntRect
#include "nsRegion.h" // for nsIntRegion
#include "nsTraceRefcnt.h" // for MOZ_COUNT_CTOR, etc
#include "LayersTypes.h"
struct gfxMatrix;
struct nsIntSize;
@ -218,6 +219,7 @@ public:
nsIntRegion mRegionToDraw;
nsIntRegion mRegionToInvalidate;
bool mDidSelfCopy;
DrawRegionClip mClip;
};
enum {

View File

@ -115,10 +115,10 @@ protected:
{
EnsureSurface();
if (!mSurface) {
mSurface = mCompositor->GetDrawTarget()->CreateSourceSurfaceFromData(mThebesImage->Data(),
mSize,
mThebesImage->Stride(),
mFormat);
mSurface = Factory::CreateWrappingDataSourceSurface(mThebesImage->Data(),
mThebesImage->Stride(),
mSize,
mFormat);
}
return true;
}

View File

@ -131,7 +131,7 @@ BasicThebesLayer::PaintThebes(gfxContext* aContext,
groupContext = aContext;
}
SetAntialiasingFlags(this, groupContext);
aCallback(this, groupContext, toDraw, nsIntRegion(), aCallbackData);
aCallback(this, groupContext, toDraw, CLIP_NONE, nsIntRegion(), aCallbackData);
if (needsGroup) {
BasicManager()->PopGroupToSourceWithCachedSurface(aContext, groupContext);
if (needsClipToVisibleRegion) {
@ -236,6 +236,7 @@ BasicThebesLayer::Validate(LayerManager::DrawThebesLayerCallback aCallback,
PaintBuffer(state.mContext,
state.mRegionToDraw, extendedDrawRegion, state.mRegionToInvalidate,
state.mDidSelfCopy,
state.mClip,
aCallback, aCallbackData);
MOZ_LAYERS_LOG_IF_SHADOWABLE(this, ("Layer::Mutated(%p) PaintThebes", this));
Mutated();

View File

@ -103,6 +103,7 @@ protected:
const nsIntRegion& aExtendedRegionToDraw,
const nsIntRegion& aRegionToInvalidate,
bool aDidSelfCopy,
DrawRegionClip aClip,
LayerManager::DrawThebesLayerCallback aCallback,
void* aCallbackData)
{
@ -110,8 +111,8 @@ protected:
BasicManager()->SetTransactionIncomplete();
return;
}
aCallback(this, aContext, aExtendedRegionToDraw, aRegionToInvalidate,
aCallbackData);
aCallback(this, aContext, aExtendedRegionToDraw, aClip,
aRegionToInvalidate, aCallbackData);
// Everything that's visible has been validated. Do this instead of just
// OR-ing with aRegionToDraw, since that can lead to a very complex region
// here (OR doesn't automatically simplify to the simplest possible

View File

@ -106,7 +106,7 @@ ClientThebesLayer::PaintThebes()
PaintBuffer(state.mContext,
state.mRegionToDraw, extendedDrawRegion, state.mRegionToInvalidate,
state.mDidSelfCopy);
state.mDidSelfCopy, state.mClip);
MOZ_LAYERS_LOG_IF_SHADOWABLE(this, ("Layer::Mutated(%p) PaintThebes", this));
Mutated();
} else {
@ -146,7 +146,7 @@ ClientThebesLayer::PaintBuffer(gfxContext* aContext,
const nsIntRegion& aRegionToDraw,
const nsIntRegion& aExtendedRegionToDraw,
const nsIntRegion& aRegionToInvalidate,
bool aDidSelfCopy)
bool aDidSelfCopy, DrawRegionClip aClip)
{
ContentClientRemote* contentClientRemote = static_cast<ContentClientRemote*>(mContentClient.get());
MOZ_ASSERT(contentClientRemote->GetIPDLActor());
@ -161,7 +161,8 @@ ClientThebesLayer::PaintBuffer(gfxContext* aContext,
}
ClientManager()->GetThebesLayerCallback()(this,
aContext,
aExtendedRegionToDraw,
aExtendedRegionToDraw,
aClip,
aRegionToInvalidate,
ClientManager()->GetThebesLayerCallbackData());

View File

@ -105,7 +105,8 @@ protected:
const nsIntRegion& aRegionToDraw,
const nsIntRegion& aExtendedRegionToDraw,
const nsIntRegion& aRegionToInvalidate,
bool aDidSelfCopy);
bool aDidSelfCopy,
DrawRegionClip aClip);
void PaintThebes();

View File

@ -69,18 +69,6 @@ private:
return static_cast<ClientLayerManager*>(mManager);
}
// BasicImplData
virtual void
PaintBuffer(gfxContext* aContext,
const nsIntRegion& aRegionToDraw,
const nsIntRegion& aExtendedRegionToDraw,
const nsIntRegion& aRegionToInvalidate,
bool aDidSelfCopy,
LayerManager::DrawThebesLayerCallback aCallback,
void* aCallbackData)
{ NS_RUNTIMEABORT("Not reached."); }
/**
* For the initial PaintThebes of a transaction, calculates all the data
* needed for that paint and any repeated transactions.

View File

@ -894,12 +894,14 @@ ContentClientIncremental::BeginPaintBuffer(ThebesLayer* aLayer,
// although they never cover it. This leads to two draw rects, the narow strip and the actually
// newly exposed area. It would be wise to fix this glitch in any way to have simpler
// clip and draw regions.
gfxUtils::ClipToRegion(result.mContext, result.mRegionToDraw);
result.mClip = CLIP_DRAW;
if (mContentType == GFX_CONTENT_COLOR_ALPHA) {
result.mContext->Save();
gfxUtils::ClipToRegion(result.mContext, result.mRegionToDraw);
result.mContext->SetOperator(gfxContext::OPERATOR_CLEAR);
result.mContext->Paint();
result.mContext->SetOperator(gfxContext::OPERATOR_OVER);
result.mContext->Restore();
}
return result;

View File

@ -274,7 +274,7 @@ BasicTiledLayerBuffer::PaintThebes(const nsIntRegion& aNewValidRegion,
#endif
PROFILER_LABEL("BasicTiledLayerBuffer", "PaintThebesSingleBufferDraw");
mCallback(mThebesLayer, ctxt, aPaintRegion, nsIntRegion(), mCallbackData);
mCallback(mThebesLayer, ctxt, aPaintRegion, CLIP_NONE, nsIntRegion(), mCallbackData);
}
#ifdef GFX_TILEDLAYER_PREF_WARNINGS
@ -383,6 +383,7 @@ BasicTiledLayerBuffer::ValidateTileInternal(BasicTiledLayerTile aTile,
mCallback(mThebesLayer, ctxt,
nsIntRegion(nsIntRect(a, nsIntSize(GetScaledTileLength(),
GetScaledTileLength()))),
CLIP_NONE,
nsIntRegion(), mCallbackData);
}

View File

@ -392,7 +392,6 @@ APZCTreeManager::ProcessEvent(const WidgetInputEvent& aEvent,
gfx3DMatrix transformToApzc;
gfx3DMatrix transformToGecko;
GetInputTransforms(apzc, transformToApzc, transformToGecko);
ApplyTransform(&(aOutEvent->refPoint), transformToApzc);
gfx3DMatrix outTransform = transformToApzc * transformToGecko;
ApplyTransform(&(aOutEvent->refPoint), outTransform);
return nsEventStatus_eIgnore;

View File

@ -158,20 +158,6 @@ public:
void* GetThebesLayerCallbackData() const
{ return mThebesLayerCallbackData; }
/*
* Helper functions for our layers
*/
void CallThebesLayerDrawCallback(ThebesLayer* aLayer,
gfxContext* aContext,
const nsIntRegion& aRegionToDraw)
{
NS_ASSERTION(mThebesLayerCallback,
"CallThebesLayerDrawCallback without callback!");
mThebesLayerCallback(aLayer, aContext,
aRegionToDraw, nsIntRegion(),
mThebesLayerCallbackData);
}
#ifdef MOZ_LAYERS_HAVE_LOG
virtual const char* Name() const MOZ_OVERRIDE { return ""; }
#endif // MOZ_LAYERS_HAVE_LOG

View File

@ -414,40 +414,22 @@ ThebesLayerD3D10::DrawRegion(nsIntRegion &aRegion, SurfaceMode aMode)
destinationSurface = mD2DSurface;
}
nsRefPtr<gfxContext> context;
MOZ_ASSERT(mDrawTarget);
nsRefPtr<gfxContext> context = new gfxContext(mDrawTarget);
if (mDrawTarget) {
context = new gfxContext(mDrawTarget);
} else {
context = new gfxContext(destinationSurface);
}
nsIntRegionRectIterator iter(aRegion);
context->Translate(gfxPoint(-visibleRect.x, -visibleRect.y));
context->NewPath();
const nsIntRect *iterRect;
while ((iterRect = iter.Next())) {
context->Rectangle(gfxRect(iterRect->x, iterRect->y, iterRect->width, iterRect->height));
if (mDrawTarget && aMode == SURFACE_SINGLE_CHANNEL_ALPHA) {
if (aMode == SURFACE_SINGLE_CHANNEL_ALPHA) {
nsIntRegionRectIterator iter(aRegion);
const nsIntRect *iterRect;
while ((iterRect = iter.Next())) {
mDrawTarget->ClearRect(Rect(iterRect->x, iterRect->y, iterRect->width, iterRect->height));
}
}
context->Clip();
if (!mDrawTarget && aMode == SURFACE_SINGLE_CHANNEL_ALPHA) {
context->SetOperator(gfxContext::OPERATOR_CLEAR);
context->Paint();
context->SetOperator(gfxContext::OPERATOR_OVER);
}
if (mD2DSurface) {
mD2DSurface->SetSubpixelAntialiasingEnabled(!(mContentFlags & CONTENT_COMPONENT_ALPHA));
} else if (mDrawTarget) {
mDrawTarget->SetPermitSubpixelAA(!(mContentFlags & CONTENT_COMPONENT_ALPHA));
}
mDrawTarget->SetPermitSubpixelAA(!(mContentFlags & CONTENT_COMPONENT_ALPHA));
LayerManagerD3D10::CallbackInfo cbInfo = mD3DManager->GetCallbackInfo();
cbInfo.Callback(this, context, aRegion, nsIntRegion(), cbInfo.CallbackData);
cbInfo.Callback(this, context, aRegion, CLIP_DRAW, nsIntRegion(), cbInfo.CallbackData);
}
void

View File

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

View File

@ -200,21 +200,6 @@ public:
void* GetThebesLayerCallbackData() const
{ return mThebesLayerCallbackData; }
/*
* Helper functions for our layers
*/
void CallThebesLayerDrawCallback(ThebesLayer* aLayer,
gfxContext* aContext,
const nsIntRegion& aRegionToDraw)
{
NS_ASSERTION(mThebesLayerCallback,
"CallThebesLayerDrawCallback without callback!");
mThebesLayerCallback(aLayer, aContext,
aRegionToDraw, nsIntRegion(),
mThebesLayerCallbackData);
}
GLenum FBOTextureTarget() { return mFBOTextureTarget; }
/**

View File

@ -828,12 +828,14 @@ BasicBufferOGL::BeginPaint(ContentType aContentType,
// although they never cover it. This leads to two draw rects, the narow strip and the actually
// newly exposed area. It would be wise to fix this glitch in any way to have simpler
// clip and draw regions.
gfxUtils::ClipToRegion(result.mContext, result.mRegionToDraw);
result.mClip = CLIP_DRAW;
if (mTexImage->GetContentType() == GFX_CONTENT_COLOR_ALPHA) {
result.mContext->Save();
gfxUtils::ClipToRegion(result.mContext, result.mRegionToDraw);
result.mContext->SetOperator(gfxContext::OPERATOR_CLEAR);
result.mContext->Paint();
result.mContext->SetOperator(gfxContext::OPERATOR_OVER);
result.mContext->Restore();
}
return result;
@ -931,7 +933,7 @@ ThebesLayerOGL::RenderLayer(int aPreviousFrameBuffer,
} else {
void* callbackData = mOGLManager->GetThebesLayerCallbackData();
SetAntialiasingFlags(this, state.mContext);
callback(this, state.mContext, state.mRegionToDraw,
callback(this, state.mContext, state.mRegionToDraw, state.mClip,
state.mRegionToInvalidate, callbackData);
// Everything that's visible has been validated. Do this instead of just
// OR-ing with aRegionToDraw, since that can lead to a very complex region

View File

@ -213,13 +213,18 @@ WasIncrementalGC(JSRuntime *rt);
extern JS_FRIEND_API(size_t)
GetGCNumber();
class AutoAssertNoGC {
class JS_PUBLIC_API(AutoAssertNoGC)
{
#ifdef DEBUG
size_t gcNumber;
public:
AutoAssertNoGC();
~AutoAssertNoGC();
#else
public:
/* Prevent unreferenced local warnings in opt builds. */
AutoAssertNoGC() {}
#endif
};
@ -311,6 +316,31 @@ ExposeObjectToActiveJS(JSObject *obj)
ExposeGCThingToActiveJS(obj, JSTRACE_OBJECT);
}
/*
* If a GC is currently marking, mark the object black.
*/
static JS_ALWAYS_INLINE void
MarkGCThingAsLive(JSRuntime *rt_, void *thing, JSGCTraceKind kind)
{
shadow::Runtime *rt = shadow::Runtime::asShadowRuntime(rt_);
#ifdef JSGC_GENERATIONAL
/*
* Any object in the nursery will not be freed during any GC running at that time.
*/
if (js::gc::IsInsideNursery(rt, thing))
return;
#endif
if (IsIncrementalBarrierNeededOnGCThing(rt, thing, kind))
IncrementalReferenceBarrier(thing, kind);
}
static JS_ALWAYS_INLINE void
MarkStringAsLive(Zone *zone, JSString *string)
{
JSRuntime *rt = JS::shadow::Zone::asShadowZone(zone)->runtimeFromMainThread();
MarkGCThingAsLive(rt, string, JSTRACE_STRING);
}
} /* namespace JS */
#endif /* js_GCAPI_h */

View File

@ -1249,6 +1249,8 @@ js_InitTypedObjectClass(JSContext *cx, HandleObject obj)
RootedObject module(cx, NewObjectWithClassProto(cx, &JSObject::class_,
objProto, global));
if (!module)
return nullptr;
// Define TypedObject global.

View File

@ -38,6 +38,7 @@
#include "frontend/ParseMaps-inl.h"
#include "frontend/ParseNode-inl.h"
#include "vm/ScopeObject-inl.h"
using namespace js;
using namespace js::gc;
@ -1165,9 +1166,9 @@ TryConvertFreeName(BytecodeEmitter *bce, ParseNode *pn)
if (bce->script->directlyInsideEval)
return false;
RootedObject outerScope(bce->sc->context, bce->script->enclosingStaticScope());
for (StaticScopeIter ssi(bce->sc->context, outerScope); !ssi.done(); ssi++) {
if (ssi.type() != StaticScopeIter::FUNCTION) {
if (ssi.type() == StaticScopeIter::BLOCK) {
for (StaticScopeIter<CanGC> ssi(bce->sc->context, outerScope); !ssi.done(); ssi++) {
if (ssi.type() != StaticScopeIter<CanGC>::FUNCTION) {
if (ssi.type() == StaticScopeIter<CanGC>::BLOCK) {
// Use generic ops if a catch block is encountered.
return false;
}
@ -6446,6 +6447,11 @@ frontend::EmitTree(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn)
: EmitVariables(cx, bce, pn, InitializeVars);
break;
case PNK_IMPORT:
// TODO: Implement emitter support for modules
bce->reportError(nullptr, JSMSG_MODULES_NOT_IMPLEMENTED);
return false;
case PNK_ARRAYPUSH: {
int slot;

View File

@ -295,6 +295,16 @@ class FullParseHandler
return new_<UnaryNode>(PNK_SEMI, JSOP_NOP, pos, (ParseNode *) nullptr);
}
ParseNode *newImportDeclaration(ParseNode *importSpecSet,
ParseNode *moduleSpec, const TokenPos &pos)
{
ParseNode *pn = new_<BinaryNode>(PNK_IMPORT, JSOP_NOP, pos,
importSpecSet, moduleSpec);
if (!pn)
return null();
return pn;
}
ParseNode *newExprStatement(ParseNode *expr, uint32_t end) {
JS_ASSERT(expr->pn_pos.end <= end);
return new_<UnaryNode>(PNK_SEMI, JSOP_NOP, TokenPos(expr->pn_pos.begin, end), expr);

View File

@ -128,6 +128,9 @@ class UpvarCookie
F(ARRAYPUSH) \
F(LEXICALSCOPE) \
F(LET) \
F(IMPORT) \
F(IMPORT_SPEC_LIST) \
F(IMPORT_SPEC) \
F(SEQ) \
F(FORIN) \
F(FOROF) \

View File

@ -3628,6 +3628,134 @@ Parser<SyntaxParseHandler>::letStatement()
return SyntaxParseHandler::NodeFailure;
}
template<typename ParseHandler>
typename ParseHandler::Node
Parser<ParseHandler>::importDeclaration()
{
JS_ASSERT(tokenStream.currentToken().type == TOK_IMPORT);
if (pc->sc->isFunctionBox() || !pc->atBodyLevel()) {
report(ParseError, false, null(), JSMSG_IMPORT_DECL_AT_TOP_LEVEL);
return null();
}
uint32_t begin = pos().begin;
TokenKind tt = tokenStream.getToken();
Node importSpecSet = handler.newList(PNK_IMPORT_SPEC_LIST);
if (!importSpecSet)
return null();
if (tt == TOK_NAME || tt == TOK_LC) {
if (tt == TOK_NAME) {
// Handle the form |import a from 'b'|, by adding a single import
// specifier to the list, with 'default' as the import name and
// 'a' as the binding name. This is equivalent to
// |import { default as a } from 'b'|.
Node importName = newName(context->names().default_);
if (!importName)
return null();
Node bindingName = newName(tokenStream.currentName());
if (!bindingName)
return null();
Node importSpec = handler.newBinary(PNK_IMPORT_SPEC, importName, bindingName);
if (!importSpec)
return null();
handler.addList(importSpecSet, importSpec);
} else {
do {
// Handle the forms |import {} from 'a'| and
// |import { ..., } from 'a'| (where ... is non empty), by
// escaping the loop early if the next token is }.
tt = tokenStream.peekToken(TokenStream::KeywordIsName);
if (tt == TOK_ERROR)
return null();
if (tt == TOK_RC)
break;
// If the next token is a keyword, the previous call to
// peekToken matched it as a TOK_NAME, and put it in the
// lookahead buffer, so this call will match keywords as well.
MUST_MATCH_TOKEN(TOK_NAME, JSMSG_NO_IMPORT_NAME);
Node importName = newName(tokenStream.currentName());
if (!importName)
return null();
if (tokenStream.getToken() == TOK_NAME &&
tokenStream.currentName() == context->names().as)
{
if (tokenStream.getToken() != TOK_NAME) {
report(ParseError, false, null(), JSMSG_NO_BINDING_NAME);
return null();
}
} else {
// Keywords cannot be bound to themselves, so an import name
// that is a keyword is a syntax error if it is not followed
// by the keyword 'as'.
if (IsKeyword(importName->name())) {
JSAutoByteString bytes;
if (!AtomToPrintableString(context, importName->name(), &bytes))
return null();
report(ParseError, false, null(), JSMSG_AS_AFTER_RESERVED_WORD, bytes.ptr());
return null();
}
tokenStream.ungetToken();
}
Node bindingName = newName(tokenStream.currentName());
if (!bindingName)
return null();
Node importSpec = handler.newBinary(PNK_IMPORT_SPEC, importName, bindingName);
if (!importSpec)
return null();
handler.addList(importSpecSet, importSpec);
} while (tokenStream.matchToken(TOK_COMMA));
MUST_MATCH_TOKEN(TOK_RC, JSMSG_RC_AFTER_IMPORT_SPEC_LIST);
}
if (tokenStream.getToken() != TOK_NAME ||
tokenStream.currentName() != context->names().from)
{
report(ParseError, false, null(), JSMSG_FROM_AFTER_IMPORT_SPEC_SET);
return null();
}
MUST_MATCH_TOKEN(TOK_STRING, JSMSG_MODULE_SPEC_AFTER_FROM);
} else {
if (tt != TOK_STRING) {
report(ParseError, false, null(), JSMSG_DECLARATION_AFTER_IMPORT);
return null();
}
// Handle the form |import 'a'| by leaving the list empty. This is
// equivalent to |import {} from 'a'|.
importSpecSet->pn_pos.end = importSpecSet->pn_pos.begin;
}
Node moduleSpec = stringLiteral();
if (!moduleSpec)
return null();
if (!MatchOrInsertSemicolon(tokenStream))
return null();
return handler.newImportDeclaration(importSpecSet, moduleSpec,
TokenPos(begin, pos().end));
}
template<>
SyntaxParseHandler::Node
Parser<SyntaxParseHandler>::importDeclaration()
{
JS_ALWAYS_FALSE(abortIfSyntaxParser());
return SyntaxParseHandler::NodeFailure;
}
template <typename ParseHandler>
typename ParseHandler::Node
Parser<ParseHandler>::expressionStatement()
@ -4907,6 +5035,8 @@ Parser<ParseHandler>::statement(bool canHaveDirectives)
case TOK_LET:
return letStatement();
case TOK_IMPORT:
return importDeclaration();
case TOK_SEMI:
return handler.newEmptyStatement(pos());
case TOK_IF:

View File

@ -512,6 +512,7 @@ class Parser : private AutoGCRooter, public StrictModeGetter
Node debuggerStatement();
Node letStatement();
Node importDeclaration();
Node expressionStatement();
Node variables(ParseNodeKind kind, bool *psimple = nullptr,
StaticBlockObject *blockObj = nullptr,

View File

@ -297,7 +297,7 @@ gc::GetPageFaultCount()
return 0;
}
#elif defined(XP_UNIX) || defined(XP_MACOSX) || defined(DARWIN)
#elif defined(XP_UNIX)
#include <sys/mman.h>
#include <sys/resource.h>

View File

@ -39,6 +39,7 @@ JS::Zone::Zone(JSRuntime *rt)
maybeAlive(true),
gcMallocBytes(0),
gcGrayRoots(),
data(nullptr),
types(this)
{
/* Ensure that there are no vtables to mess us up here. */

View File

@ -255,6 +255,9 @@ struct Zone : public JS::shadow::Zone,
/* This compartment's gray roots. */
js::Vector<js::GrayRoot, 0, js::SystemAllocPolicy> gcGrayRoots;
/* Per-zone data for use by an embedder. */
void *data;
Zone(JSRuntime *rt);
~Zone();
bool init(JSContext *cx);

View File

@ -0,0 +1 @@
loadRelativeToScript("../../tests/js1_8_5/extensions/shell.js");

View File

@ -0,0 +1,13 @@
"use strict";
function loop(a) {
a = arguments.length;
var result = 0;
for (var i = 0; i < 5000; i++) {
result += a;
}
return result;
}
assertEq(loop(11), 5000);

View File

@ -0,0 +1,13 @@
if (typeof dis === "function") {
(function() {
function foo() {}
dis(function bar(e) {
try {
(function() { e; });
} catch (e) {
foo();
}
});
}());
}

View File

@ -0,0 +1,15 @@
load(libdir + "asserts.js");
assertThrowsInstanceOf(
function() {
function foo() {}
foo = null;
(function bar(e) {
try {
(function() { e; });
throw 1;
} catch (e) {
foo();
}
})();
},
TypeError);

View File

@ -0,0 +1,186 @@
load(libdir + "match.js");
load(libdir + "asserts.js");
var { Pattern, MatchError } = Match;
program = (elts) => Pattern({
type: "Program",
body: elts
})
importDeclaration = (specifiers, source) => Pattern({
type: "ImportDeclaration",
specifiers: specifiers,
source: source
});
importSpecifier = (id, name) => Pattern({
type: "ImportSpecifier",
id: id,
name: name
});
ident = (name) => Pattern({
type: "Identifier",
name: name
})
lit = (val) => Pattern({
type: "Literal",
value: val
})
program([
importDeclaration(
[
importSpecifier(
ident("default"),
ident("a")
)
],
lit("b")
)
]).assert(Reflect.parse("import a from 'b'"));
program([
importDeclaration(
[],
lit("a")
)
]).assert(Reflect.parse("import {} from 'a'"));
program([
importDeclaration(
[
importSpecifier(
ident("a"),
ident("a")
)
],
lit("b")
)
]).assert(Reflect.parse("import { a } from 'b'"));
program([
importDeclaration(
[
importSpecifier(
ident("a"),
ident("a")
)
],
lit("b")
)
]).assert(Reflect.parse("import { a, } from 'b'"));
program([
importDeclaration(
[
importSpecifier(
ident("a"),
ident("b")
)
],
lit("c")
)
]).assert(Reflect.parse("import { a as b } from 'c'"));
program([
importDeclaration(
[
importSpecifier(
ident("as"),
ident("as")
)
],
lit("a")
)
]).assert(Reflect.parse("import { as as as } from 'a'"));
program([
importDeclaration(
[
importSpecifier(
ident("true"),
ident("a")
)
],
lit("b")
)
]).assert(Reflect.parse("import { true as a } from 'b'"));
program([
importDeclaration(
[
importSpecifier(
ident("a"),
ident("a")
),
importSpecifier(
ident("b"),
ident("b")
),
],
lit("c")
)
]).assert(Reflect.parse("import { a, b } from 'c'"));
program([
importDeclaration(
[
importSpecifier(
ident("a"),
ident("b")
),
importSpecifier(
ident("c"),
ident("d")
),
],
lit("e")
)
]).assert(Reflect.parse("import { a as b, c as d } from 'e'"));
program([
importDeclaration(
[],
lit("a")
)
]).assert(Reflect.parse("import 'a'"));
var loc = Reflect.parse("import { a as b } from 'c'", {
loc: true
}).body[0].loc;
assertEq(loc.start.line, 1);
assertEq(loc.start.column, 0);
assertEq(loc.start.line, 1);
assertEq(loc.end.column, 26);
assertThrowsInstanceOf(function () {
Reflect.parse("function f() { import a from 'b' }");
}, SyntaxError);
assertThrowsInstanceOf(function () {
Reflect.parse("if (true) import a from 'b'");
}, SyntaxError);
assertThrowsInstanceOf(function() {
Reflect.parse("import {");
}, SyntaxError);
assertThrowsInstanceOf(function() {
Reflect.parse("import {}");
}, SyntaxError);
assertThrowsInstanceOf(function() {
Reflect.parse("import {} from");
}, SyntaxError);
assertThrowsInstanceOf(function() {
Reflect.parse("import {,} from 'a'");
}, SyntaxError);
assertThrowsInstanceOf(function() {
Reflect.parse("import { a as true } from 'b'");
}, SyntaxError);
assertThrowsInstanceOf(function() {
Reflect.parse("import { true } from 'a'");
}, SyntaxError);

View File

@ -1231,6 +1231,7 @@ class MOZ_STACK_CLASS ModuleCompiler
char * errorString_;
uint32_t errorOffset_;
bool errorOverRecursed_;
int64_t usecBefore_;
SlowFunctionVector slowFunctions_;
@ -1260,6 +1261,7 @@ class MOZ_STACK_CLASS ModuleCompiler
globalAccesses_(cx),
errorString_(nullptr),
errorOffset_(UINT32_MAX),
errorOverRecursed_(false),
usecBefore_(PRMJ_Now()),
slowFunctions_(cx),
finishedFunctionBodies_(false)
@ -1275,6 +1277,8 @@ class MOZ_STACK_CLASS ModuleCompiler
errorString_);
js_free(errorString_);
}
if (errorOverRecursed_)
js_ReportOverRecursed(cx_);
// Avoid spurious Label assertions on compilation failure.
if (!stackOverflowLabel_.bound())
@ -1324,7 +1328,15 @@ class MOZ_STACK_CLASS ModuleCompiler
}
bool fail(ParseNode *pn, const char *str) {
return failOffset(pn ? pn->pn_pos.begin : parser_.tokenStream.peekTokenPos().begin, str);
if (pn)
return failOffset(pn->pn_pos.begin, str);
// The exact rooting static analysis does not perform dataflow analysis, so it believes
// that unrooted things on the stack during compilation may still be accessed after this.
// Since pn is typically only null under OOM, this suppression simply forces any GC to be
// delayed until the compilation is off the stack and more memory can be freed.
gc::AutoSuppressGC nogc(cx_);
return failOffset(parser_.tokenStream.peekTokenPos().begin, str);
}
bool failfVA(ParseNode *pn, const char *fmt, va_list ap) {
@ -1353,6 +1365,11 @@ class MOZ_STACK_CLASS ModuleCompiler
return false;
}
bool failOverRecursed() {
errorOverRecursed_ = true;
return false;
}
static const unsigned SLOW_FUNCTION_THRESHOLD_MS = 250;
bool maybeReportCompileTime(const Func &func) {
@ -3813,7 +3830,7 @@ CheckMathBuiltinCall(FunctionCompiler &f, ParseNode *callNode, AsmJSMathBuiltin
static bool
CheckCall(FunctionCompiler &f, ParseNode *call, RetType retType, MDefinition **def, Type *type)
{
JS_CHECK_RECURSION(f.cx(), return false);
JS_CHECK_RECURSION_DONT_REPORT(f.cx(), return f.m().failOverRecursed());
ParseNode *callee = CallCallee(call);
@ -4104,7 +4121,7 @@ static bool
CheckAddOrSub(FunctionCompiler &f, ParseNode *expr, MDefinition **def, Type *type,
unsigned *numAddOrSubOut = nullptr)
{
JS_CHECK_RECURSION(f.cx(), return false);
JS_CHECK_RECURSION_DONT_REPORT(f.cx(), return f.m().failOverRecursed());
JS_ASSERT(expr->isKind(PNK_ADD) || expr->isKind(PNK_SUB));
ParseNode *lhs = BinaryLeft(expr);
@ -4308,7 +4325,7 @@ CheckBitwise(FunctionCompiler &f, ParseNode *bitwise, MDefinition **def, Type *t
static bool
CheckExpr(FunctionCompiler &f, ParseNode *expr, MDefinition **def, Type *type)
{
JS_CHECK_RECURSION(f.cx(), return false);
JS_CHECK_RECURSION_DONT_REPORT(f.cx(), return f.m().failOverRecursed());
if (!f.mirGen().ensureBallast())
return false;
@ -4781,7 +4798,7 @@ CheckStatementList(FunctionCompiler &f, ParseNode *stmtList)
static bool
CheckStatement(FunctionCompiler &f, ParseNode *stmt, LabelVector *maybeLabels)
{
JS_CHECK_RECURSION(f.cx(), return false);
JS_CHECK_RECURSION_DONT_REPORT(f.cx(), return f.m().failOverRecursed());
if (!f.mirGen().ensureBallast())
return false;

View File

@ -1907,7 +1907,7 @@ Address
BaselineCompiler::getScopeCoordinateAddressFromObject(Register objReg, Register reg)
{
ScopeCoordinate sc(pc);
Shape *shape = ScopeCoordinateToStaticScopeShape(cx, script, pc);
Shape *shape = ScopeCoordinateToStaticScopeShape(script, pc);
Address addr;
if (shape->numFixedSlots() <= sc.slot) {
@ -1950,7 +1950,7 @@ BaselineCompiler::emit_JSOP_CALLALIASEDVAR()
bool
BaselineCompiler::emit_JSOP_SETALIASEDVAR()
{
JSScript *outerScript = ScopeCoordinateFunctionScript(cx, script, pc);
JSScript *outerScript = ScopeCoordinateFunctionScript(script, pc);
if (outerScript && outerScript->treatAsRunOnce) {
// Type updates for this operation might need to be tracked, so treat
// this as a SETPROP.

View File

@ -1460,7 +1460,7 @@ DoTypeUpdateFallback(JSContext *cx, BaselineFrame *frame, ICUpdatedStub *stub, H
JS_ASSERT(obj->isNative());
jsbytecode *pc = stub->getChainFallback()->icEntry()->pc(script);
if (*pc == JSOP_SETALIASEDVAR)
id = NameToId(ScopeCoordinateName(cx, script, pc));
id = NameToId(ScopeCoordinateName(script, pc));
else
id = NameToId(script->getName(pc));
types::AddTypePropertyId(cx, obj, id, value);
@ -6843,7 +6843,7 @@ DoSetPropFallback(JSContext *cx, BaselineFrame *frame, ICSetProp_Fallback *stub,
RootedPropertyName name(cx);
if (op == JSOP_SETALIASEDVAR)
name = ScopeCoordinateName(cx, script, pc);
name = ScopeCoordinateName(script, pc);
else
name = script->getName(pc);
RootedId id(cx, NameToId(name));

View File

@ -46,6 +46,7 @@ IonBuilder::IonBuilder(JSContext *cx, TempAllocator *temp, MIRGraph *graph,
cx(cx),
baselineFrame_(baselineFrame),
abortReason_(AbortReason_Disable),
reprSetHash_(nullptr),
constraints_(constraints),
analysis_(info->script()),
thisTypes(nullptr),
@ -5696,7 +5697,11 @@ IonBuilder::newOsrPreheader(MBasicBlock *predecessor, jsbytecode *loopEntry)
for (uint32_t i = 0; i < info().nargs(); i++) {
uint32_t slot = needsArgsObj ? info().argSlotUnchecked(i) : info().argSlot(i);
if (needsArgsObj) {
// Only grab arguments from the arguments object if the arguments object
// aliases formals. If the argsobj does not alias formals, then the
// formals may have been assigned to during interpretation, and that change
// will not be reflected in the argsobj.
if (needsArgsObj && info().argsObjAliasesFormals()) {
JS_ASSERT(argsObj && argsObj->isOsrArgumentsObject());
// If this is an aliased formal, then the arguments object
// contains a hole at this index. Any references to this
@ -7678,8 +7683,9 @@ IonBuilder::testCommonGetterSetter(types::TemporaryTypeSet *types, PropertyName
}
bool
IonBuilder::annotateGetPropertyCache(JSContext *cx, MDefinition *obj, MGetPropertyCache *getPropCache,
types::TemporaryTypeSet *objTypes, types::TemporaryTypeSet *pushedTypes)
IonBuilder::annotateGetPropertyCache(MDefinition *obj, MGetPropertyCache *getPropCache,
types::TemporaryTypeSet *objTypes,
types::TemporaryTypeSet *pushedTypes)
{
PropertyName *name = getPropCache->name();
@ -8240,7 +8246,7 @@ IonBuilder::getPropTryInlineAccess(bool *emitted, PropertyName *name,
Shape *objShape = shapes[0];
obj = addShapeGuard(obj, objShape, Bailout_ShapeGuard);
Shape *shape = objShape->search(cx, NameToId(name));
Shape *shape = objShape->searchLinear(NameToId(name));
JS_ASSERT(shape);
if (!loadSlot(obj, shape, rvalType, barrier, types))
@ -8255,7 +8261,7 @@ IonBuilder::getPropTryInlineAccess(bool *emitted, PropertyName *name,
for (size_t i = 0; i < shapes.length(); i++) {
Shape *objShape = shapes[i];
Shape *shape = objShape->search(cx, NameToId(name));
Shape *shape = objShape->searchLinear(NameToId(name));
JS_ASSERT(shape);
if (!load->addShape(objShape, shape))
return false;
@ -8307,7 +8313,7 @@ IonBuilder::getPropTryCache(bool *emitted, PropertyName *name,
}
if (JSOp(*pc) == JSOP_CALLPROP) {
if (!annotateGetPropertyCache(cx, obj, load, obj->resultTypeSet(), types))
if (!annotateGetPropertyCache(obj, load, obj->resultTypeSet(), types))
return false;
}
@ -8642,7 +8648,7 @@ IonBuilder::setPropTryInlineAccess(bool *emitted, MDefinition *obj,
Shape *objShape = shapes[0];
obj = addShapeGuard(obj, objShape, Bailout_ShapeGuard);
Shape *shape = objShape->search(cx, NameToId(name));
Shape *shape = objShape->searchLinear(NameToId(name));
JS_ASSERT(shape);
bool needsBarrier = objTypes->propertyNeedsBarrier(constraints(), NameToId(name));
@ -8658,7 +8664,7 @@ IonBuilder::setPropTryInlineAccess(bool *emitted, MDefinition *obj,
for (size_t i = 0; i < shapes.length(); i++) {
Shape *objShape = shapes[i];
Shape *shape = objShape->search(cx, NameToId(name));
Shape *shape = objShape->searchLinear(NameToId(name));
JS_ASSERT(shape);
if (!ins->addShape(objShape, shape))
return false;
@ -8727,9 +8733,8 @@ IonBuilder::jsop_delelem()
bool
IonBuilder::jsop_regexp(RegExpObject *reobj)
{
JSObject *prototype = script()->global().getOrCreateRegExpPrototype(cx);
if (!prototype)
return false;
JSObject *prototype = reobj->getProto();
JS_ASSERT(prototype == script()->global().maybeGetRegExpPrototype());
JS_ASSERT(&reobj->JSObject::global() == &script()->global());
@ -9057,7 +9062,7 @@ IonBuilder::walkScopeChain(unsigned hops)
bool
IonBuilder::hasStaticScopeObject(ScopeCoordinate sc, JSObject **pcall)
{
JSScript *outerScript = ScopeCoordinateFunctionScript(cx, script(), pc);
JSScript *outerScript = ScopeCoordinateFunctionScript(script(), pc);
if (!outerScript || !outerScript->treatAsRunOnce)
return false;
@ -9114,7 +9119,7 @@ IonBuilder::jsop_getaliasedvar(ScopeCoordinate sc)
{
JSObject *call = nullptr;
if (hasStaticScopeObject(sc, &call) && call) {
PropertyName *name = ScopeCoordinateName(cx, script(), pc);
PropertyName *name = ScopeCoordinateName(script(), pc);
bool succeeded;
if (!getStaticName(call, name, &succeeded))
return false;
@ -9124,7 +9129,7 @@ IonBuilder::jsop_getaliasedvar(ScopeCoordinate sc)
MDefinition *obj = walkScopeChain(sc.hops);
Shape *shape = ScopeCoordinateToStaticScopeShape(cx, script(), pc);
Shape *shape = ScopeCoordinateToStaticScopeShape(script(), pc);
MInstruction *load;
if (shape->numFixedSlots() <= sc.slot) {
@ -9154,7 +9159,7 @@ IonBuilder::jsop_setaliasedvar(ScopeCoordinate sc)
return false;
}
MDefinition *value = current->pop();
PropertyName *name = ScopeCoordinateName(cx, script(), pc);
PropertyName *name = ScopeCoordinateName(script(), pc);
if (call) {
// Push the object on the stack to match the bound object expected in
@ -9177,7 +9182,7 @@ IonBuilder::jsop_setaliasedvar(ScopeCoordinate sc)
MDefinition *rval = current->peek(-1);
MDefinition *obj = walkScopeChain(sc.hops);
Shape *shape = ScopeCoordinateToStaticScopeShape(cx, script(), pc);
Shape *shape = ScopeCoordinateToStaticScopeShape(script(), pc);
if (NeedsPostBarrier(info(), rval))
current->add(MPostWriteBarrier::New(obj, rval));
@ -9333,16 +9338,14 @@ TypeRepresentationSetHash *
IonBuilder::getOrCreateReprSetHash()
{
if (!reprSetHash_) {
TypeRepresentationSetHash* hash =
cx->new_<TypeRepresentationSetHash>();
if (!hash || !hash->init()) {
js_delete(hash);
TypeRepresentationSetHash *hash =
temp_->lifoAlloc()->new_<TypeRepresentationSetHash>();
if (!hash || !hash->init())
return nullptr;
}
reprSetHash_ = hash;
}
return reprSetHash_.get();
return reprSetHash_;
}
bool

View File

@ -636,8 +636,9 @@ class IonBuilder : public MIRGenerator
bool testShouldDOMCall(types::TypeSet *inTypes,
JSFunction *func, JSJitInfo::OpType opType);
bool annotateGetPropertyCache(JSContext *cx, MDefinition *obj, MGetPropertyCache *getPropCache,
types::TemporaryTypeSet *objTypes, types::TemporaryTypeSet *pushedTypes);
bool annotateGetPropertyCache(MDefinition *obj, MGetPropertyCache *getPropCache,
types::TemporaryTypeSet *objTypes,
types::TemporaryTypeSet *pushedTypes);
MGetPropertyCache *getInlineableGetPropertyCache(CallInfo &callInfo);
@ -712,7 +713,7 @@ class IonBuilder : public MIRGenerator
JSContext *cx;
BaselineFrame *baselineFrame_;
AbortReason abortReason_;
ScopedJSDeletePtr<TypeRepresentationSetHash> reprSetHash_;
TypeRepresentationSetHash *reprSetHash_;
// Constraints for recording dependencies on type information.
types::CompilerConstraintList *constraints_;

View File

@ -417,3 +417,13 @@ MSG_DEF(JSMSG_TYPEDOBJECT_NO_SUCH_PROP, 363, 1, JSEXN_TYPEERR, "No such property
MSG_DEF(JSMSG_TYPEDOBJECT_HANDLE_BAD_ARGS, 364, 2, JSEXN_TYPEERR, "argument {0} invalid: expected {1}")
MSG_DEF(JSMSG_TYPEDOBJECT_HANDLE_UNATTACHED, 365, 0, JSEXN_TYPEERR, "handle unattached")
MSG_DEF(JSMSG_TYPEDOBJECT_HANDLE_BAD_TYPE, 366, 0, JSEXN_TYPEERR, "handle moved to destination of incorrect type")
MSG_DEF(JSMSG_IMPORT_DECL_AT_TOP_LEVEL, 367, 0, JSEXN_SYNTAXERR, "import declarations may only appear at top level")
MSG_DEF(JSMSG_NO_IMPORT_NAME, 368, 0, JSEXN_SYNTAXERR, "missing import name")
MSG_DEF(JSMSG_AS_AFTER_RESERVED_WORD, 369, 1, JSEXN_SYNTAXERR, "missing keyword 'as' after reserved word '{0}'")
MSG_DEF(JSMSG_NO_BINDING_NAME, 370, 0, JSEXN_SYNTAXERR, "missing binding name")
MSG_DEF(JSMSG_RC_AFTER_IMPORT_SPEC_LIST, 371, 0, JSEXN_SYNTAXERR, "missing '}' after module specifier list")
MSG_DEF(JSMSG_FROM_AFTER_IMPORT_SPEC_SET, 372, 0, JSEXN_SYNTAXERR, "missing keyword 'from' after import specifier set")
MSG_DEF(JSMSG_DECLARATION_AFTER_IMPORT, 373, 0, JSEXN_SYNTAXERR, "missing declaration after 'import' keyword")
MSG_DEF(JSMSG_MODULE_SPEC_AFTER_FROM, 374, 0, JSEXN_SYNTAXERR, "missing module specifier after 'from' keyword")
MSG_DEF(JSMSG_MODULES_NOT_IMPLEMENTED, 375, 0, JSEXN_SYNTAXERR, "modules are not implemented yet")

View File

@ -908,6 +908,18 @@ JS_SetDestroyCompartmentCallback(JSRuntime *rt, JSDestroyCompartmentCallback cal
rt->destroyCompartmentCallback = callback;
}
JS_PUBLIC_API(void)
JS_SetDestroyZoneCallback(JSRuntime *rt, JSZoneCallback callback)
{
rt->destroyZoneCallback = callback;
}
JS_PUBLIC_API(void)
JS_SetSweepZoneCallback(JSRuntime *rt, JSZoneCallback callback)
{
rt->sweepZoneCallback = callback;
}
JS_PUBLIC_API(void)
JS_SetCompartmentNameCallback(JSRuntime *rt, JSCompartmentNameCallback callback)
{
@ -988,6 +1000,18 @@ JS_GetCompartmentPrivate(JSCompartment *compartment)
return compartment->data;
}
JS_PUBLIC_API(void)
JS_SetZoneUserData(JS::Zone *zone, void *data)
{
zone->data = data;
}
JS_PUBLIC_API(void *)
JS_GetZoneUserData(JS::Zone *zone)
{
return zone->data;
}
JS_PUBLIC_API(bool)
JS_WrapObject(JSContext *cx, MutableHandleObject objp)
{

View File

@ -841,6 +841,9 @@ typedef JSObject *
typedef void
(* JSDestroyCompartmentCallback)(JSFreeOp *fop, JSCompartment *compartment);
typedef void
(* JSZoneCallback)(JS::Zone *zone);
typedef void
(* JSCompartmentNameCallback)(JSRuntime *rt, JSCompartment *compartment,
char *buf, size_t bufsize);
@ -1623,6 +1626,12 @@ JS_GetImplementationVersion(void);
extern JS_PUBLIC_API(void)
JS_SetDestroyCompartmentCallback(JSRuntime *rt, JSDestroyCompartmentCallback callback);
extern JS_PUBLIC_API(void)
JS_SetDestroyZoneCallback(JSRuntime *rt, JSZoneCallback callback);
extern JS_PUBLIC_API(void)
JS_SetSweepZoneCallback(JSRuntime *rt, JSZoneCallback callback);
extern JS_PUBLIC_API(void)
JS_SetCompartmentNameCallback(JSRuntime *rt, JSCompartmentNameCallback callback);
@ -1638,6 +1647,12 @@ JS_SetCompartmentPrivate(JSCompartment *compartment, void *data);
extern JS_PUBLIC_API(void *)
JS_GetCompartmentPrivate(JSCompartment *compartment);
extern JS_PUBLIC_API(void)
JS_SetZoneUserData(JS::Zone *zone, void *data);
extern JS_PUBLIC_API(void *)
JS_GetZoneUserData(JS::Zone *zone);
extern JS_PUBLIC_API(bool)
JS_WrapObject(JSContext *cx, JS::MutableHandleObject objp);

View File

@ -57,6 +57,8 @@ ASTDEF(AST_TRY_STMT, "TryStatement", "tryStatemen
ASTDEF(AST_THROW_STMT, "ThrowStatement", "throwStatement")
ASTDEF(AST_DEBUGGER_STMT, "DebuggerStatement", "debuggerStatement")
ASTDEF(AST_LET_STMT, "LetStatement", "letStatement")
ASTDEF(AST_IMPORT_DECL, "ImportDeclaration", "importDeclaration")
ASTDEF(AST_IMPORT_SPEC, "ImportSpecifier", "importSpecifier")
ASTDEF(AST_CASE, "SwitchCase", "switchCase")
ASTDEF(AST_CATCH, "CatchClause", "catchClause")

View File

@ -25,6 +25,8 @@
#include "jsobjinlines.h"
#include "vm/ScopeObject-inl.h"
using namespace js;
using namespace JS;
@ -453,8 +455,8 @@ js::GetOutermostEnclosingFunctionOfScriptedCaller(JSContext *cx)
RootedFunction scriptedCaller(cx, iter.callee());
RootedScript outermost(cx, scriptedCaller->nonLazyScript());
for (StaticScopeIter i(cx, scriptedCaller); !i.done(); i++) {
if (i.type() == StaticScopeIter::FUNCTION)
for (StaticScopeIter<NoGC> i(scriptedCaller); !i.done(); i++) {
if (i.type() == StaticScopeIter<NoGC>::FUNCTION)
outermost = i.funScript();
}
return outermost;

View File

@ -665,7 +665,7 @@ GetNativeStackLimit(JSContext *cx)
* extra space so that we can ensure that crucial code is able to run.
*/
#define JS_CHECK_RECURSION(cx, onerror) \
#define JS_CHECK_RECURSION(cx, onerror) \
JS_BEGIN_MACRO \
int stackDummy_; \
if (!JS_CHECK_STACK_SIZE(js::GetNativeStackLimit(cx), &stackDummy_)) { \
@ -674,6 +674,14 @@ GetNativeStackLimit(JSContext *cx)
} \
JS_END_MACRO
#define JS_CHECK_RECURSION_DONT_REPORT(cx, onerror) \
JS_BEGIN_MACRO \
int stackDummy_; \
if (!JS_CHECK_STACK_SIZE(js::GetNativeStackLimit(cx), &stackDummy_)) { \
onerror; \
} \
JS_END_MACRO
#define JS_CHECK_RECURSION_WITH_SP_DONT_REPORT(cx, sp, onerror) \
JS_BEGIN_MACRO \
if (!JS_CHECK_STACK_SIZE(js::GetNativeStackLimit(cx), sp)) { \

View File

@ -2614,6 +2614,7 @@ static void
SweepZones(FreeOp *fop, bool lastGC)
{
JSRuntime *rt = fop->runtime();
JSZoneCallback callback = rt->destroyZoneCallback;
/* Skip the atomsCompartment zone. */
Zone **read = rt->zones.begin() + 1;
@ -2628,6 +2629,8 @@ SweepZones(FreeOp *fop, bool lastGC)
if (!zone->hold && zone->wasGCStarted()) {
if (zone->allocator.arenas.arenaListsAreEmpty() || lastGC) {
zone->allocator.arenas.checkEmptyFreeLists();
if (callback)
callback(zone);
SweepCompartments(fop, zone, false, lastGC);
JS_ASSERT(zone->compartments.empty());
fop->delete_(zone);
@ -3714,6 +3717,9 @@ BeginSweepingZoneGroup(JSRuntime *rt)
if (rt->isAtomsZone(zone))
sweepingAtoms = true;
if (rt->sweepZoneCallback)
rt->sweepZoneCallback(zone);
}
ValidateIncrementalMarking(rt);

View File

@ -389,7 +389,7 @@ class BytecodeParser
JSContext *cx_;
LifoAllocScope allocScope_;
JSScript *script_;
RootedScript script_;
Bytecode **codeArray_;
@ -397,7 +397,7 @@ class BytecodeParser
BytecodeParser(JSContext *cx, JSScript *script)
: cx_(cx),
allocScope_(&cx->tempLifoAlloc()),
script_(script),
script_(cx, script),
codeArray_(nullptr) { }
bool parse();
@ -949,7 +949,7 @@ js_Disassemble1(JSContext *cx, HandleScript script, jsbytecode *pc,
}
case JOF_SCOPECOORD: {
Value v = StringValue(ScopeCoordinateName(cx, script, pc));
Value v = StringValue(ScopeCoordinateName(script, pc));
JSAutoByteString bytes;
if (!ToDisassemblySource(cx, v, &bytes))
return 0;
@ -1590,7 +1590,7 @@ ExpressionDecompiler::decompilePC(jsbytecode *pc)
}
case JSOP_CALLALIASEDVAR:
case JSOP_GETALIASEDVAR: {
JSAtom *atom = ScopeCoordinateName(cx, script, pc);
JSAtom *atom = ScopeCoordinateName(script, pc);
JS_ASSERT(atom);
return write(atom);
}

View File

@ -562,6 +562,10 @@ class NodeBuilder
bool letStatement(NodeVector &head, HandleValue stmt, TokenPos *pos, MutableHandleValue dst);
bool importDeclaration(NodeVector &elts, HandleValue moduleSpec, TokenPos *pos, MutableHandleValue dst);
bool importSpecifier(HandleValue importName, HandleValue bindingName, TokenPos *pos, MutableHandleValue dst);
/*
* expressions
*/
@ -1353,6 +1357,38 @@ NodeBuilder::letStatement(NodeVector &head, HandleValue stmt, TokenPos *pos, Mut
dst);
}
bool
NodeBuilder::importDeclaration(NodeVector &elts, HandleValue moduleSpec, TokenPos *pos,
MutableHandleValue dst)
{
RootedValue array(cx);
if (!newArray(elts, &array))
return false;
RootedValue cb(cx, callbacks[AST_IMPORT_DECL]);
if (!cb.isNull())
return callback(cb, array, moduleSpec, pos, dst);
return newNode(AST_IMPORT_DECL, pos,
"specifiers", array,
"source", moduleSpec,
dst);
}
bool
NodeBuilder::importSpecifier(HandleValue importName, HandleValue bindingName, TokenPos *pos,
MutableHandleValue dst)
{
RootedValue cb(cx, callbacks[AST_IMPORT_SPEC]);
if (!cb.isNull())
return callback(cb, importName, bindingName, pos, dst);
return newNode(AST_IMPORT_SPEC, pos,
"id", importName,
"name", bindingName,
dst);
}
bool
NodeBuilder::variableDeclaration(NodeVector &elts, VarDeclKind kind, TokenPos *pos,
MutableHandleValue dst)
@ -1520,6 +1556,8 @@ class ASTSerializer
bool variableDeclaration(ParseNode *pn, bool let, MutableHandleValue dst);
bool variableDeclarator(ParseNode *pn, VarDeclKind *pkind, MutableHandleValue dst);
bool let(ParseNode *pn, bool expr, MutableHandleValue dst);
bool importDeclaration(ParseNode *pn, MutableHandleValue dst);
bool importSpecifier(ParseNode *pn, MutableHandleValue dst);
bool optStatement(ParseNode *pn, MutableHandleValue dst) {
if (!pn) {
@ -1883,6 +1921,41 @@ ASTSerializer::let(ParseNode *pn, bool expr, MutableHandleValue dst)
builder.letStatement(dtors, v, &pn->pn_pos, dst);
}
bool
ASTSerializer::importDeclaration(ParseNode *pn, MutableHandleValue dst)
{
JS_ASSERT(pn->isKind(PNK_IMPORT));
JS_ASSERT(pn->pn_left->isKind(PNK_IMPORT_SPEC_LIST));
JS_ASSERT(pn->pn_right->isKind(PNK_STRING));
NodeVector elts(cx);
if (!elts.reserve(pn->pn_count))
return false;
for (ParseNode *next = pn->pn_left->pn_head; next; next = next->pn_next) {
RootedValue elt(cx);
if (!importSpecifier(next, &elt))
return false;
elts.infallibleAppend(elt);
}
RootedValue moduleSpec(cx);
return literal(pn->pn_right, &moduleSpec) &&
builder.importDeclaration(elts, moduleSpec, &pn->pn_pos, dst);
}
bool
ASTSerializer::importSpecifier(ParseNode *pn, MutableHandleValue dst)
{
JS_ASSERT(pn->isKind(PNK_IMPORT_SPEC));
RootedValue importName(cx);
RootedValue bindingName(cx);
return identifier(pn->pn_left, &importName) &&
identifier(pn->pn_right, &bindingName) &&
builder.importSpecifier(importName, bindingName, &pn->pn_pos, dst);
}
bool
ASTSerializer::switchCase(ParseNode *pn, MutableHandleValue dst)
{
@ -2038,6 +2111,9 @@ ASTSerializer::statement(ParseNode *pn, MutableHandleValue dst)
? let(pn, false, dst)
: declaration(pn, dst);
case PNK_IMPORT:
return importDeclaration(pn, dst);
case PNK_NAME:
LOCAL_ASSERT(pn->isUsed());
return statement(pn->pn_lexdef, dst);

View File

@ -687,8 +687,8 @@ js::XDRScript(XDRState<mode> *xdr, HandleObject enclosingScope, HandleScript enc
if (!innerScript)
return false;
RootedObject staticScope(cx, innerScript->enclosingStaticScope());
StaticScopeIter ssi(cx, staticScope);
if (ssi.done() || ssi.type() == StaticScopeIter::FUNCTION) {
StaticScopeIter<NoGC> ssi(staticScope);
if (ssi.done() || ssi.type() == StaticScopeIter<NoGC>::FUNCTION) {
JS_ASSERT(ssi.done() == !fun);
funEnclosingScopeIndex = UINT32_MAX;
} else {
@ -2315,9 +2315,9 @@ js::CloneScript(JSContext *cx, HandleObject enclosingScope, HandleFunction fun,
return nullptr;
}
RootedObject staticScope(cx, innerFun->nonLazyScript()->enclosingStaticScope());
StaticScopeIter ssi(cx, staticScope);
StaticScopeIter<CanGC> ssi(cx, staticScope);
RootedObject enclosingScope(cx);
if (!ssi.done() && ssi.type() == StaticScopeIter::BLOCK)
if (!ssi.done() && ssi.type() == StaticScopeIter<CanGC>::BLOCK)
enclosingScope = objects[FindBlockIndex(src, ssi.block())];
else
enclosingScope = fun;
@ -3001,8 +3001,8 @@ LazyScript::Create(ExclusiveContext *cx, HandleFunction fun,
uint32_t
LazyScript::staticLevel(JSContext *cx) const
{
for (StaticScopeIter ssi(cx, enclosingScope()); !ssi.done(); ssi++) {
if (ssi.type() == StaticScopeIter::FUNCTION)
for (StaticScopeIter<NoGC> ssi(enclosingScope()); !ssi.done(); ssi++) {
if (ssi.type() == StaticScopeIter<NoGC>::FUNCTION)
return ssi.funScript()->staticLevel + 1;
}
return 1;

View File

@ -4129,10 +4129,6 @@ static const JSFunctionSpecWithHelp shell_functions[] = {
"intern(str)",
" Internalize str in the atom table."),
JS_FN_HELP("clone", Clone, 1, 0,
"clone(fun[, scope])",
" Clone function object."),
JS_FN_HELP("getpda", GetPDA, 1, 0,
"getpda(obj)",
" Get the property descriptors for obj."),
@ -4277,6 +4273,10 @@ static const JSFunctionSpecWithHelp shell_functions[] = {
};
static const JSFunctionSpecWithHelp fuzzing_unsafe_functions[] = {
JS_FN_HELP("clone", Clone, 1, 0,
"clone(fun[, scope])",
" Clone function object."),
JS_FN_HELP("getSelfHostedValue", GetSelfHostedValue, 1, 0,
"getSelfHostedValue()",
" Get a self-hosted value by its name. Note that these values don't get \n"

View File

@ -15,6 +15,7 @@
macro(anonymous, anonymous, "anonymous") \
macro(apply, apply, "apply") \
macro(arguments, arguments, "arguments") \
macro(as, as, "as") \
macro(ArrayType, ArrayType, "ArrayType") \
macro(buffer, buffer, "buffer") \
macro(builder, builder, "builder") \
@ -43,6 +44,7 @@
macro(DateTimeFormatFormatGet, DateTimeFormatFormatGet, "Intl_DateTimeFormat_format_get") \
macro(decodeURI, decodeURI, "decodeURI") \
macro(decodeURIComponent, decodeURIComponent, "decodeURIComponent") \
macro(default_, default_, "default") \
macro(defineProperty, defineProperty, "defineProperty") \
macro(defineGetter, defineGetter, "__defineGetter__") \
macro(defineSetter, defineSetter, "__defineSetter__") \
@ -68,6 +70,7 @@
macro(float32, float32, "float32") \
macro(float64, float64, "float64") \
macro(format, format, "format") \
macro(from, from, "from") \
macro(get, get, "get") \
macro(getInternals, getInternals, "getInternals") \
macro(getOwnPropertyDescriptor, getOwnPropertyDescriptor, "getOwnPropertyDescriptor") \

View File

@ -390,6 +390,12 @@ class GlobalObject : public JSObject
return &self->getPrototype(JSProto_RegExp).toObject();
}
JSObject *maybeGetRegExpPrototype() {
if (regexpClassInitialized())
return &getPrototype(JSProto_RegExp).toObject();
return nullptr;
}
JSObject *getOrCreateArrayBufferPrototype(JSContext *cx) {
if (arrayBufferClassInitialized())
return &getPrototype(JSProto_ArrayBuffer).toObject();
@ -523,9 +529,10 @@ class GlobalObject : public JSObject
bool getIntrinsicValue(JSContext *cx, HandlePropertyName name, MutableHandleValue value) {
if (maybeGetIntrinsicValue(name, value.address()))
return true;
Rooted<GlobalObject*> self(cx, this);
if (!cx->runtime()->cloneSelfHostedValue(cx, name, value))
return false;
RootedObject holder(cx, intrinsicsHolder());
RootedObject holder(cx, self->intrinsicsHolder());
RootedId id(cx, NameToId(name));
return JS_DefinePropertyById(cx, holder, id, value, nullptr, nullptr, 0);
}

View File

@ -2787,7 +2787,7 @@ CASE(JSOP_SETALIASEDVAR)
// Avoid computing the name if no type updates are needed, as this may be
// expensive on scopes with large numbers of variables.
PropertyName *name = obj.hasSingletonType() ? ScopeCoordinateName(cx, script, REGS.pc)
PropertyName *name = obj.hasSingletonType() ? ScopeCoordinateName(script, REGS.pc)
: nullptr;
obj.setAliasedVar(cx, sc, name, REGS.sp[-1]);

View File

@ -41,12 +41,12 @@
macro(void, void_, TOK_VOID, JSVERSION_DEFAULT) \
macro(while, while_, TOK_WHILE, JSVERSION_DEFAULT) \
macro(with, with, TOK_WITH, JSVERSION_DEFAULT) \
macro(import, import, TOK_IMPORT, JSVERSION_DEFAULT) \
/* Reserved keywords. */ \
macro(class, class_, TOK_RESERVED, JSVERSION_DEFAULT) \
macro(enum, enum_, TOK_RESERVED, JSVERSION_DEFAULT) \
macro(export, export, TOK_RESERVED, JSVERSION_DEFAULT) \
macro(extends, extends, TOK_RESERVED, JSVERSION_DEFAULT) \
macro(import, import, TOK_RESERVED, JSVERSION_DEFAULT) \
macro(super, super, TOK_RESERVED, JSVERSION_DEFAULT) \
/* Future reserved keywords, but only in strict mode. */ \
macro(implements, implements, TOK_STRICT_RESERVED, JSVERSION_DEFAULT) \

View File

@ -146,6 +146,8 @@ JSRuntime::JSRuntime(JSUseHelperThreads useHelperThreads)
nativeStackBase(0),
cxCallback(nullptr),
destroyCompartmentCallback(nullptr),
destroyZoneCallback(nullptr),
sweepZoneCallback(nullptr),
compartmentNameCallback(nullptr),
activityCallback(nullptr),
activityCallbackArg(nullptr),

View File

@ -950,6 +950,12 @@ struct JSRuntime : public JS::shadow::Runtime,
/* Compartment destroy callback. */
JSDestroyCompartmentCallback destroyCompartmentCallback;
/* Zone destroy callback. */
JSZoneCallback destroyZoneCallback;
/* Zone sweep callback. */
JSZoneCallback sweepZoneCallback;
/* Call this to get the name of a compartment. */
JSCompartmentNameCallback compartmentNameCallback;

View File

@ -36,6 +36,74 @@ CallObject::setAliasedVar(JSContext *cx, AliasedFormalIter fi, PropertyName *nam
types::AddTypePropertyId(cx, this, NameToId(name), v);
}
template <AllowGC allowGC>
inline bool
StaticScopeIter<allowGC>::done() const
{
return !obj;
}
template <AllowGC allowGC>
inline void
StaticScopeIter<allowGC>::operator++(int)
{
if (obj->template is<StaticBlockObject>()) {
obj = obj->template as<StaticBlockObject>().enclosingStaticScope();
} else if (onNamedLambda || !obj->template as<JSFunction>().isNamedLambda()) {
onNamedLambda = false;
obj = obj->template as<JSFunction>().nonLazyScript()->enclosingStaticScope();
} else {
onNamedLambda = true;
}
JS_ASSERT_IF(obj, obj->template is<StaticBlockObject>() || obj->template is<JSFunction>());
JS_ASSERT_IF(onNamedLambda, obj->template is<JSFunction>());
}
template <AllowGC allowGC>
inline bool
StaticScopeIter<allowGC>::hasDynamicScopeObject() const
{
return obj->template is<StaticBlockObject>()
? obj->template as<StaticBlockObject>().needsClone()
: obj->template as<JSFunction>().isHeavyweight();
}
template <AllowGC allowGC>
inline Shape *
StaticScopeIter<allowGC>::scopeShape() const
{
JS_ASSERT(hasDynamicScopeObject());
JS_ASSERT(type() != NAMED_LAMBDA);
return type() == BLOCK
? block().lastProperty()
: funScript()->bindings.callObjShape();
}
template <AllowGC allowGC>
inline typename StaticScopeIter<allowGC>::Type
StaticScopeIter<allowGC>::type() const
{
if (onNamedLambda)
return NAMED_LAMBDA;
return obj->template is<StaticBlockObject>() ? BLOCK : FUNCTION;
}
template <AllowGC allowGC>
inline StaticBlockObject &
StaticScopeIter<allowGC>::block() const
{
JS_ASSERT(type() == BLOCK);
return obj->template as<StaticBlockObject>();
}
template <AllowGC allowGC>
inline JSScript *
StaticScopeIter<allowGC>::funScript() const
{
JS_ASSERT(type() == FUNCTION);
return obj->template as<JSFunction>().nonLazyScript();
}
} /* namespace js */
#endif /* vm_ScopeObject_inl_h */

View File

@ -32,75 +32,6 @@ typedef Rooted<ArgumentsObject *> RootedArgumentsObject;
/*****************************************************************************/
StaticScopeIter::StaticScopeIter(ExclusiveContext *cx, JSObject *objArg)
: obj(cx, objArg), onNamedLambda(false)
{
JS_ASSERT_IF(obj, obj->is<StaticBlockObject>() || obj->is<JSFunction>());
}
bool
StaticScopeIter::done() const
{
return !obj;
}
void
StaticScopeIter::operator++(int)
{
if (obj->is<StaticBlockObject>()) {
obj = obj->as<StaticBlockObject>().enclosingStaticScope();
} else if (onNamedLambda || !obj->as<JSFunction>().isNamedLambda()) {
onNamedLambda = false;
obj = obj->as<JSFunction>().nonLazyScript()->enclosingStaticScope();
} else {
onNamedLambda = true;
}
JS_ASSERT_IF(obj, obj->is<StaticBlockObject>() || obj->is<JSFunction>());
JS_ASSERT_IF(onNamedLambda, obj->is<JSFunction>());
}
bool
StaticScopeIter::hasDynamicScopeObject() const
{
return obj->is<StaticBlockObject>()
? obj->as<StaticBlockObject>().needsClone()
: obj->as<JSFunction>().isHeavyweight();
}
Shape *
StaticScopeIter::scopeShape() const
{
JS_ASSERT(hasDynamicScopeObject());
JS_ASSERT(type() != NAMED_LAMBDA);
return type() == BLOCK
? block().lastProperty()
: funScript()->bindings.callObjShape();
}
StaticScopeIter::Type
StaticScopeIter::type() const
{
if (onNamedLambda)
return NAMED_LAMBDA;
return obj->is<StaticBlockObject>() ? BLOCK : FUNCTION;
}
StaticBlockObject &
StaticScopeIter::block() const
{
JS_ASSERT(type() == BLOCK);
return obj->as<StaticBlockObject>();
}
JSScript *
StaticScopeIter::funScript() const
{
JS_ASSERT(type() == FUNCTION);
return obj->as<JSFunction>().nonLazyScript();
}
/*****************************************************************************/
static JSObject *
InnermostStaticScope(JSScript *script, jsbytecode *pc)
{
@ -115,9 +46,9 @@ InnermostStaticScope(JSScript *script, jsbytecode *pc)
}
Shape *
js::ScopeCoordinateToStaticScopeShape(JSContext *cx, JSScript *script, jsbytecode *pc)
js::ScopeCoordinateToStaticScopeShape(JSScript *script, jsbytecode *pc)
{
StaticScopeIter ssi(cx, InnermostStaticScope(script, pc));
StaticScopeIter<NoGC> ssi(InnermostStaticScope(script, pc));
ScopeCoordinate sc(pc);
while (true) {
if (ssi.hasDynamicScopeObject()) {
@ -131,9 +62,9 @@ js::ScopeCoordinateToStaticScopeShape(JSContext *cx, JSScript *script, jsbytecod
}
PropertyName *
js::ScopeCoordinateName(JSContext *cx, JSScript *script, jsbytecode *pc)
js::ScopeCoordinateName(JSScript *script, jsbytecode *pc)
{
Shape::Range<NoGC> r(ScopeCoordinateToStaticScopeShape(cx, script, pc));
Shape::Range<NoGC> r(ScopeCoordinateToStaticScopeShape(script, pc));
ScopeCoordinate sc(pc);
while (r.front().slot() != sc.slot)
r.popFront();
@ -141,14 +72,14 @@ js::ScopeCoordinateName(JSContext *cx, JSScript *script, jsbytecode *pc)
/* Beware nameless destructuring formal. */
if (!JSID_IS_ATOM(id))
return cx->runtime()->atomState.empty;
return script->runtimeFromAnyThread()->atomState.empty;
return JSID_TO_ATOM(id)->asPropertyName();
}
JSScript *
js::ScopeCoordinateFunctionScript(JSContext *cx, JSScript *script, jsbytecode *pc)
js::ScopeCoordinateFunctionScript(JSScript *script, jsbytecode *pc)
{
StaticScopeIter ssi(cx, InnermostStaticScope(script, pc));
StaticScopeIter<NoGC> ssi(InnermostStaticScope(script, pc));
ScopeCoordinate sc(pc);
while (true) {
if (ssi.hasDynamicScopeObject()) {
@ -158,7 +89,7 @@ js::ScopeCoordinateFunctionScript(JSContext *cx, JSScript *script, jsbytecode *p
}
ssi++;
}
if (ssi.type() != StaticScopeIter::FUNCTION)
if (ssi.type() != StaticScopeIter<NoGC>::FUNCTION)
return nullptr;
return ssi.funScript();
}
@ -2195,7 +2126,7 @@ RemoveReferencedNames(JSContext *cx, HandleScript script, PropertyNameSet &remai
case JSOP_GETALIASEDVAR:
case JSOP_CALLALIASEDVAR:
case JSOP_SETALIASEDVAR:
name = ScopeCoordinateName(cx, script, pc);
name = ScopeCoordinateName(script, pc);
break;
default:

View File

@ -54,13 +54,26 @@ namespace frontend { struct Definition; }
*
* (See also AssertDynamicScopeMatchesStaticScope.)
*/
template <AllowGC allowGC>
class StaticScopeIter
{
RootedObject obj;
typename MaybeRooted<JSObject*, allowGC>::RootType obj;
bool onNamedLambda;
public:
explicit StaticScopeIter(ExclusiveContext *cx, JSObject *obj);
StaticScopeIter(ExclusiveContext *cx, JSObject *obj)
: obj(cx, obj), onNamedLambda(false)
{
JS_STATIC_ASSERT(allowGC == CanGC);
JS_ASSERT_IF(obj, obj->is<StaticBlockObject>() || obj->is<JSFunction>());
}
StaticScopeIter(JSObject *obj)
: obj((ExclusiveContext *) nullptr, obj), onNamedLambda(false)
{
JS_STATIC_ASSERT(allowGC == NoGC);
JS_ASSERT_IF(obj, obj->is<StaticBlockObject>() || obj->is<JSFunction>());
}
bool done() const;
void operator++(int);
@ -106,15 +119,15 @@ struct ScopeCoordinate
* accessed by the ALIASEDVAR op at 'pc'.
*/
extern Shape *
ScopeCoordinateToStaticScopeShape(JSContext *cx, JSScript *script, jsbytecode *pc);
ScopeCoordinateToStaticScopeShape(JSScript *script, jsbytecode *pc);
/* Return the name being accessed by the given ALIASEDVAR op. */
extern PropertyName *
ScopeCoordinateName(JSContext *cx, JSScript *script, jsbytecode *pc);
ScopeCoordinateName(JSScript *script, jsbytecode *pc);
/* Return the function script accessed by the given ALIASEDVAR op, or nullptr. */
extern JSScript *
ScopeCoordinateFunctionScript(JSContext *cx, JSScript *script, jsbytecode *pc);
ScopeCoordinateFunctionScript(JSScript *script, jsbytecode *pc);
/*****************************************************************************/

View File

@ -1295,6 +1295,7 @@ class Shape : public gc::BarrieredCell<Shape>
}
inline Shape *search(ExclusiveContext *cx, jsid id);
inline Shape *searchLinear(jsid id);
/* For JIT usage */
static inline size_t offsetOfBase() { return offsetof(Shape, base_); }
@ -1582,6 +1583,25 @@ Shape::Shape(UnownedBaseShape *base, uint32_t nfixed)
kids.setNull();
}
inline Shape *
Shape::searchLinear(jsid id)
{
/*
* Non-dictionary shapes can acquire a table at any point the main thread
* is operating on it, so other threads inspecting such shapes can't use
* their table without racing. This function can be called from any thread
* on any non-dictionary shape.
*/
JS_ASSERT(!inDictionary());
for (Shape *shape = this; shape; shape = shape->parent) {
if (shape->propidRef() == id)
return shape;
}
return nullptr;
}
/*
* Keep this function in sync with search. It neither hashifies the start
* shape nor increments linear search count.
@ -1598,12 +1618,7 @@ Shape::searchNoHashify(Shape *start, jsid id)
return SHAPE_FETCH(spp);
}
for (Shape *shape = start; shape; shape = shape->parent) {
if (shape->propidRef() == id)
return shape;
}
return nullptr;
return start->searchLinear(id);
}
inline bool

View File

@ -20,6 +20,7 @@
#include "jit/IonFrameIterator-inl.h"
#include "vm/Interpreter-inl.h"
#include "vm/Probes-inl.h"
#include "vm/ScopeObject-inl.h"
using namespace js;
@ -204,7 +205,7 @@ AssertDynamicScopeMatchesStaticScope(JSContext *cx, JSScript *script, JSObject *
{
#ifdef DEBUG
RootedObject enclosingScope(cx, script->enclosingStaticScope());
for (StaticScopeIter i(cx, enclosingScope); !i.done(); i++) {
for (StaticScopeIter<NoGC> i(enclosingScope); !i.done(); i++) {
if (i.hasDynamicScopeObject()) {
/*
* 'with' does not participate in the static scope of the script,
@ -214,15 +215,15 @@ AssertDynamicScopeMatchesStaticScope(JSContext *cx, JSScript *script, JSObject *
scope = &scope->as<WithObject>().enclosingScope();
switch (i.type()) {
case StaticScopeIter::BLOCK:
case StaticScopeIter<NoGC>::BLOCK:
JS_ASSERT(i.block() == scope->as<ClonedBlockObject>().staticBlock());
scope = &scope->as<ClonedBlockObject>().enclosingScope();
break;
case StaticScopeIter::FUNCTION:
case StaticScopeIter<NoGC>::FUNCTION:
JS_ASSERT(scope->as<CallObject>().callee().nonLazyScript() == i.funScript());
scope = &scope->as<CallObject>().enclosingScope();
break;
case StaticScopeIter::NAMED_LAMBDA:
case StaticScopeIter<NoGC>::NAMED_LAMBDA:
scope = &scope->as<DeclEnvObject>().enclosingScope();
break;
}

View File

@ -741,8 +741,6 @@ XPCJSRuntime::FinalizeCallback(JSFreeOp *fop, JSFinalizeStatus status, bool isCo
// Find dying scopes.
XPCWrappedNativeScope::StartFinalizationPhaseOfGC(fop, self);
XPCStringConvert::ClearCache();
self->mDoingFinalization = true;
break;
}

View File

@ -24,24 +24,29 @@
#include "jsapi.h"
#include "xpcpublic.h"
// One-slot cache, because it turns out it's common for web pages to
// get the same string a few times in a row. We get about a 40% cache
// hit rate on this cache last it was measured. We'd get about 70%
// hit rate with a hashtable with removal on finalization, but that
// would take a lot more machinery.
nsStringBuffer* XPCStringConvert::sCachedBuffer = nullptr;
JSString* XPCStringConvert::sCachedString = nullptr;
// Called from GC finalize callback to make sure we don't hand out a pointer to
// a JSString that's about to be finalized by incremental sweeping.
// static
void
XPCStringConvert::ClearCache()
XPCStringConvert::FreeZoneCache(JS::Zone *zone)
{
sCachedBuffer = nullptr;
sCachedString = nullptr;
// Put the zone user data into an AutoPtr (which will do the cleanup for us),
// and null out the user data (which may already be null).
nsAutoPtr<ZoneStringCache> cache(static_cast<ZoneStringCache*>(JS_GetZoneUserData(zone)));
JS_SetZoneUserData(zone, nullptr);
}
// static
void
XPCStringConvert::ClearZoneCache(JS::Zone *zone)
{
ZoneStringCache *cache = static_cast<ZoneStringCache*>(JS_GetZoneUserData(zone));
if (cache) {
cache->mBuffer = nullptr;
cache->mString = nullptr;
}
}
// static
void
XPCStringConvert::FinalizeDOMString(const JSStringFinalizer *fin, jschar *chars)
{
@ -83,26 +88,6 @@ XPCStringConvert::ReadableToJSVal(JSContext *cx,
}
// blech, have to copy.
jschar *chars = reinterpret_cast<jschar *>
(JS_malloc(cx, (length + 1) *
sizeof(jschar)));
if (!chars)
return JS::NullValue();
if (length && !CopyUnicodeTo(readable, 0,
reinterpret_cast<PRUnichar *>(chars),
length)) {
JS_free(cx, chars);
return JS::NullValue();
}
chars[length] = 0;
str = JS_NewUCString(cx, chars, length);
if (!str) {
JS_free(cx, chars);
}
return str ? STRING_TO_JSVAL(str) : JSVAL_NULL;
str = JS_NewUCStringCopyN(cx, readable.BeginReading(), length);
return str ? JS::StringValue(str) : JS::NullValue();
}

View File

@ -149,6 +149,17 @@ xpc_ActivateDebugMode();
// readable string conversions, static methods and members only
class XPCStringConvert
{
// One-slot cache, because it turns out it's common for web pages to
// get the same string a few times in a row. We get about a 40% cache
// hit rate on this cache last it was measured. We'd get about 70%
// hit rate with a hashtable with removal on finalization, but that
// would take a lot more machinery.
struct ZoneStringCache
{
nsStringBuffer* mBuffer;
JSString* mString;
};
public:
// If the string shares the readable's buffer, that buffer will
@ -162,10 +173,12 @@ public:
StringBufferToJSVal(JSContext* cx, nsStringBuffer* buf, uint32_t length,
JS::MutableHandleValue rval, bool* sharedBuffer)
{
if (buf == sCachedBuffer &&
JS::GetGCThingZone(sCachedString) == js::GetContextZone(cx))
{
rval.set(JS::StringValue(sCachedString));
JS::Zone *zone = js::GetContextZone(cx);
ZoneStringCache *cache = static_cast<ZoneStringCache*>(JS_GetZoneUserData(zone));
if (cache && buf == cache->mBuffer) {
MOZ_ASSERT(JS::GetGCThingZone(cache->mString) == zone);
JS::MarkStringAsLive(zone, cache->mString);
rval.setString(cache->mString);
*sharedBuffer = false;
return true;
}
@ -177,17 +190,20 @@ public:
return false;
}
rval.setString(str);
sCachedString = str;
sCachedBuffer = buf;
if (!cache) {
cache = new ZoneStringCache();
JS_SetZoneUserData(zone, cache);
}
cache->mBuffer = buf;
cache->mString = str;
*sharedBuffer = true;
return true;
}
static void ClearCache();
static void FreeZoneCache(JS::Zone *zone);
static void ClearZoneCache(JS::Zone *zone);
private:
static nsStringBuffer* sCachedBuffer;
static JSString* sCachedString;
static const JSStringFinalizer sDOMStringFinalizer;
static void FinalizeDOMString(const JSStringFinalizer *fin, jschar *chars);

View File

@ -24,6 +24,7 @@
#include "GeckoProfiler.h"
#include "mozilla/gfx/Tools.h"
#include "mozilla/gfx/2D.h"
#include <algorithm>
@ -1942,6 +1943,7 @@ PaintInactiveLayer(nsDisplayListBuilder* aBuilder,
context = new gfxContext(surf);
}
#endif
basic->BeginTransaction();
basic->SetTarget(context);
if (aItem->GetType() == nsDisplayItem::TYPE_SVG_EFFECTS) {
@ -2347,7 +2349,7 @@ FrameLayerBuilder::AddThebesDisplayItem(ThebesLayer* aLayer,
{
ThebesDisplayItemLayerUserData* thebesData =
static_cast<ThebesDisplayItemLayerUserData*>(aLayer->GetUserData(&gThebesDisplayItemLayerUserData));
nsRefPtr<LayerManager> tempManager;
nsRefPtr<BasicLayerManager> tempManager;
nsIntRect intClip;
bool hasClip = false;
if (aLayerState != LAYER_NONE) {
@ -2417,6 +2419,7 @@ FrameLayerBuilder::AddThebesDisplayItem(ThebesLayer* aLayer,
tempManager->SetRoot(layer);
layerBuilder->WillEndTransaction();
tempManager->AbortTransaction();
nsIntPoint offset = GetLastPaintOffset(aLayer) - GetTranslationForThebesLayer(aLayer);
props->MoveBy(-offset);
@ -2506,13 +2509,7 @@ FrameLayerBuilder::StoreDataForFrame(nsIFrame* aFrame,
FrameLayerBuilder::ClippedDisplayItem::~ClippedDisplayItem()
{
if (mInactiveLayerManager) {
// We always start a transaction during layer construction for all inactive
// layers, but we don't necessarily call EndTransaction during painting.
// If the transaaction is still open, end it to avoid assertions.
BasicLayerManager* basic = static_cast<BasicLayerManager*>(mInactiveLayerManager.get());
if (basic->InTransaction()) {
basic->EndTransaction(nullptr, nullptr);
}
basic->SetUserData(&gLayerManagerLayerBuilder, nullptr);
}
}
@ -2523,7 +2520,7 @@ FrameLayerBuilder::AddLayerDisplayItem(Layer* aLayer,
const DisplayItemClip& aClip,
LayerState aLayerState,
const nsPoint& aTopLeft,
LayerManager* aManager,
BasicLayerManager* aManager,
nsAutoPtr<nsDisplayItemGeometry> aGeometry)
{
if (aLayer->Manager() != mRetainingManager)
@ -3114,6 +3111,167 @@ static void DebugPaintItem(nsRenderingContext* aDest, nsDisplayItem *aItem, nsDi
}
#endif
/* static */ void
FrameLayerBuilder::RecomputeVisibilityForItems(nsTArray<ClippedDisplayItem>& aItems,
nsDisplayListBuilder *aBuilder,
const nsIntRegion& aRegionToDraw,
const nsIntPoint& aOffset,
int32_t aAppUnitsPerDevPixel,
float aXScale,
float aYScale)
{
uint32_t i;
// Update visible regions. We need perform visibility analysis again
// because we may be asked to draw into part of a ThebesLayer that
// isn't actually visible in the window (e.g., because a ThebesLayer
// expanded its visible region to a rectangle internally), in which
// case the mVisibleRect stored in the display item may be wrong.
nsRegion visible = aRegionToDraw.ToAppUnits(aAppUnitsPerDevPixel);
visible.MoveBy(NSIntPixelsToAppUnits(aOffset.x, aAppUnitsPerDevPixel),
NSIntPixelsToAppUnits(aOffset.y, aAppUnitsPerDevPixel));
visible.ScaleInverseRoundOut(aXScale, aYScale);
for (i = aItems.Length(); i > 0; --i) {
ClippedDisplayItem* cdi = &aItems[i - 1];
const DisplayItemClip& clip = cdi->mItem->GetClip();
NS_ASSERTION(AppUnitsPerDevPixel(cdi->mItem) == aAppUnitsPerDevPixel,
"a thebes layer should contain items only at the same zoom");
NS_ABORT_IF_FALSE(clip.HasClip() ||
clip.GetRoundedRectCount() == 0,
"If we have rounded rects, we must have a clip rect");
if (!clip.IsRectAffectedByClip(visible.GetBounds())) {
cdi->mItem->RecomputeVisibility(aBuilder, &visible);
continue;
}
// Do a little dance to account for the fact that we're clipping
// to cdi->mClipRect
nsRegion clipped;
clipped.And(visible, clip.NonRoundedIntersection());
nsRegion finalClipped = clipped;
cdi->mItem->RecomputeVisibility(aBuilder, &finalClipped);
// If we have rounded clip rects, don't subtract from the visible
// region since we aren't displaying everything inside the rect.
if (clip.GetRoundedRectCount() == 0) {
nsRegion removed;
removed.Sub(clipped, finalClipped);
nsRegion newVisible;
newVisible.Sub(visible, removed);
// Don't let the visible region get too complex.
if (newVisible.GetNumRects() <= 15) {
visible = newVisible;
}
}
}
}
void
FrameLayerBuilder::PaintItems(nsTArray<ClippedDisplayItem>& aItems,
const nsIntRect& aRect,
gfxContext *aContext,
nsRenderingContext *aRC,
nsDisplayListBuilder* aBuilder,
nsPresContext* aPresContext,
const nsIntPoint& aOffset,
float aXScale, float aYScale,
int32_t aCommonClipCount)
{
int32_t appUnitsPerDevPixel = aPresContext->AppUnitsPerDevPixel();
nsRect boundRect = aRect.ToAppUnits(appUnitsPerDevPixel);
boundRect.MoveBy(NSIntPixelsToAppUnits(aOffset.x, appUnitsPerDevPixel),
NSIntPixelsToAppUnits(aOffset.y, appUnitsPerDevPixel));
boundRect.ScaleInverseRoundOut(aXScale, aYScale);
DisplayItemClip currentClip;
bool currentClipIsSetInContext = false;
DisplayItemClip tmpClip;
for (uint32_t i = 0; i < aItems.Length(); ++i) {
ClippedDisplayItem* cdi = &aItems[i];
nsRect paintRect = cdi->mItem->GetVisibleRect().Intersect(boundRect);
if (paintRect.IsEmpty())
continue;
// If the new desired clip state is different from the current state,
// update the clip.
const DisplayItemClip* clip = &cdi->mItem->GetClip();
if (clip->GetRoundedRectCount() > 0 &&
!clip->IsRectClippedByRoundedCorner(cdi->mItem->GetVisibleRect())) {
tmpClip = *clip;
tmpClip.RemoveRoundedCorners();
clip = &tmpClip;
}
if (currentClipIsSetInContext != clip->HasClip() ||
(clip->HasClip() && *clip != currentClip)) {
if (currentClipIsSetInContext) {
aContext->Restore();
}
currentClipIsSetInContext = clip->HasClip();
if (currentClipIsSetInContext) {
currentClip = *clip;
aContext->Save();
NS_ASSERTION(aCommonClipCount < 100,
"Maybe you really do have more than a hundred clipping rounded rects, or maybe something has gone wrong.");
currentClip.ApplyTo(aContext, aPresContext, aCommonClipCount);
aContext->NewPath();
}
}
if (cdi->mInactiveLayerManager) {
PaintInactiveLayer(aBuilder, cdi->mInactiveLayerManager, cdi->mItem, aContext, aRC);
} else {
nsIFrame* frame = cdi->mItem->Frame();
frame->AddStateBits(NS_FRAME_PAINTED_THEBES);
#ifdef MOZ_DUMP_PAINTING
if (gfxUtils::sDumpPainting) {
DebugPaintItem(aRC, cdi->mItem, aBuilder);
} else {
#else
{
#endif
cdi->mItem->Paint(aBuilder, aRC);
}
}
if (CheckDOMModified())
break;
}
if (currentClipIsSetInContext) {
aContext->Restore();
}
}
/**
* Returns true if it is preferred to draw the list of display
* items separately for each rect in the visible region rather
* than clipping to a complex region.
*/
static bool ShouldDrawRectsSeparately(gfxContext* aContext, DrawRegionClip aClip)
{
if (aContext->IsCairo() || aClip == CLIP_NONE) {
return false;
}
DrawTarget *dt = aContext->GetDrawTarget();
return dt->GetType() == BACKEND_DIRECT2D;
}
static void DrawForcedBackgroundColor(gfxContext* aContext, Layer* aLayer, nscolor aBackgroundColor)
{
if (NS_GET_A(aBackgroundColor) > 0) {
nsIntRect r = aLayer->GetVisibleRegion().GetBounds();
aContext->NewPath();
aContext->Rectangle(gfxRect(r.x, r.y, r.width, r.height));
aContext->SetColor(gfxRGBA(aBackgroundColor));
aContext->Fill();
}
}
/*
* A note on residual transforms:
*
@ -3146,6 +3304,7 @@ static void DebugPaintItem(nsRenderingContext* aDest, nsDisplayItem *aItem, nsDi
FrameLayerBuilder::DrawThebesLayer(ThebesLayer* aLayer,
gfxContext* aContext,
const nsIntRegion& aRegionToDraw,
DrawRegionClip aClip,
const nsIntRegion& aRegionToInvalidate,
void* aCallbackData)
{
@ -3160,163 +3319,77 @@ FrameLayerBuilder::DrawThebesLayer(ThebesLayer* aLayer,
if (layerBuilder->CheckDOMModified())
return;
nsTArray<ClippedDisplayItem> items;
uint32_t commonClipCount;
nsIFrame* containerLayerFrame;
{
ThebesLayerItemsEntry* entry = layerBuilder->mThebesLayerItems.GetEntry(aLayer);
NS_ASSERTION(entry, "We shouldn't be drawing into a layer with no items!");
items.SwapElements(entry->mItems);
commonClipCount = entry->mCommonClipCount;
containerLayerFrame = entry->mContainerLayerFrame;
// Later after this point, due to calls to DidEndTransaction
// for temporary layer managers, mThebesLayerItems can change,
// so 'entry' could become invalid.
}
if (!containerLayerFrame) {
ThebesLayerItemsEntry* entry = layerBuilder->mThebesLayerItems.GetEntry(aLayer);
NS_ASSERTION(entry, "We shouldn't be drawing into a layer with no items!");
if (!entry->mContainerLayerFrame) {
return;
}
ThebesDisplayItemLayerUserData* userData =
static_cast<ThebesDisplayItemLayerUserData*>
(aLayer->GetUserData(&gThebesDisplayItemLayerUserData));
NS_ASSERTION(userData, "where did our user data go?");
if (NS_GET_A(userData->mForcedBackgroundColor) > 0) {
nsIntRect r = aLayer->GetVisibleRegion().GetBounds();
aContext->NewPath();
aContext->Rectangle(gfxRect(r.x, r.y, r.width, r.height));
aContext->SetColor(gfxRGBA(userData->mForcedBackgroundColor));
aContext->Fill();
bool shouldDrawRectsSeparately = ShouldDrawRectsSeparately(aContext, aClip);
if (!shouldDrawRectsSeparately) {
if (aClip == CLIP_DRAW_SNAPPED) {
gfxUtils::ClipToRegionSnapped(aContext, aRegionToDraw);
} else if (aClip == CLIP_DRAW) {
gfxUtils::ClipToRegion(aContext, aRegionToDraw);
}
DrawForcedBackgroundColor(aContext, aLayer, userData->mForcedBackgroundColor);
}
// make the origin of the context coincide with the origin of the
// ThebesLayer
gfxContextMatrixAutoSaveRestore saveMatrix(aContext);
nsIntPoint offset = GetTranslationForThebesLayer(aLayer);
// Apply the residual transform if it has been enabled, to ensure that
// snapping when we draw into aContext exactly matches the ideal transform.
// See above for why this is OK.
aContext->Translate(aLayer->GetResidualTranslation() - gfxPoint(offset.x, offset.y));
aContext->Scale(userData->mXScale, userData->mYScale);
nsPresContext* presContext = containerLayerFrame->PresContext();
nsPresContext* presContext = entry->mContainerLayerFrame->PresContext();
int32_t appUnitsPerDevPixel = presContext->AppUnitsPerDevPixel();
uint32_t i;
// Update visible regions. We need perform visibility analysis again
// because we may be asked to draw into part of a ThebesLayer that
// isn't actually visible in the window (e.g., because a ThebesLayer
// expanded its visible region to a rectangle internally), in which
// case the mVisibleRect stored in the display item may be wrong.
nsRegion visible = aRegionToDraw.ToAppUnits(appUnitsPerDevPixel);
visible.MoveBy(NSIntPixelsToAppUnits(offset.x, appUnitsPerDevPixel),
NSIntPixelsToAppUnits(offset.y, appUnitsPerDevPixel));
visible.ScaleInverseRoundOut(userData->mXScale, userData->mYScale);
for (i = items.Length(); i > 0; --i) {
ClippedDisplayItem* cdi = &items[i - 1];
const DisplayItemClip& clip = cdi->mItem->GetClip();
NS_ASSERTION(AppUnitsPerDevPixel(cdi->mItem) == appUnitsPerDevPixel,
"a thebes layer should contain items only at the same zoom");
NS_ABORT_IF_FALSE(clip.HasClip() ||
clip.GetRoundedRectCount() == 0,
"If we have rounded rects, we must have a clip rect");
if (!clip.IsRectAffectedByClip(visible.GetBounds())) {
cdi->mItem->RecomputeVisibility(builder, &visible);
continue;
}
// Do a little dance to account for the fact that we're clipping
// to cdi->mClipRect
nsRegion clipped;
clipped.And(visible, clip.NonRoundedIntersection());
nsRegion finalClipped = clipped;
cdi->mItem->RecomputeVisibility(builder, &finalClipped);
// If we have rounded clip rects, don't subtract from the visible
// region since we aren't displaying everything inside the rect.
if (clip.GetRoundedRectCount() == 0) {
nsRegion removed;
removed.Sub(clipped, finalClipped);
nsRegion newVisible;
newVisible.Sub(visible, removed);
// Don't let the visible region get too complex.
if (newVisible.GetNumRects() <= 15) {
visible = newVisible;
}
}
}
RecomputeVisibilityForItems(entry->mItems, builder, aRegionToDraw,
offset, appUnitsPerDevPixel,
userData->mXScale, userData->mYScale);
nsRefPtr<nsRenderingContext> rc = new nsRenderingContext();
rc->Init(presContext->DeviceContext(), aContext);
DisplayItemClip currentClip;
bool currentClipIsSetInContext = false;
DisplayItemClip tmpClip;
if (shouldDrawRectsSeparately) {
nsIntRegionRectIterator it(aRegionToDraw);
while (const nsIntRect* iterRect = it.Next()) {
gfxContextAutoSaveRestore save(aContext);
aContext->NewPath();
aContext->Rectangle(*iterRect, aClip == CLIP_DRAW_SNAPPED);
aContext->Clip();
for (i = 0; i < items.Length(); ++i) {
ClippedDisplayItem* cdi = &items[i];
DrawForcedBackgroundColor(aContext, aLayer, userData->mForcedBackgroundColor);
if (cdi->mItem->GetVisibleRect().IsEmpty())
continue;
// Apply the residual transform if it has been enabled, to ensure that
// snapping when we draw into aContext exactly matches the ideal transform.
// See above for why this is OK.
aContext->Translate(aLayer->GetResidualTranslation() - gfxPoint(offset.x, offset.y));
aContext->Scale(userData->mXScale, userData->mYScale);
// If the new desired clip state is different from the current state,
// update the clip.
const DisplayItemClip* clip = &cdi->mItem->GetClip();
if (clip->GetRoundedRectCount() > 0 &&
!clip->IsRectClippedByRoundedCorner(cdi->mItem->GetVisibleRect())) {
tmpClip = *clip;
tmpClip.RemoveRoundedCorners();
clip = &tmpClip;
}
if (currentClipIsSetInContext != clip->HasClip() ||
(clip->HasClip() && *clip != currentClip)) {
if (currentClipIsSetInContext) {
aContext->Restore();
}
currentClipIsSetInContext = clip->HasClip();
if (currentClipIsSetInContext) {
currentClip = *clip;
aContext->Save();
NS_ASSERTION(commonClipCount < 100,
"Maybe you really do have more than a hundred clipping rounded rects, or maybe something has gone wrong.");
currentClip.ApplyTo(aContext, presContext, commonClipCount);
aContext->NewPath();
}
layerBuilder->PaintItems(entry->mItems, *iterRect, aContext, rc,
builder, presContext,
offset, userData->mXScale, userData->mYScale,
entry->mCommonClipCount);
}
} else {
// Apply the residual transform if it has been enabled, to ensure that
// snapping when we draw into aContext exactly matches the ideal transform.
// See above for why this is OK.
aContext->Translate(aLayer->GetResidualTranslation() - gfxPoint(offset.x, offset.y));
aContext->Scale(userData->mXScale, userData->mYScale);
if (cdi->mInactiveLayerManager) {
PaintInactiveLayer(builder, cdi->mInactiveLayerManager, cdi->mItem, aContext, rc);
} else {
nsIFrame* frame = cdi->mItem->Frame();
frame->AddStateBits(NS_FRAME_PAINTED_THEBES);
#ifdef MOZ_DUMP_PAINTING
if (gfxUtils::sDumpPainting) {
DebugPaintItem(rc, cdi->mItem, builder);
} else {
#else
{
#endif
cdi->mItem->Paint(builder, rc);
}
}
if (layerBuilder->CheckDOMModified())
break;
}
{
ThebesLayerItemsEntry* entry =
layerBuilder->mThebesLayerItems.GetEntry(aLayer);
items.SwapElements(entry->mItems);
}
if (currentClipIsSetInContext) {
aContext->Restore();
layerBuilder->PaintItems(entry->mItems, aRegionToDraw.GetBounds(), aContext, rc,
builder, presContext,
offset, userData->mXScale, userData->mYScale,
entry->mCommonClipCount);
}
if (presContext->GetPaintFlashing()) {

View File

@ -24,6 +24,7 @@ namespace mozilla {
namespace layers {
class ContainerLayer;
class LayerManager;
class BasicLayerManager;
class ThebesLayer;
}
@ -95,6 +96,7 @@ public:
typedef layers::ThebesLayer ThebesLayer;
typedef layers::ImageLayer ImageLayer;
typedef layers::LayerManager LayerManager;
typedef layers::BasicLayerManager BasicLayerManager;
FrameLayerBuilder() :
mRetainingManager(nullptr),
@ -242,6 +244,7 @@ public:
static void DrawThebesLayer(ThebesLayer* aLayer,
gfxContext* aContext,
const nsIntRegion& aRegionToDraw,
mozilla::layers::DrawRegionClip aClip,
const nsIntRegion& aRegionToInvalidate,
void* aCallbackData);
@ -273,7 +276,7 @@ public:
const DisplayItemClip& aClip,
LayerState aLayerState,
const nsPoint& aTopLeft,
LayerManager* aManager,
BasicLayerManager* aManager,
nsAutoPtr<nsDisplayItemGeometry> aGeometry);
/**
@ -420,7 +423,7 @@ public:
LayerManagerData* mParent;
nsRefPtr<Layer> mLayer;
nsRefPtr<Layer> mOptLayer;
nsRefPtr<LayerManager> mInactiveManager;
nsRefPtr<BasicLayerManager> mInactiveManager;
nsAutoTArray<nsIFrame*, 1> mFrameList;
nsAutoPtr<nsDisplayItemGeometry> mGeometry;
DisplayItemClip mClip;
@ -518,6 +521,24 @@ protected:
uint32_t mContainerLayerGeneration;
};
static void RecomputeVisibilityForItems(nsTArray<ClippedDisplayItem>& aItems,
nsDisplayListBuilder* aBuilder,
const nsIntRegion& aRegionToDraw,
const nsIntPoint& aOffset,
int32_t aAppUnitsPerDevPixel,
float aXScale,
float aYScale);
void PaintItems(nsTArray<ClippedDisplayItem>& aItems,
const nsIntRect& aRect,
gfxContext* aContext,
nsRenderingContext* aRC,
nsDisplayListBuilder* aBuilder,
nsPresContext* aPresContext,
const nsIntPoint& aOffset,
float aXScale, float aYScale,
int32_t aCommonClipCount);
/**
* We accumulate ClippedDisplayItem elements in a hashtable during
* the paint process. This is the hashentry for that hashtable.

View File

@ -27,7 +27,7 @@ MACPORTS_URL = {'8': 'https://distfiles.macports.org/MacPorts/MacPorts-2.1.3-10.
'7': 'https://distfiles.macports.org/MacPorts/MacPorts-2.1.3-10.7-Lion.pkg',
'6': 'https://distfiles.macports.org/MacPorts/MacPorts-2.1.3-10.6-SnowLeopard.pkg',}
MACPORTS_CLANG_PACKAGE = 'clang-3.2'
MACPORTS_CLANG_PACKAGE = 'clang-3.3'
RE_CLANG_VERSION = re.compile('Apple (?:clang|LLVM) version (\d+\.\d+)')

View File

@ -19,12 +19,26 @@ from manifestparser import TestManifest
from mozhttpd import MozHttpd
from marionette import Marionette
from moztest.results import TestResultCollection
from moztest.results import TestResultCollection, TestResult, relevant_line
from marionette_test import MarionetteJSTestCase, MarionetteTestCase
class MarionetteTest(TestResult):
@property
def test_name(self):
if self.test_class is not None:
return '%s.py %s.%s' % (self.test_class.split('.')[0],
self.test_class,
self.name)
else:
return self.name
class MarionetteTestResult(unittest._TextTestResult, TestResultCollection):
resultClass = MarionetteTest
def __init__(self, *args, **kwargs):
self.marionette = kwargs.pop('marionette')
TestResultCollection.__init__(self, 'MarionetteTest')
@ -83,10 +97,25 @@ class MarionetteTestResult(unittest._TextTestResult, TestResultCollection):
else:
return 0
def add_test_result(self, test, *args, **kwargs):
self.add_result(test, *args, **kwargs)
self[-1].time_start = test.start_time
self[-1].time_end = time.time() if test.start_time else 0
def add_test_result(self, test, result_expected='PASS',
result_actual='PASS', output='', context=None, **kwargs):
def get_class(test):
return test.__class__.__module__ + '.' + test.__class__.__name__
name = str(test).split()[0]
test_class = get_class(test)
if hasattr(test, 'jsFile'):
name = os.path.basename(test.jsFile)
test_class = None
t = self.resultClass(name=name, test_class=test_class,
time_start=test.start_time, result_expected=result_expected,
context=context, **kwargs)
t.finish(result_actual,
time_end=time.time() if test.start_time else 0,
reason=relevant_line(output),
output=output)
self.append(t)
def addError(self, test, err):
self.add_test_result(test, output=self._exc_info_to_string(err, test), result_actual='ERROR')

View File

@ -24,9 +24,7 @@ interface nsIAlertsService : nsISupports
* @param alertListener Used for callbacks. May be null if the caller
* doesn't care about callbacks.
* @param name The name of the notification. This is currently
* only used on OS X with Growl and Android.
* On OS X with Growl, users can disable notifications
* with a given name. On Android the name is hashed
* only used on Android. On Android the name is hashed
* and used as a notification ID. Notifications will
* replace previous notifications with the same name.
* @param dir Bidi override for the title. Valid values are

View File

@ -53,7 +53,7 @@ function runTest() {
ok(true, "Alerts service is available");
} catch (ex) {
todo(false,
"Alerts service is not available. (Mac OS X without Growl?)", ex);
"Alerts service is not available.", ex);
return;
}
@ -64,7 +64,7 @@ function runTest() {
false, "foobarcookie", observer);
ok(true, "showAlertNotification() succeeded. Waiting for notification...");
} catch (ex) {
todo(false, "showAlertNotification() failed. (Mac OS X without Growl?)", ex);
todo(false, "showAlertNotification() failed.", ex);
SimpleTest.finish();
}
}

View File

@ -35,7 +35,7 @@ if (!("@mozilla.org/alerts-service;1" in Cc)) {
getService(Ci.nsIAlertsService);
ok(true, "Alerts service is available");
} catch (ex) {
todo(false, "Alerts service is not available. (Mac OS X without Growl?)", ex);
todo(false, "Alerts service is not available.", ex);
}
if (notifier) {
@ -46,7 +46,7 @@ if (!("@mozilla.org/alerts-service;1" in Cc)) {
gNotificationIsAvailable = true;
} catch (ex) {
todo(false, "showAlertNotification() failed. (Mac OS X without Growl?)", ex);
todo(false, "showAlertNotification() failed.", ex);
}
}
}

View File

@ -83,7 +83,6 @@
<li><a href="about:license#gears">Google Gears License</a></li>
<li><a href="about:license#gears-istumbler">Google Gears/iStumbler License</a></li>
<li><a href="about:license#vp8">Google VP8 License</a></li>
<li><a href="about:license#growl">Growl License</a></li>
<li><a href="about:license#gyp">gyp License</a></li>
<li><a href="about:license#halloc">halloc License</a></li>
<li><a href="about:license#harfbuzz">HarfBuzz License</a></li>
@ -2260,48 +2259,7 @@ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
</pre>
<hr>
<h1><a id="growl"></a>Growl License</h1>
<p>This license applies to certain files in the directory
<span class="path">toolkit/components/alerts/mac/growl/</span>.
(This code only ships in the Mac OS X version of the product.)
<pre>
Copyright (c) The Growl Project, 2004-2011
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of Growl nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
</pre>
<hr>
<h1><a id="gyp"></a>gyp License</h1>

View File

@ -452,6 +452,8 @@ CycleCollectedJSRuntime::CycleCollectedJSRuntime(uint32_t aMaxbytes,
JS_SetGrayGCRootsTracer(mJSRuntime, TraceGrayJS, this);
JS_SetGCCallback(mJSRuntime, GCCallback, this);
JS_SetContextCallback(mJSRuntime, ContextCallback, this);
JS_SetDestroyZoneCallback(mJSRuntime, XPCStringConvert::FreeZoneCache);
JS_SetSweepZoneCallback(mJSRuntime, XPCStringConvert::ClearZoneCache);
nsCycleCollector_registerJSRuntime(this);
}