add cycle detection with use
This commit is contained in:
@@ -45,8 +45,6 @@ prosperon.on('SIGSEGV', function() {
|
|||||||
os.exit(1)
|
os.exit(1)
|
||||||
})
|
})
|
||||||
|
|
||||||
var use_cache = {}
|
|
||||||
|
|
||||||
Object.defineProperty(Function.prototype, "hashify", {
|
Object.defineProperty(Function.prototype, "hashify", {
|
||||||
value: function () {
|
value: function () {
|
||||||
var hash = new Map()
|
var hash = new Map()
|
||||||
@@ -67,6 +65,8 @@ var canonical = io.realdir(RESPATH) + 'resources.js'
|
|||||||
var content = io.slurp(RESPATH)
|
var content = io.slurp(RESPATH)
|
||||||
var resources = js.eval(RESPATH, `(function setup_resources(){${content}})`).call({})
|
var resources = js.eval(RESPATH, `(function setup_resources(){${content}})`).call({})
|
||||||
|
|
||||||
|
var use_cache = {}
|
||||||
|
|
||||||
use_cache[resources.canonical('resources.js')] = resources
|
use_cache[resources.canonical('resources.js')] = resources
|
||||||
|
|
||||||
function print_api(obj) {
|
function print_api(obj) {
|
||||||
@@ -277,9 +277,49 @@ switch(os.platform()) {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var use_cache = {}
|
||||||
|
var inProgress = {}
|
||||||
|
var loadingStack = []
|
||||||
|
|
||||||
globalThis.use = function use(file) {
|
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)
|
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
|
use_cache[file] = mod.module_ret
|
||||||
return use_cache[file]
|
return use_cache[file]
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user