blob: f01f7b1ec8dde4d70ef15fddd446fea9a71b4958 [file] [log] [blame]
{% 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_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());
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 #}