| 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
|
|
|