Load the given script at the given path, recursively loading any subscripts as well.
(path: string | Link, context: Record<string, unknown>)
| 61 | |
| 62 | /** Load the given script at the given path, recursively loading any subscripts as well. */ |
| 63 | public async load(path: string | Link, context: Record<string, unknown>): Promise<Result<unknown, string>> { |
| 64 | // Always check the cache first. |
| 65 | const key = this.pathkey(path); |
| 66 | const currentScript = this.scripts.get(key); |
| 67 | if (currentScript) { |
| 68 | if (currentScript.type === "loaded") return Result.success(currentScript.object); |
| 69 | |
| 70 | // TODO: If we try to load an already-loading script, we are almost certainly doing something |
| 71 | // weird. Either the caller is not `await`-ing the load and loading multiple times, OR |
| 72 | // we are in a `require()` loop. Either way, we'll error out for now since we can't handle |
| 73 | // either case currently. |
| 74 | return Result.failure( |
| 75 | `Failed to import script "${path.toString()}", as it is in the middle of being loaded. Do you have |
| 76 | a circular dependency in your require() calls? The currently loaded or loading scripts are: |
| 77 | ${Array.from(this.scripts.values()) |
| 78 | .map((sc) => "\t" + sc.path) |
| 79 | .join("\n")}` |
| 80 | ); |
| 81 | } |
| 82 | |
| 83 | // Cache has missed, so add ourselves to the cache and try and load it directly. |
| 84 | const deferral = deferred<Result<unknown, string>>(); |
| 85 | this.scripts.set(key, { type: "loading", promise: deferral, path: key }); |
| 86 | |
| 87 | const result = await this.loadUncached(path, context); |
| 88 | deferral.resolve(result); |
| 89 | |
| 90 | if (result.successful) { |
| 91 | this.scripts.set(key, { type: "loaded", path: key, object: result.value }); |
| 92 | } else { |
| 93 | this.scripts.delete(key); |
| 94 | } |
| 95 | |
| 96 | return result; |
| 97 | } |
| 98 | |
| 99 | /** Load a script, directly bypassing the cache. */ |
| 100 | private async loadUncached( |