mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Merge inbound to m-c
This commit is contained in:
commit
723c3d7877
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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)]
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
@ -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,
|
||||
|
@ -2,3 +2,4 @@
|
||||
|
||||
[test_bug357450.js]
|
||||
[test_copypaste.xul]
|
||||
[test_messagemanager_principal.html]
|
||||
|
94
content/base/test/test_messagemanager_principal.html
Normal file
94
content/base/test/test_messagemanager_principal.html
Normal 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>
|
@ -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;
|
||||
}
|
||||
|
@ -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]
|
||||
|
47
content/html/content/test/test_option_defaultSelected.html
Normal file
47
content/html/content/test/test_option_defaultSelected.html
Normal 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>
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
||||
/**
|
||||
|
@ -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);
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -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*
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -265,6 +265,7 @@ public:
|
||||
typedef void (* DrawThebesLayerCallback)(ThebesLayer* aLayer,
|
||||
gfxContext* aContext,
|
||||
const nsIntRegion& aRegionToDraw,
|
||||
DrawRegionClip aClip,
|
||||
const nsIntRegion& aRegionToInvalidate,
|
||||
void* aCallbackData);
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
|
@ -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 {
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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
|
||||
|
@ -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());
|
||||
|
||||
|
@ -105,7 +105,8 @@ protected:
|
||||
const nsIntRegion& aRegionToDraw,
|
||||
const nsIntRegion& aExtendedRegionToDraw,
|
||||
const nsIntRegion& aRegionToInvalidate,
|
||||
bool aDidSelfCopy);
|
||||
bool aDidSelfCopy,
|
||||
DrawRegionClip aClip);
|
||||
|
||||
void PaintThebes();
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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; }
|
||||
|
||||
/**
|
||||
|
@ -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
|
||||
|
@ -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 */
|
||||
|
@ -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.
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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) \
|
||||
|
@ -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:
|
||||
|
@ -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,
|
||||
|
@ -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>
|
||||
|
@ -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. */
|
||||
|
@ -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);
|
||||
|
1
js/src/jit-test/lib/match.js
Normal file
1
js/src/jit-test/lib/match.js
Normal file
@ -0,0 +1 @@
|
||||
loadRelativeToScript("../../tests/js1_8_5/extensions/shell.js");
|
13
js/src/jit-test/tests/arguments/strict-osr-shadowed-args.js
Normal file
13
js/src/jit-test/tests/arguments/strict-osr-shadowed-args.js
Normal 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);
|
13
js/src/jit-test/tests/basic/bug934789-1.js
Normal file
13
js/src/jit-test/tests/basic/bug934789-1.js
Normal file
@ -0,0 +1,13 @@
|
||||
if (typeof dis === "function") {
|
||||
(function() {
|
||||
function foo() {}
|
||||
|
||||
dis(function bar(e) {
|
||||
try {
|
||||
(function() { e; });
|
||||
} catch (e) {
|
||||
foo();
|
||||
}
|
||||
});
|
||||
}());
|
||||
}
|
15
js/src/jit-test/tests/basic/bug934789-2.js
Normal file
15
js/src/jit-test/tests/basic/bug934789-2.js
Normal 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);
|
186
js/src/jit-test/tests/modules/import-declaration.js
Normal file
186
js/src/jit-test/tests/modules/import-declaration.js
Normal 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);
|
@ -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;
|
||||
|
@ -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.
|
||||
|
@ -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));
|
||||
|
@ -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
|
||||
|
@ -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_;
|
||||
|
@ -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")
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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")
|
||||
|
@ -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;
|
||||
|
@ -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)) { \
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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"
|
||||
|
@ -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") \
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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]);
|
||||
|
@ -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) \
|
||||
|
@ -146,6 +146,8 @@ JSRuntime::JSRuntime(JSUseHelperThreads useHelperThreads)
|
||||
nativeStackBase(0),
|
||||
cxCallback(nullptr),
|
||||
destroyCompartmentCallback(nullptr),
|
||||
destroyZoneCallback(nullptr),
|
||||
sweepZoneCallback(nullptr),
|
||||
compartmentNameCallback(nullptr),
|
||||
activityCallback(nullptr),
|
||||
activityCallbackArg(nullptr),
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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 */
|
||||
|
@ -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:
|
||||
|
@ -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);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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()) {
|
||||
|
@ -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.
|
||||
|
@ -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+)')
|
||||
|
||||
|
@ -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')
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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>
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user