mirror of
https://github.com/HeyPuter/puter.git
synced 2026-05-04 16:40:41 +00:00
dev(kernel): make extension variable more global-like
The extension pseudo-global was only available at the root synchronous execution context of a module loaded as an extension, which meant it wasn't available for such things as handler functions for listeners even though it looks like it should be lexically scoped. This commit writes a `const` to the top of javascript files in the runtime copy of an extension so that it works as nearly to a real global as possible. A real global isn't possible here for two reasons. First, running in the same v8 VM as Puter means we can't have distinct global objects with the same name across different extensions. Second, we can't use node:vm because we would then be unable to support ES modules, which are experimental in node:vm and also there's no equivalent to createRequire for the linker even if we wanted to require the --experimental-vm-modules flag in our package.json. This seems to be the best we can do given the state of affairs of the runtime.
This commit is contained in:
+28
-14
@@ -28,6 +28,9 @@ const { spawn } = require("node:child_process");
|
||||
|
||||
const fs = require('fs');
|
||||
const path_ = require('path');
|
||||
const { prependToJSFiles } = require("./kernel/modutil");
|
||||
|
||||
const uuid = require('uuid');
|
||||
|
||||
const { quot } = libs.string;
|
||||
|
||||
@@ -215,6 +218,14 @@ class Kernel extends AdvancedBase {
|
||||
}
|
||||
fs.mkdirSync('mod_packages');
|
||||
|
||||
// Initialize some globals that external mods depend on
|
||||
globalThis.__puter_extension_globals__ = {
|
||||
extensionObjectRegistry: {},
|
||||
useapi: this.useapi,
|
||||
};
|
||||
|
||||
// Install the mods...
|
||||
|
||||
const mod_install_root_context = Context.get();
|
||||
|
||||
const mod_installation_promises = [];
|
||||
@@ -292,12 +303,23 @@ class Kernel extends AdvancedBase {
|
||||
});
|
||||
}
|
||||
|
||||
const extension_id = uuid.v4();
|
||||
|
||||
await prependToJSFiles(mod_package_dir, [
|
||||
`const { use, def } = globalThis.__puter_extension_globals__.useapi;`,
|
||||
`const extension = globalThis.__puter_extension_globals__` +
|
||||
`.extensionObjectRegistry[${JSON.stringify(extension_id)}];`,
|
||||
].join('\n') + '\n');
|
||||
|
||||
const mod_require_dir = path_.join(process.cwd(), mod_package_dir);
|
||||
|
||||
await this.run_npm_install(mod_require_dir);
|
||||
|
||||
const mod = new ExtensionModule();
|
||||
mod.extension = new Extension();
|
||||
|
||||
globalThis.__puter_extension_globals__.extensionObjectRegistry[extension_id]
|
||||
= mod.extension;
|
||||
|
||||
const mod_context = this._create_mod_context(mod_install_root_context, {
|
||||
name: mod_dirname,
|
||||
@@ -306,20 +328,12 @@ class Kernel extends AdvancedBase {
|
||||
mod_path,
|
||||
});
|
||||
|
||||
// This is where the module gets the 'use' and 'def' globals
|
||||
await this.useapi.awithuse(async () => {
|
||||
// This is where the module gets the 'extension' global
|
||||
await useapi.aglobalwith({
|
||||
extension: mod.extension,
|
||||
}, async () => {
|
||||
const maybe_promise = require(mod_require_dir);
|
||||
if ( maybe_promise && maybe_promise instanceof Promise ) {
|
||||
await maybe_promise;
|
||||
}
|
||||
// This is where the 'install' event gets triggered
|
||||
await mod.install(mod_context);
|
||||
});
|
||||
});
|
||||
const maybe_promise = require(mod_require_dir);
|
||||
if ( maybe_promise && maybe_promise instanceof Promise ) {
|
||||
await maybe_promise;
|
||||
}
|
||||
// This is where the 'install' event gets triggered
|
||||
await mod.install(mod_context);
|
||||
};
|
||||
|
||||
_create_mod_context (parent, options) {
|
||||
|
||||
Reference in New Issue
Block a user