| Index: third_party/WebKit/Source/bindings/core/v8/V8HTMLConstructor.cpp
|
| diff --git a/third_party/WebKit/Source/bindings/core/v8/V8HTMLConstructor.cpp b/third_party/WebKit/Source/bindings/core/v8/V8HTMLConstructor.cpp
|
| index 61c510dfcedf60697fed258683bf9d166488be92..54e4050ec43f8ee80b1efdb1c168d1dd71316b52 100644
|
| --- a/third_party/WebKit/Source/bindings/core/v8/V8HTMLConstructor.cpp
|
| +++ b/third_party/WebKit/Source/bindings/core/v8/V8HTMLConstructor.cpp
|
| @@ -2,6 +2,8 @@
|
| // Use of this source code is governed by a BSD-style license that can be
|
| // found in the LICENSE file.
|
|
|
| +#include "bindings/core/v8/V8HTMLConstructor.h"
|
| +
|
| #include "bindings/core/v8/DOMWrapperWorld.h"
|
| #include "bindings/core/v8/ExceptionState.h"
|
| #include "bindings/core/v8/ScriptCustomElementDefinition.h"
|
| @@ -9,6 +11,7 @@
|
| #include "bindings/core/v8/V8BindingMacros.h"
|
| #include "bindings/core/v8/V8DOMWrapper.h"
|
| #include "bindings/core/v8/V8HTMLElement.h"
|
| +#include "bindings/core/v8/V8PerContextData.h"
|
| #include "bindings/core/v8/V8ThrowException.h"
|
| #include "core/dom/Document.h"
|
| #include "core/dom/Element.h"
|
| @@ -19,13 +22,18 @@
|
|
|
| namespace blink {
|
|
|
| -void V8HTMLElement::HTMLConstructor(
|
| - const v8::FunctionCallbackInfo<v8::Value>& info) {
|
| +// https://html.spec.whatwg.org/multipage/dom.html#html-element-constructors
|
| +void V8HTMLConstructor::htmlConstructor(
|
| + const v8::FunctionCallbackInfo<v8::Value>& info,
|
| + const WrapperTypeInfo& wrapperTypeInfo,
|
| + const HTMLElementType elementInterfaceName) {
|
| DCHECK(info.IsConstructCall());
|
|
|
| v8::Isolate* isolate = info.GetIsolate();
|
| ScriptState* scriptState = ScriptState::current(isolate);
|
| + v8::Local<v8::Value> newTarget = info.NewTarget();
|
|
|
| + // Behind runtime enabled flag
|
| if (!RuntimeEnabledFeatures::customElementsV1Enabled() ||
|
| !scriptState->world().isMainWorld()) {
|
| V8ThrowException::throwTypeError(info.GetIsolate(), "Illegal constructor");
|
| @@ -33,17 +41,75 @@ void V8HTMLElement::HTMLConstructor(
|
| }
|
|
|
| LocalDOMWindow* window = scriptState->domWindow();
|
| + CustomElementRegistry* registry = window->customElements();
|
| +
|
| + // 2. If NewTarget is equal to the active function object, throw a TypeError
|
| + v8::Local<v8::Function> activeFunctionObject =
|
| + scriptState->perContextData()->constructorForType(&wrapperTypeInfo);
|
| + if (newTarget->Equals(activeFunctionObject)) {
|
| + V8ThrowException::throwTypeError(isolate, "Illegal constructor");
|
| + return;
|
| + }
|
| +
|
| + // 3. Let definition be the entry in registry with constructor equal to
|
| + // NewTarget.
|
| + // If there is no such definition, then throw a TypeError and abort these
|
| + // steps.
|
| ScriptCustomElementDefinition* definition =
|
| - ScriptCustomElementDefinition::forConstructor(
|
| - scriptState, window->customElements(), info.NewTarget());
|
| + ScriptCustomElementDefinition::forConstructor(scriptState, registry,
|
| + newTarget);
|
| if (!definition) {
|
| V8ThrowException::throwTypeError(isolate, "Illegal constructor");
|
| return;
|
| }
|
|
|
| - ExceptionState exceptionState(ExceptionState::ConstructionContext,
|
| - "HTMLElement", info.Holder(), isolate);
|
| + const AtomicString& localName = definition->descriptor().localName();
|
| + const AtomicString& name = definition->descriptor().name();
|
| +
|
| + if (localName == name) {
|
| + // Autonomous custom element
|
| + // 4.1. If the active function object is not HTMLElement, then throw a
|
| + // TypeError
|
| + if (!V8HTMLElement::wrapperTypeInfo.equals(&wrapperTypeInfo)) {
|
| + V8ThrowException::throwTypeError(isolate,
|
| + "Illegal constructor: autonomous custom "
|
| + "elements must extend HTMLElement");
|
| + return;
|
| + }
|
| + } else {
|
| + // Customized built-in element
|
| + // 5. If local name is not valid for interface, throw TypeError
|
| + if (htmlElementTypeForTag(localName) != elementInterfaceName) {
|
| + V8ThrowException::throwTypeError(isolate,
|
| + "Illegal constructor: localName does "
|
| + "not match the HTML element interface");
|
| + return;
|
| + }
|
| + }
|
| +
|
| + ExceptionState exceptionState(isolate, ExceptionState::ConstructionContext,
|
| + "HTMLConstructor");
|
| + v8::TryCatch tryCatch(isolate);
|
| +
|
| + // 6. Let prototype be Get(NewTarget, "prototype"). Rethrow any exceptions.
|
| + v8::Local<v8::String> nameString = v8AtomicString(isolate, "prototype");
|
| + v8::Local<v8::Value> prototypeValue;
|
| + if (!v8Call(
|
| + newTarget.As<v8::Object>()->Get(scriptState->context(), nameString),
|
| + prototypeValue, tryCatch)) {
|
| + exceptionState.rethrowV8Exception(tryCatch.Exception());
|
| + return;
|
| + }
|
| +
|
| + // 7. If Type(prototype) is not Object...
|
| + if (!prototypeValue->IsObject()) {
|
| + v8::Local<v8::Context> context =
|
| + newTarget.As<v8::Object>()->CreationContext();
|
| + V8PerContextData* perContextData = V8PerContextData::from(context);
|
| + prototypeValue = perContextData->prototypeForType(&wrapperTypeInfo);
|
| + }
|
|
|
| + // 8. If definition's construction stack is empty...
|
| Element* element;
|
| if (definition->constructionStack().isEmpty()) {
|
| // This is an element being created with 'new' from script
|
| @@ -69,8 +135,6 @@ void V8HTMLElement::HTMLConstructor(
|
| // instead.
|
| v8SetReturnValue(info, wrapper);
|
|
|
| - wrapper->SetPrototype(scriptState->context(), definition->prototype())
|
| - .ToChecked();
|
| + wrapper->SetPrototype(scriptState->context(), prototypeValue).ToChecked();
|
| }
|
| -
|
| } // namespace blink
|
|
|