| {% from 'utilities.cpp.tmpl' import declare_enum_validation_variable %} |
| {% from 'utilities.cpp.tmpl' import v8_value_to_local_cpp_value %} |
| {#############################################################################} |
| {% macro assign_and_return_if_hasinstance(member) %} |
| {% if member.is_array_buffer_or_view_type %} |
| if (v8Value->Is{{member.type_name}}()) { |
| {% else %} |
| if (V8{{member.type_name}}::hasInstance(v8Value, isolate)) { |
| {% endif %} |
| {% if member.is_array_buffer_view_or_typed_array %} |
| {{member.cpp_local_type}} cppValue = ToNotShared<{{member.cpp_local_type}}>(isolate, v8Value, exceptionState); |
| if (exceptionState.HadException()) |
| return; |
| {% else %} |
| {{member.cpp_local_type}} cppValue = V8{{member.type_name}}::toImpl(v8::Local<v8::Object>::Cast(v8Value)); |
| {% endif %} |
| impl.set{{member.type_name}}(cppValue); |
| return; |
| } |
| {% endmacro %} |
| {#############################################################################} |
| {% filter format_blink_cpp_source_code %} |
| {% include 'copyright_block.txt' %} |
| #include "{{this_include_header_name}}.h" |
| |
| {% for filename in cpp_includes %} |
| #include "{{filename}}" |
| {% endfor %} |
| |
| namespace blink { |
| |
| {{cpp_class}}::{{cpp_class}}() : m_type(SpecificTypeNone) {} |
| |
| {% for member in members %} |
| {{member.rvalue_cpp_type}} {{cpp_class}}::getAs{{member.type_name}}() const { |
| DCHECK(is{{member.type_name}}()); |
| return m_{{member.cpp_name}}; |
| } |
| |
| void {{cpp_class}}::set{{member.type_name}}({{member.rvalue_cpp_type}} value) { |
| DCHECK(isNull()); |
| {% if member.enum_values %} |
| NonThrowableExceptionState exceptionState; |
| {{declare_enum_validation_variable(member.enum_values) | indent(2)}} |
| if (!IsValidEnum(value, validValues, WTF_ARRAY_LENGTH(validValues), "{{member.type_name}}", exceptionState)) { |
| NOTREACHED(); |
| return; |
| } |
| {% endif %} |
| {% if member.is_array_buffer_view_or_typed_array %} |
| m_{{member.cpp_name}} = {{member.cpp_type}}(value.View()); |
| {% else %} |
| m_{{member.cpp_name}} = value; |
| {% endif %} |
| m_type = {{member.specific_type_enum}}; |
| } |
| |
| {{cpp_class}} {{cpp_class}}::from{{member.type_name}}({{member.rvalue_cpp_type}} value) { |
| {{cpp_class}} container; |
| container.set{{member.type_name}}(value); |
| return container; |
| } |
| |
| {% endfor %} |
| {{cpp_class}}::{{cpp_class}}(const {{cpp_class}}&) = default; |
| {{cpp_class}}::~{{cpp_class}}() = default; |
| {{cpp_class}}& {{cpp_class}}::operator=(const {{cpp_class}}&) = default; |
| |
| DEFINE_TRACE({{cpp_class}}) { |
| {% for member in members if member.is_traceable %} |
| visitor->Trace(m_{{member.cpp_name}}); |
| {% endfor %} |
| } |
| |
| void {{v8_class}}::toImpl(v8::Isolate* isolate, v8::Local<v8::Value> v8Value, {{cpp_class}}& impl, UnionTypeConversionMode conversionMode, ExceptionState& exceptionState) { |
| if (v8Value.IsEmpty()) |
| return; |
| |
| {# The numbers in the following comments refer to the steps described in |
| http://heycam.github.io/webidl/#es-union #} |
| {# 1. null or undefined #} |
| if (conversionMode == UnionTypeConversionMode::kNullable && IsUndefinedOrNull(v8Value)) |
| return; |
| |
| {% if dictionary_type %} |
| {# 3. Dictionaries for null or undefined #} |
| if (IsUndefinedOrNull(v8Value)) { |
| {{v8_value_to_local_cpp_value(dictionary_type) | indent}} |
| impl.set{{dictionary_type.type_name}}(cppValue); |
| return; |
| } |
| |
| {% endif %} |
| {# 4. Platform objects (interfaces) #} |
| {% for interface in interface_types %} |
| {{assign_and_return_if_hasinstance(interface) | indent(2)}} |
| |
| {% endfor %} |
| {# 8. ArrayBuffer #} |
| {% if array_buffer_type %} |
| {{assign_and_return_if_hasinstance(array_buffer_type) | indent(2)}} |
| |
| {% endif %} |
| {# 9., 10. ArrayBufferView #} |
| {# FIXME: Individual typed arrays (e.g. Uint8Array) aren\'t supported yet. #} |
| {% if array_buffer_view_type %} |
| {{assign_and_return_if_hasinstance(array_buffer_view_type) | indent(2)}} |
| |
| {% endif %} |
| {% if array_or_sequence_type %} |
| {# 11.1, 11.2. Arrays and Sequences #} |
| if (HasCallableIteratorSymbol(isolate, v8Value, exceptionState)) { |
| {{v8_value_to_local_cpp_value(array_or_sequence_type) | indent}} |
| impl.set{{array_or_sequence_type.type_name}}(cppValue); |
| return; |
| } |
| |
| {% endif %} |
| {% if dictionary_type %} |
| {# 11.3. Dictionaries #} |
| if (v8Value->IsObject()) { |
| {{v8_value_to_local_cpp_value(dictionary_type) | indent}} |
| impl.set{{dictionary_type.type_name}}(cppValue); |
| return; |
| } |
| |
| {% endif %} |
| {# 11.4. Records #} |
| {% if record_type %} |
| if (v8Value->IsObject()) { |
| {{v8_value_to_local_cpp_value(record_type) | indent}} |
| impl.set{{record_type.type_name}}(cppValue); |
| return; |
| } |
| |
| {% endif %} |
| {# TODO(bashi): Support 11.5 Callback interface when we need it #} |
| {# 11.6. Objects #} |
| {% if object_type %} |
| if (IsUndefinedOrNull(v8Value) || v8Value->IsObject()) { |
| {{v8_value_to_local_cpp_value(object_type) | indent}} |
| impl.set{{object_type.type_name}}(cppValue); |
| return; |
| } |
| |
| {% endif %} |
| {# FIXME: In some cases, we can omit boolean and numeric type checks because |
| we have fallback conversions. (step 16 and 17) #} |
| {% if boolean_type %} |
| {# 12. Boolean #} |
| if (v8Value->IsBoolean()) { |
| impl.setBoolean(v8Value.As<v8::Boolean>()->Value()); |
| return; |
| } |
| |
| {% endif %} |
| {% if numeric_type %} |
| {# 13. Number #} |
| if (v8Value->IsNumber()) { |
| {{v8_value_to_local_cpp_value(numeric_type) | indent}} |
| impl.set{{numeric_type.type_name}}(cppValue); |
| return; |
| } |
| |
| {% endif %} |
| {% if string_type %} |
| {# 14. String #} |
| { |
| {{v8_value_to_local_cpp_value(string_type) | indent}} |
| {% if string_type.enum_values %} |
| {{declare_enum_validation_variable(string_type.enum_values) | indent}} |
| if (!IsValidEnum(cppValue, validValues, WTF_ARRAY_LENGTH(validValues), "{{string_type.type_name}}", exceptionState)) |
| return; |
| {% endif %} |
| impl.set{{string_type.type_name}}(cppValue); |
| return; |
| } |
| |
| {# 15. Number (fallback) #} |
| {% elif numeric_type %} |
| { |
| {{v8_value_to_local_cpp_value(numeric_type) | indent}} |
| impl.set{{numeric_type.type_name}}(cppValue); |
| return; |
| } |
| |
| {# 16. Boolean (fallback) #} |
| {% elif boolean_type %} |
| { |
| impl.setBoolean(v8Value->BooleanValue()); |
| return; |
| } |
| |
| {% else %} |
| {# 17. TypeError #} |
| exceptionState.ThrowTypeError("The provided value is not of type '{{type_string}}'"); |
| {% endif %} |
| } |
| |
| v8::Local<v8::Value> ToV8(const {{cpp_class}}& impl, v8::Local<v8::Object> creationContext, v8::Isolate* isolate) { |
| switch (impl.m_type) { |
| case {{cpp_class}}::SpecificTypeNone: |
| {# FIXME: We might want to return undefined in some cases #} |
| return v8::Null(isolate); |
| {% for member in members %} |
| case {{cpp_class}}::{{member.specific_type_enum}}: |
| return {{member.cpp_value_to_v8_value}}; |
| {% endfor %} |
| default: |
| NOTREACHED(); |
| } |
| return v8::Local<v8::Value>(); |
| } |
| |
| {{cpp_class}} NativeValueTraits<{{cpp_class}}>::NativeValue(v8::Isolate* isolate, v8::Local<v8::Value> value, ExceptionState& exceptionState) { |
| {{cpp_class}} impl; |
| {{v8_class}}::toImpl(isolate, value, impl, UnionTypeConversionMode::kNotNullable, exceptionState); |
| return impl; |
| } |
| |
| } // namespace blink |
| |
| {% endfilter %}{# format_blink_cpp_source_code #} |