JSHTMLElementCustom.cpp [plain text]
#include "config.h"
#include "JSHTMLElement.h"
#include "CustomElementDefinitions.h"
#include "Document.h"
#include "HTMLFormElement.h"
#include "JSNodeCustom.h"
#include <runtime/InternalFunction.h>
#include <runtime/JSWithScope.h>
namespace WebCore {
using namespace JSC;
#if ENABLE(CUSTOM_ELEMENTS)
EncodedJSValue JSC_HOST_CALL constructJSHTMLElement(ExecState& exec)
{
auto* jsConstructor = jsCast<DOMConstructorObject*>(exec.callee());
auto* context = jsConstructor->scriptExecutionContext();
if (!is<Document>(context))
return throwConstructorDocumentUnavailableError(exec, "HTMLElement");
auto& document = downcast<Document>(*context);
auto* definitions = document.customElementDefinitions();
if (!definitions)
return throwVMTypeError(&exec, "new.target is not a valid custom element constructor");
VM& vm = exec.vm();
JSValue newTargetValue = exec.thisValue();
JSObject* newTarget = newTargetValue.getObject();
auto* elementInterface = definitions->findInterface(newTarget);
if (!elementInterface)
return throwVMTypeError(&exec, "new.target does not define a custom element");
if (!elementInterface->isUpgradingElement()) {
auto* globalObject = jsConstructor->globalObject();
Structure* baseStructure = getDOMStructure<JSHTMLElement>(vm, *globalObject);
auto* newElementStructure = InternalFunction::createSubclassStructure(&exec, newTargetValue, baseStructure);
if (UNLIKELY(exec.hadException()))
return JSValue::encode(jsUndefined());
Ref<HTMLElement> element = HTMLElement::create(elementInterface->name(), document);
element->setIsUnresolvedCustomElement();
auto* jsElement = JSHTMLElement::create(newElementStructure, globalObject, element.get());
cacheWrapper(globalObject->world(), element.ptr(), jsElement);
return JSValue::encode(jsElement);
}
Element* elementToUpgrade = elementInterface->lastElementInConstructionStack();
if (!elementToUpgrade) {
throwInvalidStateError(exec, "Cannot instantiate a custom element inside its own constrcutor during upgrades");
return JSValue::encode(jsUndefined());
}
JSValue elementWrapperValue = toJS(&exec, jsConstructor->globalObject(), *elementToUpgrade);
ASSERT(elementWrapperValue.isObject());
JSValue newPrototype = newTarget->get(&exec, vm.propertyNames->prototype);
if (exec.hadException())
return JSValue::encode(jsUndefined());
JSObject* elementWrapperObject = asObject(elementWrapperValue);
JSObject::setPrototype(elementWrapperObject, &exec, newPrototype, true );
if (exec.hadException())
return JSValue::encode(jsUndefined());
elementInterface->didUpgradeLastElementInConstructionStack();
return JSValue::encode(elementWrapperValue);
}
#endif
JSScope* JSHTMLElement::pushEventHandlerScope(ExecState* exec, JSScope* scope) const
{
HTMLElement& element = wrapped();
VM& vm = exec->vm();
JSGlobalObject* lexicalGlobalObject = exec->lexicalGlobalObject();
scope = JSWithScope::create(vm, lexicalGlobalObject, asObject(toJS(exec, globalObject(), element.document())), scope);
if (HTMLFormElement* form = element.form())
scope = JSWithScope::create(vm, lexicalGlobalObject, asObject(toJS(exec, globalObject(), *form)), scope);
return JSWithScope::create(vm, lexicalGlobalObject, asObject(toJS(exec, globalObject(), element)), scope);
}
}