Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: expose jiti.evalModule #146

Merged
merged 7 commits into from
Jul 4, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ test/fixtures/error-*
renovate.json
package.json
tsconfig.json
coverage
44 changes: 36 additions & 8 deletions src/jiti.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,21 @@ const defaults: JITIOptions = {
};

type Require = typeof require;
type Module = typeof module;

type ModuleCache = Record<string, Module>;

export type EvalModuleOptions = Partial<{
id: string;
filename: string;
ext: string;
cache: ModuleCache;
}>;

export interface JITI extends Require {
transform: (opts: TransformOptions) => string;
register: () => () => void;
evalModule: (source: string, options?: EvalModuleOptions) => unknown;
}

const JS_EXT_RE = /\.(c|m)?j(sx?)$/;
Expand All @@ -61,8 +73,8 @@ const TS_EXT_RE = /\.(c|m)?t(sx?)$/;
export default function createJITI(
_filename: string,
opts: JITIOptions = {},
parentModule?: typeof module,
parentCache?: Record<string, typeof module>
parentModule?: Module,
parentCache?: ModuleCache
): JITI {
opts = { ...defaults, ...opts };

Expand Down Expand Up @@ -263,7 +275,7 @@ export default function createJITI(
}

function jiti(id: string) {
const requiredModules = parentCache || {};
const cache = parentCache || {};

// Check for node: and file: protocol
if (id.startsWith("node:")) {
Expand Down Expand Up @@ -302,15 +314,30 @@ export default function createJITI(
}

// Check for CJS cache
if (requiredModules[filename]) {
return _interopDefault(requiredModules[filename]?.exports);
if (cache[filename]) {
return _interopDefault(cache[filename]?.exports);
}
if (opts.requireCache && nativeRequire.cache[filename]) {
return _interopDefault(nativeRequire.cache[filename]?.exports);
}

// Read source
let source = readFileSync(filename, "utf8");
const source = readFileSync(filename, "utf8");

// Evaluate module
return evalModule(source, { id, filename, ext, cache });
}

function evalModule(source: string, evalOptions: EvalModuleOptions = {}) {
// Resolve options
const id =
evalOptions.id ||
(evalOptions.filename
? basename(evalOptions.filename)
: `_jitiEval.${evalOptions.ext || ".js"}`);
const filename = evalOptions.filename || _resolve(id);
const ext = evalOptions.ext || extname(filename);
const cache = (opts.cache || parentCache || {}) as ModuleCache;
Comment on lines +339 to +340

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because

const x: string = 'x';

(x || {}) as Record<string, any>

compiles, it would be much safer to type it like this:

const cache = (opts.cache as ModuleCache || parentCache || {} as ModuleCache);

or even better:

const cache: ModuleCache = opts.cache || parentCache || {};

This way it would error that opts.cache does not match ModuleCache.

Copy link
Member Author

@pi0 pi0 Jul 4, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you mind to open a refactor PR? πŸ‘πŸΌ


// Transpile
const isTypescript = ext === ".ts" || ext === ".mts" || ext === ".cts";
Expand Down Expand Up @@ -359,7 +386,7 @@ export default function createJITI(
}
}

mod.require = createJITI(filename, opts, mod, requiredModules);
mod.require = createJITI(filename, opts, mod, cache);

// @ts-ignore
mod.path = dirname(filename);
Expand All @@ -368,7 +395,7 @@ export default function createJITI(
mod.paths = Module._nodeModulePaths(mod.path);

// Set CJS cache before eval
requiredModules[filename] = mod;
cache[filename] = mod;
if (opts.requireCache) {
nativeRequire.cache[filename] = mod;
}
Expand Down Expand Up @@ -440,6 +467,7 @@ export default function createJITI(
jiti.main = nativeRequire.main;
jiti.transform = transform;
jiti.register = register;
jiti.evalModule = evalModule;

return jiti;
}
2 changes: 2 additions & 0 deletions test/__snapshots__/fixtures.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ TypeError: The \\"listener\\" argument must be of type function. Received undefi
at _addListener (events)
at process.addListener (events)
at <cwd>/index.ts
at evalModule (<root>/dist/jiti)
at jiti (<root>/dist/jiti)
at Object.<anonymous> (<root>/bin/jiti)
at Module._compile (internal/modules/cjs/loader)
Expand All @@ -65,6 +66,7 @@ exports[`fixtures > esm > stdout 1`] = `
'at getStack (<cwd>/test)',
'at test (<cwd>/test)',
'at <cwd>/index.js',
'at evalModule (<root>/dist/jiti)',
'at jiti (<root>/dist/jiti)',
'at Object.<anonymous> (<root>/bin/jiti)',
'at Module._compile (internal/modules/cjs/loader)',
Expand Down