Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TraceKit can now be used on frames #68

Open
wants to merge 17 commits into
base: master
Choose a base branch
from
Open

Conversation

aquadk
Copy link

@aquadk aquadk commented Jan 17, 2017

Hi, have made this change so, I only need to include TraceKit once on my frame page.

Here is the code for the frame page.

function insertTraceKit() {

  function yourLogger(errorReport) {
    console.log(errorReport);
    return true;
  }

  TraceKit.report.subscribe(yourLogger);

  function wrapped(aThis) {
    TraceKit.report.subscribe(yourLogger, aThis.target.contentWindow);
    try {
      aThis.target.contentWindow.onunload = unwrapped;
    } catch (e) {
      //console.log('cross-origin frame detected');
    }
  }

  function unwrapped(aThis) {
    TraceKit.report.unsubscribe(yourLogger, aThis.currentTarget);
  }

  var frames = document.getElementsByTagName('frame');
  for (var i = 0; i < frames.length; i++) {
    frames[i].onload = wrapped;
  };

}

var readyStateCheckInterval = setInterval(waitInit, 10, this);

function waitInit() {
  //console.log(document.readyState);
  if (document.readyState === "interactive") {
    clearInterval(readyStateCheckInterval);
    insertTraceKit();
  }
}

Hi, have made this change so, I only need to include TraceKit once on my frame page. 

Here is the code for the frame page.

    function insertTraceKit() {

      function yourLogger(errorReport) {
        console.log(errorReport);
        return true;
      }

      TraceKit.report.subscribe(yourLogger);

      function wrapped(aThis) {
        TraceKit.report.subscribe(yourLogger, aThis.target.contentWindow);
        try {
          aThis.target.contentWindow.onunload = unwrapped;
        } catch (e) {
          //console.log('cross-origin frame detected');
        }
      }

      function unwrapped(aThis) {
        TraceKit.report.unsubscribe(yourLogger, aThis.currentTarget);
      }

      var frames = document.getElementsByTagName('frame');
      for (var i = 0; i < frames.length; i++) {
        frames[i].onload = wrapped;
      };

    }

    var readyStateCheckInterval = setInterval(waitInit, 10, this);

    function waitInit() {
      //console.log(document.readyState);
      if (document.readyState === "interactive") {
        clearInterval(readyStateCheckInterval);
        insertTraceKit();
      }
    }
Copy link
Collaborator

@niemyjski niemyjski left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the pr, There are some things I saw that need to be updated or clarified,

I'm really hesitant on accepting this. I do see the value in this, but want to know the exact benefits gained. Also, we haven't really had any users report not seeing errors in iframes. I'd like to move away from window specific code, and have this in a plugin ideally. Can you add some tests for all the code here specifically one that deals with frames.

