citizenfx / fivem

The source code for the Cfx.re modification frameworks, such as FiveM, RedM and LibertyM, as well as FXServer.
https://cfx.re/
3.48k stars 2.06k forks source link

[V8][NODE.JS] Dynamic imports don't work on FiveM server. #2659

Closed DigitalWolf98 closed 1 month ago

DigitalWolf98 commented 1 month ago

What happened?

I wanted to rewrite the localization system from Lua language to JS. In this system I should have many files with a prularization function for each locale. In the EcmaScript standard, it is possible to dynamically import the necessary modules. When attempting to use the entry const _module = import('module.js'); an error TypeError: Invalid host defined options. is thrown.

On one of the forums, I saw an entry where a user mentioned the need to disable v8-compile-cache. Here is his verbatim quote:

If you’re using Node.js and get a “invalid host defined options” error, it means you’re trying to use v8-compile-cache with ESM modules. That doesn’t work. Sadly the only solution is to remove v8-compile-cache.

I don't know if this is the case and how to do it since I have no experience with it, please help me fix it.

Expected result

Dynamic import and module execution (ES).

Reproduction steps

  1. Create an empty resource.
  2. Add a package.json file with type=“module” to support imports.
  3. Add code to dynamically import arbitrary modules in server/main.js:
    (async () => {
    try {
        for (let i = 0; i <= 10; i++) {
            const _module = await import(`./module_${i}`);
            _module.default();
        }
    } catch(err) {
        console.log('ERROR:', err?.message);
    }
    })();
  4. Add arbitrary code to the server/module_*.js:
    "use strict";
    const fn1 = () => console.log('FN_1');
    export default fn1;

Importancy

There's a workaround

Area(s)

FiveM, FXServer, ScRT: JS

Specific version(s)

FiveM, tx: v7.2.2, fx: b8981, Windows/master

Additional information

There is a workaround using the native LoadResourceFile() function and using eval(), but as we all know the eval function is not recommended for a number of reasons.

Code example server/main.js:

(async () => {
     for (let i = 0; i <= 10; i++) {
          const _module = LoadResourceFile(GetCurrentResourceName(), `server/module_${i}.js`);
          if (!_module) break;
          eval(_module);
     }
})();
prikolium-cfx commented 1 month ago

Hi. Please provide minimal resource to reproduce the issue. And did you check is static import works for you?

DigitalWolf98 commented 1 month ago

Hello. Yes, I checked if the static imports works, unfortunately it also gives an error: SyntaxError: Cannot use import statement outside a module.

Here's the basic resource I used: https://mega.nz/file/aQITmQjZ#9gB0cPrdFOW3oBsh91rcF_FLZ9NFZLTaAGTtGwSkrb0

DigitalWolf98 commented 1 month ago

Can anyone answer or should I close this problem by marking it as unsolved ?!

prikolium-cfx commented 1 month ago

Can anyone answer or should I close this problem by marking it as unsolved ?!

Current JS runtimes implementation doesn't support ESM on server and client.