| {% from 'utilities.cc.tmpl' import declare_enum_validation_variable %} |
| {% from 'utilities.cc.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_path}}" |
| |
| {% for filename in cpp_includes %} |
| #include "{{filename}}" |
| {% endfor %} |
| |
| namespace blink { |
| |
| {{cpp_class}}::{{cpp_class}}() : type_(SpecificType::kNone) {} |
| |
| {% for member in members %} |
| {{member.rvalue_cpp_type}} {{cpp_class}}::GetAs{{member.type_name}}() const { |
| DCHECK(Is{{member.type_name}}()); |
| return {{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) | trim | indent(2)}} |
| if (!IsValidEnum(value, validValues, base::size(validValues), "{{member.enum_type}}", exceptionState)) { |
| NOTREACHED(); |
| return; |
| } |
| {% endif %} |
| {% if member.is_array_buffer_view_or_typed_array %} |
| {{member.cpp_name}}_ = {{member.cpp_type}}(value.View()); |
| {% else %} |
| {{member.cpp_name}}_ = value; |
| {% endif %} |
| type_ = SpecificType::{{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; |
| |
| void {{cpp_class}}::Trace(blink::Visitor* visitor) { |
| {% for member in members if member.is_traceable %} |
| visitor->Trace({{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) | trim | 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) | trim | indent(2)}} |
| |
| {% endfor %} |
| {# 8. ArrayBuffer #} |
| {% if array_buffer_type %} |
| {{assign_and_return_if_hasinstance(array_buffer_type) | trim | 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) | trim | indent(2)}} |
| |
| {% endif %} |
| {% if array_or_sequence_type %} |
| {# 11.1, 11.2. Sequences and frozen arrays #} |
| if (HasCallableIteratorSymbol(isolate, v8Value, exceptionState)) { |
| {{v8_value_to_local_cpp_value(array_or_sequence_type) | trim | indent}} |
| {% if array_or_sequence_type.enum_values %} |
| {{declare_enum_validation_variable(array_or_sequence_type.enum_values) | trim | indent(4)}} |
| if (!IsValidEnum(cppValue, validValues, base::size(validValues), "{{array_or_sequence_type.enum_type}}", exceptionState)) |
| return; |
| {% endif %} |
| 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) | trim | 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) | trim | 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) | trim | 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) | trim | indent}} |
| impl.Set{{numeric_type.type_name}}(cppValue); |
| return; |
| } |
| |
| {% endif %} |
| {% if string_type %} |
| {# 14. String #} |
| { |
| {{v8_value_to_local_cpp_value(string_type) | trim | indent}} |
| {% if string_type.enum_values %} |
| {{declare_enum_validation_variable(string_type.enum_values) | trim | indent}} |
| if (!IsValidEnum(cppValue, validValues, base::size(validValues), "{{string_type.enum_type}}", 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) | trim | indent}} |
| impl.Set{{numeric_type.type_name}}(cppValue); |
| return; |
| } |
| |
| {# 16. Boolean (fallback) #} |
| {% elif boolean_type %} |
| { |
| impl.SetBoolean(v8Value->BooleanValue(isolate->GetCurrentContext()).ToChecked()); |
| 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.type_) { |
| case {{cpp_class}}::SpecificType::kNone: |
| {# FIXME: We might want to return undefined in some cases #} |
| return v8::Null(isolate); |
| {% for member in members %} |
| case {{cpp_class}}::SpecificType::{{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 #} |