This doesn't affect globals (describe, it, expect, etc). Those belong to the user and Jasmine doesn't depend on them.
68 lines
1.8 KiB
JavaScript
68 lines
1.8 KiB
JavaScript
globalThis.isNonMonkeyPatchableClass = function(ctor, makeInstance) {
|
|
describe('Monkey patching prevention', function() {
|
|
it(`prevents overwriting ${ctor.name}.prototype`, function() {
|
|
const existing = ctor.prototype;
|
|
|
|
try {
|
|
ctor.prototype = {};
|
|
expect(ctor.prototype).toBe(existing);
|
|
} finally {
|
|
// This will be a no-op if the test passed, but will prevent state
|
|
// leakage if it failed.
|
|
ctor.prototype = existing;
|
|
}
|
|
});
|
|
|
|
it("prevents overwriting an instance's prototype", function() {
|
|
const instance = makeInstance();
|
|
let thrown;
|
|
|
|
// The message varies from browser to browser, so we can't rely on it
|
|
try {
|
|
instance.__proto__ = {};
|
|
} catch (e) {
|
|
thrown = e;
|
|
}
|
|
|
|
expect(thrown).toBeInstanceOf(TypeError);
|
|
});
|
|
|
|
it('prevents overwriting prototype properties', function() {
|
|
let any = false;
|
|
|
|
for (const k of Object.getOwnPropertyNames(ctor.prototype)) {
|
|
any = true;
|
|
const existingValue = ctor.prototype[k];
|
|
|
|
try {
|
|
ctor.prototype[k] = {};
|
|
expect(ctor.prototype[k])
|
|
.withContext(k)
|
|
.toBe(existingValue);
|
|
} finally {
|
|
// This will be a no-op if the test passed, but will prevent state
|
|
// leakage if it failed.
|
|
ctor.prototype[k] = existingValue;
|
|
}
|
|
}
|
|
|
|
expect(any).toBe(true);
|
|
});
|
|
|
|
it('prevents overriding prototype properties', function() {
|
|
const instance = makeInstance();
|
|
let any = false;
|
|
|
|
for (const k of Object.getOwnPropertyNames(ctor.prototype)) {
|
|
any = true;
|
|
instance[k] = {};
|
|
expect(instance[k])
|
|
.withContext(k)
|
|
.toBe(ctor.prototype[k]);
|
|
}
|
|
|
|
expect(any).toBe(true);
|
|
});
|
|
});
|
|
};
|