Bug 843840 part 2. Add a way to ask DOM proxies for only their enumerable property names, and use that in the enumerate hook. r=peterv

This commit is contained in:
Boris Zbarsky 2014-04-15 22:58:44 -04:00
parent ad59a21b39
commit 9c3392475d
35 changed files with 216 additions and 80 deletions

View File

@ -23,6 +23,7 @@
#include "mozilla/dom/NodeListBinding.h"
#include "mozilla/Likely.h"
#include "nsGenericHTMLElement.h"
#include "jsfriendapi.h"
#include <algorithm>
// Form related includes
@ -553,8 +554,12 @@ nsContentList::NamedItem(const nsAString& aName, bool aDoFlush)
}
void
nsContentList::GetSupportedNames(nsTArray<nsString>& aNames)
nsContentList::GetSupportedNames(unsigned aFlags, nsTArray<nsString>& aNames)
{
if (!(aFlags & JSITER_HIDDEN)) {
return;
}
BringSelfUpToDate(true);
nsAutoTArray<nsIAtom*, 8> atoms;

View File

@ -280,7 +280,8 @@ public:
aFound = !!item;
return item;
}
virtual void GetSupportedNames(nsTArray<nsString>& aNames) MOZ_OVERRIDE;
virtual void GetSupportedNames(unsigned aFlags,
nsTArray<nsString>& aNames) MOZ_OVERRIDE;
// nsContentList public methods
NS_HIDDEN_(uint32_t) Length(bool aDoFlush);

View File

@ -171,7 +171,7 @@ public:
RemoveNamedItemNS(const nsAString& aNamespaceURI, const nsAString& aLocalName,
ErrorResult& aError);
void GetSupportedNames(nsTArray<nsString>& aNames)
void GetSupportedNames(unsigned, nsTArray<nsString>& aNames)
{
// No supported names we want to show up in iteration.
}

View File

