From 7a5e2a2a639c5a1cfd29c73883fbfa6c8119ff99 Mon Sep 17 00:00:00 2001 From: "JiaLi.Passion" Date: Fri, 31 Mar 2017 01:34:15 +0900 Subject: [PATCH] fix(error): fix #698, don not generate long stack trace when Error.stackTraceLimit = 0, add null check --- lib/zone-spec/long-stack-trace.ts | 45 +++++++++++++------- test/zone-spec/long-stack-trace-zone.spec.ts | 23 ++++++++++ 2 files changed, 53 insertions(+), 15 deletions(-) diff --git a/lib/zone-spec/long-stack-trace.ts b/lib/zone-spec/long-stack-trace.ts index 5c12460ea..87da027a3 100644 --- a/lib/zone-spec/long-stack-trace.ts +++ b/lib/zone-spec/long-stack-trace.ts @@ -58,7 +58,7 @@ function addErrorStack(lines: string[], error: Error): void { } function renderLongStackTrace(frames: LongStackTrace[], stack: string): string { - const longTrace: string[] = [stack.trim()]; + const longTrace: string[] = [stack ? stack.trim() : '']; if (frames) { let timestamp = new Date().getTime(); @@ -97,26 +97,38 @@ function renderLongStackTrace(frames: LongStackTrace[], stack: string): string { onScheduleTask: function( parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, task: Task): any { - const currentTask = Zone.currentTask; - let trace = currentTask && currentTask.data && (currentTask.data as any)[creationTrace] || []; - trace = [new LongStackTrace()].concat(trace); - if (trace.length > this.longStackTraceLimit) { - trace.length = this.longStackTraceLimit; + if (Error.stackTraceLimit > 0) { + // if Error.stackTraceLimit is 0, means stack trace + // is disabled, so we don't need to generate long stack trace + // this will improve performance in some test(some test will + // set stackTraceLimit to 0, https://github.com/angular/zone.js/issues/698 + const currentTask = Zone.currentTask; + let trace = currentTask && currentTask.data && (currentTask.data as any)[creationTrace] || []; + trace = [new LongStackTrace()].concat(trace); + if (trace.length > this.longStackTraceLimit) { + trace.length = this.longStackTraceLimit; + } + if (!task.data) task.data = {}; + (task.data as any)[creationTrace] = trace; } - if (!task.data) task.data = {}; - (task.data as any)[creationTrace] = trace; return parentZoneDelegate.scheduleTask(targetZone, task); }, onHandleError: function( parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, error: any): boolean { - const parentTask = Zone.currentTask || error.task; - if (error instanceof Error && parentTask) { - const longStack = - renderLongStackTrace(parentTask.data && parentTask.data[creationTrace], error.stack); - try { - error.stack = (error as any).longStack = longStack; - } catch (err) { + if (Error.stackTraceLimit > 0) { + // if Error.stackTraceLimit is 0, means stack trace + // is disabled, so we don't need to generate long stack trace + // this will improve performance in some test(some test will + // set stackTraceLimit to 0, https://github.com/angular/zone.js/issues/698 + const parentTask = Zone.currentTask || error.task; + if (error instanceof Error && parentTask) { + const longStack = + renderLongStackTrace(parentTask.data && parentTask.data[creationTrace], error.stack); + try { + error.stack = (error as any).longStack = longStack; + } catch (err) { + } } } return parentZoneDelegate.handleError(targetZone, error); @@ -131,6 +143,9 @@ function captureStackTraces(stackTraces: string[][], count: number): void { } function computeIgnoreFrames() { + if (Error.stackTraceLimit <= 0) { + return; + } const frames: string[][] = []; captureStackTraces(frames, 2); const frames1 = frames[0]; diff --git a/test/zone-spec/long-stack-trace-zone.spec.ts b/test/zone-spec/long-stack-trace-zone.spec.ts index 5750eae19..fa198bf98 100644 --- a/test/zone-spec/long-stack-trace-zone.spec.ts +++ b/test/zone-spec/long-stack-trace-zone.spec.ts @@ -120,4 +120,27 @@ describe('longStackTraceZone', function() { }, 0); }); }); + + it('should not produce long stack traces if Error.stackTraceLimit = 0', function(done) { + const originalStackTraceLimit = Error.stackTraceLimit; + const detectError = new Error(); + lstz.run(function() { + setTimeout(function() { + setTimeout(function() { + setTimeout(function() { + if (detectError.stack) { + expectElapsed(log[0].stack, 1); + Error.stackTraceLimit = originalStackTraceLimit; + } else { + // IE stack trace will be undefined + expect(log[0].stack).toBeFalsy(); + } + done(); + }, 0); + Error.stackTraceLimit = 0; + throw new Error('Hello'); + }, 0); + }, 0); + }); + }); });