Bug 1274159 - Part 1: Support looking up definitions by using constructor as a key;

Tag UXP Issue #1344
This commit is contained in:
Gaming4JC 2020-01-02 21:24:22 -05:00 • committed by Roy Tam
commit 516fe49cb2
5 changed files with 50 additions and 36 deletions

View file

@ -103,6 +103,7 @@ NS_IMPL_CYCLE_COLLECTION_CLASS(CustomElementRegistry)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(CustomElementRegistry) NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(CustomElementRegistry)
tmp->mCustomDefinitions.Clear(); tmp->mCustomDefinitions.Clear();
tmp->mConstructors.clear();
NS_IMPL_CYCLE_COLLECTION_UNLINK(mWhenDefinedPromiseMap) NS_IMPL_CYCLE_COLLECTION_UNLINK(mWhenDefinedPromiseMap)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mWindow) NS_IMPL_CYCLE_COLLECTION_UNLINK(mWindow)
NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
@ -149,6 +150,11 @@ NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(CustomElementRegistry)
"mCustomDefinitions prototype", "mCustomDefinitions prototype",
aClosure); aClosure);
} }
for (ConstructorMap::Enum iter(tmp->mConstructors); !iter.empty(); iter.popFront()) {
aCallbacks.Trace(&iter.front().mutableKey(),
"mConstructors key",
aClosure);
}
NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
NS_IMPL_CYCLE_COLLECTION_TRACE_END NS_IMPL_CYCLE_COLLECTION_TRACE_END
@ -183,6 +189,11 @@ CustomElementRegistry::Create(nsPIDOMWindowInner* aWindow)
RefPtr<CustomElementRegistry> customElementRegistry = RefPtr<CustomElementRegistry> customElementRegistry =
new CustomElementRegistry(aWindow); new CustomElementRegistry(aWindow);
if (!customElementRegistry->Init()) {
return nullptr;
}
return customElementRegistry.forget(); return customElementRegistry.forget();
} }
@ -241,6 +252,12 @@ CustomElementRegistry::~CustomElementRegistry()
mozilla::DropJSObjects(this); mozilla::DropJSObjects(this);
} }
bool
CustomElementRegistry::Init()
{
return mConstructors.init();
}
CustomElementDefinition* CustomElementDefinition*
CustomElementRegistry::LookupCustomElementDefinition(const nsAString& aLocalName, CustomElementRegistry::LookupCustomElementDefinition(const nsAString& aLocalName,
const nsAString* aIs) const const nsAString* aIs) const
@ -609,9 +626,13 @@ CustomElementRegistry::Define(const nsAString& aName,
* 4. If this CustomElementRegistry contains an entry with constructor constructor, * 4. If this CustomElementRegistry contains an entry with constructor constructor,
* then throw a "NotSupportedError" DOMException and abort these steps. * then throw a "NotSupportedError" DOMException and abort these steps.
*/ */
// TODO: Step 3 of HTMLConstructor also needs a way to look up definition by const auto& ptr = mConstructors.lookup(constructorUnwrapped);
// using constructor. So I plans to figure out a solution to support both of if (ptr) {
// them in bug 1274159. MOZ_ASSERT(mCustomDefinitions.Get(ptr->value()),
"Definition must be found in mCustomDefinitions");
aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
return;
}
/** /**
* 5. Let localName be name. * 5. Let localName be name.
@ -767,8 +788,16 @@ CustomElementRegistry::Define(const nsAString& aName,
/** /**
* 12. Add definition to this CustomElementRegistry. * 12. Add definition to this CustomElementRegistry.
*/ */
if (!mConstructors.put(constructorUnwrapped, nameAtom)) {
aRv.Throw(NS_ERROR_FAILURE);
return;
}
mCustomDefinitions.Put(nameAtom, definition); mCustomDefinitions.Put(nameAtom, definition);
MOZ_ASSERT(mCustomDefinitions.Count() == mConstructors.count(),
"Number of entries should be the same");
/** /**
* 13. 14. 15. Upgrade candidates * 13. 14. 15. Upgrade candidates
*/ */
@ -853,4 +882,4 @@ CustomElementDefinition::CustomElementDefinition(nsIAtom* aType,
} }
} // namespace dom } // namespace dom
} // namespace mozilla } // namespace mozilla

View file

