Skip to content
This repository was archived by the owner on May 26, 2023. It is now read-only.

Commit f9e1d0a

Browse files
committed
Avoid relying on constructor.name for instanceOf error check.
An improvement beyond graphql#1174, for non-production environments that enable minification, such as NODE_ENV='staging'. Since graphql-js goes to the trouble of providing a Symbol.toStringTag property for most of the classes it exports, and that string is immune to minification (unlike constructor.name), we should use it for error checking in instanceOf(value, constructor) whenever the constructor provides a tag, falling back to constructor.name and value.constructor.name for constructors that do not define Symbol.toStringTag (as before). Motivating issue/investigation: apollographql/apollo-client#7446 (comment)
1 parent 3bce13f commit f9e1d0a

File tree

1 file changed

+19
-3
lines changed

1 file changed

+19
-3
lines changed

src/jsutils/instanceOf.js

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { SYMBOL_TO_STRING_TAG } from '../polyfills/symbols';
2+
13
/**
24
* A replacement for instanceof which includes an error warning when multi-realm
35
* constructors are detected.
@@ -21,9 +23,23 @@ export default process.env.NODE_ENV === 'production'
2123
return true;
2224
}
2325
if (value) {
24-
const valueClass = value.constructor;
25-
const className = constructor.name;
26-
if (className && valueClass && valueClass.name === className) {
26+
const classTag = constructor?.prototype?.[SYMBOL_TO_STRING_TAG];
27+
const className = classTag || constructor.name;
28+
// When the constructor class defines a Symbol.toStringTag
29+
// property, as most classes exported by graphql-js do, use it
30+
// instead of constructor.name and value.constructor.name to
31+
// detect module/realm duplication, since the Symbol.toStringTag
32+
// string is immune to minification. This code runs only when
33+
// process.env.NODE_ENV !== 'production', but minification is
34+
// often enabled in non-production environments like 'staging'.
35+
// In these environments, this error can be thrown mistakenly if
36+
// we rely on constructor.name and value.constructor.name, since
37+
// they could be minified to the same short string, even though
38+
// value is legitimately _not_ instanceof constructor.
39+
const valueName = classTag
40+
? value[SYMBOL_TO_STRING_TAG]
41+
: value.constructor?.name;
42+
if (typeof className === 'string' && valueName === className) {
2743
throw new Error(
2844
`Cannot use ${className} "${value}" from another module or realm.
2945

0 commit comments

Comments
 (0)