Fix for bug 820657 (Implement the NamedGetter functionality on HTMLDocument) - refactor code to support document.all. r=bz.

--HG--
extra : rebase_source : b69d963e8931a4f62dce64d7f90b78a05c488347
This commit is contained in:
Peter Van der Beken 2013-03-27 18:15:37 +01:00
parent 4bdb531d59
commit ca9babdeb5

View File

@ -7120,6 +7120,76 @@ nsHTMLDocumentSH::DocumentAllTagsNewResolve(JSContext *cx, JSHandleObject obj,
}
static nsresult
ResolveAll(JSContext* cx, nsIDocument* doc, JSObject* obj)
{
JSObject *proto;
if (!::JS_GetPrototype(cx, obj, &proto)) {
return NS_ERROR_FAILURE;
}
JSObject *helper;
if (!GetDocumentAllHelper(cx, proto, &helper)) {
return NS_ERROR_FAILURE;
}
if (!::JS_GetPrototype(cx, helper ? helper : obj, &proto)) {
return NS_ERROR_FAILURE;
}
// Check if the property all is defined on obj's (or helper's
// if obj doesn't exist) prototype, if it is, don't expose our
// document.all helper.
JSBool hasAll = JS_FALSE;
if (proto && !JS_HasProperty(cx, proto, "all", &hasAll)) {
return NS_ERROR_UNEXPECTED;
}
if (hasAll && helper) {
// Our helper's prototype now has an "all" property, remove
// the helper out of the prototype chain to prevent
// shadowing of the now defined "all" property.
JSObject *tmp = obj, *tmpProto = tmp;
do {
tmp = tmpProto;
if (!::JS_GetPrototype(cx, tmp, &tmpProto)) {
return NS_ERROR_UNEXPECTED;
}
} while (tmpProto != helper);
::JS_SetPrototype(cx, tmp, proto);
}
// If we don't already have a helper and "all" isn't already defined on
// our prototype, create a helper.
if (!helper && !hasAll) {
// Print a warning so developers can stop using document.all
PrintWarningOnConsole(cx, "DocumentAllUsed");
if (!::JS_GetPrototype(cx, obj, &proto)) {
return NS_ERROR_UNEXPECTED;
}
helper = ::JS_NewObject(cx, &sHTMLDocumentAllHelperClass,
proto,
::JS_GetGlobalForObject(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)) {
xpc::Throw(cx, NS_ERROR_UNEXPECTED);
return NS_ERROR_UNEXPECTED;
}
}
return NS_OK;
}
NS_IMETHODIMP
nsHTMLDocumentSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
JSObject *obj, jsid id, uint32_t flags,
@ -7158,69 +7228,7 @@ nsHTMLDocumentSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
nsIDocument *doc = static_cast<nsIDocument*>(wrapper->Native());
if (doc->GetCompatibilityMode() == eCompatibility_NavQuirks) {
JSObject *proto;
if (!::JS_GetPrototype(cx, obj, &proto)) {
return NS_ERROR_FAILURE;
}
JSObject *helper;
if (!GetDocumentAllHelper(cx, proto, &helper)) {
return NS_ERROR_FAILURE;
}
if (!::JS_GetPrototype(cx, helper ? helper : obj, &proto)) {
return NS_ERROR_FAILURE;
}
// Check if the property all is defined on obj's (or helper's
// if obj doesn't exist) prototype, if it is, don't expose our
// document.all helper.
JSBool hasAll = JS_FALSE;
if (proto && !JS_HasProperty(cx, proto, "all", &hasAll)) {
return NS_ERROR_UNEXPECTED;
}
if (hasAll && helper) {
// Our helper's prototype now has an "all" property, remove
// the helper out of the prototype chain to prevent
// shadowing of the now defined "all" property.
JSObject *tmp = obj, *tmpProto = tmp;
do {
tmp = tmpProto;
if (!::JS_GetPrototype(cx, tmp, &tmpProto)) {
return NS_ERROR_UNEXPECTED;
}
} while (tmpProto != helper);
::JS_SetPrototype(cx, tmp, proto);
}
// If we don't already have a helper and "all" isn't already defined on
// our prototype, create a helper.
if (!helper && !hasAll) {
// Print a warning so developers can stop using document.all
PrintWarningOnConsole(cx, "DocumentAllUsed");
if (!::JS_GetPrototype(cx, obj, &proto)) {
return NS_ERROR_UNEXPECTED;
}
helper = ::JS_NewObject(cx, &sHTMLDocumentAllHelperClass,
proto,
::JS_GetGlobalForObject(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)) {
xpc::Throw(cx, NS_ERROR_UNEXPECTED);
return NS_ERROR_UNEXPECTED;
}
}
return ResolveAll(cx, doc, obj);
}
return NS_OK;