Prevent GloablErrors from being monkey patched

All current shipped versions of zone.js contain a monkey patch that fails
to pass constructor arguments on to GlobalErrors. That would crash Jasmine
if it was applied early enough to have any effect.

See <https://github.com/angular/angular/issues/63072>.
This commit is contained in:
Steve Gravrock
2025-08-11 17:57:16 -07:00
parent 42cca93926
commit 5b06531cac
5 changed files with 47 additions and 10 deletions

View File

@@ -114,7 +114,19 @@ var getJasmineRequireObj = (function(jasmineGlobal) {
j$.NullDiffBuilder = jRequire.NullDiffBuilder(j$);
j$.ObjectPath = jRequire.ObjectPath(j$);
j$.MismatchTree = jRequire.MismatchTree(j$);
j$.GlobalErrors = jRequire.GlobalErrors(j$);
// zone.js tries to monkey patch GlobalErrors in a way that is either a
// no-op or causes Jasmine to crash, depending on whether it's done before
// or after env creation. Prevent that.
const GlobalErrors = jRequire.GlobalErrors(j$);
Object.defineProperty(j$, 'GlobalErrors', {
enumerable: true,
configurable: false,
get() {
return GlobalErrors;
},
set() {}
});
j$.Truthy = jRequire.Truthy(j$);
j$.Falsy = jRequire.Falsy(j$);
@@ -1195,6 +1207,7 @@ getJasmineRequireObj().Env = function(j$) {
options = options || {};
const self = this;
const GlobalErrors = options.GlobalErrors || j$.GlobalErrors;
const global = options.global || j$.getGlobal();
const realSetTimeout = global.setTimeout;
@@ -1208,7 +1221,7 @@ getJasmineRequireObj().Env = function(j$) {
new j$.MockDate(global)
);
const globalErrors = new j$.GlobalErrors(
const globalErrors = new GlobalErrors(
undefined,
// Configuration is late-bound because GlobalErrors needs to be constructed
// before it's set to detect load-time errors in browsers

View File

@@ -625,9 +625,12 @@ describe('Env', function() {
'popListener',
'removeOverrideListener'
]);
spyOn(jasmineUnderTest, 'GlobalErrors').and.returnValue(globalErrors);
env.cleanup_();
env = new jasmineUnderTest.Env();
env = new jasmineUnderTest.Env({
GlobalErrors: function() {
return globalErrors;
}
});
expect(globalErrors.install).toHaveBeenCalled();
});
});
@@ -641,9 +644,13 @@ describe('Env', function() {
'popListener',
'removeOverrideListener'
]);
spyOn(jasmineUnderTest, 'GlobalErrors').and.returnValue(globalErrors);
env.cleanup_();
env = new jasmineUnderTest.Env({ suppressLoadErrors: true });
env = new jasmineUnderTest.Env({
suppressLoadErrors: true,
GlobalErrors: function() {
return globalErrors;
}
});
expect(globalErrors.install).not.toHaveBeenCalled();
env.execute();
expect(globalErrors.install).toHaveBeenCalled();

View File

@@ -88,10 +88,14 @@ describe('Global error handling (integration)', function() {
const globalErrors = new jasmineUnderTest.GlobalErrors(global);
const onerror = jasmine.createSpy('onerror');
globalErrors.pushListener(onerror);
spyOn(jasmineUnderTest, 'GlobalErrors').and.returnValue(globalErrors);
env.cleanup_();
env = new jasmineUnderTest.Env({ suppressLoadErrors: true });
env = new jasmineUnderTest.Env({
suppressLoadErrors: true,
GlobalErrors: function() {
return globalErrors;
}
});
const reporter = jasmine.createSpyObj('reporter', [
'jasmineDone',
'suiteDone',

View File

@@ -11,6 +11,7 @@ getJasmineRequireObj().Env = function(j$) {
options = options || {};
const self = this;
const GlobalErrors = options.GlobalErrors || j$.GlobalErrors;
const global = options.global || j$.getGlobal();
const realSetTimeout = global.setTimeout;
@@ -24,7 +25,7 @@ getJasmineRequireObj().Env = function(j$) {
new j$.MockDate(global)
);
const globalErrors = new j$.GlobalErrors(
const globalErrors = new GlobalErrors(
undefined,
// Configuration is late-bound because GlobalErrors needs to be constructed
// before it's set to detect load-time errors in browsers

View File

@@ -90,7 +90,19 @@ var getJasmineRequireObj = (function(jasmineGlobal) {
j$.NullDiffBuilder = jRequire.NullDiffBuilder(j$);
j$.ObjectPath = jRequire.ObjectPath(j$);
j$.MismatchTree = jRequire.MismatchTree(j$);
j$.GlobalErrors = jRequire.GlobalErrors(j$);
// zone.js tries to monkey patch GlobalErrors in a way that is either a
// no-op or causes Jasmine to crash, depending on whether it's done before
// or after env creation. Prevent that.
const GlobalErrors = jRequire.GlobalErrors(j$);
Object.defineProperty(j$, 'GlobalErrors', {
enumerable: true,
configurable: false,
get() {
return GlobalErrors;
},
set() {}
});
j$.Truthy = jRequire.Truthy(j$);
j$.Falsy = jRequire.Falsy(j$);