@@ -13,15 +13,15 @@ import 'package:wasm_builder/wasm_builder.dart' as w;
1313/// This class is responsible for collecting import and export annotations.
1414/// It also creates Wasm functions for Dart members and manages the worklist
1515/// used to achieve tree shaking.
16- class FunctionCollector extends MemberVisitor1 <w. FunctionType , Reference > {
16+ class FunctionCollector {
1717 final Translator translator;
1818
1919 // Wasm function for each Dart function
2020 final Map <Reference , w.BaseFunction > _functions = {};
2121 // Names of exported functions
22- final Map <Reference , String > exports = {};
22+ final Map <Reference , String > _exports = {};
2323 // Functions for which code has not yet been generated
24- final List <Reference > worklist = [];
24+ final List <Reference > _worklist = [];
2525 // Class IDs for classes that are allocated somewhere in the program
2626 final Set <int > _allocatedClasses = {};
2727 // 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> {
5353 }
5454 }
5555
56+ bool isWorkListEmpty () => _worklist.isEmpty;
57+
58+ Reference popWorkList () => _worklist.removeLast ();
59+
5660 void _importOrExport (Member member) {
5761 String ? importName = translator.getPragma (member, "wasm:import" );
5862 if (importName != null ) {
@@ -63,7 +67,7 @@ class FunctionCollector extends MemberVisitor1<w.FunctionType, Reference> {
6367 String name = importName.substring (dot + 1 );
6468 if (member is Procedure ) {
6569 w.FunctionType ftype = _makeFunctionType (
66- member.reference, member.function.returnType, null ,
70+ translator, member.reference, member.function.returnType, null ,
6771 isImportOrExport: true );
6872 _functions[member.reference] =
6973 m.importFunction (module, name, ftype, "$importName (import)" );
@@ -78,20 +82,22 @@ class FunctionCollector extends MemberVisitor1<w.FunctionType, Reference> {
7882 }
7983
8084 void addExport (Reference target, String exportName) {
81- exports [target] = exportName;
85+ _exports [target] = exportName;
8286 }
8387
88+ String ? getExport (Reference target) => _exports[target];
89+
8490 void initialize () {
8591 // 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) {
8793 Reference target = export.key;
8894 Member node = target.asMember;
8995 if (node is Procedure ) {
90- worklist .add (target);
96+ _worklist .add (target);
9197 assert (! node.isInstanceMember);
9298 assert (! node.isGetter);
9399 w.FunctionType ftype = _makeFunctionType (
94- target, node.function.returnType, null ,
100+ translator, target, node.function.returnType, null ,
95101 isImportOrExport: true );
96102 w.DefinedFunction function = m.addFunction (ftype, "$node " );
97103 _functions[target] = function;
@@ -116,14 +122,14 @@ class FunctionCollector extends MemberVisitor1<w.FunctionType, Reference> {
116122
117123 w.BaseFunction getFunction (Reference target) {
118124 return _functions.putIfAbsent (target, () {
119- worklist .add (target);
125+ _worklist .add (target);
120126 if (target.isAsyncInnerReference) {
121127 w.BaseFunction outer = getFunction (target.asProcedure.reference);
122128 return addAsyncInnerFunctionFor (outer);
123129 }
124130 w.FunctionType ftype = target.isTearOffReference
125131 ? translator.dispatchTable.selectorForTarget (target).signature
126- : target.asMember.accept1 (this , target);
132+ : target.asMember.accept1 (_FunctionTypeGenerator (translator) , target);
127133 return m.addFunction (ftype, "${target .asMember }" );
128134 });
129135 }
@@ -157,6 +163,12 @@ class FunctionCollector extends MemberVisitor1<w.FunctionType, Reference> {
157163 }
158164 }
159165 }
166+ }
167+
168+ class _FunctionTypeGenerator extends MemberVisitor1 <w.FunctionType , Reference > {
169+ final Translator translator;
170+
171+ _FunctionTypeGenerator (this .translator);
160172
161173 @override
162174 w.FunctionType defaultMember (Member node, Reference target) {
@@ -168,7 +180,7 @@ class FunctionCollector extends MemberVisitor1<w.FunctionType, Reference> {
168180 if (! node.isInstanceMember) {
169181 if (target == node.fieldReference) {
170182 // Static field initializer function
171- return _makeFunctionType (target, node.type, null );
183+ return _makeFunctionType (translator, target, node.type, null );
172184 }
173185 String kind = target == node.setterReference ? "setter" : "getter" ;
174186 throw "No implicit $kind function for static field: $node " ;
@@ -181,70 +193,70 @@ class FunctionCollector extends MemberVisitor1<w.FunctionType, Reference> {
181193 assert (! node.isAbstract);
182194 return node.isInstanceMember
183195 ? translator.dispatchTable.selectorForTarget (node.reference).signature
184- : _makeFunctionType (target, node.function.returnType, null );
196+ : _makeFunctionType (translator, target, node.function.returnType, null );
185197 }
186198
187199 @override
188200 w.FunctionType visitConstructor (Constructor node, Reference target) {
189- return _makeFunctionType (target, VoidType (),
201+ return _makeFunctionType (translator, target, VoidType (),
190202 translator.classInfo[node.enclosingClass]! .nonNullableType);
191203 }
204+ }
192205
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+ }
218231
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);
221234
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 );
230241 }
231- return type ;
242+ return w. RefType . extern (nullable : true ) ;
232243 }
244+ return type;
245+ }
233246
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))));
241254
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))];
247260
248- return m.addFunctionType (inputs, outputs);
249- }
261+ return translator.m.addFunctionType (inputs, outputs);
250262}
0 commit comments