Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / bindings / templates / attributes.cpp
index 8bb8b93..d72b262 100644 (file)
@@ -11,15 +11,21 @@ const v8::PropertyCallbackInfo<v8::Value>& info
     {% if attribute.is_reflect and not attribute.is_url and
           attribute.idl_type == 'DOMString' and is_node %}
     {% set cpp_class, v8_class = 'Element', 'V8Element' %}
-    {# FIXME: Perl skips most of function, but this seems unnecessary #}
     {% endif %}
-    {% if attribute.is_unforgeable %}
+    {# imp #}
+    {# FIXME: use a local variable for holder more often and simplify below #}
+    {% if attribute.is_unforgeable or
+          interface_name == 'Window' and attribute.idl_type == 'EventHandler' %}
+    {% if interface_name == 'Window' %}
+    v8::Handle<v8::Object> holder = info.Holder();
+    {% else %}{# perform lookup first #}
+    {# FIXME: can we remove this lookup? #}
     v8::Handle<v8::Object> holder = info.This()->FindInstanceInPrototypeChain({{v8_class}}::domTemplate(info.GetIsolate(), worldType(info.GetIsolate())));
     if (holder.IsEmpty())
         return;
+    {% endif %}{# Window #}
     {{cpp_class}}* imp = {{v8_class}}::toNative(holder);
-    {% endif %}
-    {% if attribute.cached_attribute_validation_method %}
+    {% elif attribute.cached_attribute_validation_method %}
     v8::Handle<v8::String> propertyName = v8AtomicString(info.GetIsolate(), "{{attribute.name}}");
     {{cpp_class}}* imp = {{v8_class}}::toNative(info.Holder());
     if (!imp->{{attribute.cached_attribute_validation_method}}()) {
@@ -32,52 +38,69 @@ const v8::PropertyCallbackInfo<v8::Value>& info
     {% elif not (attribute.is_static or attribute.is_unforgeable) %}
     {{cpp_class}}* imp = {{v8_class}}::toNative(info.Holder());
     {% endif %}
+    {% if interface_name == 'Window' and attribute.idl_type == 'EventHandler' %}
+    if (!imp->document())
+        return;
+    {% endif %}
+    {# Local variables #}
     {% if attribute.is_call_with_execution_context %}
-    ExecutionContext* scriptContext = getExecutionContext();
+    ExecutionContext* scriptContext = currentExecutionContext(info.GetIsolate());
     {% endif %}
-    {# Special cases #}
     {% if attribute.is_check_security_for_node or
           attribute.is_getter_raises_exception %}
     ExceptionState exceptionState(ExceptionState::GetterContext, "{{attribute.name}}", "{{interface_name}}", info.Holder(), info.GetIsolate());
     {% endif %}
+    {% if attribute.is_nullable %}
+    bool isNull = false;
+    {% endif %}
+    {# FIXME: consider always using a local variable for value #}
+    {% if attribute.cached_attribute_validation_method or
+          attribute.is_getter_raises_exception or
+          attribute.is_nullable or
+          attribute.reflect_only or
+          attribute.idl_type == 'EventHandler' %}
+    {{attribute.cpp_type}} {{attribute.cpp_value}} = {{attribute.cpp_value_original}};
+    {% endif %}
+    {# Checks #}
+    {% if attribute.is_getter_raises_exception %}
+    if (UNLIKELY(exceptionState.throwIfNeeded()))
+        return;
+    {% endif %}
     {% if attribute.is_check_security_for_node %}
-    {# FIXME: consider using a local variable to not call getter twice #}
-    if (!BindingSecurity::shouldAllowAccessToNode({{attribute.cpp_value}}, exceptionState)) {
+    {# FIXME: use a local variable to not call getter twice #}
+    if (!BindingSecurity::shouldAllowAccessToNode(info.GetIsolate(), {{attribute.cpp_value}}, exceptionState)) {
         v8SetReturnValueNull(info);
         exceptionState.throwIfNeeded();
         return;
     }
     {% endif %}
-    {% if attribute.is_getter_raises_exception %}
-    {{attribute.cpp_type}} {{attribute.cpp_value}} = {{attribute.cpp_value_original}};
-    if (UNLIKELY(exceptionState.throwIfNeeded()))
-        return;
+    {% if attribute.reflect_only %}
+    {{release_only_check(attribute.reflect_only, attribute.reflect_missing,
+                         attribute.reflect_invalid, attribute.reflect_empty)
+      | indent}}
     {% endif %}
     {% if attribute.is_nullable %}
-    bool isNull = false;
-    {{attribute.cpp_type}} {{attribute.cpp_value}} = {{attribute.cpp_value_original}};
     if (isNull) {
         v8SetReturnValueNull(info);
         return;
     }
-    {% elif attribute.idl_type == 'EventHandler' or
-            attribute.cached_attribute_validation_method %}
-    {# FIXME: consider merging all these assign to local variable statements #}
-    {{attribute.cpp_type}} {{attribute.cpp_value}} = {{attribute.cpp_value_original}};
     {% endif %}
     {% if attribute.cached_attribute_validation_method %}
     setHiddenValue(info.GetIsolate(), info.Holder(), propertyName, {{attribute.cpp_value}}.v8Value());
     {% endif %}
-    {# End special cases #}
+    {# v8SetReturnValue #}
     {% if attribute.is_keep_alive_for_gc %}
+    {# FIXME: merge local variable assignment with above #}
     {{attribute.cpp_type}} result = {{attribute.cpp_value}};
-    if (result && DOMDataStore::setReturnValueFromWrapper<{{attribute.v8_type}}>(info.GetReturnValue(), result.get()))
+    if (result && DOMDataStore::setReturnValueFromWrapper{{world_suffix}}<{{attribute.v8_type}}>(info.GetReturnValue(), result.get()))
         return;
     v8::Handle<v8::Value> wrapper = toV8(result.get(), info.Holder(), info.GetIsolate());
     if (!wrapper.IsEmpty()) {
         setHiddenValue(info.GetIsolate(), info.Holder(), "{{attribute.name}}", wrapper);
         {{attribute.v8_set_return_value}};
     }
+    {% elif world_suffix %}
+    {{attribute.v8_set_return_value_for_main_world}};
     {% else %}
     {{attribute.v8_set_return_value}};
     {% endif %}
@@ -85,6 +108,40 @@ const v8::PropertyCallbackInfo<v8::Value>& info
 {% endfilter %}
 {% endmacro %}
 
+{######################################}
+{% macro release_only_check(reflect_only_values, reflect_missing,
+                            reflect_invalid, reflect_empty) %}
+{# Attribute is limited to only known values: check that the attribute value is
+   one of those. If not, set it to the empty string.
+   http://www.whatwg.org/specs/web-apps/current-work/#limited-to-only-known-values #}
+{# FIXME: rename resultValue to jsValue #}
+{% if reflect_empty %}
+if (resultValue.isNull()) {
+{% if reflect_missing %}
+    resultValue = "{{reflect_missing}}";
+{% else %}
+    ;
+{% endif %}
+} else if (resultValue.isEmpty()) {
+    resultValue = "{{reflect_empty}}";
+{% else %}
+if (resultValue.isEmpty()) {
+{# FIXME: should use [ReflectEmpty] instead; need to change IDL files #}
+{% if reflect_missing %}
+    resultValue = "{{reflect_missing}}";
+{% else %}
+    ;
+{% endif %}
+{% endif %}
+{% for value in reflect_only_values %}
+} else if (equalIgnoringCase(resultValue, "{{value}}")) {
+    resultValue = "{{value}}";
+{% endfor %}
+} else {
+    resultValue = "{{reflect_invalid}}";
+}
+{% endmacro %}
+
 
 {##############################################################################}
 {% macro attribute_getter_callback(attribute, world_suffix) %}
@@ -98,10 +155,10 @@ v8::Local<v8::String>, const v8::PropertyCallbackInfo<v8::Value>& info
 {
     TRACE_EVENT_SET_SAMPLING_STATE("Blink", "DOMGetter");
     {% if attribute.deprecate_as %}
-    UseCounter::countDeprecation(activeExecutionContext(), UseCounter::{{attribute.deprecate_as}});
+    UseCounter::countDeprecation(activeExecutionContext(info.GetIsolate()), UseCounter::{{attribute.deprecate_as}});
     {% endif %}
     {% if attribute.measure_as %}
-    UseCounter::count(activeExecutionContext(), UseCounter::{{attribute.measure_as}});
+    UseCounter::count(activeExecutionContext(info.GetIsolate()), UseCounter::{{attribute.measure_as}});
     {% endif %}
     {% if world_suffix in attribute.activity_logging_world_list_for_getter %}
     V8PerContextData* contextData = V8PerContextData::from(info.GetIsolate()->GetCurrentContext());
@@ -132,7 +189,8 @@ v8::Local<v8::Value> jsValue, const v8::PropertyCallbackInfo<void>& info
     {% if attribute.is_reflect and attribute.idl_type == 'DOMString' and
           is_node %}
     {% set cpp_class, v8_class = 'Element', 'V8Element' %}
-    {# FIXME: Perl skips most of function, but this seems unnecessary #}
+    {# FIXME: Perl skips most of function, but this seems unnecessary;
+       we only need to skip the CallbackDeliveryScope #}
     {% endif %}
     {% if attribute.has_setter_exception_state %}
     ExceptionState exceptionState(ExceptionState::SetterContext, "{{attribute.name}}", "{{interface_name}}", info.Holder(), info.GetIsolate());
@@ -153,7 +211,7 @@ v8::Local<v8::Value> jsValue, const v8::PropertyCallbackInfo<void>& info
         return;
     {% elif not attribute.is_static %}
     {{cpp_class}}* imp = {{v8_class}}::toNative(info.Holder());
-    {% endif %}
+    {% endif %}{# imp #}
     {% if attribute.idl_type == 'EventHandler' and interface_name == 'Window' %}
     if (!imp->document())
         return;
@@ -161,7 +219,7 @@ v8::Local<v8::Value> jsValue, const v8::PropertyCallbackInfo<void>& info
     {% if attribute.idl_type != 'EventHandler' %}
     {{attribute.v8_value_to_local_cpp_value}};
     {% elif not is_node %}{# EventHandler hack #}
-    transferHiddenDependency(info.Holder(), {{attribute.event_handler_getter_expression}}, jsValue, {{v8_class}}::eventListenerCacheIndex, info.GetIsolate());
+    moveEventListenerToNewWrapper(info.Holder(), {{attribute.event_handler_getter_expression}}, jsValue, {{v8_class}}::eventListenerCacheIndex, info.GetIsolate());
     {% endif %}
     {% if attribute.enum_validation_expression %}
     {# Setter ignores invalid enum values: http://www.w3.org/TR/WebIDL/#idl-enums #}
@@ -169,12 +227,15 @@ v8::Local<v8::Value> jsValue, const v8::PropertyCallbackInfo<void>& info
     if (!({{attribute.enum_validation_expression}}))
         return;
     {% endif %}
-    {% if attribute.is_reflect and
-          not(attribute.idl_type == 'DOMString' and is_node) %}
+    {% if attribute.is_custom_element_callbacks or
+          (attribute.is_reflect and
+           not(attribute.idl_type == 'DOMString' and is_node)) %}
+    {# Skip on compact node DOMString getters #}
     CustomElementCallbackDispatcher::CallbackDeliveryScope deliveryScope;
     {% endif %}
-    {% if attribute.is_call_with_execution_context %}
-    ExecutionContext* scriptContext = getExecutionContext();
+    {% if attribute.is_call_with_execution_context or
+          attribute.is_setter_call_with_execution_context %}
+    ExecutionContext* scriptContext = currentExecutionContext(info.GetIsolate());
     {% endif %}
     {{attribute.cpp_setter}};
     {% if attribute.is_setter_raises_exception %}
@@ -203,10 +264,10 @@ v8::Local<v8::String>, v8::Local<v8::Value> jsValue, const v8::PropertyCallbackI
     {% endif %}
     TRACE_EVENT_SET_SAMPLING_STATE("Blink", "DOMSetter");
     {% if attribute.deprecate_as %}
-    UseCounter::countDeprecation(activeExecutionContext(), UseCounter::{{attribute.deprecate_as}});
+    UseCounter::countDeprecation(activeExecutionContext(info.GetIsolate()), UseCounter::{{attribute.deprecate_as}});
     {% endif %}
     {% if attribute.measure_as %}
-    UseCounter::count(activeExecutionContext(), UseCounter::{{attribute.measure_as}});
+    UseCounter::count(activeExecutionContext(info.GetIsolate()), UseCounter::{{attribute.measure_as}});
     {% endif %}
     {% if world_suffix in attribute.activity_logging_world_list_for_setter %}
     V8PerContextData* contextData = V8PerContextData::from(info.GetIsolate()->GetCurrentContext());
@@ -215,7 +276,7 @@ v8::Local<v8::String>, v8::Local<v8::Value> jsValue, const v8::PropertyCallbackI
         contextData->activityLogger()->log("{{interface_name}}.{{attribute.name}}", 1, &loggerArg[0], "Setter");
     }
     {% endif %}
-    {% if attribute.is_reflect %}
+    {% if attribute.is_custom_element_callbacks or attribute.is_reflect %}
     CustomElementCallbackDispatcher::CallbackDeliveryScope deliveryScope;
     {% endif %}
     {% if attribute.has_custom_setter %}