diff --git a/scripts/core/engine.js b/scripts/core/engine.js index a4de2794..418c5de4 100644 --- a/scripts/core/engine.js +++ b/scripts/core/engine.js @@ -45,8 +45,6 @@ prosperon.on('SIGSEGV', function() { os.exit(1) }) -var use_cache = {} - Object.defineProperty(Function.prototype, "hashify", { value: function () { var hash = new Map() @@ -67,6 +65,8 @@ var canonical = io.realdir(RESPATH) + 'resources.js' var content = io.slurp(RESPATH) var resources = js.eval(RESPATH, `(function setup_resources(){${content}})`).call({}) +var use_cache = {} + use_cache[resources.canonical('resources.js')] = resources function print_api(obj) { @@ -277,9 +277,49 @@ switch(os.platform()) { break } +var use_cache = {} +var inProgress = {} +var loadingStack = [] + globalThis.use = function use(file) { - if (use_cache[file]) return use_cache[file] + // If we've already begun loading this file in this chain, show the cycle + if (loadingStack.includes(file)) { + // Find where in the stack this file first appeared + let cycleIndex = loadingStack.indexOf(file) + // Extract just the modules in the cycle + let cyclePath = loadingStack.slice(cycleIndex).concat(file) + + throw new Error( + `Circular dependency detected while loading "${file}".\n` + + `Module chain: ${loadingStack.join(" -> ")}\n` + + `Cycle specifically: ${cyclePath.join(" -> ")}` + ) + } + + // Already fully loaded? Return it + if (use_cache[file]) { + return use_cache[file] + } + + // If it's loading (but not on the stack), mark it as a new chain entry + // (This is optional if you just rely on loadingStack. + // But if you'd like a simple “already loading” check, keep 'inProgress'.) + if (inProgress[file]) { + throw new Error(`Circular dependency detected while loading "${file}"`) + } + inProgress[file] = true + + // Push onto loading stack for chain tracking + loadingStack.push(file) + + // Actually load the module var mod = script_fn(file) + + // Done loading, remove from the chain and mark as loaded + loadingStack.pop() + delete inProgress[file] + + // Cache and return use_cache[file] = mod.module_ret return use_cache[file] }