Skip to content

Commit

Permalink
Work around limitations of React Native Map/Set polyfills.
Browse files Browse the repository at this point in the history
As explained here, with astonishing honesty:
https://github.com/facebook/react-native/blob/98a6f19d7c41e1d4fd3c04d07bb2c4e627f21724/Libraries/vendor/core/Map.js#L44-L50

As reported most recently here:
apollographql/react-apollo#2442 (comment)

For the record, I have previously complained that these polyfills are
simply buggy and should be replaced:
#3394 (comment)

While that is still true, this workaround should moot the debate. 🐮
  • Loading branch information
benjamn committed Oct 3, 2018
1 parent 7b1c254 commit 833072e
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 0 deletions.
32 changes: 32 additions & 0 deletions packages/apollo-cache-inmemory/src/fixPolyfills.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
const frozen = {};
const frozenTestMap = new Map();

if (typeof Object.freeze === 'function') {
Object.freeze(frozen);
}

try {
// If non-extensible objects can't be stored as keys in a Map, make sure we
// do not freeze/seal/etc. an object without first attempting to put it in a
// Map. For example, this gives the React Native Map polyfill a chance to tag
// objects before they become non-extensible:
// https://github.com/facebook/react-native/blob/98a6f19d7c/Libraries/vendor/core/Map.js#L44-L50
// https://github.com/apollographql/react-apollo/issues/2442#issuecomment-426489517
frozenTestMap.set(frozen, frozen).delete(frozen);
} catch {
const wrap = (method: <T>(obj: T) => T): typeof method => {
return method && (obj => {
try {
// If .set succeeds, also call .delete to avoid leaking memory.
frozenTestMap.set(obj, obj).delete(obj);
} finally {
// If .set or .delete fails, the exception will be silently swallowed
// by this return-from-finally statement:
return method.call(Object, obj);
}
});
};
Object.freeze = wrap(Object.freeze);
Object.seal = wrap(Object.seal);
Object.preventExtensions = wrap(Object.preventExtensions);
}
3 changes: 3 additions & 0 deletions packages/apollo-cache-inmemory/src/inMemoryCache.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
// Make builtins like Map and Set safe to use with non-extensible objects.
import './fixPolyfills';

import { DocumentNode } from 'graphql';

import { Cache, DataProxy, ApolloCache, Transaction } from 'apollo-cache';
Expand Down

0 comments on commit 833072e

Please sign in to comment.