зеркало из https://github.com/mozilla/gecko-dev.git
Merge last PGO-green changeset of mozilla-inbound to mozilla-central
This commit is contained in:
Коммит
5ada0548cd
|
@ -38,6 +38,7 @@ MOCHITEST_BROWSER_FILES = \
|
|||
browser_privatebrowsing_protocolhandler.js \
|
||||
browser_privatebrowsing_protocolhandler_page.html \
|
||||
browser_privatebrowsing_theming.js \
|
||||
browser_privatebrowsing_ui.js \
|
||||
browser_privatebrowsing_urlbarfocus.js \
|
||||
browser_privatebrowsing_windowtitle.js \
|
||||
browser_privatebrowsing_windowtitle_page.html \
|
||||
|
|
|
@ -0,0 +1,82 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
// This test makes sure that the gPrivateBrowsingUI object, the Private Browsing
|
||||
// menu item and its XUL <command> element work correctly.
|
||||
|
||||
function test() {
|
||||
// initialization
|
||||
waitForExplicitFinish();
|
||||
let windowsToClose = [];
|
||||
let testURI = "about:blank";
|
||||
let pbMenuItem;
|
||||
let cmd;
|
||||
|
||||
function doTest(aIsPrivateMode, aWindow, aCallback) {
|
||||
aWindow.gBrowser.selectedBrowser.addEventListener("load", function onLoad() {
|
||||
aWindow.gBrowser.selectedBrowser.removeEventListener("load", onLoad, true);
|
||||
|
||||
ok(aWindow.gPrivateBrowsingUI, "The gPrivateBrowsingUI object exists");
|
||||
|
||||
pbMenuItem = aWindow.document.getElementById("menu_newPrivateWindow");
|
||||
ok(pbMenuItem, "The Private Browsing menu item exists");
|
||||
|
||||
cmd = aWindow.document.getElementById("Tools:PrivateBrowsing");
|
||||
isnot(cmd, null, "XUL command object for the private browsing service exists");
|
||||
|
||||
is(pbMenuItem.getAttribute("label"), "New Private Window",
|
||||
"The Private Browsing menu item should read \"New Private Window\"");
|
||||
is(PrivateBrowsingUtils.isWindowPrivate(aWindow), aIsPrivateMode,
|
||||
"PrivateBrowsingUtils should report the correct per-window private browsing status (privateBrowsing should be " +
|
||||
aIsPrivateMode + ")");
|
||||
|
||||
aCallback();
|
||||
}, true);
|
||||
|
||||
aWindow.gBrowser.selectedBrowser.loadURI(testURI);
|
||||
};
|
||||
|
||||
function openPrivateBrowsingModeByUI(aWindow, aCallback) {
|
||||
Services.obs.addObserver(function observer(aSubject, aTopic, aData) {
|
||||
aSubject.addEventListener("load", function() {
|
||||
aSubject.removeEventListener("load", arguments.callee);
|
||||
Services.obs.removeObserver(observer, "domwindowopened");
|
||||
windowsToClose.push(aSubject);
|
||||
aCallback(aSubject);
|
||||
}, false);
|
||||
}, "domwindowopened", false);
|
||||
|
||||
cmd = aWindow.document.getElementById("Tools:PrivateBrowsing");
|
||||
var func = new Function("", cmd.getAttribute("oncommand"));
|
||||
func.call(cmd);
|
||||
};
|
||||
|
||||
function testOnWindow(aOptions, aCallback) {
|
||||
whenNewWindowLoaded(aOptions, function(aWin) {
|
||||
windowsToClose.push(aWin);
|
||||
// execute should only be called when need, like when you are opening
|
||||
// web pages on the test. If calling executeSoon() is not necesary, then
|
||||
// call whenNewWindowLoaded() instead of testOnWindow() on your test.
|
||||
executeSoon(function() aCallback(aWin));
|
||||
});
|
||||
};
|
||||
|
||||
// this function is called after calling finish() on the test.
|
||||
registerCleanupFunction(function() {
|
||||
windowsToClose.forEach(function(aWin) {
|
||||
aWin.close();
|
||||
});
|
||||
});
|
||||
|
||||
// test first when not on private mode
|
||||
testOnWindow({}, function(aWin) {
|
||||
doTest(false, aWin, function() {
|
||||
// then test when on private mode, opening a new private window from the
|
||||
// user interface.
|
||||
openPrivateBrowsingModeByUI(aWin, function(aPrivateWin) {
|
||||
doTest(true, aPrivateWin, finish);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
|
@ -2060,10 +2060,10 @@ private:
|
|||
|
||||
// XXX These belong somewhere else
|
||||
nsresult
|
||||
NS_NewHTMLDocument(nsIDocument** aInstancePtrResult);
|
||||
NS_NewHTMLDocument(nsIDocument** aInstancePtrResult, bool aLoadedAsData = false);
|
||||
|
||||
nsresult
|
||||
NS_NewXMLDocument(nsIDocument** aInstancePtrResult);
|
||||
NS_NewXMLDocument(nsIDocument** aInstancePtrResult, bool aLoadedAsData = false);
|
||||
|
||||
nsresult
|
||||
NS_NewSVGDocument(nsIDocument** aInstancePtrResult);
|
||||
|
|
|
@ -1945,6 +1945,7 @@ GK_ATOM(DeleteTxnName, "Deleting")
|
|||
GK_ATOM(Remote, "remote")
|
||||
GK_ATOM(RemoteId, "_remote_id")
|
||||
GK_ATOM(DisplayPort, "_displayport")
|
||||
GK_ATOM(CriticalDisplayPort, "_critical_displayport")
|
||||
|
||||
// Names for system metrics
|
||||
GK_ATOM(scrollbar_start_backward, "scrollbar-start-backward")
|
||||
|
|
|
@ -527,10 +527,7 @@ nsNodeUtils::CloneAndAdopt(nsINode *aNode, bool aClone, bool aDeep,
|
|||
if (aCx && wrapper) {
|
||||
nsIXPConnect *xpc = nsContentUtils::XPConnect();
|
||||
if (xpc) {
|
||||
nsCOMPtr<nsIXPConnectJSObjectHolder> oldWrapper;
|
||||
rv = xpc->ReparentWrappedNativeIfFound(aCx, wrapper, aNewScope, aNode,
|
||||
getter_AddRefs(oldWrapper));
|
||||
|
||||
rv = xpc->ReparentWrappedNativeIfFound(aCx, wrapper, aNewScope, aNode);
|
||||
if (NS_FAILED(rv)) {
|
||||
aNode->mNodeInfo.swap(nodeInfo);
|
||||
|
||||
|
|
|
@ -143,7 +143,8 @@ public:
|
|||
|
||||
nsHTMLCanvasElement* GetCanvas() const
|
||||
{
|
||||
return mCanvasElement;
|
||||
// corresponds to changes to the old bindings made in bug 745025
|
||||
return mCanvasElement->GetOriginalCanvas();
|
||||
}
|
||||
|
||||
void Save();
|
||||
|
|
|
@ -604,7 +604,11 @@ nsEventListenerManager::SetEventHandler(nsIAtom *aName,
|
|||
// XXX sXBL/XBL2 issue -- do we really want the owner here? What
|
||||
// if that's the XBL document?
|
||||
doc = node->OwnerDoc();
|
||||
global = doc->GetScriptGlobalObject();
|
||||
MOZ_ASSERT(!doc->IsLoadedAsData(), "Should not get in here at all");
|
||||
|
||||
// We want to allow compiling an event handler even in an unloaded
|
||||
// document, so use GetScopeObject here, not GetScriptHandlingObject.
|
||||
global = doc->GetScopeObject();
|
||||
} else {
|
||||
nsCOMPtr<nsPIDOMWindow> win = GetTargetAsInnerWindow();
|
||||
if (win) {
|
||||
|
@ -623,6 +627,13 @@ nsEventListenerManager::SetEventHandler(nsIAtom *aName,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
nsCOMPtr<nsPIDOMWindow> win = do_QueryInterface(global);
|
||||
if (win) {
|
||||
MOZ_ASSERT(win->IsInnerWindow(), "We should not have an outer window here!");
|
||||
}
|
||||
#endif
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
// return early preventing the event listener from being added
|
||||
// 'doc' is fetched above
|
||||
|
|
|
@ -99,6 +99,7 @@ MOCHITEST_FILES = \
|
|||
test_bug716822.html \
|
||||
test_bug742376.html \
|
||||
test_dragstart.html \
|
||||
test_bug812744.html \
|
||||
$(NULL)
|
||||
|
||||
MOCHITEST_CHROME_FILES = \
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=812744
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for Bug 812744</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=812744">Mozilla Bug 812744</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
<iframe id="f"></iframe>
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
|
||||
/** Test for Bug 812744 **/
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
addLoadEvent(function() {
|
||||
var f = $("f");
|
||||
var el = f.contentDocument.documentElement;
|
||||
f.onload = function() {
|
||||
el.setAttribute("onmouseleave", "(void 0)");
|
||||
is(el.onmouseleave.toString(), "function onmouseleave(event) {\n(void 0)\n}",
|
||||
"Should have a function here");
|
||||
SimpleTest.finish();
|
||||
};
|
||||
f.src = "http://www.example.com/"
|
||||
});
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
|
@ -173,7 +173,7 @@ protected:
|
|||
void CallPrintCallback();
|
||||
|
||||
nsString mCurrentContextId;
|
||||
nsCOMPtr<nsIDOMHTMLCanvasElement> mOriginalCanvas;
|
||||
nsRefPtr<nsHTMLCanvasElement> mOriginalCanvas;
|
||||
nsCOMPtr<nsIPrintCallback> mPrintCallback;
|
||||
nsCOMPtr<nsICanvasRenderingContextInternal> mCurrentContext;
|
||||
nsCOMPtr<nsHTMLCanvasPrintState> mPrintState;
|
||||
|
@ -193,7 +193,7 @@ public:
|
|||
|
||||
void ResetPrintCallback();
|
||||
|
||||
nsIDOMHTMLCanvasElement* GetOriginalCanvas();
|
||||
nsHTMLCanvasElement* GetOriginalCanvas();
|
||||
};
|
||||
|
||||
inline nsISupports*
|
||||
|
|
|
@ -796,7 +796,7 @@ protected:
|
|||
nsCOMPtr<nsIContent> mSourceLoadCandidate;
|
||||
|
||||
// An audio stream for writing audio directly from JS.
|
||||
nsRefPtr<AudioStream> mAudioStream;
|
||||
nsAutoPtr<AudioStream> mAudioStream;
|
||||
|
||||
// Range of time played.
|
||||
nsTimeRanges mPlayed;
|
||||
|
|
|
@ -307,7 +307,7 @@ nsHTMLCanvasElement::IsPrintCallbackDone()
|
|||
return mPrintState->mIsDone;
|
||||
}
|
||||
|
||||
nsIDOMHTMLCanvasElement*
|
||||
nsHTMLCanvasElement*
|
||||
nsHTMLCanvasElement::GetOriginalCanvas()
|
||||
{
|
||||
return mOriginalCanvas ? mOriginalCanvas.get() : this;
|
||||
|
@ -323,16 +323,16 @@ nsHTMLCanvasElement::CopyInnerTo(Element* aDest)
|
|||
nsHTMLCanvasElement* self = const_cast<nsHTMLCanvasElement*>(this);
|
||||
dest->mOriginalCanvas = self;
|
||||
|
||||
HTMLImageOrCanvasOrVideoElement element;
|
||||
element.SetAsHTMLCanvasElement() = this;
|
||||
nsCOMPtr<nsISupports> cxt;
|
||||
dest->GetContext(NS_LITERAL_STRING("2d"), JSVAL_VOID, getter_AddRefs(cxt));
|
||||
nsRefPtr<CanvasRenderingContext2D> context2d =
|
||||
static_cast<CanvasRenderingContext2D*>(cxt.get());
|
||||
if (context2d && !self->mPrintCallback) {
|
||||
HTMLImageOrCanvasOrVideoElement element;
|
||||
element.SetAsHTMLCanvasElement() = this;
|
||||
ErrorResult err;
|
||||
context2d->DrawImage(element,
|
||||
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, err);
|
||||
0.0, 0.0, err);
|
||||
rv = err.ErrorCode();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -172,7 +172,7 @@ RemoveFromAgentSheets(nsCOMArray<nsIStyleSheet> &aAgentSheets, const nsAString&
|
|||
}
|
||||
|
||||
nsresult
|
||||
NS_NewHTMLDocument(nsIDocument** aInstancePtrResult)
|
||||
NS_NewHTMLDocument(nsIDocument** aInstancePtrResult, bool aLoadedAsData)
|
||||
{
|
||||
nsHTMLDocument* doc = new nsHTMLDocument();
|
||||
NS_ENSURE_TRUE(doc, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
@ -185,6 +185,7 @@ NS_NewHTMLDocument(nsIDocument** aInstancePtrResult)
|
|||
}
|
||||
|
||||
*aInstancePtrResult = doc;
|
||||
doc->SetLoadedAsData(aLoadedAsData);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
@ -1515,11 +1516,9 @@ nsHTMLDocument::Open(const nsAString& aContentTypeOrUrl,
|
|||
nsCOMPtr<nsIScriptGlobalObject> newScope(do_QueryReferent(mScopeObject));
|
||||
if (oldScope && newScope != oldScope) {
|
||||
nsIXPConnect *xpc = nsContentUtils::XPConnect();
|
||||
nsCOMPtr<nsIXPConnectJSObjectHolder> ignored;
|
||||
rv = xpc->ReparentWrappedNativeIfFound(cx, oldScope->GetGlobalJSObject(),
|
||||
newScope->GetGlobalJSObject(),
|
||||
static_cast<nsINode*>(this),
|
||||
getter_AddRefs(ignored));
|
||||
static_cast<nsINode*>(this));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = xpc->RescueOrphansInScope(cx, oldScope->GetGlobalJSObject());
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
#include "prlog.h"
|
||||
#include "prmem.h"
|
||||
#include "prdtoa.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "AudioStream.h"
|
||||
#include "nsAlgorithm.h"
|
||||
#include "VideoUtils.h"
|
||||
|
@ -17,7 +16,6 @@
|
|||
extern "C" {
|
||||
#include "sydneyaudio/sydney_audio.h"
|
||||
}
|
||||
#include "nsThreadUtils.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
|
||||
#if defined(MOZ_CUBEB)
|
||||
|
@ -51,8 +49,6 @@ static const int64_t MS_PER_S = 1000;
|
|||
class nsNativeAudioStream : public AudioStream
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
~nsNativeAudioStream();
|
||||
nsNativeAudioStream();
|
||||
|
||||
|
@ -209,33 +205,8 @@ void AudioStream::ShutdownLibrary()
|
|||
#endif
|
||||
}
|
||||
|
||||
nsIThread *
|
||||
AudioStream::GetThread()
|
||||
{
|
||||
if (!mAudioPlaybackThread) {
|
||||
NS_NewNamedThread("Audio Stream",
|
||||
getter_AddRefs(mAudioPlaybackThread),
|
||||
nullptr,
|
||||
MEDIA_THREAD_STACK_SIZE);
|
||||
}
|
||||
return mAudioPlaybackThread;
|
||||
}
|
||||
|
||||
class AsyncShutdownPlaybackThread : public nsRunnable
|
||||
{
|
||||
public:
|
||||
AsyncShutdownPlaybackThread(nsIThread* aThread) : mThread(aThread) {}
|
||||
NS_IMETHODIMP Run() { return mThread->Shutdown(); }
|
||||
private:
|
||||
nsCOMPtr<nsIThread> mThread;
|
||||
};
|
||||
|
||||
AudioStream::~AudioStream()
|
||||
{
|
||||
if (mAudioPlaybackThread) {
|
||||
nsCOMPtr<nsIRunnable> event = new AsyncShutdownPlaybackThread(mAudioPlaybackThread);
|
||||
NS_DispatchToMainThread(event);
|
||||
}
|
||||
}
|
||||
|
||||
nsNativeAudioStream::nsNativeAudioStream() :
|
||||
|
@ -251,8 +222,6 @@ nsNativeAudioStream::~nsNativeAudioStream()
|
|||
Shutdown();
|
||||
}
|
||||
|
||||
NS_IMPL_THREADSAFE_ISUPPORTS0(nsNativeAudioStream)
|
||||
|
||||
nsresult nsNativeAudioStream::Init(int32_t aNumChannels, int32_t aRate,
|
||||
const dom::AudioChannelType aAudioChannelType)
|
||||
{
|
||||
|
@ -498,8 +467,6 @@ private:
|
|||
class nsBufferedAudioStream : public AudioStream
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
nsBufferedAudioStream();
|
||||
~nsBufferedAudioStream();
|
||||
|
||||
|
@ -598,8 +565,6 @@ nsBufferedAudioStream::~nsBufferedAudioStream()
|
|||
Shutdown();
|
||||
}
|
||||
|
||||
NS_IMPL_THREADSAFE_ISUPPORTS0(nsBufferedAudioStream)
|
||||
|
||||
nsresult
|
||||
nsBufferedAudioStream::Init(int32_t aNumChannels, int32_t aRate,
|
||||
const dom::AudioChannelType aAudioChannelType)
|
||||
|
|
|
@ -7,9 +7,6 @@
|
|||
#define AudioStream_h_
|
||||
|
||||
#include "nscore.h"
|
||||
#include "nsISupportsImpl.h"
|
||||
#include "nsIThread.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "AudioSampleFormat.h"
|
||||
#include "AudioChannelCommon.h"
|
||||
|
||||
|
@ -19,7 +16,7 @@ namespace mozilla {
|
|||
// callers, or made from a single thread. One exception is that access to
|
||||
// GetPosition, GetPositionInFrames, SetVolume, and Get{Rate,Channels}
|
||||
// is thread-safe without external synchronization.
|
||||
class AudioStream : public nsISupports
|
||||
class AudioStream
|
||||
{
|
||||
public:
|
||||
AudioStream()
|
||||
|
@ -37,10 +34,6 @@ public:
|
|||
// library after using it.
|
||||
static void ShutdownLibrary();
|
||||
|
||||
// Thread that is shared between audio streams.
|
||||
// This may return null in the child process
|
||||
nsIThread *GetThread();
|
||||
|
||||
// AllocateStream will return either a local stream or a remoted stream
|
||||
// depending on where you call it from. If you call this from a child process,
|
||||
// you may receive an implementation which forwards to a compositing process.
|
||||
|
@ -96,7 +89,6 @@ public:
|
|||
int GetChannels() { return mChannels; }
|
||||
|
||||
protected:
|
||||
nsCOMPtr<nsIThread> mAudioPlaybackThread;
|
||||
int mRate;
|
||||
int mChannels;
|
||||
};
|
||||
|
|
|
@ -611,7 +611,7 @@ private:
|
|||
// This is created and destroyed on the audio thread, while holding the
|
||||
// decoder monitor, so if this is used off the audio thread, you must
|
||||
// first acquire the decoder monitor and check that it is non-null.
|
||||
nsRefPtr<AudioStream> mAudioStream;
|
||||
nsAutoPtr<AudioStream> mAudioStream;
|
||||
|
||||
// The reader, don't call its methods with the decoder monitor held.
|
||||
// This is created in the play state machine's constructor, and destroyed
|
||||
|
|
|
@ -442,7 +442,7 @@ protected:
|
|||
// Amount of time that we've wanted to play silence because of the stream
|
||||
// blocking.
|
||||
MediaTime mBlockedAudioTime;
|
||||
nsRefPtr<AudioStream> mStream;
|
||||
nsAutoPtr<AudioStream> mStream;
|
||||
TrackID mTrackID;
|
||||
};
|
||||
nsTArray<AudioOutputStream> mAudioOutputStreams;
|
||||
|
|
|
@ -89,6 +89,11 @@ ssize_t MediaStreamSource::readAt(off64_t offset, void *data, size_t size)
|
|||
NS_FAILED(mResource->Read(ptr, todo, &bytesRead))) {
|
||||
return ERROR_IO;
|
||||
}
|
||||
|
||||
if (bytesRead == 0) {
|
||||
return size - todo;
|
||||
}
|
||||
|
||||
offset += bytesRead;
|
||||
todo -= bytesRead;
|
||||
ptr += bytesRead;
|
||||
|
|
|
@ -24,7 +24,7 @@ MediaPluginReader::MediaPluginReader(AbstractMediaDecoder *aDecoder) :
|
|||
mAudioSeekTimeUs(-1),
|
||||
mLastVideoFrame(NULL)
|
||||
{
|
||||
reinterpret_cast<MediaPluginDecoder *>(aDecoder)->GetContentType(mType);
|
||||
static_cast<MediaPluginDecoder *>(aDecoder)->GetContentType(mType);
|
||||
}
|
||||
|
||||
MediaPluginReader::~MediaPluginReader()
|
||||
|
|
|
@ -168,7 +168,7 @@ NS_NewDOMDocument(nsIDOMDocument** aInstancePtrResult,
|
|||
|
||||
|
||||
nsresult
|
||||
NS_NewXMLDocument(nsIDocument** aInstancePtrResult)
|
||||
NS_NewXMLDocument(nsIDocument** aInstancePtrResult, bool aLoadedAsData)
|
||||
{
|
||||
nsXMLDocument* doc = new nsXMLDocument();
|
||||
NS_ENSURE_TRUE(doc, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
@ -181,6 +181,7 @@ NS_NewXMLDocument(nsIDocument** aInstancePtrResult)
|
|||
}
|
||||
|
||||
*aInstancePtrResult = doc;
|
||||
doc->SetLoadedAsData(aLoadedAsData);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
|
|
@ -113,7 +113,8 @@ txMozillaTextOutput::startDocument()
|
|||
}
|
||||
|
||||
nsresult
|
||||
txMozillaTextOutput::createResultDocument(nsIDOMDocument* aSourceDocument)
|
||||
txMozillaTextOutput::createResultDocument(nsIDOMDocument* aSourceDocument,
|
||||
bool aLoadedAsData)
|
||||
{
|
||||
/*
|
||||
* Create an XHTML document to hold the text.
|
||||
|
@ -132,7 +133,8 @@ txMozillaTextOutput::createResultDocument(nsIDOMDocument* aSourceDocument)
|
|||
*/
|
||||
|
||||
// Create the document
|
||||
nsresult rv = NS_NewXMLDocument(getter_AddRefs(mDocument));
|
||||
nsresult rv = NS_NewXMLDocument(getter_AddRefs(mDocument),
|
||||
aLoadedAsData);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
nsCOMPtr<nsIDocument> source = do_QueryInterface(aSourceDocument);
|
||||
NS_ENSURE_STATE(source);
|
||||
|
|
|
@ -28,7 +28,8 @@ public:
|
|||
TX_DECL_TXAXMLEVENTHANDLER
|
||||
TX_DECL_TXAOUTPUTXMLEVENTHANDLER
|
||||
|
||||
nsresult createResultDocument(nsIDOMDocument* aSourceDocument);
|
||||
nsresult createResultDocument(nsIDOMDocument* aSourceDocument,
|
||||
bool aLoadedAsData);
|
||||
|
||||
private:
|
||||
nsresult createXHTMLElement(nsIAtom* aName, nsIContent** aResult);
|
||||
|
|
|
@ -791,19 +791,22 @@ void txMozillaXMLOutput::processHTTPEquiv(nsIAtom* aHeader, const nsString& aVal
|
|||
|
||||
nsresult
|
||||
txMozillaXMLOutput::createResultDocument(const nsSubstring& aName, int32_t aNsID,
|
||||
nsIDOMDocument* aSourceDocument)
|
||||
nsIDOMDocument* aSourceDocument,
|
||||
bool aLoadedAsData)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
// Create the document
|
||||
if (mOutputFormat.mMethod == eHTMLOutput) {
|
||||
rv = NS_NewHTMLDocument(getter_AddRefs(mDocument));
|
||||
rv = NS_NewHTMLDocument(getter_AddRefs(mDocument),
|
||||
aLoadedAsData);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
else {
|
||||
// We should check the root name/namespace here and create the
|
||||
// appropriate document
|
||||
rv = NS_NewXMLDocument(getter_AddRefs(mDocument));
|
||||
rv = NS_NewXMLDocument(getter_AddRefs(mDocument),
|
||||
aLoadedAsData);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
// This should really be handled by nsIDocument::BeginLoad
|
||||
|
|
|
@ -74,7 +74,8 @@ public:
|
|||
nsresult closePrevious(bool aFlushText);
|
||||
|
||||
nsresult createResultDocument(const nsSubstring& aName, int32_t aNsID,
|
||||
nsIDOMDocument* aSourceDocument);
|
||||
nsIDOMDocument* aSourceDocument,
|
||||
bool aLoadedAsData);
|
||||
|
||||
private:
|
||||
nsresult createTxWrapper();
|
||||
|
|
|
@ -48,8 +48,10 @@ class txToDocHandlerFactory : public txAOutputHandlerFactory
|
|||
public:
|
||||
txToDocHandlerFactory(txExecutionState* aEs,
|
||||
nsIDOMDocument* aSourceDocument,
|
||||
nsITransformObserver* aObserver)
|
||||
: mEs(aEs), mSourceDocument(aSourceDocument), mObserver(aObserver)
|
||||
nsITransformObserver* aObserver,
|
||||
bool aDocumentIsData)
|
||||
: mEs(aEs), mSourceDocument(aSourceDocument), mObserver(aObserver),
|
||||
mDocumentIsData(aDocumentIsData)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -59,6 +61,7 @@ private:
|
|||
txExecutionState* mEs;
|
||||
nsCOMPtr<nsIDOMDocument> mSourceDocument;
|
||||
nsCOMPtr<nsITransformObserver> mObserver;
|
||||
bool mDocumentIsData;
|
||||
};
|
||||
|
||||
class txToFragmentHandlerFactory : public txAOutputHandlerFactory
|
||||
|
@ -95,7 +98,8 @@ txToDocHandlerFactory::createHandlerWith(txOutputFormat* aFormat,
|
|||
|
||||
nsresult rv = handler->createResultDocument(EmptyString(),
|
||||
kNameSpaceID_None,
|
||||
mSourceDocument);
|
||||
mSourceDocument,
|
||||
mDocumentIsData);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
*aHandler = handler.forget();
|
||||
}
|
||||
|
@ -108,7 +112,8 @@ txToDocHandlerFactory::createHandlerWith(txOutputFormat* aFormat,
|
|||
nsAutoPtr<txMozillaTextOutput> handler(
|
||||
new txMozillaTextOutput(mObserver));
|
||||
|
||||
nsresult rv = handler->createResultDocument(mSourceDocument);
|
||||
nsresult rv = handler->createResultDocument(mSourceDocument,
|
||||
mDocumentIsData);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
*aHandler = handler.forget();
|
||||
}
|
||||
|
@ -143,7 +148,8 @@ txToDocHandlerFactory::createHandlerWith(txOutputFormat* aFormat,
|
|||
new txMozillaXMLOutput(aFormat, mObserver));
|
||||
|
||||
nsresult rv = handler->createResultDocument(aName, aNsID,
|
||||
mSourceDocument);
|
||||
mSourceDocument,
|
||||
mDocumentIsData);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
*aHandler = handler.forget();
|
||||
}
|
||||
|
@ -156,7 +162,8 @@ txToDocHandlerFactory::createHandlerWith(txOutputFormat* aFormat,
|
|||
nsAutoPtr<txMozillaTextOutput> handler(
|
||||
new txMozillaTextOutput(mObserver));
|
||||
|
||||
nsresult rv = handler->createResultDocument(mSourceDocument);
|
||||
nsresult rv = handler->createResultDocument(mSourceDocument,
|
||||
mDocumentIsData);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
*aHandler = handler.forget();
|
||||
}
|
||||
|
@ -522,7 +529,7 @@ public:
|
|||
|
||||
NS_IMETHOD Run()
|
||||
{
|
||||
mProcessor->TransformToDoc(nullptr);
|
||||
mProcessor->TransformToDoc(nullptr, false);
|
||||
return NS_OK;
|
||||
}
|
||||
};
|
||||
|
@ -612,11 +619,12 @@ txMozillaXSLTProcessor::TransformToDocument(nsIDOMNode *aSource,
|
|||
|
||||
mSource = aSource;
|
||||
|
||||
return TransformToDoc(aResult);
|
||||
return TransformToDoc(aResult, true);
|
||||
}
|
||||
|
||||
nsresult
|
||||
txMozillaXSLTProcessor::TransformToDoc(nsIDOMDocument **aResult)
|
||||
txMozillaXSLTProcessor::TransformToDoc(nsIDOMDocument **aResult,
|
||||
bool aCreateDataDocument)
|
||||
{
|
||||
nsAutoPtr<txXPathNode> sourceNode(txXPathNativeNode::createXPathNode(mSource));
|
||||
if (!sourceNode) {
|
||||
|
@ -633,7 +641,9 @@ txMozillaXSLTProcessor::TransformToDoc(nsIDOMDocument **aResult)
|
|||
|
||||
// XXX Need to add error observers
|
||||
|
||||
txToDocHandlerFactory handlerFactory(&es, sourceDOMDocument, mObserver);
|
||||
// If aResult is non-null, we're a data document
|
||||
txToDocHandlerFactory handlerFactory(&es, sourceDOMDocument, mObserver,
|
||||
aCreateDataDocument);
|
||||
es.mOutputHandlerFactory = &handlerFactory;
|
||||
|
||||
nsresult rv = es.init(*sourceNode, &mVariables);
|
||||
|
|
|
@ -96,7 +96,8 @@ public:
|
|||
return mSource;
|
||||
}
|
||||
|
||||
nsresult TransformToDoc(nsIDOMDocument **aResult);
|
||||
nsresult TransformToDoc(nsIDOMDocument **aResult,
|
||||
bool aCreateDataDocument);
|
||||
|
||||
bool IsLoadDisabled()
|
||||
{
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
SimpleTest.is(getDocShellType(typeContentFrame), Ci.nsIDocShellTreeItem.typeContent,
|
||||
"iframe with mozFrameType='content' in chrome document is typeContent");
|
||||
|
||||
SimpleTest.executeSoon(function () {
|
||||
// Wait for the window to be closed before finishing the test
|
||||
let ww = Components.classes["@mozilla.org/embedcomp/window-watcher;1"]
|
||||
.getService(Components.interfaces.nsIWindowWatcher);
|
||||
|
@ -39,15 +40,14 @@
|
|||
if (topic == "domwindowclosed") {
|
||||
ww.unregisterNotification(windowObs);
|
||||
|
||||
SimpleTest.executeSoon(function () {
|
||||
SimpleTest.waitForFocus(function() {
|
||||
SimpleTest.finish();
|
||||
}, opener);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
window.close();
|
||||
});
|
||||
}
|
||||
]]></script>
|
||||
</window>
|
||||
|
|
|
@ -30,8 +30,10 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=769771
|
|||
/** Test for Bug 769771 **/
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
addLoadEvent(function () {
|
||||
window.open("mozFrameType_window.xul", "mozFrameType",
|
||||
"chrome,width=600,height=600");
|
||||
});
|
||||
|
||||
]]>
|
||||
</script>
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include "nsContentUtils.h"
|
||||
#include "nsIDOMActivityOptions.h"
|
||||
#include "nsEventStateManager.h"
|
||||
#include "nsIConsoleService.h"
|
||||
|
||||
using namespace mozilla::dom;
|
||||
|
||||
|
@ -52,11 +53,23 @@ Activity::Initialize(nsISupports* aOwner,
|
|||
|
||||
Init(window);
|
||||
|
||||
if (!nsEventStateManager::IsHandlingUserInput()) {
|
||||
nsCOMPtr<nsIDocument> document = do_QueryInterface(window->GetExtantDocument());
|
||||
|
||||
if (!nsEventStateManager::IsHandlingUserInput() &&
|
||||
!nsContentUtils::IsChromeDoc(document)) {
|
||||
nsCOMPtr<nsIDOMRequestService> rs =
|
||||
do_GetService("@mozilla.org/dom/dom-request-service;1");
|
||||
rs->FireErrorAsync(static_cast<DOMRequest*>(this),
|
||||
NS_LITERAL_STRING("NotUserInput"));
|
||||
|
||||
nsCOMPtr<nsIConsoleService> console(
|
||||
do_GetService("@mozilla.org/consoleservice;1"));
|
||||
NS_ENSURE_TRUE(console, NS_OK);
|
||||
|
||||
nsString message =
|
||||
NS_LITERAL_STRING("Can start activity from non user input or chrome code");
|
||||
console->LogStringMessage(message.get());
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -757,7 +757,8 @@ static nsDOMClassInfoData sClassInfoData[] = {
|
|||
WINDOW_SCRIPTABLE_FLAGS)
|
||||
|
||||
NS_DEFINE_CLASSINFO_DATA(Location, nsLocationSH,
|
||||
(DOM_DEFAULT_SCRIPTABLE_FLAGS &
|
||||
((DOM_DEFAULT_SCRIPTABLE_FLAGS |
|
||||
nsIXPCScriptable::WANT_ADDPROPERTY) &
|
||||
~nsIXPCScriptable::ALLOW_PROP_MODS_TO_PROTOTYPE))
|
||||
|
||||
NS_DEFINE_CLASSINFO_DATA(Navigator, nsNavigatorSH,
|
||||
|
@ -7610,6 +7611,20 @@ nsLocationSH::PreCreate(nsISupports *nativeObj, JSContext *cx,
|
|||
return *parentObj ? NS_OK : NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsLocationSH::AddProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
|
||||
JSObject *obj, jsid id, jsval *vp, bool *_retval)
|
||||
{
|
||||
// Shadowing protection. This will go away when nsLocation moves to the new
|
||||
// bindings.
|
||||
if (wrapper->HasNativeMember(id)) {
|
||||
JS_ReportError(cx, "Permission denied to shadow native property");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// DOM Navigator helper
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
|
|
@ -454,6 +454,8 @@ public:
|
|||
|
||||
NS_IMETHOD PreCreate(nsISupports *nativeObj, JSContext *cx,
|
||||
JSObject *globalObj, JSObject **parentObj);
|
||||
NS_IMETHODIMP AddProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
|
||||
JSObject *obj, jsid id, jsval *vp, bool *_retval);
|
||||
|
||||
static nsIClassInfo *doCreate(nsDOMClassInfoData* aData)
|
||||
{
|
||||
|
|
|
@ -402,6 +402,54 @@ nsDOMWindowUtils::SetDisplayPortForElement(float aXPx, float aYPx,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWindowUtils::SetCriticalDisplayPortForElement(float aXPx, float aYPx,
|
||||
float aWidthPx, float aHeightPx,
|
||||
nsIDOMElement* aElement)
|
||||
{
|
||||
if (!nsContentUtils::IsCallerChrome()) {
|
||||
return NS_ERROR_DOM_SECURITY_ERR;
|
||||
}
|
||||
|
||||
nsIPresShell* presShell = GetPresShell();
|
||||
if (!presShell) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
if (!aElement) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIContent> content = do_QueryInterface(aElement);
|
||||
|
||||
if (!content) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
if (content->GetCurrentDoc() != presShell->GetDocument()) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
nsRect displayport;
|
||||
if (!nsLayoutUtils::GetDisplayPort(content, &displayport)) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
nsRect criticalDisplayport(nsPresContext::CSSPixelsToAppUnits(aXPx),
|
||||
nsPresContext::CSSPixelsToAppUnits(aYPx),
|
||||
nsPresContext::CSSPixelsToAppUnits(aWidthPx),
|
||||
nsPresContext::CSSPixelsToAppUnits(aHeightPx));
|
||||
content->SetProperty(nsGkAtoms::CriticalDisplayPort, new nsRect(criticalDisplayport),
|
||||
DestroyNsRect);
|
||||
|
||||
nsIFrame* rootFrame = presShell->GetRootFrame();
|
||||
if (rootFrame) {
|
||||
rootFrame->InvalidateFrame();
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWindowUtils::SetResolution(float aXResolution, float aYResolution)
|
||||
{
|
||||
|
|
|
@ -148,6 +148,18 @@ interface nsIDOMWindowUtils : nsISupports {
|
|||
in float aWidthPx, in float aHeightPx,
|
||||
in nsIDOMElement aElement);
|
||||
|
||||
/**
|
||||
* When a display port is set, this allows a sub-section of that
|
||||
* display port to be marked as 'critical'. In this scenario, the
|
||||
* area outside of this rectangle may be rendered at a lower
|
||||
* detail (for example, by reducing its resolution), or not rendered
|
||||
* at all under some circumstances.
|
||||
* This call will have no effect if a display port has not been set.
|
||||
*/
|
||||
void setCriticalDisplayPortForElement(in float aXPx, in float aYPx,
|
||||
in float aWidthPx, in float aHeightPx,
|
||||
in nsIDOMElement aElement);
|
||||
|
||||
/**
|
||||
* Get/set the resolution at which rescalable web content is drawn.
|
||||
* Currently this is only (some) thebes content.
|
||||
|
|
|
@ -2037,7 +2037,7 @@ this.ContentTypeValue = {
|
|||
*/
|
||||
encodeConstrainedMedia: function encodeConstrainedMedia(data, value) {
|
||||
if (value.params) {
|
||||
throw new CodeError("Constrained-media: should use general form instread");
|
||||
throw new CodeError("Constrained-media: should use general form instead");
|
||||
}
|
||||
|
||||
TypeValue.encode(data, value.media);
|
||||
|
@ -2475,7 +2475,7 @@ this.WSP_HEADER_FIELDS = (function () {
|
|||
})();
|
||||
|
||||
// WSP Content Type Assignments
|
||||
// @see http://www.wapforum.org/wina
|
||||
// @see http://www.openmobilealliance.org/tech/omna/omna-wsp-content-type.aspx
|
||||
this.WSP_WELL_KNOWN_CONTENT_TYPES = (function () {
|
||||
let types = {};
|
||||
|
||||
|
@ -2484,18 +2484,115 @@ this.WSP_WELL_KNOWN_CONTENT_TYPES = (function () {
|
|||
type: type,
|
||||
number: number,
|
||||
};
|
||||
types[type] = types[number] = entry;
|
||||
// For case like "text/x-vCalendar", we need toLoweCase() for generating
|
||||
// the same index.
|
||||
types[type.toLowerCase()] = types[number] = entry;
|
||||
}
|
||||
|
||||
// Well Known Values
|
||||
// Encoding Version: 1.1
|
||||
add("*/*", 0x00);
|
||||
add("text/*", 0x01);
|
||||
add("text/html", 0x02);
|
||||
add("text/plain", 0x03);
|
||||
add("text/x-hdml", 0x04);
|
||||
add("text/x-ttml", 0x05);
|
||||
add("text/x-vCalendar", 0x06);
|
||||
add("text/x-vCard", 0x07);
|
||||
add("text/vnd.wap.wml", 0x08);
|
||||
add("text/vnd.wap.wmlscript", 0x09);
|
||||
add("text/vnd.wap.wta-event", 0x0A);
|
||||
add("multipart/*", 0x0B);
|
||||
add("multipart/mixed", 0x0C);
|
||||
add("multipart/form-data", 0x0D);
|
||||
add("multipart/byterantes", 0x0E);
|
||||
add("multipart/alternative", 0x0F);
|
||||
add("application/*", 0x10);
|
||||
add("application/java-vm", 0x11);
|
||||
add("application/x-www-form-urlencoded", 0x12);
|
||||
add("application/x-hdmlc", 0x13);
|
||||
add("application/vnd.wap.wmlc", 0x14);
|
||||
add("application/vnd.wap.wmlscriptc", 0x15);
|
||||
add("application/vnd.wap.wta-eventc", 0x16);
|
||||
add("application/vnd.wap.uaprof", 0x17);
|
||||
add("application/vnd.wap.wtls-ca-certificate", 0x18);
|
||||
add("application/vnd.wap.wtls-user-certificate", 0x19);
|
||||
add("application/x-x509-ca-cert", 0x1A);
|
||||
add("application/x-x509-user-cert", 0x1B);
|
||||
add("image/*", 0x1C);
|
||||
add("image/gif", 0x1D);
|
||||
add("image/jpeg", 0x1E);
|
||||
add("image/tiff", 0x1F);
|
||||
add("image/png", 0x20);
|
||||
add("image/vnd.wap.wbmp", 0x21);
|
||||
add("application/vnd.wap.multipart.*", 0x22);
|
||||
add("application/vnd.wap.multipart.mixed", 0x23);
|
||||
add("application/vnd.wap.multipart.form-data", 0x24);
|
||||
add("application/vnd.wap.multipart.byteranges", 0x25);
|
||||
add("application/vnd.wap.multipart.alternative", 0x26);
|
||||
add("application/xml", 0x27);
|
||||
add("text/xml", 0x28);
|
||||
add("application/vnd.wap.wbxml", 0x29);
|
||||
add("application/x-x968-cross-cert", 0x2A);
|
||||
add("application/x-x968-ca-cert", 0x2B);
|
||||
add("application/x-x968-user-cert", 0x2C);
|
||||
add("text/vnd.wap.si", 0x2D);
|
||||
|
||||
// Encoding Version: 1.2
|
||||
add("application/vnd.wap.sic", 0x2E);
|
||||
add("text/vnd.wap.sl", 0x2F);
|
||||
add("application/vnd.wap.slc", 0x30);
|
||||
add("text/vnd.wap.co", 0x31);
|
||||
add("application/vnd.wap.coc", 0x32);
|
||||
add("application/vnd.wap.multipart.related", 0x33);
|
||||
add("application/vnd.wap.sia", 0x34);
|
||||
|
||||
// Encoding Version: 1.3
|
||||
add("text/vnd.wap.connectivity-xml", 0x35);
|
||||
add("application/vnd.wap.connectivity-wbxml", 0x36);
|
||||
|
||||
// Encoding Version: 1.4
|
||||
add("application/pkcs7-mime", 0x37);
|
||||
add("application/vnd.wap.hashed-certificate", 0x38);
|
||||
add("application/vnd.wap.signed-certificate", 0x39);
|
||||
add("application/vnd.wap.cert-response", 0x3A);
|
||||
add("application/xhtml+xml", 0x3B);
|
||||
add("application/wml+xml", 0x3C);
|
||||
add("text/css", 0x3D);
|
||||
add("application/vnd.wap.mms-message", 0x3E);
|
||||
add("application/vnd.wap.rollover-certificate", 0x3F);
|
||||
|
||||
// Encoding Version: 1.5
|
||||
add("application/vnd.wap.locc+wbxml", 0x40);
|
||||
add("application/vnd.wap.loc+xml", 0x41);
|
||||
add("application/vnd.syncml.dm+wbxml", 0x42);
|
||||
add("application/vnd.syncml.dm+xml", 0x43);
|
||||
add("application/vnd.syncml.notification", 0x44);
|
||||
add("application/vnd.wap.xhtml+xml", 0x45);
|
||||
add("application/vnd.wv.csp.cir", 0x46);
|
||||
add("application/vnd.oma.dd+xml", 0x47);
|
||||
add("application/vnd.oma.drm.message", 0x48);
|
||||
add("application/vnd.oma.drm.content", 0x49);
|
||||
add("application/vnd.oma.drm.rights+xml", 0x4A);
|
||||
add("application/vnd.oma.drm.rights+wbxml", 0x4B);
|
||||
add("application/vnd.wv.csp+xml", 0x4C);
|
||||
add("application/vnd.wv.csp+wbxml", 0x4D);
|
||||
add("application/vnd.syncml.ds.notification", 0x4E);
|
||||
|
||||
// Encoding Version: 1.6
|
||||
add("audio/*", 0x4F);
|
||||
add("video/*", 0x50);
|
||||
|
||||
// Encoding Version: TBD
|
||||
add("application/vnd.oma.dd2+xml", 0x51);
|
||||
add("application/mikey", 0x52);
|
||||
add("application/vnd.oma.dcd", 0x53);
|
||||
add("application/vnd.oma.dcdc", 0x54);
|
||||
add("text/x-vMessage", 0x55);
|
||||
add("application/vnd.omads-email+wbxml", 0x56);
|
||||
add("text/x-vBookmark", 0x57);
|
||||
add("application/vnd.syncml.dm.notification", 0x58);
|
||||
add("application/octet-stream", 0x5A);
|
||||
|
||||
return types;
|
||||
})();
|
||||
|
|
|
@ -718,7 +718,7 @@ add_test(function test_TypeValue_decode() {
|
|||
wsp_decode_test(WSP.TypeValue, [0x33 | 0x80],
|
||||
"application/vnd.wap.multipart.related");
|
||||
// Test for NotWellKnownEncodingError
|
||||
wsp_decode_test(WSP.TypeValue, [0x80], null, "NotWellKnownEncodingError");
|
||||
wsp_decode_test(WSP.TypeValue, [0x59 | 0x80], null, "NotWellKnownEncodingError");
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
|
@ -1046,10 +1046,12 @@ add_test(function test_ContentTypeValue_decodeConstrainedMedia() {
|
|||
// Test for string-typed return value from ConstrainedEncoding
|
||||
wsp_decode_test_ex(func, [65, 0], {media: "a", params: null});
|
||||
// Test for number-typed return value from ConstrainedEncoding
|
||||
wsp_decode_test_ex(func, [0x33 | 0x80],
|
||||
{media: "application/vnd.wap.multipart.related", params: null});
|
||||
for(let ix = 0; ix <WSP.WSP_WELL_KNOWN_CONTENT_TYPES.length ; ++ix){
|
||||
wsp_decode_test_ex(func, [WSP.WSP_WELL_KNOWN_CONTENT_TYPES[ix].number | 0x80],
|
||||
{media: WSP.WSP_WELL_KNOWN_CONTENT_TYPES[ix].value, params: null});
|
||||
}
|
||||
// Test for NotWellKnownEncodingError
|
||||
wsp_decode_test_ex(func, [0x80], null, "NotWellKnownEncodingError");
|
||||
wsp_decode_test_ex(func, [0x59 | 0x80], null, "NotWellKnownEncodingError");
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
|
@ -1065,7 +1067,7 @@ add_test(function test_ContentTypeValue_decodeMedia() {
|
|||
wsp_decode_test_ex(func, [65, 0], "a");
|
||||
// Test for IntegerValue
|
||||
wsp_decode_test_ex(func, [0x3E | 0x80], "application/vnd.wap.mms-message");
|
||||
wsp_decode_test_ex(func, [0x80], null, "NotWellKnownEncodingError");
|
||||
wsp_decode_test_ex(func, [0x59 | 0x80], null, "NotWellKnownEncodingError");
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
|
@ -1126,8 +1128,12 @@ add_test(function test_ContentTypeValue_encodeConstrainedMedia() {
|
|||
wsp_encode_test_ex(func, {media: "a", params: [{a: "b"}]}, null, "CodeError");
|
||||
wsp_encode_test_ex(func, {media: "no/such.type"},
|
||||
[110, 111, 47, 115, 117, 99, 104, 46, 116, 121, 112, 101, 0]);
|
||||
wsp_encode_test_ex(func, {media: "application/vnd.wap.multipart.related"},
|
||||
[0x33 | 0x80]);
|
||||
for(let ix = 0; ix <WSP.WSP_WELL_KNOWN_CONTENT_TYPES.length ; ++ix){
|
||||
wsp_encode_test_ex(func, {media: WSP.WSP_WELL_KNOWN_CONTENT_TYPES[ix].value},
|
||||
[WSP.WSP_WELL_KNOWN_CONTENT_TYPES[ix].number | 0x80]);
|
||||
}
|
||||
wsp_encode_test_ex(func, {media: "TexT/X-hdml"}, [0x04 | 0x80]);
|
||||
wsp_encode_test_ex(func, {media: "appLication/*"}, [0x10 | 0x80]);
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
function runTest() {
|
||||
"use strict";
|
||||
var p1 = document.getElementById("plugin1");
|
||||
var realOrigin = "http://mochi.test:8888";
|
||||
|
||||
|
|
|
@ -43,15 +43,7 @@ nsDOMDesktopNotification::PostDesktopNotification()
|
|||
|
||||
DOMCI_DATA(DesktopNotification, nsDOMDesktopNotification)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_CLASS(nsDOMDesktopNotification)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsDOMDesktopNotification, nsDOMEventTargetHelper)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsDOMDesktopNotification, nsDOMEventTargetHelper)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(nsDOMDesktopNotification)
|
||||
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMDesktopNotification)
|
||||
NS_INTERFACE_MAP_BEGIN(nsDOMDesktopNotification)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIDOMDesktopNotification)
|
||||
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(DesktopNotification)
|
||||
NS_INTERFACE_MAP_END_INHERITING(nsDOMEventTargetHelper)
|
||||
|
|
|
@ -72,7 +72,6 @@ class nsDOMDesktopNotification : public nsDOMEventTargetHelper,
|
|||
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsDOMDesktopNotification,nsDOMEventTargetHelper)
|
||||
NS_DECL_NSIDOMDESKTOPNOTIFICATION
|
||||
|
||||
nsDOMDesktopNotification(const nsAString & title,
|
||||
|
|
|
@ -3,63 +3,37 @@ b2g = true
|
|||
browser = false
|
||||
qemu = true
|
||||
|
||||
[test_crash_emulator.js]
|
||||
[test_incoming_answer_hangup.js]
|
||||
disabled = Bug 790463
|
||||
[test_incoming_reject.js]
|
||||
disabled = Bug 811167
|
||||
[test_outgoing_answer_hangup.js]
|
||||
disabled = Bug 811167
|
||||
[test_incoming_answer_hangup_oncallschanged.js]
|
||||
disabled = Bug 811167
|
||||
[test_outgoing_answer_hangup_oncallschanged.js]
|
||||
disabled = Bug 811167
|
||||
[test_outgoing_hangup_alerting.js]
|
||||
disabled = Bug 811167
|
||||
[test_outgoing_hangup_held.js]
|
||||
disabled = Bug 811167
|
||||
[test_outgoing_badNumber.js]
|
||||
disabled = Bug 761533
|
||||
[test_outgoing_busy.js]
|
||||
disabled = Bug 761533
|
||||
[test_outgoing_reject.js]
|
||||
disabled = Bug 811167
|
||||
[test_voicemail_statuschanged.py]
|
||||
disabled = Bug 806138
|
||||
[test_voicemail_number.js]
|
||||
disabled = Bug 811167
|
||||
[test_incoming_hold_resume.js]
|
||||
disabled = Bug 811167
|
||||
[test_outgoing_hold_resume.js]
|
||||
disabled = Bug 790463
|
||||
[test_incoming_already_connected.js]
|
||||
disabled = Bug 790463
|
||||
[test_incoming_answer_remote_hangup.js]
|
||||
disabled = Bug 811167
|
||||
[test_incoming_connecting_hangup.js]
|
||||
disabled = Bug 811167
|
||||
[test_incoming_connecting_remote_hangup.js]
|
||||
disabled = Bug 811167
|
||||
[test_incoming_hangup_held.js]
|
||||
disabled = Bug 790463
|
||||
[test_incoming_remote_cancel.js]
|
||||
disabled = Bug 811167
|
||||
[test_incoming_remote_hangup_held.js]
|
||||
disabled = Bug 811167
|
||||
[test_outgoing_already_held.js]
|
||||
disabled = Bug 790463
|
||||
[test_outgoing_answer_local_hangup.js]
|
||||
disabled = Bug 790463
|
||||
[test_outgoing_remote_hangup_held.js]
|
||||
disabled = Bug 790463
|
||||
[test_incoming_already_held.js]
|
||||
disabled = Bug 790463
|
||||
[test_swap_held_and_active.js]
|
||||
disabled = Bug 790463
|
||||
[test_incoming_onstatechange.js]
|
||||
disabled = Bug 811167
|
||||
[test_outgoing_onstatechange.js]
|
||||
disabled = Bug 811167
|
||||
[test_redundant_operations.js]
|
||||
disabled = Bug 811167
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
MARIONETTE_TIMEOUT = 10000;
|
||||
|
||||
SpecialPowers.addPermission("telephony", true, document);
|
||||
|
||||
let telephony = window.navigator.mozTelephony;
|
||||
let outNumber = "5555551111";
|
||||
let outgoingCall;
|
||||
|
||||
function dial() {
|
||||
log("Make an outgoing call.");
|
||||
outgoingCall = telephony.dial(outNumber);
|
||||
|
||||
outgoingCall.onalerting = function onalerting(event) {
|
||||
log("Received 'alerting' call event.");
|
||||
answer();
|
||||
};
|
||||
}
|
||||
|
||||
function answer() {
|
||||
log("Answering the outgoing call.");
|
||||
|
||||
outgoingCall.onconnected = function onconnectedOut(event) {
|
||||
log("Received 'connected' call event for the original outgoing call.");
|
||||
// just some code to keep call active for awhile
|
||||
callStartTime = Date.now();
|
||||
waitFor(cleanUp,function() {
|
||||
callDuration = Date.now() - callStartTime;
|
||||
log("Waiting while call is active, call duration (ms): " + callDuration);
|
||||
return(callDuration >= 2000);
|
||||
});
|
||||
};
|
||||
runEmulatorCmd("gsm accept " + outNumber);
|
||||
}
|
||||
|
||||
function cleanUp(){
|
||||
outgoingCall.hangUp();
|
||||
ok("passed");
|
||||
finish();
|
||||
}
|
||||
|
||||
dial();
|
|
@ -80,19 +80,6 @@ try {
|
|||
} catch (e) {
|
||||
}
|
||||
|
||||
// Make sure watch works correctly.
|
||||
var watchTest = {a: 42};
|
||||
var watchHandler = function(prop, oldval, newval) { return 22; }
|
||||
Object.prototype.watch.call(watchTest, 'a', watchHandler);
|
||||
watchTest.a = 1;
|
||||
is(watchTest.a, 22, "Watch works correctly");
|
||||
|
||||
// Now make sure we can't watch location.
|
||||
try {
|
||||
Object.prototype.watch.call(location, 'href', function(prop, oldval, newval) {});
|
||||
ok(false, "shouldn't be able to set a watchpoint on location");
|
||||
} catch (e) {}
|
||||
|
||||
ok(window === orig, "can't override window");
|
||||
ok(window.location === origLocation, "properties are properly aliased");
|
||||
ok(document.location === origLocation, "properties are properly aliased");
|
||||
|
|
|
@ -33,6 +33,7 @@ public:
|
|||
: mCompositionBounds(0, 0, 0, 0)
|
||||
, mContentRect(0, 0, 0, 0)
|
||||
, mDisplayPort(0, 0, 0, 0)
|
||||
, mCriticalDisplayPort(0, 0, 0, 0)
|
||||
, mViewport(0, 0, 0, 0)
|
||||
, mScrollOffset(0, 0)
|
||||
, mScrollId(NULL_SCROLL_ID)
|
||||
|
@ -50,6 +51,7 @@ public:
|
|||
return mCompositionBounds.IsEqualEdges(aOther.mCompositionBounds) &&
|
||||
mContentRect.IsEqualEdges(aOther.mContentRect) &&
|
||||
mDisplayPort.IsEqualEdges(aOther.mDisplayPort) &&
|
||||
mCriticalDisplayPort.IsEqualEdges(aOther.mCriticalDisplayPort) &&
|
||||
mViewport.IsEqualEdges(aOther.mViewport) &&
|
||||
mScrollOffset == aOther.mScrollOffset &&
|
||||
mScrollId == aOther.mScrollId &&
|
||||
|
@ -149,6 +151,14 @@ public:
|
|||
// displayport set on them. See bug 775452.
|
||||
gfx::Rect mDisplayPort;
|
||||
|
||||
// If non-empty, the area of a frame's contents that is considered critical
|
||||
// to paint. Area outside of this area (i.e. area inside mDisplayPort, but
|
||||
// outside of mCriticalDisplayPort) is considered low-priority, and may be
|
||||
// painted with lower precision, or not painted at all.
|
||||
//
|
||||
// The same restrictions for mDisplayPort apply here.
|
||||
gfx::Rect mCriticalDisplayPort;
|
||||
|
||||
// The CSS viewport, which is the dimensions we're using to constrain the
|
||||
// <html> element of this frame, relative to the top-left of the layer. Note
|
||||
// that its offset is structured in such a way that it doesn't depend on the
|
||||
|
|
|
@ -29,7 +29,9 @@ namespace layers {
|
|||
// template pattern.
|
||||
//
|
||||
// Tiles are aligned to a grid with one of the grid points at (0,0) and other
|
||||
// grid points spaced evenly in the x- and y-directions by GetTileLength().
|
||||
// grid points spaced evenly in the x- and y-directions by GetTileLength()
|
||||
// multiplied by mResolution. GetScaledTileLength() provides convenience for
|
||||
// accessing these values.
|
||||
//
|
||||
// This tile buffer stores a valid region, which defines the areas that have
|
||||
// up-to-date content. The contents of tiles within this region will be reused
|
||||
|
@ -66,6 +68,11 @@ namespace layers {
|
|||
// void SwapTiles(Tile& aTileA, Tile& aTileB);
|
||||
//
|
||||
// Swaps two tiles.
|
||||
//
|
||||
// The contents of the tile buffer will be rendered at the resolution specified
|
||||
// in mResolution, which can be altered with SetResolution. The resolution
|
||||
// should always be a factor of the tile length, to avoid tiles covering
|
||||
// non-integer amounts of pixels.
|
||||
|
||||
template<typename Derived, typename Tile>
|
||||
class TiledLayerBuffer
|
||||
|
@ -74,20 +81,23 @@ public:
|
|||
TiledLayerBuffer()
|
||||
: mRetainedWidth(0)
|
||||
, mRetainedHeight(0)
|
||||
, mResolution(1)
|
||||
{}
|
||||
|
||||
~TiledLayerBuffer() {}
|
||||
|
||||
// Given a tile origin aligned to a multiple of GetTileLength(),
|
||||
// Given a tile origin aligned to a multiple of GetScaledTileLength,
|
||||
// return the tile that describes that region.
|
||||
// NOTE: To get the valid area of that tile you must intersect
|
||||
// (aTileOrigin.x, aTileOrigin.y, GetTileLength(), GetTileLength())
|
||||
// (aTileOrigin.x, aTileOrigin.y,
|
||||
// GetScaledTileLength(), GetScaledTileLength())
|
||||
// and GetValidRegion() to get the area of the tile that is valid.
|
||||
Tile GetTile(const nsIntPoint& aTileOrigin) const;
|
||||
|
||||
// Given a tile x, y relative to the top left of the layer, this function
|
||||
// will return the tile for
|
||||
// (x*GetTileLength(), y*GetTileLength(), GetTileLength(), GetTileLength())
|
||||
// (x*GetScaledTileLength(), y*GetScaledTileLength(),
|
||||
// GetScaledTileLength(), GetScaledTileLength())
|
||||
Tile GetTile(int x, int y) const;
|
||||
|
||||
// This operates the same as GetTile(aTileOrigin), but will also replace the
|
||||
|
@ -101,6 +111,7 @@ public:
|
|||
bool RemoveTile(int x, int y, Tile& aRemovedTile);
|
||||
|
||||
uint16_t GetTileLength() const { return TILEDLAYERBUFFER_TILE_SIZE; }
|
||||
uint32_t GetScaledTileLength() const { return TILEDLAYERBUFFER_TILE_SIZE / mResolution; }
|
||||
|
||||
unsigned int GetTileCount() const { return mRetainedTiles.Length(); }
|
||||
|
||||
|
@ -110,13 +121,30 @@ public:
|
|||
|
||||
// Given a position i, this function returns the position inside the current tile.
|
||||
int GetTileStart(int i) const {
|
||||
return (i >= 0) ? (i % GetTileLength())
|
||||
: ((GetTileLength() - (-i % GetTileLength())) % GetTileLength());
|
||||
return (i >= 0) ? (i % GetScaledTileLength())
|
||||
: ((GetScaledTileLength() - (-i % GetScaledTileLength())) %
|
||||
GetScaledTileLength());
|
||||
}
|
||||
|
||||
// Rounds the given coordinate down to the nearest tile boundary.
|
||||
int RoundDownToTileEdge(int aX) const { return aX - GetTileStart(aX); }
|
||||
|
||||
// Get and set draw scaling. mResolution affects the resolution at which the
|
||||
// contents of the buffer are drawn. mResolution has no effect on the
|
||||
// coordinate space of the valid region, but does affect the size of an
|
||||
// individual tile's rect in relation to the valid region.
|
||||
// Setting the resolution will invalidate the buffer.
|
||||
float GetResolution() const { return mResolution; }
|
||||
void SetResolution(float aResolution) {
|
||||
if (mResolution == aResolution) {
|
||||
return;
|
||||
}
|
||||
|
||||
Update(nsIntRegion(), nsIntRegion());
|
||||
mResolution = aResolution;
|
||||
}
|
||||
bool IsLowPrecision() const { return mResolution < 1; }
|
||||
|
||||
protected:
|
||||
// The implementor should call Update() to change
|
||||
// the new valid region. This implementation will call
|
||||
|
@ -132,11 +160,13 @@ protected:
|
|||
* stored as column major with the same origin as mValidRegion.GetBounds().
|
||||
* Any tile that does not intersect mValidRegion is a PlaceholderTile.
|
||||
* Only the region intersecting with mValidRegion should be read from a tile,
|
||||
* another other region is assumed to be uninitialized.
|
||||
* another other region is assumed to be uninitialized. The contents of the
|
||||
* tiles is scaled by mResolution.
|
||||
*/
|
||||
nsTArray<Tile> mRetainedTiles;
|
||||
int mRetainedWidth; // in tiles
|
||||
int mRetainedHeight; // in tiles
|
||||
float mResolution;
|
||||
|
||||
private:
|
||||
const Derived& AsDerived() const { return *static_cast<const Derived*>(this); }
|
||||
|
@ -187,10 +217,10 @@ TiledLayerBuffer<Derived, Tile>::GetTile(const nsIntPoint& aTileOrigin) const
|
|||
// TODO Cache firstTileOriginX/firstTileOriginY
|
||||
// Find the tile x/y of the first tile and the target tile relative to the (0, 0)
|
||||
// origin, the difference is the tile x/y relative to the start of the tile buffer.
|
||||
int firstTileX = floor_div(mValidRegion.GetBounds().x, GetTileLength());
|
||||
int firstTileY = floor_div(mValidRegion.GetBounds().y, GetTileLength());
|
||||
return GetTile(floor_div(aTileOrigin.x, GetTileLength()) - firstTileX,
|
||||
floor_div(aTileOrigin.y, GetTileLength()) - firstTileY);
|
||||
int firstTileX = floor_div(mValidRegion.GetBounds().x, GetScaledTileLength());
|
||||
int firstTileY = floor_div(mValidRegion.GetBounds().y, GetScaledTileLength());
|
||||
return GetTile(floor_div(aTileOrigin.x, GetScaledTileLength()) - firstTileX,
|
||||
floor_div(aTileOrigin.y, GetScaledTileLength()) - firstTileY);
|
||||
}
|
||||
|
||||
template<typename Derived, typename Tile> Tile
|
||||
|
@ -204,10 +234,10 @@ template<typename Derived, typename Tile> bool
|
|||
TiledLayerBuffer<Derived, Tile>::RemoveTile(const nsIntPoint& aTileOrigin,
|
||||
Tile& aRemovedTile)
|
||||
{
|
||||
int firstTileX = floor_div(mValidRegion.GetBounds().x, GetTileLength());
|
||||
int firstTileY = floor_div(mValidRegion.GetBounds().y, GetTileLength());
|
||||
return RemoveTile(floor_div(aTileOrigin.x, GetTileLength()) - firstTileX,
|
||||
floor_div(aTileOrigin.y, GetTileLength()) - firstTileY,
|
||||
int firstTileX = floor_div(mValidRegion.GetBounds().x, GetScaledTileLength());
|
||||
int firstTileY = floor_div(mValidRegion.GetBounds().y, GetScaledTileLength());
|
||||
return RemoveTile(floor_div(aTileOrigin.x, GetScaledTileLength()) - firstTileX,
|
||||
floor_div(aTileOrigin.y, GetScaledTileLength()) - firstTileY,
|
||||
aRemovedTile);
|
||||
}
|
||||
|
||||
|
@ -251,14 +281,14 @@ TiledLayerBuffer<Derived, Tile>::Update(const nsIntRegion& aNewValidRegion,
|
|||
for (int32_t x = newBound.x; x < newBound.XMost(); tileX++) {
|
||||
// Compute tileRect(x,y,width,height) in layer space coordinate
|
||||
// giving us the rect of the tile that hits the newBounds.
|
||||
int width = GetTileLength() - GetTileStart(x);
|
||||
int width = GetScaledTileLength() - GetTileStart(x);
|
||||
if (x + width > newBound.XMost()) {
|
||||
width = newBound.x + newBound.width - x;
|
||||
}
|
||||
|
||||
tileY = 0;
|
||||
for (int32_t y = newBound.y; y < newBound.YMost(); tileY++) {
|
||||
int height = GetTileLength() - GetTileStart(y);
|
||||
int height = GetScaledTileLength() - GetTileStart(y);
|
||||
if (y + height > newBound.y + newBound.height) {
|
||||
height = newBound.y + newBound.height - y;
|
||||
}
|
||||
|
@ -268,8 +298,8 @@ TiledLayerBuffer<Derived, Tile>::Update(const nsIntRegion& aNewValidRegion,
|
|||
// This old tiles contains some valid area so move it to the new tile
|
||||
// buffer. Replace the tile in the old buffer with a placeholder
|
||||
// to leave the old buffer index unaffected.
|
||||
int tileX = floor_div(x - oldBufferOrigin.x, GetTileLength());
|
||||
int tileY = floor_div(y - oldBufferOrigin.y, GetTileLength());
|
||||
int tileX = floor_div(x - oldBufferOrigin.x, GetScaledTileLength());
|
||||
int tileY = floor_div(y - oldBufferOrigin.y, GetScaledTileLength());
|
||||
int index = tileX * oldRetainedHeight + tileY;
|
||||
|
||||
// The tile may have been removed, skip over it in this case.
|
||||
|
@ -328,14 +358,14 @@ TiledLayerBuffer<Derived, Tile>::Update(const nsIntRegion& aNewValidRegion,
|
|||
// Compute tileRect(x,y,width,height) in layer space coordinate
|
||||
// giving us the rect of the tile that hits the newBounds.
|
||||
int tileStartX = RoundDownToTileEdge(x);
|
||||
int width = GetTileLength() - GetTileStart(x);
|
||||
int width = GetScaledTileLength() - GetTileStart(x);
|
||||
if (x + width > newBound.XMost())
|
||||
width = newBound.XMost() - x;
|
||||
|
||||
tileY = 0;
|
||||
for (int y = newBound.y; y < newBound.y + newBound.height; tileY++) {
|
||||
int tileStartY = RoundDownToTileEdge(y);
|
||||
int height = GetTileLength() - GetTileStart(y);
|
||||
int height = GetScaledTileLength() - GetTileStart(y);
|
||||
if (y + height > newBound.YMost()) {
|
||||
height = newBound.YMost() - y;
|
||||
}
|
||||
|
@ -350,8 +380,8 @@ TiledLayerBuffer<Derived, Tile>::Update(const nsIntRegion& aNewValidRegion,
|
|||
// because we can reuse all of the content from the
|
||||
// previous buffer.
|
||||
#ifdef DEBUG
|
||||
int currTileX = floor_div(x - newBufferOrigin.x, GetTileLength());
|
||||
int currTileY = floor_div(y - newBufferOrigin.y, GetTileLength());
|
||||
int currTileX = floor_div(x - newBufferOrigin.x, GetScaledTileLength());
|
||||
int currTileY = floor_div(y - newBufferOrigin.y, GetScaledTileLength());
|
||||
int index = currTileX * mRetainedHeight + currTileY;
|
||||
NS_ABORT_IF_FALSE(!newValidRegion.Intersects(tileRect) ||
|
||||
!IsPlaceholder(newRetainedTiles.
|
||||
|
@ -362,8 +392,8 @@ TiledLayerBuffer<Derived, Tile>::Update(const nsIntRegion& aNewValidRegion,
|
|||
continue;
|
||||
}
|
||||
|
||||
int tileX = floor_div(x - newBufferOrigin.x, GetTileLength());
|
||||
int tileY = floor_div(y - newBufferOrigin.y, GetTileLength());
|
||||
int tileX = floor_div(x - newBufferOrigin.x, GetScaledTileLength());
|
||||
int tileY = floor_div(y - newBufferOrigin.y, GetScaledTileLength());
|
||||
int index = tileX * mRetainedHeight + tileY;
|
||||
NS_ABORT_IF_FALSE(index >= 0 &&
|
||||
static_cast<unsigned>(index) < newRetainedTiles.Length(),
|
||||
|
|
|
@ -1299,7 +1299,8 @@ bool
|
|||
BasicShadowLayerManager::ProgressiveUpdateCallback(bool aHasPendingNewThebesContent,
|
||||
gfx::Rect& aViewport,
|
||||
float& aScaleX,
|
||||
float& aScaleY)
|
||||
float& aScaleY,
|
||||
bool aDrawingCritical)
|
||||
{
|
||||
#ifdef MOZ_WIDGET_ANDROID
|
||||
Layer* primaryScrollable = GetPrimaryScrollableLayer();
|
||||
|
@ -1311,13 +1312,16 @@ BasicShadowLayerManager::ProgressiveUpdateCallback(bool aHasPendingNewThebesCont
|
|||
const gfx3DMatrix& rootTransform = GetRoot()->GetTransform();
|
||||
float devPixelRatioX = 1 / rootTransform.GetXScale();
|
||||
float devPixelRatioY = 1 / rootTransform.GetYScale();
|
||||
gfx::Rect displayPort((metrics.mDisplayPort.x + metrics.mScrollOffset.x) * devPixelRatioX,
|
||||
(metrics.mDisplayPort.y + metrics.mScrollOffset.y) * devPixelRatioY,
|
||||
metrics.mDisplayPort.width * devPixelRatioX,
|
||||
metrics.mDisplayPort.height * devPixelRatioY);
|
||||
const gfx::Rect& metricsDisplayPort =
|
||||
(aDrawingCritical && !metrics.mCriticalDisplayPort.IsEmpty()) ?
|
||||
metrics.mCriticalDisplayPort : metrics.mDisplayPort;
|
||||
gfx::Rect displayPort((metricsDisplayPort.x + metrics.mScrollOffset.x) * devPixelRatioX,
|
||||
(metricsDisplayPort.y + metrics.mScrollOffset.y) * devPixelRatioY,
|
||||
metricsDisplayPort.width * devPixelRatioX,
|
||||
metricsDisplayPort.height * devPixelRatioY);
|
||||
|
||||
return AndroidBridge::Bridge()->ProgressiveUpdateCallback(
|
||||
aHasPendingNewThebesContent, displayPort, devPixelRatioX,
|
||||
aHasPendingNewThebesContent, displayPort, devPixelRatioX, aDrawingCritical,
|
||||
aViewport, aScaleX, aScaleY);
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -276,6 +276,7 @@ public:
|
|||
virtual void ClearCachedResources(Layer* aSubtree = nullptr) MOZ_OVERRIDE;
|
||||
|
||||
void SetRepeatTransaction() { mRepeatTransaction = true; }
|
||||
bool GetRepeatTransaction() { return mRepeatTransaction; }
|
||||
|
||||
bool IsRepeatTransaction() { return mIsRepeatTransaction; }
|
||||
|
||||
|
@ -283,7 +284,8 @@ public:
|
|||
* Called for each iteration of a progressive tile update. Fills
|
||||
* aViewport, aScaleX and aScaleY with the current scale and viewport
|
||||
* being used to composite the layers in this manager, to determine what area
|
||||
* intersects with the target render rectangle.
|
||||
* intersects with the target render rectangle. aDrawingCritical will be
|
||||
* true if the current drawing operation is using the critical displayport.
|
||||
* Returns true if the update should continue, or false if it should be
|
||||
* cancelled.
|
||||
* This is only called if gfxPlatform::UseProgressiveTilePainting() returns
|
||||
|
@ -292,7 +294,8 @@ public:
|
|||
bool ProgressiveUpdateCallback(bool aHasPendingNewThebesContent,
|
||||
gfx::Rect& aViewport,
|
||||
float& aScaleX,
|
||||
float& aScaleY);
|
||||
float& aScaleY,
|
||||
bool aDrawingCritical);
|
||||
|
||||
private:
|
||||
/**
|
||||
|
|
|
@ -105,11 +105,15 @@ BasicTiledLayerBuffer::PaintThebes(BasicTiledThebesLayer* aLayer,
|
|||
const nsIntRect bounds = aPaintRegion.GetBounds();
|
||||
{
|
||||
SAMPLE_LABEL("BasicTiledLayerBuffer", "PaintThebesSingleBufferAlloc");
|
||||
mSinglePaintBuffer = new gfxImageSurface(gfxIntSize(bounds.width, bounds.height), GetFormat(), !aLayer->CanUseOpaqueSurface());
|
||||
mSinglePaintBuffer = new gfxImageSurface(
|
||||
gfxIntSize(ceilf(bounds.width * mResolution),
|
||||
ceilf(bounds.height * mResolution)),
|
||||
GetFormat(), !aLayer->CanUseOpaqueSurface());
|
||||
mSinglePaintBufferOffset = nsIntPoint(bounds.x, bounds.y);
|
||||
}
|
||||
nsRefPtr<gfxContext> ctxt = new gfxContext(mSinglePaintBuffer);
|
||||
ctxt->NewPath();
|
||||
ctxt->Scale(mResolution, mResolution);
|
||||
ctxt->Translate(gfxPoint(-bounds.x, -bounds.y));
|
||||
#ifdef GFX_TILEDLAYER_PREF_WARNINGS
|
||||
if (PR_IntervalNow() - start > 3) {
|
||||
|
@ -165,9 +169,6 @@ BasicTiledLayerBuffer::ValidateTileInternal(BasicTiledLayerTile aTile,
|
|||
aTile = BasicTiledLayerTile(tmpTile);
|
||||
}
|
||||
|
||||
gfxRect drawRect(aDirtyRect.x - aTileOrigin.x, aDirtyRect.y - aTileOrigin.y,
|
||||
aDirtyRect.width, aDirtyRect.height);
|
||||
|
||||
// Use the gfxReusableSurfaceWrapper, which will reuse the surface
|
||||
// if the compositor no longer has a read lock, otherwise the surface
|
||||
// will be copied into a new writable surface.
|
||||
|
@ -176,23 +177,35 @@ BasicTiledLayerBuffer::ValidateTileInternal(BasicTiledLayerTile aTile,
|
|||
|
||||
// Bug 742100, this gfxContext really should live on the stack.
|
||||
nsRefPtr<gfxContext> ctxt = new gfxContext(writableSurface);
|
||||
|
||||
if (mSinglePaintBuffer) {
|
||||
gfxRect drawRect(aDirtyRect.x - aTileOrigin.x, aDirtyRect.y - aTileOrigin.y,
|
||||
aDirtyRect.width, aDirtyRect.height);
|
||||
|
||||
ctxt->SetOperator(gfxContext::OPERATOR_SOURCE);
|
||||
ctxt->NewPath();
|
||||
ctxt->SetSource(mSinglePaintBuffer.get(),
|
||||
gfxPoint(mSinglePaintBufferOffset.x - aDirtyRect.x + drawRect.x,
|
||||
mSinglePaintBufferOffset.y - aDirtyRect.y + drawRect.y));
|
||||
gfxPoint((mSinglePaintBufferOffset.x - aDirtyRect.x + drawRect.x) *
|
||||
mResolution,
|
||||
(mSinglePaintBufferOffset.y - aDirtyRect.y + drawRect.y) *
|
||||
mResolution));
|
||||
drawRect.Scale(mResolution, mResolution);
|
||||
ctxt->Rectangle(drawRect, true);
|
||||
ctxt->Fill();
|
||||
} else {
|
||||
ctxt->NewPath();
|
||||
ctxt->Scale(mResolution, mResolution);
|
||||
ctxt->Translate(gfxPoint(-aTileOrigin.x, -aTileOrigin.y));
|
||||
nsIntPoint a = aTileOrigin;
|
||||
mCallback(mThebesLayer, ctxt, nsIntRegion(nsIntRect(a, nsIntSize(GetTileLength(), GetTileLength()))), nsIntRegion(), mCallbackData);
|
||||
nsIntPoint a = nsIntPoint(aTileOrigin.x, aTileOrigin.y);
|
||||
mCallback(mThebesLayer, ctxt,
|
||||
nsIntRegion(nsIntRect(a, nsIntSize(GetScaledTileLength(),
|
||||
GetScaledTileLength()))),
|
||||
nsIntRegion(), mCallbackData);
|
||||
}
|
||||
|
||||
#ifdef GFX_TILEDLAYER_DEBUG_OVERLAY
|
||||
DrawDebugOverlay(writableSurface, aTileOrigin.x, aTileOrigin.y);
|
||||
DrawDebugOverlay(writableSurface, aTileOrigin.x * mResolution,
|
||||
aTileOrigin.y * mResolution);
|
||||
#endif
|
||||
|
||||
return aTile;
|
||||
|
@ -251,29 +264,35 @@ RoundedTransformViewportBounds(const gfx::Rect& aViewport,
|
|||
}
|
||||
|
||||
bool
|
||||
BasicTiledThebesLayer::ComputeProgressiveUpdateRegion(const nsIntRegion& aInvalidRegion,
|
||||
BasicTiledThebesLayer::ComputeProgressiveUpdateRegion(BasicTiledLayerBuffer& aTiledBuffer,
|
||||
const nsIntRegion& aInvalidRegion,
|
||||
const nsIntRegion& aOldValidRegion,
|
||||
nsIntRegion& aRegionToPaint,
|
||||
const gfx3DMatrix& aTransform,
|
||||
const nsIntRect& aCompositionBounds,
|
||||
const gfx::Point& aScrollOffset,
|
||||
const gfxSize& aResolution,
|
||||
bool aIsRepeated)
|
||||
{
|
||||
aRegionToPaint = aInvalidRegion;
|
||||
|
||||
// If this is a low precision buffer, we force progressive updates. The
|
||||
// assumption is that the contents is less important, so visual coherency
|
||||
// is lower priority than speed.
|
||||
bool drawingLowPrecision = aTiledBuffer.IsLowPrecision();
|
||||
|
||||
// Find out if we have any non-stale content to update.
|
||||
nsIntRegion freshRegion;
|
||||
if (!mFirstPaint) {
|
||||
freshRegion.And(aInvalidRegion, aOldValidRegion);
|
||||
freshRegion.Sub(aInvalidRegion, freshRegion);
|
||||
}
|
||||
nsIntRegion staleRegion;
|
||||
staleRegion.And(aInvalidRegion, aOldValidRegion);
|
||||
|
||||
// Find out the current view transform to determine which tiles to draw
|
||||
// first, and see if we should just abort this paint. Aborting is usually
|
||||
// caused by there being an incoming, more relevant paint.
|
||||
gfx::Rect viewport;
|
||||
float scaleX, scaleY;
|
||||
if (BasicManager()->ProgressiveUpdateCallback(!freshRegion.IsEmpty(), viewport, scaleX, scaleY)) {
|
||||
if (BasicManager()->ProgressiveUpdateCallback(!staleRegion.Contains(aInvalidRegion),
|
||||
viewport,
|
||||
scaleX, scaleY, !drawingLowPrecision)) {
|
||||
SAMPLE_MARKER("Abort painting");
|
||||
aRegionToPaint.SetEmpty();
|
||||
return aIsRepeated;
|
||||
|
@ -284,10 +303,16 @@ BasicTiledThebesLayer::ComputeProgressiveUpdateRegion(const nsIntRegion& aInvali
|
|||
RoundedTransformViewportBounds(viewport, aScrollOffset, aResolution,
|
||||
scaleX, scaleY, aTransform);
|
||||
|
||||
// Paint tiles that have no content before tiles that only have stale content.
|
||||
bool drawingStale = freshRegion.IsEmpty();
|
||||
// Paint tiles that have stale content or that intersected with the screen
|
||||
// at the time of issuing the draw command in a single transaction first.
|
||||
// This is to avoid rendering glitches on animated page content, and when
|
||||
// layers change size/shape.
|
||||
nsIntRect criticalViewportRect = roundedTransformedViewport.Intersect(aCompositionBounds);
|
||||
aRegionToPaint.And(aInvalidRegion, criticalViewportRect);
|
||||
aRegionToPaint.Or(aRegionToPaint, staleRegion);
|
||||
bool drawingStale = !aRegionToPaint.IsEmpty();
|
||||
if (!drawingStale) {
|
||||
aRegionToPaint = freshRegion;
|
||||
aRegionToPaint = aInvalidRegion;
|
||||
}
|
||||
|
||||
// Prioritise tiles that are currently visible on the screen.
|
||||
|
@ -297,32 +322,35 @@ BasicTiledThebesLayer::ComputeProgressiveUpdateRegion(const nsIntRegion& aInvali
|
|||
paintVisible = true;
|
||||
}
|
||||
|
||||
// Paint area that's visible and overlaps previously valid content to avoid
|
||||
// visible glitches in animated elements, such as gifs.
|
||||
bool paintInSingleTransaction = paintVisible && (drawingStale || mFirstPaint);
|
||||
|
||||
// The following code decides what order to draw tiles in, based on the
|
||||
// current scroll direction of the primary scrollable layer.
|
||||
NS_ASSERTION(!aRegionToPaint.IsEmpty(), "Unexpectedly empty paint region!");
|
||||
nsIntRect paintBounds = aRegionToPaint.GetBounds();
|
||||
|
||||
int startX, incX, startY, incY;
|
||||
int tileLength = aTiledBuffer.GetScaledTileLength();
|
||||
if (aScrollOffset.x >= mLastScrollOffset.x) {
|
||||
startX = mTiledBuffer.RoundDownToTileEdge(paintBounds.x);
|
||||
incX = mTiledBuffer.GetTileLength();
|
||||
startX = aTiledBuffer.RoundDownToTileEdge(paintBounds.x);
|
||||
incX = tileLength;
|
||||
} else {
|
||||
startX = mTiledBuffer.RoundDownToTileEdge(paintBounds.XMost() - 1);
|
||||
incX = -mTiledBuffer.GetTileLength();
|
||||
startX = aTiledBuffer.RoundDownToTileEdge(paintBounds.XMost() - 1);
|
||||
incX = -tileLength;
|
||||
}
|
||||
|
||||
if (aScrollOffset.y >= mLastScrollOffset.y) {
|
||||
startY = mTiledBuffer.RoundDownToTileEdge(paintBounds.y);
|
||||
incY = mTiledBuffer.GetTileLength();
|
||||
startY = aTiledBuffer.RoundDownToTileEdge(paintBounds.y);
|
||||
incY = tileLength;
|
||||
} else {
|
||||
startY = mTiledBuffer.RoundDownToTileEdge(paintBounds.YMost() - 1);
|
||||
incY = -mTiledBuffer.GetTileLength();
|
||||
startY = aTiledBuffer.RoundDownToTileEdge(paintBounds.YMost() - 1);
|
||||
incY = -tileLength;
|
||||
}
|
||||
|
||||
// Find a tile to draw.
|
||||
nsIntRect tileBounds(startX, startY,
|
||||
mTiledBuffer.GetTileLength(),
|
||||
mTiledBuffer.GetTileLength());
|
||||
nsIntRect tileBounds(startX, startY, tileLength, tileLength);
|
||||
int32_t scrollDiffX = aScrollOffset.x - mLastScrollOffset.x;
|
||||
int32_t scrollDiffY = aScrollOffset.y - mLastScrollOffset.y;
|
||||
// This loop will always terminate, as there is at least one tile area
|
||||
|
@ -345,23 +373,75 @@ BasicTiledThebesLayer::ComputeProgressiveUpdateRegion(const nsIntRegion& aInvali
|
|||
// The region needed to paint is larger then our progressive chunk size
|
||||
// therefore update what we want to paint and ask for a new paint transaction.
|
||||
|
||||
// If we're drawing stale, visible content, make sure that it happens
|
||||
// in one go by repeating this work without calling the painted
|
||||
// callback. The remaining content is then drawn tile-by-tile in
|
||||
// multiple transactions.
|
||||
if (paintVisible && drawingStale) {
|
||||
// If we need to draw more than one tile to maintain coherency, make
|
||||
// sure it happens in the same transaction by requesting this work be
|
||||
// repeated immediately.
|
||||
// If this is unnecessary, the remaining work will be done tile-by-tile in
|
||||
// subsequent transactions.
|
||||
if (!drawingLowPrecision && paintInSingleTransaction) {
|
||||
repeatImmediately = true;
|
||||
} else {
|
||||
BasicManager()->SetRepeatTransaction();
|
||||
}
|
||||
} else {
|
||||
// The transaction is completed, store the last scroll offset.
|
||||
mLastScrollOffset = aScrollOffset;
|
||||
}
|
||||
|
||||
return repeatImmediately;
|
||||
}
|
||||
|
||||
bool
|
||||
BasicTiledThebesLayer::ProgressiveUpdate(BasicTiledLayerBuffer& aTiledBuffer,
|
||||
nsIntRegion& aValidRegion,
|
||||
nsIntRegion& aInvalidRegion,
|
||||
const nsIntRegion& aOldValidRegion,
|
||||
const gfx3DMatrix& aTransform,
|
||||
const nsIntRect& aCompositionBounds,
|
||||
const gfx::Point& aScrollOffset,
|
||||
const gfxSize& aResolution,
|
||||
LayerManager::DrawThebesLayerCallback aCallback,
|
||||
void* aCallbackData)
|
||||
{
|
||||
bool repeat = false;
|
||||
do {
|
||||
// Compute the region that should be updated. Repeat as many times as
|
||||
// is required.
|
||||
nsIntRegion regionToPaint;
|
||||
repeat = ComputeProgressiveUpdateRegion(aTiledBuffer,
|
||||
aInvalidRegion,
|
||||
aOldValidRegion,
|
||||
regionToPaint,
|
||||
aTransform,
|
||||
aCompositionBounds,
|
||||
aScrollOffset,
|
||||
aResolution,
|
||||
repeat);
|
||||
|
||||
// There's no further work to be done, return if nothing has been
|
||||
// drawn, or give what has been drawn to the shadow layer to upload.
|
||||
if (regionToPaint.IsEmpty()) {
|
||||
if (repeat) {
|
||||
break;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Keep track of what we're about to refresh.
|
||||
aValidRegion.Or(aValidRegion, regionToPaint);
|
||||
|
||||
// aValidRegion may have been altered by InvalidateRegion, but we still
|
||||
// want to display stale content until it gets progressively updated.
|
||||
// Create a region that includes stale content.
|
||||
nsIntRegion validOrStale;
|
||||
validOrStale.Or(aValidRegion, aOldValidRegion);
|
||||
|
||||
// Paint the computed region and subtract it from the invalid region.
|
||||
aTiledBuffer.PaintThebes(this, validOrStale, regionToPaint, aCallback, aCallbackData);
|
||||
aInvalidRegion.Sub(aInvalidRegion, regionToPaint);
|
||||
} while (repeat);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
BasicTiledThebesLayer::PaintThebes(gfxContext* aContext,
|
||||
Layer* aMaskLayer,
|
||||
|
@ -382,23 +462,15 @@ BasicTiledThebesLayer::PaintThebes(gfxContext* aContext,
|
|||
if (mTiledBuffer.HasFormatChanged(this)) {
|
||||
mValidRegion = nsIntRegion();
|
||||
}
|
||||
if (mLowPrecisionTiledBuffer.HasFormatChanged(this)) {
|
||||
mLowPrecisionValidRegion = nsIntRegion();
|
||||
}
|
||||
|
||||
nsIntRegion invalidRegion = mVisibleRegion;
|
||||
invalidRegion.Sub(invalidRegion, mValidRegion);
|
||||
if (invalidRegion.IsEmpty())
|
||||
return;
|
||||
|
||||
gfxSize resolution(1, 1);
|
||||
for (ContainerLayer* parent = GetParent(); parent; parent = parent->GetParent()) {
|
||||
const FrameMetrics& metrics = parent->GetFrameMetrics();
|
||||
resolution.width *= metrics.mResolution.width;
|
||||
resolution.height *= metrics.mResolution.height;
|
||||
}
|
||||
|
||||
// Only draw progressively when the resolution is unchanged.
|
||||
if (gfxPlatform::UseProgressiveTilePainting() &&
|
||||
!BasicManager()->HasShadowTarget() &&
|
||||
mTiledBuffer.GetResolution() == resolution) {
|
||||
// Calculate the transform required to convert screen space into layer space
|
||||
gfx3DMatrix transform = GetEffectiveTransform();
|
||||
// XXX Not sure if this code for intermediate surfaces is correct.
|
||||
|
@ -411,70 +483,92 @@ BasicTiledThebesLayer::PaintThebes(gfxContext* aContext,
|
|||
}
|
||||
transform.Invert();
|
||||
|
||||
// Store the old valid region, then clear it before painting.
|
||||
// We clip the old valid region to the visible region, as it only gets
|
||||
// used to decide stale content (currently valid and previously visible)
|
||||
nsIntRegion oldValidRegion = mTiledBuffer.GetValidRegion();
|
||||
oldValidRegion.And(oldValidRegion, mVisibleRegion);
|
||||
mTiledBuffer.ClearPaintedRegion();
|
||||
nsIntRect layerDisplayPort;
|
||||
nsIntRegion lowPrecisionInvalidRegion;
|
||||
const gfx::Rect& criticalDisplayPort = GetParent()->GetFrameMetrics().mCriticalDisplayPort;
|
||||
if (!criticalDisplayPort.IsEmpty()) {
|
||||
// Calculate the invalid region for the low precision buffer
|
||||
lowPrecisionInvalidRegion.Sub(mVisibleRegion, mLowPrecisionValidRegion);
|
||||
|
||||
// Make sure that tiles that fall outside of the visible region are
|
||||
// discarded on the first update.
|
||||
if (!BasicManager()->IsRepeatTransaction()) {
|
||||
mValidRegion.And(mValidRegion, mVisibleRegion);
|
||||
// Find the critical display port in layer space.
|
||||
gfxRect transformedCriticalDisplayPort = transform.TransformBounds(
|
||||
gfxRect(criticalDisplayPort.x, criticalDisplayPort.y,
|
||||
criticalDisplayPort.width, criticalDisplayPort.height));
|
||||
transformedCriticalDisplayPort.RoundOut();
|
||||
layerDisplayPort = nsIntRect(transformedCriticalDisplayPort.x,
|
||||
transformedCriticalDisplayPort.y,
|
||||
transformedCriticalDisplayPort.width,
|
||||
transformedCriticalDisplayPort.height);
|
||||
|
||||
// Clip the invalid region to the critical display-port
|
||||
invalidRegion.And(invalidRegion, layerDisplayPort);
|
||||
if (invalidRegion.IsEmpty() && lowPrecisionInvalidRegion.IsEmpty()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate the scroll offset since the last transaction.
|
||||
gfxSize resolution(1, 1);
|
||||
for (ContainerLayer* parent = GetParent(); parent; parent = parent->GetParent()) {
|
||||
const FrameMetrics& metrics = parent->GetFrameMetrics();
|
||||
resolution.width *= metrics.mResolution.width;
|
||||
resolution.height *= metrics.mResolution.height;
|
||||
}
|
||||
|
||||
// Calculate the scroll offset since the last transaction, and the
|
||||
// composition bounds.
|
||||
nsIntRect compositionBounds;
|
||||
gfx::Point scrollOffset(0, 0);
|
||||
Layer* primaryScrollable = BasicManager()->GetPrimaryScrollableLayer();
|
||||
if (primaryScrollable) {
|
||||
const FrameMetrics& metrics = primaryScrollable->AsContainerLayer()->GetFrameMetrics();
|
||||
scrollOffset = metrics.mScrollOffset;
|
||||
gfxRect transformedViewport = transform.TransformBounds(
|
||||
gfxRect(metrics.mCompositionBounds.x, metrics.mCompositionBounds.y,
|
||||
metrics.mCompositionBounds.width, metrics.mCompositionBounds.height));
|
||||
transformedViewport.RoundOut();
|
||||
compositionBounds = nsIntRect(transformedViewport.x, transformedViewport.y,
|
||||
transformedViewport.width, transformedViewport.height);
|
||||
}
|
||||
|
||||
bool repeat = false;
|
||||
do {
|
||||
// Compute the region that should be updated. Repeat as many times as
|
||||
// is required.
|
||||
nsIntRegion regionToPaint;
|
||||
repeat = ComputeProgressiveUpdateRegion(invalidRegion,
|
||||
oldValidRegion,
|
||||
regionToPaint,
|
||||
transform,
|
||||
scrollOffset,
|
||||
resolution,
|
||||
repeat);
|
||||
if (!invalidRegion.IsEmpty()) {
|
||||
bool updatedBuffer = false;
|
||||
// Only draw progressively when the resolution is unchanged.
|
||||
if (gfxPlatform::UseProgressiveTilePainting() &&
|
||||
!BasicManager()->HasShadowTarget() &&
|
||||
mTiledBuffer.GetFrameResolution() == resolution) {
|
||||
// Store the old valid region, then clear it before painting.
|
||||
// We clip the old valid region to the visible region, as it only gets
|
||||
// used to decide stale content (currently valid and previously visible)
|
||||
nsIntRegion oldValidRegion = mTiledBuffer.GetValidRegion();
|
||||
oldValidRegion.And(oldValidRegion, mVisibleRegion);
|
||||
if (!layerDisplayPort.IsEmpty()) {
|
||||
oldValidRegion.And(oldValidRegion, layerDisplayPort);
|
||||
}
|
||||
|
||||
// There's no further work to be done, return if nothing has been
|
||||
// drawn, or give what has been drawn to the shadow layer to upload.
|
||||
if (regionToPaint.IsEmpty()) {
|
||||
if (repeat) {
|
||||
break;
|
||||
// Make sure that tiles that fall outside of the visible region are
|
||||
// discarded on the first update.
|
||||
if (!BasicManager()->IsRepeatTransaction()) {
|
||||
mValidRegion.And(mValidRegion, mVisibleRegion);
|
||||
if (!layerDisplayPort.IsEmpty()) {
|
||||
mValidRegion.And(mValidRegion, layerDisplayPort);
|
||||
}
|
||||
}
|
||||
|
||||
updatedBuffer =
|
||||
ProgressiveUpdate(mTiledBuffer, mValidRegion, invalidRegion,
|
||||
oldValidRegion, transform, compositionBounds,
|
||||
scrollOffset, resolution, aCallback, aCallbackData);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Keep track of what we're about to refresh.
|
||||
mValidRegion.Or(mValidRegion, regionToPaint);
|
||||
|
||||
// mValidRegion would have been altered by InvalidateRegion, but we still
|
||||
// want to display stale content until it gets progressively updated.
|
||||
// Create a region that includes stale content.
|
||||
nsIntRegion validOrStale;
|
||||
validOrStale.Or(mValidRegion, oldValidRegion);
|
||||
|
||||
// Paint the computed region and subtract it from the invalid region.
|
||||
mTiledBuffer.PaintThebes(this, validOrStale, regionToPaint, aCallback, aCallbackData);
|
||||
invalidRegion.Sub(invalidRegion, regionToPaint);
|
||||
} while (repeat);
|
||||
} else {
|
||||
mTiledBuffer.ClearPaintedRegion();
|
||||
mTiledBuffer.SetResolution(resolution);
|
||||
updatedBuffer = true;
|
||||
mTiledBuffer.SetFrameResolution(resolution);
|
||||
mValidRegion = mVisibleRegion;
|
||||
if (!layerDisplayPort.IsEmpty()) {
|
||||
mValidRegion.And(mValidRegion, layerDisplayPort);
|
||||
}
|
||||
mTiledBuffer.PaintThebes(this, mValidRegion, invalidRegion, aCallback, aCallbackData);
|
||||
}
|
||||
|
||||
if (updatedBuffer) {
|
||||
mTiledBuffer.ReadLock();
|
||||
|
||||
// Only paint the mask layer on the first transaction.
|
||||
|
@ -490,6 +584,77 @@ BasicTiledThebesLayer::PaintThebes(gfxContext* aContext,
|
|||
BasicTiledLayerBuffer *heapCopy = new BasicTiledLayerBuffer(mTiledBuffer);
|
||||
|
||||
BasicManager()->PaintedTiledLayerBuffer(BasicManager()->Hold(this), heapCopy);
|
||||
mTiledBuffer.ClearPaintedRegion();
|
||||
}
|
||||
}
|
||||
|
||||
// If we have a critical display-port defined, render the full display-port
|
||||
// progressively in the low-precision tiled buffer.
|
||||
bool updatedLowPrecision = false;
|
||||
if (gfxPlatform::UseLowPrecisionBuffer() &&
|
||||
!criticalDisplayPort.IsEmpty() &&
|
||||
!nsIntRegion(layerDisplayPort).Contains(mVisibleRegion)) {
|
||||
nsIntRegion oldValidRegion = mLowPrecisionTiledBuffer.GetValidRegion();
|
||||
oldValidRegion.And(oldValidRegion, mVisibleRegion);
|
||||
|
||||
// If the frame resolution has changed, invalidate the buffer
|
||||
if (mLowPrecisionTiledBuffer.GetFrameResolution() != resolution) {
|
||||
if (!mLowPrecisionValidRegion.IsEmpty()) {
|
||||
updatedLowPrecision = true;
|
||||
}
|
||||
oldValidRegion.SetEmpty();
|
||||
mLowPrecisionValidRegion.SetEmpty();
|
||||
mLowPrecisionTiledBuffer.SetFrameResolution(resolution);
|
||||
}
|
||||
|
||||
// Invalidate previously valid content that is no longer visible
|
||||
if (!BasicManager()->IsRepeatTransaction()) {
|
||||
mLowPrecisionValidRegion.And(mLowPrecisionValidRegion, mVisibleRegion);
|
||||
}
|
||||
|
||||
// Remove the valid high-precision region from the invalid low-precision
|
||||
// region. We don't want to spend time drawing things twice.
|
||||
nsIntRegion invalidHighPrecisionIntersect;
|
||||
invalidHighPrecisionIntersect.And(lowPrecisionInvalidRegion, mValidRegion);
|
||||
lowPrecisionInvalidRegion.Sub(lowPrecisionInvalidRegion, invalidHighPrecisionIntersect);
|
||||
|
||||
if (!lowPrecisionInvalidRegion.IsEmpty()) {
|
||||
updatedLowPrecision =
|
||||
ProgressiveUpdate(mLowPrecisionTiledBuffer, mLowPrecisionValidRegion,
|
||||
lowPrecisionInvalidRegion, oldValidRegion, transform,
|
||||
compositionBounds, scrollOffset, resolution, aCallback,
|
||||
aCallbackData);
|
||||
}
|
||||
|
||||
// Re-add the high-precision valid region intersection so that we can
|
||||
// maintain coherency when the valid region changes.
|
||||
lowPrecisionInvalidRegion.Or(lowPrecisionInvalidRegion, invalidHighPrecisionIntersect);
|
||||
} else if (!mLowPrecisionValidRegion.IsEmpty()) {
|
||||
// Clear the low precision tiled buffer
|
||||
updatedLowPrecision = true;
|
||||
mLowPrecisionValidRegion.SetEmpty();
|
||||
mLowPrecisionTiledBuffer.PaintThebes(this, mLowPrecisionValidRegion,
|
||||
mLowPrecisionValidRegion, aCallback,
|
||||
aCallbackData);
|
||||
}
|
||||
|
||||
// We send a Painted callback if we clear the valid region of the low
|
||||
// precision buffer, so that the shadow buffer's valid region can be updated
|
||||
// and the associated resources can be freed.
|
||||
if (updatedLowPrecision) {
|
||||
mLowPrecisionTiledBuffer.ReadLock();
|
||||
BasicTiledLayerBuffer *heapCopy = new BasicTiledLayerBuffer(mLowPrecisionTiledBuffer);
|
||||
|
||||
// The GL layer manager uses the buffer resolution to distinguish calls
|
||||
// to PaintedTiledLayerBuffer.
|
||||
BasicManager()->PaintedTiledLayerBuffer(BasicManager()->Hold(this), heapCopy);
|
||||
mLowPrecisionTiledBuffer.ClearPaintedRegion();
|
||||
}
|
||||
|
||||
// The transaction is completed, store the last scroll offset.
|
||||
if (!BasicManager()->GetRepeatTransaction()) {
|
||||
mLastScrollOffset = scrollOffset;
|
||||
}
|
||||
mFirstPaint = false;
|
||||
}
|
||||
|
||||
|
|
|
@ -12,6 +12,8 @@
|
|||
#include "BasicImplData.h"
|
||||
#include <algorithm>
|
||||
|
||||
#define LOW_PRECISION_RESOLUTION 0.25
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
|
@ -107,8 +109,8 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
const gfxSize& GetResolution() { return mResolution; }
|
||||
void SetResolution(const gfxSize& aResolution) { mResolution = aResolution; }
|
||||
const gfxSize& GetFrameResolution() { return mFrameResolution; }
|
||||
void SetFrameResolution(const gfxSize& aResolution) { mFrameResolution = aResolution; }
|
||||
|
||||
bool HasFormatChanged(BasicTiledThebesLayer* aThebesLayer) const;
|
||||
protected:
|
||||
|
@ -133,7 +135,7 @@ private:
|
|||
BasicTiledThebesLayer* mThebesLayer;
|
||||
LayerManager::DrawThebesLayerCallback mCallback;
|
||||
void* mCallbackData;
|
||||
gfxSize mResolution;
|
||||
gfxSize mFrameResolution;
|
||||
bool mLastPaintOpaque;
|
||||
|
||||
// The buffer we use when UseSinglePaintBuffer() above is true.
|
||||
|
@ -166,6 +168,7 @@ public:
|
|||
, mFirstPaint(true)
|
||||
{
|
||||
MOZ_COUNT_CTOR(BasicTiledThebesLayer);
|
||||
mLowPrecisionTiledBuffer.SetResolution(LOW_PRECISION_RESOLUTION);
|
||||
}
|
||||
|
||||
~BasicTiledThebesLayer()
|
||||
|
@ -179,6 +182,7 @@ public:
|
|||
virtual void InvalidateRegion(const nsIntRegion& aRegion) {
|
||||
mInvalidRegion.Or(mInvalidRegion, aRegion);
|
||||
mValidRegion.Sub(mValidRegion, aRegion);
|
||||
mLowPrecisionValidRegion.Sub(mLowPrecisionValidRegion, aRegion);
|
||||
}
|
||||
|
||||
// Shadow methods
|
||||
|
@ -220,12 +224,14 @@ private:
|
|||
* at once to maintain visual coherency.
|
||||
*
|
||||
* aInvalidRegion is the current invalid region.
|
||||
* aOldValidRegion is the valid region of mTiledBuffer at the beginning of the
|
||||
* aOldValidRegion is the valid region of aTiledBuffer at the beginning of the
|
||||
* current transaction.
|
||||
* aRegionToPaint will be filled with the region to update. This may be empty,
|
||||
* which indicates that there is no more work to do.
|
||||
* aTransform is the transform required to convert from screen-space to
|
||||
* layer-space.
|
||||
* aCompositionBounds is the composition bounds from the primary scrollable
|
||||
* layer, transformed into layer coordinates.
|
||||
* aScrollOffset is the current scroll offset of the primary scrollable layer.
|
||||
* aResolution is the render resolution of the layer.
|
||||
* aIsRepeated should be true if this function has already been called during
|
||||
|
@ -234,16 +240,35 @@ private:
|
|||
* Returns true if it should be called again, false otherwise. In the case
|
||||
* that aRegionToPaint is empty, this will return aIsRepeated for convenience.
|
||||
*/
|
||||
bool ComputeProgressiveUpdateRegion(const nsIntRegion& aInvalidRegion,
|
||||
bool ComputeProgressiveUpdateRegion(BasicTiledLayerBuffer& aTiledBuffer,
|
||||
const nsIntRegion& aInvalidRegion,
|
||||
const nsIntRegion& aOldValidRegion,
|
||||
nsIntRegion& aRegionToPaint,
|
||||
const gfx3DMatrix& aTransform,
|
||||
const nsIntRect& aCompositionBounds,
|
||||
const gfx::Point& aScrollOffset,
|
||||
const gfxSize& aResolution,
|
||||
bool aIsRepeated);
|
||||
|
||||
/**
|
||||
* Performs a progressive update of a given tiled buffer.
|
||||
* See ComputeProgressiveUpdateRegion above for parameter documentation.
|
||||
*/
|
||||
bool ProgressiveUpdate(BasicTiledLayerBuffer& aTiledBuffer,
|
||||
nsIntRegion& aValidRegion,
|
||||
nsIntRegion& aInvalidRegion,
|
||||
const nsIntRegion& aOldValidRegion,
|
||||
const gfx3DMatrix& aTransform,
|
||||
const nsIntRect& aCompositionBounds,
|
||||
const gfx::Point& aScrollOffset,
|
||||
const gfxSize& aResolution,
|
||||
LayerManager::DrawThebesLayerCallback aCallback,
|
||||
void* aCallbackData);
|
||||
|
||||
// Members
|
||||
BasicTiledLayerBuffer mTiledBuffer;
|
||||
BasicTiledLayerBuffer mLowPrecisionTiledBuffer;
|
||||
nsIntRegion mLowPrecisionValidRegion;
|
||||
gfx::Point mLastScrollOffset;
|
||||
bool mFirstPaint;
|
||||
};
|
||||
|
|
|
@ -875,7 +875,8 @@ CompositorParent::TransformShadowTree(TimeStamp aCurrentFrame)
|
|||
// We synchronise the viewport information with Java after sending the above
|
||||
// notifications, so that Java can take these into account in its response.
|
||||
// Calculate the absolute display port to send to Java
|
||||
gfx::Rect displayPortLayersPixels(metrics.mDisplayPort);
|
||||
gfx::Rect displayPortLayersPixels(metrics.mCriticalDisplayPort.IsEmpty() ?
|
||||
metrics.mDisplayPort : metrics.mCriticalDisplayPort);
|
||||
nsIntRect displayPortDevPixels(
|
||||
NS_lround(displayPortLayersPixels.x * devPixelRatioX),
|
||||
NS_lround(displayPortLayersPixels.y * devPixelRatioY),
|
||||
|
|
|
@ -136,6 +136,9 @@ ReusableTileStoreOGL::HarvestTiles(TiledThebesLayerOGL* aLayer,
|
|||
const gfxSize& aOldResolution,
|
||||
const gfxSize& aNewResolution)
|
||||
{
|
||||
NS_ASSERTION(aVideoMemoryTiledBuffer->GetResolution() == 1.0f,
|
||||
"ReusableTileStoreOGL cannot harvest scaled tiles!");
|
||||
|
||||
gfxSize scaleFactor = gfxSize(aNewResolution.width / aOldResolution.width,
|
||||
aNewResolution.height / aOldResolution.height);
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include "ReusableTileStoreOGL.h"
|
||||
#include "BasicTiledThebesLayer.h"
|
||||
#include "gfxImageSurface.h"
|
||||
#include "gfxPlatform.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
@ -46,7 +47,7 @@ TiledLayerBufferOGL::Upload(const BasicTiledLayerBuffer* aMainMemoryTiledBuffer,
|
|||
long start = PR_IntervalNow();
|
||||
#endif
|
||||
|
||||
mResolution = aResolution;
|
||||
mFrameResolution = aResolution;
|
||||
mMainMemoryTiledBuffer = aMainMemoryTiledBuffer;
|
||||
mContext->MakeCurrent();
|
||||
Update(aNewValidRegion, aInvalidateRegion);
|
||||
|
@ -115,7 +116,10 @@ TiledThebesLayerOGL::TiledThebesLayerOGL(LayerManagerOGL *aManager)
|
|||
: ShadowThebesLayer(aManager, nullptr)
|
||||
, LayerOGL(aManager)
|
||||
, mVideoMemoryTiledBuffer(aManager->gl())
|
||||
, mLowPrecisionVideoMemoryTiledBuffer(aManager->gl())
|
||||
, mReusableTileStore(nullptr)
|
||||
, mPendingUpload(false)
|
||||
, mPendingLowPrecisionUpload(false)
|
||||
{
|
||||
mImplData = static_cast<LayerOGL*>(this);
|
||||
}
|
||||
|
@ -123,6 +127,7 @@ TiledThebesLayerOGL::TiledThebesLayerOGL(LayerManagerOGL *aManager)
|
|||
TiledThebesLayerOGL::~TiledThebesLayerOGL()
|
||||
{
|
||||
mMainMemoryTiledBuffer.ReadUnlock();
|
||||
mLowPrecisionMainMemoryTiledBuffer.ReadUnlock();
|
||||
if (mReusableTileStore)
|
||||
delete mReusableTileStore;
|
||||
}
|
||||
|
@ -139,18 +144,54 @@ TiledThebesLayerOGL::MemoryPressure()
|
|||
void
|
||||
TiledThebesLayerOGL::PaintedTiledLayerBuffer(const BasicTiledLayerBuffer* mTiledBuffer)
|
||||
{
|
||||
if (mTiledBuffer->IsLowPrecision()) {
|
||||
mLowPrecisionMainMemoryTiledBuffer.ReadUnlock();
|
||||
mLowPrecisionMainMemoryTiledBuffer = *mTiledBuffer;
|
||||
mLowPrecisionRegionToUpload.Or(mLowPrecisionRegionToUpload,
|
||||
mLowPrecisionMainMemoryTiledBuffer.GetPaintedRegion());
|
||||
mLowPrecisionMainMemoryTiledBuffer.ClearPaintedRegion();
|
||||
mPendingLowPrecisionUpload = true;
|
||||
} else {
|
||||
mMainMemoryTiledBuffer.ReadUnlock();
|
||||
mMainMemoryTiledBuffer = *mTiledBuffer;
|
||||
// TODO: Remove me once Bug 747811 lands.
|
||||
delete mTiledBuffer;
|
||||
mRegionToUpload.Or(mRegionToUpload, mMainMemoryTiledBuffer.GetPaintedRegion());
|
||||
mMainMemoryTiledBuffer.ClearPaintedRegion();
|
||||
mPendingUpload = true;
|
||||
}
|
||||
|
||||
// TODO: Remove me once Bug 747811 lands.
|
||||
delete mTiledBuffer;
|
||||
}
|
||||
|
||||
void
|
||||
TiledThebesLayerOGL::ProcessLowPrecisionUploadQueue()
|
||||
{
|
||||
if (!mPendingLowPrecisionUpload)
|
||||
return;
|
||||
|
||||
mLowPrecisionRegionToUpload.And(mLowPrecisionRegionToUpload,
|
||||
mLowPrecisionMainMemoryTiledBuffer.GetValidRegion());
|
||||
// XXX The aResolution parameter of Upload is unused here - this is normally
|
||||
// set so that ReusableTileStoreOGL knows the frame resolution of tiles
|
||||
// it's harvesting.
|
||||
mLowPrecisionVideoMemoryTiledBuffer.SetResolution(
|
||||
mLowPrecisionMainMemoryTiledBuffer.GetResolution());
|
||||
mLowPrecisionVideoMemoryTiledBuffer.Upload(&mLowPrecisionMainMemoryTiledBuffer,
|
||||
mLowPrecisionMainMemoryTiledBuffer.GetValidRegion(),
|
||||
mLowPrecisionRegionToUpload, gfxSize(1, 1));
|
||||
nsIntRegion validRegion = mLowPrecisionVideoMemoryTiledBuffer.GetValidRegion();
|
||||
|
||||
mLowPrecisionMainMemoryTiledBuffer.ReadUnlock();
|
||||
|
||||
mLowPrecisionMainMemoryTiledBuffer = BasicTiledLayerBuffer();
|
||||
mLowPrecisionRegionToUpload = nsIntRegion();
|
||||
mPendingLowPrecisionUpload = false;
|
||||
}
|
||||
|
||||
void
|
||||
TiledThebesLayerOGL::ProcessUploadQueue()
|
||||
{
|
||||
if (mRegionToUpload.IsEmpty())
|
||||
if (!mPendingUpload)
|
||||
return;
|
||||
|
||||
// We should only be retaining old tiles if we're not fixed position.
|
||||
|
@ -159,9 +200,10 @@ TiledThebesLayerOGL::ProcessUploadQueue()
|
|||
if (mReusableTileStore && mIsFixedPosition) {
|
||||
delete mReusableTileStore;
|
||||
mReusableTileStore = nullptr;
|
||||
} else if (!mReusableTileStore && !mIsFixedPosition) {
|
||||
} else if (gfxPlatform::UseReusableTileStore() &&
|
||||
!mReusableTileStore && !mIsFixedPosition) {
|
||||
// XXX Add a pref for reusable tile store size
|
||||
mReusableTileStore = new ReusableTileStoreOGL(gl(), 2);
|
||||
mReusableTileStore = new ReusableTileStoreOGL(gl(), 1);
|
||||
}
|
||||
|
||||
gfxSize resolution(1, 1);
|
||||
|
@ -181,7 +223,7 @@ TiledThebesLayerOGL::ProcessUploadQueue()
|
|||
&mVideoMemoryTiledBuffer,
|
||||
mVideoMemoryTiledBuffer.GetValidRegion(),
|
||||
mMainMemoryTiledBuffer.GetValidRegion(),
|
||||
mVideoMemoryTiledBuffer.GetResolution(),
|
||||
mVideoMemoryTiledBuffer.GetFrameResolution(),
|
||||
resolution);
|
||||
}
|
||||
|
||||
|
@ -192,6 +234,7 @@ TiledThebesLayerOGL::ProcessUploadQueue()
|
|||
mVideoMemoryTiledBuffer.Upload(&mMainMemoryTiledBuffer,
|
||||
mMainMemoryTiledBuffer.GetValidRegion(),
|
||||
mRegionToUpload, resolution);
|
||||
|
||||
mValidRegion = mVideoMemoryTiledBuffer.GetValidRegion();
|
||||
|
||||
mMainMemoryTiledBuffer.ReadUnlock();
|
||||
|
@ -202,7 +245,7 @@ TiledThebesLayerOGL::ProcessUploadQueue()
|
|||
// tile by tile.
|
||||
mMainMemoryTiledBuffer = BasicTiledLayerBuffer();
|
||||
mRegionToUpload = nsIntRegion();
|
||||
|
||||
mPendingUpload = false;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -240,53 +283,51 @@ TiledThebesLayerOGL::RenderTile(const TiledTexture& aTile,
|
|||
}
|
||||
|
||||
void
|
||||
TiledThebesLayerOGL::RenderLayer(int aPreviousFrameBuffer, const nsIntPoint& aOffset)
|
||||
TiledThebesLayerOGL::RenderLayerBuffer(TiledLayerBufferOGL& aLayerBuffer,
|
||||
const nsIntRegion& aValidRegion,
|
||||
const nsIntPoint& aOffset,
|
||||
const nsIntRegion& aMaskRegion)
|
||||
{
|
||||
gl()->MakeCurrent();
|
||||
gl()->fActiveTexture(LOCAL_GL_TEXTURE0);
|
||||
ProcessUploadQueue();
|
||||
|
||||
Layer* maskLayer = GetMaskLayer();
|
||||
|
||||
// Render old tiles to fill in gaps we haven't had the time to render yet.
|
||||
if (mReusableTileStore) {
|
||||
mReusableTileStore->DrawTiles(this,
|
||||
mVideoMemoryTiledBuffer.GetValidRegion(),
|
||||
mVideoMemoryTiledBuffer.GetResolution(),
|
||||
GetEffectiveTransform(), aOffset, maskLayer);
|
||||
}
|
||||
|
||||
// Render valid tiles.
|
||||
const nsIntRegion& visibleRegion = GetEffectiveVisibleRegion();
|
||||
const nsIntRect visibleRect = visibleRegion.GetBounds();
|
||||
float resolution = aLayerBuffer.GetResolution();
|
||||
gfx3DMatrix transform = GetEffectiveTransform();
|
||||
transform.Scale(1/resolution, 1/resolution, 1);
|
||||
|
||||
uint32_t rowCount = 0;
|
||||
uint32_t tileX = 0;
|
||||
for (int32_t x = visibleRect.x; x < visibleRect.x + visibleRect.width;) {
|
||||
rowCount++;
|
||||
int32_t tileStartX = mVideoMemoryTiledBuffer.GetTileStart(x);
|
||||
int16_t w = mVideoMemoryTiledBuffer.GetTileLength() - tileStartX;
|
||||
int32_t tileStartX = aLayerBuffer.GetTileStart(x);
|
||||
int32_t w = aLayerBuffer.GetScaledTileLength() - tileStartX;
|
||||
if (x + w > visibleRect.x + visibleRect.width)
|
||||
w = visibleRect.x + visibleRect.width - x;
|
||||
int tileY = 0;
|
||||
for (int32_t y = visibleRect.y; y < visibleRect.y + visibleRect.height;) {
|
||||
int32_t tileStartY = mVideoMemoryTiledBuffer.GetTileStart(y);
|
||||
int16_t h = mVideoMemoryTiledBuffer.GetTileLength() - tileStartY;
|
||||
int32_t tileStartY = aLayerBuffer.GetTileStart(y);
|
||||
int32_t h = aLayerBuffer.GetScaledTileLength() - tileStartY;
|
||||
if (y + h > visibleRect.y + visibleRect.height)
|
||||
h = visibleRect.y + visibleRect.height - y;
|
||||
|
||||
TiledTexture tileTexture = mVideoMemoryTiledBuffer.
|
||||
GetTile(nsIntPoint(mVideoMemoryTiledBuffer.RoundDownToTileEdge(x),
|
||||
mVideoMemoryTiledBuffer.RoundDownToTileEdge(y)));
|
||||
if (tileTexture != mVideoMemoryTiledBuffer.GetPlaceholderTile()) {
|
||||
TiledTexture tileTexture = aLayerBuffer.
|
||||
GetTile(nsIntPoint(aLayerBuffer.RoundDownToTileEdge(x),
|
||||
aLayerBuffer.RoundDownToTileEdge(y)));
|
||||
if (tileTexture != aLayerBuffer.GetPlaceholderTile()) {
|
||||
nsIntRegion tileDrawRegion = nsIntRegion(nsIntRect(x, y, w, h));
|
||||
tileDrawRegion.And(tileDrawRegion, mValidRegion);
|
||||
tileDrawRegion.And(tileDrawRegion, aValidRegion);
|
||||
tileDrawRegion.Sub(tileDrawRegion, aMaskRegion);
|
||||
|
||||
nsIntPoint tileOffset(x - tileStartX, y - tileStartY);
|
||||
uint16_t tileSize = mVideoMemoryTiledBuffer.GetTileLength();
|
||||
RenderTile(tileTexture, GetEffectiveTransform(), aOffset, tileDrawRegion,
|
||||
if (!tileDrawRegion.IsEmpty()) {
|
||||
tileDrawRegion.ScaleRoundOut(resolution, resolution);
|
||||
|
||||
nsIntPoint tileOffset((x - tileStartX) * resolution,
|
||||
(y - tileStartY) * resolution);
|
||||
uint32_t tileSize = aLayerBuffer.GetTileLength();
|
||||
RenderTile(tileTexture, transform, aOffset, tileDrawRegion,
|
||||
tileOffset, nsIntSize(tileSize, tileSize), maskLayer);
|
||||
}
|
||||
}
|
||||
tileY++;
|
||||
y += h;
|
||||
}
|
||||
|
@ -295,5 +336,28 @@ TiledThebesLayerOGL::RenderLayer(int aPreviousFrameBuffer, const nsIntPoint& aOf
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
TiledThebesLayerOGL::RenderLayer(int aPreviousFrameBuffer, const nsIntPoint& aOffset)
|
||||
{
|
||||
gl()->MakeCurrent();
|
||||
gl()->fActiveTexture(LOCAL_GL_TEXTURE0);
|
||||
ProcessUploadQueue();
|
||||
ProcessLowPrecisionUploadQueue();
|
||||
|
||||
// Render old tiles to fill in gaps we haven't had the time to render yet.
|
||||
if (mReusableTileStore) {
|
||||
mReusableTileStore->DrawTiles(this,
|
||||
mVideoMemoryTiledBuffer.GetValidRegion(),
|
||||
mVideoMemoryTiledBuffer.GetFrameResolution(),
|
||||
GetEffectiveTransform(), aOffset, GetMaskLayer());
|
||||
}
|
||||
|
||||
// Render valid tiles.
|
||||
RenderLayerBuffer(mLowPrecisionVideoMemoryTiledBuffer,
|
||||
mLowPrecisionVideoMemoryTiledBuffer.GetValidRegion(),
|
||||
aOffset, mValidRegion);
|
||||
RenderLayerBuffer(mVideoMemoryTiledBuffer, mValidRegion, aOffset, nsIntRegion());
|
||||
}
|
||||
|
||||
} // mozilla
|
||||
} // layers
|
||||
|
|
|
@ -80,7 +80,9 @@ public:
|
|||
|
||||
TiledTexture GetPlaceholderTile() const { return TiledTexture(); }
|
||||
|
||||
const gfxSize& GetResolution() { return mResolution; }
|
||||
// Stores the absolute resolution of the containing frame, calculated
|
||||
// by the sum of the resolutions of all parent layers' FrameMetrics.
|
||||
const gfxSize& GetFrameResolution() { return mFrameResolution; }
|
||||
|
||||
protected:
|
||||
TiledTexture ValidateTile(TiledTexture aTile,
|
||||
|
@ -96,7 +98,7 @@ protected:
|
|||
private:
|
||||
nsRefPtr<gl::GLContext> mContext;
|
||||
const BasicTiledLayerBuffer* mMainMemoryTiledBuffer;
|
||||
gfxSize mResolution;
|
||||
gfxSize mFrameResolution;
|
||||
|
||||
void GetFormatAndTileForImageFormat(gfxASurface::gfxImageFormat aFormat,
|
||||
GLenum& aOutFormat,
|
||||
|
@ -129,6 +131,7 @@ public:
|
|||
}
|
||||
void PaintedTiledLayerBuffer(const BasicTiledLayerBuffer* mTiledBuffer);
|
||||
void ProcessUploadQueue();
|
||||
void ProcessLowPrecisionUploadQueue();
|
||||
|
||||
void MemoryPressure();
|
||||
|
||||
|
@ -142,10 +145,20 @@ public:
|
|||
Layer* aMaskLayer);
|
||||
|
||||
private:
|
||||
void RenderLayerBuffer(TiledLayerBufferOGL& aLayerBuffer,
|
||||
const nsIntRegion& aValidRegion,
|
||||
const nsIntPoint& aOffset,
|
||||
const nsIntRegion& aMaskRegion);
|
||||
|
||||
nsIntRegion mRegionToUpload;
|
||||
nsIntRegion mLowPrecisionRegionToUpload;
|
||||
BasicTiledLayerBuffer mMainMemoryTiledBuffer;
|
||||
BasicTiledLayerBuffer mLowPrecisionMainMemoryTiledBuffer;
|
||||
TiledLayerBufferOGL mVideoMemoryTiledBuffer;
|
||||
TiledLayerBufferOGL mLowPrecisionVideoMemoryTiledBuffer;
|
||||
ReusableTileStoreOGL* mReusableTileStore;
|
||||
bool mPendingUpload : 1;
|
||||
bool mPendingLowPrecisionUpload : 1;
|
||||
};
|
||||
|
||||
} // layers
|
||||
|
|
|
@ -1246,6 +1246,38 @@ gfxPlatform::UseProgressiveTilePainting()
|
|||
return sUseProgressiveTilePainting;
|
||||
}
|
||||
|
||||
bool
|
||||
gfxPlatform::UseLowPrecisionBuffer()
|
||||
{
|
||||
static bool sUseLowPrecisionBuffer;
|
||||
static bool sUseLowPrecisionBufferPrefCached = false;
|
||||
|
||||
if (!sUseLowPrecisionBufferPrefCached) {
|
||||
sUseLowPrecisionBufferPrefCached = true;
|
||||
mozilla::Preferences::AddBoolVarCache(&sUseLowPrecisionBuffer,
|
||||
"layers.low-precision-buffer",
|
||||
false);
|
||||
}
|
||||
|
||||
return sUseLowPrecisionBuffer;
|
||||
}
|
||||
|
||||
bool
|
||||
gfxPlatform::UseReusableTileStore()
|
||||
{
|
||||
static bool sUseReusableTileStore;
|
||||
static bool sUseReusableTileStorePrefCached = false;
|
||||
|
||||
if (!sUseReusableTileStorePrefCached) {
|
||||
sUseReusableTileStorePrefCached = true;
|
||||
mozilla::Preferences::AddBoolVarCache(&sUseReusableTileStore,
|
||||
"layers.reuse-invalid-tiles",
|
||||
false);
|
||||
}
|
||||
|
||||
return sUseReusableTileStore;
|
||||
}
|
||||
|
||||
bool
|
||||
gfxPlatform::OffMainThreadCompositingEnabled()
|
||||
{
|
||||
|
|
|
@ -405,6 +405,14 @@ public:
|
|||
// Break large OMTC tiled thebes layer painting into small paints.
|
||||
static bool UseProgressiveTilePainting();
|
||||
|
||||
// When a critical display-port is set, render the visible area outside of
|
||||
// it into a buffer at a lower precision. Requires tiled buffers.
|
||||
static bool UseLowPrecisionBuffer();
|
||||
|
||||
// Retain some invalid tiles when the valid region of a layer changes and
|
||||
// excludes previously valid tiles.
|
||||
static bool UseReusableTileStore();
|
||||
|
||||
static bool OffMainThreadCompositingEnabled();
|
||||
|
||||
/**
|
||||
|
|
|
@ -1324,6 +1324,12 @@ bool imgLoader::ValidateEntry(imgCacheEntry *aEntry,
|
|||
aCORSMode, aLoadingPrincipal))
|
||||
return false;
|
||||
|
||||
// Never validate data URIs.
|
||||
nsAutoCString scheme;
|
||||
aURI->GetScheme(scheme);
|
||||
if (scheme.EqualsLiteral("data"))
|
||||
return true;
|
||||
|
||||
bool validateRequest = false;
|
||||
|
||||
// If the request's loadId is the same as the aCX, then it is ok to use
|
||||
|
|
|
@ -965,6 +965,7 @@ struct ParamTraits<mozilla::layers::FrameMetrics>
|
|||
WriteParam(aMsg, aParam.mContentRect);
|
||||
WriteParam(aMsg, aParam.mScrollOffset);
|
||||
WriteParam(aMsg, aParam.mDisplayPort);
|
||||
WriteParam(aMsg, aParam.mCriticalDisplayPort);
|
||||
WriteParam(aMsg, aParam.mCompositionBounds);
|
||||
WriteParam(aMsg, aParam.mScrollId);
|
||||
WriteParam(aMsg, aParam.mResolution);
|
||||
|
@ -980,6 +981,7 @@ struct ParamTraits<mozilla::layers::FrameMetrics>
|
|||
ReadParam(aMsg, aIter, &aResult->mContentRect) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mScrollOffset) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mDisplayPort) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mCriticalDisplayPort) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mCompositionBounds) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mScrollId) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mResolution) &&
|
||||
|
|
|
@ -1 +1,348 @@
|
|||
//this space intentionally left blank
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/* ES5 15.4.4.14. */
|
||||
function ArrayIndexOf(searchElement/*, fromIndex*/) {
|
||||
/* Step 1. */
|
||||
var O = %ToObject(this);
|
||||
|
||||
/* Steps 2-3. */
|
||||
var len = TO_UINT32(O.length);
|
||||
|
||||
/* Step 4. */
|
||||
if (len === 0)
|
||||
return -1;
|
||||
|
||||
/* Step 5. */
|
||||
var n = arguments.length > 1 ? %ToInteger(arguments[1]) : 0;
|
||||
|
||||
/* Step 6. */
|
||||
if (n >= len)
|
||||
return -1;
|
||||
|
||||
var k;
|
||||
/* Step 7. */
|
||||
if (n >= 0)
|
||||
k = n;
|
||||
/* Step 8. */
|
||||
else {
|
||||
/* Step a. */
|
||||
k = len + n;
|
||||
/* Step b. */
|
||||
if (k < 0)
|
||||
k = 0;
|
||||
}
|
||||
|
||||
/* Step 9. */
|
||||
for (; k < len; k++) {
|
||||
if (k in O && O[k] === searchElement)
|
||||
return k;
|
||||
}
|
||||
|
||||
/* Step 10. */
|
||||
return -1;
|
||||
}
|
||||
|
||||
function ArrayStaticIndexOf(list, searchElement/*, fromIndex*/) {
|
||||
if (arguments.length < 1)
|
||||
%ThrowError(JSMSG_MISSING_FUN_ARG, 0, 'Array.indexOf');
|
||||
var fromIndex = arguments.length > 2 ? arguments[2] : 0;
|
||||
return %_CallFunction(list, searchElement, fromIndex, ArrayIndexOf);
|
||||
}
|
||||
|
||||
/* ES5 15.4.4.15. */
|
||||
function ArrayLastIndexOf(searchElement/*, fromIndex*/) {
|
||||
/* Step 1. */
|
||||
var O = %ToObject(this);
|
||||
|
||||
/* Steps 2-3. */
|
||||
var len = TO_UINT32(O.length);
|
||||
|
||||
/* Step 4. */
|
||||
if (len === 0)
|
||||
return -1;
|
||||
|
||||
/* Step 5. */
|
||||
var n = arguments.length > 1 ? %ToInteger(arguments[1]) : len - 1;
|
||||
|
||||
/* Steps 6-7. */
|
||||
var k;
|
||||
if (n > len - 1)
|
||||
k = len - 1;
|
||||
else if (n < 0)
|
||||
k = len + n;
|
||||
else
|
||||
k = n;
|
||||
|
||||
/* Step 8. */
|
||||
for (; k >= 0; k--) {
|
||||
if (k in O && O[k] === searchElement)
|
||||
return k;
|
||||
}
|
||||
|
||||
/* Step 9. */
|
||||
return -1;
|
||||
}
|
||||
|
||||
function ArrayStaticLastIndexOf(list, searchElement/*, fromIndex*/) {
|
||||
if (arguments.length < 1)
|
||||
%ThrowError(JSMSG_MISSING_FUN_ARG, 0, 'Array.lastIndexOf');
|
||||
var fromIndex;
|
||||
if (arguments.length > 2) {
|
||||
fromIndex = arguments[2];
|
||||
} else {
|
||||
var O = %ToObject(list);
|
||||
var len = TO_UINT32(O.length);
|
||||
fromIndex = len - 1;
|
||||
}
|
||||
return %_CallFunction(list, searchElement, fromIndex, ArrayLastIndexOf);
|
||||
}
|
||||
|
||||
/* ES5 15.4.4.16. */
|
||||
function ArrayEvery(callbackfn/*, thisArg*/) {
|
||||
/* Step 1. */
|
||||
var O = %ToObject(this);
|
||||
|
||||
/* Steps 2-3. */
|
||||
var len = TO_UINT32(O.length);
|
||||
|
||||
/* Step 4. */
|
||||
if (arguments.length === 0)
|
||||
%ThrowError(JSMSG_MISSING_FUN_ARG, 0, 'Array.prototype.every');
|
||||
if (!IsCallable(callbackfn))
|
||||
%ThrowError(JSMSG_NOT_FUNCTION, %_DecompileArg(0, callbackfn));
|
||||
|
||||
/* Step 5. */
|
||||
var T = arguments.length > 1 ? arguments[1] : void 0;
|
||||
|
||||
/* Steps 6-7. */
|
||||
/* Steps a (implicit), and d. */
|
||||
for (var k = 0; k < len; k++) {
|
||||
/* Step b */
|
||||
if (k in O) {
|
||||
/* Step c. */
|
||||
if (!%_CallFunction(T, O[k], k, O, callbackfn))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* Step 8. */
|
||||
return true;
|
||||
}
|
||||
|
||||
function ArrayStaticEvery(list, callbackfn/*, thisArg*/) {
|
||||
if (arguments.length < 2)
|
||||
%ThrowError(JSMSG_MISSING_FUN_ARG, 0, 'Array.every');
|
||||
if (!IsCallable(callbackfn))
|
||||
%ThrowError(JSMSG_NOT_FUNCTION, %_DecompileArg(1, callbackfn));
|
||||
var T = arguments.length > 2 ? arguments[2] : void 0;
|
||||
return %_CallFunction(list, callbackfn, T, ArrayEvery);
|
||||
}
|
||||
|
||||
/* ES5 15.4.4.17. */
|
||||
function ArraySome(callbackfn/*, thisArg*/) {
|
||||
/* Step 1. */
|
||||
var O = %ToObject(this);
|
||||
|
||||
/* Steps 2-3. */
|
||||
var len = TO_UINT32(O.length);
|
||||
|
||||
/* Step 4. */
|
||||
if (arguments.length === 0)
|
||||
%ThrowError(JSMSG_MISSING_FUN_ARG, 0, 'Array.prototype.some');
|
||||
if (!IsCallable(callbackfn))
|
||||
%ThrowError(JSMSG_NOT_FUNCTION, %_DecompileArg(0, callbackfn));
|
||||
|
||||
/* Step 5. */
|
||||
var T = arguments.length > 1 ? arguments[1] : void 0;
|
||||
|
||||
/* Steps 6-7. */
|
||||
/* Steps a (implicit), and d. */
|
||||
for (var k = 0; k < len; k++) {
|
||||
/* Step b */
|
||||
if (k in O) {
|
||||
/* Step c. */
|
||||
if (%_CallFunction(T, O[k], k, O, callbackfn))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/* Step 8. */
|
||||
return false;
|
||||
}
|
||||
|
||||
function ArrayStaticSome(list, callbackfn/*, thisArg*/) {
|
||||
if (arguments.length < 2)
|
||||
%ThrowError(JSMSG_MISSING_FUN_ARG, 0, 'Array.some');
|
||||
if (!IsCallable(callbackfn))
|
||||
%ThrowError(JSMSG_NOT_FUNCTION, %_DecompileArg(1, callbackfn));
|
||||
var T = arguments.length > 2 ? arguments[2] : void 0;
|
||||
return %_CallFunction(list, callbackfn, T, ArraySome);
|
||||
}
|
||||
|
||||
/* ES5 15.4.4.18. */
|
||||
function ArrayForEach(callbackfn/*, thisArg*/) {
|
||||
/* Step 1. */
|
||||
var O = %ToObject(this);
|
||||
|
||||
/* Steps 2-3. */
|
||||
var len = TO_UINT32(O.length);
|
||||
|
||||
/* Step 4. */
|
||||
if (arguments.length === 0)
|
||||
%ThrowError(JSMSG_MISSING_FUN_ARG, 0, 'Array.prototype.forEach');
|
||||
if (!IsCallable(callbackfn))
|
||||
%ThrowError(JSMSG_NOT_FUNCTION, %_DecompileArg(0, callbackfn));
|
||||
|
||||
/* Step 5. */
|
||||
var T = arguments.length > 1 ? arguments[1] : void 0;
|
||||
|
||||
/* Steps 6-7. */
|
||||
/* Steps a (implicit), and d. */
|
||||
for (var k = 0; k < len; k++) {
|
||||
/* Step b */
|
||||
if (k in O) {
|
||||
/* Step c. */
|
||||
%_CallFunction(T, O[k], k, O, callbackfn);
|
||||
}
|
||||
}
|
||||
|
||||
/* Step 8. */
|
||||
return void 0;
|
||||
}
|
||||
|
||||
function ArrayStaticForEach(list, callbackfn/*, thisArg*/) {
|
||||
if (arguments.length < 2)
|
||||
%ThrowError(JSMSG_MISSING_FUN_ARG, 0, 'Array.forEach');
|
||||
if (!IsCallable(callbackfn))
|
||||
%ThrowError(JSMSG_NOT_FUNCTION, %_DecompileArg(1, callbackfn));
|
||||
var T = arguments.length > 2 ? arguments[2] : void 0;
|
||||
%_CallFunction(list, callbackfn, T, ArrayForEach);
|
||||
}
|
||||
|
||||
/* ES5 15.4.4.21. */
|
||||
function ArrayReduce(callbackfn/*, initialValue*/) {
|
||||
/* Step 1. */
|
||||
var O = %ToObject(this);
|
||||
|
||||
/* Steps 2-3. */
|
||||
var len = TO_UINT32(O.length);
|
||||
|
||||
/* Step 4. */
|
||||
if (arguments.length === 0)
|
||||
%ThrowError(JSMSG_MISSING_FUN_ARG, 0, 'Array.prototype.reduce');
|
||||
if (!IsCallable(callbackfn))
|
||||
%ThrowError(JSMSG_NOT_FUNCTION, %_DecompileArg(0, callbackfn));
|
||||
|
||||
/* Step 6. */
|
||||
var k = 0;
|
||||
|
||||
/* Steps 5, 7-8. */
|
||||
var accumulator;
|
||||
if (arguments.length > 1) {
|
||||
accumulator = arguments[1];
|
||||
} else {
|
||||
/* Step 5. */
|
||||
if (len === 0)
|
||||
%ThrowError(JSMSG_EMPTY_ARRAY_REDUCE);
|
||||
var kPresent = false;
|
||||
for (; k < len; k++) {
|
||||
if (k in O) {
|
||||
accumulator = O[k];
|
||||
kPresent = true;
|
||||
k++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!kPresent)
|
||||
%ThrowError(JSMSG_EMPTY_ARRAY_REDUCE);
|
||||
}
|
||||
|
||||
/* Step 9. */
|
||||
/* Steps a (implicit), and d. */
|
||||
for (; k < len; k++) {
|
||||
/* Step b */
|
||||
if (k in O) {
|
||||
/* Step c. */
|
||||
accumulator = callbackfn(accumulator, O[k], k, O);
|
||||
}
|
||||
}
|
||||
|
||||
/* Step 10. */
|
||||
return accumulator;
|
||||
}
|
||||
|
||||
function ArrayStaticReduce(list, callbackfn) {
|
||||
if (arguments.length < 2)
|
||||
%ThrowError(JSMSG_MISSING_FUN_ARG, 0, 'Array.reduce');
|
||||
if (!IsCallable(callbackfn))
|
||||
%ThrowError(JSMSG_NOT_FUNCTION, %_DecompileArg(1, callbackfn));
|
||||
if (arguments.length > 2)
|
||||
return %_CallFunction(list, callbackfn, arguments[2], ArrayReduce);
|
||||
else
|
||||
return %_CallFunction(list, callbackfn, ArrayReduce);
|
||||
}
|
||||
|
||||
/* ES5 15.4.4.22. */
|
||||
function ArrayReduceRight(callbackfn/*, initialValue*/) {
|
||||
/* Step 1. */
|
||||
var O = %ToObject(this);
|
||||
|
||||
/* Steps 2-3. */
|
||||
var len = TO_UINT32(O.length);
|
||||
|
||||
/* Step 4. */
|
||||
if (arguments.length === 0)
|
||||
%ThrowError(JSMSG_MISSING_FUN_ARG, 0, 'Array.prototype.reduce');
|
||||
if (!IsCallable(callbackfn))
|
||||
%ThrowError(JSMSG_NOT_FUNCTION, %_DecompileArg(0, callbackfn));
|
||||
|
||||
/* Step 6. */
|
||||
var k = len - 1;
|
||||
|
||||
/* Steps 5, 7-8. */
|
||||
var accumulator;
|
||||
if (arguments.length > 1) {
|
||||
accumulator = arguments[1];
|
||||
} else {
|
||||
/* Step 5. */
|
||||
if (len === 0)
|
||||
%ThrowError(JSMSG_EMPTY_ARRAY_REDUCE);
|
||||
var kPresent = false;
|
||||
for (; k >= 0; k--) {
|
||||
if (k in O) {
|
||||
accumulator = O[k];
|
||||
kPresent = true;
|
||||
k--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!kPresent)
|
||||
%ThrowError(JSMSG_EMPTY_ARRAY_REDUCE);
|
||||
}
|
||||
|
||||
/* Step 9. */
|
||||
/* Steps a (implicit), and d. */
|
||||
for (; k >= 0; k--) {
|
||||
/* Step b */
|
||||
if (k in O) {
|
||||
/* Step c. */
|
||||
accumulator = callbackfn(accumulator, O[k], k, O);
|
||||
}
|
||||
}
|
||||
|
||||
/* Step 10. */
|
||||
return accumulator;
|
||||
}
|
||||
|
||||
function ArrayStaticReduceRight(list, callbackfn) {
|
||||
if (arguments.length < 2)
|
||||
%ThrowError(JSMSG_MISSING_FUN_ARG, 0, 'Array.reduceRight');
|
||||
if (!IsCallable(callbackfn))
|
||||
%ThrowError(JSMSG_NOT_FUNCTION, %_DecompileArg(1, callbackfn));
|
||||
if (arguments.length > 2)
|
||||
return %_CallFunction(list, callbackfn, arguments[2], ArrayReduceRight);
|
||||
else
|
||||
return %_CallFunction(list, callbackfn, ArrayReduceRight);
|
||||
}
|
||||
|
|
|
@ -85,7 +85,7 @@ GetBailedJSScript(JSContext *cx)
|
|||
switch (GetCalleeTokenTag(frame->calleeToken())) {
|
||||
case CalleeToken_Function: {
|
||||
JSFunction *fun = CalleeTokenToFunction(frame->calleeToken());
|
||||
return fun->script().get(nogc);
|
||||
return fun->nonLazyScript().get(nogc);
|
||||
}
|
||||
case CalleeToken_Script:
|
||||
return CalleeTokenToScript(frame->calleeToken());
|
||||
|
@ -197,7 +197,7 @@ PushInlinedFrame(JSContext *cx, StackFrame *callerFrame)
|
|||
const Value &calleeVal = regs.sp[-callerArgc - 2];
|
||||
|
||||
RootedFunction fun(cx, calleeVal.toObject().toFunction());
|
||||
RootedScript script(cx, fun->script());
|
||||
RootedScript script(cx, fun->nonLazyScript());
|
||||
CallArgs inlineArgs = CallArgsFromSp(callerArgc, regs.sp);
|
||||
|
||||
// Bump the stack pointer to make it look like the inline args have been pushed, but they will
|
||||
|
|
|
@ -311,7 +311,7 @@ CodeGenerator::visitLambda(LLambda *lir)
|
|||
|
||||
JS_STATIC_ASSERT(offsetof(JSFunction, flags) == offsetof(JSFunction, nargs) + 2);
|
||||
masm.store32(Imm32(u.word), Address(output, offsetof(JSFunction, nargs)));
|
||||
masm.storePtr(ImmGCPtr(fun->script().unsafeGet()),
|
||||
masm.storePtr(ImmGCPtr(fun->nonLazyScript().unsafeGet()),
|
||||
Address(output, JSFunction::offsetOfNativeOrScript()));
|
||||
masm.storePtr(scopeChain, Address(output, JSFunction::offsetOfEnvironment()));
|
||||
masm.storePtr(ImmGCPtr(fun->displayAtom()), Address(output, JSFunction::offsetOfAtom()));
|
||||
|
@ -926,7 +926,7 @@ CodeGenerator::visitCallKnown(LCallKnown *call)
|
|||
|
||||
// If the function is known to be uncompilable, only emit the call to InvokeFunction.
|
||||
ExecutionMode executionMode = gen->info().executionMode();
|
||||
RootedScript targetScript(cx, target->script());
|
||||
RootedScript targetScript(cx, target->nonLazyScript());
|
||||
if (GetIonScript(targetScript, executionMode) == ION_DISABLED_SCRIPT) {
|
||||
if (!emitCallInvokeFunction(call, calleereg, call->numActualArgs(), unusedStack))
|
||||
return false;
|
||||
|
|
|
@ -54,7 +54,7 @@ static inline bool CanIonCompile(JSContext *cx, HandleFunction fun, ExecutionMod
|
|||
{
|
||||
if (!fun->isInterpreted())
|
||||
return false;
|
||||
RootedScript script(cx, fun->script());
|
||||
RootedScript script(cx, fun->nonLazyScript());
|
||||
return CanIonCompile(script, cmode);
|
||||
}
|
||||
|
||||
|
|
|
@ -1564,7 +1564,7 @@ ion::FastInvoke(JSContext *cx, HandleFunction fun, CallArgsList &args)
|
|||
{
|
||||
JS_CHECK_RECURSION(cx, return IonExec_Error);
|
||||
|
||||
RootedScript script(cx, fun->script());
|
||||
RootedScript script(cx, fun->nonLazyScript());
|
||||
IonScript *ion = script->ionScript();
|
||||
IonCode *code = ion->method();
|
||||
void *jitcode = code->raw();
|
||||
|
|
|
@ -204,7 +204,7 @@ IonBuilder::canInlineTarget(JSFunction *target)
|
|||
return false;
|
||||
}
|
||||
|
||||
RootedScript inlineScript(cx, target->script());
|
||||
RootedScript inlineScript(cx, target->nonLazyScript());
|
||||
ExecutionMode executionMode = info().executionMode();
|
||||
if (!CanIonCompile(inlineScript, executionMode)) {
|
||||
IonSpew(IonSpew_Inlining, "Cannot inline due to disable Ion compilation");
|
||||
|
@ -2835,7 +2835,7 @@ IonBuilder::jsop_call_inline(HandleFunction callee, uint32 argc, bool constructi
|
|||
|
||||
// Compilation information is allocated for the duration of the current tempLifoAlloc
|
||||
// lifetime.
|
||||
RootedScript calleeScript(cx, callee->script());
|
||||
RootedScript calleeScript(cx, callee->nonLazyScript());
|
||||
CompileInfo *info = cx->tempLifoAlloc().new_<CompileInfo>(calleeScript.get(), callee,
|
||||
(jsbytecode *)NULL, constructing,
|
||||
SequentialExecution);
|
||||
|
@ -2930,7 +2930,7 @@ IonBuilder::makeInliningDecision(AutoObjectVector &targets, uint32 argc)
|
|||
if (!target->isInterpreted())
|
||||
return false;
|
||||
|
||||
script = target->script();
|
||||
script = target->nonLazyScript();
|
||||
uint32_t calleeUses = script->getUseCount();
|
||||
|
||||
if (target->nargs < argc) {
|
||||
|
@ -3549,7 +3549,7 @@ IonBuilder::createThisScriptedSingleton(HandleFunction target, HandleObject prot
|
|||
types::TypeObject *type = proto->getNewType(cx, target);
|
||||
if (!type)
|
||||
return NULL;
|
||||
if (!types::TypeScript::ThisTypes(target->script().unsafeGet())->hasType(types::Type::ObjectType(type)))
|
||||
if (!types::TypeScript::ThisTypes(target->nonLazyScript().unsafeGet())->hasType(types::Type::ObjectType(type)))
|
||||
return NULL;
|
||||
|
||||
RootedObject templateObject(cx, js_CreateThisForFunctionWithProto(cx, target, proto));
|
||||
|
|
|
@ -1624,7 +1624,7 @@ GenerateScopeChainGuard(MacroAssembler &masm, JSObject *scopeObj,
|
|||
CallObject *callObj = &scopeObj->asCall();
|
||||
if (!callObj->isForEval()) {
|
||||
RawFunction fun = &callObj->callee();
|
||||
RawScript script = fun->script().get(nogc);
|
||||
RawScript script = fun->nonLazyScript().get(nogc);
|
||||
if (!script->funHasExtensibleScope)
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -441,7 +441,7 @@ MarkIonJSFrame(JSTracer *trc, const IonFrameIterator &frame)
|
|||
// is now NULL or recompiled). Manually trace it here.
|
||||
IonScript::Trace(trc, ionScript);
|
||||
} else if (CalleeTokenIsFunction(layout->calleeToken())) {
|
||||
ionScript = CalleeTokenToFunction(layout->calleeToken())->script()->ion;
|
||||
ionScript = CalleeTokenToFunction(layout->calleeToken())->nonLazyScript()->ion;
|
||||
} else {
|
||||
ionScript = CalleeTokenToScript(layout->calleeToken())->ion;
|
||||
}
|
||||
|
@ -926,7 +926,7 @@ InlineFrameIterator::findNextFrame()
|
|||
si_.nextFrame();
|
||||
|
||||
callee_ = funval.toObject().toFunction();
|
||||
script_ = callee_->script().get(nogc);
|
||||
script_ = callee_->nonLazyScript().get(nogc);
|
||||
pc_ = script_->code + si_.pcOffset();
|
||||
}
|
||||
|
||||
|
|
|
@ -72,7 +72,7 @@ ScriptFromCalleeToken(CalleeToken token)
|
|||
case CalleeToken_Script:
|
||||
return CalleeTokenToScript(token);
|
||||
case CalleeToken_Function:
|
||||
return CalleeTokenToFunction(token)->script().get(nogc);
|
||||
return CalleeTokenToFunction(token)->nonLazyScript().get(nogc);
|
||||
}
|
||||
JS_NOT_REACHED("invalid callee token tag");
|
||||
return NULL;
|
||||
|
|
|
@ -556,7 +556,7 @@ bool
|
|||
TypeInferenceOracle::canEnterInlinedFunction(JSFunction *target)
|
||||
{
|
||||
AssertCanGC();
|
||||
RootedScript script(cx, target->script());
|
||||
RootedScript script(cx, target->nonLazyScript());
|
||||
if (!script->hasAnalysis() || !script->analysis()->ranInference())
|
||||
return false;
|
||||
|
||||
|
|
|
@ -41,8 +41,8 @@ static inline bool
|
|||
ShouldMonitorReturnType(JSFunction *fun)
|
||||
{
|
||||
return fun->isInterpreted() &&
|
||||
(!fun->script()->hasAnalysis() ||
|
||||
!fun->script()->analysis()->ranInference());
|
||||
(!fun->nonLazyScript()->hasAnalysis() ||
|
||||
!fun->nonLazyScript()->analysis()->ranInference());
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -50,18 +50,16 @@ InvokeFunction(JSContext *cx, JSFunction *fun, uint32 argc, Value *argv, Value *
|
|||
{
|
||||
Value fval = ObjectValue(*fun);
|
||||
|
||||
if (fun->isInterpretedLazy()) {
|
||||
Rooted<JSFunction*> rootedFun(cx, fun);
|
||||
if (!InitializeLazyFunctionScript(cx, rootedFun))
|
||||
return false;
|
||||
}
|
||||
|
||||
// In order to prevent massive bouncing between Ion and JM, see if we keep
|
||||
// hitting functions that are uncompilable.
|
||||
|
||||
if (fun->isInterpreted() && !fun->script()->canIonCompile()) {
|
||||
if (fun->isInterpreted()) {
|
||||
if (fun->isInterpretedLazy() && !fun->getOrCreateScript(cx).unsafeGet())
|
||||
return false;
|
||||
if (!fun->nonLazyScript()->canIonCompile()) {
|
||||
JSScript *script = GetTopIonJSScript(cx);
|
||||
if (script->hasIonScript() && ++script->ion->slowCallCount >= js_IonOptions.slowCallLimit) {
|
||||
if (script->hasIonScript() &&
|
||||
++script->ion->slowCallCount >= js_IonOptions.slowCallLimit)
|
||||
{
|
||||
AutoFlushCache afc("InvokeFunction");
|
||||
|
||||
// Poison the script so we don't try to run it again. This will
|
||||
|
@ -69,6 +67,7 @@ InvokeFunction(JSContext *cx, JSFunction *fun, uint32 argc, Value *argv, Value *
|
|||
ForbidCompilation(cx, script);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TI will return false for monitorReturnTypes, meaning there is no
|
||||
// TypeBarrier or Monitor instruction following this. However, we need to
|
||||
|
@ -98,9 +97,9 @@ InvokeConstructor(JSContext *cx, JSObject *obj, uint32 argc, Value *argv, Value
|
|||
bool needsMonitor;
|
||||
|
||||
if (obj->isFunction()) {
|
||||
if (obj->toFunction()->isInterpretedLazy()) {
|
||||
Rooted<JSFunction*> rootedFun(cx, obj->toFunction());
|
||||
if (!InitializeLazyFunctionScript(cx, rootedFun))
|
||||
if (obj->toFunction()->isInterpretedLazy() &&
|
||||
!obj->toFunction()->getOrCreateScript(cx).unsafeGet())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
needsMonitor = ShouldMonitorReturnType(obj->toFunction());
|
||||
|
|
|
@ -4871,8 +4871,8 @@ JS_CloneFunctionObject(JSContext *cx, JSObject *funobjArg, JSRawObject parentArg
|
|||
* script, we cannot clone it without breaking the compiler's assumptions.
|
||||
*/
|
||||
RootedFunction fun(cx, funobj->toFunction());
|
||||
if (fun->isInterpreted() && (fun->script()->enclosingStaticScope() ||
|
||||
(fun->script()->compileAndGo && !parent->isGlobal())))
|
||||
if (fun->isInterpreted() && (fun->nonLazyScript()->enclosingStaticScope() ||
|
||||
(fun->nonLazyScript()->compileAndGo && !parent->isGlobal())))
|
||||
{
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_CLONE_FUNOBJ_SCOPE);
|
||||
return NULL;
|
||||
|
|
|
@ -2938,228 +2938,6 @@ array_slice(JSContext *cx, unsigned argc, Value *vp)
|
|||
return JS_TRUE;
|
||||
}
|
||||
|
||||
enum IndexOfKind {
|
||||
IndexOf,
|
||||
LastIndexOf
|
||||
};
|
||||
|
||||
static JSBool
|
||||
array_indexOfHelper(JSContext *cx, IndexOfKind mode, CallArgs &args)
|
||||
{
|
||||
uint32_t length, i, stop;
|
||||
int direction;
|
||||
JSBool hole;
|
||||
|
||||
RootedValue tosearch(cx), elt(cx);
|
||||
|
||||
RootedObject obj(cx, ToObject(cx, args.thisv()));
|
||||
if (!obj)
|
||||
return false;
|
||||
if (!GetLengthProperty(cx, obj, &length))
|
||||
return JS_FALSE;
|
||||
if (length == 0)
|
||||
goto not_found;
|
||||
|
||||
if (args.length() <= 1) {
|
||||
i = (mode == LastIndexOf) ? length - 1 : 0;
|
||||
tosearch = (args.length() != 0) ? args[0] : UndefinedValue();
|
||||
} else {
|
||||
double start;
|
||||
|
||||
tosearch = args[0];
|
||||
if (!ToInteger(cx, args[1], &start))
|
||||
return false;
|
||||
if (start < 0) {
|
||||
start += length;
|
||||
if (start < 0) {
|
||||
if (mode == LastIndexOf)
|
||||
goto not_found;
|
||||
i = 0;
|
||||
} else {
|
||||
i = (uint32_t)start;
|
||||
}
|
||||
} else if (start >= length) {
|
||||
if (mode == IndexOf)
|
||||
goto not_found;
|
||||
i = length - 1;
|
||||
} else {
|
||||
i = (uint32_t)start;
|
||||
}
|
||||
}
|
||||
|
||||
if (mode == LastIndexOf) {
|
||||
stop = 0;
|
||||
direction = -1;
|
||||
} else {
|
||||
stop = length - 1;
|
||||
direction = 1;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
if (!JS_CHECK_OPERATION_LIMIT(cx) ||
|
||||
!GetElement(cx, obj, (uint32_t)i, &hole, &elt)) {
|
||||
return JS_FALSE;
|
||||
}
|
||||
if (!hole) {
|
||||
bool equal;
|
||||
if (!StrictlyEqual(cx, elt, tosearch, &equal))
|
||||
return false;
|
||||
if (equal) {
|
||||
args.rval().setNumber(i);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (i == stop)
|
||||
goto not_found;
|
||||
i += direction;
|
||||
}
|
||||
|
||||
not_found:
|
||||
args.rval().setInt32(-1);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
array_indexOf(JSContext *cx, unsigned argc, Value *vp)
|
||||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
return array_indexOfHelper(cx, IndexOf, args);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
array_lastIndexOf(JSContext *cx, unsigned argc, Value *vp)
|
||||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
return array_indexOfHelper(cx, LastIndexOf, args);
|
||||
}
|
||||
|
||||
/* ECMA 15.4.4.16-15.4.4.18. */
|
||||
class ArrayForEachBehavior
|
||||
{
|
||||
public:
|
||||
static bool shouldExit(MutableHandleValue callbackRval, MutableHandleValue rval) { return false; }
|
||||
static Value lateExitValue() { return UndefinedValue(); }
|
||||
};
|
||||
|
||||
class ArrayEveryBehavior
|
||||
{
|
||||
public:
|
||||
static bool shouldExit(MutableHandleValue callbackRval, MutableHandleValue rval)
|
||||
{
|
||||
if (!ToBoolean(callbackRval)) {
|
||||
rval.setBoolean(false);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
static Value lateExitValue() { return BooleanValue(true); }
|
||||
};
|
||||
|
||||
class ArraySomeBehavior
|
||||
{
|
||||
public:
|
||||
static bool shouldExit(MutableHandleValue callbackRval, MutableHandleValue rval)
|
||||
{
|
||||
if (ToBoolean(callbackRval)) {
|
||||
rval.setBoolean(true);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
static Value lateExitValue() { return BooleanValue(false); }
|
||||
};
|
||||
|
||||
template <class Behavior>
|
||||
static inline bool
|
||||
array_readonlyCommon(JSContext *cx, CallArgs &args)
|
||||
{
|
||||
/* Step 1. */
|
||||
RootedObject obj(cx, ToObject(cx, args.thisv()));
|
||||
if (!obj)
|
||||
return false;
|
||||
|
||||
/* Step 2-3. */
|
||||
uint32_t len;
|
||||
if (!GetLengthProperty(cx, obj, &len))
|
||||
return false;
|
||||
|
||||
/* Step 4. */
|
||||
if (args.length() == 0) {
|
||||
js_ReportMissingArg(cx, args.calleev(), 0);
|
||||
return false;
|
||||
}
|
||||
RootedObject callable(cx, ValueToCallable(cx, &args[0]));
|
||||
if (!callable)
|
||||
return false;
|
||||
|
||||
/* Step 5. */
|
||||
RootedValue thisv(cx, args.length() >= 2 ? args[1] : UndefinedValue());
|
||||
|
||||
/* Step 6. */
|
||||
uint32_t k = 0;
|
||||
|
||||
/* Step 7. */
|
||||
RootedValue kValue(cx);
|
||||
FastInvokeGuard fig(cx, ObjectValue(*callable));
|
||||
InvokeArgsGuard &ag = fig.args();
|
||||
while (k < len) {
|
||||
if (!JS_CHECK_OPERATION_LIMIT(cx))
|
||||
return false;
|
||||
|
||||
/* Step a, b, and c.i. */
|
||||
JSBool kNotPresent;
|
||||
if (!GetElement(cx, obj, k, &kNotPresent, &kValue))
|
||||
return false;
|
||||
|
||||
/* Step c.ii-iii. */
|
||||
if (!kNotPresent) {
|
||||
if (!ag.pushed() && !cx->stack.pushInvokeArgs(cx, 3, &ag))
|
||||
return false;
|
||||
ag.setCallee(ObjectValue(*callable));
|
||||
ag.setThis(thisv);
|
||||
ag[0] = kValue;
|
||||
ag[1] = NumberValue(k);
|
||||
ag[2] = ObjectValue(*obj);
|
||||
if (!fig.invoke(cx))
|
||||
return false;
|
||||
|
||||
if (Behavior::shouldExit(ag.rval(), args.rval()))
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Step d. */
|
||||
k++;
|
||||
}
|
||||
|
||||
/* Step 8. */
|
||||
args.rval().set(Behavior::lateExitValue());
|
||||
return true;
|
||||
}
|
||||
|
||||
/* ES5 15.4.4.16. */
|
||||
static JSBool
|
||||
array_every(JSContext *cx, unsigned argc, Value *vp)
|
||||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
return array_readonlyCommon<ArrayEveryBehavior>(cx, args);
|
||||
}
|
||||
|
||||
/* ES5 15.4.4.17. */
|
||||
static JSBool
|
||||
array_some(JSContext *cx, unsigned argc, Value *vp)
|
||||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
return array_readonlyCommon<ArraySomeBehavior>(cx, args);
|
||||
}
|
||||
|
||||
/* ES5 15.4.4.18. */
|
||||
static JSBool
|
||||
array_forEach(JSContext *cx, unsigned argc, Value *vp)
|
||||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
return array_readonlyCommon<ArrayForEachBehavior>(cx, args);
|
||||
}
|
||||
|
||||
/* ES5 15.4.4.19. */
|
||||
static JSBool
|
||||
array_map(JSContext *cx, unsigned argc, Value *vp)
|
||||
|
@ -3322,137 +3100,6 @@ array_filter(JSContext *cx, unsigned argc, Value *vp)
|
|||
return true;
|
||||
}
|
||||
|
||||
/* ES5 15.4.4.21-15.4.4.22. */
|
||||
class ArrayReduceBehavior
|
||||
{
|
||||
public:
|
||||
static void initialize(uint32_t len, uint32_t *start, uint32_t *end, int32_t *step)
|
||||
{
|
||||
*start = 0;
|
||||
*step = 1;
|
||||
*end = len;
|
||||
}
|
||||
};
|
||||
|
||||
class ArrayReduceRightBehavior
|
||||
{
|
||||
public:
|
||||
static void initialize(uint32_t len, uint32_t *start, uint32_t *end, int32_t *step)
|
||||
{
|
||||
*start = len - 1;
|
||||
*step = -1;
|
||||
/*
|
||||
* We rely on (well defined) unsigned integer underflow to check our
|
||||
* end condition after visiting the full range (including 0).
|
||||
*/
|
||||
*end = UINT32_MAX;
|
||||
}
|
||||
};
|
||||
|
||||
template<class Behavior>
|
||||
static inline bool
|
||||
array_reduceCommon(JSContext *cx, CallArgs &args)
|
||||
{
|
||||
/* Step 1. */
|
||||
RootedObject obj(cx, ToObject(cx, args.thisv()));
|
||||
if (!obj)
|
||||
return false;
|
||||
|
||||
/* Step 2-3. */
|
||||
uint32_t len;
|
||||
if (!GetLengthProperty(cx, obj, &len))
|
||||
return false;
|
||||
|
||||
/* Step 4. */
|
||||
if (args.length() == 0) {
|
||||
js_ReportMissingArg(cx, args.calleev(), 0);
|
||||
return false;
|
||||
}
|
||||
RootedObject callable(cx, ValueToCallable(cx, &args[0]));
|
||||
if (!callable)
|
||||
return false;
|
||||
|
||||
/* Step 5. */
|
||||
if (len == 0 && args.length() < 2) {
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_EMPTY_ARRAY_REDUCE);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Step 6. */
|
||||
uint32_t k, end;
|
||||
int32_t step;
|
||||
Behavior::initialize(len, &k, &end, &step);
|
||||
|
||||
/* Step 7-8. */
|
||||
RootedValue accumulator(cx);
|
||||
if (args.length() >= 2) {
|
||||
accumulator = args[1];
|
||||
} else {
|
||||
JSBool kNotPresent = true;
|
||||
while (kNotPresent && k != end) {
|
||||
if (!GetElement(cx, obj, k, &kNotPresent, &accumulator))
|
||||
return false;
|
||||
k += step;
|
||||
}
|
||||
if (kNotPresent) {
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_EMPTY_ARRAY_REDUCE);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* Step 9. */
|
||||
RootedValue kValue(cx);
|
||||
FastInvokeGuard fig(cx, ObjectValue(*callable));
|
||||
InvokeArgsGuard &ag = fig.args();
|
||||
while (k != end) {
|
||||
if (!JS_CHECK_OPERATION_LIMIT(cx))
|
||||
return false;
|
||||
|
||||
/* Step a, b, and c.i. */
|
||||
JSBool kNotPresent;
|
||||
if (!GetElement(cx, obj, k, &kNotPresent, &kValue))
|
||||
return false;
|
||||
|
||||
/* Step c.ii. */
|
||||
if (!kNotPresent) {
|
||||
if (!ag.pushed() && !cx->stack.pushInvokeArgs(cx, 4, &ag))
|
||||
return false;
|
||||
ag.setCallee(ObjectValue(*callable));
|
||||
ag.setThis(UndefinedValue());
|
||||
ag[0] = accumulator;
|
||||
ag[1] = kValue;
|
||||
ag[2] = NumberValue(k);
|
||||
ag[3] = ObjectValue(*obj);
|
||||
if (!fig.invoke(cx))
|
||||
return false;
|
||||
accumulator = ag.rval();
|
||||
}
|
||||
|
||||
/* Step d. */
|
||||
k += step;
|
||||
}
|
||||
|
||||
/* Step 10. */
|
||||
args.rval().set(accumulator);
|
||||
return true;
|
||||
}
|
||||
|
||||
/* ES5 15.4.4.21. */
|
||||
static JSBool
|
||||
array_reduce(JSContext *cx, unsigned argc, Value *vp)
|
||||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
return array_reduceCommon<ArrayReduceBehavior>(cx, args);
|
||||
}
|
||||
|
||||
/* ES5 15.4.4.22. */
|
||||
static JSBool
|
||||
array_reduceRight(JSContext *cx, unsigned argc, Value *vp)
|
||||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
return array_reduceCommon<ArrayReduceRightBehavior>(cx, args);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
array_isArray(JSContext *cx, unsigned argc, Value *vp)
|
||||
{
|
||||
|
@ -3485,15 +3132,15 @@ static JSFunctionSpec array_methods[] = {
|
|||
JS_FN("concat", array_concat, 1,JSFUN_GENERIC_NATIVE),
|
||||
JS_FN("slice", array_slice, 2,JSFUN_GENERIC_NATIVE),
|
||||
|
||||
JS_FN("indexOf", array_indexOf, 1,JSFUN_GENERIC_NATIVE),
|
||||
JS_FN("lastIndexOf", array_lastIndexOf, 1,JSFUN_GENERIC_NATIVE),
|
||||
JS_FN("forEach", array_forEach, 1,JSFUN_GENERIC_NATIVE),
|
||||
{"lastIndexOf", {NULL, NULL}, 1,0, "ArrayLastIndexOf"},
|
||||
{"indexOf", {NULL, NULL}, 1,0, "ArrayIndexOf"},
|
||||
{"forEach", {NULL, NULL}, 1,0, "ArrayForEach"},
|
||||
JS_FN("map", array_map, 1,JSFUN_GENERIC_NATIVE),
|
||||
JS_FN("reduce", array_reduce, 1,JSFUN_GENERIC_NATIVE),
|
||||
JS_FN("reduceRight", array_reduceRight, 1,JSFUN_GENERIC_NATIVE),
|
||||
{"reduce", {NULL, NULL}, 1,0, "ArrayReduce"},
|
||||
{"reduceRight", {NULL, NULL}, 1,0, "ArrayReduceRight"},
|
||||
JS_FN("filter", array_filter, 1,JSFUN_GENERIC_NATIVE),
|
||||
JS_FN("some", array_some, 1,JSFUN_GENERIC_NATIVE),
|
||||
JS_FN("every", array_every, 1,JSFUN_GENERIC_NATIVE),
|
||||
{"some", {NULL, NULL}, 1,0, "ArraySome"},
|
||||
{"every", {NULL, NULL}, 1,0, "ArrayEvery"},
|
||||
|
||||
JS_FN("iterator", JS_ArrayIterator, 0,0),
|
||||
JS_FS_END
|
||||
|
@ -3501,6 +3148,13 @@ static JSFunctionSpec array_methods[] = {
|
|||
|
||||
static JSFunctionSpec array_static_methods[] = {
|
||||
JS_FN("isArray", array_isArray, 1,0),
|
||||
{"lastIndexOf", {NULL, NULL}, 2,0, "ArrayStaticLastIndexOf"},
|
||||
{"indexOf", {NULL, NULL}, 2,0, "ArrayStaticIndexOf"},
|
||||
{"forEach", {NULL, NULL}, 2,0, "ArrayStaticForEach"},
|
||||
{"every", {NULL, NULL}, 2,0, "ArrayStaticEvery"},
|
||||
{"some", {NULL, NULL}, 2,0, "ArrayStaticSome"},
|
||||
{"reduce", {NULL, NULL}, 2,0, "ArrayStaticReduce"},
|
||||
{"reduceRight", {NULL, NULL}, 2,0, "ArrayStaticReduceRight"},
|
||||
JS_FS_END
|
||||
};
|
||||
|
||||
|
|
|
@ -431,7 +431,7 @@ JSRuntime::cloneSelfHostedFunctionScript(JSContext *cx, Handle<PropertyName*> na
|
|||
return false;
|
||||
|
||||
RootedFunction sourceFun(cx, funVal.toObject().toFunction());
|
||||
Rooted<JSScript*> sourceScript(cx, sourceFun->script());
|
||||
Rooted<JSScript*> sourceScript(cx, sourceFun->nonLazyScript());
|
||||
JS_ASSERT(!sourceScript->enclosingStaticScope());
|
||||
RawScript cscript = CloneScript(cx, NullPtr(), targetFun, sourceScript);
|
||||
if (!cscript)
|
||||
|
|
|
@ -401,13 +401,13 @@ JS_GetFunctionArgumentCount(JSContext *cx, JSFunction *fun)
|
|||
JS_PUBLIC_API(JSBool)
|
||||
JS_FunctionHasLocalNames(JSContext *cx, JSFunction *fun)
|
||||
{
|
||||
return fun->script()->bindings.count() > 0;
|
||||
return fun->nonLazyScript()->bindings.count() > 0;
|
||||
}
|
||||
|
||||
extern JS_PUBLIC_API(uintptr_t *)
|
||||
JS_GetFunctionLocalNameArray(JSContext *cx, JSFunction *fun, void **markp)
|
||||
{
|
||||
RootedScript script(cx, fun->script());
|
||||
RootedScript script(cx, fun->nonLazyScript());
|
||||
BindingVector bindings(cx);
|
||||
if (!FillBindingVector(script, &bindings))
|
||||
return NULL;
|
||||
|
@ -449,7 +449,7 @@ JS_PUBLIC_API(JSScript *)
|
|||
JS_GetFunctionScript(JSContext *cx, JSFunction *fun)
|
||||
{
|
||||
AutoAssertNoGC nogc;
|
||||
return fun->maybeScript().get(nogc);
|
||||
return fun->maybeNonLazyScript().get(nogc);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSNative)
|
||||
|
@ -1013,7 +1013,7 @@ JS_GetFunctionTotalSize(JSContext *cx, JSFunction *fun)
|
|||
size_t nbytes = sizeof *fun;
|
||||
nbytes += JS_GetObjectTotalSize(cx, fun);
|
||||
if (fun->isInterpreted())
|
||||
nbytes += JS_GetScriptTotalSize(cx, fun->script().get(nogc));
|
||||
nbytes += JS_GetScriptTotalSize(cx, fun->nonLazyScript().get(nogc));
|
||||
if (fun->displayAtom())
|
||||
nbytes += GetAtomTotalSize(cx, fun->displayAtom());
|
||||
return nbytes;
|
||||
|
|
|
@ -368,7 +368,7 @@ js::IsObjectInContextCompartment(RawObject obj, const JSContext *cx)
|
|||
JS_FRIEND_API(bool)
|
||||
js::IsOriginalScriptFunction(JSFunction *fun)
|
||||
{
|
||||
return fun->script()->function() == fun;
|
||||
return fun->nonLazyScript()->function() == fun;
|
||||
}
|
||||
|
||||
JS_FRIEND_API(JSScript *)
|
||||
|
@ -382,7 +382,7 @@ js::GetOutermostEnclosingFunctionOfScriptedCaller(JSContext *cx)
|
|||
return NULL;
|
||||
|
||||
JSFunction *scriptedCaller = fp->fun();
|
||||
RootedScript outermost(cx, scriptedCaller->script());
|
||||
RootedScript outermost(cx, scriptedCaller->nonLazyScript());
|
||||
for (StaticScopeIter i(scriptedCaller); !i.done(); i++) {
|
||||
if (i.type() == StaticScopeIter::FUNCTION)
|
||||
outermost = i.funScript();
|
||||
|
|
|
@ -91,7 +91,7 @@ fun_getProperty(JSContext *cx, HandleObject obj_, HandleId id, MutableHandleValu
|
|||
* check any calls that were inlined.
|
||||
*/
|
||||
if (fun->isInterpreted()) {
|
||||
fun->script()->uninlineable = true;
|
||||
fun->getOrCreateScript(cx)->uninlineable = true;
|
||||
MarkTypeObjectFlags(cx, fun, OBJECT_FLAG_UNINLINEABLE);
|
||||
}
|
||||
|
||||
|
@ -156,7 +156,7 @@ fun_getProperty(JSContext *cx, HandleObject obj_, HandleId id, MutableHandleValu
|
|||
if (inlined) {
|
||||
mjit::JITChunk *chunk = fp->prev()->jit()->chunk(prevpc);
|
||||
RawFunction fun = chunk->inlineFrames()[inlined->inlineIndex].fun;
|
||||
fun->script()->uninlineable = true;
|
||||
fun->nonLazyScript()->uninlineable = true;
|
||||
MarkTypeObjectFlags(cx, fun, OBJECT_FLAG_UNINLINEABLE);
|
||||
}
|
||||
}
|
||||
|
@ -321,7 +321,7 @@ fun_resolve(JSContext *cx, HandleObject obj, HandleId id, unsigned flags,
|
|||
RootedValue v(cx);
|
||||
if (JSID_IS_ATOM(id, cx->names().length)) {
|
||||
//FIXME: bug 810715 - deal with lazy interpreted functions with default args
|
||||
uint16_t defaults = fun->hasScript() ? fun->script()->ndefaults : 0;
|
||||
uint16_t defaults = fun->hasScript() ? fun->nonLazyScript()->ndefaults : 0;
|
||||
v.setInt32(fun->nargs - defaults - fun->hasRest());
|
||||
} else {
|
||||
v.setString(fun->atom() == NULL ? cx->runtime->emptyString : fun->atom());
|
||||
|
@ -344,7 +344,7 @@ fun_resolve(JSContext *cx, HandleObject obj, HandleId id, unsigned flags,
|
|||
PropertyOp getter;
|
||||
StrictPropertyOp setter;
|
||||
unsigned attrs = JSPROP_PERMANENT;
|
||||
if (fun->isInterpretedLazy() && !InitializeLazyFunctionScript(cx, fun))
|
||||
if (fun->isInterpretedLazy() && !fun->getOrCreateScript(cx).unsafeGet())
|
||||
return false;
|
||||
if (fun->isInterpreted() ? fun->inStrictMode() : fun->isBoundFunction()) {
|
||||
JSObject *throwTypeError = fun->global().getThrowTypeError();
|
||||
|
@ -398,7 +398,7 @@ js::XDRInterpretedFunction(XDRState<mode> *xdr, HandleObject enclosingScope, Han
|
|||
firstword = !!fun->atom();
|
||||
flagsword = (fun->nargs << 16) | fun->flags;
|
||||
atom = fun->atom();
|
||||
script = fun->script();
|
||||
script = fun->nonLazyScript();
|
||||
} else {
|
||||
fun = js_NewFunction(cx, NullPtr(), NULL, 0, JSFunction::INTERPRETED, NullPtr(), NullPtr());
|
||||
if (!fun)
|
||||
|
@ -425,8 +425,8 @@ js::XDRInterpretedFunction(XDRState<mode> *xdr, HandleObject enclosingScope, Han
|
|||
script->setFunction(fun);
|
||||
if (!JSFunction::setTypeForScriptedFunction(cx, fun))
|
||||
return false;
|
||||
JS_ASSERT(fun->nargs == fun->script()->bindings.numArgs());
|
||||
RootedScript script(cx, fun->script());
|
||||
JS_ASSERT(fun->nargs == fun->nonLazyScript()->bindings.numArgs());
|
||||
RootedScript script(cx, fun->nonLazyScript());
|
||||
js_CallNewScriptHook(cx, script, fun);
|
||||
objp.set(fun);
|
||||
}
|
||||
|
@ -452,7 +452,7 @@ js::CloneInterpretedFunction(JSContext *cx, HandleObject enclosingScope, HandleF
|
|||
if (!clone)
|
||||
return NULL;
|
||||
|
||||
RootedScript srcScript(cx, srcFun->script());
|
||||
RootedScript srcScript(cx, srcFun->nonLazyScript());
|
||||
RawScript clonedScript = CloneScript(cx, enclosingScope, clone, srcScript);
|
||||
if (!clonedScript)
|
||||
return NULL;
|
||||
|
@ -465,25 +465,11 @@ js::CloneInterpretedFunction(JSContext *cx, HandleObject enclosingScope, HandleF
|
|||
if (!JSFunction::setTypeForScriptedFunction(cx, clone))
|
||||
return NULL;
|
||||
|
||||
RootedScript cloneScript(cx, clone->script());
|
||||
RootedScript cloneScript(cx, clone->nonLazyScript());
|
||||
js_CallNewScriptHook(cx, cloneScript, clone);
|
||||
return clone;
|
||||
}
|
||||
|
||||
bool
|
||||
js::InitializeLazyFunctionScript(JSContext *cx, HandleFunction fun)
|
||||
{
|
||||
JS_ASSERT(fun->isInterpretedLazy());
|
||||
JSFunctionSpec *fs = static_cast<JSFunctionSpec *>(fun->getExtendedSlot(0).toPrivate());
|
||||
RootedAtom funAtom(cx, Atomize(cx, fs->selfHostedName, strlen(fs->selfHostedName)));
|
||||
if (!funAtom)
|
||||
return false;
|
||||
Rooted<PropertyName *> funName(cx, funAtom->asPropertyName());
|
||||
if (!cx->runtime->cloneSelfHostedFunctionScript(cx, funName, fun))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* [[HasInstance]] internal method for Function objects: fetch the .prototype
|
||||
* property of its 'this' parameter, and walks the prototype chain of v (only
|
||||
|
@ -575,7 +561,7 @@ FindBody(JSContext *cx, HandleFunction fun, StableCharPtr chars, size_t length,
|
|||
// We don't need principals, since those are only used for error reporting.
|
||||
CompileOptions options(cx);
|
||||
options.setFileAndLine("internal-findBody", 0)
|
||||
.setVersion(fun->script()->getVersion());
|
||||
.setVersion(fun->nonLazyScript()->getVersion());
|
||||
TokenStream ts(cx, options, chars, length, NULL);
|
||||
JS_ASSERT(chars[0] == '(');
|
||||
int nest = 0;
|
||||
|
@ -626,7 +612,7 @@ js::FunctionToString(JSContext *cx, HandleFunction fun, bool bodyOnly, bool lamb
|
|||
RootedScript script(cx);
|
||||
|
||||
if (fun->hasScript()) {
|
||||
script = fun->script();
|
||||
script = fun->nonLazyScript();
|
||||
if (script->isGeneratorExp) {
|
||||
if ((!bodyOnly && !out.append("function genexp() {")) ||
|
||||
!out.append("\n [generator expression]\n") ||
|
||||
|
@ -1057,6 +1043,19 @@ JSFunction::getBoundFunctionArgumentCount() const
|
|||
return getSlot(JSSLOT_BOUND_FUNCTION_ARGS_COUNT).toPrivateUint32();
|
||||
}
|
||||
|
||||
bool
|
||||
JSFunction::initializeLazyScript(JSContext *cx)
|
||||
{
|
||||
JS_ASSERT(isInterpretedLazy());
|
||||
JSFunctionSpec *fs = static_cast<JSFunctionSpec *>(getExtendedSlot(0).toPrivate());
|
||||
RootedAtom funAtom(cx, Atomize(cx, fs->selfHostedName, strlen(fs->selfHostedName)));
|
||||
if (!funAtom)
|
||||
return false;
|
||||
Rooted<PropertyName *> funName(cx, funAtom->asPropertyName());
|
||||
Rooted<JSFunction*> self(cx, this);
|
||||
return cx->runtime->cloneSelfHostedFunctionScript(cx, funName, self);
|
||||
}
|
||||
|
||||
/* ES5 15.3.4.5.1 and 15.3.4.5.2. */
|
||||
JSBool
|
||||
js::CallOrConstructBoundFunction(JSContext *cx, unsigned argc, Value *vp)
|
||||
|
@ -1116,7 +1115,7 @@ fun_isGenerator(JSContext *cx, unsigned argc, Value *vp)
|
|||
|
||||
bool result = false;
|
||||
if (fun->hasScript()) {
|
||||
RawScript script = fun->script().get(nogc);
|
||||
RawScript script = fun->nonLazyScript().get(nogc);
|
||||
JS_ASSERT(script->length != 0);
|
||||
result = script->isGenerator;
|
||||
}
|
||||
|
@ -1484,7 +1483,7 @@ js_CloneFunctionObject(JSContext *cx, HandleFunction fun, HandleObject parent,
|
|||
clone->nargs = fun->nargs;
|
||||
clone->flags = fun->flags & ~JSFunction::EXTENDED;
|
||||
if (fun->isInterpreted()) {
|
||||
clone->initScript(fun->script().unsafeGet());
|
||||
clone->initScript(fun->nonLazyScript().unsafeGet());
|
||||
clone->initEnvironment(parent);
|
||||
} else {
|
||||
clone->initNative(fun->native(), fun->jitInfo());
|
||||
|
@ -1517,7 +1516,7 @@ js_CloneFunctionObject(JSContext *cx, HandleFunction fun, HandleObject parent,
|
|||
* no enclosing lexical scope (only the global scope).
|
||||
*/
|
||||
if (clone->isInterpreted()) {
|
||||
RootedScript script(cx, clone->script());
|
||||
RootedScript script(cx, clone->nonLazyScript());
|
||||
JS_ASSERT(script->compartment() == fun->compartment());
|
||||
JS_ASSERT_IF(script->compartment() != cx->compartment,
|
||||
!script->enclosingStaticScope());
|
||||
|
@ -1535,7 +1534,7 @@ js_CloneFunctionObject(JSContext *cx, HandleFunction fun, HandleObject parent,
|
|||
|
||||
GlobalObject *global = script->compileAndGo ? &script->global() : NULL;
|
||||
|
||||
script = clone->script();
|
||||
script = clone->nonLazyScript();
|
||||
js_CallNewScriptHook(cx, script, clone);
|
||||
Debugger::onNewScript(cx, script, global);
|
||||
}
|
||||
|
|
|
@ -73,6 +73,8 @@ struct JSFunction : public JSObject
|
|||
} u;
|
||||
private:
|
||||
js::HeapPtrAtom atom_; /* name for diagnostics and decompiling */
|
||||
|
||||
bool initializeLazyScript(JSContext *cx);
|
||||
public:
|
||||
|
||||
/* A function can be classified as either native (C++) or interpreted (JS): */
|
||||
|
@ -176,11 +178,36 @@ struct JSFunction : public JSObject
|
|||
static inline size_t offsetOfEnvironment() { return offsetof(JSFunction, u.i.env_); }
|
||||
static inline size_t offsetOfAtom() { return offsetof(JSFunction, atom_); }
|
||||
|
||||
js::Return<JSScript*> script() const {
|
||||
js::Return<JSScript*> getOrCreateScript(JSContext *cx) {
|
||||
JS_ASSERT(isInterpreted());
|
||||
if (isInterpretedLazy()) {
|
||||
js::RootedFunction self(cx, this);
|
||||
js::MaybeCheckStackRoots(cx);
|
||||
if (!initializeLazyScript(cx))
|
||||
return js::NullPtr();
|
||||
}
|
||||
JS_ASSERT(hasScript());
|
||||
return JS::HandleScript::fromMarkedLocation(&u.i.script_);
|
||||
}
|
||||
|
||||
bool maybeGetOrCreateScript(JSContext *cx, js::MutableHandle<JSScript*> script) {
|
||||
if (isNative()) {
|
||||
script.set(NULL);
|
||||
return true;
|
||||
}
|
||||
script.set(getOrCreateScript(cx).unsafeGet());
|
||||
return hasScript();
|
||||
}
|
||||
|
||||
js::Return<JSScript*> nonLazyScript() const {
|
||||
JS_ASSERT(hasScript());
|
||||
return JS::HandleScript::fromMarkedLocation(&u.i.script_);
|
||||
}
|
||||
|
||||
js::Return<JSScript*> maybeNonLazyScript() const {
|
||||
return isInterpreted() ? nonLazyScript() : JS::NullPtr();
|
||||
}
|
||||
|
||||
js::HeapPtrScript &mutableScript() {
|
||||
JS_ASSERT(isInterpreted());
|
||||
return *(js::HeapPtrScript *)&u.i.script_;
|
||||
|
@ -189,10 +216,6 @@ struct JSFunction : public JSObject
|
|||
inline void setScript(JSScript *script_);
|
||||
inline void initScript(JSScript *script_);
|
||||
|
||||
js::Return<JSScript*> maybeScript() const {
|
||||
return isInterpreted() ? script() : JS::NullPtr();
|
||||
}
|
||||
|
||||
JSNative native() const {
|
||||
JS_ASSERT(isNative());
|
||||
return u.n.native;
|
||||
|
@ -344,9 +367,6 @@ XDRInterpretedFunction(XDRState<mode> *xdr, HandleObject enclosingScope,
|
|||
extern JSObject *
|
||||
CloneInterpretedFunction(JSContext *cx, HandleObject enclosingScope, HandleFunction fun);
|
||||
|
||||
bool
|
||||
InitializeLazyFunctionScript(JSContext *cx, HandleFunction fun);
|
||||
|
||||
/*
|
||||
* Report an error that call.thisv is not compatible with the specified class,
|
||||
* assuming that the method (clasp->name).prototype.<name of callee function>
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
inline bool
|
||||
JSFunction::inStrictMode() const
|
||||
{
|
||||
return script()->strictModeCode;
|
||||
return nonLazyScript()->strictModeCode;
|
||||
}
|
||||
|
||||
inline void
|
||||
|
|
|
@ -1320,13 +1320,9 @@ TypeConstraintCall::newType(JSContext *cx, TypeSet *source, Type type)
|
|||
return;
|
||||
}
|
||||
|
||||
if (callee->isInterpretedLazy()) {
|
||||
RootedFunction fun(cx, callee);
|
||||
if (!InitializeLazyFunctionScript(cx, fun))
|
||||
RootedScript calleeScript(cx, callee->getOrCreateScript(cx));
|
||||
if (!calleeScript)
|
||||
return;
|
||||
}
|
||||
|
||||
RootedScript calleeScript(cx, callee->script());
|
||||
if (!calleeScript->ensureHasTypes(cx))
|
||||
return;
|
||||
|
||||
|
@ -1403,16 +1399,10 @@ TypeConstraintPropagateThis::newType(JSContext *cx, TypeSet *source, Type type)
|
|||
return;
|
||||
}
|
||||
|
||||
if (callee->isInterpretedLazy()) {
|
||||
RootedFunction fun(cx, callee);
|
||||
if (!InitializeLazyFunctionScript(cx, fun))
|
||||
return;
|
||||
}
|
||||
|
||||
if (!callee->script()->ensureHasTypes(cx))
|
||||
if (!(callee->getOrCreateScript(cx).unsafeGet() && callee->nonLazyScript()->ensureHasTypes(cx)))
|
||||
return;
|
||||
|
||||
TypeSet *thisTypes = TypeScript::ThisTypes(callee->script().unsafeGet());
|
||||
TypeSet *thisTypes = TypeScript::ThisTypes(callee->nonLazyScript().unsafeGet());
|
||||
if (this->types)
|
||||
this->types->addSubset(cx, thisTypes);
|
||||
else
|
||||
|
@ -3396,7 +3386,7 @@ TypeObject::setFlags(JSContext *cx, TypeObjectFlags flags)
|
|||
if (singleton) {
|
||||
/* Make sure flags are consistent with persistent object state. */
|
||||
JS_ASSERT_IF(flags & OBJECT_FLAG_UNINLINEABLE,
|
||||
interpretedFunction->script()->uninlineable);
|
||||
interpretedFunction->nonLazyScript()->uninlineable);
|
||||
JS_ASSERT_IF(flags & OBJECT_FLAG_ITERATED,
|
||||
singleton->lastProperty()->hasObjectFlag(BaseShape::ITERATED_SINGLETON));
|
||||
}
|
||||
|
@ -4636,7 +4626,7 @@ AnalyzeNewScriptProperties(JSContext *cx, TypeObject *type, JSFunction *fun,
|
|||
return false;
|
||||
}
|
||||
|
||||
RootedScript script(cx, fun->script());
|
||||
RootedScript script(cx, fun->nonLazyScript());
|
||||
if (!script->ensureRanAnalysis(cx) || !script->ensureRanInference(cx)) {
|
||||
pbaseobj.set(NULL);
|
||||
cx->compartment->types.setPendingNukeTypes(cx);
|
||||
|
@ -4774,7 +4764,7 @@ AnalyzePoppedThis(JSContext *cx, Vector<SSAUseChain *> *pendingPoppedThis,
|
|||
TypeObject *type, JSFunction *fun, MutableHandleObject pbaseobj,
|
||||
Vector<TypeNewScript::Initializer> *initializerList)
|
||||
{
|
||||
RootedScript script(cx, fun->script());
|
||||
RootedScript script(cx, fun->nonLazyScript());
|
||||
ScriptAnalysis *analysis = script->analysis();
|
||||
|
||||
while (!pendingPoppedThis->empty()) {
|
||||
|
@ -5219,7 +5209,7 @@ types::TypeMonitorCallSlow(JSContext *cx, HandleObject callee, const CallArgs &a
|
|||
bool constructing)
|
||||
{
|
||||
unsigned nargs = callee->toFunction()->nargs;
|
||||
RootedScript script(cx, callee->toFunction()->script());
|
||||
RootedScript script(cx, callee->toFunction()->nonLazyScript());
|
||||
|
||||
if (!constructing)
|
||||
TypeScript::SetThis(cx, script, args.thisv());
|
||||
|
@ -5545,8 +5535,8 @@ JSScript::makeAnalysis(JSContext *cx)
|
|||
/* static */ bool
|
||||
JSFunction::setTypeForScriptedFunction(JSContext *cx, HandleFunction fun, bool singleton)
|
||||
{
|
||||
JS_ASSERT(fun->script().unsafeGet());
|
||||
JS_ASSERT(fun->script()->function() == fun);
|
||||
JS_ASSERT(fun->nonLazyScript().unsafeGet());
|
||||
JS_ASSERT(fun->nonLazyScript()->function() == fun);
|
||||
|
||||
if (!cx->typeInferenceEnabled())
|
||||
return true;
|
||||
|
@ -5696,8 +5686,7 @@ JSObject::makeLazyType(JSContext *cx)
|
|||
RootedObject self(cx, this);
|
||||
/* De-lazification of functions can GC, so we need to do it up here. */
|
||||
if (self->isFunction() && self->toFunction()->isInterpretedLazy()) {
|
||||
RootedFunction fun(cx, self->toFunction());
|
||||
if (!InitializeLazyFunctionScript(cx, fun))
|
||||
if (!self->toFunction()->getOrCreateScript(cx).unsafeGet())
|
||||
return NULL;
|
||||
}
|
||||
JSProtoKey key = JSCLASS_CACHED_PROTO_KEY(getClass());
|
||||
|
@ -5724,7 +5713,7 @@ JSObject::makeLazyType(JSContext *cx)
|
|||
|
||||
if (self->isFunction() && self->toFunction()->isInterpreted()) {
|
||||
type->interpretedFunction = self->toFunction();
|
||||
if (type->interpretedFunction->script()->uninlineable)
|
||||
if (type->interpretedFunction->nonLazyScript()->uninlineable)
|
||||
type->flags |= OBJECT_FLAG_UNINLINEABLE;
|
||||
}
|
||||
|
||||
|
|
|
@ -532,7 +532,7 @@ TypeMonitorCall(JSContext *cx, const js::CallArgs &args, bool constructing)
|
|||
if (callee->isFunction()) {
|
||||
JSFunction *fun = callee->toFunction();
|
||||
if (fun->isInterpreted()) {
|
||||
js::RootedScript script(cx, fun->script());
|
||||
js::RootedScript script(cx, fun->nonLazyScript());
|
||||
if (!script->ensureRanAnalysis(cx))
|
||||
return false;
|
||||
if (cx->typeInferenceEnabled())
|
||||
|
@ -703,7 +703,7 @@ UseNewTypeForClone(JSFunction *fun)
|
|||
* instance a singleton type and clone the underlying script.
|
||||
*/
|
||||
|
||||
RawScript script = fun->script().get(nogc);
|
||||
RawScript script = fun->nonLazyScript().get(nogc);
|
||||
|
||||
if (script->length >= 50)
|
||||
return false;
|
||||
|
|
|
@ -368,7 +368,8 @@ js::InvokeKernel(JSContext *cx, CallArgs args, MaybeConstruct construct)
|
|||
if (fun->isNative())
|
||||
return CallJSNative(cx, fun->native(), args);
|
||||
|
||||
if (fun->isInterpretedLazy() && !InitializeLazyFunctionScript(cx, fun))
|
||||
RootedScript script(cx, fun->getOrCreateScript(cx));
|
||||
if (!script)
|
||||
return false;
|
||||
|
||||
if (!TypeMonitorCall(cx, args, construct))
|
||||
|
@ -380,7 +381,6 @@ js::InvokeKernel(JSContext *cx, CallArgs args, MaybeConstruct construct)
|
|||
return false;
|
||||
|
||||
/* Run function until JSOP_STOP, JSOP_RETURN or error. */
|
||||
RootedScript script(cx, fun->script());
|
||||
JSBool ok = RunScript(cx, script, ifg.fp());
|
||||
|
||||
/* Propagate the return value out. */
|
||||
|
@ -2346,9 +2346,9 @@ BEGIN_CASE(JSOP_FUNCALL)
|
|||
|
||||
InitialFrameFlags initial = construct ? INITIAL_CONSTRUCT : INITIAL_NONE;
|
||||
bool newType = cx->typeInferenceEnabled() && UseNewType(cx, script, regs.pc);
|
||||
if (fun->isInterpretedLazy() && !InitializeLazyFunctionScript(cx, fun))
|
||||
RawScript funScript = fun->getOrCreateScript(cx).unsafeGet();
|
||||
if (!funScript)
|
||||
goto error;
|
||||
RawScript funScript = fun->script().unsafeGet();
|
||||
if (!cx->stack.pushInlineFrame(cx, regs, args, *fun, funScript, initial))
|
||||
goto error;
|
||||
|
||||
|
|
|
@ -1021,7 +1021,7 @@ class FastInvokeGuard
|
|||
JSFunction *fun = fval.toObject().toFunction();
|
||||
if (fun->hasScript()) {
|
||||
fun_ = fun;
|
||||
script_ = fun->script();
|
||||
script_ = fun->nonLazyScript();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1033,7 +1033,7 @@ class FastInvokeGuard
|
|||
bool invoke(JSContext *cx) {
|
||||
#ifdef JS_ION
|
||||
if (useIon_ && fun_) {
|
||||
JS_ASSERT(fun_->script() == script_);
|
||||
JS_ASSERT(fun_->nonLazyScript() == script_);
|
||||
|
||||
ion::MethodStatus status = ion::CanEnterUsingFastInvoke(cx, script_, args_.length());
|
||||
if (status == ion::Method_Error)
|
||||
|
|
|
@ -2366,7 +2366,7 @@ js_CreateThisForFunctionWithProto(JSContext *cx, HandleObject callee, JSObject *
|
|||
}
|
||||
|
||||
if (res && cx->typeInferenceEnabled()) {
|
||||
RootedScript script(cx, callee->toFunction()->script());
|
||||
RootedScript script(cx, callee->toFunction()->nonLazyScript());
|
||||
TypeScript::SetThis(cx, script, types::Type::ObjectType(res));
|
||||
}
|
||||
|
||||
|
@ -2397,7 +2397,7 @@ js_CreateThisForFunction(JSContext *cx, HandleObject callee, bool newType)
|
|||
if (!JSObject::setSingletonType(cx, nobj))
|
||||
return NULL;
|
||||
|
||||
RootedScript calleeScript(cx, callee->toFunction()->script());
|
||||
RootedScript calleeScript(cx, callee->toFunction()->nonLazyScript());
|
||||
TypeScript::SetThis(cx, calleeScript, types::Type::ObjectType(nobj));
|
||||
|
||||
return nobj;
|
||||
|
@ -5240,7 +5240,7 @@ dumpValue(const Value &v)
|
|||
fputs("<unnamed function", stderr);
|
||||
}
|
||||
if (fun->hasScript()) {
|
||||
JSScript *script = fun->script().get(nogc);
|
||||
JSScript *script = fun->nonLazyScript().get(nogc);
|
||||
fprintf(stderr, " (%s:%u)",
|
||||
script->filename ? script->filename : "", script->lineno);
|
||||
}
|
||||
|
|
|
@ -1129,7 +1129,7 @@ js_NewPrinter(JSContext *cx, const char *name, JSFunction *fun,
|
|||
jp->localNames = NULL;
|
||||
jp->decompiledOpcodes = NULL;
|
||||
if (fun && fun->hasScript()) {
|
||||
if (!SetPrinterLocalNames(cx, fun->script().unsafeGet(), jp)) {
|
||||
if (!SetPrinterLocalNames(cx, fun->nonLazyScript().unsafeGet(), jp)) {
|
||||
js_DestroyPrinter(jp);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -1785,7 +1785,7 @@ GetArgOrVarAtom(JSPrinter *jp, unsigned slot)
|
|||
{
|
||||
LOCAL_ASSERT_RV(jp->fun, NULL);
|
||||
LOCAL_ASSERT_RV(slot < jp->script->bindings.count(), NULL);
|
||||
LOCAL_ASSERT_RV(jp->script == jp->fun->script().unsafeGet(), NULL);
|
||||
LOCAL_ASSERT_RV(jp->script == jp->fun->nonLazyScript().unsafeGet(), NULL);
|
||||
JSAtom *name = (*jp->localNames)[slot].name();
|
||||
#if !JS_HAS_DESTRUCTURING
|
||||
LOCAL_ASSERT_RV(name, NULL);
|
||||
|
@ -4744,10 +4744,10 @@ Decompile(SprintStack *ss, jsbytecode *pc, int nb)
|
|||
*/
|
||||
LifoAllocScope las(&cx->tempLifoAlloc());
|
||||
outerLocalNames = jp->localNames;
|
||||
if (!SetPrinterLocalNames(cx, fun->script().unsafeGet(), jp))
|
||||
if (!SetPrinterLocalNames(cx, fun->nonLazyScript().unsafeGet(), jp))
|
||||
return NULL;
|
||||
|
||||
inner = fun->script().unsafeGet();
|
||||
inner = fun->nonLazyScript().unsafeGet();
|
||||
if (!InitSprintStack(cx, &ss2, jp, StackDepth(inner))) {
|
||||
js_delete(jp->localNames);
|
||||
jp->localNames = outerLocalNames;
|
||||
|
@ -5618,7 +5618,7 @@ js_DecompileFunctionBody(JSPrinter *jp)
|
|||
return JS_TRUE;
|
||||
}
|
||||
|
||||
script = jp->fun->script().unsafeGet();
|
||||
script = jp->fun->nonLazyScript().unsafeGet();
|
||||
return DecompileBody(jp, script, script->code);
|
||||
}
|
||||
|
||||
|
@ -5655,7 +5655,7 @@ js_DecompileFunction(JSPrinter *jp)
|
|||
jp->indent -= 4;
|
||||
js_printf(jp, "\t}");
|
||||
} else {
|
||||
RootedScript script(cx, fun->script());
|
||||
RootedScript script(cx, fun->nonLazyScript());
|
||||
#if JS_HAS_DESTRUCTURING
|
||||
SprintStack ss(cx);
|
||||
#endif
|
||||
|
|
|
@ -665,7 +665,7 @@ js::XDRScript(XDRState<mode> *xdr, HandleObject enclosingScope, HandleScript enc
|
|||
/* Code the nested function's enclosing scope. */
|
||||
uint32_t funEnclosingScopeIndex = 0;
|
||||
if (mode == XDR_ENCODE) {
|
||||
StaticScopeIter ssi((*objp)->toFunction()->script()->enclosingStaticScope());
|
||||
StaticScopeIter ssi((*objp)->toFunction()->nonLazyScript()->enclosingStaticScope());
|
||||
if (ssi.done() || ssi.type() == StaticScopeIter::FUNCTION) {
|
||||
JS_ASSERT(ssi.done() == !fun);
|
||||
funEnclosingScopeIndex = UINT32_MAX;
|
||||
|
@ -1872,7 +1872,7 @@ JSScript::enclosingScriptsCompiledSuccessfully() const
|
|||
RawFunction fun = enclosing->toFunction();
|
||||
if (!fun->hasScript())
|
||||
return false;
|
||||
enclosing = fun->script()->enclosingScope_;
|
||||
enclosing = fun->nonLazyScript()->enclosingScope_;
|
||||
} else {
|
||||
enclosing = enclosing->asStaticBlock().enclosingStaticScope();
|
||||
}
|
||||
|
@ -2212,7 +2212,7 @@ js::CloneScript(JSContext *cx, HandleObject enclosingScope, HandleFunction fun,
|
|||
} else if (obj->isFunction()) {
|
||||
RootedFunction innerFun(cx, obj->toFunction());
|
||||
|
||||
StaticScopeIter ssi(innerFun->script()->enclosingStaticScope());
|
||||
StaticScopeIter ssi(innerFun->nonLazyScript()->enclosingStaticScope());
|
||||
RootedObject enclosingScope(cx);
|
||||
if (!ssi.done() && ssi.type() == StaticScopeIter::BLOCK)
|
||||
enclosingScope = objects[FindBlockIndex(src, ssi.block())];
|
||||
|
|
|
@ -2369,7 +2369,7 @@ LambdaIsGetElem(JSObject &lambda)
|
|||
if (!fun->hasScript())
|
||||
return NULL;
|
||||
|
||||
RawScript script = fun->script().get(nogc);
|
||||
RawScript script = fun->nonLazyScript().get(nogc);
|
||||
jsbytecode *pc = script->code;
|
||||
|
||||
/*
|
||||
|
|
|
@ -295,7 +295,7 @@ mjit::Compiler::scanInlineCalls(uint32_t index, uint32_t depth)
|
|||
okay = false;
|
||||
break;
|
||||
}
|
||||
RootedScript script(cx, fun->script());
|
||||
RootedScript script(cx, fun->nonLazyScript());
|
||||
|
||||
/*
|
||||
* Don't inline calls to scripts which haven't been analyzed.
|
||||
|
@ -394,7 +394,7 @@ mjit::Compiler::scanInlineCalls(uint32_t index, uint32_t depth)
|
|||
continue;
|
||||
|
||||
JSFunction *fun = obj->toFunction();
|
||||
RootedScript script(cx, fun->script());
|
||||
RootedScript script(cx, fun->nonLazyScript());
|
||||
|
||||
CompileStatus status = addInlineFrame(script, nextDepth, index, pc);
|
||||
if (status != Compile_Okay)
|
||||
|
|
|
@ -200,7 +200,7 @@ stubs::FixupArity(VMFrame &f, uint32_t nactual)
|
|||
*/
|
||||
InitialFrameFlags initial = oldfp->initialFlags();
|
||||
RootedFunction fun(cx, oldfp->fun());
|
||||
RootedScript script(cx, fun->script());
|
||||
RootedScript script(cx, fun->nonLazyScript());
|
||||
void *ncode = oldfp->nativeReturnAddress();
|
||||
|
||||
/* Pop the inline frame. */
|
||||
|
@ -285,11 +285,10 @@ UncachedInlineCall(VMFrame &f, InitialFrameFlags initial,
|
|||
CallArgs args = CallArgsFromSp(argc, f.regs.sp);
|
||||
RootedFunction newfun(cx, args.callee().toFunction());
|
||||
|
||||
if (newfun->isInterpretedLazy() && !InitializeLazyFunctionScript(cx, newfun))
|
||||
RootedScript newscript(cx, newfun->getOrCreateScript(cx));
|
||||
if (!newscript)
|
||||
return false;
|
||||
|
||||
RootedScript newscript(cx, newfun->script());
|
||||
|
||||
bool construct = InitialFrameFlagsAreConstructing(initial);
|
||||
|
||||
RootedScript fscript(cx, f.script());
|
||||
|
|
|
@ -1069,7 +1069,7 @@ VMFrame::script()
|
|||
{
|
||||
AutoAssertNoGC nogc;
|
||||
if (regs.inlined())
|
||||
return chunk()->inlineFrames()[regs.inlined()->inlineIndex].fun->script();
|
||||
return chunk()->inlineFrames()[regs.inlined()->inlineIndex].fun->nonLazyScript();
|
||||
return fp()->script();
|
||||
}
|
||||
|
||||
|
|
|
@ -1001,7 +1001,7 @@ class CallCompiler : public BaseCompiler
|
|||
/* Guard that it's the same script. */
|
||||
Address scriptAddr(ic.funObjReg, JSFunction::offsetOfNativeOrScript());
|
||||
Jump funGuard = masm.branchPtr(Assembler::NotEqual, scriptAddr,
|
||||
ImmPtr(obj->toFunction()->script().get(nogc)));
|
||||
ImmPtr(obj->toFunction()->nonLazyScript().get(nogc)));
|
||||
Jump done = masm.jump();
|
||||
|
||||
LinkerHelper linker(masm, JSC::JAEGER_CODE);
|
||||
|
@ -1250,7 +1250,7 @@ class CallCompiler : public BaseCompiler
|
|||
!ic.hasIonStub() &&
|
||||
ic.frameSize.isStatic() &&
|
||||
ic.frameSize.staticArgc() <= ion::SNAPSHOT_MAX_NARGS &&
|
||||
fun->hasScript() && fun->script()->hasIonScript())
|
||||
fun->hasScript() && fun->nonLazyScript()->hasIonScript())
|
||||
{
|
||||
if (!generateIonStub())
|
||||
THROWV(NULL);
|
||||
|
@ -1261,7 +1261,7 @@ class CallCompiler : public BaseCompiler
|
|||
|
||||
AutoAssertNoGC nogc;
|
||||
JS_ASSERT(fun);
|
||||
JSScript *script = fun->script().get(nogc);
|
||||
JSScript *script = fun->nonLazyScript().get(nogc);
|
||||
JS_ASSERT(script);
|
||||
|
||||
uint32_t flags = callingNew ? StackFrame::CONSTRUCTING : 0;
|
||||
|
@ -1280,7 +1280,8 @@ class CallCompiler : public BaseCompiler
|
|||
} else if (ic.fastGuardedObject &&
|
||||
!ic.hasJsFunCheck &&
|
||||
!ic.fastGuardedNative &&
|
||||
ic.fastGuardedObject->toFunction()->script() == fun->script()) {
|
||||
ic.fastGuardedObject->toFunction()->nonLazyScript() == fun->nonLazyScript())
|
||||
{
|
||||
/*
|
||||
* Note: Multiple "function guard" stubs are not yet
|
||||
* supported, thus the fastGuardedNative check.
|
||||
|
@ -1432,7 +1433,7 @@ ic::GenerateArgumentCheckStub(VMFrame &f)
|
|||
JITScript *jit = f.jit();
|
||||
StackFrame *fp = f.fp();
|
||||
JSFunction *fun = fp->fun();
|
||||
JSScript *script = fun->script().get(nogc);
|
||||
JSScript *script = fun->nonLazyScript().get(nogc);
|
||||
|
||||
if (jit->argsCheckPool)
|
||||
jit->resetArgsCheck();
|
||||
|
|
|
@ -2217,7 +2217,7 @@ frameCountersOffset(VMFrame &f)
|
|||
uint32_t index = cx->regs().inlined()->inlineIndex;
|
||||
InlineFrame *frames = f.chunk()->inlineFrames();
|
||||
for (unsigned i = 0; i < index; i++)
|
||||
offset += frames[i].fun->script()->length;
|
||||
offset += frames[i].fun->nonLazyScript()->length;
|
||||
}
|
||||
|
||||
jsbytecode *pc;
|
||||
|
|
|
@ -250,7 +250,7 @@ Recompiler::expandInlineFrames(JSCompartment *compartment,
|
|||
uint8_t* codeStart = (uint8_t *)chunk->code.m_code.executableAddress();
|
||||
|
||||
InlineFrame *inner = &chunk->inlineFrames()[inlined->inlineIndex];
|
||||
jsbytecode *innerpc = inner->fun->script()->code + inlined->pcOffset;
|
||||
jsbytecode *innerpc = inner->fun->nonLazyScript()->code + inlined->pcOffset;
|
||||
|
||||
StackFrame *innerfp = expandInlineFrameChain(fp, inner);
|
||||
|
||||
|
|
|
@ -1623,7 +1623,7 @@ stubs::CheckArgumentTypes(VMFrame &f)
|
|||
{
|
||||
StackFrame *fp = f.fp();
|
||||
JSFunction *fun = fp->fun();
|
||||
RootedScript fscript(f.cx, fun->script());
|
||||
RootedScript fscript(f.cx, fun->nonLazyScript());
|
||||
RecompilationMonitor monitor(f.cx);
|
||||
|
||||
{
|
||||
|
@ -1651,7 +1651,7 @@ stubs::AssertArgumentTypes(VMFrame &f)
|
|||
AutoAssertNoGC nogc;
|
||||
StackFrame *fp = f.fp();
|
||||
JSFunction *fun = fp->fun();
|
||||
RawScript script = fun->script().get(nogc);
|
||||
RawScript script = fun->nonLazyScript().get(nogc);
|
||||
|
||||
/*
|
||||
* Don't check the type of 'this' for constructor frames, the 'this' value
|
||||
|
|
|
@ -301,6 +301,143 @@ GetLine(FILE *file, const char * prompt)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static size_t
|
||||
GetDeflatedUTF8StringLength(JSContext *cx, const jschar *chars,
|
||||
size_t nchars)
|
||||
{
|
||||
size_t nbytes;
|
||||
const jschar *end;
|
||||
unsigned c, c2;
|
||||
|
||||
nbytes = nchars;
|
||||
for (end = chars + nchars; chars != end; chars++) {
|
||||
c = *chars;
|
||||
if (c < 0x80)
|
||||
continue;
|
||||
if (0xD800 <= c && c <= 0xDFFF) {
|
||||
/* nbytes sets 1 length since this is surrogate pair. */
|
||||
if (c >= 0xDC00 || (chars + 1) == end) {
|
||||
nbytes += 2; /* Bad Surrogate */
|
||||
continue;
|
||||
}
|
||||
c2 = chars[1];
|
||||
if (c2 < 0xDC00 || c2 > 0xDFFF) {
|
||||
nbytes += 2; /* Bad Surrogate */
|
||||
continue;
|
||||
}
|
||||
c = ((c - 0xD800) << 10) + (c2 - 0xDC00) + 0x10000;
|
||||
nbytes--;
|
||||
chars++;
|
||||
}
|
||||
c >>= 11;
|
||||
nbytes++;
|
||||
while (c) {
|
||||
c >>= 5;
|
||||
nbytes++;
|
||||
}
|
||||
}
|
||||
return nbytes;
|
||||
}
|
||||
|
||||
static bool
|
||||
PutUTF8ReplacementCharacter(char **dst, size_t *dstlenp) {
|
||||
if (*dstlenp < 3)
|
||||
return false;
|
||||
*(*dst)++ = (char) 0xEF;
|
||||
*(*dst)++ = (char) 0xBF;
|
||||
*(*dst)++ = (char) 0xBD;
|
||||
*dstlenp -= 3;
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Write up to |*dstlenp| bytes into |dst|. Writes the number of bytes used
|
||||
* into |*dstlenp| on success. Returns false on failure.
|
||||
*/
|
||||
static bool
|
||||
DeflateStringToUTF8Buffer(JSContext *cx, const jschar *src, size_t srclen,
|
||||
char *dst, size_t *dstlenp)
|
||||
{
|
||||
size_t dstlen = *dstlenp;
|
||||
size_t origDstlen = dstlen;
|
||||
|
||||
while (srclen) {
|
||||
uint32_t v;
|
||||
jschar c = *src++;
|
||||
srclen--;
|
||||
if (c >= 0xDC00 && c <= 0xDFFF) {
|
||||
if (!PutUTF8ReplacementCharacter(&dst, &dstlen))
|
||||
goto bufferTooSmall;
|
||||
continue;
|
||||
} else if (c < 0xD800 || c > 0xDBFF) {
|
||||
v = c;
|
||||
} else {
|
||||
if (srclen < 1) {
|
||||
if (!PutUTF8ReplacementCharacter(&dst, &dstlen))
|
||||
goto bufferTooSmall;
|
||||
continue;
|
||||
}
|
||||
jschar c2 = *src;
|
||||
if ((c2 < 0xDC00) || (c2 > 0xDFFF)) {
|
||||
if (!PutUTF8ReplacementCharacter(&dst, &dstlen))
|
||||
goto bufferTooSmall;
|
||||
continue;
|
||||
}
|
||||
src++;
|
||||
srclen--;
|
||||
v = ((c - 0xD800) << 10) + (c2 - 0xDC00) + 0x10000;
|
||||
}
|
||||
size_t utf8Len;
|
||||
if (v < 0x0080) {
|
||||
/* no encoding necessary - performance hack */
|
||||
if (dstlen == 0)
|
||||
goto bufferTooSmall;
|
||||
*dst++ = (char) v;
|
||||
utf8Len = 1;
|
||||
} else {
|
||||
uint8_t utf8buf[4];
|
||||
utf8Len = js_OneUcs4ToUtf8Char(utf8buf, v);
|
||||
if (utf8Len > dstlen)
|
||||
goto bufferTooSmall;
|
||||
for (size_t i = 0; i < utf8Len; i++)
|
||||
*dst++ = (char) utf8buf[i];
|
||||
}
|
||||
dstlen -= utf8Len;
|
||||
}
|
||||
*dstlenp = (origDstlen - dstlen);
|
||||
return true;
|
||||
|
||||
bufferTooSmall:
|
||||
*dstlenp = (origDstlen - dstlen);
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BUFFER_TOO_SMALL);
|
||||
return false;
|
||||
}
|
||||
|
||||
static char *
|
||||
JSStringToUTF8(JSContext *cx, JSString *str)
|
||||
{
|
||||
JSLinearString *linear = str->ensureLinear(cx);
|
||||
if (!linear)
|
||||
return NULL;
|
||||
|
||||
const jschar *chars = linear->chars();
|
||||
size_t length = linear->length();
|
||||
|
||||
size_t tgtlen = GetDeflatedUTF8StringLength(cx, chars, length);
|
||||
char *utf8chars = cx->pod_malloc<char>(tgtlen + 1);
|
||||
if (!utf8chars)
|
||||
return NULL;
|
||||
|
||||
bool ok = DeflateStringToUTF8Buffer(cx, chars, length, utf8chars, &tgtlen);
|
||||
if (!ok) {
|
||||
JS_free(cx, utf8chars);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
utf8chars[tgtlen] = 0;
|
||||
return utf8chars;
|
||||
}
|
||||
|
||||
/*
|
||||
* State to store as JSContext private.
|
||||
*
|
||||
|
@ -545,10 +682,12 @@ Process(JSContext *cx, JSObject *obj_, const char *filename, bool forceTTY)
|
|||
str = JS_ValueToSource(cx, result);
|
||||
ok = !!str;
|
||||
if (ok) {
|
||||
JSAutoByteString bytes(cx, str);
|
||||
ok = !!bytes;
|
||||
if (ok)
|
||||
fprintf(gOutFile, "%s\n", bytes.ptr());
|
||||
char *utf8chars = JSStringToUTF8(cx, str);
|
||||
ok = !!utf8chars;
|
||||
if (ok) {
|
||||
fprintf(gOutFile, "%s\n", utf8chars);
|
||||
JS_free(cx, utf8chars);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1164,7 +1303,7 @@ PutStr(JSContext *cx, unsigned argc, jsval *vp)
|
|||
str = JS_ValueToString(cx, argv[0]);
|
||||
if (!str)
|
||||
return false;
|
||||
bytes = JS_EncodeString(cx, str);
|
||||
bytes = JSStringToUTF8(cx, str);
|
||||
if (!bytes)
|
||||
return false;
|
||||
fputs(bytes, gOutFile);
|
||||
|
@ -1197,7 +1336,7 @@ PrintInternal(JSContext *cx, unsigned argc, jsval *vp, FILE *file)
|
|||
str = JS_ValueToString(cx, argv[i]);
|
||||
if (!str)
|
||||
return false;
|
||||
bytes = JS_EncodeString(cx, str);
|
||||
bytes = JSStringToUTF8(cx, str);
|
||||
if (!bytes)
|
||||
return false;
|
||||
fprintf(file, "%s%s", i ? " " : "", bytes);
|
||||
|
@ -1317,7 +1456,8 @@ ValueToScript(JSContext *cx, jsval v, JSFunction **funp = NULL)
|
|||
if (!fun)
|
||||
return NULL;
|
||||
|
||||
RootedScript script(cx, fun->maybeScript());
|
||||
RootedScript script(cx);
|
||||
fun->maybeGetOrCreateScript(cx, &script);
|
||||
if (!script)
|
||||
JS_ReportErrorNumber(cx, my_GetErrorMessage, NULL, JSSMSG_SCRIPTS_ONLY);
|
||||
|
||||
|
@ -1785,8 +1925,9 @@ DisassembleScript(JSContext *cx, JSScript *script_, JSFunction *fun, bool lines,
|
|||
if (obj->isFunction()) {
|
||||
Sprint(sp, "\n");
|
||||
RawFunction fun = obj->toFunction();
|
||||
RawScript nested = fun->maybeScript().unsafeGet();
|
||||
if (!DisassembleScript(cx, nested, fun, lines, recursive, sp))
|
||||
RootedScript script(cx);
|
||||
fun->maybeGetOrCreateScript(cx, &script);
|
||||
if (!DisassembleScript(cx, script.get(), fun, lines, recursive, sp))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -2212,7 +2353,7 @@ Clone(JSContext *cx, unsigned argc, jsval *vp)
|
|||
}
|
||||
if (funobj->compartment() != cx->compartment) {
|
||||
JSFunction *fun = funobj->toFunction();
|
||||
if (fun->hasScript() && fun->script()->compileAndGo) {
|
||||
if (fun->hasScript() && fun->nonLazyScript()->compileAndGo) {
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_UNEXPECTED_TYPE,
|
||||
"function", "compile-and-go");
|
||||
return false;
|
||||
|
@ -4201,7 +4342,7 @@ Exec(JSContext *cx, unsigned argc, jsval *vp)
|
|||
ok = false;
|
||||
goto done;
|
||||
}
|
||||
nargv[i] = JS_EncodeString(cx, str);
|
||||
nargv[i] = JSStringToUTF8(cx, str);
|
||||
if (!nargv[i]) {
|
||||
ok = false;
|
||||
goto done;
|
||||
|
|
|
@ -74,7 +74,7 @@ ArgumentsObject::element(uint32_t i) const
|
|||
const Value &v = data()->args[i];
|
||||
if (v.isMagic(JS_FORWARD_TO_CALL_OBJECT)) {
|
||||
CallObject &callobj = getFixedSlot(MAYBE_CALL_SLOT).toObject().asCall();
|
||||
for (AliasedFormalIter fi(callobj.callee().script().get(nogc)); ; fi++) {
|
||||
for (AliasedFormalIter fi(callobj.callee().nonLazyScript().get(nogc)); ; fi++) {
|
||||
if (fi.frameIndex() == i)
|
||||
return callobj.aliasedVar(fi);
|
||||
}
|
||||
|
@ -90,7 +90,7 @@ ArgumentsObject::setElement(uint32_t i, const Value &v)
|
|||
HeapValue &lhs = data()->args[i];
|
||||
if (lhs.isMagic(JS_FORWARD_TO_CALL_OBJECT)) {
|
||||
CallObject &callobj = getFixedSlot(MAYBE_CALL_SLOT).toObject().asCall();
|
||||
for (AliasedFormalIter fi(callobj.callee().script().get(nogc)); ; fi++) {
|
||||
for (AliasedFormalIter fi(callobj.callee().nonLazyScript().get(nogc)); ; fi++) {
|
||||
if (fi.frameIndex() == i) {
|
||||
callobj.setAliasedVar(fi, v);
|
||||
return;
|
||||
|
|
|
@ -2731,7 +2731,7 @@ DebuggerScript_getChildScripts(JSContext *cx, unsigned argc, Value *vp)
|
|||
obj = objects->vector[i];
|
||||
if (obj->isFunction()) {
|
||||
fun = static_cast<JSFunction *>(obj.get());
|
||||
funScript = fun->script();
|
||||
funScript = fun->nonLazyScript();
|
||||
s = dbg->wrapScript(cx, funScript);
|
||||
if (!s || !js_NewbornArrayPush(cx, result, ObjectValue(*s)))
|
||||
return false;
|
||||
|
@ -3445,7 +3445,7 @@ DebuggerFrame_getScript(JSContext *cx, unsigned argc, Value *vp)
|
|||
if (fp->isFunctionFrame() && !fp->isEvalFrame()) {
|
||||
JSFunction &callee = fp->callee();
|
||||
if (callee.isInterpreted()) {
|
||||
RootedScript script(cx, callee.script());
|
||||
RootedScript script(cx, callee.nonLazyScript());
|
||||
scriptObject = debug->wrapScript(cx, script);
|
||||
if (!scriptObject)
|
||||
return false;
|
||||
|
@ -3925,11 +3925,11 @@ DebuggerObject_getParameterNames(JSContext *cx, unsigned argc, Value *vp)
|
|||
result->ensureDenseArrayInitializedLength(cx, 0, fun->nargs);
|
||||
|
||||
if (fun->isInterpreted()) {
|
||||
JS_ASSERT(fun->nargs == fun->script()->bindings.numArgs());
|
||||
JS_ASSERT(fun->nargs == fun->nonLazyScript()->bindings.numArgs());
|
||||
|
||||
if (fun->nargs > 0) {
|
||||
BindingVector bindings(cx);
|
||||
RootedScript script(cx, fun->script());
|
||||
RootedScript script(cx, fun->nonLazyScript());
|
||||
if (!FillBindingVector(script, &bindings))
|
||||
return false;
|
||||
for (size_t i = 0; i < fun->nargs; i++) {
|
||||
|
@ -3967,7 +3967,7 @@ DebuggerObject_getScript(JSContext *cx, unsigned argc, Value *vp)
|
|||
return true;
|
||||
}
|
||||
|
||||
RootedScript script(cx, fun->script());
|
||||
RootedScript script(cx, fun->nonLazyScript());
|
||||
RootedObject scriptObject(cx, dbg->wrapScript(cx, script));
|
||||
if (!scriptObject)
|
||||
return false;
|
||||
|
|
|
@ -405,7 +405,7 @@ GlobalObject::initFunctionAndObjectClasses(JSContext *cx)
|
|||
* Notify any debuggers about the creation of the script for
|
||||
* |Function.prototype| -- after all initialization, for simplicity.
|
||||
*/
|
||||
RootedScript functionProtoScript(cx, functionProto->script());
|
||||
RootedScript functionProtoScript(cx, functionProto->nonLazyScript());
|
||||
js_CallNewScriptHook(cx, functionProtoScript, functionProto);
|
||||
return functionProto;
|
||||
}
|
||||
|
|
|
@ -367,7 +367,7 @@ SPSProfiler::discardMJITCode(mjit::JITScript *jscr,
|
|||
|
||||
unregisterScript(jscr->script, chunk);
|
||||
for (unsigned i = 0; i < chunk->nInlineFrames; i++)
|
||||
unregisterScript(chunk->inlineFrames()[i].fun->script().get(nogc), chunk);
|
||||
unregisterScript(chunk->inlineFrames()[i].fun->nonLazyScript().get(nogc), chunk);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -42,7 +42,7 @@ StaticScopeIter::operator++(int)
|
|||
obj = obj->asStaticBlock().enclosingStaticScope();
|
||||
} else if (onNamedLambda || !obj->toFunction()->isNamedLambda()) {
|
||||
onNamedLambda = false;
|
||||
obj = obj->toFunction()->script()->enclosingStaticScope();
|
||||
obj = obj->toFunction()->nonLazyScript()->enclosingStaticScope();
|
||||
} else {
|
||||
onNamedLambda = true;
|
||||
}
|
||||
|
@ -86,7 +86,7 @@ StaticScopeIter::funScript() const
|
|||
{
|
||||
AutoAssertNoGC nogc;
|
||||
JS_ASSERT(type() == FUNCTION);
|
||||
return obj->toFunction()->script().get(nogc);
|
||||
return obj->toFunction()->nonLazyScript().get(nogc);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
@ -1040,7 +1040,7 @@ ScopeIter::settle()
|
|||
CallObject &callobj = cur_->asCall();
|
||||
type_ = callobj.isForEval() ? StrictEvalScope : Call;
|
||||
hasScopeObject_ = true;
|
||||
JS_ASSERT_IF(type_ == Call, callobj.callee().script() == fp_->script());
|
||||
JS_ASSERT_IF(type_ == Call, callobj.callee().nonLazyScript() == fp_->script());
|
||||
} else {
|
||||
JS_ASSERT(!cur_->isScope());
|
||||
JS_ASSERT(fp_->isGlobalFrame() || fp_->isDebuggerFrame());
|
||||
|
@ -1122,7 +1122,7 @@ class DebugScopeProxy : public BaseProxyHandler
|
|||
/* Handle unaliased formals, vars, and consts at function scope. */
|
||||
if (scope->isCall() && !scope->asCall().isForEval()) {
|
||||
CallObject &callobj = scope->asCall();
|
||||
RootedScript script(cx, callobj.callee().script());
|
||||
RootedScript script(cx, callobj.callee().nonLazyScript());
|
||||
if (!script->ensureHasTypes(cx))
|
||||
return false;
|
||||
|
||||
|
@ -1247,7 +1247,7 @@ class DebugScopeProxy : public BaseProxyHandler
|
|||
static bool isMissingArgumentsBinding(ScopeObject &scope)
|
||||
{
|
||||
return isFunctionScope(scope) &&
|
||||
!scope.asCall().callee().script()->argumentsHasVarBinding();
|
||||
!scope.asCall().callee().nonLazyScript()->argumentsHasVarBinding();
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1265,7 +1265,7 @@ class DebugScopeProxy : public BaseProxyHandler
|
|||
if (!isArguments(cx, id) || !isFunctionScope(scope))
|
||||
return true;
|
||||
|
||||
if (scope.asCall().callee().script()->needsArgsObj())
|
||||
if (scope.asCall().callee().nonLazyScript()->needsArgsObj())
|
||||
return true;
|
||||
|
||||
StackFrame *maybefp = cx->runtime->debugScopes->hasLiveFrame(scope);
|
||||
|
@ -1399,7 +1399,7 @@ class DebugScopeProxy : public BaseProxyHandler
|
|||
* they must be manually appended here.
|
||||
*/
|
||||
if (scope.isCall() && !scope.asCall().isForEval()) {
|
||||
RootedScript script(cx, scope.asCall().callee().script());
|
||||
RootedScript script(cx, scope.asCall().callee().nonLazyScript());
|
||||
for (BindingIter bi(script); bi; bi++) {
|
||||
if (!bi->aliased() && !props.append(NameToId(bi->name())))
|
||||
return false;
|
||||
|
@ -1438,7 +1438,7 @@ class DebugScopeProxy : public BaseProxyHandler
|
|||
* a manual search is necessary.
|
||||
*/
|
||||
if (!found && scope->isCall() && !scope->asCall().isForEval()) {
|
||||
RootedScript script(cx, scope->asCall().callee().script());
|
||||
RootedScript script(cx, scope->asCall().callee().nonLazyScript());
|
||||
for (BindingIter bi(script); bi; bi++) {
|
||||
if (!bi->aliased() && NameToId(bi->name()) == id) {
|
||||
found = true;
|
||||
|
|
|
@ -139,7 +139,7 @@ StackFrame::initCallFrame(JSContext *cx, JSFunction &callee,
|
|||
LOWERED_CALL_APPLY |
|
||||
OVERFLOW_ARGS |
|
||||
UNDERFLOW_ARGS)) == 0);
|
||||
JS_ASSERT(callee.script() == script);
|
||||
JS_ASSERT(callee.nonLazyScript() == script);
|
||||
|
||||
/* Initialize stack frame members. */
|
||||
flags_ = FUNCTION | HAS_PREVPC | HAS_SCOPECHAIN | HAS_BLOCKCHAIN | flagsArg;
|
||||
|
@ -413,7 +413,7 @@ ContextStack::getCallFrame(JSContext *cx, MaybeReportError report, const CallArg
|
|||
JSFunction *fun, JSScript *script, StackFrame::Flags *flags) const
|
||||
{
|
||||
AssertCanGC();
|
||||
JS_ASSERT(fun->script() == script);
|
||||
JS_ASSERT(fun->nonLazyScript() == script);
|
||||
unsigned nformal = fun->nargs;
|
||||
|
||||
Value *firstUnused = args.end();
|
||||
|
@ -458,7 +458,7 @@ ContextStack::pushInlineFrame(JSContext *cx, FrameRegs ®s, const CallArgs &ar
|
|||
JS_ASSERT(onTop());
|
||||
JS_ASSERT(regs.sp == args.end());
|
||||
/* Cannot assert callee == args.callee() since this is called from LeaveTree. */
|
||||
JS_ASSERT(callee.script() == script);
|
||||
JS_ASSERT(callee.nonLazyScript() == script);
|
||||
|
||||
StackFrame::Flags flags = ToFrameFlags(initial);
|
||||
StackFrame *fp = getCallFrame(cx, report, args, &callee, script, &flags);
|
||||
|
@ -495,8 +495,8 @@ ContextStack::getFixupFrame(JSContext *cx, MaybeReportError report,
|
|||
{
|
||||
AssertCanGC();
|
||||
JS_ASSERT(onTop());
|
||||
JS_ASSERT(fun->script() == args.callee().toFunction()->script());
|
||||
JS_ASSERT(fun->script() == script);
|
||||
JS_ASSERT(fun->nonLazyScript() == args.callee().toFunction()->nonLazyScript());
|
||||
JS_ASSERT(fun->nonLazyScript() == script);
|
||||
|
||||
StackFrame::Flags flags = ToFrameFlags(initial);
|
||||
StackFrame *fp = getCallFrame(cx, report, args, fun, script, &flags);
|
||||
|
@ -564,7 +564,7 @@ ContextStack::currentScript(jsbytecode **ppc,
|
|||
mjit::JITChunk *chunk = fp->jit()->chunk(regs.pc);
|
||||
JS_ASSERT(inlined->inlineIndex < chunk->nInlineFrames);
|
||||
mjit::InlineFrame *frame = &chunk->inlineFrames()[inlined->inlineIndex];
|
||||
RawScript script = frame->fun->script().get(nogc);
|
||||
RawScript script = frame->fun->nonLazyScript().get(nogc);
|
||||
if (!allowCrossCompartment && script->compartment() != cx_->compartment)
|
||||
return NULL;
|
||||
if (ppc)
|
||||
|
|
|
@ -249,7 +249,7 @@ AssertDynamicScopeMatchesStaticScope(JSScript *script, JSObject *scope)
|
|||
scope = &scope->asClonedBlock().enclosingScope();
|
||||
break;
|
||||
case StaticScopeIter::FUNCTION:
|
||||
JS_ASSERT(scope->asCall().callee().script() == i.funScript());
|
||||
JS_ASSERT(scope->asCall().callee().nonLazyScript() == i.funScript());
|
||||
scope = &scope->asCall().enclosingScope();
|
||||
break;
|
||||
case StaticScopeIter::NAMED_LAMBDA:
|
||||
|
@ -363,7 +363,7 @@ StackFrame::epilogue(JSContext *cx)
|
|||
JS_ASSERT(isNonEvalFunctionFrame());
|
||||
|
||||
if (fun()->isHeavyweight())
|
||||
JS_ASSERT_IF(hasCallObj(), scopeChain()->asCall().callee().script() == script);
|
||||
JS_ASSERT_IF(hasCallObj(), scopeChain()->asCall().callee().nonLazyScript() == script);
|
||||
else
|
||||
AssertDynamicScopeMatchesStaticScope(script, scopeChain());
|
||||
|
||||
|
@ -903,7 +903,7 @@ ContextStack::ensureOnTop(JSContext *cx, MaybeReportError report, unsigned nvars
|
|||
|
||||
if (fun) {
|
||||
AutoCompartment ac(cx, fun);
|
||||
fun->script()->uninlineable = true;
|
||||
fun->nonLazyScript()->uninlineable = true;
|
||||
types::MarkTypeObjectFlags(cx, fun, types::OBJECT_FLAG_UNINLINEABLE);
|
||||
}
|
||||
}
|
||||
|
@ -991,7 +991,7 @@ ContextStack::pushInvokeFrame(JSContext *cx, MaybeReportError report,
|
|||
JS_ASSERT(onTop());
|
||||
JS_ASSERT(space().firstUnused() == args.end());
|
||||
|
||||
RootedScript script(cx, fun->script());
|
||||
RootedScript script(cx, fun->nonLazyScript());
|
||||
|
||||
StackFrame::Flags flags = ToFrameFlags(initial);
|
||||
StackFrame *fp = getCallFrame(cx, report, args, fun, script, &flags);
|
||||
|
|
|
@ -612,7 +612,7 @@ class StackFrame
|
|||
return isFunctionFrame()
|
||||
? isEvalFrame()
|
||||
? u.evalScript
|
||||
: (JSScript*)fun()->script().unsafeGet()
|
||||
: (JSScript*)fun()->nonLazyScript().unsafeGet()
|
||||
: exec.script;
|
||||
}
|
||||
|
||||
|
|
|
@ -67,7 +67,7 @@ interface nsIXPConnectJSObjectHolder : nsISupports
|
|||
readonly attribute JSObjectPtr JSObject;
|
||||
};
|
||||
|
||||
[uuid(f819a95a-6ab5-4a02-bda6-32861e859581)]
|
||||
[uuid(92e98688-0154-4b65-971b-0d4afe8fd7cb)]
|
||||
interface nsIXPConnectWrappedNative : nsIXPConnectJSObjectHolder
|
||||
{
|
||||
/* attribute 'JSObject' inherited from nsIXPConnectJSObjectHolder */
|
||||
|
@ -81,6 +81,7 @@ interface nsIXPConnectWrappedNative : nsIXPConnectJSObjectHolder
|
|||
readonly attribute nsIXPConnect XPConnect;
|
||||
nsIInterfaceInfo FindInterfaceWithMember(in jsid nameID);
|
||||
nsIInterfaceInfo FindInterfaceWithName(in jsid nameID);
|
||||
[notxpcom] bool HasNativeMember(in jsid name);
|
||||
|
||||
void debugDump(in short depth);
|
||||
|
||||
|
@ -288,7 +289,7 @@ interface nsIXPCFunctionThisTranslator : nsISupports
|
|||
{ 0xbd, 0xd6, 0x0, 0x0, 0x64, 0x65, 0x73, 0x74 } }
|
||||
%}
|
||||
|
||||
[uuid(e28a33ce-dfe9-4816-ae20-0f1dc8077230)]
|
||||
[uuid(b551afea-f38c-46d4-bc93-f1e05aebfec2)]
|
||||
interface nsIXPConnect : nsISupports
|
||||
{
|
||||
%{ C++
|
||||
|
@ -518,7 +519,7 @@ interface nsIXPConnect : nsISupports
|
|||
setFunctionThisTranslator(in nsIIDRef aIID,
|
||||
in nsIXPCFunctionThisTranslator aTranslator);
|
||||
|
||||
nsIXPConnectJSObjectHolder
|
||||
void
|
||||
reparentWrappedNativeIfFound(in JSContextPtr aJSContext,
|
||||
in JSObjectPtr aScope,
|
||||
in JSObjectPtr aNewParent,
|
||||
|
|
|
@ -118,7 +118,7 @@ interface ScheduledGCCallback : nsISupports
|
|||
/**
|
||||
* interface of Components.utils
|
||||
*/
|
||||
[scriptable, uuid(a93e230d-e883-4ff8-9aeb-dbe5cc771059)]
|
||||
[scriptable, uuid(b3290d8e-b010-4693-a261-10bbf006b8f0)]
|
||||
interface nsIXPCComponents_Utils : nsISupports
|
||||
{
|
||||
|
||||
|
@ -323,12 +323,22 @@ interface nsIXPCComponents_Utils : nsISupports
|
|||
* disappear at any moment.
|
||||
*
|
||||
* Forces a recomputation of all wrappers in and out of the compartment
|
||||
* containing |obj|. If |obj| is not an object, all wrappers system-wide
|
||||
* containing |vobj|. If |vobj| is not an object, all wrappers system-wide
|
||||
* are recomputed.
|
||||
*/
|
||||
[implicit_jscontext]
|
||||
void recomputeWrappers([optional] in jsval vobj);
|
||||
|
||||
/*
|
||||
* To be called from JS only. This is for Gecko internal use only, and may
|
||||
* disappear at any moment.
|
||||
*
|
||||
* Enables Xray vision for same-compartment access for the compartment
|
||||
* indicated by |vscope|. All outgoing wrappers are recomputed.
|
||||
*/
|
||||
[implicit_jscontext]
|
||||
void setWantXrays(in jsval vscope);
|
||||
|
||||
/*
|
||||
* This seemingly-paradoxical API allows privileged code to explicitly give
|
||||
* unprivileged code a reference to its own Components object (whereas it's
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче