From ba9815c96a028a6a6330b2383968f1b2fc25d066 Mon Sep 17 00:00:00 2001 From: Boris Zbarsky Date: Thu, 1 Nov 2012 13:51:57 -0400 Subject: [PATCH] Bug 807222 part 6. Fix getOwnPropertyNames to work correctly on Window. r=jst One note: it might be better to change the signature of Enumerate() to indicate whether we're enumerating just the enumerable properties or all of them, so we can skip doing this when someone does for...in on the window. --- .../test/browser_webconsole_completion.js | 9 ++--- dom/base/nsDOMClassInfo.cpp | 36 +++++++++++++++++++ dom/base/nsScriptNameSpaceManager.cpp | 23 ++++++++++++ dom/base/nsScriptNameSpaceManager.h | 6 ++++ dom/base/test/Makefile.in | 1 + dom/base/test/test_window_enumeration.html | 33 +++++++++++++++++ 6 files changed, 104 insertions(+), 4 deletions(-) create mode 100644 dom/base/test/test_window_enumeration.html diff --git a/browser/devtools/webconsole/test/browser_webconsole_completion.js b/browser/devtools/webconsole/test/browser_webconsole_completion.js index 0dc1981fe0b1..8f7766a69b97 100644 --- a/browser/devtools/webconsole/test/browser_webconsole_completion.js +++ b/browser/devtools/webconsole/test/browser_webconsole_completion.js @@ -50,13 +50,14 @@ function testCompletion(hud) { is(input.selectionEnd, 8, "end selection is alright"); is(jsterm.completeNode.value.replace(/ /g, ""), "", "'docu' completed"); - // Test typing 'window.O' and press tab. - input.value = "window.O"; - input.setSelectionRange(8, 8); + // Test typing 'window.Ob' and press tab. Just 'window.O' is + // ambiguous: could be window.Object, window.Option, etc. + input.value = "window.Ob"; + input.setSelectionRange(9, 9); jsterm.complete(jsterm.COMPLETE_FORWARD, testNext); yield; - is(input.value, "window.Object", "'window.O' tab completion"); + is(input.value, "window.Object", "'window.Ob' tab completion"); // Test typing 'document.getElem'. input.value = "document.getElem"; diff --git a/dom/base/nsDOMClassInfo.cpp b/dom/base/nsDOMClassInfo.cpp index f4b8a4ccfb29..0cb0637f2dd7 100644 --- a/dom/base/nsDOMClassInfo.cpp +++ b/dom/base/nsDOMClassInfo.cpp @@ -5593,12 +5593,48 @@ nsWindowSH::GetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx, return NS_OK; } +struct ResolveGlobalNameClosure +{ + JSContext* cx; + JSObject* obj; + bool* retval; +}; + +static PLDHashOperator +ResolveGlobalName(const nsAString& aName, void* aClosure) +{ + ResolveGlobalNameClosure* closure = + static_cast(aClosure); + JS::Value dummy; + bool ok = JS_LookupUCProperty(closure->cx, closure->obj, + aName.BeginReading(), aName.Length(), + &dummy); + if (!ok) { + *closure->retval = false; + return PL_DHASH_STOP; + } + return PL_DHASH_NEXT; +} + NS_IMETHODIMP nsWindowSH::Enumerate(nsIXPConnectWrappedNative *wrapper, JSContext *cx, JSObject *obj, bool *_retval) { if (!ObjectIsNativeWrapper(cx, obj)) { *_retval = JS_EnumerateStandardClasses(cx, obj); + if (!*_retval) { + return NS_OK; + } + + // Now resolve everything from the namespace manager + nsScriptNameSpaceManager *nameSpaceManager = + nsJSRuntime::GetNameSpaceManager(); + if (!nameSpaceManager) { + NS_ERROR("Can't get namespace manager."); + return NS_ERROR_UNEXPECTED; + } + ResolveGlobalNameClosure closure = { cx, obj, _retval }; + nameSpaceManager->EnumerateGlobalNames(ResolveGlobalName, &closure); } return NS_OK; diff --git a/dom/base/nsScriptNameSpaceManager.cpp b/dom/base/nsScriptNameSpaceManager.cpp index b9419136fde7..ef668bea4e71 100644 --- a/dom/base/nsScriptNameSpaceManager.cpp +++ b/dom/base/nsScriptNameSpaceManager.cpp @@ -802,6 +802,29 @@ nsScriptNameSpaceManager::RegisterDefineDOMInterface(const nsAFlatString& aName, } } +struct GlobalNameClosure +{ + nsScriptNameSpaceManager::GlobalNameEnumerator enumerator; + void* closure; +}; + +static PLDHashOperator +EnumerateGlobalName(PLDHashTable*, PLDHashEntryHdr *hdr, uint32_t, + void* aClosure) +{ + GlobalNameMapEntry *entry = static_cast(hdr); + GlobalNameClosure* closure = static_cast(aClosure); + return closure->enumerator(entry->mKey, closure->closure); +} + +void +nsScriptNameSpaceManager::EnumerateGlobalNames(GlobalNameEnumerator aEnumerator, + void* aClosure) +{ + GlobalNameClosure closure = { aEnumerator, aClosure }; + PL_DHashTableEnumerate(&mGlobalNames, EnumerateGlobalName, &closure); +} + static size_t SizeOfEntryExcludingThis(PLDHashEntryHdr *aHdr, nsMallocSizeOfFun aMallocSizeOf, void *aArg) diff --git a/dom/base/nsScriptNameSpaceManager.h b/dom/base/nsScriptNameSpaceManager.h index 1cfdc85d92a2..9ea3eb9e0cda 100644 --- a/dom/base/nsScriptNameSpaceManager.h +++ b/dom/base/nsScriptNameSpaceManager.h @@ -143,6 +143,12 @@ public: mozilla::dom::DefineInterface aDefineDOMInterface, mozilla::dom::PrefEnabled aPrefEnabled); + typedef PLDHashOperator + (* GlobalNameEnumerator)(const nsAString& aGlobalName, void* aClosure); + + void EnumerateGlobalNames(GlobalNameEnumerator aEnumerator, + void* aClosure); + size_t SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf); private: diff --git a/dom/base/test/Makefile.in b/dom/base/test/Makefile.in index a6ab1ce88fbe..a3931ca30fb7 100644 --- a/dom/base/test/Makefile.in +++ b/dom/base/test/Makefile.in @@ -17,6 +17,7 @@ MOCHITEST_FILES = \ test_gsp-qualified.html \ test_nondomexception.html \ test_screen_orientation.html \ + test_window_enumeration.html \ $(NULL) MOCHITEST_CHROME_FILES = \ diff --git a/dom/base/test/test_window_enumeration.html b/dom/base/test/test_window_enumeration.html new file mode 100644 index 000000000000..584bcddf51cd --- /dev/null +++ b/dom/base/test/test_window_enumeration.html @@ -0,0 +1,33 @@ + + + + + + Test for Bug 807222 + + + + +Mozilla Bug 807222 +

+ +
+
+
+ +