@ -7,13 +7,14 @@
#ifndef mozilla_dom_CustomElementRegistry_h #ifndef mozilla_dom_CustomElementRegistry_h
#define mozilla_dom_CustomElementRegistry_h #define mozilla_dom_CustomElementRegistry_h
#include "js/GCHashTable.h"
#include "js/TypeDecls.h" #include "js/TypeDecls.h"
#include "mozilla/Attributes.h" #include "mozilla/Attributes.h"
#include "mozilla/ErrorResult.h" #include "mozilla/ErrorResult.h"
#include "mozilla/dom/BindingDeclarations.h" #include "mozilla/dom/BindingDeclarations.h"
#include "mozilla/dom/FunctionBinding.h"
#include "nsCycleCollectionParticipant.h" #include "nsCycleCollectionParticipant.h"
#include "nsWrapperCache.h" #include "nsWrapperCache.h"
#include "mozilla/dom/FunctionBinding.h"
class nsDocument; class nsDocument;
@ -173,6 +174,8 @@ private:
explicit CustomElementRegistry(nsPIDOMWindowInner* aWindow); explicit CustomElementRegistry(nsPIDOMWindowInner* aWindow);
~CustomElementRegistry(); ~CustomElementRegistry();
bool Init();
/** /**
* Registers an unresolved custom element that is a candidate for * Registers an unresolved custom element that is a candidate for
* upgrade when the definition is registered via registerElement. * upgrade when the definition is registered via registerElement.
@ -192,15 +195,25 @@ private:
DefinitionMap; DefinitionMap;
typedef nsClassHashtable<nsISupportsHashKey, nsTArray<nsWeakPtr>> typedef nsClassHashtable<nsISupportsHashKey, nsTArray<nsWeakPtr>>
CandidateMap; CandidateMap;
typedef JS::GCHashMap<JS::Heap<JSObject*>,
nsCOMPtr<nsIAtom>,
js::MovableCellHasher<JS::Heap<JSObject*>>,
js::SystemAllocPolicy> ConstructorMap;
// Hashtable for custom element definitions in web components. // Hashtable for custom element definitions in web components.
// Custom prototypes are stored in the compartment where // Custom prototypes are stored in the compartment where
// registerElement was called. // registerElement was called.
DefinitionMap mCustomDefinitions; DefinitionMap mCustomDefinitions;
// Hashtable for looking up definitions by using constructor as key.
// Custom elements' name are stored here and we need to lookup
// mCustomDefinitions again to get definitions.
ConstructorMap mConstructors;
typedef nsRefPtrHashtable<nsISupportsHashKey, Promise> typedef nsRefPtrHashtable<nsISupportsHashKey, Promise>
WhenDefinedPromiseMap; WhenDefinedPromiseMap;
WhenDefinedPromiseMap mWhenDefinedPromiseMap; WhenDefinedPromiseMap mWhenDefinedPromiseMap;
// The "upgrade candidates map" from the web components spec. Maps from a // The "upgrade candidates map" from the web components spec. Maps from a
// namespace id and local name to a list of elements to upgrade if that // namespace id and local name to a list of elements to upgrade if that
// element is registered as a custom element. // element is registered as a custom element.

View file

@ -20,11 +20,12 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=560072
/** Test for Bug 560072 **/ /** Test for Bug 560072 **/
is(document.body, is(document.body,
Object.getOwnPropertyDescriptor(HTMLDocument.prototype, "body").get.call(document), Object.getOwnPropertyDescriptor(Document.prototype, "body").get.call(document),
"Should get body out of property descriptor"); "Should get body out of property descriptor");
is(document.body, is(document.body,
Object.getOwnPropertyDescriptor(Object.getPrototypeOf(document), "body").get.call(document), Object.getOwnPropertyDescriptor(
Object.getPrototypeOf(Object.getPrototypeOf(document)), "body").get.call(document),
"Should get body out of property descriptor this way too"); "Should get body out of property descriptor this way too");
</script> </script>

View file

@ -1,8 +1,5 @@
[CustomElementRegistry.html] [CustomElementRegistry.html]
type: testharness type: testharness
[customElements.define must throw a NotSupportedError when there is already a custom element with the same class]
expected: FAIL
[customElements.define must get callbacks of the constructor prototype] [customElements.define must get callbacks of the constructor prototype]
expected: FAIL expected: FAIL

View file

@ -1,26 +0,0 @@
[define.html]
type: testharness
[If constructor is HTMLElement, should throw a TypeError]
expected: FAIL
[If constructor is HTMLButtonElement, should throw a TypeError]
expected: FAIL
[If constructor is HTMLImageElement, should throw a TypeError]
expected: FAIL
[If constructor is HTMLMediaElement, should throw a TypeError]
expected: FAIL
[If constructor is Image, should throw a TypeError]
expected: FAIL
[If constructor is Audio, should throw a TypeError]
expected: FAIL
[If constructor is Option, should throw a TypeError]
expected: FAIL
[If the constructor is already defined, should throw a NotSupportedError]
expected: FAIL