Commit f8c388b 1 parent 265ac93 commit f8c388b Copy full SHA for f8c388b
File tree 2 files changed +71
-0
lines changed
2 files changed +71
-0
lines changed Original file line number Diff line number Diff line change @@ -21,12 +21,33 @@ function transformSourceFile(
21
21
): TS.SourceFile {
22
22
const requiredImportedSymbolSet = new Set<ImportedSymbol >();
23
23
24
+ /**
25
+ * An optimization in which every imported symbol is converted into
26
+ * a string that can be matched against directly to guard against
27
+ * duplicates
28
+ */
29
+ const requiredImportedSymbolSetFlags = new Set<string >();
30
+
24
31
context.sourceFileToAddTslibDefinition.set(sourceFile.fileName, false);
25
32
context.sourceFileToRequiredImportedSymbolSet.set(
26
33
sourceFile.fileName,
27
34
requiredImportedSymbolSet
28
35
);
29
36
37
+ const computeImportedSymbolFlag = (symbol: ImportedSymbol): string =>
38
+ [
39
+ "name",
40
+ "propertyName",
41
+ "moduleSpecifier",
42
+ "isNamespaceImport",
43
+ "isDefaultImport",
44
+ ]
45
+ .map(
46
+ (property) =>
47
+ `${property}:${symbol[property as keyof ImportedSymbol] ?? false}`
48
+ )
49
+ .join("|");
50
+
30
51
const visitorOptions: Omit<
31
52
BeforeVisitorOptions<TS .Node>,
32
53
"node" | "sourceFile"
@@ -38,6 +59,12 @@ function transformSourceFile(
38
59
},
39
60
40
61
requireImportedSymbol: (importedSymbol: ImportedSymbol): void => {
62
+ // Guard against duplicates and compute a string so we can do
63
+ // constant time lookups to compare against existing symbols
64
+ const flag = computeImportedSymbolFlag(importedSymbol);
65
+ if (requiredImportedSymbolSetFlags.has(flag)) return;
66
+ requiredImportedSymbolSetFlags.add(flag);
67
+
41
68
requiredImportedSymbolSet.add(importedSymbol);
42
69
},
43
70
Original file line number Diff line number Diff line change @@ -156,6 +156,50 @@ test(
156
156
}
157
157
) ;
158
158
159
+ test (
160
+ "Won't include imports multiple times when the same implementation is registered multiple times. #1" ,
161
+ withTypeScript ,
162
+ ( t , { typescript } ) => {
163
+ const bundle = generateTransformerResult (
164
+ [
165
+ {
166
+ entry : true ,
167
+ fileName : "index.ts" ,
168
+ text : `
169
+ import {DIContainer} from "@wessberg/di";
170
+ import {IFoo, Foo} from "./foo";
171
+
172
+ const container = new DIContainer();
173
+ container.registerSingleton<IFoo, Foo>();
174
+ container.registerSingleton<IFoo, Foo>();
175
+ ` ,
176
+ } ,
177
+ {
178
+ entry : false ,
179
+ fileName : "foo.ts" ,
180
+ text : `
181
+ export interface IFoo {}
182
+ export class Foo implements IFoo {}
183
+ ` ,
184
+ } ,
185
+ ] ,
186
+ { typescript }
187
+ ) ;
188
+ const file = bundle . find ( ( { fileName } ) => fileName . includes ( "index.js" ) ) ! ;
189
+
190
+ t . deepEqual (
191
+ formatCode ( file . text ) ,
192
+ formatCode ( `\
193
+ import { Foo } from "./foo";
194
+ import { DIContainer } from "@wessberg/di";
195
+ const container = new DIContainer();
196
+ container.registerSingleton(undefined, { identifier: "IFoo", implementation: Foo });
197
+ container.registerSingleton(undefined, { identifier: "IFoo", implementation: Foo });
198
+ ` )
199
+ ) ;
200
+ }
201
+ ) ;
202
+
159
203
test (
160
204
"Supports custom implementation functions. #1" ,
161
205
withTypeScript ,
You can’t perform that action at this time.
0 commit comments