Skip to content

Commit

Permalink
Cache query documents transformed by InMemoryCache.
Browse files Browse the repository at this point in the history
After #3444 removed `Map`-based caching for `addTypenameToDocument` (in
order to fix memory leaks), the `InMemoryCache#transformDocument` method
now creates a completely new `DocumentNode` every time it's called
(assuming this.addTypename is true, which it is by default).

This commit uses a `WeakMap` to cache calls to `addTypenameToDocument` in
`InMemoryCache#transformDocument`, so that repeated cache reads will no
longer create an unbounded number of new `DocumentNode` objects. The
benefit of the `WeakMap` is that it does not prevent its keys (the
original `DocumentNode` objects) from being garbage collected, which is
another way of preventing memory leaks.  Note that `WeakMap` may have to
be polyfilled in older browsers, but there are many options for that.

This optimization will be important for #3394, since the query document is
involved in cache keys used to store cache partial query results.

cc @hwillson @jbaxleyiii @brunorzn
  • Loading branch information
benjamn committed Jun 6, 2018
1 parent ffea402 commit 9073936
Showing 1 changed file with 11 additions and 1 deletion.
12 changes: 11 additions & 1 deletion packages/apollo-cache-inmemory/src/inMemoryCache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ export class InMemoryCache extends ApolloCache<NormalizedCacheObject> {
protected optimistic: OptimisticStoreItem[] = [];
private watches: Cache.WatchOptions[] = [];
private addTypename: boolean;
private typenameDocumentCache = new WeakMap<DocumentNode, DocumentNode>();

// Set this while in a transaction to prevent broadcasts...
// don't forget to turn it back on!
Expand Down Expand Up @@ -204,7 +205,16 @@ export class InMemoryCache extends ApolloCache<NormalizedCacheObject> {
}

public transformDocument(document: DocumentNode): DocumentNode {
if (this.addTypename) return addTypenameToDocument(document);
if (this.addTypename) {
let result = this.typenameDocumentCache.get(document);
if (!result) {
this.typenameDocumentCache.set(
document,
(result = addTypenameToDocument(document)),
);
}
return result;
}
return document;
}

Expand Down

0 comments on commit 9073936

Please sign in to comment.