// I wrote this in packages/util/misc in cocalc and copied it here. -- William Stein12// TODO: this is also in python-wasm/src/util.ts -- refactor somewhere...34// Get *all* methods of an object (including from base classes!).5// See https://flaviocopes.com/how-to-list-object-methods-javascript/6// This is used by bind_methods below to bind all methods7// of an instance of an object, all the way up the8// prototype chain, just to be 100% sure!9function get_methods(obj: object): string[] {10let properties = new Set<string>();11let current_obj = obj;12do {13Object.getOwnPropertyNames(current_obj).map((item) => properties.add(item));14} while ((current_obj = Object.getPrototypeOf(current_obj)));15return [...properties.keys()].filter(16(item) => typeof obj[item] === "function"17);18}1920// Bind all or specified methods of the object. If method_names21// is not given, binds **all** methods.22// For example, in a base class constructor, you can do23// bind_methods(this);24// and every method will always be bound even for derived classes25// (assuming they call super if they overload the constructor!).26// Do this for classes that don't get created in a tight inner27// loop and for which you want 'safer' semantics.28export function bind_methods<T extends object>(29obj: T,30method_names: undefined | string[] = undefined31): T {32if (method_names === undefined) {33method_names = get_methods(obj);34method_names.splice(method_names.indexOf("constructor"), 1);35}36for (const method_name of method_names) {37obj[method_name] = obj[method_name].bind(obj);38}39return obj;40}414243