Bug 877277 - Move the document.all getter into WebIDL; r=smaug

This commit is contained in:
Ms2ger 2013-06-12 08:55:00 +02:00
Родитель 09bb5c9224
Коммит 88ca948d77
5 изменённых файлов: 84 добавлений и 204 удалений

Просмотреть файл

@ -201,18 +201,44 @@ nsHTMLDocument::nsHTMLDocument()
SetIsDOMBinding();
}
nsHTMLDocument::~nsHTMLDocument()
{
mAll = nullptr;
NS_DROP_JS_OBJECTS(this, nsHTMLDocument);
}
NS_IMPL_CYCLE_COLLECTION_INHERITED_10(nsHTMLDocument, nsDocument,
mImages,
mApplets,
mEmbeds,
mLinks,
mAnchors,
mScripts,
mForms,
mFormControls,
mWyciwygChannel,
mMidasCommandManager)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsHTMLDocument, nsDocument)
NS_ASSERTION(!nsCCUncollectableMarker::InGeneration(cb, tmp->GetMarkedCCGeneration()),
"Shouldn't traverse nsHTMLDocument!");
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mImages)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mApplets)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mEmbeds)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mLinks)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mAnchors)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mScripts)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mForms)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mFormControls)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mWyciwygChannel)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMidasCommandManager)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsHTMLDocument, nsDocument)
tmp->mAll = nullptr;
NS_IMPL_CYCLE_COLLECTION_UNLINK(mImages)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mApplets)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mEmbeds)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mLinks)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mAnchors)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mScripts)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mForms)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mFormControls)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mWyciwygChannel)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mMidasCommandManager)
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(nsHTMLDocument, nsDocument)
NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mAll)
NS_IMPL_CYCLE_COLLECTION_TRACE_END
NS_IMPL_ADDREF_INHERITED(nsHTMLDocument, nsDocument)
NS_IMPL_RELEASE_INHERITED(nsHTMLDocument, nsDocument)
@ -2310,10 +2336,6 @@ nsHTMLDocument::NamedGetter(JSContext* cx, const nsAString& aName, bool& aFound,
nsISupports* supp = ResolveName(aName, &cache);
if (!supp) {
aFound = false;
if (aName.EqualsLiteral("all")) {
JS::Rooted<JSObject*> obj(cx, GetWrapper());
rv = nsHTMLDocumentSH::TryResolveAll(cx, this, obj);
}
return nullptr;
}
@ -2698,6 +2720,27 @@ nsHTMLDocument::GetDocumentAllResult(const nsAString& aID,
return cont;
}
JSObject*
nsHTMLDocument::GetAll(JSContext* aCx, ErrorResult& aRv)
{
if (!mAll) {
mAll = JS_NewObject(aCx, &sHTMLDocumentAllClass, nullptr,
JS_GetGlobalForObject(aCx, GetWrapper()));
if (!mAll) {
aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
return nullptr;
}
// Make the JSObject hold a reference to this.
JS_SetPrivate(mAll, static_cast<nsINode*>(this));
NS_ADDREF_THIS();
NS_HOLD_JS_OBJECTS(this, nsHTMLDocument);
}
return mAll;
}
static void
NotifyEditableStateChange(nsINode *aNode, nsIDocument *aDocument)
{

Просмотреть файл

@ -44,13 +44,14 @@ public:
using nsDocument::GetPlugins;
nsHTMLDocument();
~nsHTMLDocument();
virtual nsresult Init() MOZ_OVERRIDE;
NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr) MOZ_OVERRIDE;
NS_IMETHOD_(nsrefcnt) AddRef(void) MOZ_OVERRIDE;
NS_IMETHOD_(nsrefcnt) Release(void) MOZ_OVERRIDE;
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(nsHTMLDocument,
nsDocument)
// nsIDocument
virtual void Reset(nsIChannel* aChannel, nsILoadGroup* aLoadGroup) MOZ_OVERRIDE;
virtual void ResetToURI(nsIURI* aURI, nsILoadGroup* aLoadGroup,
nsIPrincipal* aPrincipal) MOZ_OVERRIDE;
@ -69,9 +70,15 @@ public:
virtual void StopDocumentLoad() MOZ_OVERRIDE;
virtual void BeginLoad() MOZ_OVERRIDE;
virtual void EndLoad() MOZ_OVERRIDE;
virtual NS_HIDDEN_(void) Destroy() MOZ_OVERRIDE
{
mAll = nullptr;
nsDocument::Destroy();
}
// nsIHTMLDocument
virtual void SetCompatibilityMode(nsCompatibility aMode) MOZ_OVERRIDE;
virtual bool IsWriting() MOZ_OVERRIDE
@ -108,6 +115,7 @@ public:
nsISupports *GetDocumentAllResult(const nsAString& aID,
nsWrapperCache **aCache,
nsresult *aResult);
JSObject* GetAll(JSContext* aCx, mozilla::ErrorResult& aRv);
nsISupports* ResolveName(const nsAString& aName, nsWrapperCache **aCache);
virtual already_AddRefed<nsISupports> ResolveName(const nsAString& aName,
@ -155,8 +163,6 @@ public:
void EndUpdate(nsUpdateType aUpdateType) MOZ_OVERRIDE;
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsHTMLDocument, nsDocument)
virtual nsresult SetEditingState(EditingState aState) MOZ_OVERRIDE;
virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const MOZ_OVERRIDE;
@ -294,6 +300,8 @@ protected:
nsRefPtr<nsContentList> mForms;
nsRefPtr<nsContentList> mFormControls;
JSObject* mAll;
/** # of forms in the document, synchronously set */
int32_t mNumForms;

Просмотреть файл

@ -892,7 +892,6 @@ jsid nsDOMClassInfo::sTop_id = JSID_VOID;
jsid nsDOMClassInfo::sDocument_id = JSID_VOID;
jsid nsDOMClassInfo::sFrames_id = JSID_VOID;
jsid nsDOMClassInfo::sSelf_id = JSID_VOID;
jsid nsDOMClassInfo::sAll_id = JSID_VOID;
jsid nsDOMClassInfo::sWrappedJSObject_id = JSID_VOID;
jsid nsDOMClassInfo::sURL_id = JSID_VOID;
jsid nsDOMClassInfo::sOnload_id = JSID_VOID;
@ -1088,7 +1087,6 @@ nsDOMClassInfo::DefineStaticJSVals(JSContext *cx)
SET_JSID_TO_STRING(sDocument_id, cx, "document");
SET_JSID_TO_STRING(sFrames_id, cx, "frames");
SET_JSID_TO_STRING(sSelf_id, cx, "self");
SET_JSID_TO_STRING(sAll_id, cx, "all");
SET_JSID_TO_STRING(sWrappedJSObject_id, cx, "wrappedJSObject");
SET_JSID_TO_STRING(sURL_id, cx, "URL");
SET_JSID_TO_STRING(sOnload_id, cx, "onload");
@ -2611,7 +2609,6 @@ nsDOMClassInfo::ShutDown()
sDocument_id = JSID_VOID;
sFrames_id = JSID_VOID;
sSelf_id = JSID_VOID;
sAll_id = JSID_VOID;
sWrappedJSObject_id = JSID_VOID;
sOnload_id = JSID_VOID;
sOnerror_id = JSID_VOID;
@ -2725,8 +2722,9 @@ ChildWindowGetter(JSContext *cx, JSHandleObject obj, JSHandleId id,
static nsHTMLDocument*
GetDocument(JSObject *obj)
{
MOZ_ASSERT(js::GetObjectJSClass(obj) == &sHTMLDocumentAllClass);
return static_cast<nsHTMLDocument*>(
static_cast<nsIHTMLDocument*>(::JS_GetPrivate(obj)));
static_cast<nsINode*>(JS_GetPrivate(obj)));
}
// static
@ -5625,9 +5623,9 @@ nsNamedArraySH::GetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
}
// HTMLDocument helper
// HTMLAllCollection
static JSClass sHTMLDocumentAllClass = {
JSClass sHTMLDocumentAllClass = {
"HTML document.all class",
JSCLASS_HAS_PRIVATE | JSCLASS_PRIVATE_IS_NSISUPPORTS | JSCLASS_NEW_RESOLVE |
JSCLASS_EMULATES_UNDEFINED | JSCLASS_HAS_RESERVED_SLOTS(1),
@ -5644,19 +5642,6 @@ static JSClass sHTMLDocumentAllClass = {
};
static JSClass sHTMLDocumentAllHelperClass = {
"HTML document.all helper class",
JSCLASS_NEW_RESOLVE,
JS_PropertyStub, /* addProperty */
JS_DeletePropertyStub, /* delProperty */
nsHTMLDocumentSH::DocumentAllHelperGetProperty, /* getProperty */
JS_StrictPropertyStub, /* setProperty */
JS_EnumerateStub,
(JSResolveOp)nsHTMLDocumentSH::DocumentAllHelperNewResolve,
JS_ConvertStub
};
// static
JSBool
nsHTMLDocumentSH::GetDocumentAllNodeList(JSContext *cx,
@ -5860,13 +5845,10 @@ nsHTMLDocumentSH::DocumentAllNewResolve(JSContext *cx, JSHandleObject obj, JSHan
return ok;
}
// Finalize hook used by document related JS objects, but also by
// sGlobalScopePolluterClass!
void
nsHTMLDocumentSH::ReleaseDocument(JSFreeOp *fop, JSObject *obj)
{
nsIHTMLDocument *doc = static_cast<nsIHTMLDocument *>(JS_GetPrivate(obj));
nsIHTMLDocument* doc = GetDocument(obj);
if (doc) {
xpc::DeferredRelease(doc);
}
@ -5916,155 +5898,6 @@ nsHTMLDocumentSH::CallToGetPropMapper(JSContext *cx, unsigned argc, jsval *vp)
}
static inline bool
GetDocumentAllHelper(JSContext *cx, JS::Handle<JSObject*> aObj, JSObject **result)
{
JS::Rooted<JSObject*> obj(cx, aObj);
while (obj && JS_GetClass(obj) != &sHTMLDocumentAllHelperClass) {
if (!::JS_GetPrototype(cx, obj, obj.address())) {
return false;
}
}
*result = obj;
return true;
}
JSBool
nsHTMLDocumentSH::DocumentAllHelperGetProperty(JSContext *cx, JSHandleObject obj,
JSHandleId id, JSMutableHandleValue vp)
{
if (nsDOMClassInfo::sAll_id != id) {
return JS_TRUE;
}
if (!vp.isObjectOrNull()) {
// First time through, create the collection, and set the
// document as its private nsISupports data.
nsresult rv;
nsCOMPtr<nsIHTMLDocument> doc = do_QueryWrapper(cx, obj, &rv);
if (NS_FAILED(rv)) {
xpc::Throw(cx, rv);
return JS_FALSE;
}
JS::Rooted<JSObject*> all(cx);
all = ::JS_NewObject(cx, &sHTMLDocumentAllClass, nullptr,
::JS_GetGlobalForObject(cx, obj));
if (!all) {
return JS_FALSE;
}
// Let the JSObject take over ownership of doc.
::JS_SetPrivate(all, doc.forget().get());
vp.setObject(*all);
}
return JS_TRUE;
}
JSBool
nsHTMLDocumentSH::DocumentAllHelperNewResolve(JSContext *cx, JSHandleObject obj,
JSHandleId id, unsigned flags,
JS::MutableHandle<JSObject*> objp)
{
if (nsDOMClassInfo::sAll_id == id) {
// document.all is resolved for the first time. Define it.
JS::Rooted<JSObject*> helper(cx);
if (!GetDocumentAllHelper(cx, obj, helper.address())) {
return JS_FALSE;
}
if (helper) {
if (!::JS_DefineProperty(cx, helper, "all", JSVAL_VOID, nullptr, nullptr,
JSPROP_ENUMERATE)) {
return JS_FALSE;
}
objp.set(helper);
}
}
return JS_TRUE;
}
static nsresult
ResolveAll(JSContext* cx, nsIDocument* doc, JS::Handle<JSObject*> obj)
{
JS::Rooted<JSObject*> proto(cx);
if (!::JS_GetPrototype(cx, obj, proto.address())) {
return NS_ERROR_FAILURE;
}
JS::Rooted<JSObject*> helper(cx);
if (!GetDocumentAllHelper(cx, proto, helper.address())) {
return NS_ERROR_FAILURE;
}
if (!::JS_GetPrototype(cx, helper ? helper : obj, proto.address())) {
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.
JS::Rooted<JSObject*> tmp(cx, obj), tmpProto(cx, tmp);
do {
tmp = tmpProto;
if (!::JS_GetPrototype(cx, tmp, tmpProto.address())) {
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) {
if (!::JS_GetPrototype(cx, obj, proto.address())) {
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;
}
nsresult
nsHTMLDocumentSH::TryResolveAll(JSContext* cx, nsHTMLDocument* doc,
JS::Handle<JSObject*> obj)
{
JSAutoCompartment ac(cx, obj);
return ResolveAll(cx, doc, obj);
}
// HTMLFormElement helper
NS_IMETHODIMP

Просмотреть файл

@ -217,7 +217,6 @@ public:
static jsid sDocument_id;
static jsid sFrames_id;
static jsid sSelf_id;
static jsid sAll_id;
static jsid sJava_id;
static jsid sPackages_id;
static jsid sWrappedJSObject_id;
@ -591,7 +590,9 @@ private:
};
// HTMLDocument helper
// HTMLAllCollection
extern JSClass sHTMLDocumentAllClass;
class nsHTMLDocumentSH
{
@ -606,14 +607,6 @@ public:
unsigned flags, JS::MutableHandle<JSObject*> objp);
static void ReleaseDocument(JSFreeOp *fop, JSObject *obj);
static JSBool CallToGetPropMapper(JSContext *cx, unsigned argc, jsval *vp);
static JSBool DocumentAllHelperGetProperty(JSContext *cx, JSHandleObject obj,
JSHandleId id, JSMutableHandleValue vp);
static JSBool DocumentAllHelperNewResolve(JSContext *cx, JSHandleObject obj,
JSHandleId id, unsigned flags,
JS::MutableHandle<JSObject*> objp);
static nsresult TryResolveAll(JSContext* cx, nsHTMLDocument* doc,
JS::Handle<JSObject*> obj);
};

Просмотреть файл

@ -65,6 +65,9 @@ interface HTMLDocument : Document {
void clear();
[Throws]
readonly attribute object all;
// https://dvcs.w3.org/hg/editing/raw-file/tip/editing.html#selections
[Throws]
Selection getSelection();