blob: 90e1e25f3f78d8a5aebdb74e2aebea22db1f69c8 [file] [log] [blame]
{% 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 (v8_value->Is{{member.type_name}}()) {
{% else %}
if (V8{{member.type_name}}::HasInstance(v8_value, isolate)) {
{% endif %}
{% if member.is_array_buffer_view_or_typed_array %}
{{member.cpp_local_type}} cpp_value = ToNotShared<{{member.cpp_local_type}}>(isolate, v8_value, exception_state);
if (exception_state.HadException())
return;
{% else %}
{{member.cpp_local_type}} cpp_value = V8{{member.type_name}}::ToImpl(v8::Local<v8::Object>::Cast(v8_value));
{% endif %}
impl.Set{{member.type_name}}(cpp_value);
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 exception_state;
{{declare_enum_validation_variable(member.enum_values) | trim | indent(2)}}
if (!IsValidEnum(value, kValidValues, base::size(kValidValues), "{{member.enum_type}}", exception_state)) {
NOTREACHED();
return;
}
{% endif %}
{{member.cpp_name}}_ = value;
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(Visitor* visitor) const {
{% 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> v8_value,
{{cpp_class}}& impl,
UnionTypeConversionMode conversion_mode,
ExceptionState& exception_state) {
if (v8_value.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 (conversion_mode == UnionTypeConversionMode::kNullable && IsUndefinedOrNull(v8_value))
return;
{% if dictionary_type %}
{# 3. Dictionaries for null or undefined #}
if (IsUndefinedOrNull(v8_value)) {
{{v8_value_to_local_cpp_value(dictionary_type) | trim | indent}}
impl.Set{{dictionary_type.type_name}}(cpp_value);
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 (v8_value->IsObject()) {
ScriptIterator script_iterator = ScriptIterator::FromIterable(
isolate, v8_value.As<v8::Object>(), exception_state);
if (exception_state.HadException())
return;
if (!script_iterator.IsNull()) {
{{v8_value_to_local_cpp_value(array_or_sequence_type) | trim | indent(6)}}
{% if array_or_sequence_type.enum_values %}
{{declare_enum_validation_variable(array_or_sequence_type.enum_values) | trim | indent(6)}}
if (!IsValidEnum(cpp_value, kValidValues, base::size(kValidValues),
"{{array_or_sequence_type.enum_type}}", exception_state))
return;
{% endif %}
impl.Set{{array_or_sequence_type.type_name}}(cpp_value);
return;
}
}
{% endif %}
{% if dictionary_type %}
{# 11.3. Dictionaries #}
if (v8_value->IsObject()) {
{{v8_value_to_local_cpp_value(dictionary_type) | trim | indent}}
impl.Set{{dictionary_type.type_name}}(cpp_value);
return;
}
{% endif %}
{# 11.4. Records #}
{% if record_type %}
if (v8_value->IsObject()) {
{{v8_value_to_local_cpp_value(record_type) | trim | indent}}
impl.Set{{record_type.type_name}}(cpp_value);
return;
}
{% endif %}
{# TODO(bashi): Support 11.5 Callback interface when we need it #}
{# 11.6. Objects #}
{% if object_type %}
if (IsUndefinedOrNull(v8_value) || v8_value->IsObject()) {
{{v8_value_to_local_cpp_value(object_type) | trim | indent}}
impl.Set{{object_type.type_name}}(cpp_value);
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 (v8_value->IsBoolean()) {
impl.SetBoolean(v8_value.As<v8::Boolean>()->Value());
return;
}
{% endif %}
{% if numeric_type %}
{# 13. Number #}
if (v8_value->IsNumber()) {
{{v8_value_to_local_cpp_value(numeric_type) | trim | indent}}
impl.Set{{numeric_type.type_name}}(cpp_value);
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(cpp_value, kValidValues, base::size(kValidValues), "{{string_type.enum_type}}", exception_state))
return;
{% endif %}
impl.Set{{string_type.type_name}}(cpp_value);
return;
}
{# 15. Number (fallback) #}
{% elif numeric_type %}
{
{{v8_value_to_local_cpp_value(numeric_type) | trim | indent}}
impl.Set{{numeric_type.type_name}}(cpp_value);
return;
}
{# 16. Boolean (fallback) #}
{% elif boolean_type %}
{
impl.SetBoolean(v8_value->BooleanValue(isolate));
return;
}
{% else %}
{# 17. TypeError #}
exception_state.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& exception_state) {
{{cpp_class}} impl;
{{v8_class}}::ToImpl(isolate, value, impl, UnionTypeConversionMode::kNotNullable, exception_state);
return impl;
}
} // namespace blink
{% endfilter %}{# format_blink_cpp_source_code #}