const verbose = false; function isPropertyOfType(obj, name, type) { let desc; desc = Object.getOwnPropertyDescriptor(obj, name) return typeof type === 'undefined' || typeof desc.value === type; } function getProperties(obj, type) { let properties = []; for (let name of Object.getOwnPropertyNames(obj)) { if (isPropertyOfType(obj, name, type)) properties.push(name); } return properties; } function* generateObjects(root = this, level = 0) { if (level > 4) return; let obj_names = getProperties(root, 'object'); for (let obj_name of obj_names) { if (obj_name.startsWith('$')) continue; // Ignore internal objects. let obj = root[obj_name]; yield obj; yield* generateObjects(obj, level + 1); } } function getObjects() { let objects = []; for (let obj of generateObjects()) if (!objects.includes(obj)) objects.push(obj); return objects; } function getFunctions(obj) { return getProperties(obj, 'function'); } const thrower = new Proxy({}, { get() { throw 0xc0defefe; } }); for (let o of getObjects()) { for (let f of getFunctions(o)) { const arityPlusOne = o[f].length + 1; if (verbose) print(`Calling ${o}['${f}'](${Array(arityPlusOne).fill("thrower")})`); try { o[f](Array(arityPlusOne).fill(thrower)); } catch (e) { if (`${e}`.includes('constructor without new is invalid')) { try { if (verbose) print(` Constructing instead`); new o[f](Array(arityPlusOne).fill(thrower)); } catch (e) { if (verbose) print(` threw ${e}`); } } else { if (verbose) print(` threw ${e}`); } } } }