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
8 const v8::PropertyCallbackInfo<v8::Value>& info
11 {% if attribute.is_reflect and not attribute.is_url and
12 attribute.idl_type == 'DOMString' and is_node %}
13 {% set cpp_class, v8_class = 'Element', 'V8Element' %}
16 {% if attribute.is_unforgeable and interface_name != 'Window' %}
17 {# perform lookup first #}
18 {# FIXME: can we remove this lookup? #}
19 v8::Handle<v8::Object> holder = {{v8_class}}::findInstanceInPrototypeChain(info.This(), info.GetIsolate());
22 {% elif not attribute.is_static %}
23 v8::Handle<v8::Object> holder = info.Holder();
26 {% if attribute.cached_attribute_validation_method %}
27 v8::Handle<v8::String> propertyName = v8AtomicString(info.GetIsolate(), "{{attribute.name}}");
28 {{cpp_class}}* impl = {{v8_class}}::toNative(holder);
29 if (!impl->{{attribute.cached_attribute_validation_method}}()) {
30 v8::Handle<v8::Value> v8Value = V8HiddenValue::getHiddenValue(info.GetIsolate(), holder, propertyName);
31 if (!v8Value.IsEmpty()) {
32 v8SetReturnValue(info, v8Value);
36 {% elif not attribute.is_static %}
37 {{cpp_class}}* impl = {{v8_class}}::toNative(holder);
39 {% if attribute.is_partial_interface_member and not attribute.is_static %}
40 {# instance members (non-static members) in partial interface take |impl| #}
43 {% if interface_name == 'Window' and attribute.idl_type == 'EventHandler' %}
44 if (!impl->document())
48 {% if attribute.is_call_with_execution_context %}
49 ExecutionContext* scriptContext = currentExecutionContext(info.GetIsolate());
51 {% if attribute.is_call_with_script_state %}
52 ScriptState* state = ScriptState::current(info.GetIsolate());
54 {% if attribute.is_check_security_for_node or
55 attribute.is_getter_raises_exception %}
56 ExceptionState exceptionState(ExceptionState::GetterContext, "{{attribute.name}}", "{{interface_name}}", holder, info.GetIsolate());
58 {% if attribute.is_nullable and not attribute.has_type_checking_nullable %}
61 {# FIXME: consider always using a local variable for value #}
62 {% if attribute.cached_attribute_validation_method or
63 attribute.is_getter_raises_exception or
64 attribute.is_nullable or
65 attribute.reflect_only or
66 attribute.idl_type == 'EventHandler' %}
67 {{attribute.cpp_type}} {{attribute.cpp_value}} = {{attribute.cpp_value_original}};
70 {% if attribute.is_getter_raises_exception %}
71 if (UNLIKELY(exceptionState.throwIfNeeded()))
74 {% if attribute.is_check_security_for_node %}
75 {# FIXME: use a local variable to not call getter twice #}
76 if (!BindingSecurity::shouldAllowAccessToNode(info.GetIsolate(), {{attribute.cpp_value}}, exceptionState)) {
77 v8SetReturnValueNull(info);
78 exceptionState.throwIfNeeded();
82 {% if attribute.reflect_only %}
83 {{release_only_check(attribute.reflect_only, attribute.reflect_missing,
84 attribute.reflect_invalid, attribute.reflect_empty)
87 {% if attribute.is_nullable %}
88 {% if attribute.has_type_checking_nullable %}
89 if (!{{attribute.cpp_value}}) {
93 v8SetReturnValueNull(info);
97 {% if attribute.cached_attribute_validation_method %}
98 V8HiddenValue::setHiddenValue(info.GetIsolate(), holder, propertyName, {{attribute.cpp_value}}.v8Value());
100 {# v8SetReturnValue #}
101 {% if attribute.is_keep_alive_for_gc %}
102 {# FIXME: merge local variable assignment with above #}
103 {{attribute.cpp_type}} result({{attribute.cpp_value}});
104 if (result && DOMDataStore::setReturnValueFromWrapper{{world_suffix}}<{{attribute.v8_type}}>(info.GetReturnValue(), result.get()))
106 v8::Handle<v8::Value> wrapper = toV8(result.get(), holder, info.GetIsolate());
107 if (!wrapper.IsEmpty()) {
108 V8HiddenValue::setHiddenValue(info.GetIsolate(), holder, v8AtomicString(info.GetIsolate(), "{{attribute.name}}"), wrapper);
109 {{attribute.v8_set_return_value}};
111 {% elif world_suffix %}
112 {{attribute.v8_set_return_value_for_main_world}};
114 {{attribute.v8_set_return_value}};
120 {######################################}
121 {% macro release_only_check(reflect_only_values, reflect_missing,
122 reflect_invalid, reflect_empty) %}
123 {# Attribute is limited to only known values: check that the attribute value is
124 one of those. If not, set it to the empty string.
125 http://www.whatwg.org/specs/web-apps/current-work/#limited-to-only-known-values #}
126 {% if reflect_empty %}
127 if (v8Value.isNull()) {
128 {% if reflect_missing %}
129 v8Value = "{{reflect_missing}}";
133 } else if (v8Value.isEmpty()) {
134 v8Value = "{{reflect_empty}}";
136 if (v8Value.isEmpty()) {
137 {# FIXME: should use [ReflectEmpty] instead; need to change IDL files #}
138 {% if reflect_missing %}
139 v8Value = "{{reflect_missing}}";
144 {% for value in reflect_only_values %}
145 } else if (equalIgnoringCase(v8Value, "{{value}}")) {
146 v8Value = "{{value}}";
149 v8Value = "{{reflect_invalid}}";
154 {##############################################################################}
155 {% macro attribute_getter_callback(attribute, world_suffix) %}
156 {% filter conditional(attribute.conditional_string) %}
157 static void {{attribute.name}}AttributeGetterCallback{{world_suffix}}(
158 {%- if attribute.is_expose_js_accessors %}
159 const v8::FunctionCallbackInfo<v8::Value>& info
161 v8::Local<v8::String>, const v8::PropertyCallbackInfo<v8::Value>& info
164 TRACE_EVENT_SET_SAMPLING_STATE("Blink", "DOMGetter");
165 {% if attribute.deprecate_as %}
166 UseCounter::countDeprecation(callingExecutionContext(info.GetIsolate()), UseCounter::{{attribute.deprecate_as}});
168 {% if attribute.measure_as %}
169 UseCounter::count(callingExecutionContext(info.GetIsolate()), UseCounter::{{attribute.measure_as}});
171 {% if world_suffix in attribute.activity_logging_world_list_for_getter %}
172 DOMWrapperWorld& world = DOMWrapperWorld::current(info.GetIsolate());
173 if (world.activityLogger())
174 world.activityLogger()->logGetter("{{interface_name}}.{{attribute.name}}");
176 {% if attribute.has_custom_getter %}
177 {{v8_class}}::{{attribute.name}}AttributeGetterCustom(info);
179 {{cpp_class}}V8Internal::{{attribute.name}}AttributeGetter{{world_suffix}}(info);
181 TRACE_EVENT_SET_SAMPLING_STATE("V8", "V8Execution");
187 {##############################################################################}
188 {% macro constructor_getter_callback(attribute, world_suffix) %}
189 {% filter conditional(attribute.conditional_string) %}
190 static void {{attribute.name}}ConstructorGetterCallback{{world_suffix}}(v8::Local<v8::String> property, const v8::PropertyCallbackInfo<v8::Value>& info)
192 TRACE_EVENT_SET_SAMPLING_STATE("Blink", "DOMGetter");
193 {% if attribute.deprecate_as %}
194 UseCounter::countDeprecation(callingExecutionContext(info.GetIsolate()), UseCounter::{{attribute.deprecate_as}});
196 {% if attribute.measure_as %}
197 UseCounter::count(callingExecutionContext(info.GetIsolate()), UseCounter::{{attribute.measure_as}});
199 {{cpp_class}}V8Internal::{{cpp_class}}ConstructorGetter{{world_suffix}}(property, info);
200 TRACE_EVENT_SET_SAMPLING_STATE("V8", "V8Execution");
206 {##############################################################################}
207 {% macro attribute_setter(attribute, world_suffix) %}
208 {% filter conditional(attribute.conditional_string) %}
209 static void {{attribute.name}}AttributeSetter{{world_suffix}}(
210 {%- if attribute.is_expose_js_accessors %}
211 v8::Local<v8::Value> v8Value, const v8::FunctionCallbackInfo<v8::Value>& info
213 v8::Local<v8::Value> v8Value, const v8::PropertyCallbackInfo<void>& info
216 {% if attribute.is_reflect and attribute.idl_type == 'DOMString' and
218 {% set cpp_class, v8_class = 'Element', 'V8Element' %}
220 {# Local variables #}
221 {% if not attribute.is_static %}
222 v8::Handle<v8::Object> holder = info.Holder();
224 {% if attribute.has_setter_exception_state %}
225 ExceptionState exceptionState(ExceptionState::SetterContext, "{{attribute.name}}", "{{interface_name}}", holder, info.GetIsolate());
228 {% if attribute.has_type_checking_interface %}
229 {# Type checking for interface types (if interface not implemented, throw
230 TypeError), per http://www.w3.org/TR/WebIDL/#es-interface #}
231 if ({% if attribute.is_nullable %}!isUndefinedOrNull(v8Value) && {% endif %}!V8{{attribute.idl_type}}::hasInstance(v8Value, info.GetIsolate())) {
232 exceptionState.throwTypeError("The provided value is not of type '{{attribute.idl_type}}'.");
233 exceptionState.throwIfNeeded();
238 {% if attribute.put_forwards %}
239 {{cpp_class}}* proxyImpl = {{v8_class}}::toNative(holder);
240 {{attribute.cpp_type}} impl = WTF::getPtr(proxyImpl->{{attribute.name}}());
243 {% elif not attribute.is_static %}
244 {{cpp_class}}* impl = {{v8_class}}::toNative(holder);
246 {% if attribute.is_partial_interface_member and not attribute.is_static %}
247 {# instance members (non-static members) in partial interface take |impl| #}
250 {% if attribute.idl_type == 'EventHandler' and interface_name == 'Window' %}
251 if (!impl->document())
254 {# Convert JS value to C++ value #}
255 {% if attribute.idl_type != 'EventHandler' %}
256 {{attribute.v8_value_to_local_cpp_value}};
257 {% elif not is_node %}{# EventHandler hack #}
258 moveEventListenerToNewWrapper(holder, {{attribute.event_handler_getter_expression}}, v8Value, {{v8_class}}::eventListenerCacheIndex, info.GetIsolate());
260 {# Type checking, possibly throw a TypeError, per:
261 http://www.w3.org/TR/WebIDL/#es-type-mapping #}
262 {% if attribute.has_type_checking_unrestricted %}
263 {# Non-finite floating point values (NaN, +Infinity or −Infinity), per:
264 http://heycam.github.io/webidl/#es-float
265 http://heycam.github.io/webidl/#es-double #}
266 if (!std::isfinite(cppValue)) {
267 exceptionState.throwTypeError("The provided {{attribute.idl_type}} value is non-finite.");
268 exceptionState.throwIfNeeded();
271 {% elif attribute.enum_validation_expression %}
272 {# Setter ignores invalid enum values:
273 http://www.w3.org/TR/WebIDL/#idl-enums #}
274 String string = cppValue;
275 if (!({{attribute.enum_validation_expression}}))
278 {# Pre-set context #}
279 {% if attribute.is_custom_element_callbacks or
280 (attribute.is_reflect and
281 not(attribute.idl_type == 'DOMString' and is_node)) %}
282 {# Skip on compact node DOMString getters #}
283 CustomElementCallbackDispatcher::CallbackDeliveryScope deliveryScope;
285 {% if attribute.is_call_with_execution_context or
286 attribute.is_setter_call_with_execution_context %}
287 ExecutionContext* scriptContext = currentExecutionContext(info.GetIsolate());
290 {{attribute.cpp_setter}};
292 {% if attribute.is_setter_raises_exception %}
293 exceptionState.throwIfNeeded();
295 {% if attribute.cached_attribute_validation_method %}
296 V8HiddenValue::deleteHiddenValue(info.GetIsolate(), holder, v8AtomicString(info.GetIsolate(), "{{attribute.name}}")); // Invalidate the cached value.
303 {##############################################################################}
304 {% macro attribute_setter_callback(attribute, world_suffix) %}
305 {% filter conditional(attribute.conditional_string) %}
306 static void {{attribute.name}}AttributeSetterCallback{{world_suffix}}(
307 {%- if attribute.is_expose_js_accessors %}
308 const v8::FunctionCallbackInfo<v8::Value>& info
310 v8::Local<v8::String>, v8::Local<v8::Value> v8Value, const v8::PropertyCallbackInfo<void>& info
313 {% if attribute.is_expose_js_accessors %}
314 v8::Local<v8::Value> v8Value = info[0];
316 TRACE_EVENT_SET_SAMPLING_STATE("Blink", "DOMSetter");
317 {% if attribute.deprecate_as %}
318 UseCounter::countDeprecation(callingExecutionContext(info.GetIsolate()), UseCounter::{{attribute.deprecate_as}});
320 {% if attribute.measure_as %}
321 UseCounter::count(callingExecutionContext(info.GetIsolate()), UseCounter::{{attribute.measure_as}});
323 {% if world_suffix in attribute.activity_logging_world_list_for_setter %}
324 DOMWrapperWorld& world = DOMWrapperWorld::current(info.GetIsolate());
325 if (world.activityLogger()) {
326 {% if attribute.activity_logging_include_old_value_for_setter %}
327 {{cpp_class}}* impl = {{v8_class}}::toNative(info.Holder());
328 {% if attribute.cpp_value_original %}
329 {{attribute.cpp_type}} original = {{attribute.cpp_value_original}};
331 {{attribute.cpp_type}} original = {{attribute.cpp_value}};
333 v8::Handle<v8::Value> originalValue = {{attribute.cpp_value_to_v8_value}};
334 world.activityLogger()->logSetter("{{interface_name}}.{{attribute.name}}", v8Value, originalValue);
336 world.activityLogger()->logSetter("{{interface_name}}.{{attribute.name}}", v8Value);
340 {% if attribute.is_custom_element_callbacks or attribute.is_reflect %}
341 CustomElementCallbackDispatcher::CallbackDeliveryScope deliveryScope;
343 {% if attribute.has_custom_setter %}
344 {{v8_class}}::{{attribute.name}}AttributeSetterCustom(v8Value, info);
346 {{cpp_class}}V8Internal::{{attribute.name}}AttributeSetter{{world_suffix}}(v8Value, info);
348 TRACE_EVENT_SET_SAMPLING_STATE("V8", "V8Execution");