@ -76,7 +76,8 @@ public:
virtual mozilla::dom::Element*
GetFirstNamedElement(const nsAString& aName, bool& aFound) = 0;
virtual void GetSupportedNames(nsTArray<nsString>& aNames) = 0;
virtual void GetSupportedNames(unsigned aFlags,
nsTArray<nsString>& aNames) = 0;
JSObject* GetWrapperPreserveColor()
{

View File

@ -17,6 +17,7 @@
#include "nsIDOMNode.h"
#include "nsIDOMNodeList.h"
#include "nsIFormControl.h"
#include "jsfriendapi.h"
namespace mozilla {
namespace dom {
@ -395,8 +396,13 @@ CollectNames(const nsAString& aName,
}
void
HTMLFormControlsCollection::GetSupportedNames(nsTArray<nsString>& aNames)
HTMLFormControlsCollection::GetSupportedNames(unsigned aFlags,
nsTArray<nsString>& aNames)
{
if (!(aFlags & JSITER_HIDDEN)) {
return;
}
FlushPendingNotifications();
// Just enumerate mNameLookupTable. This won't guarantee order, but
// that's OK, because the HTML5 spec doesn't define an order for

View File

@ -54,7 +54,8 @@ public:
bool dummy;
NamedGetter(aName, dummy, aResult);
}
virtual void GetSupportedNames(nsTArray<nsString>& aNames);
virtual void GetSupportedNames(unsigned aFlags,
nsTArray<nsString>& aNames) MOZ_OVERRIDE;
nsresult AddElementToTable(nsGenericHTMLFormElement* aChild,
const nsAString& aName);

View File

@ -1441,7 +1441,7 @@ HTMLFormElement::NameIsEnumerable(const nsAString& aName)
}
void
HTMLFormElement::GetSupportedNames(nsTArray<nsString >& aRetval)
HTMLFormElement::GetSupportedNames(unsigned, nsTArray<nsString >& aRetval)
{
// TODO https://www.w3.org/Bugs/Public/show_bug.cgi?id=22320
}

View File

@ -397,7 +397,7 @@ public:
bool NameIsEnumerable(const nsAString& aName);
void GetSupportedNames(nsTArray<nsString >& aRetval);
void GetSupportedNames(unsigned, nsTArray<nsString >& aRetval);
static int32_t
CompareFormControlPosition(Element* aElement1, Element* aElement2,

View File

@ -28,6 +28,7 @@
#include "nsRuleData.h"
#include "nsServiceManagerUtils.h"
#include "nsStyleConsts.h"
#include "jsfriendapi.h"
namespace mozilla {
namespace dom {
@ -280,8 +281,13 @@ HTMLOptionsCollection::NamedItem(const nsAString& aName,
}
void
HTMLOptionsCollection::GetSupportedNames(nsTArray<nsString>& aNames)
HTMLOptionsCollection::GetSupportedNames(unsigned aFlags,
nsTArray<nsString>& aNames)
{
if (!(aFlags & JSITER_HIDDEN)) {
return;
}
nsAutoTArray<nsIAtom*, 8> atoms;
for (uint32_t i = 0; i < mElements.Length(); ++i) {
HTMLOptionElement* content = mElements.ElementAt(i);

View File

@ -150,7 +150,8 @@ public:
{
aError = SetOption(aIndex, aOption);
}
virtual void GetSupportedNames(nsTArray<nsString>& aNames) MOZ_OVERRIDE;
virtual void GetSupportedNames(unsigned aFlags,
nsTArray<nsString>& aNames) MOZ_OVERRIDE;
private:
/** The list of options (holds strong references). This is infallible, so

View File

@ -297,7 +297,7 @@ HTMLPropertiesCollection::CrawlSubtree(Element* aElement)
}
void
HTMLPropertiesCollection::GetSupportedNames(nsTArray<nsString>& aNames)
HTMLPropertiesCollection::GetSupportedNames(unsigned, nsTArray<nsString>& aNames)
{
EnsureFresh();
mNames->CopyList(aNames);

View File

@ -95,7 +95,8 @@ public:
EnsureFresh();
return mNames;
}
virtual void GetSupportedNames(nsTArray<nsString>& aNames) MOZ_OVERRIDE;
virtual void GetSupportedNames(unsigned,
nsTArray<nsString>& aNames) MOZ_OVERRIDE;
NS_DECL_NSIDOMHTMLCOLLECTION

View File

@ -12,6 +12,7 @@
#include "mozilla/dom/HTMLCollectionBinding.h"
#include "mozilla/dom/HTMLTableElementBinding.h"
#include "nsContentUtils.h"
#include "jsfriendapi.h"
NS_IMPL_NS_NEW_HTML_ELEMENT(Table)
@ -41,7 +42,8 @@ public:
virtual Element*
GetFirstNamedElement(const nsAString& aName, bool& aFound) MOZ_OVERRIDE;
virtual void GetSupportedNames(nsTArray<nsString>& aNames);
virtual void GetSupportedNames(unsigned aFlags,
nsTArray<nsString>& aNames) MOZ_OVERRIDE;
NS_IMETHOD ParentDestroyed();
@ -234,13 +236,18 @@ TableRowsCollection::GetFirstNamedElement(const nsAString& aName, bool& aFound)
}
void
TableRowsCollection::GetSupportedNames(nsTArray<nsString>& aNames)
TableRowsCollection::GetSupportedNames(unsigned aFlags,
nsTArray<nsString>& aNames)
{
if (!(aFlags & JSITER_HIDDEN)) {
return;
}
DO_FOR_EACH_ROWGROUP(
nsTArray<nsString> names;
nsCOMPtr<nsIHTMLCollection> coll = do_QueryInterface(rows);
if (coll) {
coll->GetSupportedNames(names);
coll->GetSupportedNames(aFlags, names);
for (uint32_t i = 0; i < names.Length(); ++i) {
if (!aNames.Contains(names[i])) {
aNames.AppendElement(names[i]);

View File

@ -149,7 +149,7 @@ nsDOMStringMap::NamedDeleter(const nsAString& aProp, bool& found)
}
void
nsDOMStringMap::GetSupportedNames(nsTArray<nsString>& aNames)
nsDOMStringMap::GetSupportedNames(unsigned, nsTArray<nsString>& aNames)
{
uint32_t attrCount = mElement->GetAttrCount();

View File

@ -43,7 +43,7 @@ public:
mozilla::ErrorResult& rv);
void NamedDeleter(const nsAString& aProp, bool &found);
bool NameIsEnumerable(const nsAString& aName);
void GetSupportedNames(nsTArray<nsString>& aNames);
void GetSupportedNames(unsigned, nsTArray<nsString>& aNames);
js::ExpandoAndGeneration mExpandoAndGeneration;

View File

@ -32,14 +32,27 @@ names = [];
for (var name in x) {
names.push(name);
}
is(names.length, 14, "Should have 14 items");
is(names.length, 10, "Should have 10 enumerated names");
is(names[0], "0", "Enum entry 1");
is(names[1], "1", "Enum entry 2");
is(names[2], "2", "Enum entry 3");
is(names[3], "3", "Enum entry 4");
is(names[4], "4", "Enum entry 5");
is(names[5], "something", "Enum entry 6");
is(names[6], "namedItem", "Enum entry 7");
is(names[7], "item", "Enum entry 8");
is(names[8], "@@iterator", "Enum entry 9");
is(names[9], "length", "Enum entry 10");
names = Object.getOwnPropertyNames(x);
is(names.length, 10, "Should have 10 items");
// Now sort entries 5 through 8, for comparison purposes. We don't sort the
// whole array, because we want to make sure the ordering between the parts
// is correct
temp = names.slice(5, 9);
temp.sort();
names.splice.bind(names, 5, 4).apply(null, temp);
is(names.length, 14, "Should have still have 14 items");
is(names.length, 10, "Should still have 10 items");
is(names[0], "0", "Entry 1")
is(names[1], "1", "Entry 2")
is(names[2], "2", "Entry 3")
@ -50,10 +63,6 @@ is(names[6], "x", "Entry 7")
is(names[7], "y", "Entry 8")
is(names[8], "z", "Entry 9")
is(names[9], "something", "Entry 10")
is(names[10], "namedItem", "Entry 11")
is(names[11], "item", "Entry 12")
is(names[12], "@@iterator", "Entry 13")
is(names[13], "length", "Entry 14")
</script>
</pre>
</body>

View File

@ -24,11 +24,23 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=772869
/** Test for Bug 772869 **/
var x = document.getElementsByClassName("foo");
x.something = "another";
names = [];
var names = [];
for (var name in x) {
names.push(name);
}
is(names.length, 13, "Should have 13 items");
is(names.length, 9, "Should have 9 enumerated names");
is(names[0], "0", "Enum entry 1")
is(names[1], "1", "Enum entry 2")
is(names[2], "2", "Enum entry 3")
is(names[3], "3", "Enum entry 4")
is(names[4], "something", "Enum entry 5")
is(names[5], "item", "Enum entry 6")
is(names[6], "namedItem", "Enum entry 7")
is(names[7], "@@iterator", "Enum entry 8")
is(names[8], "length", "Enum entry 9")
names = Object.getOwnPropertyNames(x);
is(names.length, 9, "Should have 9 items");
is(names[0], "0", "Entry 1")
is(names[1], "1", "Entry 2")
is(names[2], "2", "Entry 3")
@ -38,10 +50,6 @@ is(names[5], "y", "Entry 6")
is(names[6], "z", "Entry 7")
is(names[7], "w", "Entry 8")
is(names[8], "something", "Entry 9")
is(names[9], "item", "Entry 10")
is(names[10], "namedItem", "Entry 11")
is(names[11], "@@iterator", "Entry 12")
is(names[12], "length", "Entry 13")
</script>
</pre>
</body>

View File

@ -27,7 +27,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=772869
var opt = $("s").options;
opt.loopy = "something"
var names = Object.getOwnPropertyNames(opt);
is(names.length, 9, "Should have eight entries");
is(names.length, 9, "Should have nine entries");
is(names[0], "0", "Entry 1")
is(names[1], "1", "Entry 2")
is(names[2], "2", "Entry 3")
@ -42,9 +42,19 @@ var names2 = [];
for (var name in opt) {
names2.push(name);
}
for (var i = 0; i < names.length; ++i) {
is(names2[i], names[i], "Correct entry at " + i);
}
is(names2.length, 12, "Should have twelve enumerated names");
is(names2[0], "0", "Enum entry 1")
is(names2[1], "1", "Enum entry 2")
is(names2[2], "2", "Enum entry 3")
is(names2[3], "3", "Enum entry 4")
is(names2[4], "loopy", "Enum entry 5")
is(names2[5], "add", "Enum entrry 6")
is(names2[6], "remove", "Enum entry 7")
is(names2[7], "length", "Enum entry 8")
is(names2[8], "selectedIndex", "Enum entry 9")
is(names2[9], "item", "Enum entry 10")
is(names2[10], "namedItem", "Enum entry 11")
is(names2[11], "@@iterator", "Enum entry 12")
</script>
</pre>

View File

@ -34,11 +34,25 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=772869
/** Test for Bug 772869 **/
var x = $("f").rows;
x.something = "another";
names = [];
var names = [];
for (var name in x) {
names.push(name);
}
is(names.length, 15, "Should have 15 items");
is(names.length, 11, "Should have 11 enumerated names");
is(names[0], "0", "Enum entry 1")
is(names[1], "1", "Enum entry 2")
is(names[2], "2", "Enum entry 3")
is(names[3], "3", "Enum entry 4")
is(names[4], "4", "Enum entry 5")
is(names[5], "5", "Enum entry 6")
is(names[6], "something", "Enum entry 7")
is(names[7], "item", "Enum entry 8")
is(names[8], "namedItem", "Enum entry 9")
is(names[9], "@@iterator", "Enum entry 10")
is(names[10], "length", "Enum entry 11")
names = Object.getOwnPropertyNames(x);
is(names.length, 11, "Should have 11 items");
is(names[0], "0", "Entry 1")
is(names[1], "1", "Entry 2")
is(names[2], "2", "Entry 3")
@ -50,10 +64,6 @@ is(names[7], "y", "Entry 8")
is(names[8], "z", "Entry 9")
is(names[9], "w", "Entry 10")
is(names[10], "something", "Entry 11")
is(names[11], "item", "Entry 12")
is(names[12], "namedItem", "Entry 13")
is(names[13], "@@iterator", "Entry 14")
is(names[14], "length", "Entry 15")
</script>
</pre>
</body>

View File

@ -2282,7 +2282,7 @@ IdentifierMapEntryAddNames(nsIdentifierMapEntry* aEntry, void* aArg)
}
void
nsHTMLDocument::GetSupportedNames(nsTArray<nsString>& aNames)
nsHTMLDocument::GetSupportedNames(unsigned, nsTArray<nsString>& aNames)
{
mIdentifierMap.EnumerateEntries(IdentifierMapEntryAddNames, &aNames);
}

View File

@ -175,7 +175,7 @@ public:
JSObject* NamedGetter(JSContext* cx, const nsAString& aName, bool& aFound,
mozilla::ErrorResult& rv);
bool NameIsEnumerable(const nsAString& aName);
void GetSupportedNames(nsTArray<nsString>& aNames);
void GetSupportedNames(unsigned, nsTArray<nsString>& aNames);
nsGenericHTMLElement *GetBody();
void SetBody(nsGenericHTMLElement* aBody, mozilla::ErrorResult& rv);
mozilla::dom::HTMLSharedElement *GetHead() {

View File

@ -168,9 +168,10 @@ WindowNamedPropertiesHandler::defineProperty(JSContext* aCx,
}
bool
WindowNamedPropertiesHandler::getOwnPropertyNames(JSContext* aCx,
JS::Handle<JSObject*> aProxy,
JS::AutoIdVector& aProps)
WindowNamedPropertiesHandler::ownPropNames(JSContext* aCx,
JS::Handle<JSObject*> aProxy,
unsigned flags,
JS::AutoIdVector& aProps)
{
// Grab the DOM window.
nsGlobalWindow* win = GetWindowFromGlobal(JS_GetGlobalForObject(aCx, aProxy));
@ -186,7 +187,7 @@ WindowNamedPropertiesHandler::getOwnPropertyNames(JSContext* aCx,
return true;
}
nsHTMLDocument* document = static_cast<nsHTMLDocument*>(htmlDoc.get());
document->GetSupportedNames(names);
document->GetSupportedNames(flags, names);
JS::AutoIdVector docProps(aCx);
if (!AppendNamedPropertyIds(aCx, aProxy, names, false, docProps)) {

View File

@ -37,8 +37,8 @@ public:
JS::Handle<jsid> aId,
JS::MutableHandle<JSPropertyDescriptor> aDesc) MOZ_OVERRIDE;
virtual bool
getOwnPropertyNames(JSContext* aCx, JS::Handle<JSObject*> aProxy,
JS::AutoIdVector& aProps) MOZ_OVERRIDE;
ownPropNames(JSContext* aCx, JS::Handle<JSObject*> aProxy, unsigned flags,
JS::AutoIdVector& aProps) MOZ_OVERRIDE;
virtual bool
delete_(JSContext* aCx, JS::Handle<JSObject*> aProxy, JS::Handle<jsid> aId,
bool* aBp) MOZ_OVERRIDE;

View File

@ -188,7 +188,7 @@ nsMimeTypeArray::Length()
}
void
nsMimeTypeArray::GetSupportedNames(nsTArray< nsString >& aRetval)
nsMimeTypeArray::GetSupportedNames(unsigned, nsTArray< nsString >& aRetval)
{
EnsurePluginMimeTypes();

View File

@ -38,7 +38,7 @@ public:
nsMimeType* NamedGetter(const nsAString& name, bool &found);
bool NameIsEnumerable(const nsAString& name);
uint32_t Length();
void GetSupportedNames(nsTArray< nsString >& retval);
void GetSupportedNames(unsigned, nsTArray< nsString >& retval);
protected:
void EnsurePluginMimeTypes();

View File

@ -241,7 +241,7 @@ nsPluginArray::Length()
}
void
nsPluginArray::GetSupportedNames(nsTArray< nsString >& aRetval)
nsPluginArray::GetSupportedNames(unsigned, nsTArray<nsString>& aRetval)
{
aRetval.Clear();
@ -461,7 +461,7 @@ nsPluginElement::Length()
}
void
nsPluginElement::GetSupportedNames(nsTArray< nsString >& retval)
nsPluginElement::GetSupportedNames(unsigned, nsTArray<nsString>& retval)
{
EnsurePluginMimeTypes();

View File

@ -54,7 +54,7 @@ public:
nsPluginElement* NamedGetter(const nsAString& aName, bool &aFound);
bool NameIsEnumerable(const nsAString& aName);
uint32_t Length();
void GetSupportedNames(nsTArray< nsString >& aRetval);
void GetSupportedNames(unsigned, nsTArray<nsString>& aRetval);
private:
bool AllowPlugins() const;
@ -104,7 +104,7 @@ public:
nsMimeType* NamedGetter(const nsAString& name, bool &found);
bool NameIsEnumerable(const nsAString& aName);
uint32_t Length();
void GetSupportedNames(nsTArray< nsString >& retval);
void GetSupportedNames(unsigned, nsTArray<nsString>& retval);
nsTArray<nsRefPtr<nsMimeType> >& MimeTypes();

View File

@ -779,7 +779,7 @@ class CGTemplatedType(CGWrapper):
const = "const " if isConst else ""
pre = "%s%s<" % (const, templateName)
ref = "&" if isReference else ""
post = " >%s" % ref
post = ">%s" % ref
CGWrapper.__init__(self, child, pre=pre, post=post)
@ -8768,7 +8768,8 @@ class CGDOMJSProxyHandler_getOwnPropertyDescriptor(ClassMethod):
Argument('JS::Handle<jsid>', 'id'),
Argument('JS::MutableHandle<JSPropertyDescriptor>', 'desc'),
Argument('unsigned', 'flags')]
ClassMethod.__init__(self, "getOwnPropertyDescriptor", "bool", args)
ClassMethod.__init__(self, "getOwnPropertyDescriptor", "bool", args,
virtual=True, override=True)
self.descriptor = descriptor
def getBody(self):
@ -8955,7 +8956,8 @@ class CGDOMJSProxyHandler_delete(ClassMethod):
args = [Argument('JSContext*', 'cx'), Argument('JS::Handle<JSObject*>', 'proxy'),
Argument('JS::Handle<jsid>', 'id'),
Argument('bool*', 'bp')]
ClassMethod.__init__(self, "delete_", "bool", args)
ClassMethod.__init__(self, "delete_", "bool", args,
virtual=True, override=True)
self.descriptor = descriptor
def getBody(self):
@ -9034,12 +9036,14 @@ return dom::DOMProxyHandler::delete_(cx, proxy, id, bp);"""
return delete
class CGDOMJSProxyHandler_getOwnPropertyNames(ClassMethod):
def __init__(self, descriptor):
class CGDOMJSProxyHandler_ownPropNames(ClassMethod):
def __init__(self, descriptor, ):
args = [Argument('JSContext*', 'cx'),
Argument('JS::Handle<JSObject*>', 'proxy'),
Argument('unsigned', 'flags'),
Argument('JS::AutoIdVector&', 'props')]
ClassMethod.__init__(self, "getOwnPropertyNames", "bool", args)
ClassMethod.__init__(self, "ownPropNames", "bool", args,
virtual=True, override=True)
self.descriptor = descriptor
def getBody(self):
@ -9064,7 +9068,7 @@ for (int32_t i = 0; i < int32_t(length); ++i) {
shadow = "false"
addNames = """
nsTArray<nsString> names;
UnwrapProxy(proxy)->GetSupportedNames(names);
UnwrapProxy(proxy)->GetSupportedNames(flags, names);
if (!AppendNamedPropertyIds(cx, proxy, names, %s, props)) {
return false;
}
@ -9074,7 +9078,7 @@ if (!AppendNamedPropertyIds(cx, proxy, names, %s, props)) {
if UseHolderForUnforgeable(self.descriptor):
addUnforgeable = (
"if (!js::GetPropertyNames(cx, ${holder}, JSITER_OWNONLY | JSITER_HIDDEN, &props)) {\n"
"if (!js::GetPropertyNames(cx, ${holder}, flags, &props)) {\n"
" return false;\n"
"}")
addUnforgeable = CallOnUnforgeableHolder(self.descriptor,
@ -9086,7 +9090,7 @@ if (!AppendNamedPropertyIds(cx, proxy, names, %s, props)) {
""" + addIndices + addUnforgeable + addNames + """
JS::Rooted<JSObject*> expando(cx);
if (!isXray && (expando = DOMProxyHandler::GetExpandoObject(proxy)) &&
!js::GetPropertyNames(cx, expando, JSITER_OWNONLY | JSITER_HIDDEN, &props)) {
!js::GetPropertyNames(cx, expando, flags, &props)) {
return false;
}
@ -9099,7 +9103,8 @@ class CGDOMJSProxyHandler_hasOwn(ClassMethod):
Argument('JS::Handle<JSObject*>', 'proxy'),
Argument('JS::Handle<jsid>', 'id'),
Argument('bool*', 'bp')]
ClassMethod.__init__(self, "hasOwn", "bool", args)
ClassMethod.__init__(self, "hasOwn", "bool", args,
virtual=True, override=True)
self.descriptor = descriptor
def getBody(self):
@ -9162,7 +9167,8 @@ class CGDOMJSProxyHandler_get(ClassMethod):
Argument('JS::Handle<JSObject*>', 'receiver'),
Argument('JS::Handle<jsid>', 'id'),
Argument('JS::MutableHandle<JS::Value>', 'vp')]
ClassMethod.__init__(self, "get", "bool", args)
ClassMethod.__init__(self, "get", "bool", args,
virtual=True, override=True)
self.descriptor = descriptor
def getBody(self):
@ -9257,7 +9263,8 @@ class CGDOMJSProxyHandler_className(ClassMethod):
class CGDOMJSProxyHandler_finalizeInBackground(ClassMethod):
def __init__(self, descriptor):
args = [Argument('JS::Value', 'priv')]
ClassMethod.__init__(self, "finalizeInBackground", "bool", args)
ClassMethod.__init__(self, "finalizeInBackground", "bool", args,
virtual=True, override=True)
self.descriptor = descriptor
def getBody(self):
@ -9267,7 +9274,8 @@ class CGDOMJSProxyHandler_finalizeInBackground(ClassMethod):
class CGDOMJSProxyHandler_finalize(ClassMethod):
def __init__(self, descriptor):
args = [Argument('JSFreeOp*', 'fop'), Argument('JSObject*', 'proxy')]
ClassMethod.__init__(self, "finalize", "void", args)
ClassMethod.__init__(self, "finalize", "void", args,
virtual=True, override=True)
self.descriptor = descriptor
def getBody(self):
@ -9343,7 +9351,7 @@ class CGDOMJSProxyHandler(CGClass):
CGDOMJSProxyHandler_defineProperty(descriptor),
ClassUsingDeclaration("mozilla::dom::DOMProxyHandler",
"defineProperty"),
CGDOMJSProxyHandler_getOwnPropertyNames(descriptor),
CGDOMJSProxyHandler_ownPropNames(descriptor),
CGDOMJSProxyHandler_hasOwn(descriptor),
CGDOMJSProxyHandler_get(descriptor),
CGDOMJSProxyHandler_className(descriptor),
@ -11138,7 +11146,11 @@ class CGBindingImplClass(CGClass):
"GetSupportedNames",
(IDLSequenceType(None,
BuiltinTypes[IDLBuiltinType.Types.domstring]),
[]),
# Let's use unsigned long for the type here, though really
# it's just a C++ "unsigned"...
[FakeArgument(BuiltinTypes[IDLBuiltinType.Types.unsigned_long],
FakeMember(),
name="aFlags")]),
{"infallible": True}))
self.methodDecls.append(
CGNativeMember(

View File

@ -234,7 +234,7 @@ BaseDOMProxyHandler::enumerate(JSContext* cx, JS::Handle<JSObject*> proxy,
if (!JS_GetPrototype(cx, proxy, &proto)) {
return false;
}
return getOwnPropertyNames(cx, proxy, props) &&
return keys(cx, proxy, props) &&
(!proto || js::GetPropertyNames(cx, proto, 0, &props));
}
@ -251,6 +251,22 @@ BaseDOMProxyHandler::unwatch(JSContext* cx, JS::Handle<JSObject*> proxy, JS::Han
return js::UnwatchGuts(cx, proxy, id);
}
bool
BaseDOMProxyHandler::getOwnPropertyNames(JSContext* cx,
JS::Handle<JSObject*> proxy,
JS::AutoIdVector& props)
{
return ownPropNames(cx, proxy, JSITER_OWNONLY | JSITER_HIDDEN, props);
}
bool
BaseDOMProxyHandler::keys(JSContext* cx,
JS::Handle<JSObject*> proxy,
JS::AutoIdVector& props)
{
return ownPropNames(cx, proxy, JSITER_OWNONLY, props);
}
bool
DOMProxyHandler::has(JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id, bool* bp)
{

View File

@ -57,6 +57,22 @@ public:
JS::Handle<JSObject*> callable) MOZ_OVERRIDE;
bool unwatch(JSContext* cx, JS::Handle<JSObject*> proxy,
JS::Handle<jsid> id) MOZ_OVERRIDE;
virtual bool getOwnPropertyNames(JSContext* cx, JS::Handle<JSObject*> proxy,
JS::AutoIdVector &props) MOZ_OVERRIDE;
// We override keys() and implement it directly instead of using the
// default implementation, which would getOwnPropertyNames and then
// filter out the non-enumerable ones. This avoids doing
// unnecessary work during enumeration.
virtual bool keys(JSContext* cx, JS::Handle<JSObject*> proxy,
JS::AutoIdVector &props) MOZ_OVERRIDE;
protected:
// Hook for subclasses to implement shared getOwnPropertyNames()/keys()
// functionality. The "flags" argument is either JSITER_OWNONLY (for keys())
// or JSITER_OWNONLY | JSITER_HIDDEN (for getOwnPropertyNames()).
virtual bool ownPropNames(JSContext* cx, JS::Handle<JSObject*> proxy,
unsigned flags,
JS::AutoIdVector& props) = 0;
};
class DOMProxyHandler : public BaseDOMProxyHandler

View File

@ -990,7 +990,7 @@ public:
void NamedGetter(const nsAString&, bool&, nsAString&);
bool NameIsEnumerable(const nsAString&);
void GetSupportedNames(nsTArray<nsString>&);
void GetSupportedNames(unsigned, nsTArray<nsString>&);
};
class TestIndexedGetterAndSetterAndNamedGetterInterface : public nsISupports,
@ -1004,7 +1004,7 @@ public:
void NamedGetter(const nsAString&, bool&, nsAString&);
bool NameIsEnumerable(const nsAString&);
void GetSupportedNames(nsTArray<nsString>&);
void GetSupportedNames(unsigned, nsTArray<nsString>&);
int32_t IndexedGetter(uint32_t, bool&);
void IndexedSetter(uint32_t, int32_t);
uint32_t Length();
@ -1024,7 +1024,7 @@ public:
bool NameIsEnumerable(const nsAString&);
void NamedItem(const nsAString&, nsAString&);
uint32_t Length();
void GetSupportedNames(nsTArray<nsString>&);
void GetSupportedNames(unsigned, nsTArray<nsString>&);
};
class TestIndexedSetterInterface : public nsISupports,
@ -1054,7 +1054,7 @@ public:
void NamedSetter(const nsAString&, TestIndexedSetterInterface&);
TestIndexedSetterInterface* NamedGetter(const nsAString&, bool&);
bool NameIsEnumerable(const nsAString&);
void GetSupportedNames(nsTArray<nsString>&);
void GetSupportedNames(unsigned, nsTArray<nsString>&);
};
class TestIndexedAndNamedSetterInterface : public nsISupports,
@ -1073,7 +1073,7 @@ public:
TestIndexedSetterInterface* NamedGetter(const nsAString&, bool&);
bool NameIsEnumerable(const nsAString&);
void SetNamedItem(const nsAString&, TestIndexedSetterInterface&);
void GetSupportedNames(nsTArray<nsString>&);
void GetSupportedNames(unsigned, nsTArray<nsString>&);
};
class TestIndexedAndNamedGetterAndSetterInterface : public TestIndexedSetterInterface
@ -1089,7 +1089,7 @@ public:
void NamedSetter(const nsAString&, const nsAString&);
void Stringify(nsAString&);
uint32_t Length();
void GetSupportedNames(nsTArray<nsString>&);
void GetSupportedNames(unsigned, nsTArray<nsString>&);
};
class TestCppKeywordNamedMethodsInterface : public nsISupports,
@ -1152,7 +1152,7 @@ public:
void NamedDeleter(const nsAString&, bool&);
long NamedGetter(const nsAString&, bool&);
bool NameIsEnumerable(const nsAString&);
void GetSupportedNames(nsTArray<nsString>&);
void GetSupportedNames(unsigned, nsTArray<nsString>&);
};
class TestNamedDeleterWithRetvalInterface : public nsISupports,
@ -1170,7 +1170,7 @@ public:
bool NameIsEnumerable(const nsAString&);
bool DelNamedItem(const nsAString&);
bool DelNamedItem(const nsAString&, bool&) MOZ_DELETE;
void GetSupportedNames(nsTArray<nsString>&);
void GetSupportedNames(unsigned, nsTArray<nsString>&);
};
class TestIndexedAndNamedDeleterInterface : public nsISupports,
@ -1192,7 +1192,7 @@ public:
bool NameIsEnumerable(const nsAString&);
void DelNamedItem(const nsAString&);
void DelNamedItem(const nsAString&, bool&) MOZ_DELETE;
void GetSupportedNames(nsTArray<nsString>&);
void GetSupportedNames(unsigned, nsTArray<nsString>&);
};
class TestParentInterface : public nsISupports,

