OLD | NEW |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "bindings/core/v8/ScriptCustomElementDefinitionBuilder.h" | 5 #include "bindings/core/v8/ScriptCustomElementDefinitionBuilder.h" |
6 | 6 |
7 #include "bindings/core/v8/DOMWrapperWorld.h" | 7 #include "bindings/core/v8/DOMWrapperWorld.h" |
8 #include "bindings/core/v8/ExceptionState.h" | 8 #include "bindings/core/v8/ExceptionState.h" |
9 #include "bindings/core/v8/ScriptCustomElementDefinition.h" | 9 #include "bindings/core/v8/ScriptCustomElementDefinition.h" |
10 #include "bindings/core/v8/ScriptState.h" | 10 #include "bindings/core/v8/ScriptState.h" |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
74 continue; | 74 continue; |
75 } | 75 } |
76 m_exceptionState.throwDOMException( | 76 m_exceptionState.throwDOMException( |
77 NotSupportedError, | 77 NotSupportedError, |
78 "this constructor is already being defined in this registry"); | 78 "this constructor is already being defined in this registry"); |
79 return false; | 79 return false; |
80 } | 80 } |
81 return true; | 81 return true; |
82 } | 82 } |
83 | 83 |
| 84 bool ScriptCustomElementDefinitionBuilder::valueForName( |
| 85 const v8::Local<v8::Object>& object, const String& name, |
| 86 v8::Local<v8::Value>& value) const |
| 87 { |
| 88 v8::Isolate* isolate = m_scriptState->isolate(); |
| 89 v8::Local<v8::Context> context = m_scriptState->context(); |
| 90 v8::Local<v8::String> nameString = v8String(isolate, name); |
| 91 v8::TryCatch tryCatch(isolate); |
| 92 if (!v8Call(object->Get(context, nameString), value, tryCatch)) { |
| 93 m_exceptionState.rethrowV8Exception(tryCatch.Exception()); |
| 94 return false; |
| 95 } |
| 96 return true; |
| 97 } |
| 98 |
84 bool ScriptCustomElementDefinitionBuilder::checkPrototype() | 99 bool ScriptCustomElementDefinitionBuilder::checkPrototype() |
85 { | 100 { |
86 v8::Isolate* isolate = m_scriptState->isolate(); | |
87 v8::Local<v8::Context> context = m_scriptState->context(); | |
88 v8::Local<v8::String> prototypeString = | |
89 v8AtomicString(isolate, "prototype"); | |
90 v8::Local<v8::Value> prototypeValue; | 101 v8::Local<v8::Value> prototypeValue; |
91 if (!v8Call( | 102 if (!valueForName(m_constructor, "prototype", prototypeValue)) |
92 m_constructor->Get(context, prototypeString), prototypeValue)) { | |
93 return false; | 103 return false; |
94 } | |
95 if (!prototypeValue->IsObject()) { | 104 if (!prototypeValue->IsObject()) { |
96 m_exceptionState.throwTypeError( | 105 m_exceptionState.throwTypeError( |
97 "constructor prototype is not an object"); | 106 "constructor prototype is not an object"); |
98 return false; | 107 return false; |
99 } | 108 } |
100 m_prototype = prototypeValue.As<v8::Object>(); | 109 m_prototype = prototypeValue.As<v8::Object>(); |
101 // If retrieving the prototype destroyed the context, indicate that | 110 // If retrieving the prototype destroyed the context, indicate that |
102 // defining the element should not proceed. | 111 // defining the element should not proceed. |
103 return true; | 112 return true; |
104 } | 113 } |
105 | 114 |
| 115 bool ScriptCustomElementDefinitionBuilder::callableForName(const String& name, |
| 116 v8::Local<v8::Object>& callback) const |
| 117 { |
| 118 v8::Local<v8::Value> value; |
| 119 if (!valueForName(m_prototype, name, value)) |
| 120 return false; |
| 121 // "undefined" means "omitted", so return true. |
| 122 if (value->IsUndefined()) |
| 123 return true; |
| 124 if (!value->IsObject()) { |
| 125 m_exceptionState.throwTypeError( |
| 126 String::format("\"%s\" is not an object", name.ascii().data())); |
| 127 return false; |
| 128 } |
| 129 callback = value.As<v8::Object>(); |
| 130 if (!callback->IsCallable()) { |
| 131 m_exceptionState.throwTypeError( |
| 132 String::format("\"%s\" is not callable", name.ascii().data())); |
| 133 return false; |
| 134 } |
| 135 return true; |
| 136 } |
| 137 |
| 138 bool ScriptCustomElementDefinitionBuilder::retrieveObservedAttributes() |
| 139 { |
| 140 const String kObservedAttributes = "observedAttributes"; |
| 141 v8::Local<v8::Value> observedAttributesValue; |
| 142 if (!valueForName(m_constructor, kObservedAttributes, observedAttributesValu
e)) |
| 143 return false; |
| 144 if (observedAttributesValue->IsUndefined()) |
| 145 return true; |
| 146 Vector<AtomicString> list = toImplArray<Vector<AtomicString>>( |
| 147 observedAttributesValue, 0, m_scriptState->isolate(), m_exceptionState); |
| 148 if (m_exceptionState.hadException()) |
| 149 return false; |
| 150 if (list.isEmpty()) |
| 151 return true; |
| 152 m_observedAttributes.reserveCapacityForSize(list.size()); |
| 153 for (const auto& attribute : list) |
| 154 m_observedAttributes.add(attribute); |
| 155 return true; |
| 156 } |
| 157 |
| 158 bool ScriptCustomElementDefinitionBuilder::rememberOriginalProperties() |
| 159 { |
| 160 // Spec requires to use values of these properties at the point |
| 161 // CustomElementDefinition is built, even if JS changes them afterwards. |
| 162 const String kConnectedCallback = "connectedCallback"; |
| 163 const String kDisconnectedCallback = "disconnectedCallback"; |
| 164 const String kAttributeChangedCallback = "attributeChangedCallback"; |
| 165 return retrieveObservedAttributes() |
| 166 && callableForName(kConnectedCallback, m_connectedCallback) |
| 167 && callableForName(kDisconnectedCallback, m_disconnectedCallback) |
| 168 && callableForName(kAttributeChangedCallback, m_attributeChangedCallback
); |
| 169 } |
| 170 |
106 CustomElementDefinition* ScriptCustomElementDefinitionBuilder::build( | 171 CustomElementDefinition* ScriptCustomElementDefinitionBuilder::build( |
107 const CustomElementDescriptor& descriptor) | 172 const CustomElementDescriptor& descriptor) |
108 { | 173 { |
109 return ScriptCustomElementDefinition::create( | 174 return ScriptCustomElementDefinition::create( |
110 m_scriptState.get(), | 175 m_scriptState.get(), |
111 m_registry, | 176 m_registry, |
112 descriptor, | 177 descriptor, |
113 m_constructor, | 178 m_constructor, |
114 m_prototype); | 179 m_prototype, |
| 180 m_connectedCallback, |
| 181 m_disconnectedCallback, |
| 182 m_attributeChangedCallback, |
| 183 m_observedAttributes); |
115 } | 184 } |
116 | 185 |
117 } // namespace blink | 186 } // namespace blink |
OLD | NEW |