ioBroker.javascript icon indicating copy to clipboard operation
ioBroker.javascript copied to clipboard

[QUESTION] Best way to access global functions from dependencies

Open chpio opened this issue 2 years ago • 7 comments

Hello, i've started developing a collection of iobroker scripts, but it seems that it's not possible to access the global functions (like on) from a required dependency, or am i just missing something?

A pretty stupid workaround would be to just pass all the functions to an init function:

import {init, simpleBrightnessToggle} from "@chpio/iobroker";

init({on, setState, getState, /*all other functions*/});
simpleBrightnessToggle(/*...*/);

From the dep:

export interface IoBrokerJsFns {
  /*...*/
};

// exported, so that it can be accessed from my other internal modules
export let ioBrokerFns: null | IoBrokerJsFns = null;
export function init(fns: IoBrokerJsFns): void {
  ioBrokerFns = fns;
}

export function simpleBrightnessToggle(
	buttonId: string,
	brightnessId: string,
	brightnessLevels: Array<number>,
): void {
  ensureNotNull(ioBrokerFns);
  ioBrokerFns.on(/*...*/);
}

i would rather not use it, cause it's ugly and if you have multiple such deps you need to init them all, recursively, update the passed functions when new functions are added, etc... it's a mess.

Thank you.

chpio avatar Jan 10 '22 09:01 chpio

These are no "global functions" per see, these are just methodsadded to the current sandbox, so it is the same as for all other "self defined methods" vs require ...

Apollon77 avatar Jan 10 '22 09:01 Apollon77

I guess it's not possible to change the require fn in a way that it is able to import a "virtual" module, say "iobroker.javascript.api", that would return the sandboxed object with all the functions? It would also need to patch the require function of the imported module for recursion to work.

chpio avatar Jan 10 '22 09:01 chpio

because this is no library this will not really work ... maybe @AlCalzone has ideas?

Apollon77 avatar Jan 10 '22 09:01 Apollon77

The sandbox is already patching the require function, but I'm not sure if/how it is possible to change the global scope of the returned module. Maybe something with module.createRequire, but its been too long that I played with that - and it might work differently in the node:vm scope.

AlCalzone avatar Jan 10 '22 10:01 AlCalzone

The sandbox is already patching the require function, but I'm not sure if/how it is possible to change the global scope of the returned module.

i meant all requires down the require-tree, recursively. And then:

function require(mod: string) {
  // our "virtual" package
  if (mod === "iobroker.javascript.api") {
    return ioBrokerApiModule;
  }
  
  return originalRequire(mod);  
}

Would that work?

chpio avatar May 04 '22 19:05 chpio

There isn't simply a module that defines the functions. They are defined in the sandbox that acts as the context for the Node.js script VM.

https://nodejs.org/api/vm.html#scriptruninnewcontextcontextobject-options

AlCalzone avatar May 05 '22 07:05 AlCalzone

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs within the next 7 days. Please check if the issue is still relevant in the most current version of the adapter and tell us. Also check that all relevant details, logs and reproduction steps are included and update them if needed. Thank you for your contributions. Dieses Problem wurde automatisch als veraltet markiert, da es in letzter Zeit keine Aktivitäten gab. Es wird geschlossen, wenn nicht innerhalb der nächsten 7 Tage weitere Aktivitäten stattfinden. Bitte überprüft, ob das Problem auch in der aktuellsten Version des Adapters noch relevant ist, und teilt uns dies mit. Überprüft auch, ob alle relevanten Details, Logs und Reproduktionsschritte enthalten sind bzw. aktualisiert diese. Vielen Dank für Eure Unterstützung.

stale[bot] avatar May 09 '23 02:05 stale[bot]