angular / zone.js

Implements Zones for JavaScript
https://github.com/angular/angular/tree/master/packages/zone.js/
MIT License
3.25k stars 408 forks source link

Zone long stack traces generates wrong stack trace #1195

Closed timofei-iatsenko closed 5 years ago

timofei-iatsenko commented 5 years ago

I created a small stackblitz repo which shows the problem:

https://stackblitz.com/edit/typescript-ouevfy?file=index.html

Click on both buttons, and you will see that place of actual definition of event handler is incorrect. Here is a really simple example where both definitions really close to each other, but in real application, the situation is much worse.

Actually for all EventTasks (not sure about other, haven't tested it) captured stacktrace equals to the latest one defined event handler.

This caused because here long-stack-trace.ts

onScheduleTask: function(...): any {
 // ...
  if (!task.data) task.data = {};
  (task.data as any)[creationTrace] = trace; // <------
 // ...
}

data property from ZoneTask is a reference to global object defined here as OPTIMIZED_ZONE_EVENT_TASK_DATA constant.

And all execution of this callback just mutate this object and all tasks inherit the same stack trace.

There are two possible ways to resolve the problem. It's either possible to modify long-stack-trace.ts file

-  (task.data as any)[creationTrace] = trace;
+    (task.data as any) = {
+      ...task.data,
+      [creationTrace]: trace,
+    };

Or break the reference in ZoneTask itself

class ZoneTask<T extends TaskType> implements Task {
   ...
    constructor(...) {
      this.type = type;
      this.source = source;
-     this.data = options;
+     this.data = { ...options };
      this.scheduleFn = scheduleFn;
      this.cancelFn = cancelFn;
      this.callback = callback;
   }
}
JiaLiPassion commented 5 years ago

@thekip , thanks for posting this issue, I will check it.