OLD | NEW |
(Empty) | |
| 1 # Copyright (C) 2013 Google Inc. All rights reserved. |
| 2 # |
| 3 # Redistribution and use in source and binary forms, with or without |
| 4 # modification, are permitted provided that the following conditions are |
| 5 # met: |
| 6 # |
| 7 # * Redistributions of source code must retain the above copyright |
| 8 # notice, this list of conditions and the following disclaimer. |
| 9 # * Redistributions in binary form must reproduce the above |
| 10 # copyright notice, this list of conditions and the following disclaimer |
| 11 # in the documentation and/or other materials provided with the |
| 12 # distribution. |
| 13 # * Neither the name of Google Inc. nor the names of its |
| 14 # contributors may be used to endorse or promote products derived from |
| 15 # this software without specific prior written permission. |
| 16 # |
| 17 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| 18 # 'AS IS' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| 19 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| 20 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| 21 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| 22 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| 23 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| 24 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 25 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 26 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 27 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 28 |
| 29 |
| 30 import v8_types |
| 31 from v8_types import get_array_or_sequence_type, primitive_type |
| 32 |
| 33 # WIP |
| 34 from v8_includes import get_includes_for_type, includes_for_type |
| 35 from v8_types import get_native_type, is_callback_function_type, is_enum_type, i
s_primitive_type, is_ref_ptr_type, is_union_type |
| 36 |
| 37 |
| 38 CPP_VALUE_TO_JS_VALUE_DICT = { |
| 39 'boolean': 'v8Boolean({cpp_value}, {isolate})', |
| 40 # long long and unsigned long long are not representable in ECMAScript. |
| 41 'long long': 'v8::Number::New(static_cast<double>({cpp_value}))', |
| 42 'unsigned long long': 'v8::Number::New(static_cast<double>({cpp_value}))', |
| 43 'float': 'v8::Number::New({cpp_value})', |
| 44 'double': 'v8::Number::New({cpp_value})', |
| 45 'DOMTimeStamp': 'v8::Number::New(static_cast<double>({cpp_value}))', |
| 46 'DOMString': 'v8String({cpp_value}, {isolate})', |
| 47 } |
| 48 CPP_VALUE_TO_JS_VALUE_ARRAY_OR_SEQUENCE_TYPE = 'v8Array({cpp_value}, {isolate})' |
| 49 CPP_VALUE_TO_JS_VALUE_DEFAULT = 'toV8({cpp_value}, {creation_context}, {isolate}
)' |
| 50 |
| 51 CPP_VALUE_TO_JS_VALUE_RETURN_DICT = { |
| 52 'unsigned': 'v8SetReturnValueUnsigned({callback_info}, {cpp_value});', |
| 53 } |
| 54 |
| 55 |
| 56 def cpp_value_to_js_value(data_type, cpp_value, isolate, creation_context=''): |
| 57 """Return an expression converting a C++ value to a JS value.""" |
| 58 if data_type in CPP_VALUE_TO_JS_VALUE_DICT: |
| 59 expression_format_string = CPP_VALUE_TO_JS_VALUE_DICT[data_type] |
| 60 elif primitive_type(data_type): # primitive but not in dict |
| 61 raise Exception('unexpected data_type %s' % data_type) |
| 62 elif get_array_or_sequence_type(data_type): |
| 63 expression_format_string = CPP_VALUE_TO_JS_VALUE_ARRAY_OR_SEQUENCE_TYPE |
| 64 else: |
| 65 expression_format_string = CPP_VALUE_TO_JS_VALUE_DEFAULT |
| 66 return expression_format_string.format(cpp_value=cpp_value, creation_context
=creation_context, isolate=isolate) |
| 67 |
| 68 |
| 69 def cpp_value_to_js_value_return(data_type, cpp_value, callback_info=''): |
| 70 """Return an expression converting a C++ value to a JS value, as a return va
lue.""" |
| 71 cpp_type = v8_types.cpp_type(data_type) |
| 72 if cpp_type in CPP_VALUE_TO_JS_VALUE_RETURN_DICT: |
| 73 expression_format_string = CPP_VALUE_TO_JS_VALUE_RETURN_DICT[cpp_type] |
| 74 else: |
| 75 raise Exception('unexpected data_type %s' % data_type) |
| 76 return expression_format_string.format(callback_info=callback_info, cpp_valu
e=cpp_value) |
| 77 |
| 78 |
| 79 ################################################################################ |
| 80 # WIP |
| 81 ################################################################################ |
| 82 |
| 83 JS_VALUE_TO_NATIVE_DICT = { |
| 84 # js_type -> (native_expression_format, additional_includes) |
| 85 'boolean': ('{js_value}->BooleanValue()', []), |
| 86 'float': ('static_cast<{idl_type}>({js_value}->NumberValue())', []), |
| 87 'double': ('static_cast<{idl_type}>({js_value}->NumberValue())', []), |
| 88 'byte': ('toInt8({arguments})', []), |
| 89 'octet': ('toUInt8({arguments})', []), |
| 90 'long': ('toInt32({arguments})', []), |
| 91 'short': ('toInt32({arguments})', []), |
| 92 'unsigned long': ('toUInt32({arguments})', []), |
| 93 'unsigned short': ('toUInt32({arguments})', []), |
| 94 'long long': ('toInt64({arguments})', []), |
| 95 'unsigned long long': ('toUInt64({arguments})', []), |
| 96 'CompareHow': ('static_cast<Range::CompareHow>({js_value}->Int32Value())', [
]), |
| 97 'Date': ('toWebCoreDate({js_value})', []), |
| 98 'DOMStringList': ('toDOMStringList({js_value}, {isolate})', []), |
| 99 'DOMString': ('{js_value}', []), |
| 100 'SerializedScriptValue': ('SerializedScriptValue::create({js_value}, {isolat
e})', ['bindings/v8/SerializedScriptValue.h']), |
| 101 'Dictionary': ('Dictionary({js_value}, {isolate})', ['bindings/v8/Dictionary
.h']), |
| 102 'any': ('ScriptValue({js_value})', ['bindings/v8/ScriptValue.h']), |
| 103 'NodeFilter': ('toNodeFilter({js_value})', []), |
| 104 'MediaQueryListListener': ('MediaQueryListListener::create({js_value})', ['c
ore/css/MediaQueryListListener.h']), |
| 105 'EventTarget': ('V8DOMWrapper::isDOMWrapper({js_value}) ? toWrapperTypeInfo(
v8::Handle<v8::Object>::Cast({js_value}))->toEventTarget(v8::Handle<v8::Object>:
:Cast({js_value})) : 0', []), |
| 106 'XPathNSResolver': ('toXPathNSResolver({js_value}, {isolate})', []), |
| 107 } |
| 108 |
| 109 |
| 110 def array_or_sequence_type_to_native(array_or_sequence_type, js_value, isolate): |
| 111 if is_ref_ptr_type(array_or_sequence_type): |
| 112 native_expression_format = '(toRefPtrNativeArray<{array_or_sequence_type
}, V8{array_or_sequence_type}>({js_value}, {isolate}))' |
| 113 native_expression = native_expression_format.format(array_or_sequence_ty
pe=array_or_sequence_type, js_value=js_value, isolate=isolate) |
| 114 additional_includes = ['V8%s.h' % array_or_sequence_type] |
| 115 return native_expression, additional_includes |
| 116 |
| 117 native_type = get_native_type(array_or_sequence_type) |
| 118 native_expression_format = 'toNativeArray<{native_type}>({js_value})' |
| 119 native_expression = native_expression_format.format(native_type=native_type,
js_value=js_value) |
| 120 return native_expression, [] |
| 121 |
| 122 |
| 123 def get_js_value_to_native(idl_type, extended_attributes, js_value, isolate): |
| 124 if 'EnforceRange' in extended_attributes: |
| 125 arguments_list = [js_value, 'EnforceRange', 'ok'] |
| 126 arguments = ', '.join(arguments_list) |
| 127 else: # NormalConversion |
| 128 arguments = js_value |
| 129 |
| 130 array_or_sequence_type = get_array_or_sequence_type(idl_type) |
| 131 if array_or_sequence_type: |
| 132 return array_or_sequence_type_to_native(array_or_sequence_type, js_value
, isolate) |
| 133 |
| 134 if is_enum_type(idl_type): |
| 135 idl_type = 'DOMString' |
| 136 if is_callback_function_type(idl_type): |
| 137 idl_type = 'any' |
| 138 |
| 139 if idl_type in JS_VALUE_TO_NATIVE_DICT: |
| 140 native_expression_format, additional_includes = JS_VALUE_TO_NATIVE_DICT[
idl_type] |
| 141 elif idl_type == 'ArrayBuffer': |
| 142 native_expression_format = '$value->IsArrayBuffer() ? V8ArrayBuffer::toN
ative(v8::Handle<v8::ArrayBuffer>::Cast({js_value})) : 0' |
| 143 additional_includes = get_includes_for_type(idl_type) |
| 144 else: |
| 145 native_expression_format = 'V8{idl_type}::HasInstance({js_value}, {isola
te}, worldType({isolate})) ? V8{idl_type}::toNative(v8::Handle<v8::Object>::Cast
({js_value})) : 0' |
| 146 additional_includes = get_includes_for_type(idl_type) + ['V8%s.h' % idl_
type] |
| 147 |
| 148 native_expression = native_expression_format.format(arguments=arguments, idl
_type=idl_type, isolate=isolate, js_value=js_value) |
| 149 return native_expression, additional_includes |
| 150 |
| 151 |
| 152 def get_js_value_to_native_statement(data_type, extended_attributes, js_value, v
ariable_name, isolate): |
| 153 native_type = get_native_type(data_type, extended_attributes=extended_attrib
utes, used_to_assign_js_value=True) |
| 154 if data_type == 'unsigned long' and 'IsIndex' in extended_attributes: |
| 155 # Special-case index arguments because we need to check that they aren't
< 0. |
| 156 native_type = 'int' |
| 157 native_value, includes = get_js_value_to_native(data_type, extended_attribut
es, js_value, isolate) |
| 158 # print '[get_js_value_to_native_statement]', native_value |
| 159 if data_type == 'DOMString' or is_enum_type(data_type): |
| 160 if not native_type.startswith('V8StringResource'): |
| 161 raise Exception('Wrong native type passed: ' + native_type) |
| 162 code = 'V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(%s, %s, %s);' % (native_typ
e, variable_name, native_value) |
| 163 elif 'EnforceRange' in extended_attributes: |
| 164 code = 'V8TRYCATCH_WITH_TYPECHECK_VOID(%s, %s, %s, %s);' % (native_type,
variable_name, native_value, isolate) |
| 165 else: |
| 166 code = 'V8TRYCATCH_VOID(%s, %s, %s);' % (native_type, variable_name, nat
ive_value) |
| 167 return code, includes |
| 168 |
| 169 |
| 170 def get_pass_owner_expression(data_type, expression): |
| 171 if is_ref_ptr_type(data_type): |
| 172 return expression + '.release()' |
| 173 return expression |
| 174 |
| 175 |
| 176 def get_native_to_js_value_statement(idl_type, extended_attributes, native_value
, receiver='', creation_context='', isolate='', callback_info='', script_wrappab
le='', for_main_world_suffix='', indent='', used_as_return_value=False): |
| 177 """ |
| 178 Create statement which convert native(C++) value into JS value. |
| 179 FIXME: merge with cpp_value_to_js_value and cpp_value_to_js_value_return |
| 180 |
| 181 @param[in] idl_type IDL type |
| 182 @param[in] extended_attributes |
| 183 @param[in] native_value e.g. 'imp->getImte(index)' |
| 184 |
| 185 @param[in] indent |
| 186 @param[in] receiver '%s' will be replaced with JS value. to ret
urn something, use used_as_return_value=True |
| 187 @param[in] creation_context |
| 188 @param[in] isolate |
| 189 @param[in] callback_info |
| 190 @param[in] script_wrappable |
| 191 @param[in] for_main_world_suffix |
| 192 @param[in] used_as_return_value |
| 193 """ |
| 194 # print '[get_native_to_js_value_statement]', idl_type, native_value |
| 195 def create_arguments(arguments): |
| 196 return ', '.join([argument for argument in arguments if argument]) |
| 197 |
| 198 def create_statement(receiver, js_value): |
| 199 # print 'create_statement', receiver, js_value, '\n\n\n' |
| 200 if '%s' in receiver: |
| 201 return receiver % js_value |
| 202 return receiver |
| 203 |
| 204 def create_statements(receiver, js_value): |
| 205 if isinstance(receiver, str): |
| 206 return create_statement(receiver, js_value) |
| 207 if isinstance(receiver, list): |
| 208 return '\n'.join([create_statement(each_receiver, js_value) for each
_receiver in receiver]) |
| 209 raise Exception('receiver should be string or list') |
| 210 |
| 211 if not isolate: |
| 212 raise Exception('An Isolate is mandatory for native value => JS value co
nversion.') |
| 213 |
| 214 includes = [] |
| 215 |
| 216 if is_union_type(idl_type): |
| 217 codes = [] |
| 218 for i, union_member_type in enumerate(idl_type.union_member_types): |
| 219 union_member_number = i |
| 220 union_member_variable = '%s%d' % (native_value, union_member_number) |
| 221 union_member_enabled_variable = '%s%dEnabled' % (native_value, union
_member_number) |
| 222 union_member_native_value = get_pass_owner_expression(union_member_t
ype, union_member_variable) |
| 223 return_js_value_code, union_member_includes = get_native_to_js_value
_statement(union_member_type, extended_attributes, union_member_native_value, re
ceiver=receiver, creation_context=creation_context, isolate=isolate, callback_in
fo=callback_info, script_wrappable=script_wrappable, for_main_world_suffix=for_m
ain_world_suffix, indent=indent + indent, used_as_return_value=used_as_return_va
lue) |
| 224 includes += union_member_includes |
| 225 code = '' |
| 226 if used_as_return_value: |
| 227 code += indent + 'if (%s) {\n' % union_member_enabled_variable |
| 228 code += indent + indent + return_js_value_code + '\n' |
| 229 code += indent + indent + 'return;\n' |
| 230 code += indent + '}\n' |
| 231 else: |
| 232 code += indent + 'if (%s) {\n' % union_member_enabled_variable |
| 233 code += return_js_value_code + '\n' |
| 234 codes.append(code) |
| 235 # print '[]', codes |
| 236 return '\n'.join(codes), includes |
| 237 |
| 238 native_type = get_native_type(idl_type) |
| 239 |
| 240 if idl_type == 'boolean': |
| 241 if used_as_return_value: |
| 242 # receiver = ['%s;', 'return;'] |
| 243 receiver = ['%s;'] |
| 244 return create_statements(receiver, 'v8SetReturnValueBool(%s, %s)' %
(callback_info, native_value)), includes |
| 245 return create_statements(receiver, 'v8Boolean(%s, %s)' % (native_value,
isolate)), includes |
| 246 |
| 247 if idl_type == 'void': |
| 248 if used_as_return_value: |
| 249 # return 'return;', includes |
| 250 return '', includes |
| 251 return create_statements(receiver, 'v8Undefined()'), includes |
| 252 |
| 253 # HTML5 says that unsigned reflected attributes should be in the range |
| 254 # [0, 2^31). When a value isn't in this range, a default value (or 0) |
| 255 # should be returned instead. |
| 256 if 'Reflect' in extended_attributes and (idl_type in ['unsigned long', 'unsi
gned short']): |
| 257 native_value = native_value.replace('getUnsignedIntegralAttribute', 'get
IntegralAttribute') |
| 258 if used_as_return_value: |
| 259 receiver = ['%s;'] |
| 260 return create_statements(receiver, 'v8SetReturnValueUnsigned(%s, std
::max(0, %s))' % (callback_info, native_value)), includes |
| 261 return create_statements(receiver, 'v8::Integer::NewFromUnsigned(std::ma
x(0, %s), %s);' % (native_value, isolate)), includes |
| 262 |
| 263 if native_type == 'int': |
| 264 if used_as_return_value: |
| 265 # receiver = ['%s;', 'return;'] |
| 266 receiver = ['%s;'] |
| 267 return create_statements(receiver, 'v8SetReturnValueInt(%s, %s)' % (
callback_info, native_value)), includes |
| 268 return create_statements(receiver, 'v8::Integer::New(%s, %s)' % (native_
value, isolate)), includes |
| 269 |
| 270 if native_type == 'unsigned': |
| 271 if used_as_return_value: |
| 272 # receiver = ['%s;', 'return;'] |
| 273 receiver = ['%s;'] |
| 274 return create_statements(receiver, 'v8SetReturnValueUnsigned(%s, %s)
' % (callback_info, native_value)), includes |
| 275 return create_statements(receiver, 'v8::Integer::NewFromUnsigned(%s, %s)
' % (native_value, isolate)), includes |
| 276 |
| 277 if idl_type == 'Date': |
| 278 if used_as_return_value: |
| 279 # receiver = ['%s;', 'return;'] |
| 280 # receiver = ['v8SetReturnValue(%s, %%s);' % callback_info, 'ret
urn;'] |
| 281 receiver = ['v8SetReturnValue(%s, %%s);' % callback_info] |
| 282 # return create_statements(receiver, 'v8SetReturnValue(%s, v8Dat
eOrNull(%s, %s))' % (callback_info, native_value, isolate)), includes |
| 283 return create_statements(receiver, 'v8DateOrNull(%s, %s)' % (native_valu
e, isolate)), includes |
| 284 |
| 285 # long long and unsigned long long are not representable in ECMAScript. |
| 286 if idl_type in ['long long', 'unsigned long long', 'DOMTimeStamp']: |
| 287 if used_as_return_value: |
| 288 # receiver = ['%s;', 'return;'] |
| 289 receiver = ['%s;'] |
| 290 return create_statements(receiver, 'v8SetReturnValue(%s, static_cast
<double>(%s))' % (callback_info, native_value)), includes |
| 291 return create_statements(receiver, 'v8::Number::New(static_cast<double>(
%s))' % native_value), includes |
| 292 |
| 293 if is_primitive_type(idl_type): |
| 294 if idl_type not in ['float', 'double']: |
| 295 raise Exception('unexpected type %s' % idl_type) |
| 296 if used_as_return_value: |
| 297 # receiver = ['%s;', 'return;'] |
| 298 receiver = ['%s;'] |
| 299 return create_statements(receiver, 'v8SetReturnValue(%s, %s)' % (cal
lback_info, native_value)), includes |
| 300 return create_statements(receiver, 'v8::Number::New(%s)' % native_value)
, includes |
| 301 |
| 302 if native_type == 'ScriptValue': |
| 303 if used_as_return_value: |
| 304 receiver = ['v8SetReturnValue(%s, %%s);' % callback_info] |
| 305 js_value = '%s.v8Value()' % native_value |
| 306 return create_statements(receiver, js_value), includes |
| 307 |
| 308 if idl_type == 'DOMString' or is_enum_type(idl_type): |
| 309 conversion = extended_attributes.get('TreatReturnedNullStringAs') |
| 310 js_value = '' |
| 311 null_as = '' |
| 312 function_suffix = '' |
| 313 arguments = create_arguments([native_value, isolate]) |
| 314 if conversion is None: |
| 315 null_as = 'NullStringAsEmpty' |
| 316 js_value = 'v8String(%s)' % arguments |
| 317 elif conversion == 'Null': |
| 318 null_as = 'NullStringAsNull' |
| 319 js_value = 'v8StringOrNull(%s)' % arguments |
| 320 function_suffix = 'OrNull' |
| 321 elif conversion == 'Undefined': |
| 322 null_as = 'NullStringAsUndefined' |
| 323 js_value = 'v8StringOrUndefined(%s)' % arguments |
| 324 function_suffix = 'OrUndefined' |
| 325 else: |
| 326 raise Exception('Unknown value for TreatReturnedNullStringAs extende
d attribute') |
| 327 |
| 328 if used_as_return_value: |
| 329 receiver = ['v8SetReturnValueString%s(%s, %%s, %s);' % (function_suf
fix, callback_info, isolate)] |
| 330 return create_statements(receiver, native_value), includes |
| 331 return create_statements(receiver, js_value), includes |
| 332 |
| 333 array_or_sequence_type = get_array_or_sequence_type(idl_type) |
| 334 if array_or_sequence_type: |
| 335 if is_ref_ptr_type(array_or_sequence_type): |
| 336 includes += get_includes_for_type(array_or_sequence_type) |
| 337 if used_as_return_value: |
| 338 # receiver = ['v8SetReturnValue(%s, %%s);' % callback_info, 'ret
urn;'] |
| 339 receiver = ['v8SetReturnValue(%s, %%s);' % callback_info] |
| 340 # return create_statements(receiver, 'v8SetReturnValue(%s, v8Arr
ay(%s, %s))' % (callback_info, native_value, isolate)), includes |
| 341 return create_statements(receiver, 'v8Array(%s, %s)' % (native_value, is
olate)), includes |
| 342 |
| 343 includes += get_includes_for_type(idl_type) |
| 344 |
| 345 if idl_type == 'SerializedScriptValue': |
| 346 includes.append('%s.h' % idl_type) |
| 347 if used_as_return_value: |
| 348 receiver = ['v8SetReturnValue(%s, %%s);' % callback_info] |
| 349 js_value = '%s ? %s->deserialize() : v8::Handle<v8::Value>(v8::Null(%s))
' % (native_value, native_value, isolate) |
| 350 return create_statements(receiver, js_value), includes |
| 351 |
| 352 includes.append('wtf/RefPtr.h') |
| 353 includes.append('wtf/GetPtr.h') |
| 354 |
| 355 if used_as_return_value: |
| 356 # receiver = ['v8SetReturnValue(%s, %%s);' % callback_info, 'return;
'] |
| 357 receiver = ['v8SetReturnValue(%s, %%s);' % callback_info] |
| 358 |
| 359 if script_wrappable: |
| 360 # FIXME: Use safe handles |
| 361 if for_main_world_suffix == 'ForMainWorld': |
| 362 return create_statements(receiver, 'toV8ForMainWorld(%s, %s.Holder()
, %s.GetIsolate())' % (native_value, callback_info, callback_info)), includes |
| 363 return create_statements(receiver, 'toV8Fast(%s, %s, %s)' % (native_valu
e, callback_info, script_wrappable)), includes |
| 364 |
| 365 # FIXME: Use safe handles |
| 366 return create_statements(receiver, 'toV8(%s, %s, %s)' % (native_value, creat
ion_context, isolate)), includes |
OLD | NEW |