1{##############################################################################} 2{% macro attribute_getter(attribute, world_suffix) %} 3{% filter conditional(attribute.conditional_string) %} 4static void {{attribute.name}}AttributeGetter{{world_suffix}}( 5{%- if attribute.is_expose_js_accessors %} 6const v8::FunctionCallbackInfo<v8::Value>& info 7{%- else %} 8const 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(), "{{attribute.name}}"); 23 {{cpp_class}}* impl = {{v8_class}}::toImpl(holder); 24 if (!impl->{{attribute.cached_attribute_validation_method}}()) { 25 v8::Handle<v8::Value> v8Value = V8HiddenValue::getHiddenValue(info.GetIsolate(), 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}}::toImpl(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.name}}", "{{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_original}}); 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, {{attribute.cpp_value_to_v8_value}}); 85 {% endif %} 86 {# v8SetReturnValue #} 87 {% if attribute.is_keep_alive_for_gc %} 88 if ({{attribute.cpp_value}} && DOMDataStore::setReturnValueFromWrapper{{world_suffix}}<V8{{attribute.idl_type}}>(info.GetReturnValue(), {{attribute.cpp_value}}.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-values #} 110{% if reflect_empty %} 111if ({{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 %} 120if ({{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) %} 141static void {{attribute.name}}AttributeGetterCallback{{world_suffix}}( 142{%- if attribute.is_expose_js_accessors %} 143const v8::FunctionCallbackInfo<v8::Value>& info 144{%- else %} 145v8::Local<v8::String>, const v8::PropertyCallbackInfo<v8::Value>& info 146{%- endif %}) 147{ 148 TRACE_EVENT_SET_SAMPLING_STATE("blink", "DOMGetter"); 149 {% if attribute.deprecate_as %} 150 UseCounter::countDeprecation(callingExecutionContext(info.GetIsolate()), UseCounter::{{attribute.deprecate_as}}); 151 {% endif %} 152 {% if attribute.measure_as %} 153 UseCounter::count(callingExecutionContext(info.GetIsolate()), UseCounter::{{attribute.measure_as}}); 154 {% endif %} 155 {% if world_suffix in attribute.activity_logging_world_list_for_getter %} 156 ScriptState* scriptState = ScriptState::from(info.GetIsolate()->GetCurrentContext()); 157 V8PerContextData* contextData = scriptState->perContextData(); 158 {% if attribute.activity_logging_world_check %} 159 if (scriptState->world().isIsolatedWorld() && contextData && contextData->activityLogger()) 160 {% else %} 161 if (contextData && contextData->activityLogger()) 162 {% endif %} 163 contextData->activityLogger()->logGetter("{{interface_name}}.{{attribute.name}}"); 164 {% endif %} 165 {% if attribute.has_custom_getter %} 166 {{v8_class}}::{{attribute.name}}AttributeGetterCustom(info); 167 {% else %} 168 {{cpp_class}}V8Internal::{{attribute.name}}AttributeGetter{{world_suffix}}(info); 169 {% endif %} 170 TRACE_EVENT_SET_SAMPLING_STATE("v8", "V8Execution"); 171} 172{% endfilter %} 173{% endmacro %} 174 175 176{##############################################################################} 177{% macro constructor_getter_callback(attribute, world_suffix) %} 178{% filter conditional(attribute.conditional_string) %} 179static void {{attribute.name}}ConstructorGetterCallback{{world_suffix}}(v8::Local<v8::String> property, const v8::PropertyCallbackInfo<v8::Value>& info) 180{ 181 TRACE_EVENT_SET_SAMPLING_STATE("blink", "DOMGetter"); 182 {% if attribute.deprecate_as %} 183 UseCounter::countDeprecation(callingExecutionContext(info.GetIsolate()), UseCounter::{{attribute.deprecate_as}}); 184 {% endif %} 185 {% if attribute.measure_as %} 186 UseCounter::count(callingExecutionContext(info.GetIsolate()), UseCounter::{{attribute.measure_as}}); 187 {% endif %} 188 {{cpp_class}}V8Internal::{{cpp_class}}ConstructorGetter{{world_suffix}}(property, info); 189 TRACE_EVENT_SET_SAMPLING_STATE("v8", "V8Execution"); 190} 191{% endfilter %} 192{% endmacro %} 193 194 195{##############################################################################} 196{% macro attribute_setter(attribute, world_suffix) %} 197{% filter conditional(attribute.conditional_string) %} 198static void {{attribute.name}}AttributeSetter{{world_suffix}}( 199{%- if attribute.is_expose_js_accessors %} 200v8::Local<v8::Value> v8Value, const v8::FunctionCallbackInfo<v8::Value>& info 201{%- else %} 202v8::Local<v8::Value> v8Value, const v8::PropertyCallbackInfo<void>& info 203{%- endif %}) 204{ 205 {% if attribute.is_reflect and attribute.idl_type == 'DOMString' 206 and is_node and not attribute.is_implemented_in_private_script %} 207 {% set cpp_class, v8_class = 'Element', 'V8Element' %} 208 {% endif %} 209 {# Local variables #} 210 {% if not attribute.is_static %} 211 v8::Handle<v8::Object> holder = info.Holder(); 212 {% endif %} 213 {% if attribute.has_setter_exception_state %} 214 ExceptionState exceptionState(ExceptionState::SetterContext, "{{attribute.name}}", "{{interface_name}}", holder, info.GetIsolate()); 215 {% endif %} 216 {# Type checking #} 217 {% if attribute.has_type_checking_interface %} 218 {# Type checking for interface types (if interface not implemented, throw 219 TypeError), per http://www.w3.org/TR/WebIDL/#es-interface #} 220 if ({% if attribute.is_nullable %}!isUndefinedOrNull(v8Value) && {% endif %}!V8{{attribute.idl_type}}::hasInstance(v8Value, info.GetIsolate())) { 221 exceptionState.throwTypeError("The provided value is not of type '{{attribute.idl_type}}'."); 222 exceptionState.throwIfNeeded(); 223 return; 224 } 225 {% endif %} 226 {# impl #} 227 {% if attribute.put_forwards %} 228 {{cpp_class}}* proxyImpl = {{v8_class}}::toImpl(holder); 229 {{attribute.cpp_type}} impl = WTF::getPtr(proxyImpl->{{attribute.name}}()); 230 if (!impl) 231 return; 232 {% elif not attribute.is_static %} 233 {{cpp_class}}* impl = {{v8_class}}::toImpl(holder); 234 {% endif %} 235 {% if attribute.idl_type == 'EventHandler' and interface_name == 'Window' %} 236 if (!impl->document()) 237 return; 238 {% endif %} 239 {# Convert JS value to C++ value #} 240 {% if attribute.idl_type != 'EventHandler' %} 241 {{attribute.v8_value_to_local_cpp_value}}; 242 {% elif not is_node %}{# EventHandler hack #} 243 moveEventListenerToNewWrapper(holder, {{attribute.event_handler_getter_expression}}, v8Value, {{v8_class}}::eventListenerCacheIndex, info.GetIsolate()); 244 {% endif %} 245 {# Type checking, possibly throw a TypeError, per: 246 http://www.w3.org/TR/WebIDL/#es-type-mapping #} 247 {% if attribute.has_type_checking_unrestricted %} 248 {# Non-finite floating point values (NaN, +Infinity or −Infinity), per: 249 http://heycam.github.io/webidl/#es-float 250 http://heycam.github.io/webidl/#es-double #} 251 if (!std::isfinite(cppValue)) { 252 exceptionState.throwTypeError("The provided {{attribute.idl_type}} value is non-finite."); 253 exceptionState.throwIfNeeded(); 254 return; 255 } 256 {% elif attribute.enum_validation_expression %} 257 {# Setter ignores invalid enum values: 258 http://www.w3.org/TR/WebIDL/#idl-enums #} 259 String string = cppValue; 260 if (!({{attribute.enum_validation_expression}})) 261 return; 262 {% endif %} 263 {# Pre-set context #} 264 {% if attribute.is_custom_element_callbacks or 265 (attribute.is_reflect and 266 not(attribute.idl_type == 'DOMString' and is_node)) %} 267 {# Skip on compact node DOMString getters #} 268 CustomElementProcessingStack::CallbackDeliveryScope deliveryScope; 269 {% endif %} 270 {% if attribute.is_call_with_execution_context or 271 attribute.is_setter_call_with_execution_context %} 272 ExecutionContext* executionContext = currentExecutionContext(info.GetIsolate()); 273 {% endif %} 274 {# Set #} 275 {{attribute.cpp_setter}}; 276 {# Post-set #} 277 {% if attribute.is_setter_raises_exception %} 278 exceptionState.throwIfNeeded(); 279 {% endif %} 280 {% if attribute.cached_attribute_validation_method %} 281 V8HiddenValue::deleteHiddenValue(info.GetIsolate(), holder, v8AtomicString(info.GetIsolate(), "{{attribute.name}}")); // Invalidate the cached value. 282 {% endif %} 283} 284{% endfilter %} 285{% endmacro %} 286 287 288{##############################################################################} 289{% macro attribute_setter_callback(attribute, world_suffix) %} 290{% filter conditional(attribute.conditional_string) %} 291static void {{attribute.name}}AttributeSetterCallback{{world_suffix}}( 292{%- if attribute.is_expose_js_accessors %} 293const v8::FunctionCallbackInfo<v8::Value>& info 294{%- else %} 295v8::Local<v8::String>, v8::Local<v8::Value> v8Value, const v8::PropertyCallbackInfo<void>& info 296{%- endif %}) 297{ 298 {% if attribute.is_expose_js_accessors %} 299 v8::Local<v8::Value> v8Value = info[0]; 300 {% endif %} 301 TRACE_EVENT_SET_SAMPLING_STATE("blink", "DOMSetter"); 302 {% if attribute.deprecate_as %} 303 UseCounter::countDeprecation(callingExecutionContext(info.GetIsolate()), UseCounter::{{attribute.deprecate_as}}); 304 {% endif %} 305 {% if attribute.measure_as %} 306 UseCounter::count(callingExecutionContext(info.GetIsolate()), UseCounter::{{attribute.measure_as}}); 307 {% endif %} 308 {% if world_suffix in attribute.activity_logging_world_list_for_setter %} 309 ScriptState* scriptState = ScriptState::from(info.GetIsolate()->GetCurrentContext()); 310 V8PerContextData* contextData = scriptState->perContextData(); 311 {% if attribute.activity_logging_world_check %} 312 if (scriptState->world().isIsolatedWorld() && contextData && contextData->activityLogger()) { 313 {% else %} 314 if (contextData && contextData->activityLogger()) { 315 {% endif %} 316 contextData->activityLogger()->logSetter("{{interface_name}}.{{attribute.name}}", v8Value); 317 } 318 {% endif %} 319 {% if attribute.is_custom_element_callbacks or attribute.is_reflect %} 320 CustomElementProcessingStack::CallbackDeliveryScope deliveryScope; 321 {% endif %} 322 {% if attribute.has_custom_setter %} 323 {{v8_class}}::{{attribute.name}}AttributeSetterCustom(v8Value, info); 324 {% else %} 325 {{cpp_class}}V8Internal::{{attribute.name}}AttributeSetter{{world_suffix}}(v8Value, info); 326 {% endif %} 327 TRACE_EVENT_SET_SAMPLING_STATE("v8", "V8Execution"); 328} 329{% endfilter %} 330{% endmacro %} 331 332 333{##############################################################################} 334{% macro attribute_getter_implemented_in_private_script(attribute) %} 335bool {{v8_class}}::PrivateScript::{{attribute.name}}AttributeGetter(LocalFrame* frame, {{cpp_class}}* holderImpl, {{attribute.cpp_type}}* result) 336{ 337 if (!frame) 338 return false; 339 v8::HandleScope handleScope(toIsolate(frame)); 340 ScriptForbiddenScope::AllowUserAgentScript script; 341 v8::Handle<v8::Context> contextInPrivateScript = toV8Context(frame, DOMWrapperWorld::privateScriptIsolatedWorld()); 342 if (contextInPrivateScript.IsEmpty()) 343 return false; 344 ScriptState* scriptState = ScriptState::from(contextInPrivateScript); 345 ScriptState* scriptStateInUserScript = ScriptState::forMainWorld(frame); 346 if (!scriptState->executionContext()) 347 return false; 348 349 ScriptState::Scope scope(scriptState); 350 v8::Handle<v8::Value> holder = toV8(holderImpl, scriptState->context()->Global(), scriptState->isolate()); 351 352 ExceptionState exceptionState(ExceptionState::GetterContext, "{{attribute.name}}", "{{cpp_class}}", scriptState->context()->Global(), scriptState->isolate()); 353 v8::Handle<v8::Value> v8Value = PrivateScriptRunner::runDOMAttributeGetter(scriptState, scriptStateInUserScript, "{{cpp_class}}", "{{attribute.name}}", holder); 354 if (v8Value.IsEmpty()) 355 return false; 356 {{attribute.private_script_v8_value_to_local_cpp_value}}; 357 RELEASE_ASSERT(!exceptionState.hadException()); 358 *result = cppValue; 359 return true; 360} 361{% endmacro %} 362 363 364{% macro attribute_setter_implemented_in_private_script(attribute) %} 365bool {{v8_class}}::PrivateScript::{{attribute.name}}AttributeSetter(LocalFrame* frame, {{cpp_class}}* holderImpl, {{attribute.argument_cpp_type}} cppValue) 366{ 367 if (!frame) 368 return false; 369 v8::HandleScope handleScope(toIsolate(frame)); 370 ScriptForbiddenScope::AllowUserAgentScript script; 371 v8::Handle<v8::Context> contextInPrivateScript = toV8Context(frame, DOMWrapperWorld::privateScriptIsolatedWorld()); 372 if (contextInPrivateScript.IsEmpty()) 373 return false; 374 ScriptState* scriptState = ScriptState::from(contextInPrivateScript); 375 ScriptState* scriptStateInUserScript = ScriptState::forMainWorld(frame); 376 if (!scriptState->executionContext()) 377 return false; 378 379 ScriptState::Scope scope(scriptState); 380 v8::Handle<v8::Value> holder = toV8(holderImpl, scriptState->context()->Global(), scriptState->isolate()); 381 382 ExceptionState exceptionState(ExceptionState::SetterContext, "{{attribute.name}}", "{{cpp_class}}", scriptState->context()->Global(), scriptState->isolate()); 383 return PrivateScriptRunner::runDOMAttributeSetter(scriptState, scriptStateInUserScript, "{{cpp_class}}", "{{attribute.name}}", holder, {{attribute.private_script_cpp_value_to_v8_value}}); 384} 385{% endmacro %} 386 387 388{##############################################################################} 389{% macro attribute_configuration(attribute) %} 390{% set getter_callback = 391 '%sV8Internal::%sAttributeGetterCallback' % 392 (cpp_class, attribute.name) 393 if not attribute.constructor_type else 394 ('%sV8Internal::%sConstructorGetterCallback' % 395 (cpp_class, attribute.name) 396 if attribute.needs_constructor_getter_callback else 397 '{0}V8Internal::{0}ConstructorGetter'.format(cpp_class)) %} 398{% set getter_callback_for_main_world = 399 '%sV8Internal::%sAttributeGetterCallbackForMainWorld' % 400 (cpp_class, attribute.name) 401 if attribute.is_per_world_bindings else '0' %} 402{% set setter_callback = attribute.setter_callback %} 403{% set setter_callback_for_main_world = 404 '%sV8Internal::%sAttributeSetterCallbackForMainWorld' % 405 (cpp_class, attribute.name) 406 if attribute.is_per_world_bindings and 407 (not attribute.is_read_only or attribute.put_forwards) else '0' %} 408{% set wrapper_type_info = 409 'const_cast<WrapperTypeInfo*>(&V8%s::wrapperTypeInfo)' % 410 attribute.constructor_type 411 if attribute.constructor_type else '0' %} 412{% set access_control = 'static_cast<v8::AccessControl>(%s)' % 413 ' | '.join(attribute.access_control_list) %} 414{% set property_attribute = 'static_cast<v8::PropertyAttribute>(%s)' % 415 ' | '.join(attribute.property_attributes) %} 416{% set only_exposed_to_private_script = 'V8DOMConfiguration::OnlyExposedToPrivateScript' if attribute.only_exposed_to_private_script else 'V8DOMConfiguration::ExposedToAllScripts' %} 417{% set on_prototype = 'V8DOMConfiguration::OnPrototype' 418 if interface_name == 'Window' and attribute.idl_type == 'EventHandler' 419 else 'V8DOMConfiguration::OnInstance' %} 420{% set attribute_configuration_list = [ 421 '"%s"' % attribute.name, 422 getter_callback, 423 setter_callback, 424 getter_callback_for_main_world, 425 setter_callback_for_main_world, 426 wrapper_type_info, 427 access_control, 428 property_attribute, 429 only_exposed_to_private_script, 430 ] %} 431{% if not attribute.is_expose_js_accessors %} 432{% set attribute_configuration_list = attribute_configuration_list 433 + [on_prototype] %} 434{% endif %} 435{{'{'}}{{attribute_configuration_list | join(', ')}}{{'}'}} 436{%- endmacro %} 437