tracekit.js Outdated
installGlobalHandler();
handlers.push(handler);
function subscribe(handler, aWindow) {
aWindow = (aWindow || window);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we rename aWindow to win it's shorter and you know what it does, it's also consistent with your function above.

tracekit.js Outdated
@@ -921,7 +935,7 @@ TraceKit.computeStackTrace = (function computeStackTraceWrapper() {
}
}
} else if ((parts = lineRE3.exec(lines[line]))) {
var url = window.location.href.replace(/#.*$/, '');
var url = TraceKit.windowPointer.location.href.replace(/#.*$/, '');
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about parsing source in the inner frame?

tracekit.js Outdated
@@ -880,7 +894,7 @@ TraceKit.computeStackTrace = (function computeStackTraceWrapper() {
lineRE2 = /^\s*Line (\d+) of inline#(\d+) script in ((?:file|https?|blob)\S+)(?:: in function (\S+))?\s*$/i,
lineRE3 = /^\s*Line (\d+) of function script\s*$/i,
stack = [],
scripts = (window && window.document && window.document.getElementsByTagName('script')),
scripts = (TraceKit.windowPointer && TraceKit.windowPointer.document && TraceKit.windowPointer.document.getElementsByTagName('script')),
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you move this window pointer to a local variable, this will not minify very well.

tracekit.js Outdated
@@ -419,7 +431,9 @@ TraceKit.computeStackTrace = (function computeStackTraceWrapper() {
*/
var source = '';
var domain = '';
try { domain = window.document.domain; } catch (e) { }
try {
domain = window.document.domain;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not use the pointer here>

tracekit.js Outdated
_oldOnerrorHandler = window.onerror;
window.onerror = traceKitWindowOnError;
_onErrorHandlerInstalled = true;
var _oldOnerrorHandler = aWindow.onerror;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if this is no longer a private field we need to change the variable name

tracekit.js Outdated
}

if (_oldOnerrorHandler) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any reason for removing this?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is moved to notifyHandlers

tracekit.js Outdated
try {
handlers[i](stack, isWindowError, error);
handlers[i][0](stack, isWindowError, (aArguments.length > 4) ? aArguments[4] : null);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the 3rd and 4th parameter here? This became much less readable.

tracekit.js Outdated
} catch (inner) {
exception = inner;
}
if (handlers[i][1]._oldOnerrorHandler) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought this was a local variable.

Changed aWindow til win
value is not private anymore
+ made code easier to read
@aquadk
Copy link
Author

aquadk commented Jan 18, 2017

Hi,
Have now made the changes you asked for.

@aquadk aquadk closed this Jan 18, 2017
@aquadk aquadk reopened this Jan 18, 2017
tracekit.js Outdated
@@ -149,27 +160,31 @@ TraceKit.report = (function reportModuleWrapper() {
* @memberof TraceKit.report
* @throws An exception if an error occurs while calling an handler.
*/
function notifyHandlers(stack, isWindowError, error) {
function notifyHandlers(stack, isWindowError, aArguments) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does arguments contain? Can we call this args? and maybe a comment to break down what the possible structure is.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok, arguments contains all the arguments from onerror event

tracekit.js Outdated
try {
handlers[i](stack, isWindowError, error);
var errorObj=(aArguments.length > 4) ? aArguments[4] : null;
handlers[i][0](stack, isWindowError, errorObj);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is kind of confusing, so we call a method with stack, isWindowErorr and an array with 4 items? We seem to only be using the error object, so it might be better to revert this signature to just be error object. Previous thought: Maybe we need to add a comment stating that these arguments are actually: message, url, lineNo, columnNo, errorObj (if we were on es6, restructuring would make this so much more readable but we can't use that :(`,

tracekit.js Outdated
} catch (inner) {
exception = inner;
}
// Call old onerror events
if (handlers[i][2]) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We weren't doing this before were we? It's just really hard to follow this and make sense of what's going on.. We call all the other handlers in a try catch.

tracekit.js Outdated
@@ -183,13 +198,13 @@ TraceKit.report = (function reportModuleWrapper() {
*/
function traceKitWindowOnError(message, url, lineNo, columnNo, errorObj) {
var stack = null;

TraceKit.windowPointer = this;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So this modifies the pointer which might of been set earlier when you subscribed. I'm not sure this should be updated as it would change the subscription handler? Thoughts?

tracekit.js Outdated
for (var i = handlers.length - 1; i >= 0; --i) {
if (handlers[i] === handler) {
if (handlers[i][0] === handler && win === handlers[i][1]) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's all stored on handler now in this array?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We weren't doing this before, but since you are calling unsubscribe and you have an array with the previous error handler. Do you think we should be setting it back?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point, i will insert the code

tracekit.js Outdated
var debug = false,
sourceCache = {};
sourceCache = {},
curWin = TraceKit.windowPointer;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we rename this to win

@@ -1109,6 +1126,7 @@ TraceKit.computeStackTrace = (function computeStackTraceWrapper() {
* @memberof TraceKit.computeStackTrace
*/
function computeStackTrace(ex, depth) {
curWin = TraceKit.windowPointer;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't seem to be used

tracekit.js Outdated
var originalFn = window[fnName];
window[fnName] = function traceKitAsyncExtension() {
var originalFn = TraceKit.windowPointer[fnName];
TraceKit.windowPointer[fnName] = function traceKitAsyncExtension() {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might want to store this in a variable

@niemyjski
Copy link
Collaborator

I'm sorry for taking so long to get back to this. What is the current status of this?

@aquadk
Copy link
Author

aquadk commented Jul 3, 2017

I have updated the code for Iframe page too.


   /**    
     * Description    
     * @param {type} aTracefunc Description    
     */
    function insertTraceKit(aTracefunc) {

      TraceKit.report.subscribe(aTracefunc);

      function wrapped(aThis) {
        var w = (aThis.target || aThis);

        function docUnloadChange(e) {
          TraceKit.report.unsubscribe(yourLogger, e.currentTarget);
          //console.log('unload', e.currentTarget.location.href, e.currentTarget.readyState);
          var l = e.currentTarget.location.href;
          var checkForUnload = function (e) {
            try {
              if (l != e.location.href) {
                clearInterval(unloadCheckInterval);
                //console.log(e.location.href);
                TraceKit.report.subscribe(aTracefunc, e);
              }
            } catch (exception) {
              clearInterval(unloadCheckInterval);
              unloadCheckInterval = setInterval(checkForUnload, 100, this);
              //console.log('cross-origin frame detected');
            }
          };
          var unloadCheckInterval = setInterval(checkForUnload, 1, this);

        }

        TraceKit.report.subscribe(aTracefunc, w.contentWindow);
        try {
          w.contentWindow.addEventListener("unload", docUnloadChange);
        } catch (e) {
          //console.log('cross-origin frame detected');
        }
      }

      var frames = document.querySelectorAll('frame,iframe');
      for (var i = 0; i < frames.length; i++) {
        frames[i].onload = wrapped;
        try {
          // console.log(frames[i].contentDocument.readyState, frames[i].contentDocument.location.href);
          frames[i].readyStateCheckInterval = setInterval(fasteractiveTrace, 1, frames[i]);
        } catch (e) {
          //console.log('cross-origin frame detected');
        }
      }

      function fasteractiveTrace(e) {
        try {
          if (e.contentDocument) {
            if (e.contentDocument.readyState == "complete" || e.contentDocument.readyState == "interactive") {
              wrapped(e);
              clearInterval(e.readyStateCheckInterval);
            }
            // console.log(e.contentDocument.readyState, e.contentDocument.location.href);
          }
        } catch (exception) {
          //console.log('cross-origin frame detected');
        }
      }

    }

    var readyStateCheckInterval = setInterval(waitInit, 10, this);

    function waitInit() {
      //console.log(document.readyState);
      if (document.readyState === "complete" || document.readyState === "interactive") {
        clearInterval(readyStateCheckInterval);
        insertTraceKit(yourLogger);
      }
    }

@niemyjski
Copy link
Collaborator

Thanks, were any other changes required for this pr? Do you think we should put this in a wiki entry?

1 similar comment
@niemyjski
Copy link
Collaborator

Thanks, were any other changes required for this pr? Do you think we should put this in a wiki entry?

@niemyjski
Copy link
Collaborator

Thanks, were any other changes required for this pr? Do you think we should put this in a wiki entry? I'd like to get this merged in and cleaned up

tracekit.js Outdated
@@ -291,8 +302,8 @@ TraceKit.report = (function reportModuleWrapper() {
// slow slow IE to see if onerror occurs or not before reporting
// this exception; otherwise, we will end up with an incomplete
// stack trace
setTimeout(function () {
if (lastException === ex) {
window.setTimeout(function () {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any specific reason to putting this to window? It might block users from using this in node?

tracekit.js Outdated
};

notifyHandlers(stack, true, arguments);
notifyHandlers(stack, true, null);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

any reason for not passing through the arguments?

tracekit.js Outdated
@@ -204,17 +215,16 @@ TraceKit.report = (function reportModuleWrapper() {
TraceKit.windowPointer = this;
if (lastExceptionStack) {
TraceKit.computeStackTrace.augmentStackTraceWithInitialElement(lastExceptionStack, url, lineNo, message);
processLastException(arguments);
processLastException();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

any reason for not passing through the arguments?

@aquadk
Copy link
Author

aquadk commented Jul 17, 2018

I have merged our code and committed all changes.

Copy link
Collaborator

@niemyjski niemyjski left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I noticed that you merged in the lastest master changes but rejected all of those. Can you please go back over this pr and make sure we aren't missing anything like

  •    installGlobalHandler();
    
  •    installGlobalUnhandledRejectionHandler(); That would be greatly appreciated
    

@aquadk
Copy link
Author

aquadk commented Jul 18, 2018

Forgot to push all changes.. sorry

@niemyjski
Copy link
Collaborator

Hello, I'm not seeing any of the latest changes, can you please review the files changed here as you can see we added more code around installing additional global handlers.

@aquadk
Copy link
Author

aquadk commented Aug 15, 2018

All code are pushed into aquadk/Tracekit master branch. Including global handlers.

}

if (_oldOnerrorHandler) {
return _oldOnerrorHandler.apply(this, arguments);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we were calling old handlers to preserve existing work flows.

{
"compilerOptions": {
"module": "commonjs",
"target": "es6",
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We actually have to target es3 everywhere :.

@niemyjski
Copy link
Collaborator

Looks good, I added two comments on things, if we feel we are good I'll merge it in.

@niemyjski
Copy link
Collaborator

@aquadk Could you please review the feedback so we can take your great work and get it merged in.

declare global {
interface Window {
onunhandledrejection: PromiseRejectionEvent;
_onErrorHandlerInstalled : boolean;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we really need to expose this private var?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think so.

@niemyjski
Copy link
Collaborator

Can we get this updated so we can get it merged in.

2 similar comments
@niemyjski
Copy link
Collaborator

Can we get this updated so we can get it merged in.

@niemyjski
Copy link
Collaborator

Can we get this updated so we can get it merged in.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants