Skip to content
This repository was archived by the owner on Feb 26, 2024. It is now read-only.

Commit 88d1a49

Browse files
JiaLiPassionmhevery
authored andcommitted
fix(error): remove throw in Error constructor to improve performance in IE11 (#704)
* fix(error): remove throw in Error constructor to improve performance in IE * fix(error): fix #698, don not generate long stack trace when Error.stackTraceLimit = 0, add null check
1 parent 967a991 commit 88d1a49

File tree

3 files changed

+54
-26
lines changed

3 files changed

+54
-26
lines changed

Diff for: lib/zone-spec/long-stack-trace.ts

+30-15
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ function addErrorStack(lines: string[], error: Error): void {
5858
}
5959

6060
function renderLongStackTrace(frames: LongStackTrace[], stack: string): string {
61-
const longTrace: string[] = [stack.trim()];
61+
const longTrace: string[] = [stack ? stack.trim() : ''];
6262

6363
if (frames) {
6464
let timestamp = new Date().getTime();
@@ -97,26 +97,38 @@ function renderLongStackTrace(frames: LongStackTrace[], stack: string): string {
9797

9898
onScheduleTask: function(
9999
parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, task: Task): any {
100-
const currentTask = Zone.currentTask;
101-
let trace = currentTask && currentTask.data && (currentTask.data as any)[creationTrace] || [];
102-
trace = [new LongStackTrace()].concat(trace);
103-
if (trace.length > this.longStackTraceLimit) {
104-
trace.length = this.longStackTraceLimit;
100+
if (Error.stackTraceLimit > 0) {
101+
// if Error.stackTraceLimit is 0, means stack trace
102+
// is disabled, so we don't need to generate long stack trace
103+
// this will improve performance in some test(some test will
104+
// set stackTraceLimit to 0, https://github.com/angular/zone.js/issues/698
105+
const currentTask = Zone.currentTask;
106+
let trace = currentTask && currentTask.data && (currentTask.data as any)[creationTrace] || [];
107+
trace = [new LongStackTrace()].concat(trace);
108+
if (trace.length > this.longStackTraceLimit) {
109+
trace.length = this.longStackTraceLimit;
110+
}
111+
if (!task.data) task.data = {};
112+
(task.data as any)[creationTrace] = trace;
105113
}
106-
if (!task.data) task.data = {};
107-
(task.data as any)[creationTrace] = trace;
108114
return parentZoneDelegate.scheduleTask(targetZone, task);
109115
},
110116

111117
onHandleError: function(
112118
parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, error: any): boolean {
113-
const parentTask = Zone.currentTask || error.task;
114-
if (error instanceof Error && parentTask) {
115-
const longStack =
116-
renderLongStackTrace(parentTask.data && parentTask.data[creationTrace], error.stack);
117-
try {
118-
error.stack = (error as any).longStack = longStack;
119-
} catch (err) {
119+
if (Error.stackTraceLimit > 0) {
120+
// if Error.stackTraceLimit is 0, means stack trace
121+
// is disabled, so we don't need to generate long stack trace
122+
// this will improve performance in some test(some test will
123+
// set stackTraceLimit to 0, https://github.com/angular/zone.js/issues/698
124+
const parentTask = Zone.currentTask || error.task;
125+
if (error instanceof Error && parentTask) {
126+
const longStack =
127+
renderLongStackTrace(parentTask.data && parentTask.data[creationTrace], error.stack);
128+
try {
129+
error.stack = (error as any).longStack = longStack;
130+
} catch (err) {
131+
}
120132
}
121133
}
122134
return parentZoneDelegate.handleError(targetZone, error);
@@ -131,6 +143,9 @@ function captureStackTraces(stackTraces: string[][], count: number): void {
131143
}
132144

133145
function computeIgnoreFrames() {
146+
if (Error.stackTraceLimit <= 0) {
147+
return;
148+
}
134149
const frames: string[][] = [];
135150
captureStackTraces(frames, 2);
136151
const frames1 = frames[0];

Diff for: lib/zone.ts

-10
Original file line numberDiff line numberDiff line change
@@ -1630,16 +1630,6 @@ const Zone: ZoneType = (function(global: any) {
16301630
function ZoneAwareError(): Error {
16311631
// We always have to return native error otherwise the browser console will not work.
16321632
let error: Error = NativeError.apply(this, arguments);
1633-
if (!error.stack) {
1634-
// in IE, the error.stack will be undefined
1635-
// when error was constructed, it will only
1636-
// be available when throw
1637-
try {
1638-
throw error;
1639-
} catch (err) {
1640-
error = err;
1641-
}
1642-
}
16431633
// Save original stack trace
16441634
const originalStack = (error as any)['originalStack'] = error.stack;
16451635

Diff for: test/zone-spec/long-stack-trace-zone.spec.ts

+24-1
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,11 @@ describe('longStackTraceZone', function() {
103103
setTimeout(function() {
104104
let promise = new Promise(function(resolve, reject) {
105105
setTimeout(function() {
106-
reject(new Error('Hello Promise'));
106+
try {
107+
throw new Error('Hello Promise');
108+
} catch (err) {
109+
reject(err);
110+
}
107111
}, 0);
108112
});
109113
promise.catch(function(error) {
@@ -116,4 +120,23 @@ describe('longStackTraceZone', function() {
116120
}, 0);
117121
});
118122
});
123+
124+
it('should not produce long stack traces if Error.stackTraceLimit = 0', function(done) {
125+
const originalStackTraceLimit = Error.stackTraceLimit;
126+
lstz.run(function() {
127+
setTimeout(function() {
128+
setTimeout(function() {
129+
setTimeout(function() {
130+
if (log[0].stack) {
131+
expectElapsed(log[0].stack, 1);
132+
}
133+
Error.stackTraceLimit = originalStackTraceLimit;
134+
done();
135+
}, 0);
136+
Error.stackTraceLimit = 0;
137+
throw new Error('Hello');
138+
}, 0);
139+
}, 0);
140+
});
141+
});
119142
});

0 commit comments

Comments
 (0)