Function to reset module script require cache in plugins

Plugins want to flush the require cache so that they can run code that you’re actively working on.

Right now you have to clone the script before you do this, which gives you a fresh instance with no require cache.

This is a problem because lua loses hierarchical context when this happens. The game doesn’t know where this cloned module is supposed to exist. Debugging tools can’t associate the clone script with the original.

It becomes impossible to debug scripts being run by a plugin.

So I want a function that would let me wipe the cache of a module so that it can be required again.


It’s messy and will probably deoptimize luau, but there is one way you can do this.

local cache = {}
local requiring = {}
local function nocache_require( moduleScript: ModuleScript )
	local hasCache = cache[ moduleScript ]
	if ( hasCache ) then return hasCache end
	if ( requiring[ moduleScript ] ) then
		table.insert( requiring[ moduleScript ], coroutine.running() )
		return coroutine.yield()
	requiring[ moduleScript ] = {}

	local module, parseError = loadstring( moduleScript.Source )
	if ( parseError ) then error( parseError, 2 ) end

	local moduleEnvironment = setmetatable( {
		script = moduleScript,
		require = nocache_require, -- this cache system is required for this to work properly, just use resetCache when necessary
	}, {
		__index = getfenv( module )
	} )

	setfenv( module, moduleEnvironment )

	local output = module() -- let's assume that you are following the rules of module scripts
	for index, thread in requiring[ moduleScript ] do
		task.spawn( thread, output )
		requiring[ moduleScript ][ index ] = nil
	requiring[ moduleScript ] = nil
	return output

local function resetCache()
	table.clear( cache )

But yeah, it really sucks that we need a workaround for this to work. I vouch that we need a way to clear the module script cache-- even if only usable with plugins.

Edit: I just realized this is a year old. I thought it meant January 22nd instead of 2022. Oops.

1 Like

This should really be an engine feature, and work across all of Roblox.