Hello All,
Anyone tried using the newer ES Modules syntax for nodejs code (using export / import) as opposed to Common JavaScript (using module.exports / require)?
For what it's worth, a simple test results in
***Error***
(node:4531) Warning: To load an ES module, set "type": "module" in the package.json or use the .mjs extension.Perhaps it would work with a new prototype question, nodejs_esm say, with main_module.js named main_module.mjs instead?
__tester__.nodejs:2
import done from './cli.mjs');
^^^^^^ SyntaxError: Cannot use import statement outside a module
at wrapSafe (internal/modules/cjs/loader.js:931:16)
at Module._compile (internal/modules/cjs/loader.js:979:27)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:1035:10)
at Module.load (internal/modules/cjs/loader.js:879:32)
at Function.Module._load (internal/modules/cjs/loader.js:724:14)
at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:60:12)
at internal/main/run_main_module.js:17:47
Just trying to keep up...
More details on reproducing the issue (I do realize that nodejs is a fringe language for CR, but ESM style is getting traction)...
Question type: nodejs
Answer and Answer box preload:
import something from './something_esm.js';
Support files:
something_esm.js containing:
export default () => console.log('Running something');
package.json containing:
{
"type" : "module"
}
Then Check produces Got with:
***Error***
node:internal/process/esm_loader:74Needless to say that it works as expected running on the command line:
internalBinding('errors').triggerUncaughtException(
^ TypeError [ERR_UNKNOWN_FILE_EXTENSION]: Unknown file extension ".nodejs" for __tester__.nodejs
at new NodeError (node:internal/errors:278:15)
at Loader.defaultGetFormat [as _getFormat] (node:internal/modules/esm/get_format:71:15)
at Loader.getFormat (node:internal/modules/esm/loader:102:42)
at Loader.getModuleJob (node:internal/modules/esm/loader:231:31)
at async Loader.import (node:internal/modules/esm/loader:165:17)
at async Object.loadESM (node:internal/process/esm_loader:68:5) {
code: 'ERR_UNKNOWN_FILE_EXTENSION'
}
node esm_test.js
Running something
where esm_test.js contains the Answer code.
By default CodeRunner uses the filename __tester__.<language>
but in the case where the language is nodejs (which is the name Jobe gives its JavaScript language) the name __tester__.nodejs
seems to break when in ESM style.
The fix is to set the (undocumented) sandbox parameter "sourcefilename" to use an extension of .js
rather than .nodejs
. If you have access to the nodejs prototype, edit it, open the Advanced Customisation panel, and set the Parameters field
in the Sandbox section to
{"sourcefilename": "__tester__.js"}
I'll make this change to the prototype in the next release of CodeRunner.
If you don't have access to the prototype, you'll either have to define your own or customise each question individually.
Thanks for reporting the problem.
Thanks for the speedy answer!
I tried the cheapest user-level customization i could think of by setting
Template params to
{"sourcefilename": "__tester__.js"}
Running with Template debugging i see that
{{ QUESTION.parameters.sourcefilename }}
is set to
__tester__.js
Looks like that was too cheap - it still crashes with
TypeError [ERR_UNKNOWN_FILE_EXTENSION]: Unknown file extension ".nodejs" for __tester__.nodejs
at new NodeError (node:internal/errors:278:15)
So i guess i'll be asking the admins to patch the prototype.
You can do it as an ordinary user on a per-question basis as follows:
- Click the Customise Checkbox (at the very top, just under the Question type selector).
- Open the Advanced Customisation section.
- Set the Sandbox Parameters field as in the figure below.
However, customising individual questions isn't recommended as a general purpose fix, because future updates to the prototype will then not affect the customised questions.
Getting an admin to patch the nodejs prototype as above is probably the easiest solution. Or make yourself a new question prototype called just 'js' rather than 'nodejs'? It's not too hard - see https://github.com/trampgeek/moodle-qtype_coderunner#user-defined-question-types. But you will then have to manage the new prototype in the future.
Yes of course, Sandbox and not Template parameters :-) . Works like a charm. The admins will take a couple of days to make the change and i need just a couple of questions asap so this temporary quick fix is perfect.
Thanks a bunch for bailing me out again!
Cheers,
PS.