function proxyDescribe(local, name, wrapper, events, returnAsValue) {
  let known;
  let desc = (known = globalDesc[name]) || updateGlobalDesc(name);
  if (!desc) return;
  let { get, set, value } = desc;
  const isChild = !known && isChildWindowKey(name);
  const isWindow = value === window
    || name === 'window'
    || name === 'self'
    || name === 'globalThis'
    || name === 'top' && window === top // `top` is unforgeable
    || name === 'parent' && window === window::getWindowParent();
  if (isWindow) {
    value = desc.value = wrapper;
    get = false;
    delete desc.get;
    delete desc.set;
  } else if (get && set && isString(name)
    // Spoofed String index getters won't be called within length, length itself is unforgeable
    && name.length >= 3 && name[0] === 'o' && name[1] === 'n'
  ) {
    setWindowEvent(desc, name, events, wrapper);
  } else {
    if (get) desc.get = safeBind(get, window);
    if (set) desc.set = safeBind(set, window);
    if (value && name === kConsole) desc.value = value = safeCopy(value);
  }
  if (!isChild) {
    defineProperty(local, name, desc); /* proto is null */// eslint-disable-line no-restricted-syntax
  }
  return !returnAsValue ? desc
    : !get ? value
      : isChild ? global[name]
        : local[name];
}
Note that arrays can be eavesdropped via prototype setters like '0','1',...
on `push` and `arr[i] = 123`, as well as via getters if you read beyond
its length or from an unassigned `hole`.