JSHTMLElementCustom.cpp [plain text]
#include "config.h"
#include "JSHTMLElement.h"
#include "CustomElementRegistry.h"
#include "DOMWindow.h"
#include "Document.h"
#include "HTMLFormElement.h"
#include "JSCustomElementInterface.h"
#include "JSNodeCustom.h"
#include "ScriptExecutionContext.h"
#include <runtime/InternalFunction.h>
#include <runtime/JSWithScope.h>
namespace WebCore {
using namespace JSC;
EncodedJSValue JSC_HOST_CALL constructJSHTMLElement(ExecState& exec)
{
VM& vm = exec.vm();
auto scope = DECLARE_THROW_SCOPE(vm);
auto* jsConstructor = jsCast<DOMConstructorObject*>(exec.jsCallee());
ASSERT(jsConstructor);
auto* context = jsConstructor->scriptExecutionContext();
if (!context)
return throwConstructorScriptExecutionContextUnavailableError(exec, scope, "HTMLElement");
ASSERT(context->isDocument());
JSValue newTargetValue = exec.thisValue();
auto* globalObject = jsConstructor->globalObject();
JSValue htmlElementConstructorValue = JSHTMLElement::getConstructor(vm, globalObject);
if (newTargetValue == htmlElementConstructorValue)
return throwVMTypeError(&exec, scope, ASCIILiteral("new.target is not a valid custom element constructor"));
auto& document = downcast<Document>(*context);
auto* window = document.domWindow();
if (!window)
return throwVMTypeError(&exec, scope, ASCIILiteral("new.target is not a valid custom element constructor"));
auto* registry = window->customElementRegistry();
if (!registry)
return throwVMTypeError(&exec, scope, ASCIILiteral("new.target is not a valid custom element constructor"));
JSObject* newTarget = newTargetValue.getObject();
auto* elementInterface = registry->findInterface(newTarget);
if (!elementInterface)
return throwVMTypeError(&exec, scope, ASCIILiteral("new.target does not define a custom element"));
if (!elementInterface->isUpgradingElement()) {
Structure* baseStructure = getDOMStructure<JSHTMLElement>(vm, *globalObject);
auto* newElementStructure = InternalFunction::createSubclassStructure(&exec, newTargetValue, baseStructure);
RETURN_IF_EXCEPTION(scope, encodedJSValue());
Ref<HTMLElement> element = HTMLElement::create(elementInterface->name(), document);
element->setIsDefinedCustomElement(*elementInterface);
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, scope, ASCIILiteral("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);
RETURN_IF_EXCEPTION(scope, encodedJSValue());
JSObject* elementWrapperObject = asObject(elementWrapperValue);
JSObject::setPrototype(elementWrapperObject, &exec, newPrototype, true );
RETURN_IF_EXCEPTION(scope, encodedJSValue());
elementInterface->didUpgradeLastElementInConstructionStack();
return JSValue::encode(elementWrapperValue);
}
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);
}
}