| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2012 Google Inc. All rights reserved. | 2 * Copyright (C) 2012 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 16 matching lines...) Expand all Loading... |
| 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 29 */ | 29 */ |
| 30 | 30 |
| 31 #include "config.h" | 31 #include "config.h" |
| 32 | 32 |
| 33 #include "bindings/v8/CustomElementHelpers.h" | 33 #include "bindings/v8/CustomElementHelpers.h" |
| 34 | 34 |
| 35 #include "HTMLNames.h" | 35 #include "HTMLNames.h" |
| 36 #include "SVGNames.h" | 36 #include "SVGNames.h" |
| 37 #include "V8CustomElementConstructor.h" | 37 #include "V8Document.h" |
| 38 #include "V8HTMLElementWrapperFactory.h" | 38 #include "V8HTMLElementWrapperFactory.h" |
| 39 #include "V8SVGElementWrapperFactory.h" | 39 #include "V8SVGElementWrapperFactory.h" |
| 40 #include "bindings/v8/DOMDataStore.h" | 40 #include "bindings/v8/DOMDataStore.h" |
| 41 #include "bindings/v8/DOMWrapperWorld.h" | 41 #include "bindings/v8/DOMWrapperWorld.h" |
| 42 #include "bindings/v8/ScriptController.h" | 42 #include "bindings/v8/ScriptController.h" |
| 43 #include "bindings/v8/ScriptState.h" |
| 43 #include "bindings/v8/UnsafePersistent.h" | 44 #include "bindings/v8/UnsafePersistent.h" |
| 45 #include "bindings/v8/V8HiddenPropertyName.h" |
| 44 #include "bindings/v8/V8PerContextData.h" | 46 #include "bindings/v8/V8PerContextData.h" |
| 45 #include "core/dom/CustomElementRegistry.h" | 47 #include "core/dom/CustomElementRegistry.h" |
| 48 #include "core/dom/Element.h" |
| 49 #include "core/dom/ExceptionCode.h" |
| 46 #include "core/dom/Node.h" | 50 #include "core/dom/Node.h" |
| 47 #include "core/html/HTMLElement.h" | 51 #include "core/html/HTMLElement.h" |
| 48 #include "core/html/HTMLUnknownElement.h" | 52 #include "core/html/HTMLUnknownElement.h" |
| 49 #include "core/svg/SVGElement.h" | 53 #include "core/svg/SVGElement.h" |
| 50 | 54 |
| 51 namespace WebCore { | 55 namespace WebCore { |
| 52 | 56 |
| 53 void CustomElementHelpers::didRegisterDefinition(CustomElementDefinition* defini
tion, ScriptExecutionContext* executionContext, const HashSet<Element*>& upgrade
Candidates, const ScriptValue& prototypeValue) | 57 void CustomElementHelpers::didRegisterDefinition(CustomElementDefinition* defini
tion, ScriptExecutionContext* executionContext, const HashSet<Element*>& upgrade
Candidates, const ScriptValue& prototypeValue) |
| 54 { | 58 { |
| 55 ASSERT(v8::Isolate::GetCurrent()); | 59 ASSERT(v8::Isolate::GetCurrent()); |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 131 else { | 135 else { |
| 132 ASSERT(0); | 136 ASSERT(0); |
| 133 return v8::Handle<v8::Object>(); | 137 return v8::Handle<v8::Object>(); |
| 134 } | 138 } |
| 135 } else { | 139 } else { |
| 136 // It's a type extension | 140 // It's a type extension |
| 137 return createTypeExtensionUpgradeCandidateWrapper.invoke(element.get(),
creationContext, isolate); | 141 return createTypeExtensionUpgradeCandidateWrapper.invoke(element.get(),
creationContext, isolate); |
| 138 } | 142 } |
| 139 } | 143 } |
| 140 | 144 |
| 141 bool CustomElementHelpers::initializeConstructorWrapper(CustomElementConstructor
* constructor, const ScriptValue& prototype, ScriptState* state) | 145 static void constructCustomElement(const v8::FunctionCallbackInfo<v8::Value>& ar
gs) |
| 142 { | 146 { |
| 143 ASSERT(isFeatureAllowed(state)); | 147 v8::Isolate* isolate = args.GetIsolate(); |
| 144 ASSERT(!prototype.v8Value().IsEmpty() && prototype.v8Value()->IsObject()); | |
| 145 v8::Handle<v8::Value> wrapperValue = toV8(constructor, state->context()->Glo
bal(), state->context()->GetIsolate()); | |
| 146 if (wrapperValue.IsEmpty() || !wrapperValue->IsObject()) | |
| 147 return false; | |
| 148 v8::Handle<v8::Function> wrapper = v8::Handle<v8::Function>::Cast(wrapperVal
ue); | |
| 149 // - Object::ForceSet() nor Object::SetAccessor Doesn't work against the "pr
ototype" property of function objects. | |
| 150 // - Set()-ing here is safe because | |
| 151 // - Hooking Object.prototype's defineProperty() with "prototype" or "cons
tructor" also doesn't affect on these properties of function objects and | |
| 152 // - Using Set() is okay becaues each function has "prototype" property fr
om start and Objects.prototype cannot intercept the property access. | |
| 153 v8::Handle<v8::String> prototypeKey = v8String("prototype", state->context()
->GetIsolate()); | |
| 154 ASSERT(wrapper->HasOwnProperty(prototypeKey)); | |
| 155 wrapper->Set(prototypeKey, prototype.v8Value(), v8::ReadOnly); | |
| 156 | 148 |
| 157 v8::Handle<v8::String> constructorKey = v8String("constructor", state->conte
xt()->GetIsolate()); | 149 if (!args.IsConstructCall()) { |
| 158 v8::Handle<v8::Object> prototypeObject = v8::Handle<v8::Object>::Cast(protot
ype.v8Value()); | 150 throwTypeError("DOM object constructor cannot be called as a function.",
isolate); |
| 159 ASSERT(!prototypeObject->HasOwnProperty(constructorKey)); | 151 return; |
| 160 prototypeObject->ForceSet(constructorKey, wrapper, v8::ReadOnly); | 152 } |
| 161 return true; | 153 |
| 154 if (args.Length() > 0) { |
| 155 throwTypeError(0, isolate); |
| 156 return; |
| 157 } |
| 158 |
| 159 Document* document = V8Document::toNative(v8::Handle<v8::Object>::Cast(args.
Callee()->GetHiddenValue(V8HiddenPropertyName::document()))); |
| 160 V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<>, namespaceURI, args.
Callee()->GetHiddenValue(V8HiddenPropertyName::namespaceURI())); |
| 161 V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<>, name, args.Callee()
->GetHiddenValue(V8HiddenPropertyName::name())); |
| 162 v8::Handle<v8::Value> maybeType = args.Callee()->GetHiddenValue(V8HiddenProp
ertyName::type()); |
| 163 V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<>, type, maybeType); |
| 164 |
| 165 ExceptionCode ec = 0; |
| 166 CustomElementRegistry::CallbackDeliveryScope deliveryScope; |
| 167 RefPtr<Element> element = document->createElementNS(namespaceURI, name, mayb
eType->IsNull() ? nullAtom : type, ec); |
| 168 if (ec) { |
| 169 setDOMException(ec, isolate); |
| 170 return; |
| 171 } |
| 172 v8SetReturnValue(args, toV8Fast(element.release(), args, document)); |
| 173 } |
| 174 |
| 175 ScriptValue CustomElementHelpers::createConstructor(ScriptState* state, const Sc
riptValue& prototypeValue, Document* document, const AtomicString& namespaceURI,
const AtomicString& name, const AtomicString& type) |
| 176 { |
| 177 v8::Isolate* isolate = state->isolate(); |
| 178 |
| 179 v8::HandleScope handleScope; |
| 180 v8::TryCatch tryCatch; |
| 181 v8::Local<v8::FunctionTemplate> constructorTemplate = v8::FunctionTemplate::
New(); |
| 182 constructorTemplate->SetCallHandler(constructCustomElement); |
| 183 v8::Handle<v8::Function> constructor = constructorTemplate->GetFunction(); |
| 184 if (tryCatch.HasCaught()) { |
| 185 state->setException(tryCatch.Exception()); |
| 186 return ScriptValue(); |
| 187 } |
| 188 if (constructor.IsEmpty()) { |
| 189 state->setException(v8::Local<v8::Value>::New(setDOMException(INVALID_ST
ATE_ERR, isolate))); |
| 190 return ScriptValue(); |
| 191 } |
| 192 |
| 193 v8::Handle<v8::String> v8Name = v8String(name, isolate); |
| 194 v8::Handle<v8::Value> v8Type = v8StringOrNull(type, isolate); |
| 195 |
| 196 constructor->SetName(v8Type->IsNull() ? v8Name : v8::Handle<v8::String>::Cas
t(v8Type)); |
| 197 |
| 198 V8HiddenPropertyName::setNamedHiddenReference(constructor, "document", toV8(
document, state->context()->Global(), isolate)); |
| 199 V8HiddenPropertyName::setNamedHiddenReference(constructor, "namespaceURI", v
8String(namespaceURI, isolate)); |
| 200 V8HiddenPropertyName::setNamedHiddenReference(constructor, "name", v8Name); |
| 201 V8HiddenPropertyName::setNamedHiddenReference(constructor, "type", v8Type); |
| 202 |
| 203 // Neither Object::ForceSet nor Object::SetAccessor can set the |
| 204 // "prototype" property of function objects, so we use Set() |
| 205 // instead. This is safe because each function has "prototype" |
| 206 // property from birth so the Function, etc. prototypes will not |
| 207 // intercept the property access. |
| 208 v8::Handle<v8::Object> prototype = v8::Handle<v8::Object>::Cast(prototypeVal
ue.v8Value()); |
| 209 v8::Handle<v8::String> prototypeKey = v8String("prototype", isolate); |
| 210 ASSERT(constructor->HasOwnProperty(prototypeKey)); |
| 211 constructor->Set(prototypeKey, prototype, v8::ReadOnly); |
| 212 |
| 213 prototype->ForceSet(v8String("constructor", isolate), constructor, v8::ReadO
nly); |
| 214 |
| 215 ASSERT(!tryCatch.HasCaught()); |
| 216 |
| 217 return ScriptValue(constructor); |
| 162 } | 218 } |
| 163 | 219 |
| 164 static bool hasValidPrototypeChainFor(v8::Handle<v8::Object> prototypeObject, Wr
apperTypeInfo* typeInfo, v8::Handle<v8::Context> context) | 220 static bool hasValidPrototypeChainFor(v8::Handle<v8::Object> prototypeObject, Wr
apperTypeInfo* typeInfo, v8::Handle<v8::Context> context) |
| 165 { | 221 { |
| 166 // document.register() sets the constructor property, so the prototype shoul
dn't have one. | 222 // document.register() sets the constructor property, so the prototype shoul
dn't have one. |
| 167 if (prototypeObject->HasOwnProperty(v8String("constructor", context->GetIsol
ate()))) | 223 if (prototypeObject->HasOwnProperty(v8String("constructor", context->GetIsol
ate()))) |
| 168 return false; | 224 return false; |
| 169 | 225 |
| 170 v8::Handle<v8::Object> elementConstructor = v8::Handle<v8::Object>::Cast(V8P
erContextData::from(context)->constructorForType(typeInfo)); | 226 v8::Handle<v8::Object> elementConstructor = v8::Handle<v8::Object>::Cast(V8P
erContextData::from(context)->constructorForType(typeInfo)); |
| 171 if (elementConstructor.IsEmpty()) | 227 if (elementConstructor.IsEmpty()) |
| (...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 301 return; | 357 return; |
| 302 v8::Context::Scope scope(context); | 358 v8::Context::Scope scope(context); |
| 303 | 359 |
| 304 for (size_t i = 0; i < invocations.size(); ++i) { | 360 for (size_t i = 0; i < invocations.size(); ++i) { |
| 305 ASSERT(executionContext == invocations[i].element()->document()); | 361 ASSERT(executionContext == invocations[i].element()->document()); |
| 306 invokeReadyCallbackIfNeeded(invocations[i].element(), context); | 362 invokeReadyCallbackIfNeeded(invocations[i].element(), context); |
| 307 } | 363 } |
| 308 } | 364 } |
| 309 | 365 |
| 310 } // namespace WebCore | 366 } // namespace WebCore |
| OLD | NEW |