OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2013 Google Inc. All rights reserved. | 2 * Copyright (C) 2013 Google Inc. All rights reserved. |
3 * | 3 * |
4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are |
6 * met: | 6 * met: |
7 * | 7 * |
8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright |
9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
10 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
62 { | 62 { |
63 ASSERT(m_context == v8::Isolate::GetCurrent()->GetCurrentContext()); | 63 ASSERT(m_context == v8::Isolate::GetCurrent()->GetCurrentContext()); |
64 } | 64 } |
65 | 65 |
66 bool CustomElementConstructorBuilder::isFeatureAllowed() const | 66 bool CustomElementConstructorBuilder::isFeatureAllowed() const |
67 { | 67 { |
68 // Check that we are in the main world | 68 // Check that we are in the main world |
69 return !DOMWrapperWorld::isolatedWorld(m_context); | 69 return !DOMWrapperWorld::isolatedWorld(m_context); |
70 } | 70 } |
71 | 71 |
72 bool CustomElementConstructorBuilder::validateOptions(const AtomicString& type,
ExceptionState& es) | 72 bool CustomElementConstructorBuilder::validateOptions(const AtomicString& type,
QualifiedName& tagName, ExceptionState& es) |
73 { | 73 { |
74 ASSERT(m_prototype.IsEmpty()); | 74 ASSERT(m_prototype.IsEmpty()); |
75 | 75 |
76 ScriptValue prototypeScriptValue; | 76 ScriptValue prototypeScriptValue; |
77 if (m_options->get("prototype", prototypeScriptValue)) { | 77 if (m_options->get("prototype", prototypeScriptValue) && !prototypeScriptVal
ue.isNull()) { |
78 m_prototype = prototypeScriptValue.v8Value().As<v8::Object>(); | 78 m_prototype = prototypeScriptValue.v8Value().As<v8::Object>(); |
79 if (m_prototype.IsEmpty()) { | 79 if (m_prototype.IsEmpty()) { |
80 CustomElementException::throwException(CustomElementException::Proto
typeNotAnObject, type, es); | 80 CustomElementException::throwException(CustomElementException::Proto
typeNotAnObject, type, es); |
81 return false; | 81 return false; |
82 } | 82 } |
83 } else { | 83 } else { |
84 m_prototype = v8::Object::New(); | 84 m_prototype = v8::Object::New(); |
85 m_prototype->SetPrototype(V8PerContextData::from(m_context)->prototypeFo
rType(&V8HTMLElement::info)); | 85 v8::Local<v8::Object> basePrototype = V8PerContextData::from(m_context)-
>prototypeForType(&V8HTMLElement::info); |
| 86 if (!basePrototype.IsEmpty()) |
| 87 m_prototype->SetPrototype(basePrototype); |
86 } | 88 } |
87 | 89 |
| 90 String extends; |
| 91 bool extendsProvidedAndNonNull = m_options->get("extends", extends); |
| 92 |
88 if (!V8PerContextData::from(m_context)) { | 93 if (!V8PerContextData::from(m_context)) { |
89 // FIXME: This should generate an InvalidContext exception at a later po
int. | 94 // FIXME: This should generate an InvalidContext exception at a later po
int. |
90 CustomElementException::throwException(CustomElementException::ContextDe
stroyedCheckingPrototype, type, es); | 95 CustomElementException::throwException(CustomElementException::ContextDe
stroyedCheckingPrototype, type, es); |
91 return false; | 96 return false; |
92 } | 97 } |
93 if (hasValidPrototypeChainFor(&V8HTMLElement::info)) { | 98 |
94 m_namespaceURI = HTMLNames::xhtmlNamespaceURI; | 99 AtomicString namespaceURI = HTMLNames::xhtmlNamespaceURI; |
95 return true; | 100 if (hasValidPrototypeChainFor(&V8SVGElement::info)) |
96 } | 101 namespaceURI = SVGNames::svgNamespaceURI; |
97 if (hasValidPrototypeChainFor(&V8SVGElement::info)) { | 102 |
98 m_namespaceURI = SVGNames::svgNamespaceURI; | 103 AtomicString localName; |
99 return true; | 104 |
100 } | 105 if (extendsProvidedAndNonNull) { |
101 if (hasValidPrototypeChainFor(&V8Element::info)) { | 106 localName = extends.lower(); |
102 m_namespaceURI = nullAtom; | 107 |
103 // This generates a different DOM exception, so we feign success for now
. | 108 if (!Document::isValidName(localName)) { |
104 return true; | 109 CustomElementException::throwException(CustomElementException::Exten
dsIsInvalidName, type, es); |
| 110 return false; |
| 111 } |
| 112 if (CustomElement::isValidName(localName)) { |
| 113 CustomElementException::throwException(CustomElementException::Exten
dsIsCustomElementName, type, es); |
| 114 return false; |
| 115 } |
| 116 } else { |
| 117 localName = type; |
105 } | 118 } |
106 | 119 |
107 CustomElementException::throwException(CustomElementException::PrototypeDoes
NotExtendHTMLElementSVGElementPrototype, type, es); | 120 if (!extendsProvidedAndNonNull) |
108 return false; | 121 m_wrapperType = &V8HTMLElement::info; |
109 } | 122 else if (namespaceURI == HTMLNames::xhtmlNamespaceURI) |
| 123 m_wrapperType = findWrapperTypeForHTMLTagName(localName); |
| 124 else |
| 125 m_wrapperType = findWrapperTypeForSVGTagName(localName); |
110 | 126 |
111 bool CustomElementConstructorBuilder::findTagName(const AtomicString& customElem
entType, QualifiedName& tagName) | 127 ASSERT(m_wrapperType); |
112 { | 128 tagName = QualifiedName(nullAtom, localName, namespaceURI); |
113 ASSERT(!m_prototype.IsEmpty()); | 129 return m_wrapperType; |
114 | |
115 m_wrapperType = findWrapperType(m_prototype); | |
116 if (!m_wrapperType) { | |
117 // Invalid prototype. | |
118 return false; | |
119 } | |
120 | |
121 if (const QualifiedName* htmlName = findHTMLTagNameOfV8Type(m_wrapperType))
{ | |
122 ASSERT(htmlName->namespaceURI() == m_namespaceURI); | |
123 tagName = *htmlName; | |
124 return true; | |
125 } | |
126 | |
127 if (const QualifiedName* svgName = findSVGTagNameOfV8Type(m_wrapperType)) { | |
128 ASSERT(svgName->namespaceURI() == m_namespaceURI); | |
129 tagName = *svgName; | |
130 return true; | |
131 } | |
132 | |
133 if (m_namespaceURI != nullAtom) { | |
134 // Use the custom element type as the tag's local name. | |
135 tagName = QualifiedName(nullAtom, customElementType, m_namespaceURI); | |
136 return true; | |
137 } | |
138 | |
139 return false; | |
140 } | 130 } |
141 | 131 |
142 PassRefPtr<CustomElementLifecycleCallbacks> CustomElementConstructorBuilder::cre
ateCallbacks() | 132 PassRefPtr<CustomElementLifecycleCallbacks> CustomElementConstructorBuilder::cre
ateCallbacks() |
143 { | 133 { |
144 ASSERT(!m_prototype.IsEmpty()); | 134 ASSERT(!m_prototype.IsEmpty()); |
145 | 135 |
146 RefPtr<ScriptExecutionContext> scriptExecutionContext(toScriptExecutionConte
xt(m_context)); | 136 RefPtr<ScriptExecutionContext> scriptExecutionContext(toScriptExecutionConte
xt(m_context)); |
147 | 137 |
148 v8::TryCatch exceptionCatcher; | 138 v8::TryCatch exceptionCatcher; |
149 exceptionCatcher.SetVerbose(true); | 139 exceptionCatcher.SetVerbose(true); |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
238 ASSERT(!m_constructor.IsEmpty()); | 228 ASSERT(!m_constructor.IsEmpty()); |
239 | 229 |
240 return m_callbacks->setBinding(definition, CustomElementBinding::create(m_co
ntext->GetIsolate(), m_prototype, m_wrapperType)); | 230 return m_callbacks->setBinding(definition, CustomElementBinding::create(m_co
ntext->GetIsolate(), m_prototype, m_wrapperType)); |
241 } | 231 } |
242 | 232 |
243 ScriptValue CustomElementConstructorBuilder::bindingsReturnValue() const | 233 ScriptValue CustomElementConstructorBuilder::bindingsReturnValue() const |
244 { | 234 { |
245 return ScriptValue(m_constructor); | 235 return ScriptValue(m_constructor); |
246 } | 236 } |
247 | 237 |
248 WrapperTypeInfo* CustomElementConstructorBuilder::findWrapperType(v8::Handle<v8:
:Value> chain) | |
249 { | |
250 while (!chain.IsEmpty() && chain->IsObject()) { | |
251 v8::Handle<v8::Object> chainObject = chain.As<v8::Object>(); | |
252 // Only prototype objects of native-backed types have the extra internal
field storing WrapperTypeInfo. | |
253 if (v8PrototypeInternalFieldcount == chainObject->InternalFieldCount())
{ | |
254 WrapperTypeInfo* wrapperType = reinterpret_cast<WrapperTypeInfo*>(ch
ainObject->GetAlignedPointerFromInternalField(v8PrototypeTypeIndex)); | |
255 ASSERT(wrapperType); | |
256 return wrapperType; | |
257 } | |
258 chain = chainObject->GetPrototype(); | |
259 } | |
260 | |
261 return 0; | |
262 } | |
263 | |
264 bool CustomElementConstructorBuilder::hasValidPrototypeChainFor(WrapperTypeInfo*
type) const | 238 bool CustomElementConstructorBuilder::hasValidPrototypeChainFor(WrapperTypeInfo*
type) const |
265 { | 239 { |
266 v8::Handle<v8::Object> elementPrototype = V8PerContextData::from(m_context)-
>prototypeForType(type); | 240 v8::Handle<v8::Object> elementPrototype = V8PerContextData::from(m_context)-
>prototypeForType(type); |
267 if (elementPrototype.IsEmpty()) | 241 if (elementPrototype.IsEmpty()) |
268 return false; | 242 return false; |
269 | 243 |
270 v8::Handle<v8::Value> chain = m_prototype; | 244 v8::Handle<v8::Value> chain = m_prototype; |
271 while (!chain.IsEmpty() && chain->IsObject()) { | 245 while (!chain.IsEmpty() && chain->IsObject()) { |
272 if (chain == elementPrototype) | 246 if (chain == elementPrototype) |
273 return true; | 247 return true; |
(...skipping 25 matching lines...) Expand all Loading... |
299 | 273 |
300 ExceptionState es(args.GetIsolate()); | 274 ExceptionState es(args.GetIsolate()); |
301 CustomElementCallbackDispatcher::CallbackDeliveryScope deliveryScope; | 275 CustomElementCallbackDispatcher::CallbackDeliveryScope deliveryScope; |
302 RefPtr<Element> element = document->createElementNS(namespaceURI, tagName, m
aybeType->IsNull() ? nullAtom : type, es); | 276 RefPtr<Element> element = document->createElementNS(namespaceURI, tagName, m
aybeType->IsNull() ? nullAtom : type, es); |
303 if (es.throwIfNeeded()) | 277 if (es.throwIfNeeded()) |
304 return; | 278 return; |
305 v8SetReturnValueFast(args, element.release(), document); | 279 v8SetReturnValueFast(args, element.release(), document); |
306 } | 280 } |
307 | 281 |
308 } // namespace WebCore | 282 } // namespace WebCore |
OLD | NEW |