68 lines
2.0 KiB
TypeScript
68 lines
2.0 KiB
TypeScript
import type { Hook, Manifest } from "$lib/plugos/types.ts";
|
|
import type { System } from "$lib/plugos/system.ts";
|
|
import type { SyscallHookT } from "$lib/manifest.ts";
|
|
import type { SysCallMapping } from "$lib/plugos/system.ts";
|
|
|
|
export class SyscallHook implements Hook<SyscallHookT> {
|
|
apply(system: System<SyscallHookT>): void {
|
|
this.registerSyscalls(system);
|
|
system.on({
|
|
plugLoaded: () => {
|
|
this.registerSyscalls(system);
|
|
},
|
|
});
|
|
}
|
|
|
|
registerSyscalls(system: System<SyscallHookT>) {
|
|
// Register syscalls from all loaded plugs
|
|
for (const plug of system.loadedPlugs.values()) {
|
|
const syscalls: SysCallMapping = {};
|
|
|
|
for (
|
|
const [name, functionDef] of Object.entries(plug.manifest!.functions)
|
|
) {
|
|
if (!functionDef.syscall) {
|
|
continue;
|
|
}
|
|
|
|
const syscallName = functionDef.syscall;
|
|
|
|
// Add the syscall to our mapping
|
|
syscalls[syscallName] = (ctx, ...args) => {
|
|
// Delegate to the system to invoke the function
|
|
return system.syscall(ctx, "system.invokeFunction", [
|
|
`${plug.manifest!.name}.${name}`,
|
|
...args,
|
|
]);
|
|
};
|
|
|
|
// Register the syscalls with no required permissions
|
|
system.registerSyscalls([], syscalls);
|
|
}
|
|
}
|
|
}
|
|
|
|
validateManifest(manifest: Manifest<SyscallHookT>): string[] {
|
|
const errors: string[] = [];
|
|
for (const [name, functionDef] of Object.entries(manifest.functions)) {
|
|
if (!functionDef.syscall) {
|
|
continue;
|
|
}
|
|
|
|
// Validate syscall name is provided
|
|
if (!functionDef.syscall) {
|
|
errors.push(`Function ${name} has a syscall but no name`);
|
|
continue;
|
|
}
|
|
|
|
// Validate syscall name format (should be namespaced)
|
|
if (!functionDef.syscall.includes(".")) {
|
|
errors.push(
|
|
`Function ${name} has invalid syscall name "${functionDef.syscall}" - must be in format "namespace.name"`,
|
|
);
|
|
}
|
|
}
|
|
return errors;
|
|
}
|
|
}
|