View File

@ -14,4 +14,27 @@ test(function() {
assert_equals(typeof desc, "object", "Should have a 'log' property");
assert_false(desc.enumerable, "'log' property should not be enumerable");
}, "Correct getOwnPropertyDescriptor behavior");
test(function() {
var list = document.getElementsByTagName("div");
props = [];
for (var prop in list) {
props.push(prop);
}
assert_not_equals(props.indexOf("0"), -1, "Should enumerate '0'");
assert_equals(props.indexOf("log"), -1, "Should not enumerate 'log'");
}, "Correct enumeration behavior");
test(function() {
var list = document.getElementsByTagName("div");
props = Object.keys(list)
assert_not_equals(props.indexOf("0"), -1, "Keys should contain '0'");
assert_equals(props.indexOf("log"), -1, "Keys should not contain 'log'");
}, "Correct keys() behavior");
test(function() {
var list = document.getElementsByTagName("div");
props = Object.getOwnPropertyNames(list)
assert_not_equals(props.indexOf("0"), -1,
"own prop names should contain '0'");
assert_not_equals(props.indexOf("log"), -1,
"own prop names should contain 'log'");
}, "Correct getOwnPropertyNames() behavior");
</script>

View File

@ -20,6 +20,8 @@ test(function() {
result.push(p);
}
}
assert_array_equals(result, ['0', '1', '2']);
result = Object.getOwnPropertyNames(list);
assert_array_equals(result, ['0', '1', '2', 'foo']);
});
</script>

View File

@ -580,7 +580,7 @@ nsTreeColumns::GetNamedColumn(const nsAString& aId, nsITreeColumn** _retval)
}
void
nsTreeColumns::GetSupportedNames(nsTArray<nsString>& aNames)
nsTreeColumns::GetSupportedNames(unsigned, nsTArray<nsString>& aNames)
{
for (nsTreeColumn* currCol = mFirstColumn; currCol; currCol = currCol->GetNext()) {
aNames.AppendElement(currCol->GetId());

View File

@ -159,7 +159,7 @@ public:
nsTreeColumn* NamedGetter(const nsAString& aId, bool& aFound);
bool NameIsEnumerable(const nsAString& aName);
nsTreeColumn* GetNamedColumn(const nsAString& aId);
void GetSupportedNames(nsTArray<nsString>& aNames);
void GetSupportedNames(unsigned, nsTArray<nsString>& aNames);
// Uses XPCOM InvalidateColumns().
// Uses XPCOM RestoreNaturalOrder().