From bbb717ec12e63be39929806f62a603bdb4f61de9 Mon Sep 17 00:00:00 2001 From: Gaming4JC Date: Sun, 5 Jan 2020 10:32:30 -0500 Subject: Bug 1299363 - Part 5-1: Make the constructor created by document.registerElement() also works with construction stack. So that the old upgrade can also work with new upgrade steps which will be implemented in part 5-2. Tag UXP Issue #1344 --- dom/base/CustomElementRegistry.cpp | 34 -------------------- dom/base/nsDocument.cpp | 63 ++++++++++++++++++++++++++++++++------ 2 files changed, 54 insertions(+), 43 deletions(-) (limited to 'dom') diff --git a/dom/base/CustomElementRegistry.cpp b/dom/base/CustomElementRegistry.cpp index 1c1e3d6ae..ce2e4b04f 100644 --- a/dom/base/CustomElementRegistry.cpp +++ b/dom/base/CustomElementRegistry.cpp @@ -799,40 +799,6 @@ CustomElementRegistry::Upgrade(Element* aElement, MOZ_ASSERT(aElement->IsHTMLElement(aDefinition->mLocalName)); - AutoJSAPI jsapi; - if (NS_WARN_IF(!jsapi.Init(mWindow))) { - return; - } - - JSContext* cx = jsapi.cx(); - - JS::Rooted reflector(cx, aElement->GetWrapper()); - if (reflector) { - Maybe ac; - JS::Rooted prototype(cx, aDefinition->mPrototype); - if (aElement->NodePrincipal()->SubsumesConsideringDomain(nsContentUtils::ObjectPrincipal(prototype))) { - ac.emplace(cx, reflector); - if (!JS_WrapObject(cx, &prototype) || - !JS_SetPrototype(cx, reflector, prototype)) { - return; - } - } else { - // We want to set the custom prototype in the compartment where it was - // registered. We store the prototype from define() without unwrapped, - // hence the prototype's compartment is the compartment where it was - // registered. - // In the case that |reflector| and |prototype| are in different - // compartments, this will set the prototype on the |reflector|'s wrapper - // and thus only visible in the wrapper's compartment, since we know - // reflector's principal does not subsume prototype's in this case. - ac.emplace(cx, prototype); - if (!JS_WrapObject(cx, &reflector) || - !JS_SetPrototype(cx, reflector, prototype)) { - return; - } - } - } - EnqueueLifecycleCallback(nsIDocument::eCreated, aElement, nullptr, aDefinition); } diff --git a/dom/base/nsDocument.cpp b/dom/base/nsDocument.cpp index a0857faf8..602da421a 100644 --- a/dom/base/nsDocument.cpp +++ b/dom/base/nsDocument.cpp @@ -5670,19 +5670,64 @@ nsDocument::CustomElementConstructor(JSContext* aCx, unsigned aArgc, JS::Value* return true; } - nsDependentAtomString localName(definition->mLocalName); + RefPtr element; + + // We integrate with construction stack and do prototype swizzling here, so + // that old upgrade behavior could also share the new upgrade steps. + // And this old upgrade will be remove at some point (when everything is + // switched to latest custom element spec). + nsTArray>& constructionStack = + definition->mConstructionStack; + if (constructionStack.Length()) { + element = constructionStack.LastElement(); + NS_ENSURE_TRUE(element != ALEADY_CONSTRUCTED_MARKER, false); + + // Do prototype swizzling if dom reflector exists. + JS::Rooted reflector(aCx, element->GetWrapper()); + if (reflector) { + Maybe ac; + JS::Rooted prototype(aCx, definition->mPrototype); + if (element->NodePrincipal()->SubsumesConsideringDomain(nsContentUtils::ObjectPrincipal(prototype))) { + ac.emplace(aCx, reflector); + if (!JS_WrapObject(aCx, &prototype) || + !JS_SetPrototype(aCx, reflector, prototype)) { + return false; + } + } else { + // We want to set the custom prototype in the compartment where it was + // registered. We store the prototype from define() without unwrapped, + // hence the prototype's compartment is the compartment where it was + // registered. + // In the case that |reflector| and |prototype| are in different + // compartments, this will set the prototype on the |reflector|'s wrapper + // and thus only visible in the wrapper's compartment, since we know + // reflector's principal does not subsume prototype's in this case. + ac.emplace(aCx, prototype); + if (!JS_WrapObject(aCx, &reflector) || + !JS_SetPrototype(aCx, reflector, prototype)) { + return false; + } + } - nsCOMPtr element = - document->CreateElem(localName, nullptr, kNameSpaceID_XHTML); - NS_ENSURE_TRUE(element, true); + // Wrap into current context. + if (!JS_WrapObject(aCx, &reflector)) { + return false; + } - if (definition->mLocalName != typeAtom) { - // This element is a custom element by extension, thus we need to - // do some special setup. For non-extended custom elements, this happens - // when the element is created. - nsContentUtils::SetupCustomElement(element, &elemName); + args.rval().setObject(*reflector); + return true; + } + } else { + nsDependentAtomString localName(definition->mLocalName); + element = + document->CreateElem(localName, nullptr, kNameSpaceID_XHTML, + (definition->mLocalName != typeAtom) ? &elemName + : nullptr); + NS_ENSURE_TRUE(element, false); } + // The prototype setup happens in Element::WrapObject(). + nsresult rv = nsContentUtils::WrapNative(aCx, element, element, args.rval()); NS_ENSURE_SUCCESS(rv, true); -- cgit v1.2.3