|
5 | 5 | part of "core_patch.dart"; |
6 | 6 |
|
7 | 7 | /// Finds a named parameter in a named parameter list passed to a dynamic |
8 | | -/// forwarder or `Function.apply` and returns the index of the value of that |
9 | | -/// named parameter. Returns `null` if the name is not in the list. |
| 8 | +/// forwarder or `Function.apply` (in which case the `Symbol` will be canonical |
| 9 | +/// iff the target function accepts it). |
| 10 | +/// |
| 11 | +/// Returns `null` if the name is not in the list. |
10 | 12 | @pragma("wasm:entry-point") |
11 | 13 | int? _getNamedParameterIndex( |
12 | 14 | WasmArray<Object?> namedArguments, |
13 | 15 | Symbol paramName, |
14 | 16 | ) { |
15 | 17 | for (int i = 0; i < namedArguments.length; i += 2) { |
16 | | - // `Symbol.==` does not check identity so we have a fast path here checking |
17 | | - // identities. |
18 | | - // |
19 | | - // We can't check just identities as the symbols in the list may not be |
20 | | - // constants in `Function.apply`. |
21 | | - // |
22 | | - // Also, `paramName` will always be a constant, so with `--minify` it can |
23 | | - // only be equal to a symbol in the list if it's also identical to it. |
24 | | - if (identical(namedArguments[i], paramName) || |
25 | | - (!minify && unsafeCast<Symbol>(namedArguments[i]) == paramName)) { |
| 18 | + if (identical(namedArguments[i], paramName)) { |
26 | 19 | return i + 1; |
27 | 20 | } |
28 | 21 | } |
@@ -57,33 +50,80 @@ List<Object?> _positionalParametersToList(WasmArray<Object?> positional) { |
57 | 50 | Map<Symbol, Object?> _namedParametersToMap(WasmArray<Object?> namedArguments) { |
58 | 51 | final Map<Symbol, Object?> map = {}; |
59 | 52 | for (int i = 0; i < namedArguments.length; i += 2) { |
60 | | - map[namedArguments[i] as Symbol] = namedArguments[i + 1]; |
| 53 | + map[unsafeCast<Symbol>(namedArguments[i])] = namedArguments[i + 1]; |
61 | 54 | } |
62 | 55 | return map; |
63 | 56 | } |
64 | 57 |
|
65 | 58 | /// Converts a named parameter map passed to `Function.apply` to a list that |
66 | 59 | /// can be passed to dynamic call vtable entries. |
| 60 | +/// |
| 61 | +/// The resulting array contains (symbol, value) pairs where |
| 62 | +/// * the symbol is canonicalized iff the target closure has that symbol |
| 63 | +/// * all symbols the target closure accepts will have the same order as the |
| 64 | +/// target expects them |
67 | 65 | @pragma("wasm:entry-point") |
68 | 66 | WasmArray<Object?> _namedParameterMapToArray( |
69 | 67 | Map<Symbol, Object?>? namedArguments, |
| 68 | + _Closure targetClosure, |
70 | 69 | ) { |
71 | 70 | if (namedArguments == null || namedArguments.isEmpty) { |
72 | 71 | return const WasmArray.literal([]); |
73 | 72 | } |
74 | 73 |
|
75 | | - final List<MapEntry<Symbol, Object?>> entries = |
76 | | - namedArguments.entries.toList()..sort( |
77 | | - (entry1, entry2) => |
78 | | - _symbolToString(entry1.key).compareTo(_symbolToString(entry2.key)), |
| 74 | + final targetFunctionType = _Closure._getClosureRuntimeType(targetClosure); |
| 75 | + final targetNamedParameters = targetFunctionType.namedParameters; |
| 76 | + |
| 77 | + List<_NamedParameterValue>? entries; |
| 78 | + int i = 0; |
| 79 | + namedArguments.forEach((symbol, value) { |
| 80 | + int position = _findSymbolPosition(symbol, targetNamedParameters); |
| 81 | + |
| 82 | + // If the target knows about [symbol] then we use it's canonicalized |
| 83 | + // [Symbol] object to ensure any following code can use `identical()`. |
| 84 | + if (position != -1) symbol = targetNamedParameters[position].name; |
| 85 | + |
| 86 | + final entry = _NamedParameterValue(symbol, value, position); |
| 87 | + if (entries == null) { |
| 88 | + i++; |
| 89 | + entries ??= List<_NamedParameterValue>.filled( |
| 90 | + namedArguments.length, |
| 91 | + entry, |
79 | 92 | ); |
| 93 | + return; |
| 94 | + } |
| 95 | + entries![i++] = entry; |
| 96 | + }); |
80 | 97 |
|
81 | | - final WasmArray<Object?> result = WasmArray<Object?>(2 * entries.length); |
| 98 | + final entriesNonNullable = entries!; |
| 99 | + entriesNonNullable.sort((a, b) => a.position.compareTo(b.position)); |
82 | 100 |
|
83 | | - for (int i = 0; i < entries.length; ++i) { |
84 | | - result[2 * i] = entries[i].key; |
85 | | - result[2 * i + 1] = entries[i].value; |
| 101 | + final WasmArray<Object?> result = WasmArray<Object?>( |
| 102 | + 2 * entriesNonNullable.length, |
| 103 | + ); |
| 104 | + for (int i = 0; i < entriesNonNullable.length; ++i) { |
| 105 | + final entry = entriesNonNullable[i]; |
| 106 | + result[2 * i] = entry.symbol; |
| 107 | + result[2 * i + 1] = entry.value; |
86 | 108 | } |
87 | 109 |
|
88 | 110 | return result; |
89 | 111 | } |
| 112 | + |
| 113 | +int _findSymbolPosition(Symbol symbol, WasmArray<_NamedParameter> named) { |
| 114 | + for (int i = 0; i < named.length; ++i) { |
| 115 | + final targetSymbol = named[i].name; |
| 116 | + if (identical(targetSymbol, symbol) || |
| 117 | + (!minify && targetSymbol == symbol)) { |
| 118 | + return i; |
| 119 | + } |
| 120 | + } |
| 121 | + return -1; |
| 122 | +} |
| 123 | + |
| 124 | +class _NamedParameterValue { |
| 125 | + final Symbol symbol; |
| 126 | + final Object? value; |
| 127 | + final int position; |
| 128 | + _NamedParameterValue(this.symbol, this.value, this.position); |
| 129 | +} |
0 commit comments