Chromium Code Reviews| 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 |