mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-12-02 10:00:54 +00:00
Fixing bug 256932. Exposing elements by their ID/NAME in the global scope in quirks mode documents for more IE/Opera/Konqueror compatibility. r+sr=brendan@mozilla.org
This commit is contained in:
parent
fc12f7e08c
commit
00bcb393b4
@ -96,6 +96,7 @@
|
|||||||
#include "nsIDOMNSLocation.h"
|
#include "nsIDOMNSLocation.h"
|
||||||
#include "nsIDOMLocation.h"
|
#include "nsIDOMLocation.h"
|
||||||
#include "nsIDOMWindowInternal.h"
|
#include "nsIDOMWindowInternal.h"
|
||||||
|
#include "nsPIDOMWindow.h"
|
||||||
#include "nsIDOMJSWindow.h"
|
#include "nsIDOMJSWindow.h"
|
||||||
#include "nsIDOMWindowCollection.h"
|
#include "nsIDOMWindowCollection.h"
|
||||||
#include "nsIDOMHistory.h"
|
#include "nsIDOMHistory.h"
|
||||||
@ -925,7 +926,7 @@ nsIXPConnect *nsDOMClassInfo::sXPConnect = nsnull;
|
|||||||
nsIScriptSecurityManager *nsDOMClassInfo::sSecMan = nsnull;
|
nsIScriptSecurityManager *nsDOMClassInfo::sSecMan = nsnull;
|
||||||
PRBool nsDOMClassInfo::sIsInitialized = PR_FALSE;
|
PRBool nsDOMClassInfo::sIsInitialized = PR_FALSE;
|
||||||
PRBool nsDOMClassInfo::sDisableDocumentAllSupport = PR_FALSE;
|
PRBool nsDOMClassInfo::sDisableDocumentAllSupport = PR_FALSE;
|
||||||
|
PRBool nsDOMClassInfo::sDisableGlobalScopePollutionSupport = PR_FALSE;
|
||||||
|
|
||||||
|
|
||||||
jsval nsDOMClassInfo::sTop_id = JSVAL_VOID;
|
jsval nsDOMClassInfo::sTop_id = JSVAL_VOID;
|
||||||
@ -996,11 +997,76 @@ jsval nsDOMClassInfo::sAdd_id = JSVAL_VOID;
|
|||||||
jsval nsDOMClassInfo::sAll_id = JSVAL_VOID;
|
jsval nsDOMClassInfo::sAll_id = JSVAL_VOID;
|
||||||
jsval nsDOMClassInfo::sTags_id = JSVAL_VOID;
|
jsval nsDOMClassInfo::sTags_id = JSVAL_VOID;
|
||||||
|
|
||||||
const JSClass *nsDOMClassInfo::sObjectClass = nsnull;
|
const JSClass *nsDOMClassInfo::sObjectClass = nsnull;
|
||||||
|
|
||||||
PRBool nsDOMClassInfo::sDoSecurityCheckInAddProperty = PR_TRUE;
|
PRBool nsDOMClassInfo::sDoSecurityCheckInAddProperty = PR_TRUE;
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
PrintWarningOnConsole(JSContext *cx, const char *stringBundleProperty)
|
||||||
|
{
|
||||||
|
nsCOMPtr<nsIStringBundleService>
|
||||||
|
stringService(do_GetService(NS_STRINGBUNDLE_CONTRACTID));
|
||||||
|
if (!stringService) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsCOMPtr<nsIStringBundle> bundle;
|
||||||
|
stringService->CreateBundle(kDOMStringBundleURL, getter_AddRefs(bundle));
|
||||||
|
if (!bundle) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsXPIDLString msg;
|
||||||
|
bundle->GetStringFromName(NS_ConvertASCIItoUTF16(stringBundleProperty).get(),
|
||||||
|
getter_Copies(msg));
|
||||||
|
|
||||||
|
if (msg.IsEmpty()) {
|
||||||
|
NS_ERROR("Failed to get strings from dom.properties!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsCOMPtr<nsIConsoleService> consoleService
|
||||||
|
(do_GetService("@mozilla.org/consoleservice;1"));
|
||||||
|
if (!consoleService) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsCOMPtr<nsIScriptError> scriptError =
|
||||||
|
do_CreateInstance(NS_SCRIPTERROR_CONTRACTID);
|
||||||
|
if (!scriptError) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
JSStackFrame *fp, *iterator = nsnull;
|
||||||
|
fp = ::JS_FrameIterator(cx, &iterator);
|
||||||
|
PRUint32 lineno = 0;
|
||||||
|
nsAutoString sourcefile;
|
||||||
|
if (fp) {
|
||||||
|
JSScript* script = ::JS_GetFrameScript(cx, fp);
|
||||||
|
if (script) {
|
||||||
|
const char* filename = ::JS_GetScriptFilename(cx, script);
|
||||||
|
if (filename) {
|
||||||
|
CopyUTF8toUTF16(nsDependentCString(filename), sourcefile);
|
||||||
|
}
|
||||||
|
jsbytecode* pc = ::JS_GetFramePC(cx, fp);
|
||||||
|
if (pc) {
|
||||||
|
lineno = ::JS_PCToLineNumber(cx, script, pc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
nsresult rv = scriptError->Init(msg.get(),
|
||||||
|
sourcefile.get(),
|
||||||
|
EmptyString().get(),
|
||||||
|
lineno,
|
||||||
|
0, // column for error is not available
|
||||||
|
nsIScriptError::warningFlag,
|
||||||
|
"DOM:HTML");
|
||||||
|
if (NS_SUCCEEDED(rv)){
|
||||||
|
consoleService->LogMessage(scriptError);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static inline JSObject *
|
static inline JSObject *
|
||||||
GetGlobalJSObject(JSContext *cx, JSObject *obj)
|
GetGlobalJSObject(JSContext *cx, JSObject *obj)
|
||||||
{
|
{
|
||||||
@ -2515,6 +2581,9 @@ nsDOMClassInfo::Init()
|
|||||||
sDisableDocumentAllSupport =
|
sDisableDocumentAllSupport =
|
||||||
nsContentUtils::GetBoolPref("browser.dom.document.all.disabled");
|
nsContentUtils::GetBoolPref("browser.dom.document.all.disabled");
|
||||||
|
|
||||||
|
sDisableGlobalScopePollutionSupport =
|
||||||
|
nsContentUtils::GetBoolPref("browser.dom.global_scope_pollution.disabled");
|
||||||
|
|
||||||
sIsInitialized = PR_TRUE;
|
sIsInitialized = PR_TRUE;
|
||||||
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
@ -2697,10 +2766,6 @@ nsDOMClassInfo::PostCreate(nsIXPConnectWrappedNative *wrapper,
|
|||||||
|
|
||||||
JSClass *proto_proto_class = JS_GET_CLASS(cx, proto_proto);
|
JSClass *proto_proto_class = JS_GET_CLASS(cx, proto_proto);
|
||||||
|
|
||||||
if (!sObjectClass) {
|
|
||||||
sObjectClass = proto_proto_class;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (proto_proto_class != sObjectClass) {
|
if (proto_proto_class != sObjectClass) {
|
||||||
// We've just wrapped an object of a type that has been wrapped on
|
// We've just wrapped an object of a type that has been wrapped on
|
||||||
// this scope already so the prototype of the xpcwrapped native's
|
// this scope already so the prototype of the xpcwrapped native's
|
||||||
@ -3227,9 +3292,23 @@ nsDOMClassInfo::doCheckPropertyAccess(JSContext *cx, JSObject *obj, jsval id,
|
|||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsWindowSH::PreCreate(nsISupports *nativeObj, JSContext * cx,
|
nsWindowSH::PreCreate(nsISupports *nativeObj, JSContext *cx,
|
||||||
JSObject * globalObj, JSObject * *parentObj)
|
JSObject *globalObj, JSObject **parentObj)
|
||||||
{
|
{
|
||||||
|
// Since this is one of the first calls we'll get from XPConnect,
|
||||||
|
// grab the pointer to the Object class so we'll have it later on.
|
||||||
|
|
||||||
|
if (!sObjectClass) {
|
||||||
|
JSObject *obj, *proto = globalObj;
|
||||||
|
|
||||||
|
do {
|
||||||
|
obj = proto;
|
||||||
|
proto = ::JS_GetPrototype(cx, obj);
|
||||||
|
} while (proto);
|
||||||
|
|
||||||
|
sObjectClass = JS_GET_CLASS(cx, obj);
|
||||||
|
}
|
||||||
|
|
||||||
// Normally ::PreCreate() is used to give XPConnect the parent
|
// Normally ::PreCreate() is used to give XPConnect the parent
|
||||||
// object for the object that's being wrapped, this parent object is
|
// object for the object that's being wrapped, this parent object is
|
||||||
// set as the parent of the wrapper and it's also used to find the
|
// set as the parent of the wrapper and it's also used to find the
|
||||||
@ -3262,6 +3341,186 @@ nsWindowSH::PreCreate(nsISupports *nativeObj, JSContext * cx,
|
|||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// This JS class piggybacks on nsHTMLDocumentSH::ReleaseDocument()...
|
||||||
|
|
||||||
|
static JSClass sGlobalScopePolluterClass = {
|
||||||
|
"Global Scope Polluter",
|
||||||
|
JSCLASS_HAS_PRIVATE | JSCLASS_PRIVATE_IS_NSISUPPORTS | JSCLASS_NEW_RESOLVE,
|
||||||
|
nsWindowSH::SecurityCheckOnSetProp, nsWindowSH::SecurityCheckOnSetProp,
|
||||||
|
nsWindowSH::GlobalScopePolluterGetProperty,
|
||||||
|
nsWindowSH::SecurityCheckOnSetProp, JS_EnumerateStub,
|
||||||
|
(JSResolveOp)nsWindowSH::GlobalScopePolluterNewResolve, JS_ConvertStub,
|
||||||
|
nsHTMLDocumentSH::ReleaseDocument
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// static
|
||||||
|
JSBool JS_DLL_CALLBACK
|
||||||
|
nsWindowSH::GlobalScopePolluterGetProperty(JSContext *cx, JSObject *obj,
|
||||||
|
jsval id, jsval *vp)
|
||||||
|
{
|
||||||
|
// Someone is accessing a element by referencing its name/id in the
|
||||||
|
// global scope, do a security check to make sure that's ok.
|
||||||
|
|
||||||
|
nsresult rv =
|
||||||
|
sSecMan->CheckPropertyAccess(cx, GetGlobalJSObject(cx, obj), "Window", id,
|
||||||
|
nsIXPCSecurityManager::ACCESS_GET_PROPERTY);
|
||||||
|
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
// The security check failed. The security manager set a JS
|
||||||
|
// exception for us.
|
||||||
|
|
||||||
|
return JS_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Print a warning on the console so developers have a chance to
|
||||||
|
// catch and fix these mistakes.
|
||||||
|
PrintWarningOnConsole(cx, "GlobalScopeElementReference");
|
||||||
|
|
||||||
|
return JS_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// static
|
||||||
|
JSBool JS_DLL_CALLBACK
|
||||||
|
nsWindowSH::SecurityCheckOnSetProp(JSContext *cx, JSObject *obj, jsval id,
|
||||||
|
jsval *vp)
|
||||||
|
{
|
||||||
|
// Someone is accessing a element by referencing its name/id in the
|
||||||
|
// global scope, do a security check to make sure that's ok.
|
||||||
|
|
||||||
|
nsresult rv =
|
||||||
|
sSecMan->CheckPropertyAccess(cx, GetGlobalJSObject(cx, obj), "Window", id,
|
||||||
|
nsIXPCSecurityManager::ACCESS_SET_PROPERTY);
|
||||||
|
|
||||||
|
// If !NS_SUCCEEDED(rv) the security check failed. The security
|
||||||
|
// manager set a JS exception for us.
|
||||||
|
return NS_SUCCEEDED(rv);
|
||||||
|
}
|
||||||
|
|
||||||
|
// static
|
||||||
|
JSBool JS_DLL_CALLBACK
|
||||||
|
nsWindowSH::GlobalScopePolluterNewResolve(JSContext *cx, JSObject *obj,
|
||||||
|
jsval id, uintN flags,
|
||||||
|
JSObject **objp)
|
||||||
|
{
|
||||||
|
if (flags & (JSRESOLVE_ASSIGNING | JSRESOLVE_QUALIFIED) ||
|
||||||
|
JSVAL_IS_INT(id)) {
|
||||||
|
// Nothing to do here if we're assigning, or if we're doing a
|
||||||
|
// qualified resolve, or resolving a number
|
||||||
|
|
||||||
|
return JS_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsIHTMLDocument *doc = (nsIHTMLDocument *)::JS_GetPrivate(cx, obj);
|
||||||
|
|
||||||
|
if (!doc || doc->GetCompatibilityMode() != eCompatibility_NavQuirks) {
|
||||||
|
// If we don't have a document, or if the document is not in
|
||||||
|
// quirks mode, return early.
|
||||||
|
|
||||||
|
return JS_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
JSObject *proto = ::JS_GetPrototype(cx, obj);
|
||||||
|
JSString *jsstr = JSVAL_TO_STRING(id);
|
||||||
|
JSBool hasProp;
|
||||||
|
|
||||||
|
if (!proto || !::JS_HasUCProperty(cx, proto, ::JS_GetStringChars(jsstr),
|
||||||
|
::JS_GetStringLength(jsstr), &hasProp) ||
|
||||||
|
hasProp) {
|
||||||
|
// No prototype, or the property exists on the prototype. Do
|
||||||
|
// nothing.
|
||||||
|
|
||||||
|
return JS_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsDependentJSString str(jsstr);
|
||||||
|
nsCOMPtr<nsISupports> result;
|
||||||
|
|
||||||
|
{
|
||||||
|
nsCOMPtr<nsIDOMDocument> dom_doc(do_QueryInterface(doc));
|
||||||
|
nsCOMPtr<nsIDOMElement> element;
|
||||||
|
|
||||||
|
dom_doc->GetElementById(str, getter_AddRefs(element));
|
||||||
|
|
||||||
|
result = element;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!result) {
|
||||||
|
doc->ResolveName(str, nsnull, getter_AddRefs(result));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result) {
|
||||||
|
jsval v;
|
||||||
|
nsresult rv = WrapNative(cx, GetGlobalJSObject(cx, obj), result,
|
||||||
|
NS_GET_IID(nsISupports), &v);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
|
if (!::JS_DefineUCProperty(cx, obj, ::JS_GetStringChars(jsstr),
|
||||||
|
::JS_GetStringLength(jsstr), v, nsnull, nsnull,
|
||||||
|
0)) {
|
||||||
|
nsDOMClassInfo::ThrowJSException(cx, NS_ERROR_UNEXPECTED);
|
||||||
|
|
||||||
|
return JS_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
*objp = obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
return JS_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// static
|
||||||
|
nsresult
|
||||||
|
nsWindowSH::InstallGlobalScopePolluter(JSContext *cx, JSObject *obj,
|
||||||
|
nsIHTMLDocument *doc)
|
||||||
|
{
|
||||||
|
// If we didn't get a document, don't bother setting up a global
|
||||||
|
// scope polluter.
|
||||||
|
if (!doc || sDisableGlobalScopePollutionSupport) {
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
JSObject *gsp = ::JS_NewObject(cx, &sGlobalScopePolluterClass, nsnull, obj);
|
||||||
|
if (!gsp) {
|
||||||
|
return NS_ERROR_OUT_OF_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
JSObject *o = obj, *proto;
|
||||||
|
|
||||||
|
// Find the place in the prototype chain where we want this global
|
||||||
|
// scope polluter (right before Object.prototype).
|
||||||
|
|
||||||
|
while ((proto = ::JS_GetPrototype(cx, o))) {
|
||||||
|
if (JS_GET_CLASS(cx, proto) == sObjectClass) {
|
||||||
|
// Set the global scope polluters prototype to Object.prototype
|
||||||
|
if (!::JS_SetPrototype(cx, gsp, proto)) {
|
||||||
|
return NS_ERROR_UNEXPECTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
o = proto;
|
||||||
|
}
|
||||||
|
|
||||||
|
// And then set the ptototype of the object whose prototype was
|
||||||
|
// Object.prototype to be the global scope polluter.
|
||||||
|
if (!::JS_SetPrototype(cx, o, gsp)) {
|
||||||
|
return NS_ERROR_UNEXPECTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!::JS_SetPrivate(cx, gsp, doc)) {
|
||||||
|
return NS_ERROR_UNEXPECTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The global scope polluter will release doc on destruction (or
|
||||||
|
// reinitialzation).
|
||||||
|
NS_ADDREF(doc);
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsWindowSH::GetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
|
nsWindowSH::GetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
|
||||||
JSObject *obj, jsval id, jsval *vp, PRBool *_retval)
|
JSObject *obj, jsval id, jsval *vp, PRBool *_retval)
|
||||||
@ -4210,8 +4469,8 @@ nsWindowSH::GlobalResolve(nsISupports *native, JSContext *cx, JSObject *obj,
|
|||||||
|
|
||||||
// static
|
// static
|
||||||
nsresult
|
nsresult
|
||||||
nsWindowSH::CacheDocumentProperty(JSContext *cx, JSObject *obj,
|
nsWindowSH::OnDocumentChanged(JSContext *cx, JSObject *obj,
|
||||||
nsIDOMWindow *window)
|
nsIDOMWindow *window)
|
||||||
{
|
{
|
||||||
nsCOMPtr<nsIDOMDocument> document;
|
nsCOMPtr<nsIDOMDocument> document;
|
||||||
nsresult rv = window->GetDocument(getter_AddRefs(document));
|
nsresult rv = window->GetDocument(getter_AddRefs(document));
|
||||||
@ -4230,7 +4489,9 @@ nsWindowSH::CacheDocumentProperty(JSContext *cx, JSObject *obj,
|
|||||||
return NS_ERROR_FAILURE;
|
return NS_ERROR_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
return NS_OK;
|
nsCOMPtr<nsIHTMLDocument> html_doc(do_QueryInterface(document));
|
||||||
|
|
||||||
|
return InstallGlobalScopePolluter(cx, obj, html_doc);
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
@ -4485,7 +4746,7 @@ nsWindowSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
|
|||||||
nsCOMPtr<nsIDOMWindowInternal> window(do_QueryInterface(native));
|
nsCOMPtr<nsIDOMWindowInternal> window(do_QueryInterface(native));
|
||||||
NS_ENSURE_TRUE(window, NS_ERROR_UNEXPECTED);
|
NS_ENSURE_TRUE(window, NS_ERROR_UNEXPECTED);
|
||||||
|
|
||||||
rv = CacheDocumentProperty(cx, obj, window);
|
rv = OnDocumentChanged(cx, obj, window);
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
*objp = obj;
|
*objp = obj;
|
||||||
@ -5577,7 +5838,7 @@ nsHTMLDocumentSH::DocumentOpen(JSContext *cx, JSObject *obj, uintN argc,
|
|||||||
|
|
||||||
static JSClass sHTMLDocumentAllClass = {
|
static JSClass sHTMLDocumentAllClass = {
|
||||||
"HTML document.all class",
|
"HTML document.all class",
|
||||||
JSCLASS_HAS_PRIVATE | JSCLASS_NEW_RESOLVE | JSCLASS_PRIVATE_IS_NSISUPPORTS |
|
JSCLASS_HAS_PRIVATE | JSCLASS_PRIVATE_IS_NSISUPPORTS | JSCLASS_NEW_RESOLVE |
|
||||||
JSCLASS_HAS_RESERVED_SLOTS(1),
|
JSCLASS_HAS_RESERVED_SLOTS(1),
|
||||||
JS_PropertyStub, JS_PropertyStub, nsHTMLDocumentSH::DocumentAllGetProperty,
|
JS_PropertyStub, JS_PropertyStub, nsHTMLDocumentSH::DocumentAllGetProperty,
|
||||||
JS_PropertyStub, JS_EnumerateStub,
|
JS_PropertyStub, JS_EnumerateStub,
|
||||||
@ -5776,8 +6037,8 @@ nsHTMLDocumentSH::DocumentAllGetProperty(JSContext *cx, JSObject *obj,
|
|||||||
}
|
}
|
||||||
|
|
||||||
JSBool JS_DLL_CALLBACK
|
JSBool JS_DLL_CALLBACK
|
||||||
nsHTMLDocumentSH::DocumentAllNewResolve(JSContext *cx, JSObject *obj,
|
nsHTMLDocumentSH::DocumentAllNewResolve(JSContext *cx, JSObject *obj, jsval id,
|
||||||
jsval id, uintN flags, JSObject **objp)
|
uintN flags, JSObject **objp)
|
||||||
{
|
{
|
||||||
if (flags & JSRESOLVE_ASSIGNING) {
|
if (flags & JSRESOLVE_ASSIGNING) {
|
||||||
// Nothing to do here if we're assigning
|
// Nothing to do here if we're assigning
|
||||||
@ -5848,6 +6109,9 @@ nsHTMLDocumentSH::DocumentAllNewResolve(JSContext *cx, JSObject *obj,
|
|||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Finalize hook used by document related JS objects, but also by
|
||||||
|
// sGlobalScopePolluterClass!
|
||||||
|
|
||||||
void JS_DLL_CALLBACK
|
void JS_DLL_CALLBACK
|
||||||
nsHTMLDocumentSH::ReleaseDocument(JSContext *cx, JSObject *obj)
|
nsHTMLDocumentSH::ReleaseDocument(JSContext *cx, JSObject *obj)
|
||||||
{
|
{
|
||||||
@ -5907,71 +6171,6 @@ GetDocumentAllHelper(JSContext *cx, JSObject *obj)
|
|||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
PrintDocumentAllWarningOnConsole(JSContext *cx)
|
|
||||||
{
|
|
||||||
nsCOMPtr<nsIStringBundleService>
|
|
||||||
stringService(do_GetService(NS_STRINGBUNDLE_CONTRACTID));
|
|
||||||
if (!stringService) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsCOMPtr<nsIStringBundle> bundle;
|
|
||||||
stringService->CreateBundle(kDOMStringBundleURL, getter_AddRefs(bundle));
|
|
||||||
if (!bundle) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsXPIDLString msg;
|
|
||||||
bundle->GetStringFromName(NS_LITERAL_STRING("DocumentAllUsed").get(),
|
|
||||||
getter_Copies(msg));
|
|
||||||
|
|
||||||
if (msg.IsEmpty()) {
|
|
||||||
NS_ERROR("Failed to get strings from dom.properties!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsCOMPtr<nsIConsoleService> consoleService
|
|
||||||
(do_GetService("@mozilla.org/consoleservice;1"));
|
|
||||||
if (!consoleService) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsCOMPtr<nsIScriptError> scriptError =
|
|
||||||
do_CreateInstance(NS_SCRIPTERROR_CONTRACTID);
|
|
||||||
if (!scriptError) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
JSStackFrame *fp, *iterator = nsnull;
|
|
||||||
fp = ::JS_FrameIterator(cx, &iterator);
|
|
||||||
PRUint32 lineno = 0;
|
|
||||||
nsAutoString sourcefile;
|
|
||||||
if (fp) {
|
|
||||||
JSScript* script = ::JS_GetFrameScript(cx, fp);
|
|
||||||
if (script) {
|
|
||||||
const char* filename = ::JS_GetScriptFilename(cx, script);
|
|
||||||
if (filename) {
|
|
||||||
CopyUTF8toUTF16(nsDependentCString(filename), sourcefile);
|
|
||||||
}
|
|
||||||
jsbytecode* pc = ::JS_GetFramePC(cx, fp);
|
|
||||||
if (pc) {
|
|
||||||
lineno = ::JS_PCToLineNumber(cx, script, pc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
nsresult rv = scriptError->Init(msg.get(),
|
|
||||||
sourcefile.get(),
|
|
||||||
EmptyString().get(),
|
|
||||||
lineno,
|
|
||||||
0, // column for error is not available
|
|
||||||
nsIScriptError::warningFlag,
|
|
||||||
"DOM:HTML");
|
|
||||||
if (NS_SUCCEEDED(rv)){
|
|
||||||
consoleService->LogMessage(scriptError);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
JSBool JS_DLL_CALLBACK
|
JSBool JS_DLL_CALLBACK
|
||||||
nsHTMLDocumentSH::DocumentAllHelperGetProperty(JSContext *cx, JSObject *obj,
|
nsHTMLDocumentSH::DocumentAllHelperGetProperty(JSContext *cx, JSObject *obj,
|
||||||
jsval id, jsval *vp)
|
jsval id, jsval *vp)
|
||||||
@ -6003,7 +6202,7 @@ nsHTMLDocumentSH::DocumentAllHelperGetProperty(JSContext *cx, JSObject *obj,
|
|||||||
// qualified name. Expose the document.all collection.
|
// qualified name. Expose the document.all collection.
|
||||||
|
|
||||||
// Print a warning so developers can stop using document.all
|
// Print a warning so developers can stop using document.all
|
||||||
PrintDocumentAllWarningOnConsole(cx);
|
PrintWarningOnConsole(cx, "DocumentAllUsed");
|
||||||
|
|
||||||
if (!JSVAL_IS_OBJECT(*vp)) {
|
if (!JSVAL_IS_OBJECT(*vp)) {
|
||||||
// First time through, create the collection, and set the
|
// First time through, create the collection, and set the
|
||||||
@ -6162,39 +6361,46 @@ nsHTMLDocumentSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (id == sAll_id && !sDisableDocumentAllSupport) {
|
if (id == sAll_id && !sDisableDocumentAllSupport) {
|
||||||
JSObject *helper = GetDocumentAllHelper(cx, ::JS_GetPrototype(cx, obj));
|
wrapper->GetNative(getter_AddRefs(result));
|
||||||
|
nsCOMPtr<nsIHTMLDocument> doc(do_QueryInterface(result));
|
||||||
|
|
||||||
// If we don't already have a helper, and we're
|
if (doc->GetCompatibilityMode() == eCompatibility_NavQuirks) {
|
||||||
// resolving document.all qualified, and we're *not* detecting
|
JSObject *helper =
|
||||||
// document.all, e.g. if (document.all), create a helper.
|
GetDocumentAllHelper(cx, ::JS_GetPrototype(cx, obj));
|
||||||
if (!helper && flags & JSRESOLVE_QUALIFIED &&
|
|
||||||
!(flags & JSRESOLVE_DETECTING)) {
|
|
||||||
helper = JS_NewObject(cx, &sHTMLDocumentAllHelperClass,
|
|
||||||
::JS_GetPrototype(cx, obj),
|
|
||||||
GetGlobalJSObject(cx, obj));
|
|
||||||
|
|
||||||
if (!helper) {
|
// If we don't already have a helper, and we're resolving
|
||||||
return NS_ERROR_OUT_OF_MEMORY;
|
// document.all qualified, and we're *not* detecting
|
||||||
|
// document.all, e.g. if (document.all), create a helper.
|
||||||
|
if (!helper && flags & JSRESOLVE_QUALIFIED &&
|
||||||
|
!(flags & JSRESOLVE_DETECTING)) {
|
||||||
|
helper = JS_NewObject(cx, &sHTMLDocumentAllHelperClass,
|
||||||
|
::JS_GetPrototype(cx, obj),
|
||||||
|
GetGlobalJSObject(cx, obj));
|
||||||
|
|
||||||
|
if (!helper) {
|
||||||
|
return NS_ERROR_OUT_OF_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Insert the helper into our prototype chain. helper's prototype
|
||||||
|
// is already obj's current prototype.
|
||||||
|
if (!::JS_SetPrototype(cx, obj, helper)) {
|
||||||
|
nsDOMClassInfo::ThrowJSException(cx, NS_ERROR_UNEXPECTED);
|
||||||
|
|
||||||
|
return NS_ERROR_UNEXPECTED;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Insert the helper into our prototype chain. helper's prototype
|
// If we have (or just created) a helper, pass the resolve flags
|
||||||
// is already obj's current prototype.
|
// to the helper as its private data.
|
||||||
if (!::JS_SetPrototype(cx, obj, helper)) {
|
if (helper &&
|
||||||
|
!::JS_SetPrivate(cx, helper,
|
||||||
|
JSVAL_TO_PRIVATE(INT_TO_JSVAL(flags)))) {
|
||||||
nsDOMClassInfo::ThrowJSException(cx, NS_ERROR_UNEXPECTED);
|
nsDOMClassInfo::ThrowJSException(cx, NS_ERROR_UNEXPECTED);
|
||||||
|
|
||||||
return NS_ERROR_UNEXPECTED;
|
return NS_ERROR_UNEXPECTED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we have (or just created) a helper, pass the resolve flags
|
|
||||||
// to the helper as its private data.
|
|
||||||
if (helper && !::JS_SetPrivate(cx, helper,
|
|
||||||
JSVAL_TO_PRIVATE(INT_TO_JSVAL(flags)))) {
|
|
||||||
nsDOMClassInfo::ThrowJSException(cx, NS_ERROR_UNEXPECTED);
|
|
||||||
|
|
||||||
return NS_ERROR_UNEXPECTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -50,6 +50,7 @@ class nsIPluginInstance;
|
|||||||
class nsIForm;
|
class nsIForm;
|
||||||
class nsIDOMNodeList;
|
class nsIDOMNodeList;
|
||||||
class nsIDOMDocument;
|
class nsIDOMDocument;
|
||||||
|
class nsIHTMLDocument;
|
||||||
|
|
||||||
struct nsDOMClassInfoData;
|
struct nsDOMClassInfoData;
|
||||||
|
|
||||||
@ -199,6 +200,7 @@ protected:
|
|||||||
|
|
||||||
static PRBool sIsInitialized;
|
static PRBool sIsInitialized;
|
||||||
static PRBool sDisableDocumentAllSupport;
|
static PRBool sDisableDocumentAllSupport;
|
||||||
|
static PRBool sDisableGlobalScopePollutionSupport;
|
||||||
|
|
||||||
static jsval sTop_id;
|
static jsval sTop_id;
|
||||||
static jsval sParent_id;
|
static jsval sParent_id;
|
||||||
@ -356,8 +358,23 @@ public:
|
|||||||
NS_IMETHOD Finalize(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
|
NS_IMETHOD Finalize(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
|
||||||
JSObject *obj);
|
JSObject *obj);
|
||||||
|
|
||||||
static nsresult CacheDocumentProperty(JSContext *cx, JSObject *obj,
|
static nsresult OnDocumentChanged(JSContext *cx, JSObject *obj,
|
||||||
nsIDOMWindow *window);
|
nsIDOMWindow *window);
|
||||||
|
|
||||||
|
static JSBool JS_DLL_CALLBACK GlobalScopePolluterNewResolve(JSContext *cx,
|
||||||
|
JSObject *obj,
|
||||||
|
jsval id,
|
||||||
|
uintN flags,
|
||||||
|
JSObject **objp);
|
||||||
|
static JSBool JS_DLL_CALLBACK GlobalScopePolluterGetProperty(JSContext *cx,
|
||||||
|
JSObject *obj,
|
||||||
|
jsval id,
|
||||||
|
jsval *vp);
|
||||||
|
static JSBool JS_DLL_CALLBACK SecurityCheckOnSetProp(JSContext *cx,
|
||||||
|
JSObject *obj, jsval id,
|
||||||
|
jsval *vp);
|
||||||
|
static nsresult InstallGlobalScopePolluter(JSContext *cx, JSObject *obj,
|
||||||
|
nsIHTMLDocument *doc);
|
||||||
|
|
||||||
static nsIClassInfo *doCreate(nsDOMClassInfoData* aData)
|
static nsIClassInfo *doCreate(nsDOMClassInfoData* aData)
|
||||||
{
|
{
|
||||||
@ -434,7 +451,7 @@ protected:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
NS_IMETHOD PostCreate(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
|
NS_IMETHOD PostCreate(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
|
||||||
JSObject *obj);
|
JSObject *obj);
|
||||||
|
|
||||||
static nsIClassInfo *doCreate(nsDOMClassInfoData* aData)
|
static nsIClassInfo *doCreate(nsDOMClassInfoData* aData)
|
||||||
{
|
{
|
||||||
|
@ -645,14 +645,15 @@ GlobalWindowImpl::SetNewDocument(nsIDOMDocument* aDocument,
|
|||||||
|
|
||||||
if (mIsScopeClear) {
|
if (mIsScopeClear) {
|
||||||
mContext->InitContext(this);
|
mContext->InitContext(this);
|
||||||
} else if (mJSObject) {
|
|
||||||
// If we didn't clear the scope (i.e. the old document was
|
|
||||||
// about:blank) then we need to update the cached document
|
|
||||||
// property on the window to reflect the new document and not
|
|
||||||
// the old one.
|
|
||||||
|
|
||||||
nsWindowSH::CacheDocumentProperty(cx, mJSObject, this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If we didn't clear the scope (i.e. the old document was
|
||||||
|
// about:blank) then we need to update the cached document
|
||||||
|
// property on the window to reflect the new document and not the
|
||||||
|
// old one. And even if we did clear the scope, we need to notify
|
||||||
|
// the scriptable helper about the document change.
|
||||||
|
|
||||||
|
nsWindowSH::OnDocumentChanged(cx, mJSObject, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clear our mutation bitfield.
|
// Clear our mutation bitfield.
|
||||||
|
Loading…
Reference in New Issue
Block a user