1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
|
# Copyright 2014 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
from utilities import to_snake_case
import v8_types
import v8_utilities
UNION_CPP_INCLUDES = frozenset([
'bindings/core/v8/to_v8_for_core.h',
])
UNION_H_INCLUDES = frozenset([
'base/optional.h',
'bindings/core/v8/dictionary.h',
'bindings/core/v8/exception_state.h',
'bindings/core/v8/native_value_traits.h',
'bindings/core/v8/v8_binding_for_core.h',
'platform/heap/handle.h',
])
cpp_includes = set()
header_forward_decls = set()
header_includes = set()
def container_context(union_type, info_provider):
cpp_includes.clear()
header_forward_decls.clear()
header_includes.clear()
cpp_includes.update(UNION_CPP_INCLUDES)
header_includes.update(UNION_H_INCLUDES)
members = []
# These variables refer to member contexts if the given union type has
# corresponding types. They are used for V8 -> impl conversion.
array_buffer_type = None
array_buffer_view_type = None
array_or_sequence_type = None
boolean_type = None
dictionary_type = None
interface_types = []
numeric_type = None
object_type = None
record_type = None
string_type = None
for member in sorted(union_type.flattened_member_types, key=lambda m: m.name):
context = member_context(member, info_provider)
members.append(context)
if member.base_type == 'ArrayBuffer':
if array_buffer_type:
raise Exception('%s is ambiguous.' % union_type.name)
array_buffer_type = context
elif member.base_type == 'ArrayBufferView':
if array_buffer_view_type:
raise Exception('%s is ambiguous.' % union_type.name)
array_buffer_view_type = context
elif member.is_dictionary:
if dictionary_type:
raise Exception('%s is ambiguous.' % union_type.name)
dictionary_type = context
elif member.is_array_or_sequence_type:
if array_or_sequence_type:
raise Exception('%s is ambiguous.' % union_type.name)
array_or_sequence_type = context
# "Dictionary" is an object, rather than an IDL dictionary.
elif member.base_type == 'Dictionary':
if object_type or record_type:
raise Exception('%s is ambiguous.' % union_type.name)
object_type = context
elif member.is_record_type:
if object_type or record_type:
raise Exception('%s is ambiguous.' % union_type.name)
record_type = context
elif member.is_interface_type:
interface_types.append(context)
elif member is union_type.boolean_member_type:
boolean_type = context
elif member is union_type.numeric_member_type:
numeric_type = context
elif member is union_type.string_member_type:
string_type = context
else:
raise Exception('%s is not supported as an union member.' % member.name)
# Nullable restriction checks
nullable_members = union_type.number_of_nullable_member_types
if nullable_members > 1:
raise Exception('%s contains more than one nullable members' % union_type.name)
if dictionary_type and nullable_members == 1:
raise Exception('%s has a dictionary and a nullable member' % union_type.name)
cpp_class = union_type.cpp_type
return {
'array_buffer_type': array_buffer_type,
'array_buffer_view_type': array_buffer_view_type,
'array_or_sequence_type': array_or_sequence_type,
'boolean_type': boolean_type,
'cpp_class': cpp_class,
'cpp_includes': sorted(cpp_includes),
'dictionary_type': dictionary_type,
'header_includes': sorted(header_includes),
'header_forward_decls': sorted(header_forward_decls),
'includes_nullable_type': union_type.includes_nullable_type,
'interface_types': interface_types,
'members': members,
'numeric_type': numeric_type,
'object_type': object_type,
'record_type': record_type,
'string_type': string_type,
'type_string': str(union_type),
'v8_class': v8_types.v8_type(cpp_class),
}
def _update_includes_and_forward_decls(member, info_provider):
interface_info = info_provider.interfaces_info.get(member.name, None)
if interface_info:
cpp_includes.update(interface_info.get(
'dependencies_include_paths', []))
# We need complete types for IDL dictionaries in union containers.
if member.is_dictionary or member.is_array_buffer_view_or_typed_array:
header_includes.update(member.includes_for_type())
else:
cpp_includes.update(member.includes_for_type())
header_forward_decls.add(member.implemented_as)
else:
if member.is_record_type:
_update_includes_and_forward_decls(member.key_type, info_provider)
_update_includes_and_forward_decls(member.value_type, info_provider)
elif member.is_array_or_sequence_type:
_update_includes_and_forward_decls(member.element_type, info_provider)
elif member.is_union_type:
# Reaching this block means we have a union that is inside a
# record or sequence.
header_forward_decls.add(member.name)
cpp_includes.update([info_provider.include_path_for_union_types(member)])
cpp_includes.update(member.includes_for_type())
def member_context(member, info_provider):
_update_includes_and_forward_decls(member, info_provider)
if member.is_nullable:
member = member.inner_type
return {
'cpp_name': to_snake_case(v8_utilities.cpp_name(member)),
'cpp_type': member.cpp_type_args(used_in_cpp_sequence=True),
'cpp_local_type': member.cpp_type,
'cpp_value_to_v8_value': member.cpp_value_to_v8_value(
cpp_value='impl.GetAs%s()' % member.name, isolate='isolate',
creation_context='creationContext'),
'enum_type': member.enum_type,
'enum_values': member.enum_values,
'is_array_buffer_or_view_type': member.is_array_buffer_or_view,
'is_array_buffer_view_or_typed_array': member.is_array_buffer_view_or_typed_array,
'is_traceable': member.is_traceable,
'rvalue_cpp_type': member.cpp_type_args(used_as_rvalue_type=True),
'specific_type_enum': 'k' + member.name,
'type_name': member.name,
'v8_value_to_local_cpp_value': member.v8_value_to_local_cpp_value(
{}, 'v8Value', 'cppValue', isolate='isolate',
use_exception_state=True)
}
|