function isNotHiddenName(name) {
    return !(
        name.substr(0, HIDDEN_NAME_PREFIX.length) == HIDDEN_NAME_PREFIX &&
        name.substr(name.length - 3) === '___');
  }
Security depends on HIDDEN_NAME being both <i>unguessable</i> and
<i>undiscoverable</i> by untrusted code.

<p>Given the known weaknesses of Math.random() on existing
browsers, it does not generate unguessability we can be confident
of.

<p>It is the monkey patching logic in this file that is intended
to ensure undiscoverability. The basic idea is that there are
three fundamental means of discovering properties of an object:
The for/in loop, Object.keys(), and Object.getOwnPropertyNames(),
as well as some proposed ES6 extensions that appear on our
whitelist. The first two only discover enumerable properties, and
we only use HIDDEN_NAME to name a non-enumerable property, so the
only remaining threat should be getOwnPropertyNames and some
proposed ES6 extensions that appear on our whitelist. We monkey
patch them to remove HIDDEN_NAME from the list of properties they
returns.

<p>TODO(erights): On a platform with built-in Proxies, proxies
could be used to trap and thereby discover the HIDDEN_NAME, so we
need to monkey patch Proxy.create, Proxy.createFunction, etc, in
order to wrap the provided handler with the real handler which
filters out all traps using HIDDEN_NAME.

<p>TODO(erights): Revisit Mike Stay's suggestion that we use an
encapsulated function at a not-necessarily-secret name, which
uses the Stiegler shared-state rights amplification pattern to
reveal the associated value only to the WeakMap in which this key
is associated with that value. Since only the key retains the
function, the function can also remember the key without causing
leakage of the key, so this doesn't violate our general gc
goals. In addition, because the name need not be a guarded
secret, we could efficiently handle cross-frame frozen keys.