@@ -13,15 +13,15 @@ import 'package:wasm_builder/wasm_builder.dart' as w;
13
13
/// This class is responsible for collecting import and export annotations.
14
14
/// It also creates Wasm functions for Dart members and manages the worklist
15
15
/// used to achieve tree shaking.
16
- class FunctionCollector extends MemberVisitor1 <w. FunctionType , Reference > {
16
+ class FunctionCollector {
17
17
final Translator translator;
18
18
19
19
// Wasm function for each Dart function
20
20
final Map <Reference , w.BaseFunction > _functions = {};
21
21
// Names of exported functions
22
- final Map <Reference , String > exports = {};
22
+ final Map <Reference , String > _exports = {};
23
23
// Functions for which code has not yet been generated
24
- final List <Reference > worklist = [];
24
+ final List <Reference > _worklist = [];
25
25
// Class IDs for classes that are allocated somewhere in the program
26
26
final Set <int > _allocatedClasses = {};
27
27
// For each class ID, which functions should be added to the worklist if an
@@ -53,6 +53,10 @@ class FunctionCollector extends MemberVisitor1<w.FunctionType, Reference> {
53
53
}
54
54
}
55
55
56
+ bool isWorkListEmpty () => _worklist.isEmpty;
57
+
58
+ Reference popWorkList () => _worklist.removeLast ();
59
+
56
60
void _importOrExport (Member member) {
57
61
String ? importName = translator.getPragma (member, "wasm:import" );
58
62
if (importName != null ) {
@@ -63,7 +67,7 @@ class FunctionCollector extends MemberVisitor1<w.FunctionType, Reference> {
63
67
String name = importName.substring (dot + 1 );
64
68
if (member is Procedure ) {
65
69
w.FunctionType ftype = _makeFunctionType (
66
- member.reference, member.function.returnType, null ,
70
+ translator, member.reference, member.function.returnType, null ,
67
71
isImportOrExport: true );
68
72
_functions[member.reference] =
69
73
m.importFunction (module, name, ftype, "$importName (import)" );
@@ -78,20 +82,22 @@ class FunctionCollector extends MemberVisitor1<w.FunctionType, Reference> {
78
82
}
79
83
80
84
void addExport (Reference target, String exportName) {
81
- exports [target] = exportName;
85
+ _exports [target] = exportName;
82
86
}
83
87
88
+ String ? getExport (Reference target) => _exports[target];
89
+
84
90
void initialize () {
85
91
// Add exports to the module and add exported functions to the worklist
86
- for (var export in exports .entries) {
92
+ for (var export in _exports .entries) {
87
93
Reference target = export.key;
88
94
Member node = target.asMember;
89
95
if (node is Procedure ) {
90
- worklist .add (target);
96
+ _worklist .add (target);
91
97
assert (! node.isInstanceMember);
92
98
assert (! node.isGetter);
93
99
w.FunctionType ftype = _makeFunctionType (
94
- target, node.function.returnType, null ,
100
+ translator, target, node.function.returnType, null ,
95
101
isImportOrExport: true );
96
102
w.DefinedFunction function = m.addFunction (ftype, "$node " );
97
103
_functions[target] = function;
@@ -116,14 +122,14 @@ class FunctionCollector extends MemberVisitor1<w.FunctionType, Reference> {
116
122
117
123
w.BaseFunction getFunction (Reference target) {
118
124
return _functions.putIfAbsent (target, () {
119
- worklist .add (target);
125
+ _worklist .add (target);
120
126
if (target.isAsyncInnerReference) {
121
127
w.BaseFunction outer = getFunction (target.asProcedure.reference);
122
128
return addAsyncInnerFunctionFor (outer);
123
129
}
124
130
w.FunctionType ftype = target.isTearOffReference
125
131
? translator.dispatchTable.selectorForTarget (target).signature
126
- : target.asMember.accept1 (this , target);
132
+ : target.asMember.accept1 (_FunctionTypeGenerator (translator) , target);
127
133
return m.addFunction (ftype, "${target .asMember }" );
128
134
});
129
135
}
@@ -157,6 +163,12 @@ class FunctionCollector extends MemberVisitor1<w.FunctionType, Reference> {
157
163
}
158
164
}
159
165
}
166
+ }
167
+
168
+ class _FunctionTypeGenerator extends MemberVisitor1 <w.FunctionType , Reference > {
169
+ final Translator translator;
170
+
171
+ _FunctionTypeGenerator (this .translator);
160
172
161
173
@override
162
174
w.FunctionType defaultMember (Member node, Reference target) {
@@ -168,7 +180,7 @@ class FunctionCollector extends MemberVisitor1<w.FunctionType, Reference> {
168
180
if (! node.isInstanceMember) {
169
181
if (target == node.fieldReference) {
170
182
// Static field initializer function
171
- return _makeFunctionType (target, node.type, null );
183
+ return _makeFunctionType (translator, target, node.type, null );
172
184
}
173
185
String kind = target == node.setterReference ? "setter" : "getter" ;
174
186
throw "No implicit $kind function for static field: $node " ;
@@ -181,70 +193,70 @@ class FunctionCollector extends MemberVisitor1<w.FunctionType, Reference> {
181
193
assert (! node.isAbstract);
182
194
return node.isInstanceMember
183
195
? translator.dispatchTable.selectorForTarget (node.reference).signature
184
- : _makeFunctionType (target, node.function.returnType, null );
196
+ : _makeFunctionType (translator, target, node.function.returnType, null );
185
197
}
186
198
187
199
@override
188
200
w.FunctionType visitConstructor (Constructor node, Reference target) {
189
- return _makeFunctionType (target, VoidType (),
201
+ return _makeFunctionType (translator, target, VoidType (),
190
202
translator.classInfo[node.enclosingClass]! .nonNullableType);
191
203
}
204
+ }
192
205
193
- w.FunctionType _makeFunctionType (
194
- Reference target, DartType returnType, w.ValueType ? receiverType,
195
- {bool isImportOrExport = false }) {
196
- Member member = target.asMember;
197
- int typeParamCount = 0 ;
198
- Iterable <DartType > params;
199
- if (member is Field ) {
200
- params = [if (target.isImplicitSetter) member.setterType];
201
- } else {
202
- FunctionNode function = member.function! ;
203
- typeParamCount = (member is Constructor
204
- ? member.enclosingClass.typeParameters
205
- : function.typeParameters)
206
- .length;
207
- List <String > names = [for (var p in function.namedParameters) p.name! ]
208
- ..sort ();
209
- Map <String , DartType > nameTypes = {
210
- for (var p in function.namedParameters) p.name! : p.type
211
- };
212
- params = [
213
- for (var p in function.positionalParameters) p.type,
214
- for (String name in names) nameTypes[name]!
215
- ];
216
- function.positionalParameters.map ((p) => p.type);
217
- }
206
+ w.FunctionType _makeFunctionType (Translator translator, Reference target,
207
+ DartType returnType, w.ValueType ? receiverType,
208
+ {bool isImportOrExport = false }) {
209
+ Member member = target.asMember;
210
+ int typeParamCount = 0 ;
211
+ Iterable <DartType > params;
212
+ if (member is Field ) {
213
+ params = [if (target.isImplicitSetter) member.setterType];
214
+ } else {
215
+ FunctionNode function = member.function! ;
216
+ typeParamCount = (member is Constructor
217
+ ? member.enclosingClass.typeParameters
218
+ : function.typeParameters)
219
+ .length;
220
+ List <String > names = [for (var p in function.namedParameters) p.name! ]
221
+ ..sort ();
222
+ Map <String , DartType > nameTypes = {
223
+ for (var p in function.namedParameters) p.name! : p.type
224
+ };
225
+ params = [
226
+ for (var p in function.positionalParameters) p.type,
227
+ for (String name in names) nameTypes[name]!
228
+ ];
229
+ function.positionalParameters.map ((p) => p.type);
230
+ }
218
231
219
- List <w.ValueType > typeParameters = List .filled (typeParamCount,
220
- translator.classInfo[translator.typeClass]! .nonNullableType);
232
+ List <w.ValueType > typeParameters = List .filled (typeParamCount,
233
+ translator.classInfo[translator.typeClass]! .nonNullableType);
221
234
222
- // The only reference types allowed as parameters and returns on imported
223
- // or exported functions for JS interop are `externref` and `funcref`.
224
- w.ValueType adjustExternalType (w.ValueType type) {
225
- if (isImportOrExport && type is w.RefType ) {
226
- if (type.heapType.isSubtypeOf (w.HeapType .func)) {
227
- return w.RefType .func (nullable: true );
228
- }
229
- return w.RefType .extern (nullable: true );
235
+ // The only reference types allowed as parameters and returns on imported or
236
+ // exported functions for JS interop are `externref` and `funcref`.
237
+ w.ValueType adjustExternalType (w.ValueType type) {
238
+ if (isImportOrExport && type is w.RefType ) {
239
+ if (type.heapType.isSubtypeOf (w.HeapType .func)) {
240
+ return w.RefType .func (nullable: true );
230
241
}
231
- return type ;
242
+ return w. RefType . extern (nullable : true ) ;
232
243
}
244
+ return type;
245
+ }
233
246
234
- List <w.ValueType > inputs = [];
235
- if (receiverType != null ) {
236
- inputs.add (adjustExternalType (receiverType));
237
- }
238
- inputs.addAll (typeParameters.map (adjustExternalType));
239
- inputs.addAll (
240
- params.map ((t) => adjustExternalType (translator.translateType (t))));
247
+ List <w.ValueType > inputs = [];
248
+ if (receiverType != null ) {
249
+ inputs.add (adjustExternalType (receiverType));
250
+ }
251
+ inputs.addAll (typeParameters.map (adjustExternalType));
252
+ inputs.addAll (
253
+ params.map ((t) => adjustExternalType (translator.translateType (t))));
241
254
242
- List <w.ValueType > outputs = returnType is VoidType
243
- ? member.function? .asyncMarker == AsyncMarker .Async
244
- ? [adjustExternalType (translator.topInfo.nullableType)]
245
- : const []
246
- : [adjustExternalType (translator.translateType (returnType))];
255
+ List <w.ValueType > outputs = returnType is VoidType
256
+ ? member.function? .asyncMarker == AsyncMarker .Async
257
+ ? [adjustExternalType (translator.topInfo.nullableType)]
258
+ : const []
259
+ : [adjustExternalType (translator.translateType (returnType))];
247
260
248
- return m.addFunctionType (inputs, outputs);
249
- }
261
+ return translator.m.addFunctionType (inputs, outputs);
250
262
}
0 commit comments