Commit 6d3095b9 authored by bashi@chromium.org's avatar bashi@chromium.org

IDL: Generic Dictionary support in union types

Even though we want to avoid using generic Dictionary in IDL
files, we need them in some cases. For example, WebCrypto
uses generic Dictionary because we don't have IDL dictionary
inheritance support. Add generic Dictionary support so that
such customers can use union types.

BUG=240176

Review URL: https://codereview.chromium.org/713403004

git-svn-id: svn://svn.chromium.org/blink/trunk@185189 bbb929c8-8fbe-4397-9dbb-9b2b20218538
parent 323be439
......@@ -728,6 +728,9 @@ def v8_conversion_type(idl_type, extended_attributes):
raise 'Unrecognized TreatReturnedNullStringAs value: "%s"' % treat_returned_null_string_as
if idl_type.is_basic_type or base_idl_type == 'ScriptValue':
return base_idl_type
# Generic dictionary type
if base_idl_type == 'Dictionary':
return 'Dictionary'
# Data type with potential additional includes
add_includes_for_type(idl_type)
......@@ -767,6 +770,8 @@ V8_SET_RETURN_VALUE = {
'DOMWrapperForMainWorld': 'v8SetReturnValueForMainWorld(info, WTF::getPtr({cpp_value}))',
'DOMWrapperFast': 'v8SetReturnValueFast(info, WTF::getPtr({cpp_value}), {script_wrappable})',
'DOMWrapperDefault': 'v8SetReturnValue(info, {cpp_value})',
# Generic dictionary type
'Dictionary': 'v8SetReturnValue(info, {cpp_value})',
# Union types or dictionaries
'DictionaryOrUnion': 'v8SetReturnValue(info, result)',
}
......@@ -824,6 +829,7 @@ CPP_VALUE_TO_V8_VALUE = {
'StringOrNull': '{cpp_value}.isNull() ? v8::Handle<v8::Value>(v8::Null({isolate})) : v8String({isolate}, {cpp_value})',
'StringOrUndefined': '{cpp_value}.isNull() ? v8Undefined() : v8String({isolate}, {cpp_value})',
# Special cases
'Dictionary': '{cpp_value}.v8Value()',
'EventHandler': '{cpp_value} ? v8::Handle<v8::Value>(V8AbstractEventListener::cast({cpp_value})->getListenerObject(impl->executionContext())) : v8::Handle<v8::Value>(v8::Null({isolate}))',
'ScriptValue': '{cpp_value}.v8Value()',
'SerializedScriptValue': '{cpp_value} ? {cpp_value}->deserialize() : v8::Handle<v8::Value>(v8::Null({isolate}))',
......
......@@ -6,6 +6,7 @@ import v8_utilities
UNION_H_INCLUDES = frozenset([
'bindings/core/v8/Dictionary.h',
'bindings/core/v8/ExceptionState.h',
'bindings/core/v8/V8Binding.h',
'platform/heap/Handle.h',
......@@ -68,12 +69,13 @@ def container_context(union_type, interfaces_info):
if array_buffer_view_type:
raise Exception('%s is ambiguous.' % union_type.name)
array_buffer_view_type = context
elif member.is_interface_type:
interface_types.append(context)
elif member.is_dictionary:
# FIXME: Remove generic Dictionary special casing.
elif member.is_dictionary or member.base_type == 'Dictionary':
if dictionary_type:
raise Exception('%s is ambiguous.' % union_type.name)
dictionary_type = context
elif member.is_interface_type:
interface_types.append(context)
elif member is union_type.boolean_member_type:
boolean_type = context
elif member is union_type.numeric_member_type:
......@@ -125,5 +127,6 @@ def member_context(member, interfaces_info):
'specific_type_enum': 'SpecificType' + member.name,
'type_name': member.name,
'v8_value_to_local_cpp_value': member.v8_value_to_local_cpp_value(
{}, 'v8Value', 'cppValue', needs_exception_state_for_string=True),
{}, 'v8Value', 'cppValue', isolate='isolate',
needs_exception_state_for_string=True),
}
......@@ -80,9 +80,11 @@ void V8{{container.cpp_class}}::toImpl(v8::Isolate* isolate, v8::Handle<v8::Valu
{# FIXME: This should also check "object but not Date or RegExp". Add checks
when we implement conversions for Date and RegExp. #}
if (isUndefinedOrNull(v8Value) || v8Value->IsObject()) {
{{container.dictionary_type.cpp_local_type}} cppValue = V8{{container.dictionary_type.type_name}}::toImpl(isolate, v8Value, exceptionState);
if (!exceptionState.hadException())
impl.set{{container.dictionary_type.type_name}}(cppValue);
{% if container.dictionary_type.type_name != 'Dictionary' %}
{{container.dictionary_type.cpp_local_type}} cppValue;
{% endif %}
{{container.dictionary_type.v8_value_to_local_cpp_value}};
impl.set{{container.dictionary_type.type_name}}(cppValue);
return;
}
......
......@@ -362,6 +362,7 @@ interface TestObject {
void voidMethodDoubleOrDOMStringOrNullArg((double or DOMString)? arg);
void voidMethodDoubleOrNullOrDOMStringArg((double? or DOMString) arg);
void voidMethodDOMStringOrArrayBufferOrArrayBufferViewArg((DOMString or ArrayBuffer or ArrayBufferView) arg);
void voidMethodArrayBufferOrArrayBufferViewOrDictionaryArg((ArrayBuffer or ArrayBufferView or Dictionary) arg);
// Currently only used on interface type arguments
void voidMethodTestInterfaceEmptyOrNullArg(TestInterfaceEmpty? nullableTestInterfaceEmptyArg);
// Callback interface types
......
......@@ -7,6 +7,7 @@
#include "config.h"
#include "bindings/core/v8/UnionTypesCore.h"
#include "bindings/core/v8/Dictionary.h"
#include "bindings/core/v8/V8ArrayBuffer.h"
#include "bindings/core/v8/V8ArrayBufferView.h"
#include "bindings/core/v8/V8Node.h"
......@@ -27,6 +28,100 @@
namespace blink {
ArrayBufferOrArrayBufferViewOrDictionary::ArrayBufferOrArrayBufferViewOrDictionary()
: m_type(SpecificTypeNone)
{
}
PassRefPtr<TestArrayBuffer> ArrayBufferOrArrayBufferViewOrDictionary::getAsArrayBuffer() const
{
ASSERT(isArrayBuffer());
return m_arrayBuffer;
}
void ArrayBufferOrArrayBufferViewOrDictionary::setArrayBuffer(PassRefPtr<TestArrayBuffer> value)
{
ASSERT(isNull());
m_arrayBuffer = value;
m_type = SpecificTypeArrayBuffer;
}
PassRefPtr<TestArrayBufferView> ArrayBufferOrArrayBufferViewOrDictionary::getAsArrayBufferView() const
{
ASSERT(isArrayBufferView());
return m_arrayBufferView;
}
void ArrayBufferOrArrayBufferViewOrDictionary::setArrayBufferView(PassRefPtr<TestArrayBufferView> value)
{
ASSERT(isNull());
m_arrayBufferView = value;
m_type = SpecificTypeArrayBufferView;
}
Dictionary ArrayBufferOrArrayBufferViewOrDictionary::getAsDictionary() const
{
ASSERT(isDictionary());
return m_dictionary;
}
void ArrayBufferOrArrayBufferViewOrDictionary::setDictionary(Dictionary value)
{
ASSERT(isNull());
m_dictionary = value;
m_type = SpecificTypeDictionary;
}
void V8ArrayBufferOrArrayBufferViewOrDictionary::toImpl(v8::Isolate* isolate, v8::Handle<v8::Value> v8Value, ArrayBufferOrArrayBufferViewOrDictionary& impl, ExceptionState& exceptionState)
{
if (v8Value.IsEmpty())
return;
if (V8ArrayBuffer::hasInstance(v8Value, isolate)) {
RefPtr<TestArrayBuffer> cppValue = V8ArrayBuffer::toImpl(v8::Handle<v8::Object>::Cast(v8Value));
impl.setArrayBuffer(cppValue);
return;
}
if (V8ArrayBufferView::hasInstance(v8Value, isolate)) {
RefPtr<TestArrayBufferView> cppValue = V8ArrayBufferView::toImpl(v8::Handle<v8::Object>::Cast(v8Value));
impl.setArrayBufferView(cppValue);
return;
}
if (isUndefinedOrNull(v8Value) || v8Value->IsObject()) {
Dictionary cppValue = Dictionary(v8Value, isolate);
impl.setDictionary(cppValue);
return;
}
exceptionState.throwTypeError("Not a valid union member.");
}
v8::Handle<v8::Value> toV8(ArrayBufferOrArrayBufferViewOrDictionary& impl, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate)
{
switch (impl.m_type) {
case ArrayBufferOrArrayBufferViewOrDictionary::SpecificTypeNone:
return v8::Null(isolate);
case ArrayBufferOrArrayBufferViewOrDictionary::SpecificTypeArrayBuffer:
return toV8(impl.getAsArrayBuffer(), creationContext, isolate);
case ArrayBufferOrArrayBufferViewOrDictionary::SpecificTypeArrayBufferView:
return toV8(impl.getAsArrayBufferView(), creationContext, isolate);
case ArrayBufferOrArrayBufferViewOrDictionary::SpecificTypeDictionary:
return impl.getAsDictionary().v8Value();
default:
ASSERT_NOT_REACHED();
}
return v8::Handle<v8::Value>();
}
ArrayBufferOrArrayBufferViewOrDictionary NativeValueTraits<ArrayBufferOrArrayBufferViewOrDictionary>::nativeValue(const v8::Handle<v8::Value>& value, v8::Isolate* isolate, ExceptionState& exceptionState)
{
ArrayBufferOrArrayBufferViewOrDictionary impl;
V8ArrayBufferOrArrayBufferViewOrDictionary::toImpl(isolate, value, impl, exceptionState);
return impl;
}
BooleanOrStringOrUnrestrictedDouble::BooleanOrStringOrUnrestrictedDouble()
: m_type(SpecificTypeNone)
{
......@@ -711,9 +806,9 @@ void V8TestInterfaceWillBeGarbageCollectedOrTestDictionary::toImpl(v8::Isolate*
}
if (isUndefinedOrNull(v8Value) || v8Value->IsObject()) {
TestDictionary cppValue = V8TestDictionary::toImpl(isolate, v8Value, exceptionState);
if (!exceptionState.hadException())
impl.setTestDictionary(cppValue);
TestDictionary cppValue;
TONATIVE_VOID_EXCEPTIONSTATE_ARGINTERNAL(V8TestDictionary::toImpl(isolate, v8Value, cppValue, exceptionState), exceptionState);
impl.setTestDictionary(cppValue);
return;
}
......
......@@ -7,6 +7,7 @@
#ifndef UnionTypeCore_h
#define UnionTypeCore_h
#include "bindings/core/v8/Dictionary.h"
#include "bindings/core/v8/ExceptionState.h"
#include "bindings/core/v8/V8Binding.h"
#include "platform/heap/Handle.h"
......@@ -23,6 +24,58 @@ class TestInterfaceGarbageCollected;
class TestInterfaceImplementation;
class TestInterfaceWillBeGarbageCollected;
class ArrayBufferOrArrayBufferViewOrDictionary final {
ALLOW_ONLY_INLINE_ALLOCATION();
public:
ArrayBufferOrArrayBufferViewOrDictionary();
bool isNull() const { return m_type == SpecificTypeNone; }
bool isArrayBuffer() const { return m_type == SpecificTypeArrayBuffer; }
PassRefPtr<TestArrayBuffer> getAsArrayBuffer() const;
void setArrayBuffer(PassRefPtr<TestArrayBuffer>);
bool isArrayBufferView() const { return m_type == SpecificTypeArrayBufferView; }
PassRefPtr<TestArrayBufferView> getAsArrayBufferView() const;
void setArrayBufferView(PassRefPtr<TestArrayBufferView>);
bool isDictionary() const { return m_type == SpecificTypeDictionary; }
Dictionary getAsDictionary() const;
void setDictionary(Dictionary);
private:
enum SpecificTypes {
SpecificTypeNone,
SpecificTypeArrayBuffer,
SpecificTypeArrayBufferView,
SpecificTypeDictionary,
};
SpecificTypes m_type;
RefPtr<TestArrayBuffer> m_arrayBuffer;
RefPtr<TestArrayBufferView> m_arrayBufferView;
Dictionary m_dictionary;
friend v8::Handle<v8::Value> toV8(ArrayBufferOrArrayBufferViewOrDictionary&, v8::Handle<v8::Object>, v8::Isolate*);
};
class V8ArrayBufferOrArrayBufferViewOrDictionary final {
public:
static void toImpl(v8::Isolate*, v8::Handle<v8::Value>, ArrayBufferOrArrayBufferViewOrDictionary&, ExceptionState&);
};
v8::Handle<v8::Value> toV8(ArrayBufferOrArrayBufferViewOrDictionary&, v8::Handle<v8::Object>, v8::Isolate*);
template <class CallbackInfo>
inline void v8SetReturnValue(const CallbackInfo& callbackInfo, ArrayBufferOrArrayBufferViewOrDictionary& impl)
{
v8SetReturnValue(callbackInfo, toV8(impl, callbackInfo.Holder(), callbackInfo.GetIsolate()));
}
template <>
struct NativeValueTraits<ArrayBufferOrArrayBufferViewOrDictionary> {
static ArrayBufferOrArrayBufferViewOrDictionary nativeValue(const v8::Handle<v8::Value>&, v8::Isolate*, ExceptionState&);
};
class BooleanOrStringOrUnrestrictedDouble final {
ALLOW_ONLY_INLINE_ALLOCATION();
public:
......
......@@ -6583,6 +6583,29 @@ static void voidMethodDOMStringOrArrayBufferOrArrayBufferViewArgMethodCallback(c
TRACE_EVENT_SET_SAMPLING_STATE("v8", "V8Execution");
}
static void voidMethodArrayBufferOrArrayBufferViewOrDictionaryArgMethod(const v8::FunctionCallbackInfo<v8::Value>& info)
{
ExceptionState exceptionState(ExceptionState::ExecutionContext, "voidMethodArrayBufferOrArrayBufferViewOrDictionaryArg", "TestObject", info.Holder(), info.GetIsolate());
if (UNLIKELY(info.Length() < 1)) {
setMinimumArityTypeError(exceptionState, 1, info.Length());
exceptionState.throwIfNeeded();
return;
}
TestObject* impl = V8TestObject::toImpl(info.Holder());
ArrayBufferOrArrayBufferViewOrDictionary arg;
{
TONATIVE_VOID_EXCEPTIONSTATE_ARGINTERNAL(V8ArrayBufferOrArrayBufferViewOrDictionary::toImpl(info.GetIsolate(), info[0], arg, exceptionState), exceptionState);
}
impl->voidMethodArrayBufferOrArrayBufferViewOrDictionaryArg(arg);
}
static void voidMethodArrayBufferOrArrayBufferViewOrDictionaryArgMethodCallback(const v8::FunctionCallbackInfo<v8::Value>& info)
{
TRACE_EVENT_SET_SAMPLING_STATE("blink", "DOMMethod");
TestObjectV8Internal::voidMethodArrayBufferOrArrayBufferViewOrDictionaryArgMethod(info);
TRACE_EVENT_SET_SAMPLING_STATE("v8", "V8Execution");
}
static void voidMethodTestInterfaceEmptyOrNullArgMethod(const v8::FunctionCallbackInfo<v8::Value>& info)
{
if (UNLIKELY(info.Length() < 1)) {
......@@ -10600,6 +10623,7 @@ static const V8DOMConfiguration::MethodConfiguration V8TestObjectMethods[] = {
{"voidMethodDoubleOrDOMStringOrNullArg", TestObjectV8Internal::voidMethodDoubleOrDOMStringOrNullArgMethodCallback, 0, 1, V8DOMConfiguration::ExposedToAllScripts},
{"voidMethodDoubleOrNullOrDOMStringArg", TestObjectV8Internal::voidMethodDoubleOrNullOrDOMStringArgMethodCallback, 0, 1, V8DOMConfiguration::ExposedToAllScripts},
{"voidMethodDOMStringOrArrayBufferOrArrayBufferViewArg", TestObjectV8Internal::voidMethodDOMStringOrArrayBufferOrArrayBufferViewArgMethodCallback, 0, 1, V8DOMConfiguration::ExposedToAllScripts},
{"voidMethodArrayBufferOrArrayBufferViewOrDictionaryArg", TestObjectV8Internal::voidMethodArrayBufferOrArrayBufferViewOrDictionaryArgMethodCallback, 0, 1, V8DOMConfiguration::ExposedToAllScripts},
{"voidMethodTestInterfaceEmptyOrNullArg", TestObjectV8Internal::voidMethodTestInterfaceEmptyOrNullArgMethodCallback, 0, 1, V8DOMConfiguration::ExposedToAllScripts},
{"voidMethodTestCallbackInterfaceArg", TestObjectV8Internal::voidMethodTestCallbackInterfaceArgMethodCallback, 0, 1, V8DOMConfiguration::ExposedToAllScripts},
{"voidMethodOptionalTestCallbackInterfaceArg", TestObjectV8Internal::voidMethodOptionalTestCallbackInterfaceArgMethodCallback, 0, 0, V8DOMConfiguration::ExposedToAllScripts},
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment