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 {# FIXME: use a local variable for holder more often and simplify below #}
17 {% if attribute.is_unforgeable or
18 interface_name == 'Window' and attribute.idl_type == 'EventHandler' %}
19 {% if interface_name == 'Window' %}
20 v8::Handle<v8::Object> holder = info.Holder();
21 {% else %}{# perform lookup first #}
22 {# FIXME: can we remove this lookup? #}
23 v8::Handle<v8::Object> holder = info.This()->FindInstanceInPrototypeChain({{v8_class}}::domTemplate(info.GetIsolate(), worldType(info.GetIsolate())));
26 {% endif %}{# Window #}
27 {{cpp_class}}* imp = {{v8_class}}::toNative(holder);
28 {% elif attribute.cached_attribute_validation_method %}
29 v8::Handle<v8::String> propertyName = v8AtomicString(info.GetIsolate(), "{{attribute.name}}");
30 {{cpp_class}}* imp = {{v8_class}}::toNative(info.Holder());
31 if (!imp->{{attribute.cached_attribute_validation_method}}()) {
32 v8::Handle<v8::Value> jsValue = getHiddenValue(info.GetIsolate(), info.Holder(), propertyName);
33 if (!jsValue.IsEmpty()) {
34 v8SetReturnValue(info, jsValue);
38 {% elif not (attribute.is_static or attribute.is_unforgeable) %}
39 {{cpp_class}}* imp = {{v8_class}}::toNative(info.Holder());
41 {% if interface_name == 'Window' and attribute.idl_type == 'EventHandler' %}
46 {% if attribute.is_call_with_execution_context %}
47 ExecutionContext* scriptContext = currentExecutionContext(info.GetIsolate());
49 {% if attribute.is_check_security_for_node or
50 attribute.is_getter_raises_exception %}
51 ExceptionState exceptionState(ExceptionState::GetterContext, "{{attribute.name}}", "{{interface_name}}", info.Holder(), info.GetIsolate());
53 {% if attribute.is_nullable %}
56 {# FIXME: consider always using a local variable for value #}
57 {% if attribute.cached_attribute_validation_method or
58 attribute.is_getter_raises_exception or
59 attribute.is_nullable or
60 attribute.reflect_only or
61 attribute.idl_type == 'EventHandler' %}
62 {{attribute.cpp_type}} {{attribute.cpp_value}} = {{attribute.cpp_value_original}};
65 {% if attribute.is_getter_raises_exception %}
66 if (UNLIKELY(exceptionState.throwIfNeeded()))
69 {% if attribute.is_check_security_for_node %}
70 {# FIXME: use a local variable to not call getter twice #}
71 if (!BindingSecurity::shouldAllowAccessToNode(info.GetIsolate(), {{attribute.cpp_value}}, exceptionState)) {
72 v8SetReturnValueNull(info);
73 exceptionState.throwIfNeeded();
77 {% if attribute.reflect_only %}
78 {{release_only_check(attribute.reflect_only, attribute.reflect_missing,
79 attribute.reflect_invalid, attribute.reflect_empty)
82 {% if attribute.is_nullable %}
84 v8SetReturnValueNull(info);
88 {% if attribute.cached_attribute_validation_method %}
89 setHiddenValue(info.GetIsolate(), info.Holder(), propertyName, {{attribute.cpp_value}}.v8Value());
91 {# v8SetReturnValue #}
92 {% if attribute.is_keep_alive_for_gc %}
93 {# FIXME: merge local variable assignment with above #}
94 {{attribute.cpp_type}} result = {{attribute.cpp_value}};
95 if (result && DOMDataStore::setReturnValueFromWrapper{{world_suffix}}<{{attribute.v8_type}}>(info.GetReturnValue(), result.get()))
97 v8::Handle<v8::Value> wrapper = toV8(result.get(), info.Holder(), info.GetIsolate());
98 if (!wrapper.IsEmpty()) {
99 setHiddenValue(info.GetIsolate(), info.Holder(), "{{attribute.name}}", wrapper);
100 {{attribute.v8_set_return_value}};
102 {% elif world_suffix %}
103 {{attribute.v8_set_return_value_for_main_world}};
105 {{attribute.v8_set_return_value}};
111 {######################################}
112 {% macro release_only_check(reflect_only_values, reflect_missing,
113 reflect_invalid, reflect_empty) %}
114 {# Attribute is limited to only known values: check that the attribute value is
115 one of those. If not, set it to the empty string.
116 http://www.whatwg.org/specs/web-apps/current-work/#limited-to-only-known-values #}
117 {# FIXME: rename resultValue to jsValue #}
118 {% if reflect_empty %}
119 if (resultValue.isNull()) {
120 {% if reflect_missing %}
121 resultValue = "{{reflect_missing}}";
125 } else if (resultValue.isEmpty()) {
126 resultValue = "{{reflect_empty}}";
128 if (resultValue.isEmpty()) {
129 {# FIXME: should use [ReflectEmpty] instead; need to change IDL files #}
130 {% if reflect_missing %}
131 resultValue = "{{reflect_missing}}";
136 {% for value in reflect_only_values %}
137 } else if (equalIgnoringCase(resultValue, "{{value}}")) {
138 resultValue = "{{value}}";
141 resultValue = "{{reflect_invalid}}";
146 {##############################################################################}
147 {% macro attribute_getter_callback(attribute, world_suffix) %}
148 {% filter conditional(attribute.conditional_string) %}
149 static void {{attribute.name}}AttributeGetterCallback{{world_suffix}}(
150 {%- if attribute.is_expose_js_accessors %}
151 const v8::FunctionCallbackInfo<v8::Value>& info
153 v8::Local<v8::String>, const v8::PropertyCallbackInfo<v8::Value>& info
156 TRACE_EVENT_SET_SAMPLING_STATE("Blink", "DOMGetter");
157 {% if attribute.deprecate_as %}
158 UseCounter::countDeprecation(activeExecutionContext(info.GetIsolate()), UseCounter::{{attribute.deprecate_as}});
160 {% if attribute.measure_as %}
161 UseCounter::count(activeExecutionContext(info.GetIsolate()), UseCounter::{{attribute.measure_as}});
163 {% if world_suffix in attribute.activity_logging_world_list_for_getter %}
164 V8PerContextData* contextData = V8PerContextData::from(info.GetIsolate()->GetCurrentContext());
165 if (contextData && contextData->activityLogger())
166 contextData->activityLogger()->log("{{interface_name}}.{{attribute.name}}", 0, 0, "Getter");
168 {% if attribute.has_custom_getter %}
169 {{v8_class}}::{{attribute.name}}AttributeGetterCustom(info);
171 {{cpp_class}}V8Internal::{{attribute.name}}AttributeGetter{{world_suffix}}(info);
173 TRACE_EVENT_SET_SAMPLING_STATE("V8", "V8Execution");
179 {##############################################################################}
180 {% macro attribute_setter(attribute, world_suffix) %}
181 {% filter conditional(attribute.conditional_string) %}
182 static void {{attribute.name}}AttributeSetter{{world_suffix}}(
183 {%- if attribute.is_expose_js_accessors %}
184 v8::Local<v8::Value> jsValue, const v8::FunctionCallbackInfo<v8::Value>& info
186 v8::Local<v8::Value> jsValue, const v8::PropertyCallbackInfo<void>& info
189 {% if attribute.is_reflect and attribute.idl_type == 'DOMString' and
191 {% set cpp_class, v8_class = 'Element', 'V8Element' %}
192 {# FIXME: Perl skips most of function, but this seems unnecessary;
193 we only need to skip the CallbackDeliveryScope #}
195 {% if attribute.has_setter_exception_state %}
196 ExceptionState exceptionState(ExceptionState::SetterContext, "{{attribute.name}}", "{{interface_name}}", info.Holder(), info.GetIsolate());
198 {% if attribute.has_strict_type_checking %}
199 {# Type checking for interface types (if interface not implemented, throw
200 TypeError), per http://www.w3.org/TR/WebIDL/#es-interface #}
201 if (!isUndefinedOrNull(jsValue) && !V8{{attribute.idl_type}}::hasInstance(jsValue, info.GetIsolate())) {
202 exceptionState.throwTypeError("The provided value is not of type '{{attribute.idl_type}}'.");
203 exceptionState.throwIfNeeded();
207 {% if attribute.put_forwards %}
208 {{cpp_class}}* proxyImp = {{v8_class}}::toNative(info.Holder());
209 {{attribute.idl_type}}* imp = proxyImp->{{attribute.name}}();
212 {% elif not attribute.is_static %}
213 {{cpp_class}}* imp = {{v8_class}}::toNative(info.Holder());
215 {% if attribute.idl_type == 'EventHandler' and interface_name == 'Window' %}
216 if (!imp->document())
219 {% if attribute.idl_type != 'EventHandler' %}
220 {{attribute.v8_value_to_local_cpp_value}};
221 {% elif not is_node %}{# EventHandler hack #}
222 moveEventListenerToNewWrapper(info.Holder(), {{attribute.event_handler_getter_expression}}, jsValue, {{v8_class}}::eventListenerCacheIndex, info.GetIsolate());
224 {% if attribute.enum_validation_expression %}
225 {# Setter ignores invalid enum values: http://www.w3.org/TR/WebIDL/#idl-enums #}
226 String string = cppValue;
227 if (!({{attribute.enum_validation_expression}}))
230 {% if attribute.is_custom_element_callbacks or
231 (attribute.is_reflect and
232 not(attribute.idl_type == 'DOMString' and is_node)) %}
233 {# Skip on compact node DOMString getters #}
234 CustomElementCallbackDispatcher::CallbackDeliveryScope deliveryScope;
236 {% if attribute.is_call_with_execution_context or
237 attribute.is_setter_call_with_execution_context %}
238 ExecutionContext* scriptContext = currentExecutionContext(info.GetIsolate());
240 {{attribute.cpp_setter}};
241 {% if attribute.is_setter_raises_exception %}
242 exceptionState.throwIfNeeded();
244 {% if attribute.cached_attribute_validation_method %}
245 deleteHiddenValue(info.GetIsolate(), info.Holder(), "{{attribute.name}}"); // Invalidate the cached value.
252 {##############################################################################}
253 {% macro attribute_setter_callback(attribute, world_suffix) %}
254 {% filter conditional(attribute.conditional_string) %}
255 static void {{attribute.name}}AttributeSetterCallback{{world_suffix}}(
256 {%- if attribute.is_expose_js_accessors %}
257 const v8::FunctionCallbackInfo<v8::Value>& info
259 v8::Local<v8::String>, v8::Local<v8::Value> jsValue, const v8::PropertyCallbackInfo<void>& info
262 {% if attribute.is_expose_js_accessors %}
263 v8::Local<v8::Value> jsValue = info[0];
265 TRACE_EVENT_SET_SAMPLING_STATE("Blink", "DOMSetter");
266 {% if attribute.deprecate_as %}
267 UseCounter::countDeprecation(activeExecutionContext(info.GetIsolate()), UseCounter::{{attribute.deprecate_as}});
269 {% if attribute.measure_as %}
270 UseCounter::count(activeExecutionContext(info.GetIsolate()), UseCounter::{{attribute.measure_as}});
272 {% if world_suffix in attribute.activity_logging_world_list_for_setter %}
273 V8PerContextData* contextData = V8PerContextData::from(info.GetIsolate()->GetCurrentContext());
274 if (contextData && contextData->activityLogger()) {
275 v8::Handle<v8::Value> loggerArg[] = { jsValue };
276 contextData->activityLogger()->log("{{interface_name}}.{{attribute.name}}", 1, &loggerArg[0], "Setter");
279 {% if attribute.is_custom_element_callbacks or attribute.is_reflect %}
280 CustomElementCallbackDispatcher::CallbackDeliveryScope deliveryScope;
282 {% if attribute.has_custom_setter %}
283 {{v8_class}}::{{attribute.name}}AttributeSetterCustom(jsValue, info);
285 {{cpp_class}}V8Internal::{{attribute.name}}AttributeSetter{{world_suffix}}(jsValue, info);
287 TRACE_EVENT_SET_SAMPLING_STATE("V8", "V8Execution");