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..09a30c07531378d8160cdc2527ff2133ea9d6105 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,73 @@ 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 |
+ v8::Local<v8::Function> htmlElement = |
dominicc (has gone to gerrit)
2016/10/21 02:30:07
I think the spec is not referring to any particula
|
+ scriptState->perContextData()->constructorForType( |
+ &V8HTMLElement::wrapperTypeInfo); |
+ if (activeFunctionObject != htmlElement) { |
+ V8ThrowException::throwTypeError(isolate, "Illegal constructor"); |
dominicc (has gone to gerrit)
2016/10/21 02:30:07
You want to return at this point! The algorithm is
|
+ } |
+ } 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"); |
+ 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 +133,6 @@ void V8HTMLElement::HTMLConstructor( |
// instead. |
v8SetReturnValue(info, wrapper); |
- wrapper->SetPrototype(scriptState->context(), definition->prototype()) |
- .ToChecked(); |
+ wrapper->SetPrototype(scriptState->context(), prototypeValue).ToChecked(); |
} |
- |
} // namespace blink |