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
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' %}
17 {% if not attribute.is_static %}
18 v8::Handle<v8::Object> holder = info.Holder();
21 {% if attribute.cached_attribute_validation_method %}
22 v8::Handle<v8::String> propertyName = v8AtomicString(info.GetIsolate(), "{{attribute.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.GetIsolate(), holder, propertyName);
26 if (!v8Value.IsEmpty()) {
27 v8SetReturnValue(info, v8Value);
31 {% elif not attribute.is_static %}
32 {{cpp_class}}* impl = {{v8_class}}::toNative(holder);
34 {% if interface_name == 'Window' and attribute.idl_type == 'EventHandler' %}
35 if (!impl->document())
39 {% if attribute.is_call_with_execution_context %}
40 ExecutionContext* executionContext = currentExecutionContext(info.GetIsolate());
42 {% if attribute.is_call_with_script_state %}
43 ScriptState* scriptState = ScriptState::current(info.GetIsolate());
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());
49 {% if attribute.is_explicit_nullable %}
52 {% if attribute.is_implemented_in_private_script %}
53 {{attribute.cpp_type}} result{{attribute.cpp_type_initializer}};
54 if (!{{attribute.cpp_value_original}})
56 {% elif attribute.cpp_value_original %}
57 {{attribute.cpp_type}} {{attribute.cpp_value}}({{attribute.cpp_value_original}});
60 {% if attribute.is_getter_raises_exception %}
61 if (UNLIKELY(exceptionState.throwIfNeeded()))
64 {% if attribute.is_check_security_for_node %}
65 if (!BindingSecurity::shouldAllowAccessToNode(info.GetIsolate(), {{attribute.cpp_value}}, exceptionState)) {
66 v8SetReturnValueNull(info);
67 exceptionState.throwIfNeeded();
71 {% if attribute.reflect_only %}
72 {{release_only_check(attribute.reflect_only, attribute.reflect_missing,
73 attribute.reflect_invalid, attribute.reflect_empty,
77 {% if attribute.is_explicit_nullable %}
79 v8SetReturnValueNull(info);
83 {% if attribute.cached_attribute_validation_method %}
84 V8HiddenValue::setHiddenValue(info.GetIsolate(), holder, propertyName, {{attribute.cpp_value_to_v8_value}});
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()))
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}};
95 {% elif world_suffix %}
96 {{attribute.v8_set_return_value_for_main_world}};
98 {{attribute.v8_set_return_value}};
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 %}
111 if ({{cpp_value}}.isNull()) {
112 {% if reflect_missing %}
113 {{cpp_value}} = "{{reflect_missing}}";
117 } else if ({{cpp_value}}.isEmpty()) {
118 {{cpp_value}} = "{{reflect_empty}}";
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}}";
128 {% for value in reflect_only_values %}
129 } else if (equalIgnoringCase({{cpp_value}}, "{{value}}")) {
130 {{cpp_value}} = "{{value}}";
133 {{cpp_value}} = "{{reflect_invalid}}";
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
145 v8::Local<v8::String>, const v8::PropertyCallbackInfo<v8::Value>& info
148 TRACE_EVENT_SET_SAMPLING_STATE("blink", "DOMGetter");
149 {% if attribute.deprecate_as %}
150 UseCounter::countDeprecation(callingExecutionContext(info.GetIsolate()), UseCounter::{{attribute.deprecate_as}});
152 {% if attribute.measure_as %}
153 UseCounter::count(callingExecutionContext(info.GetIsolate()), UseCounter::{{attribute.measure_as}});
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())
161 if (contextData && contextData->activityLogger())
163 contextData->activityLogger()->logGetter("{{interface_name}}.{{attribute.name}}");
165 {% if attribute.has_custom_getter %}
166 {{v8_class}}::{{attribute.name}}AttributeGetterCustom(info);
168 {{cpp_class}}V8Internal::{{attribute.name}}AttributeGetter{{world_suffix}}(info);
170 TRACE_EVENT_SET_SAMPLING_STATE("v8", "V8Execution");
176 {##############################################################################}
177 {% macro constructor_getter_callback(attribute, world_suffix) %}
178 {% filter conditional(attribute.conditional_string) %}
179 static void {{attribute.name}}ConstructorGetterCallback{{world_suffix}}(v8::Local<v8::String> property, const v8::PropertyCallbackInfo<v8::Value>& info)
181 TRACE_EVENT_SET_SAMPLING_STATE("blink", "DOMGetter");
182 {% if attribute.deprecate_as %}
183 UseCounter::countDeprecation(callingExecutionContext(info.GetIsolate()), UseCounter::{{attribute.deprecate_as}});
185 {% if attribute.measure_as %}
186 UseCounter::count(callingExecutionContext(info.GetIsolate()), UseCounter::{{attribute.measure_as}});
188 {{cpp_class}}V8Internal::{{cpp_class}}ConstructorGetter{{world_suffix}}(property, info);
189 TRACE_EVENT_SET_SAMPLING_STATE("v8", "V8Execution");
195 {##############################################################################}
196 {% macro attribute_setter(attribute, world_suffix) %}
197 {% filter conditional(attribute.conditional_string) %}
198 static void {{attribute.name}}AttributeSetter{{world_suffix}}(
199 {%- if attribute.is_expose_js_accessors %}
200 v8::Local<v8::Value> v8Value, const v8::FunctionCallbackInfo<v8::Value>& info
202 v8::Local<v8::Value> v8Value, const v8::PropertyCallbackInfo<void>& info
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' %}
209 {# Local variables #}
210 {% if not attribute.is_static %}
211 v8::Handle<v8::Object> holder = info.Holder();
213 {% if attribute.has_setter_exception_state %}
214 ExceptionState exceptionState(ExceptionState::SetterContext, "{{attribute.name}}", "{{interface_name}}", holder, info.GetIsolate());
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();
227 {% if attribute.put_forwards %}
228 {{cpp_class}}* proxyImpl = {{v8_class}}::toNative(holder);
229 {{attribute.cpp_type}} impl = WTF::getPtr(proxyImpl->{{attribute.name}}());
232 {% elif not attribute.is_static %}
233 {{cpp_class}}* impl = {{v8_class}}::toNative(holder);
235 {% if attribute.idl_type == 'EventHandler' and interface_name == 'Window' %}
236 if (!impl->document())
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());
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();
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}}))
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 CustomElementCallbackDispatcher::CallbackDeliveryScope deliveryScope;
270 {% if attribute.is_call_with_execution_context or
271 attribute.is_setter_call_with_execution_context %}
272 ExecutionContext* executionContext = currentExecutionContext(info.GetIsolate());
275 {{attribute.cpp_setter}};
277 {% if attribute.is_setter_raises_exception %}
278 exceptionState.throwIfNeeded();
280 {% if attribute.cached_attribute_validation_method %}
281 V8HiddenValue::deleteHiddenValue(info.GetIsolate(), holder, v8AtomicString(info.GetIsolate(), "{{attribute.name}}")); // Invalidate the cached value.
288 {##############################################################################}
289 {% macro attribute_setter_callback(attribute, world_suffix) %}
290 {% filter conditional(attribute.conditional_string) %}
291 static void {{attribute.name}}AttributeSetterCallback{{world_suffix}}(
292 {%- if attribute.is_expose_js_accessors %}
293 const v8::FunctionCallbackInfo<v8::Value>& info
295 v8::Local<v8::String>, v8::Local<v8::Value> v8Value, const v8::PropertyCallbackInfo<void>& info
298 {% if attribute.is_expose_js_accessors %}
299 v8::Local<v8::Value> v8Value = info[0];
301 TRACE_EVENT_SET_SAMPLING_STATE("blink", "DOMSetter");
302 {% if attribute.deprecate_as %}
303 UseCounter::countDeprecation(callingExecutionContext(info.GetIsolate()), UseCounter::{{attribute.deprecate_as}});
305 {% if attribute.measure_as %}
306 UseCounter::count(callingExecutionContext(info.GetIsolate()), UseCounter::{{attribute.measure_as}});
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()) {
314 if (contextData && contextData->activityLogger()) {
316 {% if attribute.activity_logging_include_old_value_for_setter %}
317 {{cpp_class}}* impl = {{v8_class}}::toNative(info.Holder());
318 {% if attribute.cpp_value_original %}
319 {{attribute.cpp_type}} {{attribute.cpp_value}}({{attribute.cpp_value_original}});
321 v8::Handle<v8::Value> originalValue = {{attribute.cpp_value_to_v8_value}};
322 contextData->activityLogger()->logSetter("{{interface_name}}.{{attribute.name}}", v8Value, originalValue);
324 contextData->activityLogger()->logSetter("{{interface_name}}.{{attribute.name}}", v8Value);
328 {% if attribute.is_custom_element_callbacks or attribute.is_reflect %}
329 CustomElementCallbackDispatcher::CallbackDeliveryScope deliveryScope;
331 {% if attribute.has_custom_setter %}
332 {{v8_class}}::{{attribute.name}}AttributeSetterCustom(v8Value, info);
334 {{cpp_class}}V8Internal::{{attribute.name}}AttributeSetter{{world_suffix}}(v8Value, info);
336 TRACE_EVENT_SET_SAMPLING_STATE("v8", "V8Execution");
342 {##############################################################################}
343 {% macro attribute_getter_implemented_in_private_script(attribute) %}
344 bool {{v8_class}}::PrivateScript::{{attribute.name}}AttributeGetter(LocalFrame* frame, {{cpp_class}}* holderImpl, {{attribute.cpp_type}}* result)
348 v8::HandleScope handleScope(toIsolate(frame));
349 ScriptForbiddenScope::AllowUserAgentScript script;
350 v8::Handle<v8::Context> context = toV8Context(frame, DOMWrapperWorld::privateScriptIsolatedWorld());
351 if (context.IsEmpty())
353 ScriptState* scriptState = ScriptState::from(context);
354 if (!scriptState->executionContext())
357 ScriptState::Scope scope(scriptState);
358 v8::Handle<v8::Value> holder = toV8(holderImpl, scriptState->context()->Global(), scriptState->isolate());
360 ExceptionState exceptionState(ExceptionState::GetterContext, "{{attribute.name}}", "{{cpp_class}}", scriptState->context()->Global(), scriptState->isolate());
362 v8::Handle<v8::Value> v8Value = PrivateScriptRunner::runDOMAttributeGetter(scriptState, "{{cpp_class}}", "{{attribute.name}}", holder);
363 if (block.HasCaught()) {
364 if (!PrivateScriptRunner::rethrowExceptionInPrivateScript(scriptState->isolate(), exceptionState, block)) {
365 // FIXME: We should support more exceptions.
366 RELEASE_ASSERT_NOT_REACHED();
371 {{attribute.private_script_v8_value_to_local_cpp_value}};
372 RELEASE_ASSERT(!exceptionState.hadException());
379 {% macro attribute_setter_implemented_in_private_script(attribute) %}
380 bool {{v8_class}}::PrivateScript::{{attribute.name}}AttributeSetter(LocalFrame* frame, {{cpp_class}}* holderImpl, {{attribute.argument_cpp_type}} cppValue)
384 v8::HandleScope handleScope(toIsolate(frame));
385 ScriptForbiddenScope::AllowUserAgentScript script;
386 v8::Handle<v8::Context> context = toV8Context(frame, DOMWrapperWorld::privateScriptIsolatedWorld());
387 if (context.IsEmpty())
389 ScriptState* scriptState = ScriptState::from(context);
390 if (!scriptState->executionContext())
393 ScriptState::Scope scope(scriptState);
394 v8::Handle<v8::Value> holder = toV8(holderImpl, scriptState->context()->Global(), scriptState->isolate());
396 ExceptionState exceptionState(ExceptionState::SetterContext, "{{attribute.name}}", "{{cpp_class}}", scriptState->context()->Global(), scriptState->isolate());
398 PrivateScriptRunner::runDOMAttributeSetter(scriptState, "{{cpp_class}}", "{{attribute.name}}", holder, {{attribute.private_script_cpp_value_to_v8_value}});
399 if (block.HasCaught()) {
400 if (!PrivateScriptRunner::rethrowExceptionInPrivateScript(scriptState->isolate(), exceptionState, block)) {
401 // FIXME: We should support more exceptions.
402 RELEASE_ASSERT_NOT_REACHED();