function memoize_synchronous_function(func, max_entries = 50000) {
	const cache = {};
	const keys = [];
	const memoized_func = (...args) => {
		if (args.some((arg) => arg instanceof CanvasPattern)) {
			return func.apply(null, args);
		}
		const key = JSON.stringify(args);
		if (cache[key]) {
			return cache[key];
		} else {
			const val = func.apply(null, args);
			cache[key] = val;
			keys.push(key);
			if (keys.length > max_entries) {
				const oldest_key = keys.shift();
				delete cache[oldest_key];
			}
			return val;
		}
	};
	memoized_func.clear_memo_cache = () => {
		for (const key of keys) {
			delete cache[key];
		}
		keys.length = 0;
	};
	return memoized_func;
}
@template {any[]} A - The type of the arguments to the function
@template {any} R - The return type of the function
@param {(...args: A) => R} func - The function to memoize.
@param {number} [max_entries=50000] - The maximum number of entries to store in the cache.
@returns {((...args: A) => R) & { clear_memo_cache: () => void }} - The memoized function, with an extra `clear_memo_cache` method.