| OLD | NEW |
| (Empty) |
| 1 {##############################################################################} | |
| 2 {% macro attribute_getter(attribute, world_suffix) %} | |
| 3 {% filter conditional(attribute.conditional_string) %} | |
| 4 static void {{attribute.name}}AttributeGetter{{world_suffix}}( | |
| 5 {%- if attribute.is_expose_js_accessors %} | |
| 6 const v8::FunctionCallbackInfo<v8::Value>& info | |
| 7 {%- else %} | |
| 8 const v8::PropertyCallbackInfo<v8::Value>& info | |
| 9 {%- endif %}) | |
| 10 { | |
| 11 {% if attribute.is_reflect and not attribute.is_url | |
| 12 and attribute.idl_type == 'DOMString' and is_node | |
| 13 and not attribute.is_implemented_in_private_script %} | |
| 14 {% set cpp_class, v8_class = 'Element', 'V8Element' %} | |
| 15 {% endif %} | |
| 16 {# holder #} | |
| 17 {% if not attribute.is_static %} | |
| 18 v8::Handle<v8::Object> holder = info.Holder(); | |
| 19 {% endif %} | |
| 20 {# impl #} | |
| 21 {% if attribute.cached_attribute_validation_method %} | |
| 22 v8::Handle<v8::String> propertyName = v8AtomicString(info.GetIsolate(), "{{a
ttribute.name}}"); | |
| 23 {{cpp_class}}* impl = {{v8_class}}::toNative(holder); | |
| 24 if (!impl->{{attribute.cached_attribute_validation_method}}()) { | |
| 25 v8::Handle<v8::Value> v8Value = V8HiddenValue::getHiddenValue(info.GetIs
olate(), holder, propertyName); | |
| 26 if (!v8Value.IsEmpty()) { | |
| 27 v8SetReturnValue(info, v8Value); | |
| 28 return; | |
| 29 } | |
| 30 } | |
| 31 {% elif not attribute.is_static %} | |
| 32 {{cpp_class}}* impl = {{v8_class}}::toNative(holder); | |
| 33 {% endif %} | |
| 34 {% if interface_name == 'Window' and attribute.idl_type == 'EventHandler' %} | |
| 35 if (!impl->document()) | |
| 36 return; | |
| 37 {% endif %} | |
| 38 {# Local variables #} | |
| 39 {% if attribute.is_call_with_execution_context %} | |
| 40 ExecutionContext* executionContext = currentExecutionContext(info.GetIsolate
()); | |
| 41 {% endif %} | |
| 42 {% if attribute.is_call_with_script_state %} | |
| 43 ScriptState* scriptState = ScriptState::current(info.GetIsolate()); | |
| 44 {% endif %} | |
| 45 {% if attribute.is_check_security_for_node or | |
| 46 attribute.is_getter_raises_exception %} | |
| 47 ExceptionState exceptionState(ExceptionState::GetterContext, "{{attribute.na
me}}", "{{interface_name}}", holder, info.GetIsolate()); | |
| 48 {% endif %} | |
| 49 {% if attribute.is_explicit_nullable %} | |
| 50 bool isNull = false; | |
| 51 {% endif %} | |
| 52 {% if attribute.is_implemented_in_private_script %} | |
| 53 {{attribute.cpp_type}} result{{attribute.cpp_type_initializer}}; | |
| 54 if (!{{attribute.cpp_value_original}}) | |
| 55 return; | |
| 56 {% elif attribute.cpp_value_original %} | |
| 57 {{attribute.cpp_type}} {{attribute.cpp_value}}({{attribute.cpp_value_origina
l}}); | |
| 58 {% endif %} | |
| 59 {# Checks #} | |
| 60 {% if attribute.is_getter_raises_exception %} | |
| 61 if (UNLIKELY(exceptionState.throwIfNeeded())) | |
| 62 return; | |
| 63 {% endif %} | |
| 64 {% if attribute.is_check_security_for_node %} | |
| 65 if (!BindingSecurity::shouldAllowAccessToNode(info.GetIsolate(), {{attribute
.cpp_value}}, exceptionState)) { | |
| 66 v8SetReturnValueNull(info); | |
| 67 exceptionState.throwIfNeeded(); | |
| 68 return; | |
| 69 } | |
| 70 {% endif %} | |
| 71 {% if attribute.reflect_only %} | |
| 72 {{release_only_check(attribute.reflect_only, attribute.reflect_missing, | |
| 73 attribute.reflect_invalid, attribute.reflect_empty, | |
| 74 attribute.cpp_value) | |
| 75 | indent}} | |
| 76 {% endif %} | |
| 77 {% if attribute.is_explicit_nullable %} | |
| 78 if (isNull) { | |
| 79 v8SetReturnValueNull(info); | |
| 80 return; | |
| 81 } | |
| 82 {% endif %} | |
| 83 {% if attribute.cached_attribute_validation_method %} | |
| 84 V8HiddenValue::setHiddenValue(info.GetIsolate(), holder, propertyName, {{att
ribute.cpp_value_to_v8_value}}); | |
| 85 {% endif %} | |
| 86 {# v8SetReturnValue #} | |
| 87 {% if attribute.is_keep_alive_for_gc %} | |
| 88 if ({{attribute.cpp_value}} && DOMDataStore::setReturnValueFromWrapper{{worl
d_suffix}}<V8{{attribute.idl_type}}>(info.GetReturnValue(), {{attribute.cpp_valu
e}}.get())) | |
| 89 return; | |
| 90 v8::Handle<v8::Value> wrapper = toV8({{attribute.cpp_value}}.get(), holder,
info.GetIsolate()); | |
| 91 if (!wrapper.IsEmpty()) { | |
| 92 V8HiddenValue::setHiddenValue(info.GetIsolate(), holder, v8AtomicString(
info.GetIsolate(), "{{attribute.name}}"), wrapper); | |
| 93 {{attribute.v8_set_return_value}}; | |
| 94 } | |
| 95 {% elif world_suffix %} | |
| 96 {{attribute.v8_set_return_value_for_main_world}}; | |
| 97 {% else %} | |
| 98 {{attribute.v8_set_return_value}}; | |
| 99 {% endif %} | |
| 100 } | |
| 101 {% endfilter %} | |
| 102 {% endmacro %} | |
| 103 | |
| 104 {######################################} | |
| 105 {% macro release_only_check(reflect_only_values, reflect_missing, | |
| 106 reflect_invalid, reflect_empty, cpp_value) %} | |
| 107 {# Attribute is limited to only known values: check that the attribute value is | |
| 108 one of those. If not, set it to the empty string. | |
| 109 http://www.whatwg.org/specs/web-apps/current-work/#limited-to-only-known-valu
es #} | |
| 110 {% if reflect_empty %} | |
| 111 if ({{cpp_value}}.isNull()) { | |
| 112 {% if reflect_missing %} | |
| 113 {{cpp_value}} = "{{reflect_missing}}"; | |
| 114 {% else %} | |
| 115 ; | |
| 116 {% endif %} | |
| 117 } else if ({{cpp_value}}.isEmpty()) { | |
| 118 {{cpp_value}} = "{{reflect_empty}}"; | |
| 119 {% else %} | |
| 120 if ({{cpp_value}}.isEmpty()) { | |
| 121 {# FIXME: should use [ReflectEmpty] instead; need to change IDL files #} | |
| 122 {% if reflect_missing %} | |
| 123 {{cpp_value}} = "{{reflect_missing}}"; | |
| 124 {% else %} | |
| 125 ; | |
| 126 {% endif %} | |
| 127 {% endif %} | |
| 128 {% for value in reflect_only_values %} | |
| 129 } else if (equalIgnoringCase({{cpp_value}}, "{{value}}")) { | |
| 130 {{cpp_value}} = "{{value}}"; | |
| 131 {% endfor %} | |
| 132 } else { | |
| 133 {{cpp_value}} = "{{reflect_invalid}}"; | |
| 134 } | |
| 135 {% endmacro %} | |
| 136 | |
| 137 | |
| 138 {##############################################################################} | |
| 139 {% macro attribute_getter_callback(attribute, world_suffix) %} | |
| 140 {% filter conditional(attribute.conditional_string) %} | |
| 141 static void {{attribute.name}}AttributeGetterCallback{{world_suffix}}( | |
| 142 {%- if attribute.is_expose_js_accessors %} | |
| 143 const v8::FunctionCallbackInfo<v8::Value>& info | |
| 144 {%- else %} | |
| 145 v8::Local<v8::String>, const v8::PropertyCallbackInfo<v8::Value>& info | |
| 146 {%- endif %}) | |
| 147 { | |
| 148 TRACE_EVENT_SET_SAMPLING_STATE("blink", "DOMGetter"); | |
| 149 {% if attribute.has_custom_getter %} | |
| 150 {{v8_class}}::{{attribute.name}}AttributeGetterCustom(info); | |
| 151 {% else %} | |
| 152 {{cpp_class}}V8Internal::{{attribute.name}}AttributeGetter{{world_suffix}}(i
nfo); | |
| 153 {% endif %} | |
| 154 TRACE_EVENT_SET_SAMPLING_STATE("v8", "V8Execution"); | |
| 155 } | |
| 156 {% endfilter %} | |
| 157 {% endmacro %} | |
| 158 | |
| 159 | |
| 160 {##############################################################################} | |
| 161 {% macro constructor_getter_callback(attribute, world_suffix) %} | |
| 162 {% filter conditional(attribute.conditional_string) %} | |
| 163 static void {{attribute.name}}ConstructorGetterCallback{{world_suffix}}(v8::Loca
l<v8::String> property, const v8::PropertyCallbackInfo<v8::Value>& info) | |
| 164 { | |
| 165 TRACE_EVENT_SET_SAMPLING_STATE("blink", "DOMGetter"); | |
| 166 {{cpp_class}}V8Internal::{{cpp_class}}ConstructorGetter{{world_suffix}}(prop
erty, info); | |
| 167 TRACE_EVENT_SET_SAMPLING_STATE("v8", "V8Execution"); | |
| 168 } | |
| 169 {% endfilter %} | |
| 170 {% endmacro %} | |
| 171 | |
| 172 | |
| 173 {##############################################################################} | |
| 174 {% macro attribute_setter(attribute, world_suffix) %} | |
| 175 {% filter conditional(attribute.conditional_string) %} | |
| 176 static void {{attribute.name}}AttributeSetter{{world_suffix}}( | |
| 177 {%- if attribute.is_expose_js_accessors %} | |
| 178 v8::Local<v8::Value> v8Value, const v8::FunctionCallbackInfo<v8::Value>& info | |
| 179 {%- else %} | |
| 180 v8::Local<v8::Value> v8Value, const v8::PropertyCallbackInfo<void>& info | |
| 181 {%- endif %}) | |
| 182 { | |
| 183 {% if attribute.is_reflect and attribute.idl_type == 'DOMString' | |
| 184 and is_node and not attribute.is_implemented_in_private_script %} | |
| 185 {% set cpp_class, v8_class = 'Element', 'V8Element' %} | |
| 186 {% endif %} | |
| 187 {# Local variables #} | |
| 188 {% if not attribute.is_static %} | |
| 189 v8::Handle<v8::Object> holder = info.Holder(); | |
| 190 {% endif %} | |
| 191 {% if attribute.has_setter_exception_state %} | |
| 192 ExceptionState exceptionState(ExceptionState::SetterContext, "{{attribute.na
me}}", "{{interface_name}}", holder, info.GetIsolate()); | |
| 193 {% endif %} | |
| 194 {# Type checking #} | |
| 195 {% if attribute.has_type_checking_interface %} | |
| 196 {# Type checking for interface types (if interface not implemented, throw | |
| 197 TypeError), per http://www.w3.org/TR/WebIDL/#es-interface #} | |
| 198 if ({% if attribute.is_nullable %}!isUndefinedOrNull(v8Value) && {% endif %}
!V8{{attribute.idl_type}}::hasInstance(v8Value, info.GetIsolate())) { | |
| 199 exceptionState.throwTypeError("The provided value is not of type '{{attr
ibute.idl_type}}'."); | |
| 200 exceptionState.throwIfNeeded(); | |
| 201 return; | |
| 202 } | |
| 203 {% endif %} | |
| 204 {# impl #} | |
| 205 {% if attribute.put_forwards %} | |
| 206 {{cpp_class}}* proxyImpl = {{v8_class}}::toNative(holder); | |
| 207 {{attribute.cpp_type}} impl = WTF::getPtr(proxyImpl->{{attribute.name}}()); | |
| 208 if (!impl) | |
| 209 return; | |
| 210 {% elif not attribute.is_static %} | |
| 211 {{cpp_class}}* impl = {{v8_class}}::toNative(holder); | |
| 212 {% endif %} | |
| 213 {% if attribute.idl_type == 'EventHandler' and interface_name == 'Window' %} | |
| 214 if (!impl->document()) | |
| 215 return; | |
| 216 {% endif %} | |
| 217 {# Convert JS value to C++ value #} | |
| 218 {% if attribute.idl_type != 'EventHandler' %} | |
| 219 {{attribute.v8_value_to_local_cpp_value}}; | |
| 220 {% elif not is_node %}{# EventHandler hack #} | |
| 221 moveEventListenerToNewWrapper(holder, {{attribute.event_handler_getter_expre
ssion}}, v8Value, {{v8_class}}::eventListenerCacheIndex, info.GetIsolate()); | |
| 222 {% endif %} | |
| 223 {# Type checking, possibly throw a TypeError, per: | |
| 224 http://www.w3.org/TR/WebIDL/#es-type-mapping #} | |
| 225 {% if attribute.has_type_checking_unrestricted %} | |
| 226 {# Non-finite floating point values (NaN, +Infinity or −Infinity), per: | |
| 227 http://heycam.github.io/webidl/#es-float | |
| 228 http://heycam.github.io/webidl/#es-double #} | |
| 229 if (!std::isfinite(cppValue)) { | |
| 230 exceptionState.throwTypeError("The provided {{attribute.idl_type}} value
is non-finite."); | |
| 231 exceptionState.throwIfNeeded(); | |
| 232 return; | |
| 233 } | |
| 234 {% elif attribute.enum_validation_expression %} | |
| 235 {# Setter ignores invalid enum values: | |
| 236 http://www.w3.org/TR/WebIDL/#idl-enums #} | |
| 237 String string = cppValue; | |
| 238 if (!({{attribute.enum_validation_expression}})) | |
| 239 return; | |
| 240 {% endif %} | |
| 241 {# Pre-set context #} | |
| 242 {% if attribute.is_custom_element_callbacks or | |
| 243 (attribute.is_reflect and | |
| 244 not(attribute.idl_type == 'DOMString' and is_node)) %} | |
| 245 {# Skip on compact node DOMString getters #} | |
| 246 CustomElementProcessingStack::CallbackDeliveryScope deliveryScope; | |
| 247 {% endif %} | |
| 248 {% if attribute.is_call_with_execution_context or | |
| 249 attribute.is_setter_call_with_execution_context %} | |
| 250 ExecutionContext* executionContext = currentExecutionContext(info.GetIsolate
()); | |
| 251 {% endif %} | |
| 252 {% if attribute.is_call_with_script_state %} | |
| 253 ScriptState* scriptState = ScriptState::current(info.GetIsolate()); | |
| 254 {% endif %} | |
| 255 {# Set #} | |
| 256 {{attribute.cpp_setter}}; | |
| 257 {# Post-set #} | |
| 258 {% if attribute.is_setter_raises_exception %} | |
| 259 exceptionState.throwIfNeeded(); | |
| 260 {% endif %} | |
| 261 {% if attribute.cached_attribute_validation_method %} | |
| 262 V8HiddenValue::deleteHiddenValue(info.GetIsolate(), holder, v8AtomicString(i
nfo.GetIsolate(), "{{attribute.name}}")); // Invalidate the cached value. | |
| 263 {% endif %} | |
| 264 } | |
| 265 {% endfilter %} | |
| 266 {% endmacro %} | |
| 267 | |
| 268 | |
| 269 {##############################################################################} | |
| 270 {% macro attribute_setter_callback(attribute, world_suffix) %} | |
| 271 {% filter conditional(attribute.conditional_string) %} | |
| 272 static void {{attribute.name}}AttributeSetterCallback{{world_suffix}}( | |
| 273 {%- if attribute.is_expose_js_accessors %} | |
| 274 const v8::FunctionCallbackInfo<v8::Value>& info | |
| 275 {%- else %} | |
| 276 v8::Local<v8::String>, v8::Local<v8::Value> v8Value, const v8::PropertyCallbackI
nfo<void>& info | |
| 277 {%- endif %}) | |
| 278 { | |
| 279 {% if attribute.is_expose_js_accessors %} | |
| 280 v8::Local<v8::Value> v8Value = info[0]; | |
| 281 {% endif %} | |
| 282 TRACE_EVENT_SET_SAMPLING_STATE("blink", "DOMSetter"); | |
| 283 {% if attribute.is_custom_element_callbacks or attribute.is_reflect %} | |
| 284 CustomElementProcessingStack::CallbackDeliveryScope deliveryScope; | |
| 285 {% endif %} | |
| 286 {% if attribute.has_custom_setter %} | |
| 287 {{v8_class}}::{{attribute.name}}AttributeSetterCustom(v8Value, info); | |
| 288 {% else %} | |
| 289 {{cpp_class}}V8Internal::{{attribute.name}}AttributeSetter{{world_suffix}}(v
8Value, info); | |
| 290 {% endif %} | |
| 291 TRACE_EVENT_SET_SAMPLING_STATE("v8", "V8Execution"); | |
| 292 } | |
| 293 {% endfilter %} | |
| 294 {% endmacro %} | |
| 295 | |
| 296 | |
| 297 {##############################################################################} | |
| 298 {% macro attribute_getter_implemented_in_private_script(attribute) %} | |
| 299 bool {{v8_class}}::PrivateScript::{{attribute.name}}AttributeGetter(LocalFrame*
frame, {{cpp_class}}* holderImpl, {{attribute.cpp_type}}* result) | |
| 300 { | |
| 301 if (!frame) | |
| 302 return false; | |
| 303 v8::HandleScope handleScope(toIsolate(frame)); | |
| 304 ScriptForbiddenScope::AllowUserAgentScript script; | |
| 305 v8::Handle<v8::Context> context = toV8Context(frame, DOMWrapperWorld::privat
eScriptIsolatedWorld()); | |
| 306 if (context.IsEmpty()) | |
| 307 return false; | |
| 308 ScriptState* scriptState = ScriptState::from(context); | |
| 309 if (!scriptState->executionContext()) | |
| 310 return false; | |
| 311 | |
| 312 ScriptState::Scope scope(scriptState); | |
| 313 v8::Handle<v8::Value> holder = toV8(holderImpl, scriptState->context()->Glob
al(), scriptState->isolate()); | |
| 314 | |
| 315 ExceptionState exceptionState(ExceptionState::GetterContext, "{{attribute.na
me}}", "{{cpp_class}}", scriptState->context()->Global(), scriptState->isolate()
); | |
| 316 v8::TryCatch block; | |
| 317 v8::Handle<v8::Value> v8Value = PrivateScriptRunner::runDOMAttributeGetter(s
criptState, "{{cpp_class}}", "{{attribute.name}}", holder); | |
| 318 if (block.HasCaught()) { | |
| 319 PrivateScriptRunner::rethrowExceptionInPrivateScript(scriptState->isolat
e(), exceptionState, block); | |
| 320 block.ReThrow(); | |
| 321 return false; | |
| 322 } | |
| 323 {{attribute.private_script_v8_value_to_local_cpp_value}}; | |
| 324 RELEASE_ASSERT(!exceptionState.hadException()); | |
| 325 *result = cppValue; | |
| 326 return true; | |
| 327 } | |
| 328 {% endmacro %} | |
| 329 | |
| 330 | |
| 331 {% macro attribute_setter_implemented_in_private_script(attribute) %} | |
| 332 bool {{v8_class}}::PrivateScript::{{attribute.name}}AttributeSetter(LocalFrame*
frame, {{cpp_class}}* holderImpl, {{attribute.argument_cpp_type}} cppValue) | |
| 333 { | |
| 334 if (!frame) | |
| 335 return false; | |
| 336 v8::HandleScope handleScope(toIsolate(frame)); | |
| 337 ScriptForbiddenScope::AllowUserAgentScript script; | |
| 338 v8::Handle<v8::Context> context = toV8Context(frame, DOMWrapperWorld::privat
eScriptIsolatedWorld()); | |
| 339 if (context.IsEmpty()) | |
| 340 return false; | |
| 341 ScriptState* scriptState = ScriptState::from(context); | |
| 342 if (!scriptState->executionContext()) | |
| 343 return false; | |
| 344 | |
| 345 ScriptState::Scope scope(scriptState); | |
| 346 v8::Handle<v8::Value> holder = toV8(holderImpl, scriptState->context()->Glob
al(), scriptState->isolate()); | |
| 347 | |
| 348 ExceptionState exceptionState(ExceptionState::SetterContext, "{{attribute.na
me}}", "{{cpp_class}}", scriptState->context()->Global(), scriptState->isolate()
); | |
| 349 v8::TryCatch block; | |
| 350 PrivateScriptRunner::runDOMAttributeSetter(scriptState, "{{cpp_class}}", "{{
attribute.name}}", holder, {{attribute.private_script_cpp_value_to_v8_value}}); | |
| 351 if (block.HasCaught()) { | |
| 352 PrivateScriptRunner::rethrowExceptionInPrivateScript(scriptState->isolat
e(), exceptionState, block); | |
| 353 block.ReThrow(); | |
| 354 return false; | |
| 355 } | |
| 356 return true; | |
| 357 } | |
| 358 {% endmacro %} | |
| 359 | |
| 360 | |
| 361 {##############################################################################} | |
| 362 {% macro attribute_configuration(attribute) %} | |
| 363 {% set getter_callback = | |
| 364 '%sV8Internal::%sAttributeGetterCallback' % | |
| 365 (cpp_class, attribute.name) | |
| 366 if not attribute.constructor_type else | |
| 367 ('%sV8Internal::%sConstructorGetterCallback' % | |
| 368 (cpp_class, attribute.name) | |
| 369 if attribute.needs_constructor_getter_callback else | |
| 370 '{0}V8Internal::{0}ConstructorGetter'.format(cpp_class)) %} | |
| 371 {% set getter_callback_for_main_world = | |
| 372 '%sV8Internal::%sAttributeGetterCallbackForMainWorld' % | |
| 373 (cpp_class, attribute.name) | |
| 374 if attribute.is_per_world_bindings else '0' %} | |
| 375 {% set setter_callback = attribute.setter_callback %} | |
| 376 {% set setter_callback_for_main_world = | |
| 377 '%sV8Internal::%sAttributeSetterCallbackForMainWorld' % | |
| 378 (cpp_class, attribute.name) | |
| 379 if attribute.is_per_world_bindings and | |
| 380 (not attribute.is_read_only or attribute.put_forwards) else '0' %} | |
| 381 {% set wrapper_type_info = | |
| 382 'const_cast<WrapperTypeInfo*>(&V8%s::wrapperTypeInfo)' % | |
| 383 attribute.constructor_type | |
| 384 if attribute.constructor_type else '0' %} | |
| 385 {% set access_control = 'static_cast<v8::AccessControl>(%s)' % | |
| 386 ' | '.join(attribute.access_control_list) %} | |
| 387 {% set property_attribute = 'static_cast<v8::PropertyAttribute>(%s)' % | |
| 388 ' | '.join(attribute.property_attributes) %} | |
| 389 {% set only_exposed_to_private_script = 'V8DOMConfiguration::OnlyExposedToPrivat
eScript' if attribute.only_exposed_to_private_script else 'V8DOMConfiguration::E
xposedToAllScripts' %} | |
| 390 {% set on_prototype = 'V8DOMConfiguration::OnPrototype' | |
| 391 if interface_name == 'Window' and attribute.idl_type == 'EventHandler' | |
| 392 else 'V8DOMConfiguration::OnInstance' %} | |
| 393 {% set attribute_configuration_list = [ | |
| 394 '"%s"' % attribute.name, | |
| 395 getter_callback, | |
| 396 setter_callback, | |
| 397 getter_callback_for_main_world, | |
| 398 setter_callback_for_main_world, | |
| 399 wrapper_type_info, | |
| 400 access_control, | |
| 401 property_attribute, | |
| 402 only_exposed_to_private_script, | |
| 403 ] %} | |
| 404 {% if not attribute.is_expose_js_accessors %} | |
| 405 {% set attribute_configuration_list = attribute_configuration_list | |
| 406 + [on_prototype] %} | |
| 407 {% endif %} | |
| 408 {{'{'}}{{attribute_configuration_list | join(', ')}}{{'}'}} | |
| 409 {%- endmacro %} | |
| OLD | NEW |