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:
Steve Gravrock
2026-02-16 11:06:27 -08:00
parent 281c0d1ee8
commit 63ac7da082
23 changed files with 263 additions and 9 deletions

View File

@@ -192,6 +192,8 @@ callbacks to execute _before_ running the next one.
setInterval[IsMockClockTimingFn] = true;
clearInterval[IsMockClockTimingFn] = true;
Object.freeze(this);
return this;
// Advances the Clock's time until the mode changes.
@@ -345,5 +347,7 @@ callbacks to execute _before_ running the next one.
};
Clock.IsMockClockTimingFn = IsMockClockTimingFn;
Object.freeze(Clock);
Object.freeze(Clock.prototype);
return Clock;
};

View File

@@ -835,6 +835,8 @@ getJasmineRequireObj().Env = function(j$, private$) {
this.cleanup_ = function() {
uninstallGlobalErrors();
};
Object.freeze(this);
}
function indirectCallerFilename(depth) {
@@ -845,5 +847,7 @@ getJasmineRequireObj().Env = function(j$, private$) {
return frames[depth] && frames[depth].file;
}
Object.freeze(Env);
Object.freeze(Env.prototype);
return Env;
};

View File

@@ -87,8 +87,11 @@ getJasmineRequireObj().ParallelReportDispatcher = function(j$, private$) {
for (const eventName of private$.reporterEvents) {
this[eventName] = dispatcher[eventName].bind(dispatcher);
}
Object.freeze(this);
}
}
Object.freeze(ParallelReportDispatcher.prototype);
return ParallelReportDispatcher;
};

View File

@@ -39,7 +39,11 @@ getJasmineRequireObj().Timer = function() {
this.elapsed = function() {
return now() - startTime;
};
Object.freeze(this);
}
Object.freeze(Timer);
Object.freeze(Timer.prototype);
return Timer;
};

View File

@@ -43,6 +43,7 @@ getJasmineRequireObj().base = function(j$, private$, jasmineGlobal) {
*/
let DEFAULT_TIMEOUT_INTERVAL = 5000;
Object.defineProperty(j$, 'DEFAULT_TIMEOUT_INTERVAL', {
enumerable: true,
get: function() {
return DEFAULT_TIMEOUT_INTERVAL;
},

View File

@@ -116,6 +116,28 @@ const getJasmineRequireObj = (function() {
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$ };
};

View File

@@ -98,6 +98,8 @@ getJasmineHtmlRequireObj().HtmlReporterV2 = function(j$, private$) {
);
this.#container.appendChild(this.#htmlReporterMain);
this.#failures.show();
Object.freeze(this);
}
jasmineStarted(options) {
@@ -275,5 +277,6 @@ getJasmineHtmlRequireObj().HtmlReporterV2 = function(j$, private$) {
}
}
Object.freeze(HtmlReporterV2.prototype);
return HtmlReporterV2;
};

View File

@@ -18,6 +18,8 @@ getJasmineHtmlRequireObj().HtmlReporterV2Urls = function(j$, private$) {
return window.location;
}
});
Object.freeze(this);
}
/**
@@ -68,5 +70,6 @@ getJasmineHtmlRequireObj().HtmlReporterV2Urls = function(j$, private$) {
}
}
Object.freeze(HtmlReporterV2Urls.prototype);
return HtmlReporterV2Urls;
};

View File

@@ -14,6 +14,7 @@ getJasmineHtmlRequireObj().QueryString = function() {
*/
constructor(options) {
this.#getWindowLocation = options.getWindowLocation;
Object.freeze(this);
}
/**
@@ -81,5 +82,6 @@ getJasmineHtmlRequireObj().QueryString = function() {
return '?' + qStrPairs.join('&');
}
Object.freeze(QueryString.prototype);
return QueryString;
};

View File

@@ -25,10 +25,16 @@ const getJasmineHtmlRequireObj = (function() {
private$.FailuresView = htmlRequire.FailuresView(j$, private$);
private$.PerformanceView = htmlRequire.PerformanceView(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();
for (const k of ['HtmlReporterV2Urls', 'HtmlReporterV2', 'QueryString']) {
Object.defineProperty(j$, k, {
enumerable: true,
configurable: false,
writable: false,
value: htmlRequire[k](j$, private$)
});
}
};
return getJasmineHtmlRequire;