Prevent monkey patching
This doesn't affect globals (describe, it, expect, etc). Those belong to the user and Jasmine doesn't depend on them.
This commit is contained in:
@@ -50,10 +50,16 @@ const getJasmineHtmlRequireObj = (function() {
|
|||||||
private$.FailuresView = htmlRequire.FailuresView(j$, private$);
|
private$.FailuresView = htmlRequire.FailuresView(j$, private$);
|
||||||
private$.PerformanceView = htmlRequire.PerformanceView(j$, private$);
|
private$.PerformanceView = htmlRequire.PerformanceView(j$, private$);
|
||||||
private$.TabBar = htmlRequire.TabBar(j$, private$);
|
private$.TabBar = htmlRequire.TabBar(j$, private$);
|
||||||
j$.HtmlReporterV2Urls = htmlRequire.HtmlReporterV2Urls(j$, private$);
|
|
||||||
j$.HtmlReporterV2 = htmlRequire.HtmlReporterV2(j$, private$);
|
|
||||||
j$.QueryString = htmlRequire.QueryString();
|
|
||||||
private$.HtmlSpecFilterV2 = htmlRequire.HtmlSpecFilterV2();
|
private$.HtmlSpecFilterV2 = htmlRequire.HtmlSpecFilterV2();
|
||||||
|
|
||||||
|
for (const k of ['HtmlReporterV2Urls', 'HtmlReporterV2', 'QueryString']) {
|
||||||
|
Object.defineProperty(j$, k, {
|
||||||
|
enumerable: true,
|
||||||
|
configurable: false,
|
||||||
|
writable: false,
|
||||||
|
value: htmlRequire[k](j$, private$)
|
||||||
|
});
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return getJasmineHtmlRequire;
|
return getJasmineHtmlRequire;
|
||||||
@@ -101,6 +107,7 @@ getJasmineHtmlRequireObj().QueryString = function() {
|
|||||||
*/
|
*/
|
||||||
constructor(options) {
|
constructor(options) {
|
||||||
this.#getWindowLocation = options.getWindowLocation;
|
this.#getWindowLocation = options.getWindowLocation;
|
||||||
|
Object.freeze(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -168,6 +175,7 @@ getJasmineHtmlRequireObj().QueryString = function() {
|
|||||||
return '?' + qStrPairs.join('&');
|
return '?' + qStrPairs.join('&');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Object.freeze(QueryString.prototype);
|
||||||
return QueryString;
|
return QueryString;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -772,6 +780,8 @@ getJasmineHtmlRequireObj().HtmlReporterV2 = function(j$, private$) {
|
|||||||
);
|
);
|
||||||
this.#container.appendChild(this.#htmlReporterMain);
|
this.#container.appendChild(this.#htmlReporterMain);
|
||||||
this.#failures.show();
|
this.#failures.show();
|
||||||
|
|
||||||
|
Object.freeze(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
jasmineStarted(options) {
|
jasmineStarted(options) {
|
||||||
@@ -949,6 +959,7 @@ getJasmineHtmlRequireObj().HtmlReporterV2 = function(j$, private$) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Object.freeze(HtmlReporterV2.prototype);
|
||||||
return HtmlReporterV2;
|
return HtmlReporterV2;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -972,6 +983,8 @@ getJasmineHtmlRequireObj().HtmlReporterV2Urls = function(j$, private$) {
|
|||||||
return window.location;
|
return window.location;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Object.freeze(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1022,6 +1035,7 @@ getJasmineHtmlRequireObj().HtmlReporterV2Urls = function(j$, private$) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Object.freeze(HtmlReporterV2Urls.prototype);
|
||||||
return HtmlReporterV2Urls;
|
return HtmlReporterV2Urls;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -141,6 +141,28 @@ const getJasmineRequireObj = (function() {
|
|||||||
|
|
||||||
private$.loadedAsBrowserEsm = loadedAsBrowserEsm;
|
private$.loadedAsBrowserEsm = loadedAsBrowserEsm;
|
||||||
|
|
||||||
|
// Prevent monkey patching of existing properties but allow adding new ones.
|
||||||
|
// jasmine-html.js needs to be able to add to the jasmine namespace.
|
||||||
|
// jasmine-ajax also installs itself this way.
|
||||||
|
const writeable = [
|
||||||
|
'DEFAULT_TIMEOUT_INTERVAL',
|
||||||
|
'MAX_PRETTY_PRINT_ARRAY_LENGTH',
|
||||||
|
'MAX_PRETTY_PRINT_CHARS',
|
||||||
|
'MAX_PRETTY_PRINT_DEPTH'
|
||||||
|
];
|
||||||
|
const descriptors = Object.getOwnPropertyDescriptors(j$);
|
||||||
|
|
||||||
|
for (const [k, d] of Object.entries(descriptors)) {
|
||||||
|
if (!writeable.includes(k)) {
|
||||||
|
Object.defineProperty(j$, k, {
|
||||||
|
value: d.value,
|
||||||
|
enumerable: d.enumerable,
|
||||||
|
configurable: false,
|
||||||
|
writable: false
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return { jasmine: j$, private: private$ };
|
return { jasmine: j$, private: private$ };
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -241,6 +263,7 @@ getJasmineRequireObj().base = function(j$, private$, jasmineGlobal) {
|
|||||||
*/
|
*/
|
||||||
let DEFAULT_TIMEOUT_INTERVAL = 5000;
|
let DEFAULT_TIMEOUT_INTERVAL = 5000;
|
||||||
Object.defineProperty(j$, 'DEFAULT_TIMEOUT_INTERVAL', {
|
Object.defineProperty(j$, 'DEFAULT_TIMEOUT_INTERVAL', {
|
||||||
|
enumerable: true,
|
||||||
get: function() {
|
get: function() {
|
||||||
return DEFAULT_TIMEOUT_INTERVAL;
|
return DEFAULT_TIMEOUT_INTERVAL;
|
||||||
},
|
},
|
||||||
@@ -2077,6 +2100,8 @@ getJasmineRequireObj().Env = function(j$, private$) {
|
|||||||
this.cleanup_ = function() {
|
this.cleanup_ = function() {
|
||||||
uninstallGlobalErrors();
|
uninstallGlobalErrors();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Object.freeze(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
function indirectCallerFilename(depth) {
|
function indirectCallerFilename(depth) {
|
||||||
@@ -2087,6 +2112,8 @@ getJasmineRequireObj().Env = function(j$, private$) {
|
|||||||
return frames[depth] && frames[depth].file;
|
return frames[depth] && frames[depth].file;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Object.freeze(Env);
|
||||||
|
Object.freeze(Env.prototype);
|
||||||
return Env;
|
return Env;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -3009,6 +3036,8 @@ callbacks to execute _before_ running the next one.
|
|||||||
setInterval[IsMockClockTimingFn] = true;
|
setInterval[IsMockClockTimingFn] = true;
|
||||||
clearInterval[IsMockClockTimingFn] = true;
|
clearInterval[IsMockClockTimingFn] = true;
|
||||||
|
|
||||||
|
Object.freeze(this);
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
|
|
||||||
// Advances the Clock's time until the mode changes.
|
// Advances the Clock's time until the mode changes.
|
||||||
@@ -3162,6 +3191,8 @@ callbacks to execute _before_ running the next one.
|
|||||||
};
|
};
|
||||||
|
|
||||||
Clock.IsMockClockTimingFn = IsMockClockTimingFn;
|
Clock.IsMockClockTimingFn = IsMockClockTimingFn;
|
||||||
|
Object.freeze(Clock);
|
||||||
|
Object.freeze(Clock.prototype);
|
||||||
return Clock;
|
return Clock;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -8038,9 +8069,12 @@ getJasmineRequireObj().ParallelReportDispatcher = function(j$, private$) {
|
|||||||
for (const eventName of private$.reporterEvents) {
|
for (const eventName of private$.reporterEvents) {
|
||||||
this[eventName] = dispatcher[eventName].bind(dispatcher);
|
this[eventName] = dispatcher[eventName].bind(dispatcher);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Object.freeze(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Object.freeze(ParallelReportDispatcher.prototype);
|
||||||
return ParallelReportDispatcher;
|
return ParallelReportDispatcher;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -11698,8 +11732,12 @@ getJasmineRequireObj().Timer = function() {
|
|||||||
this.elapsed = function() {
|
this.elapsed = function() {
|
||||||
return now() - startTime;
|
return now() - startTime;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Object.freeze(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Object.freeze(Timer);
|
||||||
|
Object.freeze(Timer.prototype);
|
||||||
return Timer;
|
return Timer;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1247,4 +1247,8 @@ describe('Clock (acceptance)', function() {
|
|||||||
|
|
||||||
clock.tick(400);
|
clock.tick(400);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
isNonMonkeyPatchableClass(privateUnderTest.Clock, function() {
|
||||||
|
return new privateUnderTest.Clock({}, function() {}, {});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -874,4 +874,8 @@ describe('Env', function() {
|
|||||||
}).toThrowError('Jasmine cannot be configured via Env in parallel mode');
|
}).toThrowError('Jasmine cannot be configured via Env in parallel mode');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
isNonMonkeyPatchableClass(privateUnderTest.Env, function() {
|
||||||
|
return new privateUnderTest.Env();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -160,6 +160,13 @@ describe('ParallelReportDispatcher', function() {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
isNonMonkeyPatchableClass(
|
||||||
|
jasmineUnderTest.ParallelReportDispatcher,
|
||||||
|
function() {
|
||||||
|
return new jasmineUnderTest.ParallelReportDispatcher();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
function mockGlobalErrors() {
|
function mockGlobalErrors() {
|
||||||
const globalErrors = jasmine.createSpyObj('globalErrors', [
|
const globalErrors = jasmine.createSpyObj('globalErrors', [
|
||||||
'install',
|
'install',
|
||||||
|
|||||||
@@ -30,4 +30,8 @@ describe('Timer', function() {
|
|||||||
expect(timer.elapsed()).toEqual(jasmine.any(Number));
|
expect(timer.elapsed()).toEqual(jasmine.any(Number));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
isNonMonkeyPatchableClass(jasmineUnderTest.Timer, function() {
|
||||||
|
return new jasmineUnderTest.Timer();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -13,13 +13,61 @@ describe('The jasmine namespace', function() {
|
|||||||
expect(setDifference(actualKeys, expectedKeys())).toEqual(new Set());
|
expect(setDifference(actualKeys, expectedKeys())).toEqual(new Set());
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('Preventing monkey patching', function() {
|
||||||
|
const mutable = mutableKeys();
|
||||||
|
|
||||||
|
for (const key of expectedKeys()) {
|
||||||
|
if (mutable.includes(key)) {
|
||||||
|
it(`allows overwriting of jasmine.${key}`, function() {
|
||||||
|
const existingVal = jasmineUnderTest[key];
|
||||||
|
|
||||||
|
try {
|
||||||
|
jasmineUnderTest[key] = 'new value';
|
||||||
|
expect(jasmineUnderTest[key]).toEqual('new value');
|
||||||
|
} finally {
|
||||||
|
jasmineUnderTest[key] = existingVal;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
it(`prevents overwriting of jasmine.${key}`, function() {
|
||||||
|
const existingVal = jasmineUnderTest[key];
|
||||||
|
|
||||||
|
try {
|
||||||
|
jasmineUnderTest[key] = 'monkey patch';
|
||||||
|
expect(jasmineUnderTest[key]).toBe(existingVal);
|
||||||
|
} finally {
|
||||||
|
// This will be a no-op if the test passed, but will prevent state
|
||||||
|
// leakage if it failed.
|
||||||
|
jasmineUnderTest[key] = existingVal;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
it('allows additions', function() {
|
||||||
|
try {
|
||||||
|
jasmineUnderTest.Ajax = 'it worked';
|
||||||
|
expect(jasmineUnderTest.Ajax).toEqual('it worked');
|
||||||
|
} finally {
|
||||||
|
delete jasmineUnderTest.Ajax;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
function mutableKeys() {
|
||||||
|
return [
|
||||||
|
'MAX_PRETTY_PRINT_ARRAY_LENGTH',
|
||||||
|
'MAX_PRETTY_PRINT_CHARS',
|
||||||
|
'MAX_PRETTY_PRINT_DEPTH',
|
||||||
|
'DEFAULT_TIMEOUT_INTERVAL'
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
function expectedKeys() {
|
function expectedKeys() {
|
||||||
// Does not include properties added by requireInterface(), since that isn't
|
// Does not include properties added by requireInterface(), since that isn't
|
||||||
// called by defineJasmineUnderTest.js/nodeDefineJasmineUnderTest.js.
|
// called by defineJasmineUnderTest.js/nodeDefineJasmineUnderTest.js.
|
||||||
const result = new Set([
|
const result = new Set([
|
||||||
'MAX_PRETTY_PRINT_ARRAY_LENGTH',
|
...mutableKeys(),
|
||||||
'MAX_PRETTY_PRINT_CHARS',
|
|
||||||
'MAX_PRETTY_PRINT_DEPTH',
|
|
||||||
'debugLog',
|
'debugLog',
|
||||||
'getEnv',
|
'getEnv',
|
||||||
'isSpy',
|
'isSpy',
|
||||||
|
|||||||
@@ -0,0 +1,67 @@
|
|||||||
|
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);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
@@ -1396,4 +1396,6 @@ describe('HtmlReporterV2', function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
isNonMonkeyPatchableClass(jasmineUnderTest.HtmlReporterV2, setup);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -63,4 +63,8 @@ describe('HtmlReporterV2Urls', function() {
|
|||||||
return qs;
|
return qs;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
isNonMonkeyPatchableClass(jasmineUnderTest.HtmlReporterV2Urls, function() {
|
||||||
|
return new jasmineUnderTest.HtmlReporterV2Urls({});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -77,4 +77,12 @@ describe('QueryString', function() {
|
|||||||
expect(queryString.getParam('baz')).toBeFalsy();
|
expect(queryString.getParam('baz')).toBeFalsy();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
isNonMonkeyPatchableClass(jasmineUnderTest.QueryString, function() {
|
||||||
|
return new jasmineUnderTest.QueryString({
|
||||||
|
getWindowLocation: function() {
|
||||||
|
return { search: '' };
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ module.exports = {
|
|||||||
'helpers/domHelpers.js',
|
'helpers/domHelpers.js',
|
||||||
'helpers/integrationMatchers.js',
|
'helpers/integrationMatchers.js',
|
||||||
'helpers/callerFilenameShim.js',
|
'helpers/callerFilenameShim.js',
|
||||||
|
'helpers/monkeyPatchingSpecs.js',
|
||||||
'helpers/defineJasmineUnderTest.js',
|
'helpers/defineJasmineUnderTest.js',
|
||||||
'helpers/resetEnv.js'
|
'helpers/resetEnv.js'
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
"helpers/integrationMatchers.js",
|
"helpers/integrationMatchers.js",
|
||||||
"helpers/callerFilenameShim.js",
|
"helpers/callerFilenameShim.js",
|
||||||
"helpers/overrideConsoleLogForCircleCi.js",
|
"helpers/overrideConsoleLogForCircleCi.js",
|
||||||
|
"helpers/monkeyPatchingSpecs.js",
|
||||||
"helpers/nodeDefineJasmineUnderTest.js",
|
"helpers/nodeDefineJasmineUnderTest.js",
|
||||||
"helpers/resetEnv.js"
|
"helpers/resetEnv.js"
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -192,6 +192,8 @@ callbacks to execute _before_ running the next one.
|
|||||||
setInterval[IsMockClockTimingFn] = true;
|
setInterval[IsMockClockTimingFn] = true;
|
||||||
clearInterval[IsMockClockTimingFn] = true;
|
clearInterval[IsMockClockTimingFn] = true;
|
||||||
|
|
||||||
|
Object.freeze(this);
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
|
|
||||||
// Advances the Clock's time until the mode changes.
|
// Advances the Clock's time until the mode changes.
|
||||||
@@ -345,5 +347,7 @@ callbacks to execute _before_ running the next one.
|
|||||||
};
|
};
|
||||||
|
|
||||||
Clock.IsMockClockTimingFn = IsMockClockTimingFn;
|
Clock.IsMockClockTimingFn = IsMockClockTimingFn;
|
||||||
|
Object.freeze(Clock);
|
||||||
|
Object.freeze(Clock.prototype);
|
||||||
return Clock;
|
return Clock;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -835,6 +835,8 @@ getJasmineRequireObj().Env = function(j$, private$) {
|
|||||||
this.cleanup_ = function() {
|
this.cleanup_ = function() {
|
||||||
uninstallGlobalErrors();
|
uninstallGlobalErrors();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Object.freeze(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
function indirectCallerFilename(depth) {
|
function indirectCallerFilename(depth) {
|
||||||
@@ -845,5 +847,7 @@ getJasmineRequireObj().Env = function(j$, private$) {
|
|||||||
return frames[depth] && frames[depth].file;
|
return frames[depth] && frames[depth].file;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Object.freeze(Env);
|
||||||
|
Object.freeze(Env.prototype);
|
||||||
return Env;
|
return Env;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -87,8 +87,11 @@ getJasmineRequireObj().ParallelReportDispatcher = function(j$, private$) {
|
|||||||
for (const eventName of private$.reporterEvents) {
|
for (const eventName of private$.reporterEvents) {
|
||||||
this[eventName] = dispatcher[eventName].bind(dispatcher);
|
this[eventName] = dispatcher[eventName].bind(dispatcher);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Object.freeze(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Object.freeze(ParallelReportDispatcher.prototype);
|
||||||
return ParallelReportDispatcher;
|
return ParallelReportDispatcher;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -39,7 +39,11 @@ getJasmineRequireObj().Timer = function() {
|
|||||||
this.elapsed = function() {
|
this.elapsed = function() {
|
||||||
return now() - startTime;
|
return now() - startTime;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Object.freeze(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Object.freeze(Timer);
|
||||||
|
Object.freeze(Timer.prototype);
|
||||||
return Timer;
|
return Timer;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ getJasmineRequireObj().base = function(j$, private$, jasmineGlobal) {
|
|||||||
*/
|
*/
|
||||||
let DEFAULT_TIMEOUT_INTERVAL = 5000;
|
let DEFAULT_TIMEOUT_INTERVAL = 5000;
|
||||||
Object.defineProperty(j$, 'DEFAULT_TIMEOUT_INTERVAL', {
|
Object.defineProperty(j$, 'DEFAULT_TIMEOUT_INTERVAL', {
|
||||||
|
enumerable: true,
|
||||||
get: function() {
|
get: function() {
|
||||||
return DEFAULT_TIMEOUT_INTERVAL;
|
return DEFAULT_TIMEOUT_INTERVAL;
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -116,6 +116,28 @@ const getJasmineRequireObj = (function() {
|
|||||||
|
|
||||||
private$.loadedAsBrowserEsm = loadedAsBrowserEsm;
|
private$.loadedAsBrowserEsm = loadedAsBrowserEsm;
|
||||||
|
|
||||||
|
// Prevent monkey patching of existing properties but allow adding new ones.
|
||||||
|
// jasmine-html.js needs to be able to add to the jasmine namespace.
|
||||||
|
// jasmine-ajax also installs itself this way.
|
||||||
|
const writeable = [
|
||||||
|
'DEFAULT_TIMEOUT_INTERVAL',
|
||||||
|
'MAX_PRETTY_PRINT_ARRAY_LENGTH',
|
||||||
|
'MAX_PRETTY_PRINT_CHARS',
|
||||||
|
'MAX_PRETTY_PRINT_DEPTH'
|
||||||
|
];
|
||||||
|
const descriptors = Object.getOwnPropertyDescriptors(j$);
|
||||||
|
|
||||||
|
for (const [k, d] of Object.entries(descriptors)) {
|
||||||
|
if (!writeable.includes(k)) {
|
||||||
|
Object.defineProperty(j$, k, {
|
||||||
|
value: d.value,
|
||||||
|
enumerable: d.enumerable,
|
||||||
|
configurable: false,
|
||||||
|
writable: false
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return { jasmine: j$, private: private$ };
|
return { jasmine: j$, private: private$ };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -98,6 +98,8 @@ getJasmineHtmlRequireObj().HtmlReporterV2 = function(j$, private$) {
|
|||||||
);
|
);
|
||||||
this.#container.appendChild(this.#htmlReporterMain);
|
this.#container.appendChild(this.#htmlReporterMain);
|
||||||
this.#failures.show();
|
this.#failures.show();
|
||||||
|
|
||||||
|
Object.freeze(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
jasmineStarted(options) {
|
jasmineStarted(options) {
|
||||||
@@ -275,5 +277,6 @@ getJasmineHtmlRequireObj().HtmlReporterV2 = function(j$, private$) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Object.freeze(HtmlReporterV2.prototype);
|
||||||
return HtmlReporterV2;
|
return HtmlReporterV2;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -18,6 +18,8 @@ getJasmineHtmlRequireObj().HtmlReporterV2Urls = function(j$, private$) {
|
|||||||
return window.location;
|
return window.location;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Object.freeze(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -68,5 +70,6 @@ getJasmineHtmlRequireObj().HtmlReporterV2Urls = function(j$, private$) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Object.freeze(HtmlReporterV2Urls.prototype);
|
||||||
return HtmlReporterV2Urls;
|
return HtmlReporterV2Urls;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ getJasmineHtmlRequireObj().QueryString = function() {
|
|||||||
*/
|
*/
|
||||||
constructor(options) {
|
constructor(options) {
|
||||||
this.#getWindowLocation = options.getWindowLocation;
|
this.#getWindowLocation = options.getWindowLocation;
|
||||||
|
Object.freeze(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -81,5 +82,6 @@ getJasmineHtmlRequireObj().QueryString = function() {
|
|||||||
return '?' + qStrPairs.join('&');
|
return '?' + qStrPairs.join('&');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Object.freeze(QueryString.prototype);
|
||||||
return QueryString;
|
return QueryString;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -25,10 +25,16 @@ const getJasmineHtmlRequireObj = (function() {
|
|||||||
private$.FailuresView = htmlRequire.FailuresView(j$, private$);
|
private$.FailuresView = htmlRequire.FailuresView(j$, private$);
|
||||||
private$.PerformanceView = htmlRequire.PerformanceView(j$, private$);
|
private$.PerformanceView = htmlRequire.PerformanceView(j$, private$);
|
||||||
private$.TabBar = htmlRequire.TabBar(j$, private$);
|
private$.TabBar = htmlRequire.TabBar(j$, private$);
|
||||||
j$.HtmlReporterV2Urls = htmlRequire.HtmlReporterV2Urls(j$, private$);
|
|
||||||
j$.HtmlReporterV2 = htmlRequire.HtmlReporterV2(j$, private$);
|
|
||||||
j$.QueryString = htmlRequire.QueryString();
|
|
||||||
private$.HtmlSpecFilterV2 = htmlRequire.HtmlSpecFilterV2();
|
private$.HtmlSpecFilterV2 = htmlRequire.HtmlSpecFilterV2();
|
||||||
|
|
||||||
|
for (const k of ['HtmlReporterV2Urls', 'HtmlReporterV2', 'QueryString']) {
|
||||||
|
Object.defineProperty(j$, k, {
|
||||||
|
enumerable: true,
|
||||||
|
configurable: false,
|
||||||
|
writable: false,
|
||||||
|
value: htmlRequire[k](j$, private$)
|
||||||
|
});
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return getJasmineHtmlRequire;
|
return getJasmineHtmlRequire;
|
||||||
|
|||||||
Reference in New Issue
Block a user