Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(331)

Unified Diff: Source/bindings/scripts/v8_values.py

Issue 17572008: WIP IDL compiler rewrite (Closed) Base URL: https://chromium.googlesource.com/chromium/blink@master
Patch Set: Branch: const + primitive type readonly attributes Created 7 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « Source/bindings/scripts/v8_utilities.py ('k') | Source/bindings/templates/attributes.cpp » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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
« no previous file with comments | « Source/bindings/scripts/v8_utilities.py ('k') | Source/bindings/templates/attributes.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698