| Index: Source/bindings/scripts/v8_values.py | 
| diff --git a/Source/bindings/scripts/v8_values.py b/Source/bindings/scripts/v8_values.py | 
| new file mode 100644 | 
| index 0000000000000000000000000000000000000000..7831d2c75d9e1c349842766fb73529f98f4bb1a7 | 
| --- /dev/null | 
| +++ b/Source/bindings/scripts/v8_values.py | 
| @@ -0,0 +1,366 @@ | 
| +# Copyright (C) 2013 Google Inc. All rights reserved. | 
| +# | 
| +# Redistribution and use in source and binary forms, with or without | 
| +# modification, are permitted provided that the following conditions are | 
| +# met: | 
| +# | 
| +#     * Redistributions of source code must retain the above copyright | 
| +# notice, this list of conditions and the following disclaimer. | 
| +#     * Redistributions in binary form must reproduce the above | 
| +# copyright notice, this list of conditions and the following disclaimer | 
| +# in the documentation and/or other materials provided with the | 
| +# distribution. | 
| +#     * Neither the name of Google Inc. nor the names of its | 
| +# contributors may be used to endorse or promote products derived from | 
| +# this software without specific prior written permission. | 
| +# | 
| +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | 
| +# 'AS IS' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | 
| +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | 
| +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | 
| +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | 
| +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 
| +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 
| +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 
| +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 
| +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 
| +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 
| + | 
| + | 
| +import v8_types | 
| +from v8_types import get_array_or_sequence_type, primitive_type | 
| + | 
| +# WIP | 
| +from v8_includes import get_includes_for_type, includes_for_type | 
| +from v8_types import get_native_type, is_callback_function_type, is_enum_type, is_primitive_type, is_ref_ptr_type, is_union_type | 
| + | 
| + | 
| +CPP_VALUE_TO_JS_VALUE_DICT = { | 
| +    'boolean': 'v8Boolean({cpp_value}, {isolate})', | 
| +    # long long and unsigned long long are not representable in ECMAScript. | 
| +    'long long': 'v8::Number::New(static_cast<double>({cpp_value}))', | 
| +    'unsigned long long': 'v8::Number::New(static_cast<double>({cpp_value}))', | 
| +    'float': 'v8::Number::New({cpp_value})', | 
| +    'double': 'v8::Number::New({cpp_value})', | 
| +    'DOMTimeStamp': 'v8::Number::New(static_cast<double>({cpp_value}))', | 
| +    'DOMString': 'v8String({cpp_value}, {isolate})', | 
| +} | 
| +CPP_VALUE_TO_JS_VALUE_ARRAY_OR_SEQUENCE_TYPE = 'v8Array({cpp_value}, {isolate})' | 
| +CPP_VALUE_TO_JS_VALUE_DEFAULT = 'toV8({cpp_value}, {creation_context}, {isolate})' | 
| + | 
| +CPP_VALUE_TO_JS_VALUE_RETURN_DICT = { | 
| +    'unsigned': 'v8SetReturnValueUnsigned({callback_info}, {cpp_value});', | 
| +} | 
| + | 
| + | 
| +def cpp_value_to_js_value(data_type, cpp_value, isolate, creation_context=''): | 
| +    """Return an expression converting a C++ value to a JS value.""" | 
| +    if data_type in CPP_VALUE_TO_JS_VALUE_DICT: | 
| +        expression_format_string = CPP_VALUE_TO_JS_VALUE_DICT[data_type] | 
| +    elif primitive_type(data_type):  # primitive but not in dict | 
| +        raise Exception('unexpected data_type %s' % data_type) | 
| +    elif get_array_or_sequence_type(data_type): | 
| +        expression_format_string = CPP_VALUE_TO_JS_VALUE_ARRAY_OR_SEQUENCE_TYPE | 
| +    else: | 
| +        expression_format_string = CPP_VALUE_TO_JS_VALUE_DEFAULT | 
| +    return expression_format_string.format(cpp_value=cpp_value, creation_context=creation_context, isolate=isolate) | 
| + | 
| + | 
| +def cpp_value_to_js_value_return(data_type, cpp_value, callback_info=''): | 
| +    """Return an expression converting a C++ value to a JS value, as a return value.""" | 
| +    cpp_type = v8_types.cpp_type(data_type) | 
| +    if cpp_type in CPP_VALUE_TO_JS_VALUE_RETURN_DICT: | 
| +        expression_format_string = CPP_VALUE_TO_JS_VALUE_RETURN_DICT[cpp_type] | 
| +    else: | 
| +        raise Exception('unexpected data_type %s' % data_type) | 
| +    return expression_format_string.format(callback_info=callback_info, cpp_value=cpp_value) | 
| + | 
| + | 
| +################################################################################ | 
| +# WIP | 
| +################################################################################ | 
| + | 
| +JS_VALUE_TO_NATIVE_DICT = { | 
| +    # js_type -> (native_expression_format, additional_includes) | 
| +    'boolean': ('{js_value}->BooleanValue()', []), | 
| +    'float': ('static_cast<{idl_type}>({js_value}->NumberValue())', []), | 
| +    'double': ('static_cast<{idl_type}>({js_value}->NumberValue())', []), | 
| +    'byte': ('toInt8({arguments})', []), | 
| +    'octet': ('toUInt8({arguments})', []), | 
| +    'long': ('toInt32({arguments})', []), | 
| +    'short': ('toInt32({arguments})', []), | 
| +    'unsigned long': ('toUInt32({arguments})', []), | 
| +    'unsigned short': ('toUInt32({arguments})', []), | 
| +    'long long': ('toInt64({arguments})', []), | 
| +    'unsigned long long': ('toUInt64({arguments})', []), | 
| +    'CompareHow': ('static_cast<Range::CompareHow>({js_value}->Int32Value())', []), | 
| +    'Date': ('toWebCoreDate({js_value})', []), | 
| +    'DOMStringList': ('toDOMStringList({js_value}, {isolate})', []), | 
| +    'DOMString': ('{js_value}', []), | 
| +    'SerializedScriptValue': ('SerializedScriptValue::create({js_value}, {isolate})', ['bindings/v8/SerializedScriptValue.h']), | 
| +    'Dictionary': ('Dictionary({js_value}, {isolate})', ['bindings/v8/Dictionary.h']), | 
| +    'any': ('ScriptValue({js_value})', ['bindings/v8/ScriptValue.h']), | 
| +    'NodeFilter': ('toNodeFilter({js_value})', []), | 
| +    'MediaQueryListListener': ('MediaQueryListListener::create({js_value})', ['core/css/MediaQueryListListener.h']), | 
| +    'EventTarget': ('V8DOMWrapper::isDOMWrapper({js_value}) ? toWrapperTypeInfo(v8::Handle<v8::Object>::Cast({js_value}))->toEventTarget(v8::Handle<v8::Object>::Cast({js_value})) : 0', []), | 
| +    'XPathNSResolver': ('toXPathNSResolver({js_value}, {isolate})', []), | 
| +} | 
| + | 
| + | 
| +def array_or_sequence_type_to_native(array_or_sequence_type, js_value, isolate): | 
| +    if is_ref_ptr_type(array_or_sequence_type): | 
| +        native_expression_format = '(toRefPtrNativeArray<{array_or_sequence_type}, V8{array_or_sequence_type}>({js_value}, {isolate}))' | 
| +        native_expression = native_expression_format.format(array_or_sequence_type=array_or_sequence_type, js_value=js_value, isolate=isolate) | 
| +        additional_includes = ['V8%s.h' % array_or_sequence_type] | 
| +        return native_expression, additional_includes | 
| + | 
| +    native_type = get_native_type(array_or_sequence_type) | 
| +    native_expression_format = 'toNativeArray<{native_type}>({js_value})' | 
| +    native_expression = native_expression_format.format(native_type=native_type, js_value=js_value) | 
| +    return native_expression, [] | 
| + | 
| + | 
| +def get_js_value_to_native(idl_type, extended_attributes, js_value, isolate): | 
| +    if 'EnforceRange' in extended_attributes: | 
| +        arguments_list = [js_value, 'EnforceRange', 'ok'] | 
| +        arguments = ', '.join(arguments_list) | 
| +    else:  # NormalConversion | 
| +        arguments = js_value | 
| + | 
| +    array_or_sequence_type = get_array_or_sequence_type(idl_type) | 
| +    if array_or_sequence_type: | 
| +        return array_or_sequence_type_to_native(array_or_sequence_type, js_value, isolate) | 
| + | 
| +    if is_enum_type(idl_type): | 
| +        idl_type = 'DOMString' | 
| +    if is_callback_function_type(idl_type): | 
| +        idl_type = 'any' | 
| + | 
| +    if idl_type in JS_VALUE_TO_NATIVE_DICT: | 
| +        native_expression_format, additional_includes = JS_VALUE_TO_NATIVE_DICT[idl_type] | 
| +    elif idl_type == 'ArrayBuffer': | 
| +        native_expression_format = '$value->IsArrayBuffer() ? V8ArrayBuffer::toNative(v8::Handle<v8::ArrayBuffer>::Cast({js_value})) : 0' | 
| +        additional_includes = get_includes_for_type(idl_type) | 
| +    else: | 
| +        native_expression_format = 'V8{idl_type}::HasInstance({js_value}, {isolate}, worldType({isolate})) ? V8{idl_type}::toNative(v8::Handle<v8::Object>::Cast({js_value})) : 0' | 
| +        additional_includes = get_includes_for_type(idl_type) + ['V8%s.h' % idl_type] | 
| + | 
| +    native_expression = native_expression_format.format(arguments=arguments, idl_type=idl_type, isolate=isolate, js_value=js_value) | 
| +    return native_expression, additional_includes | 
| + | 
| + | 
| +def get_js_value_to_native_statement(data_type, extended_attributes, js_value, variable_name, isolate): | 
| +    native_type = get_native_type(data_type, extended_attributes=extended_attributes, used_to_assign_js_value=True) | 
| +    if data_type == 'unsigned long' and 'IsIndex' in extended_attributes: | 
| +        # Special-case index arguments because we need to check that they aren't < 0. | 
| +        native_type = 'int' | 
| +    native_value, includes = get_js_value_to_native(data_type, extended_attributes, js_value, isolate) | 
| +    # print '[get_js_value_to_native_statement]', native_value | 
| +    if data_type == 'DOMString' or is_enum_type(data_type): | 
| +        if not native_type.startswith('V8StringResource'): | 
| +            raise Exception('Wrong native type passed: ' + native_type) | 
| +        code = 'V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(%s, %s, %s);' % (native_type, variable_name, native_value) | 
| +    elif 'EnforceRange' in extended_attributes: | 
| +        code = 'V8TRYCATCH_WITH_TYPECHECK_VOID(%s, %s, %s, %s);' % (native_type, variable_name, native_value, isolate) | 
| +    else: | 
| +        code = 'V8TRYCATCH_VOID(%s, %s, %s);' % (native_type, variable_name, native_value) | 
| +    return code, includes | 
| + | 
| + | 
| +def get_pass_owner_expression(data_type, expression): | 
| +    if is_ref_ptr_type(data_type): | 
| +        return expression + '.release()' | 
| +    return expression | 
| + | 
| + | 
| +def get_native_to_js_value_statement(idl_type, extended_attributes, native_value, receiver='', creation_context='', isolate='', callback_info='', script_wrappable='', for_main_world_suffix='', indent='', used_as_return_value=False): | 
| +    """ | 
| +    Create statement which convert native(C++) value into JS value. | 
| +    FIXME: merge with cpp_value_to_js_value and cpp_value_to_js_value_return | 
| + | 
| +    @param[in] idl_type                  IDL type | 
| +    @param[in] extended_attributes | 
| +    @param[in] native_value          e.g. 'imp->getImte(index)' | 
| + | 
| +    @param[in] indent | 
| +    @param[in] receiver              '%s' will be replaced with JS value. to return something, use used_as_return_value=True | 
| +    @param[in] creation_context | 
| +    @param[in] isolate | 
| +    @param[in] callback_info | 
| +    @param[in] script_wrappable | 
| +    @param[in] for_main_world_suffix | 
| +    @param[in] used_as_return_value | 
| +    """ | 
| +    # print '[get_native_to_js_value_statement]', idl_type, native_value | 
| +    def create_arguments(arguments): | 
| +        return ', '.join([argument for argument in arguments if argument]) | 
| + | 
| +    def create_statement(receiver, js_value): | 
| +#             print 'create_statement', receiver, js_value, '\n\n\n' | 
| +        if '%s' in receiver: | 
| +            return receiver % js_value | 
| +        return receiver | 
| + | 
| +    def create_statements(receiver, js_value): | 
| +        if isinstance(receiver, str): | 
| +            return create_statement(receiver, js_value) | 
| +        if isinstance(receiver, list): | 
| +            return '\n'.join([create_statement(each_receiver, js_value) for each_receiver in receiver]) | 
| +        raise Exception('receiver should be string or list') | 
| + | 
| +    if not isolate: | 
| +        raise Exception('An Isolate is mandatory for native value => JS value conversion.') | 
| + | 
| +    includes = [] | 
| + | 
| +    if is_union_type(idl_type): | 
| +        codes = [] | 
| +        for i, union_member_type in enumerate(idl_type.union_member_types): | 
| +            union_member_number = i | 
| +            union_member_variable = '%s%d' % (native_value, union_member_number) | 
| +            union_member_enabled_variable = '%s%dEnabled' % (native_value, union_member_number) | 
| +            union_member_native_value = get_pass_owner_expression(union_member_type, union_member_variable) | 
| +            return_js_value_code, union_member_includes = get_native_to_js_value_statement(union_member_type, extended_attributes, union_member_native_value, receiver=receiver, creation_context=creation_context, isolate=isolate, callback_info=callback_info, script_wrappable=script_wrappable, for_main_world_suffix=for_main_world_suffix, indent=indent + indent, used_as_return_value=used_as_return_value) | 
| +            includes += union_member_includes | 
| +            code = '' | 
| +            if used_as_return_value: | 
| +                code += indent + 'if (%s) {\n' % union_member_enabled_variable | 
| +                code += indent + indent + return_js_value_code + '\n' | 
| +                code += indent + indent + 'return;\n' | 
| +                code += indent + '}\n' | 
| +            else: | 
| +                code += indent + 'if (%s) {\n' % union_member_enabled_variable | 
| +                code += return_js_value_code + '\n' | 
| +            codes.append(code) | 
| +#             print '[]', codes | 
| +        return '\n'.join(codes), includes | 
| + | 
| +    native_type = get_native_type(idl_type) | 
| + | 
| +    if idl_type == 'boolean': | 
| +        if used_as_return_value: | 
| +#                 receiver = ['%s;', 'return;'] | 
| +            receiver = ['%s;'] | 
| +            return create_statements(receiver, 'v8SetReturnValueBool(%s, %s)' % (callback_info, native_value)), includes | 
| +        return create_statements(receiver, 'v8Boolean(%s, %s)' % (native_value, isolate)), includes | 
| + | 
| +    if idl_type == 'void': | 
| +        if used_as_return_value: | 
| +#                 return 'return;', includes | 
| +            return '', includes | 
| +        return create_statements(receiver, 'v8Undefined()'), includes | 
| + | 
| +    # HTML5 says that unsigned reflected attributes should be in the range | 
| +    # [0, 2^31). When a value isn't in this range, a default value (or 0) | 
| +    # should be returned instead. | 
| +    if 'Reflect' in extended_attributes and (idl_type in ['unsigned long', 'unsigned short']): | 
| +        native_value = native_value.replace('getUnsignedIntegralAttribute', 'getIntegralAttribute') | 
| +        if used_as_return_value: | 
| +            receiver = ['%s;'] | 
| +            return create_statements(receiver, 'v8SetReturnValueUnsigned(%s, std::max(0, %s))' % (callback_info, native_value)), includes | 
| +        return create_statements(receiver, 'v8::Integer::NewFromUnsigned(std::max(0, %s), %s);' % (native_value, isolate)), includes | 
| + | 
| +    if native_type == 'int': | 
| +        if used_as_return_value: | 
| +#                 receiver = ['%s;', 'return;'] | 
| +            receiver = ['%s;'] | 
| +            return create_statements(receiver, 'v8SetReturnValueInt(%s, %s)' % (callback_info, native_value)), includes | 
| +        return create_statements(receiver, 'v8::Integer::New(%s, %s)' % (native_value, isolate)), includes | 
| + | 
| +    if native_type == 'unsigned': | 
| +        if used_as_return_value: | 
| +#                 receiver = ['%s;', 'return;'] | 
| +            receiver = ['%s;'] | 
| +            return create_statements(receiver, 'v8SetReturnValueUnsigned(%s, %s)' % (callback_info, native_value)), includes | 
| +        return create_statements(receiver, 'v8::Integer::NewFromUnsigned(%s, %s)' % (native_value, isolate)), includes | 
| + | 
| +    if idl_type == 'Date': | 
| +        if used_as_return_value: | 
| +#                 receiver = ['%s;', 'return;'] | 
| +#                 receiver = ['v8SetReturnValue(%s, %%s);' % callback_info, 'return;'] | 
| +            receiver = ['v8SetReturnValue(%s, %%s);' % callback_info] | 
| +#                 return create_statements(receiver, 'v8SetReturnValue(%s, v8DateOrNull(%s, %s))' % (callback_info, native_value, isolate)), includes | 
| +        return create_statements(receiver, 'v8DateOrNull(%s, %s)' % (native_value, isolate)), includes | 
| + | 
| +    # long long and unsigned long long are not representable in ECMAScript. | 
| +    if idl_type in ['long long', 'unsigned long long', 'DOMTimeStamp']: | 
| +        if used_as_return_value: | 
| +#                 receiver = ['%s;', 'return;'] | 
| +            receiver = ['%s;'] | 
| +            return create_statements(receiver, 'v8SetReturnValue(%s, static_cast<double>(%s))' % (callback_info, native_value)), includes | 
| +        return create_statements(receiver, 'v8::Number::New(static_cast<double>(%s))' % native_value), includes | 
| + | 
| +    if is_primitive_type(idl_type): | 
| +        if idl_type not in ['float', 'double']: | 
| +            raise Exception('unexpected type %s' % idl_type) | 
| +        if used_as_return_value: | 
| +#                 receiver = ['%s;', 'return;'] | 
| +            receiver = ['%s;'] | 
| +            return create_statements(receiver, 'v8SetReturnValue(%s, %s)' % (callback_info, native_value)), includes | 
| +        return create_statements(receiver, 'v8::Number::New(%s)' % native_value), includes | 
| + | 
| +    if native_type == 'ScriptValue': | 
| +        if used_as_return_value: | 
| +            receiver = ['v8SetReturnValue(%s, %%s);' % callback_info] | 
| +        js_value = '%s.v8Value()' % native_value | 
| +        return create_statements(receiver, js_value), includes | 
| + | 
| +    if idl_type == 'DOMString' or is_enum_type(idl_type): | 
| +        conversion = extended_attributes.get('TreatReturnedNullStringAs') | 
| +        js_value = '' | 
| +        null_as = '' | 
| +        function_suffix = '' | 
| +        arguments = create_arguments([native_value, isolate]) | 
| +        if conversion is None: | 
| +            null_as = 'NullStringAsEmpty' | 
| +            js_value = 'v8String(%s)' % arguments | 
| +        elif conversion == 'Null': | 
| +            null_as = 'NullStringAsNull' | 
| +            js_value = 'v8StringOrNull(%s)' % arguments | 
| +            function_suffix = 'OrNull' | 
| +        elif conversion == 'Undefined': | 
| +            null_as = 'NullStringAsUndefined' | 
| +            js_value = 'v8StringOrUndefined(%s)' % arguments | 
| +            function_suffix = 'OrUndefined' | 
| +        else: | 
| +            raise Exception('Unknown value for TreatReturnedNullStringAs extended attribute') | 
| + | 
| +        if used_as_return_value: | 
| +            receiver = ['v8SetReturnValueString%s(%s, %%s, %s);' % (function_suffix, callback_info, isolate)] | 
| +            return create_statements(receiver, native_value), includes | 
| +        return create_statements(receiver, js_value), includes | 
| + | 
| +    array_or_sequence_type = get_array_or_sequence_type(idl_type) | 
| +    if array_or_sequence_type: | 
| +        if is_ref_ptr_type(array_or_sequence_type): | 
| +            includes += get_includes_for_type(array_or_sequence_type) | 
| +        if used_as_return_value: | 
| +#                 receiver = ['v8SetReturnValue(%s, %%s);' % callback_info, 'return;'] | 
| +            receiver = ['v8SetReturnValue(%s, %%s);' % callback_info] | 
| +#                 return create_statements(receiver, 'v8SetReturnValue(%s, v8Array(%s, %s))' % (callback_info, native_value, isolate)), includes | 
| +        return create_statements(receiver, 'v8Array(%s, %s)' % (native_value, isolate)), includes | 
| + | 
| +    includes += get_includes_for_type(idl_type) | 
| + | 
| +    if idl_type == 'SerializedScriptValue': | 
| +        includes.append('%s.h' % idl_type) | 
| +        if used_as_return_value: | 
| +            receiver = ['v8SetReturnValue(%s, %%s);' % callback_info] | 
| +        js_value = '%s ? %s->deserialize() : v8::Handle<v8::Value>(v8::Null(%s))' % (native_value, native_value, isolate) | 
| +        return create_statements(receiver, js_value), includes | 
| + | 
| +    includes.append('wtf/RefPtr.h') | 
| +    includes.append('wtf/GetPtr.h') | 
| + | 
| +    if used_as_return_value: | 
| +#             receiver = ['v8SetReturnValue(%s, %%s);' % callback_info, 'return;'] | 
| +        receiver = ['v8SetReturnValue(%s, %%s);' % callback_info] | 
| + | 
| +    if script_wrappable: | 
| +        # FIXME: Use safe handles | 
| +        if for_main_world_suffix == 'ForMainWorld': | 
| +            return create_statements(receiver, 'toV8ForMainWorld(%s, %s.Holder(), %s.GetIsolate())' % (native_value, callback_info, callback_info)), includes | 
| +        return create_statements(receiver, 'toV8Fast(%s, %s, %s)' % (native_value, callback_info, script_wrappable)), includes | 
| + | 
| +    # FIXME: Use safe handles | 
| +    return create_statements(receiver, 'toV8(%s, %s, %s)' % (native_value, creation_context, isolate)), includes | 
|  |