mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-05 23:38:38 +09:00
parent
31b26a24e3
commit
cedff6e214
28 changed files with 82 additions and 879 deletions
|
|
@ -5352,31 +5352,6 @@ bool IsLowercaseASCII(const nsAString& aValue)
|
|||
return true;
|
||||
}
|
||||
|
||||
already_AddRefed<mozilla::dom::CustomElementRegistry>
|
||||
nsDocument::GetCustomElementRegistry()
|
||||
{
|
||||
nsAutoString contentType;
|
||||
GetContentType(contentType);
|
||||
if (!IsHTMLDocument() &&
|
||||
!contentType.EqualsLiteral("application/xhtml+xml")) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsPIDOMWindowInner> window(
|
||||
do_QueryInterface(mScriptGlobalObject ? mScriptGlobalObject
|
||||
: GetScopeObject()));
|
||||
if (!window) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<CustomElementRegistry> registry = window->CustomElements();
|
||||
if (!registry) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return registry.forget();
|
||||
}
|
||||
|
||||
// We only support pseudo-elements with two colons in this function.
|
||||
static CSSPseudoElementType
|
||||
GetPseudoElementType(const nsString& aString, ErrorResult& aRv)
|
||||
|
|
@ -5692,103 +5667,6 @@ nsIDocument::CreateAttributeNS(const nsAString& aNamespaceURI,
|
|||
return attribute.forget();
|
||||
}
|
||||
|
||||
bool
|
||||
nsDocument::CustomElementConstructor(JSContext* aCx, unsigned aArgc, JS::Value* aVp)
|
||||
{
|
||||
JS::CallArgs args = JS::CallArgsFromVp(aArgc, aVp);
|
||||
|
||||
JS::Rooted<JSObject*> global(aCx,
|
||||
JS_GetGlobalForObject(aCx, &args.callee()));
|
||||
RefPtr<nsGlobalWindow> window;
|
||||
UNWRAP_OBJECT(Window, global, window);
|
||||
MOZ_ASSERT(window, "Should have a non-null window");
|
||||
|
||||
nsDocument* document = static_cast<nsDocument*>(window->GetDoc());
|
||||
|
||||
// Function name is the type of the custom element.
|
||||
JSString* jsFunName =
|
||||
JS_GetFunctionId(JS_ValueToFunction(aCx, args.calleev()));
|
||||
nsAutoJSString elemName;
|
||||
if (!elemName.init(aCx, jsFunName)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
RefPtr<mozilla::dom::CustomElementRegistry> registry = window->CustomElements();
|
||||
if (!registry) {
|
||||
return true;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIAtom> typeAtom(NS_Atomize(elemName));
|
||||
CustomElementDefinition* definition =
|
||||
registry->mCustomDefinitions.GetWeak(typeAtom);
|
||||
if (!definition) {
|
||||
return true;
|
||||
}
|
||||
|
||||
RefPtr<Element> 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<RefPtr<nsGenericHTMLElement>>& 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<JSObject*> reflector(aCx, element->GetWrapper());
|
||||
if (reflector) {
|
||||
Maybe<JSAutoCompartment> ac;
|
||||
JS::Rooted<JSObject*> 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;
|
||||
}
|
||||
}
|
||||
|
||||
// Wrap into current context.
|
||||
if (!JS_WrapObject(aCx, &reflector)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
nsDocument::IsWebComponentsEnabled(JSContext* aCx, JSObject* aObject)
|
||||
{
|
||||
|
|
@ -5842,131 +5720,6 @@ nsDocument::IsWebComponentsEnabled(nsPIDOMWindowInner* aWindow)
|
|||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
nsDocument::RegisterElement(JSContext* aCx, const nsAString& aType,
|
||||
const ElementRegistrationOptions& aOptions,
|
||||
JS::MutableHandle<JSObject*> aRetval,
|
||||
ErrorResult& rv)
|
||||
{
|
||||
RefPtr<CustomElementRegistry> registry(GetCustomElementRegistry());
|
||||
if (!registry) {
|
||||
rv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
|
||||
return;
|
||||
}
|
||||
|
||||
AutoCEReaction ceReaction(this->GetDocGroup()->CustomElementReactionsStack(),
|
||||
aCx);
|
||||
// Unconditionally convert TYPE to lowercase.
|
||||
nsAutoString lcType;
|
||||
nsContentUtils::ASCIIToLower(aType, lcType);
|
||||
|
||||
nsIGlobalObject* sgo = GetScopeObject();
|
||||
if (!sgo) {
|
||||
rv.Throw(NS_ERROR_UNEXPECTED);
|
||||
return;
|
||||
}
|
||||
|
||||
JS::Rooted<JSObject*> global(aCx, sgo->GetGlobalJSObject());
|
||||
JS::Rooted<JSObject*> protoObject(aCx);
|
||||
|
||||
if (!aOptions.mPrototype) {
|
||||
JS::Rooted<JSObject*> htmlProto(aCx);
|
||||
htmlProto = HTMLElementBinding::GetProtoObjectHandle(aCx);
|
||||
if (!htmlProto) {
|
||||
rv.Throw(NS_ERROR_OUT_OF_MEMORY);
|
||||
return;
|
||||
}
|
||||
|
||||
protoObject = JS_NewObjectWithGivenProto(aCx, nullptr, htmlProto);
|
||||
if (!protoObject) {
|
||||
rv.Throw(NS_ERROR_UNEXPECTED);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
protoObject = aOptions.mPrototype;
|
||||
|
||||
// Get the unwrapped prototype to do some checks.
|
||||
JS::Rooted<JSObject*> protoObjectUnwrapped(aCx, js::CheckedUnwrap(protoObject));
|
||||
if (!protoObjectUnwrapped) {
|
||||
// If the caller's compartment does not have permission to access the
|
||||
// unwrapped prototype then throw.
|
||||
rv.Throw(NS_ERROR_DOM_SECURITY_ERR);
|
||||
return;
|
||||
}
|
||||
|
||||
// If PROTOTYPE is already an interface prototype object for any interface
|
||||
// object or PROTOTYPE has a non-configurable property named constructor,
|
||||
// throw a NotSupportedError and stop.
|
||||
const js::Class* clasp = js::GetObjectClass(protoObjectUnwrapped);
|
||||
if (IsDOMIfaceAndProtoClass(clasp)) {
|
||||
rv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
|
||||
return;
|
||||
}
|
||||
|
||||
JS::Rooted<JS::PropertyDescriptor> descRoot(aCx);
|
||||
JS::MutableHandle<JS::PropertyDescriptor> desc(&descRoot);
|
||||
// This check may go through a wrapper, but as we checked above
|
||||
// it should be transparent or an xray. This should be fine for now,
|
||||
// until the spec is sorted out.
|
||||
if (!JS_GetPropertyDescriptor(aCx, protoObject, "constructor", desc)) {
|
||||
rv.Throw(NS_ERROR_UNEXPECTED);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!desc.configurable()) {
|
||||
rv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
JS::Rooted<JSFunction*> constructor(aCx);
|
||||
{
|
||||
// Go into the document's global compartment when creating the constructor
|
||||
// function because we want to get the correct document (where the
|
||||
// definition is registered) when it is called.
|
||||
JSAutoCompartment ac(aCx, global);
|
||||
|
||||
// Create constructor to return. Store the name of the custom element as the
|
||||
// name of the function.
|
||||
constructor = JS_NewFunction(aCx, nsDocument::CustomElementConstructor, 0,
|
||||
JSFUN_CONSTRUCTOR,
|
||||
NS_ConvertUTF16toUTF8(lcType).get());
|
||||
if (!constructor) {
|
||||
rv.Throw(NS_ERROR_OUT_OF_MEMORY);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
JS::Rooted<JSObject*> wrappedConstructor(aCx);
|
||||
wrappedConstructor = JS_GetFunctionObject(constructor);
|
||||
if (!JS_WrapObject(aCx, &wrappedConstructor)) {
|
||||
rv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!JS_LinkConstructorAndPrototype(aCx, wrappedConstructor, protoObject)) {
|
||||
rv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
|
||||
return;
|
||||
}
|
||||
|
||||
ElementDefinitionOptions options;
|
||||
if (!aOptions.mExtends.IsVoid()) {
|
||||
// Only convert NAME to lowercase in HTML documents.
|
||||
nsAutoString lcName;
|
||||
IsHTMLDocument() ? nsContentUtils::ASCIIToLower(aOptions.mExtends, lcName)
|
||||
: lcName.Assign(aOptions.mExtends);
|
||||
|
||||
options.mExtends.Construct(lcName);
|
||||
}
|
||||
|
||||
RootedCallback<OwningNonNull<binding_detail::FastFunction>> functionConstructor(aCx);
|
||||
functionConstructor = new binding_detail::FastFunction(aCx, wrappedConstructor, sgo);
|
||||
|
||||
registry->Define(lcType, functionConstructor, options, rv);
|
||||
|
||||
aRetval.set(wrappedConstructor);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDocument::GetElementsByTagName(const nsAString& aTagname,
|
||||
nsIDOMNodeList** aReturn)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue