Home | History | Annotate | Download | only in templates
      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
      7 {%- else %}
      8 const 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 %}
    111 if ({{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 %}
    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}}";
    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) %}
    141 static void {{attribute.name}}AttributeGetterCallback{{world_suffix}}(
    142 {%- if attribute.is_expose_js_accessors %}
    143 const v8::FunctionCallbackInfo<v8::Value>& info
    144 {%- else %}
    145 v8::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) %}
    179 static 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) %}
    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
    201 {%- else %}
    202 v8::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) %}
    291 static void {{attribute.name}}AttributeSetterCallback{{world_suffix}}(
    292 {%- if attribute.is_expose_js_accessors %}
    293 const v8::FunctionCallbackInfo<v8::Value>& info
    294 {%- else %}
    295 v8::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) %}
    335 bool {{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) %}
    365 bool {{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