Skip to content

Commit cc31055

Browse files
committed
fix(core): fix angular#405, refine the error message when zone.js already loaded.
1 parent 0d0ee53 commit cc31055

File tree

2 files changed

+46
-4
lines changed

2 files changed

+46
-4
lines changed

lib/zone.ts

+33-3
Original file line numberDiff line numberDiff line change
@@ -608,7 +608,19 @@ type AmbientZoneDelegate = ZoneDelegate;
608608

609609
const Zone: ZoneType = (function(global: any) {
610610
if (global['Zone']) {
611-
throw new Error('Zone already loaded.');
611+
let zoneAlreadyLoadedMessage: string = 'Zone already loaded.';
612+
// try to findout the already loaded zone.js script file
613+
// require the loaded zone.js version to be newer than 0.8.6
614+
try {
615+
const LoadedZone: any = global['Zone'];
616+
const scriptFileName: string = LoadedZone['__zone_symbol__scriptFileName'];
617+
if (scriptFileName) {
618+
zoneAlreadyLoadedMessage =
619+
'Zone already loaded. The loaded Zone.js script file seems to be ' + scriptFileName;
620+
}
621+
} catch (error) {
622+
}
623+
throw new Error(zoneAlreadyLoadedMessage);
612624
}
613625

614626
const NO_ZONE = {name: 'NO ZONE'};
@@ -623,12 +635,17 @@ const Zone: ZoneType = (function(global: any) {
623635

624636
static assertZonePatched() {
625637
if (global.Promise !== ZoneAwarePromise) {
638+
// try to findout the already loaded zone.js script file
639+
// require the loaded zone.js version to be newer than 0.8.6
640+
const scriptFileName: string = (Zone as any)[__symbol__('scriptFileName')];
641+
const scriptFileErrorMessage: string =
642+
scriptFileName ? 'the loaded Zone.js script file seems to be ' + scriptFileName : '';
626643
throw new Error(
627644
'Zone.js has detected that ZoneAwarePromise `(window|global).Promise` ' +
628645
'has been overwritten.\n' +
629646
'Most likely cause is that a Promise polyfill has been loaded ' +
630647
'after Zone.js (Polyfilling Promise api is not necessary when zone.js is loaded. ' +
631-
'If you must load one, do so before loading zone.js.)');
648+
'If you must load one, do so before loading zone.js.)' + scriptFileErrorMessage);
632649
}
633650
}
634651

@@ -1803,11 +1820,24 @@ const Zone: ZoneType = (function(global: any) {
18031820
// Chrome: at Zone.run (http://localhost:9876/base/build/lib/zone.js:100:24)
18041821
// FireFox: Zone.prototype.run@http://localhost:9876/base/build/lib/zone.js:101:24
18051822
// Safari: run@http://localhost:9876/base/build/lib/zone.js:101:24
1806-
let fnName: string = frame.split('(')[0].split('@')[0];
1823+
let frameParts: string[] = frame.split('(');
1824+
let fnNamePart: string = frameParts[0];
1825+
1826+
let fnName: string = fnNamePart.split('@')[0];
18071827
let frameType = FrameType.transition;
18081828
if (fnName.indexOf('ZoneAwareError') !== -1) {
18091829
zoneAwareFrame1 = frame;
18101830
zoneAwareFrame2 = frame.replace('Error.', '');
1831+
1832+
// try to find the filename where zone.js live with
1833+
let fileNamePart1: string = frameParts.length > 1 ? frameParts[1] : fnNamePart;
1834+
let fileNameParts: string[] = fileNamePart1.split('@');
1835+
let fileNamePart2: string =
1836+
fileNameParts.length > 1 ? fileNameParts[1] : fileNameParts[0];
1837+
// Keep a script file name in Zone, so when zone.js report 'already loaded'
1838+
// error, it can report which file include the loaded zone.js
1839+
(Zone as any)[__symbol__('scriptFileName')] = fileNamePart2;
1840+
18111841
blackListedStackFrames[zoneAwareFrame2] = FrameType.blackList;
18121842
}
18131843
if (fnName.indexOf('runGuarded') !== -1) {

test/common/zone.spec.ts

+13-1
Original file line numberDiff line numberDiff line change
@@ -328,12 +328,24 @@ describe('Zone', function() {
328328

329329
it('should throw when Promise has been patched', () => {
330330
class WrongPromise {}
331+
const errorMessage =
332+
'Zone.js has detected that ZoneAwarePromise `(window|global).Promise` ' +
333+
'has been overwritten.';
334+
const errorScriptMessage = 'the loaded Zone.js script file seems to be';
331335

332336
const ZoneAwarePromise = global.Promise;
333337
global.Promise = WrongPromise;
334338
try {
335339
expect(ZoneAwarePromise).toBeTruthy();
336-
expect(() => Zone.assertZonePatched()).toThrow();
340+
try {
341+
Zone.assertZonePatched();
342+
} catch (error) {
343+
expect(error.message).toContain(errorMessage);
344+
expect(error.message).toContain(errorScriptMessage);
345+
const idx = error.message.lastIndexOf(errorScriptMessage);
346+
const fileName: string = error.message.slice(idx + errorScriptMessage.length);
347+
expect(fileName).toContain('zone.js');
348+
}
337349
} finally {
338350
// restore it.
339351
global.Promise = ZoneAwarePromise;

0 commit comments

Comments
 (0)