jest-environment-node-single-context
Version:
Jest environment for Node with single context
71 lines • 3.22 kB
JavaScript
;
/*
* Copyright (C) 2020 Klaus Reimer <k@ailis.de>
* See LICENSE.md for licensing information.
*/
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
const vm_1 = require("vm");
const jest_environment_node_1 = __importDefault(require("jest-environment-node"));
const fake_timers_1 = require("@jest/fake-timers");
/** Special context which is handled specially in the hacked runInContext method below */
const singleContexts = new WeakSet();
/** Remembered original runInContext method. */
const origRunInContext = vm_1.Script.prototype.runInContext;
/**
* Ugly hack to allow Jest to just use a single Node VM context. The Jest code in question is in a large private
* method of the standard Jest runtime and it would be a lot of code-copying to create a custom runtime which
* replaces the script run code. So we hack into the `script.runInContext` method instead to redirect it to
* `script.runInThisContext` for vm contexts recorded in `singleContexts` set.
*/
vm_1.Script.prototype.runInContext = function (context, options) {
if (singleContexts.has(context)) {
return this.runInThisContext(options);
}
else {
return origRunInContext.call(this, context, options);
}
};
const timerIdToRef = (id) => ({
id,
ref() {
return this;
},
unref() {
return this;
},
});
const timerRefToId = (timer) => timer === null || timer === void 0 ? void 0 : timer.id;
class SingleContextNodeEnvironment extends jest_environment_node_1.default {
constructor(config, context) {
super(config, context);
// Use shared global environment for all tests
this.global = global;
// Recreate context using the shared global environment. This fixes the environment for ESM module stuff of Jest (which doesn't just use the context
// for `script.runInContext`) but a few type mismatches are still there unfortunately. For CJS mode this is irrelevant because calls for
// `script.runInContext` using this context are always redirected to `script.runInThisContext`. All this would not be necessary if we could just get
// the CURRENT vm context. But Node API doesn't allow that.
this.context = (0, vm_1.createContext)(global);
if (this.context != null) {
// Record the VM context of this environment so the hacked `script.runInContext` redirects the call to `script.runInThisContext` for this context.
singleContexts.add(this.context);
}
// Install fake timers again, this time with shared global environment
this.fakeTimers = new fake_timers_1.LegacyFakeTimers({
config: config.projectConfig,
global,
moduleMocker: this.moduleMocker,
timerConfig: {
idToRef: timerIdToRef,
refToId: timerRefToId
}
});
this.fakeTimersModern = new fake_timers_1.ModernFakeTimers({
config: config.projectConfig,
global
});
}
}
module.exports = SingleContextNodeEnvironment;
//# sourceMappingURL=SingleContextNodeEnvironment.js.map