Commit f6d88554 authored by bashi@chromium.org's avatar bashi@chromium.org

IDL: Union type support for attributes

Some specs use union type attributes. For example, TrackEvent[1]
has 'track' attribute, of which type is
(VideoTrack or AudioTrack or TextTrack). Let's support union type
attributes so that we can reduce custom bindings. Follow-up CLs
will replace custom bindings if possible.

BUG=240176

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

git-svn-id: svn://svn.chromium.org/blink/trunk@184847 bbb929c8-8fbe-4397-9dbb-9b2b20218538
parent 43e64093
...@@ -3,6 +3,15 @@ IDL union types unittests ...@@ -3,6 +3,15 @@ IDL union types unittests
On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
Tests for attributes
PASS unionTypesTest.doubleOrStringAttribute is 0
PASS unionTypesTest.doubleOrStringAttribute is 3.14
PASS unionTypesTest.doubleOrStringAttribute is "foo"
PASS unionTypesTest.doubleOrStringAttribute is "undefined"
PASS unionTypesTest.doubleOrStringAttribute is "null"
PASS unionTypesTest.doubleOrStringAttribute is "[object Object]"
PASS unionTypesTest.doubleOrStringAttribute is ""
Tests for method arguments Tests for method arguments
PASS unionTypesTest.doubleOrStringArg(3.14) is "double is passed: 3.14" PASS unionTypesTest.doubleOrStringArg(3.14) is "double is passed: 3.14"
PASS unionTypesTest.doubleOrStringArg("foo") is "string is passed: foo" PASS unionTypesTest.doubleOrStringArg("foo") is "string is passed: foo"
......
...@@ -4,12 +4,30 @@ ...@@ -4,12 +4,30 @@
description('IDL union types unittests'); description('IDL union types unittests');
if (window.internals) { if (window.internals) {
// The conversion rule prefers string over double, hence a value which
// is neither double nor string will be converted using ToString().
var unionTypesTest = internals.unionTypesTest(); var unionTypesTest = internals.unionTypesTest();
debug('Tests for attributes');
shouldBe('unionTypesTest.doubleOrStringAttribute', '0');
unionTypesTest.doubleOrStringAttribute = 3.14;
shouldBe('unionTypesTest.doubleOrStringAttribute', '3.14');
unionTypesTest.doubleOrStringAttribute = "foo";
shouldBeEqualToString('unionTypesTest.doubleOrStringAttribute', 'foo');
unionTypesTest.doubleOrStringAttribute = undefined;
shouldBeEqualToString('unionTypesTest.doubleOrStringAttribute', 'undefined');
unionTypesTest.doubleOrStringAttribute = null;
shouldBeEqualToString('unionTypesTest.doubleOrStringAttribute', 'null');
unionTypesTest.doubleOrStringAttribute = {};
shouldBeEqualToString('unionTypesTest.doubleOrStringAttribute', '[object Object]');
unionTypesTest.doubleOrStringAttribute = [];
shouldBeEqualToString('unionTypesTest.doubleOrStringAttribute', '');
debug('');
debug('Tests for method arguments'); debug('Tests for method arguments');
shouldBeEqualToString('unionTypesTest.doubleOrStringArg(3.14)', 'double is passed: 3.14'); shouldBeEqualToString('unionTypesTest.doubleOrStringArg(3.14)', 'double is passed: 3.14');
shouldBeEqualToString('unionTypesTest.doubleOrStringArg("foo")', 'string is passed: foo'); shouldBeEqualToString('unionTypesTest.doubleOrStringArg("foo")', 'string is passed: foo');
// The conversion rule prefers string over double, hence a value which
// is neither double nor string will be converted using ToString().
shouldBeEqualToString('unionTypesTest.doubleOrStringArg(undefined)', 'string is passed: undefined'); shouldBeEqualToString('unionTypesTest.doubleOrStringArg(undefined)', 'string is passed: undefined');
shouldBeEqualToString('unionTypesTest.doubleOrStringArg(null)', 'string is passed: null'); shouldBeEqualToString('unionTypesTest.doubleOrStringArg(null)', 'string is passed: null');
shouldBeEqualToString('unionTypesTest.doubleOrStringArg({})', 'string is passed: [object Object]'); shouldBeEqualToString('unionTypesTest.doubleOrStringArg({})', 'string is passed: [object Object]');
......
...@@ -125,6 +125,7 @@ def attribute_context(interface, attribute): ...@@ -125,6 +125,7 @@ def attribute_context(interface, attribute):
'is_static': attribute.is_static, 'is_static': attribute.is_static,
'is_url': 'URL' in extended_attributes, 'is_url': 'URL' in extended_attributes,
'is_unforgeable': 'Unforgeable' in extended_attributes, 'is_unforgeable': 'Unforgeable' in extended_attributes,
'use_output_parameter_for_result': idl_type.use_output_parameter_for_result,
'measure_as': v8_utilities.measure_as(attribute), # [MeasureAs] 'measure_as': v8_utilities.measure_as(attribute), # [MeasureAs]
'name': attribute.name, 'name': attribute.name,
'only_exposed_to_private_script': is_only_exposed_to_private_script, 'only_exposed_to_private_script': is_only_exposed_to_private_script,
...@@ -234,6 +235,8 @@ def getter_expression(interface, attribute, context): ...@@ -234,6 +235,8 @@ def getter_expression(interface, attribute, context):
arguments.append('isNull') arguments.append('isNull')
if context['is_getter_raises_exception']: if context['is_getter_raises_exception']:
arguments.append('exceptionState') arguments.append('exceptionState')
if attribute.idl_type.use_output_parameter_for_result:
arguments.append('result')
return '%s(%s)' % (getter_name, ', '.join(arguments)) return '%s(%s)' % (getter_name, ', '.join(arguments))
......
...@@ -1044,7 +1044,7 @@ def interface_length(interface, constructors): ...@@ -1044,7 +1044,7 @@ def interface_length(interface, constructors):
def property_getter(getter, cpp_arguments): def property_getter(getter, cpp_arguments):
def is_null_expression(idl_type): def is_null_expression(idl_type):
if v8_methods.use_output_parameter_for_result(idl_type): if idl_type.use_output_parameter_for_result:
return 'result.isNull()' return 'result.isNull()'
if idl_type.name == 'String': if idl_type.name == 'String':
return 'result.isNull()' return 'result.isNull()'
...@@ -1055,7 +1055,7 @@ def property_getter(getter, cpp_arguments): ...@@ -1055,7 +1055,7 @@ def property_getter(getter, cpp_arguments):
idl_type = getter.idl_type idl_type = getter.idl_type
extended_attributes = getter.extended_attributes extended_attributes = getter.extended_attributes
is_raises_exception = 'RaisesException' in extended_attributes is_raises_exception = 'RaisesException' in extended_attributes
use_output_parameter_for_result = v8_methods.use_output_parameter_for_result(idl_type) use_output_parameter_for_result = idl_type.use_output_parameter_for_result
# FIXME: make more generic, so can use v8_methods.cpp_value # FIXME: make more generic, so can use v8_methods.cpp_value
cpp_method_name = 'impl->%s' % cpp_name(getter) cpp_method_name = 'impl->%s' % cpp_name(getter)
......
...@@ -62,10 +62,6 @@ def use_local_result(method): ...@@ -62,10 +62,6 @@ def use_local_result(method):
idl_type.is_explicit_nullable) idl_type.is_explicit_nullable)
def use_output_parameter_for_result(idl_type):
return idl_type.is_dictionary or idl_type.is_union_type
def method_context(interface, method, is_visible=True): def method_context(interface, method, is_visible=True):
arguments = method.arguments arguments = method.arguments
extended_attributes = method.extended_attributes extended_attributes = method.extended_attributes
...@@ -182,7 +178,7 @@ def method_context(interface, method, is_visible=True): ...@@ -182,7 +178,7 @@ def method_context(interface, method, is_visible=True):
'runtime_enabled_function': v8_utilities.runtime_enabled_function_name(method), # [RuntimeEnabled] 'runtime_enabled_function': v8_utilities.runtime_enabled_function_name(method), # [RuntimeEnabled]
'should_be_exposed_to_script': not (is_implemented_in_private_script and is_only_exposed_to_private_script), 'should_be_exposed_to_script': not (is_implemented_in_private_script and is_only_exposed_to_private_script),
'signature': 'v8::Local<v8::Signature>()' if is_static or 'DoNotCheckSignature' in extended_attributes else 'defaultSignature', 'signature': 'v8::Local<v8::Signature>()' if is_static or 'DoNotCheckSignature' in extended_attributes else 'defaultSignature',
'use_output_parameter_for_result': use_output_parameter_for_result(idl_type), 'use_output_parameter_for_result': idl_type.use_output_parameter_for_result,
'use_local_result': use_local_result(method), 'use_local_result': use_local_result(method),
'v8_set_return_value': v8_set_return_value(interface.name, method, this_cpp_value), 'v8_set_return_value': v8_set_return_value(interface.name, method, this_cpp_value),
'v8_set_return_value_for_main_world': v8_set_return_value(interface.name, method, this_cpp_value, for_main_world=True), 'v8_set_return_value_for_main_world': v8_set_return_value(interface.name, method, this_cpp_value, for_main_world=True),
...@@ -310,7 +306,7 @@ def cpp_value(interface, method, number_of_arguments): ...@@ -310,7 +306,7 @@ def cpp_value(interface, method, number_of_arguments):
# If a method returns an IDL dictionary or union type, the return value is # If a method returns an IDL dictionary or union type, the return value is
# passed as an argument to impl classes. # passed as an argument to impl classes.
idl_type = method.idl_type idl_type = method.idl_type
if idl_type and use_output_parameter_for_result(idl_type): if idl_type and idl_type.use_output_parameter_for_result:
cpp_arguments.append('result') cpp_arguments.append('result')
if method.name == 'Constructor': if method.name == 'Constructor':
......
...@@ -631,6 +631,15 @@ def v8_value_to_local_cpp_value(idl_type, extended_attributes, v8_value, variabl ...@@ -631,6 +631,15 @@ def v8_value_to_local_cpp_value(idl_type, extended_attributes, v8_value, variabl
IdlTypeBase.v8_value_to_local_cpp_value = v8_value_to_local_cpp_value IdlTypeBase.v8_value_to_local_cpp_value = v8_value_to_local_cpp_value
def use_output_parameter_for_result(idl_type):
"""True when methods/getters which return the given idl_type should
take the output argument.
"""
return idl_type.is_dictionary or idl_type.is_union_type
IdlTypeBase.use_output_parameter_for_result = property(use_output_parameter_for_result)
################################################################################ ################################################################################
# C++ -> V8 # C++ -> V8
################################################################################ ################################################################################
......
...@@ -95,6 +95,10 @@ const v8::PropertyCallbackInfo<v8::Value>& info ...@@ -95,6 +95,10 @@ const v8::PropertyCallbackInfo<v8::Value>& info
{% elif world_suffix %} {% elif world_suffix %}
{{attribute.v8_set_return_value_for_main_world}}; {{attribute.v8_set_return_value_for_main_world}};
{% else %} {% else %}
{% if attribute.use_output_parameter_for_result %}
{{attribute.cpp_type}} result;
{{attribute.cpp_value}};
{% endif %}
{{attribute.v8_set_return_value}}; {{attribute.v8_set_return_value}};
{% endif %} {% endif %}
} }
...@@ -223,6 +227,9 @@ v8::Local<v8::Value> v8Value, const v8::PropertyCallbackInfo<void>& info ...@@ -223,6 +227,9 @@ v8::Local<v8::Value> v8Value, const v8::PropertyCallbackInfo<void>& info
return; return;
} }
{% endif %} {% endif %}
{% if attribute.use_output_parameter_for_result %}
{{attribute.cpp_type}} cppValue;
{% endif %}
{# impl #} {# impl #}
{% if attribute.put_forwards %} {% if attribute.put_forwards %}
{{cpp_class}}* proxyImpl = {{v8_class}}::toImpl(holder); {{cpp_class}}* proxyImpl = {{v8_class}}::toImpl(holder);
......
...@@ -27,7 +27,7 @@ namespace blink { ...@@ -27,7 +27,7 @@ namespace blink {
} }
{% for member in container.members %} {% for member in container.members %}
{{member.rvalue_cpp_type}} {{container.cpp_class}}::getAs{{member.type_name}}() {{member.rvalue_cpp_type}} {{container.cpp_class}}::getAs{{member.type_name}}() const
{ {
ASSERT(is{{member.type_name}}()); ASSERT(is{{member.type_name}}());
return m_{{member.cpp_name}}; return m_{{member.cpp_name}};
......
...@@ -26,7 +26,7 @@ public: ...@@ -26,7 +26,7 @@ public:
{% for member in container.members %} {% for member in container.members %}
bool is{{member.type_name}}() const { return m_type == {{member.specific_type_enum}}; } bool is{{member.type_name}}() const { return m_type == {{member.specific_type_enum}}; }
{{member.rvalue_cpp_type}} getAs{{member.type_name}}(); {{member.rvalue_cpp_type}} getAs{{member.type_name}}() const;
void set{{member.type_name}}({{member.rvalue_cpp_type}}); void set{{member.type_name}}({{member.rvalue_cpp_type}});
{% endfor %} {% endfor %}
......
...@@ -155,6 +155,8 @@ interface TestObject { ...@@ -155,6 +155,8 @@ interface TestObject {
static attribute long staticLongAttribute; static attribute long staticLongAttribute;
// Exceptional type // Exceptional type
attribute EventHandler eventHandlerAttribute; attribute EventHandler eventHandlerAttribute;
// Union types
attribute (double or DOMString) doubleOrStringAttribute;
// Extended attributes // Extended attributes
[LogActivity, LogAllWorlds] attribute long activityLoggingAccessForAllWorldsLongAttribute; [LogActivity, LogAllWorlds] attribute long activityLoggingAccessForAllWorldsLongAttribute;
......
...@@ -32,7 +32,7 @@ BooleanOrStringOrUnrestrictedDouble::BooleanOrStringOrUnrestrictedDouble() ...@@ -32,7 +32,7 @@ BooleanOrStringOrUnrestrictedDouble::BooleanOrStringOrUnrestrictedDouble()
{ {
} }
bool BooleanOrStringOrUnrestrictedDouble::getAsBoolean() bool BooleanOrStringOrUnrestrictedDouble::getAsBoolean() const
{ {
ASSERT(isBoolean()); ASSERT(isBoolean());
return m_boolean; return m_boolean;
...@@ -45,7 +45,7 @@ void BooleanOrStringOrUnrestrictedDouble::setBoolean(bool value) ...@@ -45,7 +45,7 @@ void BooleanOrStringOrUnrestrictedDouble::setBoolean(bool value)
m_type = SpecificTypeBoolean; m_type = SpecificTypeBoolean;
} }
String BooleanOrStringOrUnrestrictedDouble::getAsString() String BooleanOrStringOrUnrestrictedDouble::getAsString() const
{ {
ASSERT(isString()); ASSERT(isString());
return m_string; return m_string;
...@@ -58,7 +58,7 @@ void BooleanOrStringOrUnrestrictedDouble::setString(String value) ...@@ -58,7 +58,7 @@ void BooleanOrStringOrUnrestrictedDouble::setString(String value)
m_type = SpecificTypeString; m_type = SpecificTypeString;
} }
double BooleanOrStringOrUnrestrictedDouble::getAsUnrestrictedDouble() double BooleanOrStringOrUnrestrictedDouble::getAsUnrestrictedDouble() const
{ {
ASSERT(isUnrestrictedDouble()); ASSERT(isUnrestrictedDouble());
return m_unrestrictedDouble; return m_unrestrictedDouble;
...@@ -114,12 +114,78 @@ v8::Handle<v8::Value> toV8(BooleanOrStringOrUnrestrictedDouble& impl, v8::Handle ...@@ -114,12 +114,78 @@ v8::Handle<v8::Value> toV8(BooleanOrStringOrUnrestrictedDouble& impl, v8::Handle
return v8::Handle<v8::Value>(); return v8::Handle<v8::Value>();
} }
DoubleOrString::DoubleOrString()
: m_type(SpecificTypeNone)
{
}
double DoubleOrString::getAsDouble() const
{
ASSERT(isDouble());
return m_double;
}
void DoubleOrString::setDouble(double value)
{
ASSERT(isNull());
m_double = value;
m_type = SpecificTypeDouble;
}
String DoubleOrString::getAsString() const
{
ASSERT(isString());
return m_string;
}
void DoubleOrString::setString(String value)
{
ASSERT(isNull());
m_string = value;
m_type = SpecificTypeString;
}
void V8DoubleOrString::toImpl(v8::Isolate* isolate, v8::Handle<v8::Value> v8Value, DoubleOrString& impl, ExceptionState& exceptionState)
{
if (v8Value.IsEmpty())
return;
if (v8Value->IsNumber()) {
TONATIVE_VOID_EXCEPTIONSTATE(double, cppValue, toDouble(v8Value, exceptionState), exceptionState);
impl.setDouble(cppValue);
return;
}
{
TOSTRING_VOID_EXCEPTIONSTATE(V8StringResource<>, cppValue, v8Value, exceptionState);
impl.setString(cppValue);
return;
}
exceptionState.throwTypeError("Not a valid union member.");
}
v8::Handle<v8::Value> toV8(DoubleOrString& impl, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate)
{
if (impl.isNull())
return v8::Null(isolate);
if (impl.isDouble())
return v8::Number::New(isolate, impl.getAsDouble());
if (impl.isString())
return v8String(isolate, impl.getAsString());
ASSERT_NOT_REACHED();
return v8::Handle<v8::Value>();
}
NodeOrNodeList::NodeOrNodeList() NodeOrNodeList::NodeOrNodeList()
: m_type(SpecificTypeNone) : m_type(SpecificTypeNone)
{ {
} }
PassRefPtrWillBeRawPtr<Node> NodeOrNodeList::getAsNode() PassRefPtrWillBeRawPtr<Node> NodeOrNodeList::getAsNode() const
{ {
ASSERT(isNode()); ASSERT(isNode());
return m_node; return m_node;
...@@ -132,7 +198,7 @@ void NodeOrNodeList::setNode(PassRefPtrWillBeRawPtr<Node> value) ...@@ -132,7 +198,7 @@ void NodeOrNodeList::setNode(PassRefPtrWillBeRawPtr<Node> value)
m_type = SpecificTypeNode; m_type = SpecificTypeNode;
} }
PassRefPtrWillBeRawPtr<NodeList> NodeOrNodeList::getAsNodeList() PassRefPtrWillBeRawPtr<NodeList> NodeOrNodeList::getAsNodeList() const
{ {
ASSERT(isNodeList()); ASSERT(isNodeList());
return m_nodeList; return m_nodeList;
...@@ -191,7 +257,7 @@ StringOrArrayBufferOrArrayBufferView::StringOrArrayBufferOrArrayBufferView() ...@@ -191,7 +257,7 @@ StringOrArrayBufferOrArrayBufferView::StringOrArrayBufferOrArrayBufferView()
{ {
} }
String StringOrArrayBufferOrArrayBufferView::getAsString() String StringOrArrayBufferOrArrayBufferView::getAsString() const
{ {
ASSERT(isString()); ASSERT(isString());
return m_string; return m_string;
...@@ -204,7 +270,7 @@ void StringOrArrayBufferOrArrayBufferView::setString(String value) ...@@ -204,7 +270,7 @@ void StringOrArrayBufferOrArrayBufferView::setString(String value)
m_type = SpecificTypeString; m_type = SpecificTypeString;
} }
PassRefPtr<TestArrayBuffer> StringOrArrayBufferOrArrayBufferView::getAsArrayBuffer() PassRefPtr<TestArrayBuffer> StringOrArrayBufferOrArrayBufferView::getAsArrayBuffer() const
{ {
ASSERT(isArrayBuffer()); ASSERT(isArrayBuffer());
return m_arrayBuffer; return m_arrayBuffer;
...@@ -217,7 +283,7 @@ void StringOrArrayBufferOrArrayBufferView::setArrayBuffer(PassRefPtr<TestArrayBu ...@@ -217,7 +283,7 @@ void StringOrArrayBufferOrArrayBufferView::setArrayBuffer(PassRefPtr<TestArrayBu
m_type = SpecificTypeArrayBuffer; m_type = SpecificTypeArrayBuffer;
} }
PassRefPtr<TestArrayBufferView> StringOrArrayBufferOrArrayBufferView::getAsArrayBufferView() PassRefPtr<TestArrayBufferView> StringOrArrayBufferOrArrayBufferView::getAsArrayBufferView() const
{ {
ASSERT(isArrayBufferView()); ASSERT(isArrayBufferView());
return m_arrayBufferView; return m_arrayBufferView;
...@@ -279,7 +345,7 @@ StringOrDouble::StringOrDouble() ...@@ -279,7 +345,7 @@ StringOrDouble::StringOrDouble()
{ {
} }
String StringOrDouble::getAsString() String StringOrDouble::getAsString() const
{ {
ASSERT(isString()); ASSERT(isString());
return m_string; return m_string;
...@@ -292,7 +358,7 @@ void StringOrDouble::setString(String value) ...@@ -292,7 +358,7 @@ void StringOrDouble::setString(String value)
m_type = SpecificTypeString; m_type = SpecificTypeString;
} }
double StringOrDouble::getAsDouble() double StringOrDouble::getAsDouble() const
{ {
ASSERT(isDouble()); ASSERT(isDouble());
return m_double; return m_double;
...@@ -345,7 +411,7 @@ TestInterfaceGarbageCollectedOrString::TestInterfaceGarbageCollectedOrString() ...@@ -345,7 +411,7 @@ TestInterfaceGarbageCollectedOrString::TestInterfaceGarbageCollectedOrString()
{ {
} }
RawPtr<TestInterfaceGarbageCollected> TestInterfaceGarbageCollectedOrString::getAsTestInterfaceGarbageCollected() RawPtr<TestInterfaceGarbageCollected> TestInterfaceGarbageCollectedOrString::getAsTestInterfaceGarbageCollected() const
{ {
ASSERT(isTestInterfaceGarbageCollected()); ASSERT(isTestInterfaceGarbageCollected());
return m_testInterfaceGarbageCollected; return m_testInterfaceGarbageCollected;
...@@ -358,7 +424,7 @@ void TestInterfaceGarbageCollectedOrString::setTestInterfaceGarbageCollected(Raw ...@@ -358,7 +424,7 @@ void TestInterfaceGarbageCollectedOrString::setTestInterfaceGarbageCollected(Raw
m_type = SpecificTypeTestInterfaceGarbageCollected; m_type = SpecificTypeTestInterfaceGarbageCollected;
} }
String TestInterfaceGarbageCollectedOrString::getAsString() String TestInterfaceGarbageCollectedOrString::getAsString() const
{ {
ASSERT(isString()); ASSERT(isString());
return m_string; return m_string;
...@@ -416,7 +482,7 @@ TestInterfaceOrLong::TestInterfaceOrLong() ...@@ -416,7 +482,7 @@ TestInterfaceOrLong::TestInterfaceOrLong()
{ {
} }
PassRefPtr<TestInterfaceImplementation> TestInterfaceOrLong::getAsTestInterface() PassRefPtr<TestInterfaceImplementation> TestInterfaceOrLong::getAsTestInterface() const
{ {
ASSERT(isTestInterface()); ASSERT(isTestInterface());
return m_testInterface; return m_testInterface;
...@@ -429,7 +495,7 @@ void TestInterfaceOrLong::setTestInterface(PassRefPtr<TestInterfaceImplementatio ...@@ -429,7 +495,7 @@ void TestInterfaceOrLong::setTestInterface(PassRefPtr<TestInterfaceImplementatio
m_type = SpecificTypeTestInterface; m_type = SpecificTypeTestInterface;
} }
int TestInterfaceOrLong::getAsLong() int TestInterfaceOrLong::getAsLong() const
{ {
ASSERT(isLong()); ASSERT(isLong());
return m_long; return m_long;
...@@ -488,7 +554,7 @@ TestInterfaceOrTestInterfaceEmpty::TestInterfaceOrTestInterfaceEmpty() ...@@ -488,7 +554,7 @@ TestInterfaceOrTestInterfaceEmpty::TestInterfaceOrTestInterfaceEmpty()
{ {
} }
PassRefPtr<TestInterfaceImplementation> TestInterfaceOrTestInterfaceEmpty::getAsTestInterface() PassRefPtr<TestInterfaceImplementation> TestInterfaceOrTestInterfaceEmpty::getAsTestInterface() const
{ {
ASSERT(isTestInterface()); ASSERT(isTestInterface());
return m_testInterface; return m_testInterface;
...@@ -501,7 +567,7 @@ void TestInterfaceOrTestInterfaceEmpty::setTestInterface(PassRefPtr<TestInterfac ...@@ -501,7 +567,7 @@ void TestInterfaceOrTestInterfaceEmpty::setTestInterface(PassRefPtr<TestInterfac
m_type = SpecificTypeTestInterface; m_type = SpecificTypeTestInterface;
} }
PassRefPtr<TestInterfaceEmpty> TestInterfaceOrTestInterfaceEmpty::getAsTestInterfaceEmpty() PassRefPtr<TestInterfaceEmpty> TestInterfaceOrTestInterfaceEmpty::getAsTestInterfaceEmpty() const
{ {
ASSERT(isTestInterfaceEmpty()); ASSERT(isTestInterfaceEmpty());
return m_testInterfaceEmpty; return m_testInterfaceEmpty;
...@@ -554,7 +620,7 @@ TestInterfaceWillBeGarbageCollectedOrTestDictionary::TestInterfaceWillBeGarbageC ...@@ -554,7 +620,7 @@ TestInterfaceWillBeGarbageCollectedOrTestDictionary::TestInterfaceWillBeGarbageC
{ {
} }
PassRefPtrWillBeRawPtr<TestInterfaceWillBeGarbageCollected> TestInterfaceWillBeGarbageCollectedOrTestDictionary::getAsTestInterfaceWillBeGarbageCollected() PassRefPtrWillBeRawPtr<TestInterfaceWillBeGarbageCollected> TestInterfaceWillBeGarbageCollectedOrTestDictionary::getAsTestInterfaceWillBeGarbageCollected() const
{ {
ASSERT(isTestInterfaceWillBeGarbageCollected()); ASSERT(isTestInterfaceWillBeGarbageCollected());
return m_testInterfaceWillBeGarbageCollected; return m_testInterfaceWillBeGarbageCollected;
...@@ -567,7 +633,7 @@ void TestInterfaceWillBeGarbageCollectedOrTestDictionary::setTestInterfaceWillBe ...@@ -567,7 +633,7 @@ void TestInterfaceWillBeGarbageCollectedOrTestDictionary::setTestInterfaceWillBe
m_type = SpecificTypeTestInterfaceWillBeGarbageCollected; m_type = SpecificTypeTestInterfaceWillBeGarbageCollected;
} }
TestDictionary TestInterfaceWillBeGarbageCollectedOrTestDictionary::getAsTestDictionary() TestDictionary TestInterfaceWillBeGarbageCollectedOrTestDictionary::getAsTestDictionary() const
{ {
ASSERT(isTestDictionary()); ASSERT(isTestDictionary());
return m_testDictionary; return m_testDictionary;
......
...@@ -30,15 +30,15 @@ public: ...@@ -30,15 +30,15 @@ public:
bool isNull() const { return m_type == SpecificTypeNone; } bool isNull() const { return m_type == SpecificTypeNone; }
bool isBoolean() const { return m_type == SpecificTypeBoolean; } bool isBoolean() const { return m_type == SpecificTypeBoolean; }
bool getAsBoolean(); bool getAsBoolean() const;
void setBoolean(bool); void setBoolean(bool);
bool isString() const { return m_type == SpecificTypeString; } bool isString() const { return m_type == SpecificTypeString; }
String getAsString(); String getAsString() const;
void setString(String); void setString(String);
bool isUnrestrictedDouble() const { return m_type == SpecificTypeUnrestrictedDouble; } bool isUnrestrictedDouble() const { return m_type == SpecificTypeUnrestrictedDouble; }
double getAsUnrestrictedDouble(); double getAsUnrestrictedDouble() const;
void setUnrestrictedDouble(double); void setUnrestrictedDouble(double);
private: private:
...@@ -68,6 +68,45 @@ inline void v8SetReturnValue(const CallbackInfo& callbackInfo, BooleanOrStringOr ...@@ -68,6 +68,45 @@ inline void v8SetReturnValue(const CallbackInfo& callbackInfo, BooleanOrStringOr
v8SetReturnValue(callbackInfo, toV8(impl, callbackInfo.Holder(), callbackInfo.GetIsolate())); v8SetReturnValue(callbackInfo, toV8(impl, callbackInfo.Holder(), callbackInfo.GetIsolate()));
} }
class DoubleOrString final {
ALLOW_ONLY_INLINE_ALLOCATION();
public:
DoubleOrString();
bool isNull() const { return m_type == SpecificTypeNone; }
bool isDouble() const { return m_type == SpecificTypeDouble; }
double getAsDouble() const;
void setDouble(double);
bool isString() const { return m_type == SpecificTypeString; }
String getAsString() const;
void setString(String);
private:
enum SpecificTypes {
SpecificTypeNone,
SpecificTypeDouble,
SpecificTypeString,
};
SpecificTypes m_type;
double m_double;
String m_string;
};
class V8DoubleOrString final {
public:
static void toImpl(v8::Isolate*, v8::Handle<v8::Value>, DoubleOrString&, ExceptionState&);
};
v8::Handle<v8::Value> toV8(DoubleOrString&, v8::Handle<v8::Object>, v8::Isolate*);
template <class CallbackInfo>
inline void v8SetReturnValue(const CallbackInfo& callbackInfo, DoubleOrString& impl)
{
v8SetReturnValue(callbackInfo, toV8(impl, callbackInfo.Holder(), callbackInfo.GetIsolate()));
}
class NodeOrNodeList final { class NodeOrNodeList final {
ALLOW_ONLY_INLINE_ALLOCATION(); ALLOW_ONLY_INLINE_ALLOCATION();
public: public:
...@@ -75,11 +114,11 @@ public: ...@@ -75,11 +114,11 @@ public:
bool isNull() const { return m_type == SpecificTypeNone; } bool isNull() const { return m_type == SpecificTypeNone; }
bool isNode() const { return m_type == SpecificTypeNode; } bool isNode() const { return m_type == SpecificTypeNode; }
PassRefPtrWillBeRawPtr<Node> getAsNode(); PassRefPtrWillBeRawPtr<Node> getAsNode() const;
void setNode(PassRefPtrWillBeRawPtr<Node>); void setNode(PassRefPtrWillBeRawPtr<Node>);
bool isNodeList() const { return m_type == SpecificTypeNodeList; } bool isNodeList() const { return m_type == SpecificTypeNodeList; }
PassRefPtrWillBeRawPtr<NodeList> getAsNodeList(); PassRefPtrWillBeRawPtr<NodeList> getAsNodeList() const;
void setNodeList(PassRefPtrWillBeRawPtr<NodeList>); void setNodeList(PassRefPtrWillBeRawPtr<NodeList>);
void trace(Visitor*); void trace(Visitor*);
...@@ -116,15 +155,15 @@ public: ...@@ -116,15 +155,15 @@ public:
bool isNull() const { return m_type == SpecificTypeNone; } bool isNull() const { return m_type == SpecificTypeNone; }
bool isString() const { return m_type == SpecificTypeString; } bool isString() const { return m_type == SpecificTypeString; }
String getAsString(); String getAsString() const;
void setString(String); void setString(String);
bool isArrayBuffer() const { return m_type == SpecificTypeArrayBuffer; } bool isArrayBuffer() const { return m_type == SpecificTypeArrayBuffer; }
PassRefPtr<TestArrayBuffer> getAsArrayBuffer(); PassRefPtr<TestArrayBuffer> getAsArrayBuffer() const;
void setArrayBuffer(PassRefPtr<TestArrayBuffer>); void setArrayBuffer(PassRefPtr<TestArrayBuffer>);
bool isArrayBufferView() const { return m_type == SpecificTypeArrayBufferView; } bool isArrayBufferView() const { return m_type == SpecificTypeArrayBufferView; }
PassRefPtr<TestArrayBufferView> getAsArrayBufferView(); PassRefPtr<TestArrayBufferView> getAsArrayBufferView() const;
void setArrayBufferView(PassRefPtr<TestArrayBufferView>); void setArrayBufferView(PassRefPtr<TestArrayBufferView>);
private: private:
...@@ -161,11 +200,11 @@ public: ...@@ -161,11 +200,11 @@ public:
bool isNull() const { return m_type == SpecificTypeNone; } bool isNull() const { return m_type == SpecificTypeNone; }
bool isString() const { return m_type == SpecificTypeString; } bool isString() const { return m_type == SpecificTypeString; }
String getAsString(); String getAsString() const;
void setString(String); void setString(String);
bool isDouble() const { return m_type == SpecificTypeDouble; } bool isDouble() const { return m_type == SpecificTypeDouble; }
double getAsDouble(); double getAsDouble() const;
void setDouble(double); void setDouble(double);
private: private:
...@@ -200,11 +239,11 @@ public: ...@@ -200,11 +239,11 @@ public:
bool isNull() const { return m_type == SpecificTypeNone; } bool isNull() const { return m_type == SpecificTypeNone; }
bool isTestInterfaceGarbageCollected() const { return m_type == SpecificTypeTestInterfaceGarbageCollected; } bool isTestInterfaceGarbageCollected() const { return m_type == SpecificTypeTestInterfaceGarbageCollected; }
RawPtr<TestInterfaceGarbageCollected> getAsTestInterfaceGarbageCollected(); RawPtr<TestInterfaceGarbageCollected> getAsTestInterfaceGarbageCollected() const;
void setTestInterfaceGarbageCollected(RawPtr<TestInterfaceGarbageCollected>); void setTestInterfaceGarbageCollected(RawPtr<TestInterfaceGarbageCollected>);
bool isString() const { return m_type == SpecificTypeString; } bool isString() const { return m_type == SpecificTypeString; }
String getAsString(); String getAsString() const;
void setString(String); void setString(String);
void trace(Visitor*); void trace(Visitor*);
...@@ -241,11 +280,11 @@ public: ...@@ -241,11 +280,11 @@ public:
bool isNull() const { return m_type == SpecificTypeNone; } bool isNull() const { return m_type == SpecificTypeNone; }
bool isTestInterface() const { return m_type == SpecificTypeTestInterface; } bool isTestInterface() const { return m_type == SpecificTypeTestInterface; }
PassRefPtr<TestInterfaceImplementation> getAsTestInterface(); PassRefPtr<TestInterfaceImplementation> getAsTestInterface() const;
void setTestInterface(PassRefPtr<TestInterfaceImplementation>); void setTestInterface(PassRefPtr<TestInterfaceImplementation>);
bool isLong() const { return m_type == SpecificTypeLong; } bool isLong() const { return m_type == SpecificTypeLong; }
int getAsLong(); int getAsLong() const;
void setLong(int); void setLong(int);
private: private:
...@@ -280,11 +319,11 @@ public: ...@@ -280,11 +319,11 @@ public:
bool isNull() const { return m_type == SpecificTypeNone; } bool isNull() const { return m_type == SpecificTypeNone; }
bool isTestInterface() const { return m_type == SpecificTypeTestInterface; } bool isTestInterface() const { return m_type == SpecificTypeTestInterface; }
PassRefPtr<TestInterfaceImplementation> getAsTestInterface(); PassRefPtr<TestInterfaceImplementation> getAsTestInterface() const;
void setTestInterface(PassRefPtr<TestInterfaceImplementation>); void setTestInterface(PassRefPtr<TestInterfaceImplementation>);
bool isTestInterfaceEmpty() const { return m_type == SpecificTypeTestInterfaceEmpty; } bool isTestInterfaceEmpty() const { return m_type == SpecificTypeTestInterfaceEmpty; }
PassRefPtr<TestInterfaceEmpty> getAsTestInterfaceEmpty(); PassRefPtr<TestInterfaceEmpty> getAsTestInterfaceEmpty() const;
void setTestInterfaceEmpty(PassRefPtr<TestInterfaceEmpty>); void setTestInterfaceEmpty(PassRefPtr<TestInterfaceEmpty>);
private: private:
...@@ -319,11 +358,11 @@ public: ...@@ -319,11 +358,11 @@ public:
bool isNull() const { return m_type == SpecificTypeNone; } bool isNull() const { return m_type == SpecificTypeNone; }
bool isTestInterfaceWillBeGarbageCollected() const { return m_type == SpecificTypeTestInterfaceWillBeGarbageCollected; } bool isTestInterfaceWillBeGarbageCollected() const { return m_type == SpecificTypeTestInterfaceWillBeGarbageCollected; }
PassRefPtrWillBeRawPtr<TestInterfaceWillBeGarbageCollected> getAsTestInterfaceWillBeGarbageCollected(); PassRefPtrWillBeRawPtr<TestInterfaceWillBeGarbageCollected> getAsTestInterfaceWillBeGarbageCollected() const;
void setTestInterfaceWillBeGarbageCollected(PassRefPtrWillBeRawPtr<TestInterfaceWillBeGarbageCollected>); void setTestInterfaceWillBeGarbageCollected(PassRefPtrWillBeRawPtr<TestInterfaceWillBeGarbageCollected>);
bool isTestDictionary() const { return m_type == SpecificTypeTestDictionary; } bool isTestDictionary() const { return m_type == SpecificTypeTestDictionary; }
TestDictionary getAsTestDictionary(); TestDictionary getAsTestDictionary() const;
void setTestDictionary(TestDictionary); void setTestDictionary(TestDictionary);
void trace(Visitor*); void trace(Visitor*);
......
...@@ -1734,6 +1734,39 @@ static void eventHandlerAttributeAttributeSetterCallback(v8::Local<v8::String>, ...@@ -1734,6 +1734,39 @@ static void eventHandlerAttributeAttributeSetterCallback(v8::Local<v8::String>,
TRACE_EVENT_SET_SAMPLING_STATE("v8", "V8Execution"); TRACE_EVENT_SET_SAMPLING_STATE("v8", "V8Execution");
} }
static void doubleOrStringAttributeAttributeGetter(const v8::PropertyCallbackInfo<v8::Value>& info)
{
v8::Handle<v8::Object> holder = info.Holder();
TestObject* impl = V8TestObject::toImpl(holder);
DoubleOrString result;
impl->doubleOrStringAttribute(result);
v8SetReturnValue(info, result);
}
static void doubleOrStringAttributeAttributeGetterCallback(v8::Local<v8::String>, const v8::PropertyCallbackInfo<v8::Value>& info)
{
TRACE_EVENT_SET_SAMPLING_STATE("blink", "DOMGetter");
TestObjectV8Internal::doubleOrStringAttributeAttributeGetter(info);
TRACE_EVENT_SET_SAMPLING_STATE("v8", "V8Execution");
}
static void doubleOrStringAttributeAttributeSetter(v8::Local<v8::Value> v8Value, const v8::PropertyCallbackInfo<void>& info)
{
v8::Handle<v8::Object> holder = info.Holder();
ExceptionState exceptionState(ExceptionState::SetterContext, "doubleOrStringAttribute", "TestObject", holder, info.GetIsolate());
DoubleOrString cppValue;
TestObject* impl = V8TestObject::toImpl(holder);
TONATIVE_VOID_EXCEPTIONSTATE_ARGINTERNAL(V8DoubleOrString::toImpl(info.GetIsolate(), v8Value, cppValue, exceptionState), exceptionState);
impl->setDoubleOrStringAttribute(cppValue);
}
static void doubleOrStringAttributeAttributeSetterCallback(v8::Local<v8::String>, v8::Local<v8::Value> v8Value, const v8::PropertyCallbackInfo<void>& info)
{
TRACE_EVENT_SET_SAMPLING_STATE("blink", "DOMSetter");
TestObjectV8Internal::doubleOrStringAttributeAttributeSetter(v8Value, info);
TRACE_EVENT_SET_SAMPLING_STATE("v8", "V8Execution");
}
static void activityLoggingAccessForAllWorldsLongAttributeAttributeGetter(const v8::PropertyCallbackInfo<v8::Value>& info) static void activityLoggingAccessForAllWorldsLongAttributeAttributeGetter(const v8::PropertyCallbackInfo<v8::Value>& info)
{ {
v8::Handle<v8::Object> holder = info.Holder(); v8::Handle<v8::Object> holder = info.Holder();
...@@ -10228,6 +10261,7 @@ static const V8DOMConfiguration::AttributeConfiguration V8TestObjectAttributes[] ...@@ -10228,6 +10261,7 @@ static const V8DOMConfiguration::AttributeConfiguration V8TestObjectAttributes[]
{"testInterfaceOrNullAttribute", TestObjectV8Internal::testInterfaceOrNullAttributeAttributeGetterCallback, TestObjectV8Internal::testInterfaceOrNullAttributeAttributeSetterCallback, 0, 0, 0, static_cast<v8::AccessControl>(v8::DEFAULT), static_cast<v8::PropertyAttribute>(v8::None), V8DOMConfiguration::ExposedToAllScripts, V8DOMConfiguration::OnInstance}, {"testInterfaceOrNullAttribute", TestObjectV8Internal::testInterfaceOrNullAttributeAttributeGetterCallback, TestObjectV8Internal::testInterfaceOrNullAttributeAttributeSetterCallback, 0, 0, 0, static_cast<v8::AccessControl>(v8::DEFAULT), static_cast<v8::PropertyAttribute>(v8::None), V8DOMConfiguration::ExposedToAllScripts, V8DOMConfiguration::OnInstance},
{"testEnumAttribute", TestObjectV8Internal::testEnumAttributeAttributeGetterCallback, TestObjectV8Internal::testEnumAttributeAttributeSetterCallback, 0, 0, 0, static_cast<v8::AccessControl>(v8::DEFAULT), static_cast<v8::PropertyAttribute>(v8::None), V8DOMConfiguration::ExposedToAllScripts, V8DOMConfiguration::OnInstance}, {"testEnumAttribute", TestObjectV8Internal::testEnumAttributeAttributeGetterCallback, TestObjectV8Internal::testEnumAttributeAttributeSetterCallback, 0, 0, 0, static_cast<v8::AccessControl>(v8::DEFAULT), static_cast<v8::PropertyAttribute>(v8::None), V8DOMConfiguration::ExposedToAllScripts, V8DOMConfiguration::OnInstance},
{"eventHandlerAttribute", TestObjectV8Internal::eventHandlerAttributeAttributeGetterCallback, TestObjectV8Internal::eventHandlerAttributeAttributeSetterCallback, 0, 0, 0, static_cast<v8::AccessControl>(v8::DEFAULT), static_cast<v8::PropertyAttribute>(v8::None), V8DOMConfiguration::ExposedToAllScripts, V8DOMConfiguration::OnInstance}, {"eventHandlerAttribute", TestObjectV8Internal::eventHandlerAttributeAttributeGetterCallback, TestObjectV8Internal::eventHandlerAttributeAttributeSetterCallback, 0, 0, 0, static_cast<v8::AccessControl>(v8::DEFAULT), static_cast<v8::PropertyAttribute>(v8::None), V8DOMConfiguration::ExposedToAllScripts, V8DOMConfiguration::OnInstance},
{"doubleOrStringAttribute", TestObjectV8Internal::doubleOrStringAttributeAttributeGetterCallback, TestObjectV8Internal::doubleOrStringAttributeAttributeSetterCallback, 0, 0, 0, static_cast<v8::AccessControl>(v8::DEFAULT), static_cast<v8::PropertyAttribute>(v8::None), V8DOMConfiguration::ExposedToAllScripts, V8DOMConfiguration::OnInstance},
{"activityLoggingAccessForAllWorldsLongAttribute", TestObjectV8Internal::activityLoggingAccessForAllWorldsLongAttributeAttributeGetterCallback, TestObjectV8Internal::activityLoggingAccessForAllWorldsLongAttributeAttributeSetterCallback, 0, 0, 0, static_cast<v8::AccessControl>(v8::DEFAULT), static_cast<v8::PropertyAttribute>(v8::None), V8DOMConfiguration::ExposedToAllScripts, V8DOMConfiguration::OnInstance}, {"activityLoggingAccessForAllWorldsLongAttribute", TestObjectV8Internal::activityLoggingAccessForAllWorldsLongAttributeAttributeGetterCallback, TestObjectV8Internal::activityLoggingAccessForAllWorldsLongAttributeAttributeSetterCallback, 0, 0, 0, static_cast<v8::AccessControl>(v8::DEFAULT), static_cast<v8::PropertyAttribute>(v8::None), V8DOMConfiguration::ExposedToAllScripts, V8DOMConfiguration::OnInstance},
{"activityLoggingGetterForAllWorldsLongAttribute", TestObjectV8Internal::activityLoggingGetterForAllWorldsLongAttributeAttributeGetterCallback, TestObjectV8Internal::activityLoggingGetterForAllWorldsLongAttributeAttributeSetterCallback, 0, 0, 0, static_cast<v8::AccessControl>(v8::DEFAULT), static_cast<v8::PropertyAttribute>(v8::None), V8DOMConfiguration::ExposedToAllScripts, V8DOMConfiguration::OnInstance}, {"activityLoggingGetterForAllWorldsLongAttribute", TestObjectV8Internal::activityLoggingGetterForAllWorldsLongAttributeAttributeGetterCallback, TestObjectV8Internal::activityLoggingGetterForAllWorldsLongAttributeAttributeSetterCallback, 0, 0, 0, static_cast<v8::AccessControl>(v8::DEFAULT), static_cast<v8::PropertyAttribute>(v8::None), V8DOMConfiguration::ExposedToAllScripts, V8DOMConfiguration::OnInstance},
{"activityLoggingSetterForAllWorldsLongAttribute", TestObjectV8Internal::activityLoggingSetterForAllWorldsLongAttributeAttributeGetterCallback, TestObjectV8Internal::activityLoggingSetterForAllWorldsLongAttributeAttributeSetterCallback, 0, 0, 0, static_cast<v8::AccessControl>(v8::DEFAULT), static_cast<v8::PropertyAttribute>(v8::None), V8DOMConfiguration::ExposedToAllScripts, V8DOMConfiguration::OnInstance}, {"activityLoggingSetterForAllWorldsLongAttribute", TestObjectV8Internal::activityLoggingSetterForAllWorldsLongAttributeAttributeGetterCallback, TestObjectV8Internal::activityLoggingSetterForAllWorldsLongAttributeAttributeSetterCallback, 0, 0, 0, static_cast<v8::AccessControl>(v8::DEFAULT), static_cast<v8::PropertyAttribute>(v8::None), V8DOMConfiguration::ExposedToAllScripts, V8DOMConfiguration::OnInstance},
......
...@@ -7,6 +7,37 @@ ...@@ -7,6 +7,37 @@
namespace blink { namespace blink {
void UnionTypesTest::doubleOrStringAttribute(DoubleOrString& doubleOrString)
{
switch (m_attributeType) {
case SpecificTypeNone:
// Default value is zero (of double).
doubleOrString.setDouble(0);
break;
case SpecificTypeDouble:
doubleOrString.setDouble(m_attributeDouble);
break;
case SpecificTypeString:
doubleOrString.setString(m_attributeString);
break;
default:
ASSERT_NOT_REACHED();
}
}
void UnionTypesTest::setDoubleOrStringAttribute(const DoubleOrString& doubleOrString)
{
if (doubleOrString.isDouble()) {
m_attributeDouble = doubleOrString.getAsDouble();
m_attributeType = SpecificTypeDouble;
} else if (doubleOrString.isString()) {
m_attributeString = doubleOrString.getAsString();
m_attributeType = SpecificTypeString;
} else {
ASSERT_NOT_REACHED();
}
}
String UnionTypesTest::doubleOrStringArg(DoubleOrString& doubleOrString) String UnionTypesTest::doubleOrStringArg(DoubleOrString& doubleOrString)
{ {
ASSERT(!doubleOrString.isNull()); ASSERT(!doubleOrString.isNull());
......
...@@ -19,12 +19,27 @@ public: ...@@ -19,12 +19,27 @@ public:
} }
virtual ~UnionTypesTest() { } virtual ~UnionTypesTest() { }
void doubleOrStringAttribute(DoubleOrString&);
void setDoubleOrStringAttribute(const DoubleOrString&);
String doubleOrStringArg(DoubleOrString&); String doubleOrStringArg(DoubleOrString&);
void trace(Visitor*) { } void trace(Visitor*) { }
private: private:
UnionTypesTest() { } UnionTypesTest()
: m_attributeType(SpecificTypeNone)
{
}
enum AttributeSpecificType {
SpecificTypeNone,
SpecificTypeDouble,
SpecificTypeString,
};
AttributeSpecificType m_attributeType;
double m_attributeDouble;
String m_attributeString;
}; };
} // namespace blink } // namespace blink
......
...@@ -5,5 +5,7 @@ ...@@ -5,5 +5,7 @@
[ [
GarbageCollected GarbageCollected
] interface UnionTypesTest { ] interface UnionTypesTest {
attribute (double or DOMString) doubleOrStringAttribute;
DOMString doubleOrStringArg((double or DOMString) arg); DOMString doubleOrStringArg((double or DOMString) arg);
}; };
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