зеркало из https://github.com/mozilla/gecko-dev.git
Merge m-c to s-c.
This commit is contained in:
Коммит
c96f2d2bc2
|
@ -81,24 +81,6 @@ getDocumentLocaleCB(AtkDocument *aDocument)
|
|||
return nsAccessibleWrap::ReturnString(locale);
|
||||
}
|
||||
|
||||
const gchar *
|
||||
getDocumentTypeCB(AtkDocument *aDocument)
|
||||
{
|
||||
nsAccessibleWrap *accWrap = GetAccessibleWrap(ATK_OBJECT(aDocument));
|
||||
if (!accWrap)
|
||||
return nsnull;
|
||||
|
||||
nsCOMPtr<nsIAccessibleDocument> accDocument;
|
||||
accWrap->QueryInterface(NS_GET_IID(nsIAccessibleDocument),
|
||||
getter_AddRefs(accDocument));
|
||||
NS_ENSURE_TRUE(accDocument, nsnull);
|
||||
|
||||
nsAutoString mimeType;
|
||||
nsresult rv = accDocument->GetMimeType(mimeType);
|
||||
NS_ENSURE_SUCCESS(rv, nsnull);
|
||||
return nsAccessibleWrap::ReturnString(mimeType);
|
||||
}
|
||||
|
||||
static inline GSList *
|
||||
prependToList(GSList *aList, const char *const aName, const nsAutoString &aValue)
|
||||
{
|
||||
|
|
|
@ -660,22 +660,6 @@ nsCoreUtils::GetFirstSensibleColumn(nsITreeBoxObject *aTree)
|
|||
return column.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<nsITreeColumn>
|
||||
nsCoreUtils::GetLastSensibleColumn(nsITreeBoxObject *aTree)
|
||||
{
|
||||
nsCOMPtr<nsITreeColumns> cols;
|
||||
aTree->GetColumns(getter_AddRefs(cols));
|
||||
if (!cols)
|
||||
return nsnull;
|
||||
|
||||
nsCOMPtr<nsITreeColumn> column;
|
||||
cols->GetLastColumn(getter_AddRefs(column));
|
||||
if (column && IsColumnHidden(column))
|
||||
return GetPreviousSensibleColumn(column);
|
||||
|
||||
return column.forget();
|
||||
}
|
||||
|
||||
PRUint32
|
||||
nsCoreUtils::GetSensibleColumnCount(nsITreeBoxObject *aTree)
|
||||
{
|
||||
|
|
|
@ -327,12 +327,6 @@ public:
|
|||
static already_AddRefed<nsITreeColumn>
|
||||
GetFirstSensibleColumn(nsITreeBoxObject *aTree);
|
||||
|
||||
/**
|
||||
* Return last sensible column for the given tree box object.
|
||||
*/
|
||||
static already_AddRefed<nsITreeColumn>
|
||||
GetLastSensibleColumn(nsITreeBoxObject *aTree);
|
||||
|
||||
/**
|
||||
* Return sensible columns count for the given tree box object.
|
||||
*/
|
||||
|
|
|
@ -86,6 +86,7 @@ if [ ! "$LIBXUL_SDK" ]; then
|
|||
if [ "$MOZ_WIDGET_TOOLKIT" = "android" ]; then
|
||||
add_makefiles "
|
||||
other-licenses/android/Makefile
|
||||
other-licenses/skia-npapi/Makefile
|
||||
"
|
||||
fi
|
||||
fi
|
||||
|
@ -115,6 +116,9 @@ if [ "$COMPILER_DEPEND" = "" -a "$MOZ_NATIVE_MAKEDEPEND" = "" ]; then
|
|||
fi
|
||||
|
||||
if [ "$ENABLE_TESTS" ]; then
|
||||
add_makefiles "
|
||||
build/autoconf/test/Makefile
|
||||
"
|
||||
if [ "$_MSC_VER" -a "$OS_TEST" != "x86_64" ]; then
|
||||
add_makefiles "
|
||||
build/win32/vmwarerecordinghelper/Makefile
|
||||
|
|
|
@ -3478,10 +3478,29 @@ const BrowserSearch = {
|
|||
if (!submission)
|
||||
return;
|
||||
|
||||
let newTab;
|
||||
function newTabHandler(event) {
|
||||
newTab = event.target;
|
||||
}
|
||||
gBrowser.tabContainer.addEventListener("TabOpen", newTabHandler);
|
||||
|
||||
openLinkIn(submission.uri.spec,
|
||||
useNewTab ? "tab" : "current",
|
||||
{ postData: submission.postData,
|
||||
relatedToCurrent: true });
|
||||
|
||||
gBrowser.tabContainer.removeEventListener("TabOpen", newTabHandler);
|
||||
if (newTab && !newTab.selected) {
|
||||
let tabSelected = false;
|
||||
function tabSelectHandler() {
|
||||
tabSelected = true;
|
||||
}
|
||||
newTab.addEventListener("TabSelect", tabSelectHandler);
|
||||
setTimeout(function () {
|
||||
newTab.removeEventListener("TabSelect", tabSelectHandler);
|
||||
Services.telemetry.getHistogramById("FX_CONTEXT_SEARCH_AND_TAB_SELECT").add(tabSelected);
|
||||
}, 5000);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -7659,7 +7678,8 @@ var FeedHandler = {
|
|||
if (browserForLink == gBrowser.selectedBrowser) {
|
||||
// Batch updates to avoid updating the UI for multiple onLinkAdded events
|
||||
// fired within 100ms of each other.
|
||||
clearTimeout(this._updateFeedTimeout);
|
||||
if (this._updateFeedTimeout)
|
||||
clearTimeout(this._updateFeedTimeout);
|
||||
this._updateFeedTimeout = setTimeout(this.updateFeeds.bind(this), 100);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -992,7 +992,7 @@ function makePreview(row)
|
|||
}
|
||||
#endif
|
||||
else {
|
||||
// fallback image for protocols not allowed (e.g., data: or javascript:)
|
||||
// fallback image for protocols not allowed (e.g., javascript:)
|
||||
// or elements not [yet] handled (e.g., object, embed).
|
||||
document.getElementById("brokenimagecontainer").collapsed = false;
|
||||
document.getElementById("theimagecontainer").collapsed = true;
|
||||
|
@ -1228,8 +1228,6 @@ function selectImage()
|
|||
function checkProtocol(img)
|
||||
{
|
||||
var url = img[COL_IMAGE_ADDRESS];
|
||||
if (/^data:/.test(url) && /^image\//.test(img[COL_IMAGE_NODE].type))
|
||||
return true;
|
||||
const regex = /^(https?|ftp|file|about|chrome|resource):/;
|
||||
return regex.test(url);
|
||||
return /^data:image\//i.test(url) ||
|
||||
/^(https?|ftp|file|about|chrome|resource):/.test(url);
|
||||
}
|
||||
|
|
|
@ -69,8 +69,10 @@ browser/components/shell/src/Makefile
|
|||
browser/components/tabview/Makefile
|
||||
browser/devtools/Makefile
|
||||
browser/devtools/highlighter/Makefile
|
||||
browser/devtools/scratchpad/Makefile
|
||||
browser/devtools/shared/Makefile
|
||||
browser/devtools/sourceeditor/Makefile
|
||||
browser/devtools/styleeditor/Makefile
|
||||
browser/devtools/styleinspector/Makefile
|
||||
browser/devtools/webconsole/Makefile
|
||||
browser/fuel/Makefile
|
||||
|
@ -140,6 +142,7 @@ if [ "$ENABLE_TESTS" ]; then
|
|||
browser/devtools/scratchpad/test/Makefile
|
||||
browser/devtools/shared/test/Makefile
|
||||
browser/devtools/sourceeditor/test/Makefile
|
||||
browser/devtools/styleeditor/test/Makefile
|
||||
browser/devtools/styleinspector/test/browser/Makefile
|
||||
browser/devtools/webconsole/test/browser/Makefile
|
||||
browser/fuel/test/Makefile
|
||||
|
|
|
@ -188,3 +188,7 @@ https://www.bank2.com:443 privileged,cert=escapeattack2
|
|||
#
|
||||
https://redirproxy.example.com:443 privileged,redir=test1.example.com
|
||||
|
||||
# Host used for IndexedDB Quota testing
|
||||
http://bug704464-1.example.com:80 privileged
|
||||
http://bug704464-2.example.com:80 privileged
|
||||
http://bug704464-3.example.com:80 privileged
|
||||
|
|
|
@ -1738,7 +1738,7 @@ nsScriptSecurityManager::CheckFunctionAccess(JSContext *aCx, void *aFunObj,
|
|||
#ifdef DEBUG
|
||||
{
|
||||
JS_ASSERT(JS_ObjectIsFunction(aCx, (JSObject *)aFunObj));
|
||||
JSFunction *fun = (JSFunction *)JS_GetPrivate(aCx, (JSObject *)aFunObj);
|
||||
JSFunction *fun = JS_GetObjectFunction((JSObject *)aFunObj);
|
||||
JSScript *script = JS_GetFunctionScript(aCx, fun);
|
||||
|
||||
NS_ASSERTION(!script, "Null principal for non-native function!");
|
||||
|
@ -2219,7 +2219,7 @@ nsScriptSecurityManager::GetFunctionObjectPrincipal(JSContext *cx,
|
|||
return result;
|
||||
}
|
||||
|
||||
JSFunction *fun = (JSFunction *)JS_GetPrivate(cx, obj);
|
||||
JSFunction *fun = JS_GetObjectFunction(obj);
|
||||
JSScript *script = JS_GetFunctionScript(cx, fun);
|
||||
|
||||
if (!script)
|
||||
|
@ -2243,7 +2243,7 @@ nsScriptSecurityManager::GetFunctionObjectPrincipal(JSContext *cx,
|
|||
|
||||
script = frameScript;
|
||||
}
|
||||
else if (JS_GetFunctionObject(fun) != obj)
|
||||
else if (!js::IsOriginalScriptFunction(fun))
|
||||
{
|
||||
// Here, obj is a cloned function object. In this case, the
|
||||
// clone's prototype may have been precompiled from brutally
|
||||
|
@ -2285,7 +2285,7 @@ nsScriptSecurityManager::GetFramePrincipal(JSContext *cx,
|
|||
#ifdef DEBUG
|
||||
if (NS_SUCCEEDED(*rv) && !result)
|
||||
{
|
||||
JSFunction *fun = (JSFunction *)JS_GetPrivate(cx, obj);
|
||||
JSFunction *fun = JS_GetObjectFunction(obj);
|
||||
JSScript *script = JS_GetFunctionScript(cx, fun);
|
||||
|
||||
NS_ASSERTION(!script, "Null principal for non-native function!");
|
||||
|
@ -2432,7 +2432,7 @@ nsScriptSecurityManager::doGetObjectPrincipal(JSObject *aObj
|
|||
jsClass = js::GetObjectClass(aObj);
|
||||
|
||||
if (jsClass == &js::CallClass) {
|
||||
aObj = js::GetObjectParent(aObj);
|
||||
aObj = js::GetObjectParentMaybeScope(aObj);
|
||||
|
||||
if (!aObj)
|
||||
return nsnull;
|
||||
|
@ -2484,7 +2484,7 @@ nsScriptSecurityManager::doGetObjectPrincipal(JSObject *aObj
|
|||
}
|
||||
}
|
||||
|
||||
aObj = js::GetObjectParent(aObj);
|
||||
aObj = js::GetObjectParentMaybeScope(aObj);
|
||||
|
||||
if (!aObj)
|
||||
break;
|
||||
|
|
|
@ -366,31 +366,6 @@ nsAttrAndChildArray::AttrAt(PRUint32 aPos) const
|
|||
return &ATTRS(mImpl)[aPos - mapped].mValue;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsAttrAndChildArray::SetAttr(nsIAtom* aLocalName, const nsAString& aValue)
|
||||
{
|
||||
PRUint32 i, slotCount = AttrSlotCount();
|
||||
for (i = 0; i < slotCount && AttrSlotIsTaken(i); ++i) {
|
||||
if (ATTRS(mImpl)[i].mName.Equals(aLocalName)) {
|
||||
ATTRS(mImpl)[i].mValue.SetTo(aValue);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
NS_ENSURE_TRUE(slotCount < ATTRCHILD_ARRAY_MAX_ATTR_COUNT,
|
||||
NS_ERROR_FAILURE);
|
||||
|
||||
if (i == slotCount && !AddAttrSlot()) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
new (&ATTRS(mImpl)[i].mName) nsAttrName(aLocalName);
|
||||
new (&ATTRS(mImpl)[i].mValue) nsAttrValue(aValue);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsAttrAndChildArray::SetAndTakeAttr(nsIAtom* aLocalName, nsAttrValue& aValue)
|
||||
{
|
||||
|
|
|
@ -103,7 +103,6 @@ public:
|
|||
PRUint32 AttrCount() const;
|
||||
const nsAttrValue* GetAttr(nsIAtom* aLocalName, PRInt32 aNamespaceID = kNameSpaceID_None) const;
|
||||
const nsAttrValue* AttrAt(PRUint32 aPos) const;
|
||||
nsresult SetAttr(nsIAtom* aLocalName, const nsAString& aValue);
|
||||
nsresult SetAndTakeAttr(nsIAtom* aLocalName, nsAttrValue& aValue);
|
||||
nsresult SetAndTakeAttr(nsINodeInfo* aName, nsAttrValue& aValue);
|
||||
|
||||
|
|
|
@ -594,6 +594,9 @@ GK_ATOM(x_moz_errormessage, "x-moz-errormessage")
|
|||
GK_ATOM(msthemecompatible, "msthemecompatible")
|
||||
GK_ATOM(multicol, "multicol")
|
||||
GK_ATOM(multiple, "multiple")
|
||||
#ifdef MOZ_MEDIA
|
||||
GK_ATOM(muted, "muted")
|
||||
#endif
|
||||
GK_ATOM(name, "name")
|
||||
GK_ATOM(_namespace, "namespace")
|
||||
GK_ATOM(namespaceAlias, "namespace-alias")
|
||||
|
|
|
@ -179,11 +179,11 @@ PRUint32 nsStyleLinkElement::ParseLinkTypes(const nsAString& aTypes)
|
|||
return linkMask;
|
||||
|
||||
nsAString::const_iterator current(start);
|
||||
bool inString = !nsCRT::IsAsciiSpace(*current);
|
||||
bool inString = !nsContentUtils::IsHTMLWhitespace(*current);
|
||||
nsAutoString subString;
|
||||
|
||||
while (current != done) {
|
||||
if (nsCRT::IsAsciiSpace(*current)) {
|
||||
if (nsContentUtils::IsHTMLWhitespace(*current)) {
|
||||
if (inString) {
|
||||
ToLowerCase(Substring(start, current), subString);
|
||||
linkMask |= ToLinkMask(subString);
|
||||
|
|
|
@ -253,6 +253,9 @@ nsIAtom** const kAttributesHTML[] = {
|
|||
&nsGkAtoms::min,
|
||||
&nsGkAtoms::mozdonotsend,
|
||||
&nsGkAtoms::multiple,
|
||||
#ifdef MOZ_MEDIA
|
||||
&nsGkAtoms::muted,
|
||||
#endif
|
||||
&nsGkAtoms::name,
|
||||
&nsGkAtoms::nohref,
|
||||
&nsGkAtoms::noshade,
|
||||
|
|
|
@ -743,7 +743,7 @@ nsXHTMLContentSerializer::IsShorthandAttr(const nsIAtom* aAttrName,
|
|||
#ifdef MOZ_MEDIA
|
||||
// autoplay and controls
|
||||
if ((aElementName == nsGkAtoms::video || aElementName == nsGkAtoms::audio) &&
|
||||
(aAttrName == nsGkAtoms::autoplay ||
|
||||
(aAttrName == nsGkAtoms::autoplay || aAttrName == nsGkAtoms::muted ||
|
||||
aAttrName == nsGkAtoms::controls)) {
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -1152,21 +1152,6 @@ nsXMLContentSerializer::CheckElementEnd(nsIContent * aContent,
|
|||
return aContent->GetChildCount() > 0;
|
||||
}
|
||||
|
||||
void
|
||||
nsXMLContentSerializer::AppendToString(const PRUnichar* aStr,
|
||||
PRInt32 aLength,
|
||||
nsAString& aOutputStr)
|
||||
{
|
||||
if (mBodyOnly && !mInBody) {
|
||||
return;
|
||||
}
|
||||
PRInt32 length = (aLength == -1) ? nsCRT::strlen(aStr) : aLength;
|
||||
|
||||
mColPos += length;
|
||||
|
||||
aOutputStr.Append(aStr, length);
|
||||
}
|
||||
|
||||
void
|
||||
nsXMLContentSerializer::AppendToString(const PRUnichar aChar,
|
||||
nsAString& aOutputStr)
|
||||
|
|
|
@ -102,13 +102,6 @@ class nsXMLContentSerializer : public nsIContentSerializer {
|
|||
|
||||
protected:
|
||||
|
||||
/**
|
||||
* Appends a PRUnichar string and increments the column position
|
||||
*/
|
||||
void AppendToString(const PRUnichar* aStr,
|
||||
PRInt32 aLength,
|
||||
nsAString& aOutputStr);
|
||||
|
||||
/**
|
||||
* Appends a PRUnichar character and increments the column position
|
||||
*/
|
||||
|
|
|
@ -101,34 +101,6 @@ DoDrawImageSecurityCheck(nsHTMLCanvasElement *aCanvasElement,
|
|||
aCanvasElement->SetWriteOnly();
|
||||
}
|
||||
|
||||
void
|
||||
LogMessage (const nsCString& errorString)
|
||||
{
|
||||
nsCOMPtr<nsIConsoleService> console(do_GetService(NS_CONSOLESERVICE_CONTRACTID));
|
||||
if (!console)
|
||||
return;
|
||||
|
||||
console->LogStringMessage(NS_ConvertUTF8toUTF16(errorString).get());
|
||||
fprintf(stderr, "%s\n", errorString.get());
|
||||
}
|
||||
|
||||
void
|
||||
LogMessagef (const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
char buf[256];
|
||||
|
||||
nsCOMPtr<nsIConsoleService> console(do_GetService(NS_CONSOLESERVICE_CONTRACTID));
|
||||
if (console) {
|
||||
PR_vsnprintf(buf, 256, fmt, ap);
|
||||
console->LogStringMessage(NS_ConvertUTF8toUTF16(nsDependentCString(buf)).get());
|
||||
fprintf(stderr, "%s\n", buf);
|
||||
}
|
||||
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
bool
|
||||
CoerceDouble(jsval v, double* d)
|
||||
{
|
||||
|
|
|
@ -77,9 +77,6 @@ void DoDrawImageSecurityCheck(nsHTMLCanvasElement *aCanvasElement,
|
|||
bool forceWriteOnly,
|
||||
bool CORSUsed);
|
||||
|
||||
void LogMessage (const nsCString& errorString);
|
||||
void LogMessagef (const char *fmt, ...);
|
||||
|
||||
// Make a double out of |v|, treating undefined values as 0.0 (for
|
||||
// the sake of sparse arrays). Return true iff coercion
|
||||
// succeeded.
|
||||
|
|
|
@ -1162,9 +1162,21 @@ WebGLContext::MaybeRestoreContext()
|
|||
if (mContextLost || mAllowRestore)
|
||||
return;
|
||||
|
||||
gl->MakeCurrent();
|
||||
GLContext::ContextResetARB resetStatus =
|
||||
(GLContext::ContextResetARB) gl->fGetGraphicsResetStatus();
|
||||
GLContext::ContextResetARB resetStatus = GLContext::CONTEXT_NO_ERROR;
|
||||
if (mHasRobustness) {
|
||||
gl->MakeCurrent();
|
||||
resetStatus = (GLContext::ContextResetARB) gl->fGetGraphicsResetStatus();
|
||||
// This call is safe as it does not actually interact with GL, so the
|
||||
// context does not have to be current.
|
||||
} else if (gl->GetContextType() == GLContext::ContextTypeEGL) {
|
||||
// Simulate a ARB_robustness guilty context loss for when we
|
||||
// get an EGL_CONTEXT_LOST error. It may not actually be guilty,
|
||||
// but we can't make any distinction, so we must assume the worst
|
||||
// case.
|
||||
if (!gl->MakeCurrent(true) && gl->IsContextLost()) {
|
||||
resetStatus = GLContext::CONTEXT_GUILTY_CONTEXT_RESET_ARB;
|
||||
}
|
||||
}
|
||||
|
||||
if (resetStatus != GLContext::CONTEXT_NO_ERROR) {
|
||||
// It's already lost, but clean up after it and signal to JS that it is
|
||||
|
|
|
@ -57,6 +57,7 @@
|
|||
#include "nsIDOMHTMLElement.h"
|
||||
#include "nsIJSNativeInitializer.h"
|
||||
#include "nsIMemoryReporter.h"
|
||||
#include "nsContentUtils.h"
|
||||
|
||||
#include "GLContextProvider.h"
|
||||
#include "Layers.h"
|
||||
|
@ -449,7 +450,7 @@ public:
|
|||
// Sets up the GL_ARB_robustness timer if it isn't already, so that if the
|
||||
// driver gets restarted, the context may get reset with it.
|
||||
void SetupRobustnessTimer() {
|
||||
if (mContextLost || !mHasRobustness)
|
||||
if (mContextLost || (!mHasRobustness && gl->GetContextType() != gl::GLContext::ContextTypeEGL))
|
||||
return;
|
||||
|
||||
// If the timer was already running, don't restart it here. Instead,
|
||||
|
|
|
@ -3993,7 +3993,10 @@ nsresult
|
|||
WebGLContext::DOMElementToImageSurface(nsIDOMElement *imageOrCanvas,
|
||||
gfxImageSurface **imageOut, int *format)
|
||||
{
|
||||
gfxImageSurface *surf = nsnull;
|
||||
nsCOMPtr<nsIContent> content = do_QueryInterface(imageOrCanvas);
|
||||
if (!content) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
PRUint32 flags =
|
||||
nsLayoutUtils::SFE_WANT_NEW_SURFACE |
|
||||
|
@ -4005,7 +4008,7 @@ WebGLContext::DOMElementToImageSurface(nsIDOMElement *imageOrCanvas,
|
|||
flags |= nsLayoutUtils::SFE_NO_PREMULTIPLY_ALPHA;
|
||||
|
||||
nsLayoutUtils::SurfaceFromElementResult res =
|
||||
nsLayoutUtils::SurfaceFromElement(imageOrCanvas, flags);
|
||||
nsLayoutUtils::SurfaceFromElement(content->AsElement(), flags);
|
||||
if (!res.mSurface)
|
||||
return NS_ERROR_FAILURE;
|
||||
if (res.mSurface->GetType() != gfxASurface::SurfaceTypeImage) {
|
||||
|
@ -4034,11 +4037,10 @@ WebGLContext::DOMElementToImageSurface(nsIDOMElement *imageOrCanvas,
|
|||
}
|
||||
}
|
||||
|
||||
// part 2: if the DOM element is a canvas, check that it's not write-only. That would indicate a tainted canvas,
|
||||
// i.e. a canvas that could contain cross-domain image data.
|
||||
nsCOMPtr<nsIContent> maybeDOMCanvas = do_QueryInterface(imageOrCanvas);
|
||||
if (maybeDOMCanvas && maybeDOMCanvas->IsHTML(nsGkAtoms::canvas)) {
|
||||
nsHTMLCanvasElement *canvas = static_cast<nsHTMLCanvasElement*>(maybeDOMCanvas.get());
|
||||
// part 2: if the DOM element is a canvas, check that it's not write-only.
|
||||
// That would indicate a tainted canvas, i.e. a canvas that could contain
|
||||
// cross-domain image data.
|
||||
if (nsHTMLCanvasElement* canvas = nsHTMLCanvasElement::FromContent(content)) {
|
||||
if (canvas->IsWriteOnly()) {
|
||||
LogMessageIfVerbose("The canvas used as source for texImage2D here is tainted (write-only). It is forbidden "
|
||||
"to load a WebGL texture from a tainted canvas. A Canvas becomes tainted for example "
|
||||
|
@ -4052,7 +4054,7 @@ WebGLContext::DOMElementToImageSurface(nsIDOMElement *imageOrCanvas,
|
|||
// Notice that there is never a need to mark the WebGL canvas as write-only, since we reject write-only/cross-domain
|
||||
// texture sources in the first place.
|
||||
|
||||
surf = static_cast<gfxImageSurface*>(res.mSurface.get());
|
||||
gfxImageSurface* surf = static_cast<gfxImageSurface*>(res.mSurface.get());
|
||||
|
||||
res.mSurface.forget();
|
||||
*imageOut = surf;
|
||||
|
|
|
@ -1813,11 +1813,12 @@ nsCanvasRenderingContext2D::CreatePattern(nsIDOMHTMLElement *image,
|
|||
const nsAString& repeat,
|
||||
nsIDOMCanvasPattern **_retval)
|
||||
{
|
||||
if (!image) {
|
||||
nsCOMPtr<nsIContent> content = do_QueryInterface(image);
|
||||
if (!content) {
|
||||
return NS_ERROR_DOM_TYPE_MISMATCH_ERR;
|
||||
}
|
||||
gfxPattern::GraphicsExtend extend;
|
||||
|
||||
gfxPattern::GraphicsExtend extend;
|
||||
if (repeat.IsEmpty() || repeat.EqualsLiteral("repeat")) {
|
||||
extend = gfxPattern::EXTEND_REPEAT;
|
||||
} else if (repeat.EqualsLiteral("repeat-x")) {
|
||||
|
@ -1833,7 +1834,6 @@ nsCanvasRenderingContext2D::CreatePattern(nsIDOMHTMLElement *image,
|
|||
return NS_ERROR_DOM_SYNTAX_ERR;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIContent> content = do_QueryInterface(image);
|
||||
nsHTMLCanvasElement* canvas = nsHTMLCanvasElement::FromContent(content);
|
||||
if (canvas) {
|
||||
nsIntSize size = canvas->GetSize();
|
||||
|
@ -1845,8 +1845,8 @@ nsCanvasRenderingContext2D::CreatePattern(nsIDOMHTMLElement *image,
|
|||
// The canvas spec says that createPattern should use the first frame
|
||||
// of animated images
|
||||
nsLayoutUtils::SurfaceFromElementResult res =
|
||||
nsLayoutUtils::SurfaceFromElement(image, nsLayoutUtils::SFE_WANT_FIRST_FRAME |
|
||||
nsLayoutUtils::SFE_WANT_NEW_SURFACE);
|
||||
nsLayoutUtils::SurfaceFromElement(content->AsElement(),
|
||||
nsLayoutUtils::SFE_WANT_FIRST_FRAME | nsLayoutUtils::SFE_WANT_NEW_SURFACE);
|
||||
if (!res.mSurface)
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
|
||||
|
@ -3399,11 +3399,11 @@ nsCanvasRenderingContext2D::DrawImage(nsIDOMElement *imgElt, float a1,
|
|||
if (!EnsureSurface())
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
if (!imgElt) {
|
||||
nsCOMPtr<nsIContent> content = do_QueryInterface(imgElt);
|
||||
if (!content) {
|
||||
return NS_ERROR_DOM_TYPE_MISMATCH_ERR;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIContent> content = do_QueryInterface(imgElt);
|
||||
nsHTMLCanvasElement* canvas = nsHTMLCanvasElement::FromContent(content);
|
||||
if (canvas) {
|
||||
nsIntSize size = canvas->GetSize();
|
||||
|
@ -3423,7 +3423,7 @@ nsCanvasRenderingContext2D::DrawImage(nsIDOMElement *imgElt, float a1,
|
|||
// of animated images
|
||||
PRUint32 sfeFlags = nsLayoutUtils::SFE_WANT_FIRST_FRAME;
|
||||
nsLayoutUtils::SurfaceFromElementResult res =
|
||||
nsLayoutUtils::SurfaceFromElement(imgElt, sfeFlags);
|
||||
nsLayoutUtils::SurfaceFromElement(content->AsElement(), sfeFlags);
|
||||
if (!res.mSurface) {
|
||||
// Spec says to silently do nothing if the element is still loading.
|
||||
return res.mIsStillLoading ? NS_OK : NS_ERROR_NOT_AVAILABLE;
|
||||
|
@ -3433,7 +3433,8 @@ nsCanvasRenderingContext2D::DrawImage(nsIDOMElement *imgElt, float a1,
|
|||
// as a source to work around some Cairo self-copy semantics issues.
|
||||
if (res.mSurface == mSurface) {
|
||||
sfeFlags |= nsLayoutUtils::SFE_WANT_NEW_SURFACE;
|
||||
res = nsLayoutUtils::SurfaceFromElement(imgElt, sfeFlags);
|
||||
res = nsLayoutUtils::SurfaceFromElement(content->AsElement(),
|
||||
sfeFlags);
|
||||
if (!res.mSurface)
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
|
|
@ -1889,7 +1889,8 @@ nsCanvasRenderingContext2DAzure::CreatePattern(nsIDOMHTMLElement *image,
|
|||
const nsAString& repeat,
|
||||
nsIDOMCanvasPattern **_retval)
|
||||
{
|
||||
if (!image) {
|
||||
nsCOMPtr<nsIContent> content = do_QueryInterface(image);
|
||||
if (!content) {
|
||||
return NS_ERROR_DOM_TYPE_MISMATCH_ERR;
|
||||
}
|
||||
|
||||
|
@ -1908,9 +1909,7 @@ nsCanvasRenderingContext2DAzure::CreatePattern(nsIDOMHTMLElement *image,
|
|||
return NS_ERROR_DOM_SYNTAX_ERR;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIContent> content = do_QueryInterface(image);
|
||||
nsHTMLCanvasElement* canvas = nsHTMLCanvasElement::FromContent(content);
|
||||
|
||||
if (canvas) {
|
||||
nsIntSize size = canvas->GetSize();
|
||||
if (size.width == 0 || size.height == 0) {
|
||||
|
@ -1939,8 +1938,8 @@ nsCanvasRenderingContext2DAzure::CreatePattern(nsIDOMHTMLElement *image,
|
|||
// The canvas spec says that createPattern should use the first frame
|
||||
// of animated images
|
||||
nsLayoutUtils::SurfaceFromElementResult res =
|
||||
nsLayoutUtils::SurfaceFromElement(image, nsLayoutUtils::SFE_WANT_FIRST_FRAME |
|
||||
nsLayoutUtils::SFE_WANT_NEW_SURFACE);
|
||||
nsLayoutUtils::SurfaceFromElement(content->AsElement(),
|
||||
nsLayoutUtils::SFE_WANT_FIRST_FRAME | nsLayoutUtils::SFE_WANT_NEW_SURFACE);
|
||||
|
||||
if (!res.mSurface) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
|
@ -3570,7 +3569,8 @@ nsCanvasRenderingContext2DAzure::DrawImage(nsIDOMElement *imgElt, float a1,
|
|||
float a6, float a7, float a8,
|
||||
PRUint8 optional_argc)
|
||||
{
|
||||
if (!imgElt) {
|
||||
nsCOMPtr<nsIContent> content = do_QueryInterface(imgElt);
|
||||
if (!content) {
|
||||
return NS_ERROR_DOM_TYPE_MISMATCH_ERR;
|
||||
}
|
||||
|
||||
|
@ -3591,7 +3591,6 @@ nsCanvasRenderingContext2DAzure::DrawImage(nsIDOMElement *imgElt, float a1,
|
|||
double sx,sy,sw,sh;
|
||||
double dx,dy,dw,dh;
|
||||
|
||||
nsCOMPtr<nsIContent> content = do_QueryInterface(imgElt);
|
||||
nsHTMLCanvasElement* canvas = nsHTMLCanvasElement::FromContent(content);
|
||||
if (canvas) {
|
||||
nsIntSize size = canvas->GetSize();
|
||||
|
@ -3643,7 +3642,7 @@ nsCanvasRenderingContext2DAzure::DrawImage(nsIDOMElement *imgElt, float a1,
|
|||
// of animated images
|
||||
PRUint32 sfeFlags = nsLayoutUtils::SFE_WANT_FIRST_FRAME;
|
||||
nsLayoutUtils::SurfaceFromElementResult res =
|
||||
nsLayoutUtils::SurfaceFromElement(imgElt, sfeFlags);
|
||||
nsLayoutUtils::SurfaceFromElement(content->AsElement(), sfeFlags);
|
||||
|
||||
if (!res.mSurface) {
|
||||
// Spec says to silently do nothing if the element is still loading.
|
||||
|
|
|
@ -48,6 +48,14 @@ public:
|
|||
nsHTMLVideoElement(already_AddRefed<nsINodeInfo> aNodeInfo);
|
||||
virtual ~nsHTMLVideoElement();
|
||||
|
||||
static nsHTMLVideoElement* FromContent(nsIContent* aPossibleVideo)
|
||||
{
|
||||
if (!aPossibleVideo || !aPossibleVideo->IsHTML(nsGkAtoms::video)) {
|
||||
return NULL;
|
||||
}
|
||||
return static_cast<nsHTMLVideoElement*>(aPossibleVideo);
|
||||
}
|
||||
|
||||
// nsISupports
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
||||
|
|
|
@ -1516,6 +1516,9 @@ nsresult nsHTMLMediaElement::SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
|
|||
if (aNameSpaceID == kNameSpaceID_None && aName == nsGkAtoms::src) {
|
||||
Load();
|
||||
}
|
||||
if (aNameSpaceID == kNameSpaceID_None && aName == nsGkAtoms::muted) {
|
||||
mMuted = true;
|
||||
}
|
||||
if (aNotify && aNameSpaceID == kNameSpaceID_None) {
|
||||
if (aName == nsGkAtoms::autoplay) {
|
||||
StopSuspendingAfterFirstFrame();
|
||||
|
@ -2687,18 +2690,17 @@ nsHTMLMediaElement::CopyInnerTo(nsGenericElement* aDest) const
|
|||
dest->mMediaSize = mMediaSize;
|
||||
} else {
|
||||
nsIFrame* frame = GetPrimaryFrame();
|
||||
nsCOMPtr<nsIDOMElement> elem;
|
||||
Element* element;
|
||||
if (frame && frame->GetType() == nsGkAtoms::HTMLVideoFrame &&
|
||||
static_cast<nsVideoFrame*>(frame)->ShouldDisplayPoster()) {
|
||||
elem = do_QueryInterface(static_cast<nsVideoFrame*>(frame)->
|
||||
GetPosterImage());
|
||||
nsIContent* content = static_cast<nsVideoFrame*>(frame)->GetPosterImage();
|
||||
element = content ? content->AsElement() : NULL;
|
||||
} else {
|
||||
elem = do_QueryInterface(
|
||||
static_cast<nsGenericElement*>(const_cast<nsHTMLMediaElement*>(this)));
|
||||
element = const_cast<nsHTMLMediaElement*>(this);
|
||||
}
|
||||
|
||||
nsLayoutUtils::SurfaceFromElementResult res =
|
||||
nsLayoutUtils::SurfaceFromElement(elem,
|
||||
nsLayoutUtils::SurfaceFromElement(element,
|
||||
nsLayoutUtils::SFE_WANT_NEW_SURFACE);
|
||||
dest->mPrintSurface = res.mSurface;
|
||||
dest->mMediaSize = nsIntSize(res.mSize.width, res.mSize.height);
|
||||
|
|
|
@ -1745,7 +1745,8 @@ nsHTMLDocument::Open(const nsAString& aContentTypeOrUrl,
|
|||
|
||||
nsCOMPtr<nsIScriptGlobalObject> newScope(do_QueryReferent(mScopeObject));
|
||||
if (oldScope && newScope != oldScope) {
|
||||
nsContentUtils::ReparentContentWrappersInScope(cx, oldScope, newScope);
|
||||
rv = nsContentUtils::ReparentContentWrappersInScope(cx, oldScope, newScope);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1954,6 +1955,8 @@ nsHTMLDocument::WriteCommon(JSContext *cx,
|
|||
if (NS_FAILED(rv) || !mParser) {
|
||||
return rv;
|
||||
}
|
||||
NS_ABORT_IF_FALSE(!JS_IsExceptionPending(cx),
|
||||
"Open() succeeded but JS exception is pending");
|
||||
}
|
||||
|
||||
static NS_NAMED_LITERAL_STRING(new_line, "\n");
|
||||
|
|
|
@ -2364,23 +2364,6 @@ nsXULDocument::ContextStack::SetTopIndex(PRInt32 aIndex)
|
|||
}
|
||||
|
||||
|
||||
bool
|
||||
nsXULDocument::ContextStack::IsInsideXULTemplate()
|
||||
{
|
||||
if (mDepth) {
|
||||
for (nsIContent* element = mTop->mElement; element;
|
||||
element = element->GetParent()) {
|
||||
|
||||
if (element->NodeInfo()->Equals(nsGkAtoms::_template,
|
||||
kNameSpaceID_XUL)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
//
|
||||
// Content model walking routines
|
||||
|
|
|
@ -357,8 +357,6 @@ protected:
|
|||
nsresult Peek(nsXULPrototypeElement** aPrototype, nsIContent** aElement, PRInt32* aIndex);
|
||||
|
||||
nsresult SetTopIndex(PRInt32 aIndex);
|
||||
|
||||
bool IsInsideXULTemplate();
|
||||
};
|
||||
|
||||
friend class ContextStack;
|
||||
|
|
|
@ -454,13 +454,6 @@ TestNode::Constrain(InstantiationSet& aInstantiations)
|
|||
}
|
||||
|
||||
|
||||
bool
|
||||
TestNode::HasAncestor(const ReteNode* aNode) const
|
||||
{
|
||||
return aNode == this || (mParent && mParent->HasAncestor(aNode));
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
ReteNodeSet::ReteNodeSet()
|
||||
|
|
|
@ -878,14 +878,6 @@ public:
|
|||
bool* aCantHandleYet) const = 0;
|
||||
//XXX probably better named "ApplyConstraints" or "Discrminiate" or something
|
||||
|
||||
/**
|
||||
* Determine if this node has another node as its direct ancestor.
|
||||
* @param aNode the node to look for.
|
||||
* @return true if aNode is a direct ancestor of this node, false
|
||||
* otherwise.
|
||||
*/
|
||||
bool HasAncestor(const ReteNode* aNode) const;
|
||||
|
||||
/**
|
||||
* Add another node as a child of this node.
|
||||
* @param aNode the node to add.
|
||||
|
|
|
@ -869,10 +869,18 @@ nsDOMWindowUtils::NodesFromRect(float aX, float aY,
|
|||
}
|
||||
|
||||
static already_AddRefed<gfxImageSurface>
|
||||
CanvasToImageSurface(nsIDOMHTMLCanvasElement *canvas)
|
||||
CanvasToImageSurface(nsIDOMHTMLCanvasElement* aCanvas)
|
||||
{
|
||||
nsCOMPtr<nsINode> node = do_QueryInterface(aCanvas);
|
||||
if (!node) {
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
NS_ABORT_IF_FALSE(node->IsElement(),
|
||||
"An nsINode that implements nsIDOMHTMLCanvasElement should "
|
||||
"be an element.");
|
||||
nsLayoutUtils::SurfaceFromElementResult result =
|
||||
nsLayoutUtils::SurfaceFromElement(canvas,
|
||||
nsLayoutUtils::SurfaceFromElement(node->AsElement(),
|
||||
nsLayoutUtils::SFE_WANT_IMAGE_SURFACE);
|
||||
return static_cast<gfxImageSurface*>(result.mSurface.forget().get());
|
||||
}
|
||||
|
@ -1442,44 +1450,20 @@ nsDOMWindowUtils::SendContentCommandEvent(const nsAString& aType,
|
|||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWindowUtils::GetClassName(char **aName)
|
||||
nsDOMWindowUtils::GetClassName(const JS::Value& aObject, JSContext* aCx, char** aName)
|
||||
{
|
||||
if (!nsContentUtils::IsCallerTrustedForRead()) {
|
||||
return NS_ERROR_DOM_SECURITY_ERR;
|
||||
}
|
||||
|
||||
// get the xpconnect native call context
|
||||
nsAXPCNativeCallContext *cc = nsnull;
|
||||
nsContentUtils::XPConnect()->GetCurrentNativeCallContext(&cc);
|
||||
if(!cc)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
// Get JSContext of current call
|
||||
JSContext* cx;
|
||||
nsresult rv = cc->GetJSContext(&cx);
|
||||
if(NS_FAILED(rv) || !cx)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
// get argc and argv and verify arg count
|
||||
PRUint32 argc;
|
||||
rv = cc->GetArgc(&argc);
|
||||
if(NS_FAILED(rv))
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
if(argc < 1)
|
||||
return NS_ERROR_XPC_NOT_ENOUGH_ARGS;
|
||||
|
||||
jsval* argv;
|
||||
rv = cc->GetArgvPtr(&argv);
|
||||
if(NS_FAILED(rv) || !argv)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
// Our argument must be a non-null object.
|
||||
if(JSVAL_IS_PRIMITIVE(argv[0]))
|
||||
if (JSVAL_IS_PRIMITIVE(aObject)) {
|
||||
return NS_ERROR_XPC_BAD_CONVERT_JS;
|
||||
}
|
||||
|
||||
*aName = NS_strdup(JS_GET_CLASS(cx, JSVAL_TO_OBJECT(argv[0]))->name);
|
||||
return *aName ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
|
||||
*aName = NS_strdup(JS_GET_CLASS(aCx, JSVAL_TO_OBJECT(aObject))->name);
|
||||
NS_ABORT_IF_FALSE(*aName, "NS_strdup should be infallible.");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
|
|
@ -279,7 +279,7 @@ AsyncConnectionHelper::Run()
|
|||
if (NS_SUCCEEDED(rv)) {
|
||||
bool hasSavepoint = false;
|
||||
if (mDatabase) {
|
||||
IndexedDatabaseManager::SetCurrentDatabase(mDatabase);
|
||||
IndexedDatabaseManager::SetCurrentWindow(mDatabase->Owner());
|
||||
|
||||
// Make the first savepoint.
|
||||
if (mTransaction) {
|
||||
|
@ -292,7 +292,7 @@ AsyncConnectionHelper::Run()
|
|||
mResultCode = DoDatabaseWork(connection);
|
||||
|
||||
if (mDatabase) {
|
||||
IndexedDatabaseManager::SetCurrentDatabase(nsnull);
|
||||
IndexedDatabaseManager::SetCurrentWindow(nsnull);
|
||||
|
||||
// Release or roll back the savepoint depending on the error code.
|
||||
if (hasSavepoint) {
|
||||
|
|
|
@ -98,11 +98,9 @@ GetQuotaPermissions(const nsACString& aASCIIOrigin,
|
|||
|
||||
} // anonymous namespace
|
||||
|
||||
CheckQuotaHelper::CheckQuotaHelper(IDBDatabase* aDatabase,
|
||||
CheckQuotaHelper::CheckQuotaHelper(nsPIDOMWindow* aWindow,
|
||||
mozilla::Mutex& aMutex)
|
||||
: mWindow(aDatabase->Owner()),
|
||||
mWindowSerial(mWindow->GetSerial()),
|
||||
mOrigin(aDatabase->Origin()),
|
||||
: mWindow(aWindow),
|
||||
mMutex(aMutex),
|
||||
mCondVar(mMutex, "CheckQuotaHelper::mCondVar"),
|
||||
mPromptResult(0),
|
||||
|
@ -175,51 +173,59 @@ CheckQuotaHelper::Run()
|
|||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
if (!mHasPrompted) {
|
||||
mPromptResult = GetQuotaPermissions(mOrigin, mWindow);
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
if (mASCIIOrigin.IsEmpty()) {
|
||||
rv = IndexedDatabaseManager::GetASCIIOriginFromWindow(mWindow,
|
||||
mASCIIOrigin);
|
||||
}
|
||||
|
||||
nsresult rv;
|
||||
if (mHasPrompted) {
|
||||
// Add permissions to the database, but only if we are in the parent
|
||||
// process (if we are in the child process, we have already
|
||||
// set the permission when the prompt was shown in the parent, as
|
||||
// we cannot set the permission from the child).
|
||||
if (mPromptResult != nsIPermissionManager::UNKNOWN_ACTION &&
|
||||
XRE_GetProcessType() == GeckoProcessType_Default) {
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
rv = NS_NewURI(getter_AddRefs(uri), mOrigin);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIPermissionManager> permissionManager =
|
||||
do_GetService(NS_PERMISSIONMANAGER_CONTRACTID);
|
||||
NS_ENSURE_STATE(permissionManager);
|
||||
|
||||
rv = permissionManager->Add(uri, PERMISSION_INDEXEDDB_UNLIMITED,
|
||||
mPromptResult,
|
||||
nsIPermissionManager::EXPIRE_NEVER, 0);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
if (!mHasPrompted) {
|
||||
mPromptResult = GetQuotaPermissions(mASCIIOrigin, mWindow);
|
||||
}
|
||||
}
|
||||
else if (mPromptResult == nsIPermissionManager::UNKNOWN_ACTION) {
|
||||
PRUint32 quota = IndexedDatabaseManager::GetIndexedDBQuotaMB();
|
||||
|
||||
nsString quotaString;
|
||||
quotaString.AppendInt(quota);
|
||||
if (mHasPrompted) {
|
||||
// Add permissions to the database, but only if we are in the parent
|
||||
// process (if we are in the child process, we have already
|
||||
// set the permission when the prompt was shown in the parent, as
|
||||
// we cannot set the permission from the child).
|
||||
if (mPromptResult != nsIPermissionManager::UNKNOWN_ACTION &&
|
||||
XRE_GetProcessType() == GeckoProcessType_Default) {
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
rv = NS_NewURI(getter_AddRefs(uri), mASCIIOrigin);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIPermissionManager> permissionManager =
|
||||
do_GetService(NS_PERMISSIONMANAGER_CONTRACTID);
|
||||
NS_ENSURE_STATE(permissionManager);
|
||||
|
||||
rv = permissionManager->Add(uri, PERMISSION_INDEXEDDB_UNLIMITED,
|
||||
mPromptResult,
|
||||
nsIPermissionManager::EXPIRE_NEVER, 0);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
}
|
||||
else if (mPromptResult == nsIPermissionManager::UNKNOWN_ACTION) {
|
||||
PRUint32 quota = IndexedDatabaseManager::GetIndexedDBQuotaMB();
|
||||
|
||||
nsCOMPtr<nsIObserverService> obs = GetObserverService();
|
||||
NS_ENSURE_STATE(obs);
|
||||
nsString quotaString;
|
||||
quotaString.AppendInt(quota);
|
||||
|
||||
// We have to watch to make sure that the window doesn't go away without
|
||||
// responding to us. Otherwise our database threads will hang.
|
||||
rv = obs->AddObserver(this, DOM_WINDOW_DESTROYED_TOPIC, false);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
nsCOMPtr<nsIObserverService> obs = GetObserverService();
|
||||
NS_ENSURE_STATE(obs);
|
||||
|
||||
rv = obs->NotifyObservers(static_cast<nsIRunnable*>(this),
|
||||
TOPIC_QUOTA_PROMPT, quotaString.get());
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
// We have to watch to make sure that the window doesn't go away without
|
||||
// responding to us. Otherwise our database threads will hang.
|
||||
rv = obs->AddObserver(this, DOM_WINDOW_DESTROYED_TOPIC, false);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
rv = obs->NotifyObservers(static_cast<nsIRunnable*>(this),
|
||||
TOPIC_QUOTA_PROMPT, quotaString.get());
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
MutexAutoLock lock(mMutex);
|
||||
|
|
|
@ -65,23 +65,17 @@ public:
|
|||
NS_DECL_NSIINTERFACEREQUESTOR
|
||||
NS_DECL_NSIOBSERVER
|
||||
|
||||
CheckQuotaHelper(IDBDatabase* aDatabase,
|
||||
CheckQuotaHelper(nsPIDOMWindow* aWindow,
|
||||
mozilla::Mutex& aMutex);
|
||||
|
||||
bool PromptAndReturnQuotaIsDisabled();
|
||||
|
||||
void Cancel();
|
||||
|
||||
PRUint32 WindowSerial()
|
||||
{
|
||||
return mWindowSerial;
|
||||
}
|
||||
|
||||
private:
|
||||
nsPIDOMWindow* mWindow;
|
||||
PRUint32 mWindowSerial;
|
||||
nsCString mOrigin;
|
||||
|
||||
nsCString mASCIIOrigin;
|
||||
mozilla::Mutex& mMutex;
|
||||
mozilla::CondVar mCondVar;
|
||||
PRUint32 mPromptResult;
|
||||
|
|
|
@ -64,12 +64,6 @@ USING_INDEXEDDB_NAMESPACE
|
|||
|
||||
namespace {
|
||||
|
||||
PRUint32 gDatabaseInstanceCount = 0;
|
||||
mozilla::Mutex* gPromptHelpersMutex = nsnull;
|
||||
|
||||
// Protected by gPromptHelpersMutex.
|
||||
nsTArray<nsRefPtr<CheckQuotaHelper> >* gPromptHelpers = nsnull;
|
||||
|
||||
class CreateObjectStoreHelper : public AsyncConnectionHelper
|
||||
{
|
||||
public:
|
||||
|
@ -195,11 +189,6 @@ IDBDatabase::IDBDatabase()
|
|||
mRunningVersionChange(false)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
if (!gDatabaseInstanceCount++) {
|
||||
NS_ASSERTION(!gPromptHelpersMutex, "Should be null!");
|
||||
gPromptHelpersMutex = new mozilla::Mutex("IDBDatabase gPromptHelpersMutex");
|
||||
}
|
||||
}
|
||||
|
||||
IDBDatabase::~IDBDatabase()
|
||||
|
@ -218,86 +207,20 @@ IDBDatabase::~IDBDatabase()
|
|||
if (mListenerManager) {
|
||||
mListenerManager->Disconnect();
|
||||
}
|
||||
|
||||
if (!--gDatabaseInstanceCount) {
|
||||
NS_ASSERTION(gPromptHelpersMutex, "Should not be null!");
|
||||
|
||||
delete gPromptHelpers;
|
||||
gPromptHelpers = nsnull;
|
||||
|
||||
delete gPromptHelpersMutex;
|
||||
gPromptHelpersMutex = nsnull;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
IDBDatabase::IsQuotaDisabled()
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
NS_ASSERTION(gPromptHelpersMutex, "This should never be null!");
|
||||
|
||||
MutexAutoLock lock(*gPromptHelpersMutex);
|
||||
|
||||
if (!gPromptHelpers) {
|
||||
gPromptHelpers = new nsAutoTArray<nsRefPtr<CheckQuotaHelper>, 10>();
|
||||
}
|
||||
|
||||
CheckQuotaHelper* foundHelper = nsnull;
|
||||
|
||||
PRUint32 count = gPromptHelpers->Length();
|
||||
for (PRUint32 index = 0; index < count; index++) {
|
||||
nsRefPtr<CheckQuotaHelper>& helper = gPromptHelpers->ElementAt(index);
|
||||
if (helper->WindowSerial() == Owner()->GetSerial()) {
|
||||
foundHelper = helper;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!foundHelper) {
|
||||
nsRefPtr<CheckQuotaHelper>* newHelper = gPromptHelpers->AppendElement();
|
||||
if (!newHelper) {
|
||||
NS_WARNING("Out of memory!");
|
||||
return false;
|
||||
}
|
||||
*newHelper = new CheckQuotaHelper(this, *gPromptHelpersMutex);
|
||||
foundHelper = *newHelper;
|
||||
|
||||
{
|
||||
// Unlock before calling out to XPCOM.
|
||||
MutexAutoUnlock unlock(*gPromptHelpersMutex);
|
||||
|
||||
nsresult rv = NS_DispatchToMainThread(foundHelper, NS_DISPATCH_NORMAL);
|
||||
NS_ENSURE_SUCCESS(rv, false);
|
||||
}
|
||||
}
|
||||
|
||||
return foundHelper->PromptAndReturnQuotaIsDisabled();
|
||||
}
|
||||
|
||||
void
|
||||
IDBDatabase::Invalidate()
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
NS_ASSERTION(gPromptHelpersMutex, "This should never be null!");
|
||||
|
||||
// Make sure we're closed too.
|
||||
Close();
|
||||
|
||||
// Cancel any quota prompts that are currently being displayed.
|
||||
{
|
||||
MutexAutoLock lock(*gPromptHelpersMutex);
|
||||
|
||||
if (gPromptHelpers) {
|
||||
PRUint32 count = gPromptHelpers->Length();
|
||||
for (PRUint32 index = 0; index < count; index++) {
|
||||
nsRefPtr<CheckQuotaHelper>& helper = gPromptHelpers->ElementAt(index);
|
||||
if (helper->WindowSerial() == Owner()->GetSerial()) {
|
||||
helper->Cancel();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// When the IndexedDatabaseManager needs to invalidate databases, all it has
|
||||
// is an origin, so we call back into the manager to cancel any prompts for
|
||||
// our owner.
|
||||
IndexedDatabaseManager::CancelPromptsForWindow(Owner());
|
||||
|
||||
mInvalidated = true;
|
||||
}
|
||||
|
|
|
@ -122,8 +122,6 @@ public:
|
|||
return doc.forget();
|
||||
}
|
||||
|
||||
bool IsQuotaDisabled();
|
||||
|
||||
nsCString& Origin()
|
||||
{
|
||||
return mASCIIOrigin;
|
||||
|
|
|
@ -403,24 +403,10 @@ IDBFactory::OpenCommon(const nsAString& aName,
|
|||
nsIScriptContext* context = sgo->GetContext();
|
||||
NS_ENSURE_TRUE(context, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
|
||||
|
||||
nsCOMPtr<nsIPrincipal> principal;
|
||||
nsresult rv = nsContentUtils::GetSecurityManager()->
|
||||
GetSubjectPrincipal(getter_AddRefs(principal));
|
||||
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
|
||||
|
||||
nsCString origin;
|
||||
if (nsContentUtils::IsSystemPrincipal(principal)) {
|
||||
origin.AssignLiteral("chrome");
|
||||
}
|
||||
else {
|
||||
rv = nsContentUtils::GetASCIIOrigin(principal, origin);
|
||||
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
|
||||
|
||||
if (origin.EqualsLiteral("null")) {
|
||||
NS_WARNING("IndexedDB databases not allowed for this principal!");
|
||||
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
|
||||
}
|
||||
}
|
||||
nsresult rv =
|
||||
IndexedDatabaseManager::GetASCIIOriginFromWindow(window, origin);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsRefPtr<IDBOpenDBRequest> request =
|
||||
IDBOpenDBRequest::Create(context, window);
|
||||
|
|
|
@ -887,7 +887,7 @@ CommitHelper::Run()
|
|||
}
|
||||
|
||||
if (mConnection) {
|
||||
IndexedDatabaseManager::SetCurrentDatabase(database);
|
||||
IndexedDatabaseManager::SetCurrentWindow(database->Owner());
|
||||
|
||||
if (!mAborted) {
|
||||
NS_NAMED_LITERAL_CSTRING(release, "COMMIT TRANSACTION");
|
||||
|
@ -923,7 +923,7 @@ CommitHelper::Run()
|
|||
mConnection->Close();
|
||||
mConnection = nsnull;
|
||||
|
||||
IndexedDatabaseManager::SetCurrentDatabase(nsnull);
|
||||
IndexedDatabaseManager::SetCurrentWindow(nsnull);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
|
|
@ -41,6 +41,8 @@
|
|||
|
||||
#include "nsIFile.h"
|
||||
#include "nsIObserverService.h"
|
||||
#include "nsIScriptObjectPrincipal.h"
|
||||
#include "nsIScriptSecurityManager.h"
|
||||
#include "nsISHEntry.h"
|
||||
#include "nsISimpleEnumerator.h"
|
||||
#include "nsITimer.h"
|
||||
|
@ -54,6 +56,7 @@
|
|||
#include "nsXPCOMPrivate.h"
|
||||
|
||||
#include "AsyncConnectionHelper.h"
|
||||
#include "CheckQuotaHelper.h"
|
||||
#include "IDBDatabase.h"
|
||||
#include "IDBEvents.h"
|
||||
#include "IDBFactory.h"
|
||||
|
@ -75,7 +78,7 @@
|
|||
#define PREF_INDEXEDDB_QUOTA "dom.indexedDB.warningQuota"
|
||||
|
||||
// A bad TLS index number.
|
||||
#define BAD_TLS_INDEX (PRUintn)-1
|
||||
#define BAD_TLS_INDEX (PRUintn)-1
|
||||
|
||||
USING_INDEXEDDB_NAMESPACE
|
||||
using namespace mozilla::services;
|
||||
|
@ -88,8 +91,6 @@ PRInt32 gShutdown = 0;
|
|||
// Does not hold a reference.
|
||||
IndexedDatabaseManager* gInstance = nsnull;
|
||||
|
||||
PRUintn gCurrentDatabaseIndex = BAD_TLS_INDEX;
|
||||
|
||||
PRInt32 gIndexedDBQuotaMB = DEFAULT_QUOTA_MB;
|
||||
|
||||
class QuotaCallback : public mozIStorageQuotaCallback
|
||||
|
@ -104,13 +105,7 @@ public:
|
|||
nsISupports* aUserData,
|
||||
PRInt64* _retval)
|
||||
{
|
||||
NS_ASSERTION(gCurrentDatabaseIndex != BAD_TLS_INDEX,
|
||||
"This should be impossible!");
|
||||
|
||||
IDBDatabase* database =
|
||||
static_cast<IDBDatabase*>(PR_GetThreadPrivate(gCurrentDatabaseIndex));
|
||||
|
||||
if (database && database->IsQuotaDisabled()) {
|
||||
if (IndexedDatabaseManager::QuotaIsLifted()) {
|
||||
*_retval = 0;
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -146,6 +141,8 @@ EnumerateToTArray(const nsACString& aKey,
|
|||
} // anonymous namespace
|
||||
|
||||
IndexedDatabaseManager::IndexedDatabaseManager()
|
||||
: mCurrentWindowIndex(BAD_TLS_INDEX),
|
||||
mQuotaHelperMutex("IndexedDatabaseManager.mQuotaHelperMutex")
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
NS_ASSERTION(!gInstance, "More than one instance!");
|
||||
|
@ -172,30 +169,31 @@ IndexedDatabaseManager::GetOrCreate()
|
|||
nsRefPtr<IndexedDatabaseManager> instance(gInstance);
|
||||
|
||||
if (!instance) {
|
||||
// We need a thread-local to hold our current database.
|
||||
if (gCurrentDatabaseIndex == BAD_TLS_INDEX) {
|
||||
if (PR_NewThreadPrivateIndex(&gCurrentDatabaseIndex, nsnull) !=
|
||||
PR_SUCCESS) {
|
||||
NS_ERROR("PR_NewThreadPrivateIndex failed!");
|
||||
gCurrentDatabaseIndex = BAD_TLS_INDEX;
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
if (NS_FAILED(Preferences::AddIntVarCache(&gIndexedDBQuotaMB,
|
||||
PREF_INDEXEDDB_QUOTA,
|
||||
DEFAULT_QUOTA_MB))) {
|
||||
NS_WARNING("Unable to respond to quota pref changes!");
|
||||
gIndexedDBQuotaMB = DEFAULT_QUOTA_MB;
|
||||
}
|
||||
if (NS_FAILED(Preferences::AddIntVarCache(&gIndexedDBQuotaMB,
|
||||
PREF_INDEXEDDB_QUOTA,
|
||||
DEFAULT_QUOTA_MB))) {
|
||||
NS_WARNING("Unable to respond to quota pref changes!");
|
||||
gIndexedDBQuotaMB = DEFAULT_QUOTA_MB;
|
||||
}
|
||||
|
||||
instance = new IndexedDatabaseManager();
|
||||
|
||||
if (!instance->mLiveDatabases.Init()) {
|
||||
if (!instance->mLiveDatabases.Init() ||
|
||||
!instance->mQuotaHelperHash.Init()) {
|
||||
NS_WARNING("Out of memory!");
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
// We need a thread-local to hold the current window.
|
||||
NS_ASSERTION(instance->mCurrentWindowIndex == BAD_TLS_INDEX, "Huh?");
|
||||
|
||||
if (PR_NewThreadPrivateIndex(&instance->mCurrentWindowIndex, nsnull) !=
|
||||
PR_SUCCESS) {
|
||||
NS_ERROR("PR_NewThreadPrivateIndex failed, IndexedDB disabled");
|
||||
instance->mCurrentWindowIndex = BAD_TLS_INDEX;
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
// Make a timer here to avoid potential failures later. We don't actually
|
||||
// initialize the timer until shutdown.
|
||||
instance->mShutdownTimer = do_CreateInstance(NS_TIMER_CONTRACTID);
|
||||
|
@ -548,30 +546,23 @@ IndexedDatabaseManager::OnDatabaseClosed(IDBDatabase* aDatabase)
|
|||
}
|
||||
}
|
||||
|
||||
// static
|
||||
bool
|
||||
IndexedDatabaseManager::SetCurrentDatabase(IDBDatabase* aDatabase)
|
||||
void
|
||||
IndexedDatabaseManager::SetCurrentWindowInternal(nsPIDOMWindow* aWindow)
|
||||
{
|
||||
NS_ASSERTION(gCurrentDatabaseIndex != BAD_TLS_INDEX,
|
||||
"This should have been set already!");
|
||||
|
||||
if (aWindow) {
|
||||
#ifdef DEBUG
|
||||
if (aDatabase) {
|
||||
NS_ASSERTION(!PR_GetThreadPrivate(gCurrentDatabaseIndex),
|
||||
"Someone forgot to unset gCurrentDatabaseIndex!");
|
||||
NS_ASSERTION(!PR_GetThreadPrivate(mCurrentWindowIndex),
|
||||
"Somebody forgot to clear the current window!");
|
||||
#endif
|
||||
PR_SetThreadPrivate(mCurrentWindowIndex, aWindow);
|
||||
}
|
||||
else {
|
||||
NS_ASSERTION(PR_GetThreadPrivate(gCurrentDatabaseIndex),
|
||||
"Someone forgot to set gCurrentDatabaseIndex!");
|
||||
}
|
||||
#ifdef DEBUG
|
||||
NS_ASSERTION(PR_GetThreadPrivate(mCurrentWindowIndex),
|
||||
"Somebody forgot to clear the current window!");
|
||||
#endif
|
||||
|
||||
if (PR_SetThreadPrivate(gCurrentDatabaseIndex, aDatabase) != PR_SUCCESS) {
|
||||
NS_WARNING("Failed to set gCurrentDatabaseIndex!");
|
||||
return false;
|
||||
PR_SetThreadPrivate(mCurrentWindowIndex, nsnull);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// static
|
||||
|
@ -662,6 +653,102 @@ IndexedDatabaseManager::EnsureQuotaManagementForDirectory(nsIFile* aDirectory)
|
|||
return rv;
|
||||
}
|
||||
|
||||
bool
|
||||
IndexedDatabaseManager::QuotaIsLiftedInternal()
|
||||
{
|
||||
nsPIDOMWindow* window = nsnull;
|
||||
nsRefPtr<CheckQuotaHelper> helper = nsnull;
|
||||
bool createdHelper = false;
|
||||
|
||||
window =
|
||||
static_cast<nsPIDOMWindow*>(PR_GetThreadPrivate(mCurrentWindowIndex));
|
||||
|
||||
// Once IDB is supported outside of Windows this should become an early
|
||||
// return true.
|
||||
NS_ASSERTION(window, "Why don't we have a Window here?");
|
||||
|
||||
// Hold the lock from here on.
|
||||
MutexAutoLock autoLock(mQuotaHelperMutex);
|
||||
|
||||
mQuotaHelperHash.Get(window, getter_AddRefs(helper));
|
||||
|
||||
if (!helper) {
|
||||
helper = new CheckQuotaHelper(window, mQuotaHelperMutex);
|
||||
createdHelper = true;
|
||||
|
||||
bool result = mQuotaHelperHash.Put(window, helper);
|
||||
NS_ENSURE_TRUE(result, result);
|
||||
|
||||
// Unlock while calling out to XPCOM
|
||||
{
|
||||
MutexAutoUnlock autoUnlock(mQuotaHelperMutex);
|
||||
|
||||
nsresult rv = NS_DispatchToMainThread(helper);
|
||||
NS_ENSURE_SUCCESS(rv, false);
|
||||
}
|
||||
|
||||
// Relocked. If any other threads hit the quota limit on the same Window,
|
||||
// they are using the helper we created here and are now blocking in
|
||||
// PromptAndReturnQuotaDisabled.
|
||||
}
|
||||
|
||||
bool result = helper->PromptAndReturnQuotaIsDisabled();
|
||||
|
||||
// If this thread created the helper and added it to the hash, this thread
|
||||
// must remove it.
|
||||
if (createdHelper) {
|
||||
mQuotaHelperHash.Remove(window);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void
|
||||
IndexedDatabaseManager::CancelPromptsForWindowInternal(nsPIDOMWindow* aWindow)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
nsRefPtr<CheckQuotaHelper> helper;
|
||||
|
||||
MutexAutoLock autoLock(mQuotaHelperMutex);
|
||||
|
||||
mQuotaHelperHash.Get(aWindow, getter_AddRefs(helper));
|
||||
|
||||
if (helper) {
|
||||
helper->Cancel();
|
||||
}
|
||||
}
|
||||
|
||||
// static
|
||||
nsresult
|
||||
IndexedDatabaseManager::GetASCIIOriginFromWindow(nsPIDOMWindow* aWindow,
|
||||
nsCString& aASCIIOrigin)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(),
|
||||
"We're about to touch a window off the main thread!");
|
||||
|
||||
nsCOMPtr<nsIScriptObjectPrincipal> sop = do_QueryInterface(aWindow);
|
||||
NS_ENSURE_TRUE(sop, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
|
||||
|
||||
nsCOMPtr<nsIPrincipal> principal = sop->GetPrincipal();
|
||||
NS_ENSURE_TRUE(principal, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
|
||||
|
||||
if (nsContentUtils::IsSystemPrincipal(principal)) {
|
||||
aASCIIOrigin.AssignLiteral("chrome");
|
||||
}
|
||||
else {
|
||||
nsresult rv = nsContentUtils::GetASCIIOrigin(principal, aASCIIOrigin);
|
||||
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
|
||||
|
||||
if (aASCIIOrigin.EqualsLiteral("null")) {
|
||||
NS_WARNING("IndexedDB databases not allowed for this principal!");
|
||||
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// static
|
||||
nsresult
|
||||
IndexedDatabaseManager::DispatchHelper(AsyncConnectionHelper* aHelper)
|
||||
|
|
|
@ -44,6 +44,8 @@
|
|||
#include "mozilla/dom/indexedDB/IDBDatabase.h"
|
||||
#include "mozilla/dom/indexedDB/IDBRequest.h"
|
||||
|
||||
#include "mozilla/Mutex.h"
|
||||
|
||||
#include "nsIIndexedDatabaseManager.h"
|
||||
#include "nsIObserver.h"
|
||||
#include "nsIRunnable.h"
|
||||
|
@ -51,6 +53,7 @@
|
|||
#include "nsIURI.h"
|
||||
|
||||
#include "nsClassHashtable.h"
|
||||
#include "nsRefPtrHashtable.h"
|
||||
#include "nsHashKeys.h"
|
||||
|
||||
#define INDEXEDDB_MANAGER_CONTRACTID "@mozilla.org/dom/indexeddb/manager;1"
|
||||
|
@ -62,6 +65,8 @@ BEGIN_INDEXEDDB_NAMESPACE
|
|||
|
||||
class AsyncConnectionHelper;
|
||||
|
||||
class CheckQuotaHelper;
|
||||
|
||||
class IndexedDatabaseManager : public nsIIndexedDatabaseManager,
|
||||
public nsIObserver
|
||||
{
|
||||
|
@ -129,14 +134,45 @@ public:
|
|||
// Used to check if there are running transactions in a given window.
|
||||
bool HasOpenTransactions(nsPIDOMWindow* aWindow);
|
||||
|
||||
static bool
|
||||
SetCurrentDatabase(IDBDatabase* aDatabase);
|
||||
// Set the Window that the current thread is doing operations for.
|
||||
// The caller is responsible for ensuring that aWindow is held alive.
|
||||
static inline void
|
||||
SetCurrentWindow(nsPIDOMWindow* aWindow)
|
||||
{
|
||||
IndexedDatabaseManager* mgr = Get();
|
||||
NS_ASSERTION(mgr, "Must have a manager here!");
|
||||
|
||||
return mgr->SetCurrentWindowInternal(aWindow);
|
||||
}
|
||||
|
||||
static PRUint32
|
||||
GetIndexedDBQuotaMB();
|
||||
|
||||
nsresult EnsureQuotaManagementForDirectory(nsIFile* aDirectory);
|
||||
|
||||
// Determine if the quota is lifted for the Window the current thread is
|
||||
// using.
|
||||
static inline bool
|
||||
QuotaIsLifted()
|
||||
{
|
||||
IndexedDatabaseManager* mgr = Get();
|
||||
NS_ASSERTION(mgr, "Must have a manager here!");
|
||||
|
||||
return mgr->QuotaIsLiftedInternal();
|
||||
}
|
||||
|
||||
static inline void
|
||||
CancelPromptsForWindow(nsPIDOMWindow* aWindow)
|
||||
{
|
||||
IndexedDatabaseManager* mgr = Get();
|
||||
NS_ASSERTION(mgr, "Must have a manager here!");
|
||||
|
||||
mgr->CancelPromptsForWindowInternal(aWindow);
|
||||
}
|
||||
|
||||
static nsresult
|
||||
GetASCIIOriginFromWindow(nsPIDOMWindow* aWindow, nsCString& aASCIIOrigin);
|
||||
|
||||
private:
|
||||
IndexedDatabaseManager();
|
||||
~IndexedDatabaseManager();
|
||||
|
@ -147,6 +183,10 @@ private:
|
|||
WaitingOnDatabasesCallback aCallback,
|
||||
void* aClosure);
|
||||
|
||||
void SetCurrentWindowInternal(nsPIDOMWindow* aWindow);
|
||||
bool QuotaIsLiftedInternal();
|
||||
void CancelPromptsForWindowInternal(nsPIDOMWindow* aWindow);
|
||||
|
||||
// Called when a database is created.
|
||||
bool RegisterDatabase(IDBDatabase* aDatabase);
|
||||
|
||||
|
@ -267,6 +307,15 @@ private:
|
|||
// Maintains a list of live databases per origin.
|
||||
nsClassHashtable<nsCStringHashKey, nsTArray<IDBDatabase*> > mLiveDatabases;
|
||||
|
||||
// TLS storage index for the current thread's window
|
||||
PRUintn mCurrentWindowIndex;
|
||||
|
||||
// Lock protecting mQuotaHelperHash
|
||||
mozilla::Mutex mQuotaHelperMutex;
|
||||
|
||||
// A map of Windows to the corresponding quota helper.
|
||||
nsRefPtrHashtable<nsPtrHashKey<nsPIDOMWindow>, CheckQuotaHelper> mQuotaHelperHash;
|
||||
|
||||
// Maintains a list of origins that we're currently enumerating to gather
|
||||
// usage statistics.
|
||||
nsAutoTArray<nsRefPtr<AsyncUsageRunnable>, 1> mUsageRunnables;
|
||||
|
@ -290,6 +339,21 @@ private:
|
|||
nsTArray<nsCString> mTrackedQuotaPaths;
|
||||
};
|
||||
|
||||
class AutoEnterWindow
|
||||
{
|
||||
public:
|
||||
AutoEnterWindow(nsPIDOMWindow* aWindow)
|
||||
{
|
||||
NS_ASSERTION(aWindow, "This should never be null!");
|
||||
IndexedDatabaseManager::SetCurrentWindow(aWindow);
|
||||
}
|
||||
|
||||
~AutoEnterWindow()
|
||||
{
|
||||
IndexedDatabaseManager::SetCurrentWindow(nsnull);
|
||||
}
|
||||
};
|
||||
|
||||
END_INDEXEDDB_NAMESPACE
|
||||
|
||||
#endif /* mozilla_dom_indexeddb_indexeddatabasemanager_h__ */
|
||||
|
|
|
@ -1090,6 +1090,14 @@ OpenDatabaseHelper::DoDatabaseWork()
|
|||
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
|
||||
}
|
||||
|
||||
NS_ASSERTION(mOpenDBRequest, "This should never be null!");
|
||||
|
||||
// Once we support IDB outside of Windows this assertion will no longer hold.
|
||||
nsPIDOMWindow* window = mOpenDBRequest->Owner();
|
||||
NS_ASSERTION(window, "This should never be null");
|
||||
|
||||
AutoEnterWindow autoWindow(window);
|
||||
|
||||
nsCOMPtr<nsIFile> dbFile;
|
||||
nsresult rv = GetDatabaseFile(mASCIIOrigin, mName, getter_AddRefs(dbFile));
|
||||
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
|
||||
|
|
|
@ -129,6 +129,8 @@ BROWSER_TEST_FILES = \
|
|||
browser_quotaPrompt.html \
|
||||
browser_quotaPromptAllow.js \
|
||||
browser_quotaPromptDeny.js \
|
||||
browser_quotaPromptDatabases.html \
|
||||
browser_quotaPromptDatabases.js \
|
||||
head.js \
|
||||
$(NULL)
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
*/
|
||||
|
||||
// Make sure this is a unique origin or the tests will randomly fail!
|
||||
const testPageURL = "http://test1.example.org/browser/" +
|
||||
const testPageURL = "http://bug704464-1.example.com/browser/" +
|
||||
"dom/indexedDB/test/browser_quotaPrompt.html";
|
||||
const notificationID = "indexedDB-quota-prompt";
|
||||
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
<!--
|
||||
Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
||||
-->
|
||||
<html>
|
||||
<head>
|
||||
<title>Indexed Database Test</title>
|
||||
|
||||
<script type="text/javascript;version=1.7">
|
||||
const READ_WRITE = Components.interfaces.nsIIDBTransaction.READ_WRITE;
|
||||
|
||||
let db;
|
||||
let i = 0;
|
||||
|
||||
function onAddMore() {
|
||||
const name = window.location.pathname + i++;
|
||||
|
||||
let request = mozIndexedDB.open(name, 1);
|
||||
request.onerror = errorHandler;
|
||||
request.onsuccess = grabEventAndContinueHandler;
|
||||
|
||||
request.onsuccess = function(event) {
|
||||
setTimeout(testFinishedCallback, 0, "complete");
|
||||
}
|
||||
request.onerror = function(event) {
|
||||
setTimeout(testFinishedCallback, 0, "abort");
|
||||
}
|
||||
}
|
||||
|
||||
function onDone() {
|
||||
window.removeEventListener("indexedDB-addMore", onAddMore, true);
|
||||
window.removeEventListener("indexedDB-done", onDone, true);
|
||||
|
||||
testResult = "finished";
|
||||
testException = undefined;
|
||||
finishTest();
|
||||
}
|
||||
|
||||
function testSteps()
|
||||
{
|
||||
window.addEventListener("indexedDB-addMore", onAddMore, true);
|
||||
window.addEventListener("indexedDB-done", onDone, true);
|
||||
|
||||
setTimeout(testFinishedCallback, 0, "ready");
|
||||
yield;
|
||||
}
|
||||
</script>
|
||||
|
||||
<script type="text/javascript;version=1.7" src="browserHelpers.js"></script>
|
||||
|
||||
</head>
|
||||
|
||||
<body onload="runTest();" onunload="finishTestNow();"></body>
|
||||
|
||||
</html>
|
|
@ -0,0 +1,76 @@
|
|||
/**
|
||||
* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
// Make sure this is a unique origin or the tests will randomly fail!
|
||||
const testPageURL = "http://bug704464-3.example.com/browser/" +
|
||||
"dom/indexedDB/test/browser_quotaPromptDatabases.html";
|
||||
const notificationID = "indexedDB-quota-prompt";
|
||||
|
||||
function test()
|
||||
{
|
||||
waitForExplicitFinish();
|
||||
requestLongerTimeout(10);
|
||||
setPermission(testPageURL, "indexedDB");
|
||||
removePermission(testPageURL, "indexedDB-unlimited");
|
||||
Services.prefs.setIntPref("dom.indexedDB.warningQuota", 2);
|
||||
executeSoon(test1);
|
||||
}
|
||||
|
||||
let addMoreTest1Count = 0;
|
||||
|
||||
function test1()
|
||||
{
|
||||
gBrowser.selectedTab = gBrowser.addTab();
|
||||
|
||||
gBrowser.selectedBrowser.addEventListener("load", function () {
|
||||
gBrowser.selectedBrowser.removeEventListener("load", arguments.callee, true);
|
||||
|
||||
let seenPopupCount;
|
||||
|
||||
setFinishedCallback(function(result) {
|
||||
is(result, "ready", "Got 'ready' result");
|
||||
|
||||
setFinishedCallback(function(result) {
|
||||
is(result, "complete", "Got 'complete' result");
|
||||
|
||||
if (addMoreTest1Count >= seenPopupCount + 5) {
|
||||
setFinishedCallback(function(result) {
|
||||
is(result, "finished", "Got 'finished' result");
|
||||
is(getPermission(testPageURL, "indexedDB-unlimited"),
|
||||
Components.interfaces.nsIPermissionManager.ALLOW_ACTION,
|
||||
"Correct permission set");
|
||||
gBrowser.removeCurrentTab();
|
||||
unregisterAllPopupEventHandlers();
|
||||
addMoreTest1Count = seenPopupCount;
|
||||
executeSoon(finish);
|
||||
});
|
||||
executeSoon(function() { dispatchEvent("indexedDB-done"); });
|
||||
}
|
||||
else {
|
||||
++addMoreTest1Count;
|
||||
executeSoon(function() { dispatchEvent("indexedDB-addMore"); });
|
||||
}
|
||||
});
|
||||
++addMoreTest1Count;
|
||||
executeSoon(function() { dispatchEvent("indexedDB-addMore"); });
|
||||
});
|
||||
|
||||
registerPopupEventHandler("popupshowing", function () {
|
||||
ok(true, "prompt showing");
|
||||
seenPopupCount = addMoreTest1Count - 1;
|
||||
});
|
||||
registerPopupEventHandler("popupshown", function () {
|
||||
ok(true, "prompt shown");
|
||||
triggerMainCommand(this);
|
||||
});
|
||||
registerPopupEventHandler("popuphidden", function () {
|
||||
ok(true, "prompt hidden");
|
||||
});
|
||||
|
||||
}, true);
|
||||
|
||||
info("loading test page: " + testPageURL);
|
||||
content.location = testPageURL;
|
||||
}
|
|
@ -4,7 +4,7 @@
|
|||
*/
|
||||
|
||||
// Make sure this is a unique origin or the tests will randomly fail!
|
||||
const testPageURL = "http://test2.example.org/browser/" +
|
||||
const testPageURL = "http://bug704464-2.example.com/browser/" +
|
||||
"dom/indexedDB/test/browser_quotaPrompt.html";
|
||||
const notificationID = "indexedDB-quota-prompt";
|
||||
|
||||
|
|
|
@ -68,7 +68,7 @@ interface nsIDOMWindow;
|
|||
interface nsIDOMFile;
|
||||
interface nsIFile;
|
||||
|
||||
[scriptable, uuid(c5cf91b3-0b89-4417-b13c-5540ba6ebde8)]
|
||||
[scriptable, uuid(bf868921-0288-4799-a806-2fa642590197)]
|
||||
interface nsIDOMWindowUtils : nsISupports {
|
||||
|
||||
/**
|
||||
|
@ -557,7 +557,7 @@ interface nsIDOMWindowUtils : nsISupports {
|
|||
* Returns the real classname (possibly of the mostly-transparent security
|
||||
* wrapper) of aObj.
|
||||
*/
|
||||
string getClassName(/*in JSObjectPtr aObj*/);
|
||||
[implicit_jscontext] string getClassName(in jsval aObject);
|
||||
|
||||
/**
|
||||
* Generate a content command event.
|
||||
|
|
|
@ -40,6 +40,7 @@
|
|||
|
||||
// FIXME(bug 332648): Give me a real API please!
|
||||
#include "jscntxt.h"
|
||||
#include "jsfriendapi.h"
|
||||
|
||||
#include "nsIInterfaceRequestorUtils.h"
|
||||
#include "nsJSNPRuntime.h"
|
||||
|
@ -1483,7 +1484,7 @@ CallNPMethodInternal(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
|||
// the function object.
|
||||
|
||||
if (npobj->_class->invoke) {
|
||||
JSFunction *fun = (JSFunction *)::JS_GetPrivate(cx, funobj);
|
||||
JSFunction *fun = ::JS_GetObjectFunction(funobj);
|
||||
JSString *name = ::JS_InternJSString(cx, ::JS_GetFunctionId(fun));
|
||||
NPIdentifier id = StringToNPIdentifier(cx, name);
|
||||
|
||||
|
|
|
@ -91,8 +91,8 @@ public:
|
|||
InitClass(JSContext* aCx, JSObject* aObj, JSObject* aParentProto,
|
||||
bool aMainRuntime)
|
||||
{
|
||||
JSObject* proto = JS_InitClass(aCx, aObj, aParentProto, &sClass, Construct,
|
||||
0, sProperties, sFunctions, NULL, NULL);
|
||||
JSObject* proto = js::InitClassWithReserved(aCx, aObj, aParentProto, &sClass, Construct,
|
||||
0, sProperties, sFunctions, NULL, NULL);
|
||||
if (!proto) {
|
||||
return NULL;
|
||||
}
|
||||
|
@ -102,11 +102,10 @@ public:
|
|||
parent->AssertIsOnWorkerThread();
|
||||
|
||||
JSObject* constructor = JS_GetConstructor(aCx, proto);
|
||||
if (!constructor ||
|
||||
!JS_SetReservedSlot(aCx, constructor, CONSTRUCTOR_SLOT_PARENT,
|
||||
PRIVATE_TO_JSVAL(parent))) {
|
||||
if (!constructor)
|
||||
return NULL;
|
||||
}
|
||||
js::SetFunctionNativeReserved(constructor, CONSTRUCTOR_SLOT_PARENT,
|
||||
PRIVATE_TO_JSVAL(parent));
|
||||
}
|
||||
|
||||
return proto;
|
||||
|
@ -153,11 +152,8 @@ protected:
|
|||
return false;
|
||||
}
|
||||
|
||||
jsval priv;
|
||||
if (!JS_GetReservedSlot(aCx, JSVAL_TO_OBJECT(JS_CALLEE(aCx, aVp)),
|
||||
CONSTRUCTOR_SLOT_PARENT, &priv)) {
|
||||
return false;
|
||||
}
|
||||
jsval priv = js::GetFunctionNativeReserved(JSVAL_TO_OBJECT(JS_CALLEE(aCx, aVp)),
|
||||
CONSTRUCTOR_SLOT_PARENT);
|
||||
|
||||
RuntimeService* runtimeService;
|
||||
WorkerPrivate* parent;
|
||||
|
@ -345,8 +341,8 @@ public:
|
|||
InitClass(JSContext* aCx, JSObject* aObj, JSObject* aParentProto,
|
||||
bool aMainRuntime)
|
||||
{
|
||||
JSObject* proto = JS_InitClass(aCx, aObj, aParentProto, &sClass, Construct,
|
||||
0, NULL, NULL, NULL, NULL);
|
||||
JSObject* proto = js::InitClassWithReserved(aCx, aObj, aParentProto, &sClass, Construct,
|
||||
0, NULL, NULL, NULL, NULL);
|
||||
if (!proto) {
|
||||
return NULL;
|
||||
}
|
||||
|
@ -356,11 +352,10 @@ public:
|
|||
parent->AssertIsOnWorkerThread();
|
||||
|
||||
JSObject* constructor = JS_GetConstructor(aCx, proto);
|
||||
if (!constructor ||
|
||||
!JS_SetReservedSlot(aCx, constructor, CONSTRUCTOR_SLOT_PARENT,
|
||||
PRIVATE_TO_JSVAL(parent))) {
|
||||
if (!constructor)
|
||||
return NULL;
|
||||
}
|
||||
js::SetFunctionNativeReserved(constructor, CONSTRUCTOR_SLOT_PARENT,
|
||||
PRIVATE_TO_JSVAL(parent));
|
||||
}
|
||||
|
||||
return proto;
|
||||
|
|
|
@ -271,11 +271,8 @@ private:
|
|||
JSObject* wrapper = JSVAL_TO_OBJECT(JS_CALLEE(aCx, aVp));
|
||||
JS_ASSERT(JS_ObjectIsFunction(aCx, wrapper));
|
||||
|
||||
jsval scope, listener;
|
||||
if (!JS_GetReservedSlot(aCx, wrapper, SLOT_wrappedScope, &scope) ||
|
||||
!JS_GetReservedSlot(aCx, wrapper, SLOT_wrappedFunction, &listener)) {
|
||||
return false;
|
||||
}
|
||||
jsval scope = js::GetFunctionNativeReserved(wrapper, SLOT_wrappedScope);
|
||||
jsval listener = js::GetFunctionNativeReserved(wrapper, SLOT_wrappedFunction);
|
||||
|
||||
JS_ASSERT(JSVAL_IS_OBJECT(scope));
|
||||
|
||||
|
@ -319,11 +316,8 @@ private:
|
|||
|
||||
JS_ASSERT(JSVAL_IS_OBJECT(adaptor));
|
||||
|
||||
jsval listener;
|
||||
if (!JS_GetReservedSlot(aCx, JSVAL_TO_OBJECT(adaptor), SLOT_wrappedFunction,
|
||||
&listener)) {
|
||||
return false;
|
||||
}
|
||||
jsval listener = js::GetFunctionNativeReserved(JSVAL_TO_OBJECT(adaptor),
|
||||
SLOT_wrappedFunction);
|
||||
|
||||
*aVp = listener;
|
||||
return true;
|
||||
|
@ -339,8 +333,8 @@ private:
|
|||
return false;
|
||||
}
|
||||
|
||||
JSFunction* adaptor = JS_NewFunction(aCx, UnwrapErrorEvent, 1, 0,
|
||||
JS_GetGlobalObject(aCx), "unwrap");
|
||||
JSFunction* adaptor = js::NewFunctionWithReserved(aCx, UnwrapErrorEvent, 1, 0,
|
||||
JS_GetGlobalObject(aCx), "unwrap");
|
||||
if (!adaptor) {
|
||||
return false;
|
||||
}
|
||||
|
@ -350,11 +344,9 @@ private:
|
|||
return false;
|
||||
}
|
||||
|
||||
if (!JS_SetReservedSlot(aCx, listener, SLOT_wrappedScope,
|
||||
OBJECT_TO_JSVAL(aObj)) ||
|
||||
!JS_SetReservedSlot(aCx, listener, SLOT_wrappedFunction, *aVp)) {
|
||||
return false;
|
||||
}
|
||||
js::SetFunctionNativeReserved(listener, SLOT_wrappedScope,
|
||||
OBJECT_TO_JSVAL(aObj));
|
||||
js::SetFunctionNativeReserved(listener, SLOT_wrappedFunction, *aVp);
|
||||
|
||||
jsval val = OBJECT_TO_JSVAL(listener);
|
||||
return scope->SetEventListenerOnEventTarget(aCx, name + 2, &val);
|
||||
|
|
|
@ -1022,7 +1022,7 @@ nsEditor::GetDocumentIsEmpty(bool *aDocumentIsEmpty)
|
|||
{
|
||||
*aDocumentIsEmpty = true;
|
||||
|
||||
nsIDOMElement *rootElement = GetRoot();
|
||||
nsCOMPtr<nsIDOMElement> rootElement = do_QueryInterface(GetRoot());
|
||||
NS_ENSURE_TRUE(rootElement, NS_ERROR_NULL_POINTER);
|
||||
|
||||
bool hasChildNodes;
|
||||
|
@ -1063,7 +1063,7 @@ NS_IMETHODIMP nsEditor::BeginningOfDocument()
|
|||
NS_ENSURE_TRUE(selection, NS_ERROR_NOT_INITIALIZED);
|
||||
|
||||
// get the root element
|
||||
nsIDOMElement *rootElement = GetRoot();
|
||||
nsCOMPtr<nsIDOMElement> rootElement = do_QueryInterface(GetRoot());
|
||||
NS_ENSURE_TRUE(rootElement, NS_ERROR_NULL_POINTER);
|
||||
|
||||
// find first editable thingy
|
||||
|
@ -1109,12 +1109,9 @@ nsEditor::EndOfDocument()
|
|||
NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
|
||||
|
||||
// get the root element
|
||||
nsIDOMElement *rootElement = GetRoot();
|
||||
NS_ENSURE_TRUE(rootElement, NS_ERROR_NULL_POINTER);
|
||||
|
||||
nsCOMPtr<nsIDOMNode> node = do_QueryInterface(rootElement);
|
||||
nsCOMPtr<nsIDOMNode> node = do_QueryInterface(GetRoot());
|
||||
NS_ENSURE_TRUE(node, NS_ERROR_NULL_POINTER);
|
||||
nsCOMPtr<nsIDOMNode> child;
|
||||
NS_ASSERTION(node, "Invalid root element");
|
||||
|
||||
do {
|
||||
node->GetLastChild(getter_AddRefs(child));
|
||||
|
@ -1978,18 +1975,14 @@ nsEditor::GetPhonetic(nsAString& aPhonetic)
|
|||
|
||||
|
||||
static nsresult
|
||||
GetEditorContentWindow(nsIDOMElement *aRoot, nsIWidget **aResult)
|
||||
GetEditorContentWindow(dom::Element *aRoot, nsIWidget **aResult)
|
||||
{
|
||||
NS_ENSURE_TRUE(aRoot && aResult, NS_ERROR_NULL_POINTER);
|
||||
|
||||
*aResult = 0;
|
||||
|
||||
nsCOMPtr<nsIContent> content = do_QueryInterface(aRoot);
|
||||
|
||||
NS_ENSURE_TRUE(content, NS_ERROR_FAILURE);
|
||||
|
||||
// Not ref counted
|
||||
nsIFrame *frame = content->GetPrimaryFrame();
|
||||
nsIFrame *frame = aRoot->GetPrimaryFrame();
|
||||
|
||||
NS_ENSURE_TRUE(frame, NS_ERROR_FAILURE);
|
||||
|
||||
|
@ -2103,8 +2096,8 @@ nsEditor::GetRootElement(nsIDOMElement **aRootElement)
|
|||
{
|
||||
NS_ENSURE_ARG_POINTER(aRootElement);
|
||||
NS_ENSURE_TRUE(mRootElement, NS_ERROR_NOT_AVAILABLE);
|
||||
*aRootElement = mRootElement;
|
||||
NS_ADDREF(*aRootElement);
|
||||
nsCOMPtr<nsIDOMElement> rootElement = do_QueryInterface(mRootElement);
|
||||
rootElement.forget(aRootElement);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -2175,12 +2168,10 @@ nsEditor::CloneAttributes(nsIDOMNode *aDestNode, nsIDOMNode *aSourceNode)
|
|||
|
||||
// Use transaction system for undo only if destination
|
||||
// is already in the document
|
||||
nsIDOMElement *rootElement = GetRoot();
|
||||
NS_ENSURE_TRUE(rootElement, NS_ERROR_NULL_POINTER);
|
||||
|
||||
bool destInBody = true;
|
||||
nsCOMPtr<nsIDOMNode> rootNode = do_QueryInterface(rootElement);
|
||||
nsCOMPtr<nsIDOMNode> p = aDestNode;
|
||||
nsCOMPtr<nsIDOMNode> rootNode = do_QueryInterface(GetRoot());
|
||||
NS_ENSURE_TRUE(rootNode, NS_ERROR_NULL_POINTER);
|
||||
bool destInBody = true;
|
||||
while (p && p != rootNode)
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode> tmp;
|
||||
|
@ -2292,11 +2283,12 @@ NS_IMETHODIMP nsEditor::InsertTextImpl(const nsAString& aStringToInsert,
|
|||
if (!mInIMEMode && aStringToInsert.IsEmpty()) return NS_OK;
|
||||
nsCOMPtr<nsIDOMText> nodeAsText = do_QueryInterface(*aInOutNode);
|
||||
if (!nodeAsText && IsPlaintextEditor()) {
|
||||
nsCOMPtr<nsIDOMNode> rootNode = do_QueryInterface(GetRoot());
|
||||
// In some cases, aInOutNode is the anonymous DIV, and aInOutOffset is 0.
|
||||
// To avoid injecting unneeded text nodes, we first look to see if we have
|
||||
// one available. In that case, we'll just adjust aInOutNode and aInOutOffset
|
||||
// accordingly.
|
||||
if (*aInOutNode == GetRoot() && *aInOutOffset == 0) {
|
||||
if (*aInOutNode == rootNode && *aInOutOffset == 0) {
|
||||
nsCOMPtr<nsIDOMNode> possibleTextNode;
|
||||
res = (*aInOutNode)->GetFirstChild(getter_AddRefs(possibleTextNode));
|
||||
if (NS_SUCCEEDED(res)) {
|
||||
|
@ -2309,7 +2301,7 @@ NS_IMETHODIMP nsEditor::InsertTextImpl(const nsAString& aStringToInsert,
|
|||
// In some other cases, aInOutNode is the anonymous DIV, and aInOutOffset points
|
||||
// to the terminating mozBR. In that case, we'll adjust aInOutNode and aInOutOffset
|
||||
// to the preceding text node, if any.
|
||||
if (!nodeAsText && *aInOutNode == GetRoot() && *aInOutOffset > 0) {
|
||||
if (!nodeAsText && *aInOutNode == rootNode && *aInOutOffset > 0) {
|
||||
nsCOMPtr<nsIDOMNodeList> children;
|
||||
res = (*aInOutNode)->GetChildNodes(getter_AddRefs(children));
|
||||
if (NS_SUCCEEDED(res)) {
|
||||
|
@ -2363,7 +2355,7 @@ NS_IMETHODIMP nsEditor::InsertTextImpl(const nsAString& aStringToInsert,
|
|||
} else {
|
||||
nsCOMPtr<nsIDOMNode> parent;
|
||||
(*aInOutNode)->GetParentNode(getter_AddRefs(parent));
|
||||
if (parent == GetRoot()) {
|
||||
if (parent == rootNode) {
|
||||
*aInOutNode = parent;
|
||||
}
|
||||
}
|
||||
|
@ -2530,7 +2522,7 @@ NS_IMETHODIMP nsEditor::SelectEntireDocument(nsISelection *aSelection)
|
|||
{
|
||||
if (!aSelection) { return NS_ERROR_NULL_POINTER; }
|
||||
|
||||
nsIDOMElement *rootElement = GetRoot();
|
||||
nsCOMPtr<nsIDOMElement> rootElement = do_QueryInterface(GetRoot());
|
||||
if (!rootElement) { return NS_ERROR_NOT_INITIALIZED; }
|
||||
|
||||
return aSelection->SelectAllChildren(rootElement);
|
||||
|
@ -3546,7 +3538,9 @@ nsEditor::IsRootNode(nsIDOMNode *inNode)
|
|||
{
|
||||
NS_ENSURE_TRUE(inNode, false);
|
||||
|
||||
return inNode == GetRoot();
|
||||
nsCOMPtr<nsIDOMNode> rootNode = do_QueryInterface(GetRoot());
|
||||
|
||||
return inNode == rootNode;
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -3554,11 +3548,9 @@ nsEditor::IsRootNode(nsINode *inNode)
|
|||
{
|
||||
NS_ENSURE_TRUE(inNode, false);
|
||||
|
||||
nsIDOMElement *rootElement = GetRoot();
|
||||
nsCOMPtr<nsINode> rootNode = GetRoot();
|
||||
|
||||
nsCOMPtr<nsIDOMNode> node = do_QueryInterface(inNode);
|
||||
|
||||
return node == rootElement;
|
||||
return inNode == rootNode;
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -3572,7 +3564,7 @@ bool
|
|||
nsEditor::IsDescendantOfBody(nsINode *inNode)
|
||||
{
|
||||
NS_ENSURE_TRUE(inNode, false);
|
||||
nsCOMPtr<nsIContent> root = do_QueryInterface(GetRoot());
|
||||
nsCOMPtr<nsIContent> root = GetRoot();
|
||||
NS_ENSURE_TRUE(root, false);
|
||||
|
||||
return nsContentUtils::ContentIsDescendantOf(inNode, root);
|
||||
|
@ -5149,7 +5141,7 @@ nsEditor::HandleInlineSpellCheck(PRInt32 action,
|
|||
already_AddRefed<nsIContent>
|
||||
nsEditor::FindSelectionRoot(nsINode *aNode)
|
||||
{
|
||||
nsCOMPtr<nsIContent> rootContent = do_QueryInterface(GetRoot());
|
||||
nsCOMPtr<nsIContent> rootContent = GetRoot();
|
||||
return rootContent.forget();
|
||||
}
|
||||
|
||||
|
@ -5218,7 +5210,7 @@ nsEditor::InitializeSelection(nsIDOMEventTarget* aFocusEventTarget)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsIDOMElement *
|
||||
dom::Element *
|
||||
nsEditor::GetRoot()
|
||||
{
|
||||
if (!mRootElement)
|
||||
|
@ -5236,18 +5228,14 @@ nsresult
|
|||
nsEditor::DetermineCurrentDirection()
|
||||
{
|
||||
// Get the current root direction from its frame
|
||||
nsIDOMElement *rootElement = GetRoot();
|
||||
|
||||
nsresult rv;
|
||||
dom::Element *rootElement = GetRoot();
|
||||
|
||||
// If we don't have an explicit direction, determine our direction
|
||||
// from the content's direction
|
||||
if (!(mFlags & (nsIPlaintextEditor::eEditorLeftToRight |
|
||||
nsIPlaintextEditor::eEditorRightToLeft))) {
|
||||
nsCOMPtr<nsIContent> content = do_QueryInterface(rootElement, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsIFrame* frame = content->GetPrimaryFrame();
|
||||
nsIFrame* frame = rootElement->GetPrimaryFrame();
|
||||
NS_ENSURE_TRUE(frame, NS_ERROR_FAILURE);
|
||||
|
||||
// Set the flag here, to enable us to use the same code path below.
|
||||
|
@ -5266,8 +5254,7 @@ NS_IMETHODIMP
|
|||
nsEditor::SwitchTextDirection()
|
||||
{
|
||||
// Get the current root direction from its frame
|
||||
nsIDOMElement *rootElement = GetRoot();
|
||||
|
||||
dom::Element *rootElement = GetRoot();
|
||||
nsresult rv = DetermineCurrentDirection();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
|
@ -5277,13 +5264,13 @@ nsEditor::SwitchTextDirection()
|
|||
"Unexpected mutually exclusive flag");
|
||||
mFlags &= ~nsIPlaintextEditor::eEditorRightToLeft;
|
||||
mFlags |= nsIPlaintextEditor::eEditorLeftToRight;
|
||||
rv = rootElement->SetAttribute(NS_LITERAL_STRING("dir"), NS_LITERAL_STRING("ltr"));
|
||||
rv = rootElement->SetAttr(kNameSpaceID_None, nsGkAtoms::dir, NS_LITERAL_STRING("ltr"), true);
|
||||
} else if (mFlags & nsIPlaintextEditor::eEditorLeftToRight) {
|
||||
NS_ASSERTION(!(mFlags & nsIPlaintextEditor::eEditorRightToLeft),
|
||||
"Unexpected mutually exclusive flag");
|
||||
mFlags |= nsIPlaintextEditor::eEditorRightToLeft;
|
||||
mFlags &= ~nsIPlaintextEditor::eEditorLeftToRight;
|
||||
rv = rootElement->SetAttribute(NS_LITERAL_STRING("dir"), NS_LITERAL_STRING("rtl"));
|
||||
rv = rootElement->SetAttr(kNameSpaceID_None, nsGkAtoms::dir, NS_LITERAL_STRING("rtl"), true);
|
||||
}
|
||||
|
||||
return rv;
|
||||
|
@ -5293,8 +5280,7 @@ void
|
|||
nsEditor::SwitchTextDirectionTo(PRUint32 aDirection)
|
||||
{
|
||||
// Get the current root direction from its frame
|
||||
nsIDOMElement *rootElement = GetRoot();
|
||||
|
||||
dom::Element *rootElement = GetRoot();
|
||||
nsresult rv = DetermineCurrentDirection();
|
||||
NS_ENSURE_SUCCESS(rv, );
|
||||
|
||||
|
@ -5305,14 +5291,14 @@ nsEditor::SwitchTextDirectionTo(PRUint32 aDirection)
|
|||
"Unexpected mutually exclusive flag");
|
||||
mFlags &= ~nsIPlaintextEditor::eEditorRightToLeft;
|
||||
mFlags |= nsIPlaintextEditor::eEditorLeftToRight;
|
||||
rootElement->SetAttribute(NS_LITERAL_STRING("dir"), NS_LITERAL_STRING("ltr"));
|
||||
rootElement->SetAttr(kNameSpaceID_None, nsGkAtoms::dir, NS_LITERAL_STRING("ltr"), true);
|
||||
} else if (aDirection == nsIPlaintextEditor::eEditorRightToLeft &&
|
||||
(mFlags & nsIPlaintextEditor::eEditorLeftToRight)) {
|
||||
NS_ASSERTION(!(mFlags & nsIPlaintextEditor::eEditorRightToLeft),
|
||||
"Unexpected mutually exclusive flag");
|
||||
mFlags |= nsIPlaintextEditor::eEditorRightToLeft;
|
||||
mFlags &= ~nsIPlaintextEditor::eEditorLeftToRight;
|
||||
rootElement->SetAttribute(NS_LITERAL_STRING("dir"), NS_LITERAL_STRING("rtl"));
|
||||
rootElement->SetAttr(kNameSpaceID_None, nsGkAtoms::dir, NS_LITERAL_STRING("rtl"), true);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -651,7 +651,7 @@ public:
|
|||
virtual already_AddRefed<nsIDOMEventTarget> GetDOMEventTarget() = 0;
|
||||
|
||||
// Fast non-refcounting editor root element accessor
|
||||
nsIDOMElement *GetRoot();
|
||||
mozilla::dom::Element *GetRoot();
|
||||
|
||||
// Accessor methods to flags
|
||||
bool IsPlaintextEditor() const
|
||||
|
@ -763,8 +763,8 @@ public:
|
|||
|
||||
protected:
|
||||
|
||||
PRUint32 mModCount; // number of modifications (for undo/redo stack)
|
||||
PRUint32 mFlags; // behavior flags. See nsIPlaintextEditor.idl for the flags we use.
|
||||
PRUint32 mModCount; // number of modifications (for undo/redo stack)
|
||||
PRUint32 mFlags; // behavior flags. See nsIPlaintextEditor.idl for the flags we use.
|
||||
|
||||
nsWeakPtr mSelConWeak; // weak reference to the nsISelectionController
|
||||
PRInt32 mUpdateCount;
|
||||
|
@ -785,7 +785,7 @@ protected:
|
|||
nsSelectionState *mSelState; // saved selection state for placeholder txn batching
|
||||
nsSelectionState mSavedSel; // cached selection for nsAutoSelectionReset
|
||||
nsRangeUpdater mRangeUpdater; // utility class object for maintaining preserved ranges
|
||||
nsCOMPtr<nsIDOMElement> mRootElement; // cached root node
|
||||
nsCOMPtr<mozilla::dom::Element> mRootElement; // cached root node
|
||||
PRInt32 mAction; // the current editor action
|
||||
EDirection mDirection; // the current direction of editor action
|
||||
|
||||
|
|
|
@ -1401,17 +1401,3 @@ nsHTMLCSSUtils::SetCSSPropertyPixels(nsIDOMElement * aElement,
|
|||
s.AppendInt(aIntValue);
|
||||
return SetCSSProperty(aElement, aProperty, s + NS_LITERAL_STRING("px"));
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsHTMLCSSUtils::RemoveCSSProperty(nsIDOMElement * aElement,
|
||||
const nsAString & aProperty)
|
||||
{
|
||||
nsCOMPtr<nsIDOMCSSStyleDeclaration> cssDecl;
|
||||
PRUint32 length;
|
||||
nsresult res = GetInlineStyles(aElement, getter_AddRefs(cssDecl), &length);
|
||||
if (NS_FAILED(res) || !cssDecl) return res;
|
||||
|
||||
nsAutoString returnString;
|
||||
return cssDecl->RemoveProperty(aProperty, returnString);
|
||||
}
|
||||
|
||||
|
|
|
@ -139,8 +139,6 @@ public:
|
|||
nsresult SetCSSPropertyPixels(nsIDOMElement * aElement,
|
||||
const nsAString & aProperty,
|
||||
PRInt32 aIntValue);
|
||||
nsresult RemoveCSSProperty(nsIDOMElement * aElement,
|
||||
const nsAString & aProperty);
|
||||
|
||||
/** gets the specified/computed style value of a CSS property for a given node (or its element
|
||||
* ancestor if it is not an element)
|
||||
|
|
|
@ -81,6 +81,7 @@
|
|||
#include "nsIHTMLDocument.h"
|
||||
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/dom/Element.h"
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
|
@ -256,7 +257,7 @@ nsHTMLEditRules::Init(nsPlaintextEditor *aEditor)
|
|||
NS_ENSURE_TRUE(mUtilRange, NS_ERROR_NULL_POINTER);
|
||||
|
||||
// set up mDocChangeRange to be whole doc
|
||||
nsIDOMElement *rootElem = mHTMLEditor->GetRoot();
|
||||
nsCOMPtr<nsIDOMElement> rootElem = do_QueryInterface(mHTMLEditor->GetRoot());
|
||||
if (rootElem)
|
||||
{
|
||||
// temporarily turn off rules sniffing
|
||||
|
@ -805,7 +806,7 @@ nsHTMLEditRules::GetAlignment(bool *aMixed, nsIHTMLEditor::EAlignment *aAlign)
|
|||
|
||||
// get selection location
|
||||
nsCOMPtr<nsIDOMNode> parent;
|
||||
nsIDOMElement *rootElem = mHTMLEditor->GetRoot();
|
||||
nsCOMPtr<nsIDOMElement> rootElem = do_QueryInterface(mHTMLEditor->GetRoot());
|
||||
NS_ENSURE_TRUE(rootElem, NS_ERROR_FAILURE);
|
||||
|
||||
PRInt32 offset, rootOffset;
|
||||
|
@ -1012,13 +1013,10 @@ nsHTMLEditRules::GetIndentState(bool *aCanIndent, bool *aCanOutdent)
|
|||
// in the parent hierarchy.
|
||||
|
||||
// gather up info we need for test
|
||||
nsCOMPtr<nsIDOMNode> parent, tmp, root;
|
||||
nsIDOMElement *rootElem = mHTMLEditor->GetRoot();
|
||||
NS_ENSURE_TRUE(rootElem, NS_ERROR_NULL_POINTER);
|
||||
nsCOMPtr<nsIDOMNode> parent, tmp, root = do_QueryInterface(mHTMLEditor->GetRoot());
|
||||
NS_ENSURE_TRUE(root, NS_ERROR_NULL_POINTER);
|
||||
nsCOMPtr<nsISelection> selection;
|
||||
PRInt32 selOffset;
|
||||
root = do_QueryInterface(rootElem);
|
||||
NS_ENSURE_TRUE(root, NS_ERROR_NO_INTERFACE);
|
||||
res = mHTMLEditor->GetSelection(getter_AddRefs(selection));
|
||||
NS_ENSURE_SUCCESS(res, res);
|
||||
NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
|
||||
|
@ -1108,7 +1106,7 @@ nsHTMLEditRules::GetParagraphState(bool *aMixed, nsAString &outFormat)
|
|||
}
|
||||
|
||||
// remember root node
|
||||
nsIDOMElement *rootElem = mHTMLEditor->GetRoot();
|
||||
nsCOMPtr<nsIDOMElement> rootElem = do_QueryInterface(mHTMLEditor->GetRoot());
|
||||
NS_ENSURE_TRUE(rootElem, NS_ERROR_NULL_POINTER);
|
||||
|
||||
// loop through the nodes in selection and examine their paragraph format
|
||||
|
@ -7778,9 +7776,8 @@ nsHTMLEditRules::AdjustSelection(nsISelection *aSelection, nsIEditor::EDirection
|
|||
// check if br can go into the destination node
|
||||
if (bIsEmptyNode && mHTMLEditor->CanContainTag(selNode, NS_LITERAL_STRING("br")))
|
||||
{
|
||||
nsIDOMElement *rootElement = mHTMLEditor->GetRoot();
|
||||
NS_ENSURE_TRUE(rootElement, NS_ERROR_FAILURE);
|
||||
nsCOMPtr<nsIDOMNode> rootNode(do_QueryInterface(rootElement));
|
||||
nsCOMPtr<nsIDOMNode> rootNode = do_QueryInterface(mHTMLEditor->GetRoot());
|
||||
NS_ENSURE_TRUE(rootNode, NS_ERROR_FAILURE);
|
||||
if (selNode == rootNode)
|
||||
{
|
||||
// Our root node is completely empty. Don't add a <br> here.
|
||||
|
@ -8359,7 +8356,7 @@ nsHTMLEditRules::ConfirmSelectionInBody()
|
|||
nsresult res = NS_OK;
|
||||
|
||||
// get the body
|
||||
nsIDOMElement *rootElement = mHTMLEditor->GetRoot();
|
||||
nsCOMPtr<nsIDOMElement> rootElement = do_QueryInterface(mHTMLEditor->GetRoot());
|
||||
NS_ENSURE_TRUE(rootElement, NS_ERROR_UNEXPECTED);
|
||||
|
||||
// get the selection
|
||||
|
|
|
@ -381,28 +381,29 @@ nsHTMLEditor::GetRootElement(nsIDOMElement **aRootElement)
|
|||
// Use the HTML documents body element as the editor root if we didn't
|
||||
// get a root element during initialization.
|
||||
|
||||
nsCOMPtr<nsIDOMElement> rootElement;
|
||||
nsCOMPtr<nsIDOMHTMLElement> bodyElement;
|
||||
nsresult rv = GetBodyElement(getter_AddRefs(bodyElement));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (bodyElement) {
|
||||
mRootElement = bodyElement;
|
||||
rootElement = bodyElement;
|
||||
} else {
|
||||
// If there is no HTML body element,
|
||||
// we should use the document root element instead.
|
||||
nsCOMPtr<nsIDOMDocument> doc = do_QueryReferent(mDocWeak);
|
||||
NS_ENSURE_TRUE(doc, NS_ERROR_NOT_INITIALIZED);
|
||||
|
||||
rv = doc->GetDocumentElement(getter_AddRefs(mRootElement));
|
||||
rv = doc->GetDocumentElement(getter_AddRefs(rootElement));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
// Document can have no elements
|
||||
if (!mRootElement) {
|
||||
if (!rootElement) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
}
|
||||
|
||||
*aRootElement = mRootElement;
|
||||
NS_ADDREF(*aRootElement);
|
||||
mRootElement = do_QueryInterface(rootElement);
|
||||
rootElement.forget(aRootElement);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -544,7 +545,7 @@ nsHTMLEditor::BeginningOfDocument()
|
|||
NS_ENSURE_TRUE(selection, NS_ERROR_NOT_INITIALIZED);
|
||||
|
||||
// Get the root element.
|
||||
nsIDOMElement *rootElement = GetRoot();
|
||||
nsCOMPtr<nsIDOMElement> rootElement = do_QueryInterface(GetRoot());
|
||||
if (!rootElement) {
|
||||
NS_WARNING("GetRoot() returned a null pointer (mRootElement is null)");
|
||||
return NS_OK;
|
||||
|
@ -968,155 +969,6 @@ nsHTMLEditor::GetBlockNodeParent(nsIDOMNode *aNode)
|
|||
return p.forget();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// GetBlockSection: return leftmost/rightmost nodes in aChild's block
|
||||
//
|
||||
nsresult
|
||||
nsHTMLEditor::GetBlockSection(nsIDOMNode *aChild,
|
||||
nsIDOMNode **aLeftNode,
|
||||
nsIDOMNode **aRightNode)
|
||||
{
|
||||
nsresult result = NS_OK;
|
||||
if (!aChild || !aLeftNode || !aRightNode) {return NS_ERROR_NULL_POINTER;}
|
||||
*aLeftNode = aChild;
|
||||
*aRightNode = aChild;
|
||||
|
||||
nsCOMPtr<nsIDOMNode>sibling;
|
||||
result = aChild->GetPreviousSibling(getter_AddRefs(sibling));
|
||||
while ((NS_SUCCEEDED(result)) && sibling)
|
||||
{
|
||||
bool isBlock;
|
||||
NodeIsBlockStatic(sibling, &isBlock);
|
||||
if (isBlock)
|
||||
{
|
||||
nsCOMPtr<nsIDOMCharacterData>nodeAsText = do_QueryInterface(sibling);
|
||||
if (!nodeAsText) {
|
||||
break;
|
||||
}
|
||||
// XXX: needs some logic to work for other leaf nodes besides text!
|
||||
}
|
||||
*aLeftNode = sibling;
|
||||
result = (*aLeftNode)->GetPreviousSibling(getter_AddRefs(sibling));
|
||||
}
|
||||
NS_ADDREF((*aLeftNode));
|
||||
// now do the right side
|
||||
result = aChild->GetNextSibling(getter_AddRefs(sibling));
|
||||
while ((NS_SUCCEEDED(result)) && sibling)
|
||||
{
|
||||
bool isBlock;
|
||||
NodeIsBlockStatic(sibling, &isBlock);
|
||||
if (isBlock)
|
||||
{
|
||||
nsCOMPtr<nsIDOMCharacterData>nodeAsText = do_QueryInterface(sibling);
|
||||
if (!nodeAsText) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
*aRightNode = sibling;
|
||||
result = (*aRightNode)->GetNextSibling(getter_AddRefs(sibling));
|
||||
}
|
||||
NS_ADDREF((*aRightNode));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// GetBlockSectionsForRange: return list of block sections that intersect
|
||||
// this range
|
||||
nsresult
|
||||
nsHTMLEditor::GetBlockSectionsForRange(nsIDOMRange *aRange,
|
||||
nsCOMArray<nsIDOMRange>& aSections)
|
||||
{
|
||||
if (!aRange) {return NS_ERROR_NULL_POINTER;}
|
||||
|
||||
nsresult result;
|
||||
nsCOMPtr<nsIContentIterator>iter =
|
||||
do_CreateInstance("@mozilla.org/content/post-content-iterator;1", &result);
|
||||
if (NS_FAILED(result) || !iter) {
|
||||
return result;
|
||||
}
|
||||
nsCOMPtr<nsIDOMRange> lastRange;
|
||||
iter->Init(aRange);
|
||||
while (iter->IsDone())
|
||||
{
|
||||
nsCOMPtr<nsIContent> currentContent =
|
||||
do_QueryInterface(iter->GetCurrentNode());
|
||||
|
||||
nsCOMPtr<nsIDOMNode> currentNode = do_QueryInterface(currentContent);
|
||||
if (currentNode)
|
||||
{
|
||||
// <BR> divides block content ranges. We can achieve this by nulling out lastRange
|
||||
if (currentContent->Tag() == nsEditProperty::br)
|
||||
{
|
||||
lastRange = nsnull;
|
||||
}
|
||||
else
|
||||
{
|
||||
bool isNotInlineOrText;
|
||||
result = NodeIsBlockStatic(currentNode, &isNotInlineOrText);
|
||||
if (isNotInlineOrText)
|
||||
{
|
||||
PRUint16 nodeType;
|
||||
currentNode->GetNodeType(&nodeType);
|
||||
if (nsIDOMNode::TEXT_NODE == nodeType) {
|
||||
isNotInlineOrText = true;
|
||||
}
|
||||
}
|
||||
if (!isNotInlineOrText) {
|
||||
nsCOMPtr<nsIDOMNode> leftNode;
|
||||
nsCOMPtr<nsIDOMNode> rightNode;
|
||||
result = GetBlockSection(currentNode,
|
||||
getter_AddRefs(leftNode),
|
||||
getter_AddRefs(rightNode));
|
||||
if ((NS_SUCCEEDED(result)) && leftNode && rightNode) {
|
||||
// Add range to the list if it doesn't overlap with the previous
|
||||
// range.
|
||||
bool addRange = true;
|
||||
if (lastRange)
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode> lastStartNode;
|
||||
lastRange->GetStartContainer(getter_AddRefs(lastStartNode));
|
||||
nsCOMPtr<nsIDOMNode> blockParentNodeOfLastStartNode =
|
||||
GetBlockNodeParent(lastStartNode);
|
||||
nsCOMPtr<nsIDOMElement> blockParentOfLastStartNode =
|
||||
do_QueryInterface(blockParentNodeOfLastStartNode);
|
||||
if (blockParentOfLastStartNode)
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode> blockParentNodeOfLeftNode =
|
||||
GetBlockNodeParent(leftNode);
|
||||
nsCOMPtr<nsIDOMElement> blockParentOfLeftNode =
|
||||
do_QueryInterface(blockParentNodeOfLeftNode);
|
||||
if (blockParentOfLeftNode &&
|
||||
blockParentOfLastStartNode == blockParentOfLeftNode) {
|
||||
addRange = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (addRange) {
|
||||
nsCOMPtr<nsIDOMRange> range =
|
||||
do_CreateInstance("@mozilla.org/content/range;1", &result);
|
||||
if ((NS_SUCCEEDED(result)) && range) {
|
||||
// Initialize the range.
|
||||
range->SetStart(leftNode, 0);
|
||||
range->SetEnd(rightNode, 0);
|
||||
aSections.AppendObject(range);
|
||||
lastRange = do_QueryInterface(range);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/* do not check result here, and especially do not return the result code.
|
||||
* we rely on iter->IsDone to tell us when the iteration is complete
|
||||
*/
|
||||
iter->Next();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// NextNodeInBlock: gets the next/prev node in the block, if any. Next node
|
||||
// must be an element or text node, others are ignored
|
||||
|
@ -1809,8 +1661,7 @@ nsHTMLEditor::RebuildDocumentFromSource(const nsAString& aSourceString)
|
|||
nsresult res = GetSelection(getter_AddRefs(selection));
|
||||
NS_ENSURE_SUCCESS(res, res);
|
||||
|
||||
nsIDOMElement *bodyElement = GetRoot();
|
||||
NS_ENSURE_SUCCESS(res, res);
|
||||
nsCOMPtr<nsIDOMElement> bodyElement = do_QueryInterface(GetRoot());
|
||||
NS_ENSURE_TRUE(bodyElement, NS_ERROR_NULL_POINTER);
|
||||
|
||||
// Find where the <body> tag starts.
|
||||
|
@ -2452,10 +2303,10 @@ nsHTMLEditor::GetHTMLBackgroundColorState(bool *aMixed, nsAString &aOutColor)
|
|||
}
|
||||
|
||||
// If no table or cell found, get page body
|
||||
element = GetRoot();
|
||||
NS_ENSURE_TRUE(element, NS_ERROR_NULL_POINTER);
|
||||
mozilla::dom::Element *bodyElement = GetRoot();
|
||||
NS_ENSURE_TRUE(bodyElement, NS_ERROR_NULL_POINTER);
|
||||
|
||||
return element->GetAttribute(styleName, aOutColor);
|
||||
return bodyElement->GetAttr(kNameSpaceID_None, nsGkAtoms::bgcolor, aOutColor);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -3392,7 +3243,7 @@ nsHTMLEditor::SetHTMLBackgroundColor(const nsAString& aColor)
|
|||
// If we failed to find a cell, fall through to use originally-found element
|
||||
} else {
|
||||
// No table element -- set the background color on the body tag
|
||||
element = GetRoot();
|
||||
element = do_QueryInterface(GetRoot());
|
||||
NS_ENSURE_TRUE(element, NS_ERROR_NULL_POINTER);
|
||||
}
|
||||
// Use the editor method that goes through the transaction system
|
||||
|
@ -3411,8 +3262,7 @@ NS_IMETHODIMP nsHTMLEditor::SetBodyAttribute(const nsAString& aAttribute, const
|
|||
NS_ASSERTION(mDocWeak, "Missing Editor DOM Document");
|
||||
|
||||
// Set the background color attribute on the body tag
|
||||
nsIDOMElement *bodyElement = GetRoot();
|
||||
|
||||
nsCOMPtr<nsIDOMElement> bodyElement = do_QueryInterface(GetRoot());
|
||||
NS_ENSURE_TRUE(bodyElement, NS_ERROR_NULL_POINTER);
|
||||
|
||||
// Use the editor method that goes through the transaction system
|
||||
|
@ -3880,7 +3730,7 @@ already_AddRefed<nsIDOMNode>
|
|||
nsHTMLEditor::FindUserSelectAllNode(nsIDOMNode* aNode)
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode> node = aNode;
|
||||
nsIDOMElement *root = GetRoot();
|
||||
nsCOMPtr<nsIDOMElement> root = do_QueryInterface(GetRoot());
|
||||
if (!nsEditorUtils::IsDescendantOf(aNode, root))
|
||||
return nsnull;
|
||||
|
||||
|
@ -4145,7 +3995,7 @@ nsHTMLEditor::SelectEntireDocument(nsISelection *aSelection)
|
|||
nsCOMPtr<nsIEditRules> kungFuDeathGrip(mRules);
|
||||
|
||||
// get editor root node
|
||||
nsIDOMElement *rootElement = GetRoot();
|
||||
nsCOMPtr<nsIDOMElement> rootElement = do_QueryInterface(GetRoot());
|
||||
|
||||
// is doc empty?
|
||||
bool bDocIsEmpty;
|
||||
|
@ -4190,7 +4040,9 @@ nsHTMLEditor::SelectAll()
|
|||
NS_ENSURE_TRUE(selPriv, NS_ERROR_UNEXPECTED);
|
||||
rv = selPriv->SetAncestorLimiter(nsnull);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
return selection->SelectAllChildren(mRootElement);
|
||||
nsCOMPtr<nsIDOMNode> rootElement = do_QueryInterface(mRootElement, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
return selection->SelectAllChildren(rootElement);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIPresShell> ps = GetPresShell();
|
||||
|
@ -4481,7 +4333,7 @@ nsHTMLEditor::CollapseAdjacentTextNodes(nsIDOMRange *aInRange)
|
|||
NS_IMETHODIMP
|
||||
nsHTMLEditor::SetSelectionAtDocumentStart(nsISelection *aSelection)
|
||||
{
|
||||
nsIDOMElement *rootElement = GetRoot();
|
||||
nsCOMPtr<nsIDOMElement> rootElement = do_QueryInterface(GetRoot());
|
||||
NS_ENSURE_TRUE(rootElement, NS_ERROR_NULL_POINTER);
|
||||
|
||||
return aSelection->Collapse(rootElement,0);
|
||||
|
|
|
@ -277,38 +277,6 @@ public:
|
|||
|
||||
/* ------------ Block methods moved from nsEditor -------------- */
|
||||
static already_AddRefed<nsIDOMNode> GetBlockNodeParent(nsIDOMNode *aNode);
|
||||
/** Determines the bounding nodes for the block section containing aNode.
|
||||
* The calculation is based on some nodes intrinsically being block elements
|
||||
* acording to HTML. Style sheets are not considered in this calculation.
|
||||
* <BR> tags separate block content sections. So the HTML markup:
|
||||
* <PRE>
|
||||
* <P>text1<BR>text2<B>text3</B></P>
|
||||
* </PRE>
|
||||
* contains two block content sections. The first has the text node "text1"
|
||||
* for both endpoints. The second has "text2" as the left endpoint and
|
||||
* "text3" as the right endpoint.
|
||||
* Notice that offsets aren't required, only leaf nodes. Offsets are implicit.
|
||||
*
|
||||
* @param aNode the block content returned includes aNode
|
||||
* @param aLeftNode [OUT] the left endpoint of the block content containing aNode
|
||||
* @param aRightNode [OUT] the right endpoint of the block content containing aNode
|
||||
*
|
||||
*/
|
||||
static nsresult GetBlockSection(nsIDOMNode *aNode,
|
||||
nsIDOMNode **aLeftNode,
|
||||
nsIDOMNode **aRightNode);
|
||||
|
||||
/** Compute the set of block sections in a given range.
|
||||
* A block section is the set of (leftNode, rightNode) pairs given
|
||||
* by GetBlockSection. The set is computed by computing the
|
||||
* block section for every leaf node in the range and throwing
|
||||
* out duplicates.
|
||||
*
|
||||
* @param aRange The range to compute block sections for.
|
||||
* @param aSections Allocated storage for the resulting set, stored as nsIDOMRanges.
|
||||
*/
|
||||
static nsresult GetBlockSectionsForRange(nsIDOMRange *aRange,
|
||||
nsCOMArray<nsIDOMRange>& aSections);
|
||||
|
||||
static already_AddRefed<nsIDOMNode> NextNodeInBlock(nsIDOMNode *aNode, IterDirection aDir);
|
||||
nsresult IsNextCharWhitespace(nsIDOMNode *aParentNode,
|
||||
|
|
|
@ -43,6 +43,7 @@
|
|||
#include "nsIContent.h"
|
||||
#include "nsHTMLEditUtils.h"
|
||||
#include "nsReadableUtils.h"
|
||||
#include "mozilla/dom/Element.h"
|
||||
|
||||
// Uncomment the following line if you want to disable
|
||||
// table deletion when the only column/row is removed
|
||||
|
@ -77,7 +78,7 @@ nsHTMLEditor::ShowInlineTableEditingUI(nsIDOMElement * aCell)
|
|||
}
|
||||
|
||||
// the resizers and the shadow will be anonymous children of the body
|
||||
nsIDOMElement *bodyElement = GetRoot();
|
||||
nsCOMPtr<nsIDOMElement> bodyElement = do_QueryInterface(GetRoot());
|
||||
NS_ENSURE_TRUE(bodyElement, NS_ERROR_NULL_POINTER);
|
||||
|
||||
CreateAnonymousElement(NS_LITERAL_STRING("a"), bodyElement,
|
||||
|
@ -130,10 +131,7 @@ nsHTMLEditor::HideInlineTableEditingUI()
|
|||
// UnbindFromTree.
|
||||
|
||||
// get the root content node.
|
||||
|
||||
nsIDOMElement *bodyElement = GetRoot();
|
||||
|
||||
nsCOMPtr<nsIContent> bodyContent( do_QueryInterface(bodyElement) );
|
||||
nsCOMPtr<nsIContent> bodyContent = GetRoot();
|
||||
NS_ENSURE_TRUE(bodyContent, NS_ERROR_FAILURE);
|
||||
|
||||
DeleteRefToAnonymousNode(mAddColumnBeforeButton, bodyContent, ps);
|
||||
|
|
|
@ -75,6 +75,7 @@
|
|||
#include "nsGkAtoms.h"
|
||||
#include "nsDebug.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/dom/Element.h"
|
||||
|
||||
// Drag & Drop, Clipboard
|
||||
#include "nsIClipboard.h"
|
||||
|
@ -571,7 +572,8 @@ nsPlaintextEditor::GetTextSelectionOffsets(nsISelection *aSelection,
|
|||
aSelection->GetFocusNode(getter_AddRefs(endNode));
|
||||
aSelection->GetFocusOffset(&endNodeOffset);
|
||||
|
||||
nsIDOMElement* rootNode = GetRoot();
|
||||
dom::Element *rootElement = GetRoot();
|
||||
nsCOMPtr<nsIDOMNode> rootNode = do_QueryInterface(rootElement);
|
||||
NS_ENSURE_TRUE(rootNode, NS_ERROR_NULL_POINTER);
|
||||
|
||||
PRInt32 startOffset = -1;
|
||||
|
@ -585,8 +587,7 @@ nsPlaintextEditor::GetTextSelectionOffsets(nsISelection *aSelection,
|
|||
PRInt32 nodeCount = 0; // only needed for the assertions below
|
||||
#endif
|
||||
PRUint32 totalLength = 0;
|
||||
nsCOMPtr<nsIContent> rootContent = do_QueryInterface(rootNode);
|
||||
iter->Init(rootContent);
|
||||
iter->Init(rootElement);
|
||||
for (; !iter->IsDone() && (startOffset == -1 || endOffset == -1); iter->Next()) {
|
||||
nsCOMPtr<nsIDOMNode> currentNode = do_QueryInterface(iter->GetCurrentNode());
|
||||
nsCOMPtr<nsIDOMCharacterData> textNode = do_QueryInterface(currentNode);
|
||||
|
@ -1020,16 +1021,15 @@ nsPlaintextEditor::GetTextLength(PRInt32 *aCount)
|
|||
if (docEmpty)
|
||||
return NS_OK;
|
||||
|
||||
nsIDOMElement* rootNode = GetRoot();
|
||||
NS_ENSURE_TRUE(rootNode, NS_ERROR_NULL_POINTER);
|
||||
dom::Element *rootElement = GetRoot();
|
||||
NS_ENSURE_TRUE(rootElement, NS_ERROR_NULL_POINTER);
|
||||
|
||||
nsCOMPtr<nsIContentIterator> iter =
|
||||
do_CreateInstance("@mozilla.org/content/post-content-iterator;1", &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
PRUint32 totalLength = 0;
|
||||
nsCOMPtr<nsIContent> rootContent = do_QueryInterface(rootNode);
|
||||
iter->Init(rootContent);
|
||||
iter->Init(rootElement);
|
||||
for (; !iter->IsDone(); iter->Next()) {
|
||||
nsCOMPtr<nsIDOMNode> currentNode = do_QueryInterface(iter->GetCurrentNode());
|
||||
nsCOMPtr<nsIDOMCharacterData> textNode = do_QueryInterface(currentNode);
|
||||
|
@ -1104,13 +1104,12 @@ nsPlaintextEditor::SetWrapWidth(PRInt32 aWrapColumn)
|
|||
|
||||
// Ought to set a style sheet here ...
|
||||
// Probably should keep around an mPlaintextStyleSheet for this purpose.
|
||||
nsIDOMElement *rootElement = GetRoot();
|
||||
dom::Element *rootElement = GetRoot();
|
||||
NS_ENSURE_TRUE(rootElement, NS_ERROR_NULL_POINTER);
|
||||
|
||||
// Get the current style for this root element:
|
||||
NS_NAMED_LITERAL_STRING(styleName, "style");
|
||||
nsAutoString styleValue;
|
||||
nsresult res = rootElement->GetAttribute(styleName, styleValue);
|
||||
nsresult res = rootElement->GetAttr(kNameSpaceID_None, nsGkAtoms::style, styleValue);
|
||||
NS_ENSURE_SUCCESS(res, res);
|
||||
|
||||
// We'll replace styles for these values:
|
||||
|
@ -1154,7 +1153,7 @@ nsPlaintextEditor::SetWrapWidth(PRInt32 aWrapColumn)
|
|||
else
|
||||
styleValue.AppendLiteral("white-space: pre;");
|
||||
|
||||
return rootElement->SetAttribute(styleName, styleValue);
|
||||
return rootElement->SetAttr(kNameSpaceID_None, nsGkAtoms::style, styleValue, true);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -1354,7 +1353,7 @@ nsPlaintextEditor::GetAndInitDocEncoder(const nsAString& aFormatType,
|
|||
// in which case we set the selection to encompass the root.
|
||||
else
|
||||
{
|
||||
nsIDOMElement *rootElement = GetRoot();
|
||||
nsCOMPtr<nsIDOMElement> rootElement = do_QueryInterface(GetRoot());
|
||||
NS_ENSURE_TRUE(rootElement, NS_ERROR_FAILURE);
|
||||
if (!nsTextEditUtils::IsBody(rootElement))
|
||||
{
|
||||
|
@ -1684,7 +1683,7 @@ nsPlaintextEditor::SelectEntireDocument(nsISelection *aSelection)
|
|||
if (NS_SUCCEEDED(mRules->DocumentIsEmpty(&bDocIsEmpty)) && bDocIsEmpty)
|
||||
{
|
||||
// get root node
|
||||
nsIDOMElement *rootElement = GetRoot();
|
||||
nsCOMPtr<nsIDOMElement> rootElement = do_QueryInterface(GetRoot());
|
||||
NS_ENSURE_TRUE(rootElement, NS_ERROR_FAILURE);
|
||||
|
||||
// if it's empty don't select entire doc - that would select the bogus node
|
||||
|
|
|
@ -68,6 +68,7 @@
|
|||
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/LookAndFeel.h"
|
||||
#include "mozilla/dom/Element.h"
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
|
@ -460,8 +461,7 @@ nsTextEditRules::CollapseSelectionToTrailingBRIfNeeded(nsISelection* aSelection)
|
|||
&parentOffset);
|
||||
NS_ENSURE_SUCCESS(res, res);
|
||||
|
||||
nsIDOMElement *rootElem = mEditor->GetRoot();
|
||||
nsCOMPtr<nsIDOMNode> root = do_QueryInterface(rootElem);
|
||||
nsCOMPtr<nsIDOMNode> root = do_QueryInterface(mEditor->GetRoot());
|
||||
NS_ENSURE_TRUE(root, NS_ERROR_NULL_POINTER);
|
||||
if (parentNode != root) return NS_OK;
|
||||
|
||||
|
@ -949,7 +949,7 @@ nsTextEditRules::DidUndo(nsISelection *aSelection, nsresult aResult)
|
|||
}
|
||||
else
|
||||
{
|
||||
nsIDOMElement *theRoot = mEditor->GetRoot();
|
||||
nsCOMPtr<nsIDOMElement> theRoot = do_QueryInterface(mEditor->GetRoot());
|
||||
NS_ENSURE_TRUE(theRoot, NS_ERROR_FAILURE);
|
||||
nsCOMPtr<nsIDOMNode> node = mEditor->GetLeftmostChild(theRoot);
|
||||
if (node && mEditor->IsMozEditorBogusNode(node))
|
||||
|
@ -982,7 +982,7 @@ nsTextEditRules::DidRedo(nsISelection *aSelection, nsresult aResult)
|
|||
}
|
||||
else
|
||||
{
|
||||
nsIDOMElement *theRoot = mEditor->GetRoot();
|
||||
nsCOMPtr<nsIDOMElement> theRoot = do_QueryInterface(mEditor->GetRoot());
|
||||
NS_ENSURE_TRUE(theRoot, NS_ERROR_FAILURE);
|
||||
|
||||
nsCOMPtr<nsIDOMNodeList> nodeList;
|
||||
|
@ -1056,7 +1056,7 @@ nsTextEditRules::RemoveRedundantTrailingBR()
|
|||
if (IsSingleLineEditor())
|
||||
return NS_OK;
|
||||
|
||||
nsIDOMNode* body = mEditor->GetRoot();
|
||||
nsCOMPtr<nsIDOMNode> body = do_QueryInterface(mEditor->GetRoot());
|
||||
if (!body)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
|
@ -1111,7 +1111,7 @@ nsTextEditRules::CreateTrailingBRIfNeeded()
|
|||
// but only if we aren't a single line edit field
|
||||
if (IsSingleLineEditor())
|
||||
return NS_OK;
|
||||
nsIDOMNode *body = mEditor->GetRoot();
|
||||
nsCOMPtr<nsIDOMNode> body = do_QueryInterface(mEditor->GetRoot());
|
||||
NS_ENSURE_TRUE(body, NS_ERROR_NULL_POINTER);
|
||||
nsCOMPtr<nsIDOMNode> lastChild;
|
||||
nsresult res = body->GetLastChild(getter_AddRefs(lastChild));
|
||||
|
@ -1141,7 +1141,7 @@ nsTextEditRules::CreateBogusNodeIfNeeded(nsISelection *aSelection)
|
|||
// tell rules system to not do any post-processing
|
||||
nsAutoRules beginRulesSniffing(mEditor, nsEditor::kOpIgnore, nsIEditor::eNone);
|
||||
|
||||
nsIDOMNode* body = mEditor->GetRoot();
|
||||
nsCOMPtr<nsIDOMNode> body = do_QueryInterface(mEditor->GetRoot());
|
||||
if (!body)
|
||||
{
|
||||
// we don't even have a body yet, don't insert any bogus nodes at
|
||||
|
|
|
@ -78,7 +78,7 @@ namespace mozilla {
|
|||
namespace layers {
|
||||
class LayerManagerOGL;
|
||||
class ColorTextureLayerProgram;
|
||||
};
|
||||
}
|
||||
|
||||
namespace gl {
|
||||
class GLContext;
|
||||
|
@ -542,6 +542,7 @@ public:
|
|||
#endif
|
||||
mIsGlobalSharedContext(false),
|
||||
mHasRobustness(false),
|
||||
mContextLost(false),
|
||||
mVendor(-1),
|
||||
mDebugMode(0),
|
||||
mCreationFormat(aFormat),
|
||||
|
@ -595,6 +596,8 @@ public:
|
|||
return MakeCurrentImpl(aForce);
|
||||
}
|
||||
|
||||
bool IsContextLost() { return mContextLost; }
|
||||
|
||||
virtual bool SetupLookupFunction() = 0;
|
||||
|
||||
virtual void WindowDestroyed() {}
|
||||
|
@ -1326,6 +1329,7 @@ protected:
|
|||
bool mIsGLES2;
|
||||
bool mIsGlobalSharedContext;
|
||||
bool mHasRobustness;
|
||||
bool mContextLost;
|
||||
|
||||
PRInt32 mVendor;
|
||||
|
||||
|
|
|
@ -834,6 +834,10 @@ public:
|
|||
succeeded = sEGLLibrary.fMakeCurrent(EGL_DISPLAY(),
|
||||
mSurface, mSurface,
|
||||
mContext);
|
||||
if (!succeeded && sEGLLibrary.fGetError() == LOCAL_EGL_CONTEXT_LOST) {
|
||||
mContextLost = true;
|
||||
NS_WARNING("EGL context has been lost.");
|
||||
}
|
||||
NS_ASSERTION(succeeded, "Failed to make GL context current!");
|
||||
}
|
||||
|
||||
|
|
|
@ -122,6 +122,13 @@ CreateDummyWindow(HDC *aWindowDC = nsnull)
|
|||
return win;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
HasExtension(const char* aExtensions, const char* aRequiredExtension)
|
||||
{
|
||||
return GLContext::ListHasExtension(
|
||||
reinterpret_cast<const GLubyte*>(aExtensions), aRequiredExtension);
|
||||
}
|
||||
|
||||
bool
|
||||
WGLLibrary::EnsureInitialized()
|
||||
{
|
||||
|
@ -205,9 +212,47 @@ WGLLibrary::EnsureInitialized()
|
|||
fChoosePixelFormat = nsnull;
|
||||
}
|
||||
|
||||
LibrarySymbolLoader::SymLoadStruct extensionsSymbols[] = {
|
||||
{ (PRFuncPtr *) &fGetExtensionsString, { "wglGetExtensionsStringARB", NULL} },
|
||||
{ NULL, { NULL } }
|
||||
};
|
||||
|
||||
LibrarySymbolLoader::SymLoadStruct robustnessSymbols[] = {
|
||||
{ (PRFuncPtr *) &fCreateContextAttribs, { "wglCreateContextAttribsARB", NULL} },
|
||||
{ NULL, { NULL } }
|
||||
};
|
||||
|
||||
if (LibrarySymbolLoader::LoadSymbols(mOGLLibrary, &extensionsSymbols[0],
|
||||
(LibrarySymbolLoader::PlatformLookupFunction)fGetProcAddress)) {
|
||||
const char *wglExts = fGetExtensionsString(gSharedWindowDC);
|
||||
if (wglExts && HasExtension(wglExts, "WGL_ARB_create_context")) {
|
||||
LibrarySymbolLoader::LoadSymbols(mOGLLibrary, &robustnessSymbols[0],
|
||||
(LibrarySymbolLoader::PlatformLookupFunction)fGetProcAddress);
|
||||
if (HasExtension(wglExts, "WGL_ARB_create_context_robustness")) {
|
||||
mHasRobustness = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// reset back to the previous context, just in case
|
||||
fMakeCurrent(curDC, curCtx);
|
||||
|
||||
if (mHasRobustness) {
|
||||
fDeleteContext(gSharedWindowGLContext);
|
||||
|
||||
int attribs[] = {
|
||||
LOCAL_WGL_CONTEXT_FLAGS_ARB, LOCAL_WGL_CONTEXT_ROBUST_ACCESS_BIT_ARB,
|
||||
LOCAL_WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB, LOCAL_WGL_LOSE_CONTEXT_ON_RESET_ARB,
|
||||
NULL
|
||||
};
|
||||
|
||||
gSharedWindowGLContext = fCreateContextAttribs(gSharedWindowDC, NULL, attribs);
|
||||
if (!gSharedWindowGLContext) {
|
||||
mHasRobustness = false;
|
||||
gSharedWindowGLContext = fCreateContext(gSharedWindowDC);
|
||||
}
|
||||
}
|
||||
|
||||
mInitialized = true;
|
||||
|
||||
// Call this to create the global GLContext instance,
|
||||
|
@ -309,7 +354,7 @@ public:
|
|||
|
||||
bool SupportsRobustness()
|
||||
{
|
||||
return false;
|
||||
return sWGLLibrary.HasRobustness();
|
||||
}
|
||||
|
||||
virtual bool SwapBuffers() {
|
||||
|
@ -502,16 +547,35 @@ GLContextProviderWGL::CreateForWindow(nsIWidget *aWidget)
|
|||
HDC dc = (HDC)aWidget->GetNativeData(NS_NATIVE_GRAPHIC);
|
||||
|
||||
SetPixelFormat(dc, gSharedWindowPixelFormat, NULL);
|
||||
HGLRC context = sWGLLibrary.fCreateContext(dc);
|
||||
if (!context) {
|
||||
return nsnull;
|
||||
}
|
||||
HGLRC context;
|
||||
|
||||
GLContextWGL *shareContext = GetGlobalContextWGL();
|
||||
if (shareContext &&
|
||||
!sWGLLibrary.fShareLists(shareContext->Context(), context))
|
||||
{
|
||||
shareContext = nsnull;
|
||||
|
||||
if (sWGLLibrary.HasRobustness()) {
|
||||
int attribs[] = {
|
||||
LOCAL_WGL_CONTEXT_FLAGS_ARB, LOCAL_WGL_CONTEXT_ROBUST_ACCESS_BIT_ARB,
|
||||
LOCAL_WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB, LOCAL_WGL_LOSE_CONTEXT_ON_RESET_ARB,
|
||||
NULL
|
||||
};
|
||||
|
||||
context = sWGLLibrary.fCreateContextAttribs(dc,
|
||||
shareContext ? shareContext->Context() : nsnull,
|
||||
attribs);
|
||||
if (!context && shareContext) {
|
||||
context = sWGLLibrary.fCreateContextAttribs(dc, nsnull, attribs);
|
||||
if (context) {
|
||||
shareContext = nsnull;
|
||||
}
|
||||
} else {
|
||||
context = sWGLLibrary.fCreateContext(dc);
|
||||
if (context && shareContext && !sWGLLibrary.fShareLists(shareContext->Context(), context)) {
|
||||
shareContext = nsnull;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!context) {
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
nsRefPtr<GLContextWGL> glContext = new GLContextWGL(ContextFormat(ContextFormat::BasicRGB24),
|
||||
|
@ -597,7 +661,19 @@ CreatePBufferOffscreenContext(const gfxIntSize& aSize,
|
|||
HDC pbdc = sWGLLibrary.fGetPbufferDC(pbuffer);
|
||||
NS_ASSERTION(pbdc, "expected a dc");
|
||||
|
||||
HGLRC context = sWGLLibrary.fCreateContext(pbdc);
|
||||
HGLRC context;
|
||||
if (sWGLLibrary.HasRobustness()) {
|
||||
int attribs[] = {
|
||||
LOCAL_WGL_CONTEXT_FLAGS_ARB, LOCAL_WGL_CONTEXT_ROBUST_ACCESS_BIT_ARB,
|
||||
LOCAL_WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB, LOCAL_WGL_LOSE_CONTEXT_ON_RESET_ARB,
|
||||
NULL
|
||||
};
|
||||
|
||||
context = sWGLLibrary.fCreateContextAttribs(pbdc, nsnull, attribs);
|
||||
} else {
|
||||
context = sWGLLibrary.fCreateContext(pbdc);
|
||||
}
|
||||
|
||||
if (!context) {
|
||||
sWGLLibrary.fDestroyPbuffer(pbuffer);
|
||||
return false;
|
||||
|
@ -629,15 +705,28 @@ CreateWindowOffscreenContext(const ContextFormat& aFormat)
|
|||
}
|
||||
|
||||
HGLRC context = sWGLLibrary.fCreateContext(dc);
|
||||
if (!context) {
|
||||
return nsnull;
|
||||
if (sWGLLibrary.HasRobustness()) {
|
||||
int attribs[] = {
|
||||
LOCAL_WGL_CONTEXT_FLAGS_ARB, LOCAL_WGL_CONTEXT_ROBUST_ACCESS_BIT_ARB,
|
||||
LOCAL_WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB, LOCAL_WGL_LOSE_CONTEXT_ON_RESET_ARB,
|
||||
NULL
|
||||
};
|
||||
|
||||
context = sWGLLibrary.fCreateContextAttribs(dc, shareContext->Context(), attribs);
|
||||
} else {
|
||||
context = sWGLLibrary.fCreateContext(dc);
|
||||
if (context && shareContext &&
|
||||
!sWGLLibrary.fShareLists(shareContext->Context(), context))
|
||||
{
|
||||
NS_WARNING("wglShareLists failed!");
|
||||
|
||||
sWGLLibrary.fDeleteContext(context);
|
||||
DestroyWindow(win);
|
||||
return nsnull;
|
||||
}
|
||||
}
|
||||
|
||||
if (!sWGLLibrary.fShareLists(shareContext->Context(), context)) {
|
||||
NS_WARNING("wglShareLists failed!");
|
||||
|
||||
sWGLLibrary.fDeleteContext(context);
|
||||
DestroyWindow(win);
|
||||
if (!context) {
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
|
|
|
@ -3246,4 +3246,5 @@ typedef ptrdiff_t GLintptr;
|
|||
#define LOCAL_EGL_CORE_NATIVE_ENGINE 0x305B
|
||||
#define LOCAL_EGL_READ 0x305A
|
||||
#define LOCAL_EGL_DRAW 0x3059
|
||||
#define LOCAL_EGL_CONTEXT_LOST 0x300E
|
||||
#endif
|
||||
|
|
|
@ -1,3 +1,37 @@
|
|||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is mozilla.org code.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Mozilla Foundation.
|
||||
# Portions created by the Initial Developer are Copyright (C) 2011
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
DEPTH = ../..
|
||||
topsrcdir = @top_srcdir@
|
||||
|
|
|
@ -42,7 +42,8 @@ namespace gl {
|
|||
class WGLLibrary
|
||||
{
|
||||
public:
|
||||
WGLLibrary() : mInitialized(false), mOGLLibrary(nsnull) {}
|
||||
WGLLibrary() : mInitialized(false), mOGLLibrary(nsnull),
|
||||
mHasRobustness(false) {}
|
||||
|
||||
typedef HGLRC (GLAPIENTRY * PFNWGLCREATECONTEXTPROC) (HDC);
|
||||
PFNWGLCREATECONTEXTPROC fCreateContext;
|
||||
|
@ -76,11 +77,20 @@ public:
|
|||
typedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBIVPROC) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, int* piAttributes, int *piValues);
|
||||
PFNWGLGETPIXELFORMATATTRIBIVPROC fGetPixelFormatAttribiv;
|
||||
|
||||
typedef const char * (WINAPI * PFNWGLGETEXTENSIONSSTRINGPROC) (HDC hdc);
|
||||
PFNWGLGETEXTENSIONSSTRINGPROC fGetExtensionsString;
|
||||
|
||||
typedef HGLRC (WINAPI * PFNWGLCREATECONTEXTATTRIBSPROC) (HDC hdc, HGLRC hShareContext, const int *attribList);
|
||||
PFNWGLCREATECONTEXTATTRIBSPROC fCreateContextAttribs;
|
||||
|
||||
bool EnsureInitialized();
|
||||
|
||||
bool HasRobustness() const { return mHasRobustness; }
|
||||
|
||||
private:
|
||||
bool mInitialized;
|
||||
PRLibrary *mOGLLibrary;
|
||||
bool mHasRobustness;
|
||||
};
|
||||
|
||||
// a global WGLLibrary instance
|
||||
|
|
|
@ -1,3 +1,38 @@
|
|||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is mozilla.org code.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Mozilla Foundation.
|
||||
# Portions created by the Initial Developer are Copyright (C) 2011
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
DEPTH = ../..
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
|
|
|
@ -162,6 +162,10 @@ NS_IMETHODIMP nsScriptableRegion::GetRects(JSContext* aCx, JS::Value* aRects)
|
|||
}
|
||||
|
||||
JSObject* destArray = JS_NewArrayObject(aCx, numRects * 4, NULL);
|
||||
if (!destArray) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
*aRects = OBJECT_TO_JSVAL(destArray);
|
||||
|
||||
uint32 n = 0;
|
||||
|
|
|
@ -1,3 +1,37 @@
|
|||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is mozilla.org code.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Mozilla Foundation.
|
||||
# Portions created by the Initial Developer are Copyright (C) 2011
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
DEPTH = ../..
|
||||
topsrcdir = @top_srcdir@
|
||||
|
|
|
@ -66,7 +66,7 @@ GetCurrentBatteryInformation(hal::BatteryInformation* aBatteryInfo)
|
|||
{
|
||||
aBatteryInfo->level() = dom::battery::kDefaultLevel;
|
||||
aBatteryInfo->charging() = dom::battery::kDefaultCharging;
|
||||
aBatteryInfo->remainingTime() = dom::battery::kUnknownRemainingTime;
|
||||
aBatteryInfo->remainingTime() = dom::battery::kDefaultRemainingTime;
|
||||
}
|
||||
|
||||
} // hal_impl
|
||||
|
|
|
@ -66,7 +66,7 @@ GetCurrentBatteryInformation(hal::BatteryInformation* aBatteryInfo)
|
|||
{
|
||||
aBatteryInfo->level() = dom::battery::kDefaultLevel;
|
||||
aBatteryInfo->charging() = dom::battery::kDefaultCharging;
|
||||
aBatteryInfo->remainingTime() = dom::battery::kUnknownRemainingTime;
|
||||
aBatteryInfo->remainingTime() = dom::battery::kDefaultRemainingTime;
|
||||
}
|
||||
#endif // !MOZ_ENABLE_DBUS
|
||||
|
||||
|
|
|
@ -747,7 +747,7 @@ jsd_GetValueParent(JSDContext* jsdc, JSDValue* jsdval)
|
|||
|
||||
return NULL;
|
||||
}
|
||||
parent = JS_GetParent(jsdc->dumbContext,obj);
|
||||
parent = JS_GetParentOrScopeChain(jsdc->dumbContext,obj);
|
||||
JS_LeaveCrossCompartmentCall(call);
|
||||
JS_EndRequest(jsdc->dumbContext);
|
||||
if(!parent)
|
||||
|
|
|
@ -357,6 +357,7 @@ class HashTable : private AllocPolicy
|
|||
public:
|
||||
HashTable(AllocPolicy ap)
|
||||
: AllocPolicy(ap),
|
||||
hashShift(sHashBits),
|
||||
entryCount(0),
|
||||
gen(0),
|
||||
removedCount(0),
|
||||
|
|
|
@ -564,6 +564,11 @@ public:
|
|||
return AssemblerType::getDifferenceBetweenLabels(from.m_label, to.m_label);
|
||||
}
|
||||
|
||||
ptrdiff_t differenceBetween(DataLabelPtr from, Label to)
|
||||
{
|
||||
return AssemblerType::getDifferenceBetweenLabels(from.m_label, to.m_label);
|
||||
}
|
||||
|
||||
ptrdiff_t differenceBetween(DataLabelPtr from, Jump to)
|
||||
{
|
||||
return AssemblerType::getDifferenceBetweenLabels(from.m_label, to.m_jmp);
|
||||
|
|
|
@ -334,7 +334,7 @@ public:
|
|||
return branch32(cond, left, Imm32(right));
|
||||
}
|
||||
|
||||
Jump branchPtr(Condition cond, AbsoluteAddress left, ImmPtr right)
|
||||
Jump branchPtr(Condition cond, AbsoluteAddress left, ImmPtr right, RegisterID scratch)
|
||||
{
|
||||
return branch32(cond, left, Imm32(right));
|
||||
}
|
||||
|
|
|
@ -431,6 +431,12 @@ public:
|
|||
return branchPtr(cond, Address(scratchRegister), right);
|
||||
}
|
||||
|
||||
Jump branchPtr(Condition cond, AbsoluteAddress left, ImmPtr right, RegisterID scratch)
|
||||
{
|
||||
move(ImmPtr(left.m_ptr), scratch);
|
||||
return branchPtr(cond, Address(scratch), right);
|
||||
}
|
||||
|
||||
Jump branchPtr(Condition cond, Address left, RegisterID right)
|
||||
{
|
||||
m_assembler.cmpq_rm(right, left.offset, left.base);
|
||||
|
|
|
@ -110,9 +110,9 @@ public:
|
|||
MacroAssembler::repatchInt32(dataLabel32, value);
|
||||
}
|
||||
|
||||
void repatch(CodeLocationDataLabelPtr dataLabelPtr, void* value)
|
||||
void repatch(CodeLocationDataLabelPtr dataLabelPtr, const void* value)
|
||||
{
|
||||
MacroAssembler::repatchPointer(dataLabelPtr, value);
|
||||
MacroAssembler::repatchPointer(dataLabelPtr, (void*) value);
|
||||
}
|
||||
|
||||
void repatchLoadPtrToLEA(CodeLocationInstruction instruction)
|
||||
|
|
|
@ -641,7 +641,7 @@ InitTypeConstructor(JSContext* cx,
|
|||
JSObject*& typeProto,
|
||||
JSObject*& dataProto)
|
||||
{
|
||||
JSFunction* fun = JS_DefineFunction(cx, parent, spec.name, spec.call,
|
||||
JSFunction* fun = js::DefineFunctionWithReserved(cx, parent, spec.name, spec.call,
|
||||
spec.nargs, spec.flags);
|
||||
if (!fun)
|
||||
return false;
|
||||
|
@ -672,8 +672,7 @@ InitTypeConstructor(JSContext* cx,
|
|||
|
||||
// Stash ctypes.{Pointer,Array,Struct}Type.prototype on a reserved slot of
|
||||
// the type constructor, for faster lookup.
|
||||
if (!JS_SetReservedSlot(cx, obj, SLOT_FN_CTORPROTO, OBJECT_TO_JSVAL(typeProto)))
|
||||
return false;
|
||||
js::SetFunctionNativeReserved(obj, SLOT_FN_CTORPROTO, OBJECT_TO_JSVAL(typeProto));
|
||||
|
||||
// Create an object to serve as the common ancestor for all CData objects
|
||||
// created from the given type constructor. This has ctypes.CData.prototype
|
||||
|
@ -725,14 +724,18 @@ InitInt64Class(JSContext* cx,
|
|||
if (!JS_FreezeObject(cx, ctor))
|
||||
return NULL;
|
||||
|
||||
// Stash ctypes.{Int64,UInt64}.prototype on a reserved slot of the 'join'
|
||||
// function.
|
||||
jsval join;
|
||||
ASSERT_OK(JS_GetProperty(cx, ctor, "join", &join));
|
||||
if (!JS_SetReservedSlot(cx, JSVAL_TO_OBJECT(join), SLOT_FN_INT64PROTO,
|
||||
OBJECT_TO_JSVAL(prototype)))
|
||||
// Redefine the 'join' function as an extended native and stash
|
||||
// ctypes.{Int64,UInt64}.prototype in a reserved slot of the new function.
|
||||
JS_ASSERT(clasp == &sInt64ProtoClass || clasp == &sUInt64ProtoClass);
|
||||
JSNative native = (clasp == &sInt64ProtoClass) ? Int64::Join : UInt64::Join;
|
||||
JSFunction* fun = js::DefineFunctionWithReserved(cx, ctor, "join", native,
|
||||
2, CTYPESFN_FLAGS);
|
||||
if (!fun)
|
||||
return NULL;
|
||||
|
||||
js::SetFunctionNativeReserved(fun, SLOT_FN_INT64PROTO,
|
||||
OBJECT_TO_JSVAL(prototype));
|
||||
|
||||
if (!JS_FreezeObject(cx, prototype))
|
||||
return NULL;
|
||||
|
||||
|
@ -3045,8 +3048,7 @@ CType::GetProtoFromCtor(JSContext* cx, JSObject* obj, CTypeProtoSlot slot)
|
|||
{
|
||||
// Get ctypes.{Pointer,Array,Struct}Type.prototype from a reserved slot
|
||||
// on the type constructor.
|
||||
jsval protoslot;
|
||||
ASSERT_OK(JS_GetReservedSlot(cx, obj, SLOT_FN_CTORPROTO, &protoslot));
|
||||
jsval protoslot = js::GetFunctionNativeReserved(obj, SLOT_FN_CTORPROTO);
|
||||
JSObject* proto = JSVAL_TO_OBJECT(protoslot);
|
||||
JS_ASSERT(proto);
|
||||
JS_ASSERT(CType::IsCTypeProto(cx, proto));
|
||||
|
@ -6291,8 +6293,7 @@ Int64::Join(JSContext* cx, uintN argc, jsval* vp)
|
|||
// Get Int64.prototype from the function's reserved slot.
|
||||
JSObject* callee = JSVAL_TO_OBJECT(JS_CALLEE(cx, vp));
|
||||
|
||||
jsval slot;
|
||||
ASSERT_OK(JS_GetReservedSlot(cx, callee, SLOT_FN_INT64PROTO, &slot));
|
||||
jsval slot = js::GetFunctionNativeReserved(callee, SLOT_FN_INT64PROTO);
|
||||
JSObject* proto = JSVAL_TO_OBJECT(slot);
|
||||
JS_ASSERT(JS_GET_CLASS(cx, proto) == &sInt64ProtoClass);
|
||||
|
||||
|
@ -6459,8 +6460,7 @@ UInt64::Join(JSContext* cx, uintN argc, jsval* vp)
|
|||
// Get UInt64.prototype from the function's reserved slot.
|
||||
JSObject* callee = JSVAL_TO_OBJECT(JS_CALLEE(cx, vp));
|
||||
|
||||
jsval slot;
|
||||
ASSERT_OK(JS_GetReservedSlot(cx, callee, SLOT_FN_INT64PROTO, &slot));
|
||||
jsval slot = js::GetFunctionNativeReserved(callee, SLOT_FN_INT64PROTO);
|
||||
JSObject* proto = JSVAL_TO_OBJECT(slot);
|
||||
JS_ASSERT(JS_GET_CLASS(cx, proto) == &sUInt64ProtoClass);
|
||||
|
||||
|
|
|
@ -93,7 +93,7 @@ DefineGlobals(JSContext *cx, GlobalScope &globalScope, JSScript *script)
|
|||
JSPROP_ENUMERATE | JSPROP_PERMANENT, 0, 0, DNP_SKIP_TYPE);
|
||||
if (!shape)
|
||||
return false;
|
||||
def.knownSlot = shape->slot;
|
||||
def.knownSlot = shape->slot();
|
||||
}
|
||||
|
||||
Vector<JSScript *, 16> worklist(cx);
|
||||
|
@ -123,10 +123,10 @@ DefineGlobals(JSContext *cx, GlobalScope &globalScope, JSScript *script)
|
|||
JSObject *obj = arr->vector[i];
|
||||
if (!obj->isFunction())
|
||||
continue;
|
||||
JSFunction *fun = obj->getFunctionPrivate();
|
||||
JSFunction *fun = obj->toFunction();
|
||||
JS_ASSERT(fun->isInterpreted());
|
||||
JSScript *inner = fun->script();
|
||||
if (outer->isHeavyweightFunction) {
|
||||
if (outer->function() && outer->function()->isHeavyweight()) {
|
||||
outer->isOuterFunction = true;
|
||||
inner->isInnerFunction = true;
|
||||
}
|
||||
|
|
|
@ -1383,7 +1383,7 @@ frontend::PushBlockScope(TreeContext *tc, StmtInfo *stmt, ObjectBox *blockBox, p
|
|||
PushStatement(tc, stmt, STMT_BLOCK, top);
|
||||
stmt->flags |= SIF_SCOPE;
|
||||
blockBox->parent = tc->blockChainBox;
|
||||
blockBox->object->setParent(tc->blockChain());
|
||||
blockBox->object->setStaticBlockScopeChain(tc->blockChain());
|
||||
stmt->downScope = tc->topScopeStmt;
|
||||
tc->topScopeStmt = stmt;
|
||||
tc->blockChainBox = blockBox;
|
||||
|
@ -1721,7 +1721,7 @@ frontend::LexicalLookup(TreeContext *tc, JSAtom *atom, jsint *slotp, StmtInfo *s
|
|||
|
||||
if (slotp) {
|
||||
JS_ASSERT(obj->getSlot(JSSLOT_BLOCK_DEPTH).isInt32());
|
||||
*slotp = obj->getSlot(JSSLOT_BLOCK_DEPTH).toInt32() + shape->shortid;
|
||||
*slotp = obj->getSlot(JSSLOT_BLOCK_DEPTH).toInt32() + shape->shortid();
|
||||
}
|
||||
return stmt;
|
||||
}
|
||||
|
@ -1781,8 +1781,8 @@ LookupCompileTimeConstant(JSContext *cx, BytecodeEmitter *bce, JSAtom *atom, Val
|
|||
* from our variable object here.
|
||||
*/
|
||||
if (!shape->writable() && !shape->configurable() &&
|
||||
shape->hasDefaultGetter() && obj->containsSlot(shape->slot)) {
|
||||
*constp = obj->getSlot(shape->slot);
|
||||
shape->hasDefaultGetter() && obj->containsSlot(shape->slot())) {
|
||||
*constp = obj->getSlot(shape->slot());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2020,8 +2020,13 @@ EmitEnterBlock(JSContext *cx, ParseNode *pn, BytecodeEmitter *bce)
|
|||
* js::Bindings::extensibleParents.
|
||||
*/
|
||||
if ((bce->flags & TCF_FUN_EXTENSIBLE_SCOPE) ||
|
||||
bce->bindings.extensibleParents())
|
||||
blockObj->setBlockOwnShape(cx);
|
||||
bce->bindings.extensibleParents()) {
|
||||
HeapPtrShape shape;
|
||||
shape.init(blockObj->lastProperty());
|
||||
if (!Shape::setExtensibleParents(cx, &shape))
|
||||
return false;
|
||||
blockObj->setLastPropertyInfallible(shape);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -2332,7 +2337,6 @@ BindNameToSlot(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
|
|||
JS_ASSERT(bce->inFunction());
|
||||
JS_ASSERT_IF(cookie.slot() != UpvarCookie::CALLEE_SLOT, bce->roLexdeps->lookup(atom));
|
||||
JS_ASSERT(JOF_OPTYPE(op) == JOF_ATOM);
|
||||
JS_ASSERT(bce->fun()->u.i.skipmin <= skip);
|
||||
|
||||
/*
|
||||
* If op is a mutating opcode, this upvar's lookup skips too many levels,
|
||||
|
@ -3844,13 +3848,6 @@ frontend::EmitFunctionScript(JSContext *cx, BytecodeEmitter *bce, ParseNode *bod
|
|||
bce->switchToMain();
|
||||
}
|
||||
|
||||
if (bce->flags & TCF_FUN_UNBRAND_THIS) {
|
||||
bce->switchToProlog();
|
||||
if (Emit1(cx, bce, JSOP_UNBRANDTHIS) < 0)
|
||||
return false;
|
||||
bce->switchToMain();
|
||||
}
|
||||
|
||||
return EmitTree(cx, bce, body) &&
|
||||
Emit1(cx, bce, JSOP_STOP) >= 0 &&
|
||||
JSScript::NewScriptFromEmitter(cx, bce);
|
||||
|
@ -4756,7 +4753,7 @@ ParseNode::getConstantValue(JSContext *cx, bool strictChecks, Value *vp)
|
|||
case PNK_RC: {
|
||||
JS_ASSERT(isOp(JSOP_NEWINIT) && !(pn_xflags & PNX_NONCONST));
|
||||
|
||||
gc::AllocKind kind = GuessObjectGCKind(pn_count, false);
|
||||
gc::AllocKind kind = GuessObjectGCKind(pn_count);
|
||||
JSObject *obj = NewBuiltinClassInstance(cx, &ObjectClass, kind);
|
||||
if (!obj)
|
||||
return false;
|
||||
|
@ -5447,6 +5444,40 @@ EmitWith(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
|
|||
return PopStatementBCE(cx, bce);
|
||||
}
|
||||
|
||||
static bool
|
||||
SetMethodFunction(JSContext *cx, FunctionBox *funbox, JSAtom *atom)
|
||||
{
|
||||
/*
|
||||
* Replace a boxed function with a new one with a method atom. Methods
|
||||
* require a function with the extended size finalize kind, which normal
|
||||
* functions don't have. We don't eagerly allocate functions with the
|
||||
* expanded size for boxed functions, as most functions are not methods.
|
||||
*/
|
||||
JSFunction *fun = js_NewFunction(cx, NULL, NULL,
|
||||
funbox->function()->nargs,
|
||||
funbox->function()->flags,
|
||||
funbox->function()->getParent(),
|
||||
funbox->function()->atom,
|
||||
JSFunction::ExtendedFinalizeKind);
|
||||
if (!fun)
|
||||
return false;
|
||||
|
||||
JSScript *script = funbox->function()->script();
|
||||
if (script) {
|
||||
fun->setScript(script);
|
||||
if (!script->typeSetFunction(cx, fun))
|
||||
return false;
|
||||
}
|
||||
|
||||
JS_ASSERT(funbox->function()->joinable());
|
||||
fun->setJoinable();
|
||||
|
||||
fun->setMethodAtom(atom);
|
||||
|
||||
funbox->object = fun;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
EmitForIn(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn, ptrdiff_t top)
|
||||
{
|
||||
|
@ -6329,6 +6360,8 @@ frontend::EmitTree(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
|
|||
pn2->pn_left->isOp(JSOP_SETPROP) &&
|
||||
pn2->pn_right->isOp(JSOP_LAMBDA) &&
|
||||
pn2->pn_right->pn_funbox->joinable()) {
|
||||
if (!SetMethodFunction(cx, pn2->pn_right->pn_funbox, pn2->pn_left->pn_atom))
|
||||
return JS_FALSE;
|
||||
pn2->pn_left->setOp(JSOP_SETMETHOD);
|
||||
}
|
||||
if (!EmitTree(cx, bce, pn2))
|
||||
|
@ -7096,7 +7129,7 @@ frontend::EmitTree(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
|
|||
*/
|
||||
JSObject *obj = NULL;
|
||||
if (!bce->hasSharps() && bce->compileAndGo()) {
|
||||
gc::AllocKind kind = GuessObjectGCKind(pn->pn_count, false);
|
||||
gc::AllocKind kind = GuessObjectGCKind(pn->pn_count);
|
||||
obj = NewBuiltinClassInstance(cx, &ObjectClass, kind);
|
||||
if (!obj)
|
||||
return JS_FALSE;
|
||||
|
@ -7144,6 +7177,8 @@ frontend::EmitTree(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
|
|||
obj = NULL;
|
||||
op = JSOP_INITMETHOD;
|
||||
pn2->setOp(op);
|
||||
if (!SetMethodFunction(cx, init->pn_funbox, pn3->pn_atom))
|
||||
return JS_FALSE;
|
||||
} else {
|
||||
/*
|
||||
* Disable NEWOBJECT on initializers that set __proto__, which has
|
||||
|
@ -7171,11 +7206,6 @@ frontend::EmitTree(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
|
|||
}
|
||||
}
|
||||
|
||||
if (bce->funbox && bce->funbox->shouldUnbrand(methodInits, slowMethodInits)) {
|
||||
obj = NULL;
|
||||
if (Emit1(cx, bce, JSOP_UNBRAND) < 0)
|
||||
return JS_FALSE;
|
||||
}
|
||||
if (!EmitEndInit(cx, bce, pn->pn_count))
|
||||
return JS_FALSE;
|
||||
|
||||
|
|
|
@ -203,15 +203,6 @@ struct StmtInfo {
|
|||
|
||||
/* bits 0x40000 and 0x80000 are unused */
|
||||
|
||||
/*
|
||||
* Flag signifying that the current function seems to be a constructor that
|
||||
* sets this.foo to define "methods", at least one of which can't be a null
|
||||
* closure, so we should avoid over-specializing property cache entries and
|
||||
* trace inlining guards to method function object identity, which will vary
|
||||
* per instance.
|
||||
*/
|
||||
#define TCF_FUN_UNBRAND_THIS 0x100000
|
||||
|
||||
/*
|
||||
* "Module pattern", i.e., a lambda that is immediately applied and the whole
|
||||
* of an expression statement.
|
||||
|
|
|
@ -133,20 +133,6 @@ FunctionBox::scopeIsExtensible() const
|
|||
return tcflags & TCF_FUN_EXTENSIBLE_SCOPE;
|
||||
}
|
||||
|
||||
bool
|
||||
FunctionBox::shouldUnbrand(uintN methods, uintN slowMethods) const
|
||||
{
|
||||
if (slowMethods != 0) {
|
||||
for (const FunctionBox *funbox = this; funbox; funbox = funbox->parent) {
|
||||
if (!(funbox->tcflags & TCF_FUN_MODULE_PATTERN))
|
||||
return true;
|
||||
if (funbox->inLoop)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Add |node| to |parser|'s free node list. */
|
||||
void
|
||||
ParseNodeAllocator::freeNode(ParseNode *pn)
|
||||
|
|
|
@ -1271,18 +1271,6 @@ struct FunctionBox : public ObjectBox
|
|||
* ancestor?
|
||||
*/
|
||||
bool scopeIsExtensible() const;
|
||||
|
||||
/*
|
||||
* Unbrand an object being initialized or constructed if any method cannot
|
||||
* be joined to one compiler-created null closure shared among N different
|
||||
* closure environments.
|
||||
*
|
||||
* We despecialize from caching function objects, caching slots or shapes
|
||||
* instead, because an unbranded object may still have joined methods (for
|
||||
* which shape->isMethod), since PropertyCache::fill gives precedence to
|
||||
* joined methods over branded methods.
|
||||
*/
|
||||
bool shouldUnbrand(uintN methods, uintN slowMethods) const;
|
||||
};
|
||||
|
||||
struct FunctionBoxQueue {
|
||||
|
|
|
@ -533,7 +533,7 @@ js::CheckStrictParameters(JSContext *cx, TreeContext *tc)
|
|||
|
||||
/* Start with lastVariable(), not lastArgument(), for destructuring. */
|
||||
for (Shape::Range r = tc->bindings.lastVariable(); !r.empty(); r.popFront()) {
|
||||
jsid id = r.front().propid;
|
||||
jsid id = r.front().propid();
|
||||
if (!JSID_IS_ATOM(id))
|
||||
continue;
|
||||
|
||||
|
@ -932,8 +932,11 @@ Parser::newFunction(TreeContext *tc, JSAtom *atom, FunctionSyntaxKind kind)
|
|||
JSFUN_INTERPRETED | (kind == Expression ? JSFUN_LAMBDA : 0),
|
||||
parent, atom);
|
||||
if (fun && !tc->compileAndGo()) {
|
||||
fun->clearParent();
|
||||
fun->clearType();
|
||||
if (!fun->clearParent(context))
|
||||
return NULL;
|
||||
if (!fun->clearType(context))
|
||||
return NULL;
|
||||
fun->setEnvironment(NULL);
|
||||
}
|
||||
return fun;
|
||||
}
|
||||
|
@ -1169,7 +1172,7 @@ LeaveFunction(ParseNode *fn, TreeContext *funtc, PropertyName *funName = NULL,
|
|||
* we create it eagerly whenever parameters are (or might, in the case of
|
||||
* calls to eval) be assigned.
|
||||
*/
|
||||
if (funtc->inStrictMode() && funbox->object->getFunctionPrivate()->nargs > 0) {
|
||||
if (funtc->inStrictMode() && funbox->object->toFunction()->nargs > 0) {
|
||||
AtomDeclsIter iter(&funtc->decls);
|
||||
Definition *dn;
|
||||
|
||||
|
@ -1951,7 +1954,7 @@ BindLet(JSContext *cx, BindData *data, JSAtom *atom, TreeContext *tc)
|
|||
* BytecodeEmitter.cpp:EmitEnterBlock so they don't tie up unused space
|
||||
* in the so-called "static" prototype Block.
|
||||
*/
|
||||
blockObj->setSlot(shape->slot, PrivateValue(pn));
|
||||
blockObj->setSlot(shape->slot(), PrivateValue(pn));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1965,7 +1968,7 @@ PopStatement(TreeContext *tc)
|
|||
JS_ASSERT(!obj->isClonedBlock());
|
||||
|
||||
for (Shape::Range r = obj->lastProperty()->all(); !r.empty(); r.popFront()) {
|
||||
JSAtom *atom = JSID_TO_ATOM(r.front().propid);
|
||||
JSAtom *atom = JSID_TO_ATOM(r.front().propid());
|
||||
|
||||
/* Beware the empty destructuring dummy. */
|
||||
if (atom == tc->parser->context->runtime->atomState.emptyAtom)
|
||||
|
@ -1973,14 +1976,7 @@ PopStatement(TreeContext *tc)
|
|||
tc->decls.remove(atom);
|
||||
}
|
||||
|
||||
/*
|
||||
* js_CloneBlockObject requires obj's shape to be frozen. Compare
|
||||
* Bindings::makeImmutable.
|
||||
*
|
||||
* (This is a second pass over the shapes, if obj has a dictionary, but
|
||||
* that is rare.)
|
||||
*/
|
||||
obj->lastProp->freezeIfDictionary();
|
||||
JS_ASSERT(!obj->inDictionaryMode());
|
||||
}
|
||||
PopStatementTC(tc);
|
||||
}
|
||||
|
@ -2051,7 +2047,7 @@ DefineGlobal(ParseNode *pn, BytecodeEmitter *bce, PropertyName *name)
|
|||
return true;
|
||||
}
|
||||
|
||||
def = GlobalScope::GlobalDef(shape->slot);
|
||||
def = GlobalScope::GlobalDef(shape->slot());
|
||||
} else {
|
||||
def = GlobalScope::GlobalDef(name, funbox);
|
||||
}
|
||||
|
@ -3687,7 +3683,7 @@ Parser::letStatement()
|
|||
stmt->downScope = tc->topScopeStmt;
|
||||
tc->topScopeStmt = stmt;
|
||||
|
||||
obj->setParent(tc->blockChain());
|
||||
obj->setStaticBlockScopeChain(tc->blockChain());
|
||||
blockbox->parent = tc->blockChainBox;
|
||||
tc->blockChainBox = blockbox;
|
||||
stmt->blockBox = blockbox;
|
||||
|
@ -7156,8 +7152,10 @@ Parser::primaryExpr(TokenKind tt, JSBool afterDot)
|
|||
return NULL;
|
||||
|
||||
if (!tc->compileAndGo()) {
|
||||
reobj->clearParent();
|
||||
reobj->clearType();
|
||||
if (!reobj->clearParent(context))
|
||||
return NULL;
|
||||
if (!reobj->clearType(context))
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pn->pn_objbox = tc->parser->newObjectBox(reobj);
|
||||
|
|
|
@ -164,7 +164,6 @@ FindFunArgs(FunctionBox *funbox, int level, FunctionBoxQueue *queue)
|
|||
do {
|
||||
ParseNode *fn = funbox->node;
|
||||
JS_ASSERT(fn->isArity(PN_FUNC));
|
||||
JSFunction *fun = funbox->function();
|
||||
int fnlevel = level;
|
||||
|
||||
/*
|
||||
|
@ -245,12 +244,10 @@ FindFunArgs(FunctionBox *funbox, int level, FunctionBoxQueue *queue)
|
|||
|
||||
/*
|
||||
* Finally, after we've traversed all of the current function's kids,
|
||||
* minimize fun's skipmin against our accumulated skipmin. Do likewise
|
||||
* with allskipmin, but minimize across funbox and all of its siblings,
|
||||
* to compute our return value.
|
||||
* minimize allskipmin against our accumulated skipmin. Minimize across
|
||||
* funbox and all of its siblings, to compute our return value.
|
||||
*/
|
||||
if (skipmin != UpvarCookie::FREE_LEVEL) {
|
||||
fun->u.i.skipmin = skipmin;
|
||||
if (skipmin < allskipmin)
|
||||
allskipmin = skipmin;
|
||||
}
|
||||
|
@ -512,46 +509,6 @@ FlagHeavyweights(Definition *dn, FunctionBox *funbox, uint32 *tcflags)
|
|||
*tcflags |= TCF_FUN_HEAVYWEIGHT;
|
||||
}
|
||||
|
||||
static void
|
||||
ConsiderUnbranding(FunctionBox *funbox)
|
||||
{
|
||||
/*
|
||||
* We've already recursively set our kids' kinds, which also classifies
|
||||
* enclosing functions holding upvars referenced in those descendants'
|
||||
* bodies. So now we can check our "methods".
|
||||
*
|
||||
* Despecialize from branded method-identity-based shape to shape- or
|
||||
* slot-based shape if this function smells like a constructor and too many
|
||||
* of its methods are *not* joinable null closures (i.e., they have one or
|
||||
* more upvars fetched via the display).
|
||||
*/
|
||||
bool returnsExpr = !!(funbox->tcflags & TCF_RETURN_EXPR);
|
||||
#if JS_HAS_EXPR_CLOSURES
|
||||
{
|
||||
ParseNode *pn2 = funbox->node->pn_body;
|
||||
if (pn2->isKind(PNK_UPVARS))
|
||||
pn2 = pn2->pn_tree;
|
||||
if (pn2->isKind(PNK_ARGSBODY))
|
||||
pn2 = pn2->last();
|
||||
if (!pn2->isKind(PNK_STATEMENTLIST))
|
||||
returnsExpr = true;
|
||||
}
|
||||
#endif
|
||||
if (!returnsExpr) {
|
||||
uintN methodSets = 0, slowMethodSets = 0;
|
||||
|
||||
for (ParseNode *method = funbox->methods; method; method = method->pn_link) {
|
||||
JS_ASSERT(method->isOp(JSOP_LAMBDA) || method->isOp(JSOP_LAMBDA_FC));
|
||||
++methodSets;
|
||||
if (!method->pn_funbox->joinable())
|
||||
++slowMethodSets;
|
||||
}
|
||||
|
||||
if (funbox->shouldUnbrand(methodSets, slowMethodSets))
|
||||
funbox->tcflags |= TCF_FUN_UNBRAND_THIS;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
SetFunctionKinds(FunctionBox *funbox, uint32 *tcflags, bool isDirectEval)
|
||||
{
|
||||
|
@ -559,10 +516,8 @@ SetFunctionKinds(FunctionBox *funbox, uint32 *tcflags, bool isDirectEval)
|
|||
ParseNode *fn = funbox->node;
|
||||
ParseNode *pn = fn->pn_body;
|
||||
|
||||
if (funbox->kids) {
|
||||
if (funbox->kids)
|
||||
SetFunctionKinds(funbox->kids, tcflags, isDirectEval);
|
||||
ConsiderUnbranding(funbox);
|
||||
}
|
||||
|
||||
JSFunction *fun = funbox->function();
|
||||
|
||||
|
@ -674,8 +629,8 @@ SetFunctionKinds(FunctionBox *funbox, uint32 *tcflags, bool isDirectEval)
|
|||
* must have their OWN_SHAPE flags set; the comments for
|
||||
* js::Bindings::extensibleParents explain why.
|
||||
*/
|
||||
static void
|
||||
MarkExtensibleScopeDescendants(FunctionBox *funbox, bool hasExtensibleParent)
|
||||
static bool
|
||||
MarkExtensibleScopeDescendants(JSContext *context, FunctionBox *funbox, bool hasExtensibleParent)
|
||||
{
|
||||
for (; funbox; funbox = funbox->siblings) {
|
||||
/*
|
||||
|
@ -685,14 +640,20 @@ MarkExtensibleScopeDescendants(FunctionBox *funbox, bool hasExtensibleParent)
|
|||
*/
|
||||
|
||||
JS_ASSERT(!funbox->bindings.extensibleParents());
|
||||
if (hasExtensibleParent)
|
||||
funbox->bindings.setExtensibleParents();
|
||||
if (hasExtensibleParent) {
|
||||
if (!funbox->bindings.setExtensibleParents(context))
|
||||
return false;
|
||||
}
|
||||
|
||||
if (funbox->kids) {
|
||||
MarkExtensibleScopeDescendants(funbox->kids,
|
||||
hasExtensibleParent || funbox->scopeIsExtensible());
|
||||
if (!MarkExtensibleScopeDescendants(context, funbox->kids,
|
||||
hasExtensibleParent || funbox->scopeIsExtensible())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -703,7 +664,8 @@ frontend::AnalyzeFunctions(TreeContext *tc)
|
|||
return true;
|
||||
if (!MarkFunArgs(tc->parser->context, tc->functionList, tc->parser->functionCount))
|
||||
return false;
|
||||
MarkExtensibleScopeDescendants(tc->functionList, false);
|
||||
if (!MarkExtensibleScopeDescendants(tc->parser->context, tc->functionList, false))
|
||||
return false;
|
||||
bool isDirectEval = !!tc->parser->callerFrame;
|
||||
SetFunctionKinds(tc->functionList, &tc->flags, isDirectEval);
|
||||
return true;
|
||||
|
|
|
@ -271,7 +271,8 @@ typedef HeapPtr<JSFunction> HeapPtrFunction;
|
|||
typedef HeapPtr<JSString> HeapPtrString;
|
||||
typedef HeapPtr<JSScript> HeapPtrScript;
|
||||
typedef HeapPtr<Shape> HeapPtrShape;
|
||||
typedef HeapPtr<const Shape> HeapPtrConstShape;
|
||||
typedef HeapPtr<BaseShape> HeapPtrBaseShape;
|
||||
typedef HeapPtr<types::TypeObject> HeapPtrTypeObject;
|
||||
typedef HeapPtr<JSXML> HeapPtrXML;
|
||||
|
||||
/* Useful for hashtables with a HeapPtr as key. */
|
||||
|
|
|
@ -192,7 +192,6 @@ Statistics::beginGC(JSCompartment *comp, Reason reason)
|
|||
Probes::GCStart(compartment);
|
||||
|
||||
GCCrashData crashData;
|
||||
crashData.isRegen = runtime->shapeGen & SHAPE_OVERFLOW_BIT;
|
||||
crashData.isCompartment = !!compartment;
|
||||
crash::SaveCrashData(crash::JS_CRASH_TAG_GC, &crashData, sizeof(crashData));
|
||||
}
|
||||
|
@ -277,8 +276,7 @@ Statistics::endGC()
|
|||
if (JSAccumulateTelemetryDataCallback cb = runtime->telemetryCallback) {
|
||||
(*cb)(JS_TELEMETRY_GC_REASON, triggerReason);
|
||||
(*cb)(JS_TELEMETRY_GC_IS_COMPARTMENTAL, compartment ? 1 : 0);
|
||||
(*cb)(JS_TELEMETRY_GC_IS_SHAPE_REGEN,
|
||||
runtime->shapeGen & SHAPE_OVERFLOW_BIT ? 1 : 0);
|
||||
(*cb)(JS_TELEMETRY_GC_IS_SHAPE_REGEN, 0);
|
||||
(*cb)(JS_TELEMETRY_GC_MS, t(PHASE_GC));
|
||||
(*cb)(JS_TELEMETRY_GC_MARK_MS, t(PHASE_MARK));
|
||||
(*cb)(JS_TELEMETRY_GC_SWEEP_MS, t(PHASE_SWEEP));
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
|
||||
var o4 = Object.freeze({
|
||||
set: function(summary) {}
|
||||
});
|
|
@ -0,0 +1,7 @@
|
|||
a = "".__proto__
|
||||
b = uneval().__proto__
|
||||
for (var i = 0; i < 2; i++) {
|
||||
a.__defineSetter__("valueOf", function() {})
|
||||
a + ""
|
||||
delete b.valueOf
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
for (let j = 0; j < (20); ++(__lookupSetter__)) {
|
||||
function g() { j; }
|
||||
j++;
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
Function.prototype.__proto__["p"] = 3
|
||||
c = [].__proto__
|
||||
c[5] = 3
|
||||
Namespace.prototype.__proto__[4] = function() {}
|
||||
gc()
|
||||
Function("\
|
||||
{\
|
||||
function f(d) {}\
|
||||
for each(let z in[0]) {\
|
||||
f(z)\
|
||||
}\
|
||||
}\
|
||||
")()
|
|
@ -0,0 +1 @@
|
|||
for (let x in [<y/>.(let(x) function() {})]) {}
|
|
@ -0,0 +1,3 @@
|
|||
Object.defineProperty(Namespace.prototype, "toString", {
|
||||
enumerable: true
|
||||
})
|
|
@ -0,0 +1,12 @@
|
|||
function f(s) {
|
||||
eval(s);
|
||||
return function() {
|
||||
with({}) {};
|
||||
return b;
|
||||
};
|
||||
}
|
||||
var b = 1;
|
||||
var g1 = f("");
|
||||
var g2 = f("var b = 2;");
|
||||
g1('');
|
||||
assertEq(g2(''), 2);
|
|
@ -0,0 +1,11 @@
|
|||
c = (0).__proto__
|
||||
function f(o) {
|
||||
o.__proto__ = null
|
||||
for (x in o) {}
|
||||
}
|
||||
for (i = 0; i < 9; i++) {
|
||||
f(c)
|
||||
Function.prototype.__proto__.__proto__ = c
|
||||
for (x in Function.prototype.__proto__) {}
|
||||
f(Math.__proto__)
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
// |jit-test| error: TypeError
|
||||
function f(o) {
|
||||
for (j = 0; j < 9; j++) {
|
||||
if (j) {
|
||||
o.__proto__ = null
|
||||
}
|
||||
for (v in o) {}
|
||||
}
|
||||
}
|
||||
for (i = 0; i < 9; i++) {
|
||||
(new Boolean).__proto__.__defineGetter__("toString", function() {})
|
||||
f(Boolean.prototype)
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
// Check that an onExceptionUnwind hook can force a frame to return a value early.
|
||||
|
||||
var g = newGlobal('new-compartment');
|
||||
var dbg = Debugger(g);
|
||||
dbg.onExceptionUnwind = function (frame, exc) {
|
||||
return { return:"sproon" };
|
||||
};
|
||||
g.eval("function f() { throw 'ksnife'; }");
|
||||
assertEq(g.f(), "sproon");
|
|
@ -0,0 +1,10 @@
|
|||
// Check that if an onExceptionUnwind hook forces a constructor frame to
|
||||
// return a primitive value, it still gets wrapped up in an object.
|
||||
|
||||
var g = newGlobal('new-compartment');
|
||||
var dbg = Debugger(g);
|
||||
dbg.onExceptionUnwind = function (frame, exc) {
|
||||
return { return:"sproon" };
|
||||
};
|
||||
g.eval("function f() { throw 'ksnife'; }");
|
||||
assertEq(typeof new g.f, "object");
|
|
@ -0,0 +1,11 @@
|
|||
// Check that an onExceptionUnwind hook can force a frame to throw a different exception.
|
||||
|
||||
load(libdir + "asserts.js");
|
||||
|
||||
var g = newGlobal('new-compartment');
|
||||
var dbg = Debugger(g);
|
||||
dbg.onExceptionUnwind = function (frame, exc) {
|
||||
return { throw:"sproon" };
|
||||
};
|
||||
g.eval("function f() { throw 'ksnife'; }");
|
||||
assertThrowsValue(g.f, "sproon");
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче