Table of contents
Prelude are the "invisible lines of code" that runs before the first line of a script file to create variables. Here's an example
// index.js
/*
* You might imagine some invisible lines of code before the first line like
* function require(...) { ... }
* function addEventListener(...) { ... }
*/
let circle = require(...); // but this is the first line of the script file
addEventListener(...); // where did these functions come from?
JSCore supports per-file preludes.
Using a prelude
Each Prelude object represents a block of code creating one or more variables. Suppose we already have a few of them pre1, pre2 and pre3, they can be applied to a script file during import with
let circle = module.import("circle.js", [pre1, pre2, pre3]);
Then circle.js can use the variables defined by the preludes. The preludes are evaluated in order - if multiple preludes define the same variables, the last prelude defining the variable will overwrite the previous ones.
Warning
All imports to the same file must use the same preludes in the that order, otherwise there will be an error.
Creating a prelude
Use module.createPrelude((targetScope, targetModule) => void) to create a Prelude object, where
- targetScope is the global scope of the script file the prelude is applied to, setting
targetScope.myVar = 3declaresmyVarin the global scope of that file - targetModule is the module object of the script file the prelude is applied to
Here's an example
const requirePrelude = module.createPrelude((targetScope, targetModule) {
targetScope.require = function(path) {
// puts itself as prelude for any file imported with require(...)
return targetModule.import(path, [requirePrelude]);
}
});
Avoiding prelude import cycles
Suppose preludeA is created in module A with module.createPrelude, if module B is imported with preludeA, then JSCore will consider B to have "imported" A.
flowchart LR
A[module A]
B[module B]
B -->A
So consider the code below
// A.js
let preludeA = module.createPrelude(...);
let B = module.import('./B.js', [preludeA]);
Then A imports B with module.import, but B also "imports" A as it is imported with preludeA! So there is an import cycle.
flowchart LR
A[module A]
B[module B]
B -->A
A --> B
The solution is to define the prelude in another module.
// C.js
let preludeC = module.createPrelude(...);
module.exports = preludeC;
// A.js
let preludeC = module.import("./C.js", []);
let B = module.import("./B.js", [preludeC]);
which does not create any cycles.
flowchart TD
A[module A]
B[module B]
C[module C]
B -->C
A --> C
A --> B
This should remind you of how you need a third variable to swap two variables.
// a = 1, b = 2 let temp = b; b = a; a = temp;