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

fix(plugin-inline-script-content): Call previous onreadystatechange callback #426

Merged
merged 2 commits into from
Nov 27, 2018

Conversation

bengourley
Copy link
Contributor

The inline script plugin waits for the document to be "ready" before it scrapes the content of the <html> element. This listens to the document.onreadystatechange event, which may already have a handler attached. This change stores a reference to any previous handler and calls it if it is a
function.

This fixes a reported bug where initializing Bugsnag after Pace.js causes Pace.js to malfunction.

Testing

To verify this works, you can use the following example. Serve it on localhost and drop in pace.js and bugsnag.js into a static directory alongside. Using an existing version of Bugsnag, you should see the progressbar never reaches the right hand side of the page. Using a version of Bugsnag built from this branch, it should successfully reach the right hand side when the slow "image" has loaded. A built version of Bugsnag is attached to this PR for convenience.

<!DOCTYPE html>
<html>
  <head>
    <title>This is a title</title>
    <script src="static/pace.js"></script>
    <script src="static/bugsnag.js"></script>
    <script>window.bugsnagClient = bugsnag('API_KEY')</script>
    <style>
    .pace { -webkit-pointer-events: none; pointer-events: none; -webkit-user-select: none; -moz-user-select: none; user-select: none; }
    .pace-inactive { display: none; }
    .pace .pace-progress { background: #29d; position: fixed; z-index: 2000; top: 0; right: 100%; width: 100%; height: 2px; }
    </style>
  </head>
  <body>
    <img src="https://httpstat.us/200?sleep=5000" />
    <script>
      bugsnagClient.notify(new Error('inline'))
    </script>
  </body>
</html>
bugsnag.js built from this branch
!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{("undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this).bugsnag=e()}}(function(){var t=function(e,t,n){for(var r=n,i=0,o=e.length;i"].indexOf(n[0])?undefined:n[0];return new s({functionName:r,fileName:i,lineNumber:n[1],columnNumber:n[2],source:e})},this)},parseFFOrSafari:function(e){return e.stack.split("\n").filter(function(e){return!e.match(r)},this).map(function(e){if(-1 eval")&&(e=e.replace(/ line (\d+)(?: > eval line \d+)* > eval\:\d+\:\d+/g,":$1")),-1===e.indexOf("@")&&-1===e.indexOf(":"))return new s({functionName:e});var t=/((.*".+"[^@]*)?[^@]*)(?:@)/,n=e.match(t),r=n&&n[1]?n[1]:undefined,i=this.extractLocation(e.replace(t,""));return new s({functionName:r,fileName:i[0],lineNumber:i[1],columnNumber:i[2],source:e})},this)},parseOpera:function(e){return!e.stacktrace||-1e.stacktrace.split("\n").length?this.parseOpera9(e):e.stack?this.parseOpera11(e):this.parseOpera10(e)},parseOpera9:function(e){for(var t=/Line (\d+).*script (?:in )?(\S+)/i,n=e.message.split("\n"),r=[],i=2,o=n.length;i/,"$2").replace(/\([^\)]*\)/g,"")||undefined;i.match(/\(([^\)]*)\)/)&&(t=i.replace(/^[^\(]+\(([^\)]*)\)$/,"$1"));var a=t===undefined||"[arguments not available]"===t?undefined:t.split(",");return new s({functionName:o,args:a,fileName:r[0],lineNumber:r[1],columnNumber:r[2],source:e})},this)}}});var D={};function C(){return(C=Object.assign||function(e){for(var t=1;tthis.config.maxBreadcrumbs&&(this.breadcrumbs=this.breadcrumbs.slice(this.breadcrumbs.length-this.config.maxBreadcrumbs)),this}},e.notify=function(e,t,n){var r=this;if(void 0===t&&(t={}),void 0===n&&(n=function(){}),!this._configured)throw new Error("client not configured");var i=k(this),o=le(e,t,this._logger),a=o.err,s=o.errorFramesToSkip,u=o._opts;if(u&&(t=u),!a){var c=ge("nothing");this._logger.warn(ue+" "+c),a=new Error(ce+" "+c)}"object"==typeof t&&null!==t||(t={});var f=$.ensureReport(a,s,1);if(f.app=ie({},{releaseStage:i},f.app,this.app),f.context=f.context||t.context||this.context||undefined,f.device=ie({},f.device,this.device,t.device),f.request=ie({},f.request,this.request,t.request),f.user=ie({},f.user,this.user,t.user),f.metaData=ie({},f.metaData,this.metaData,t.metaData),f.breadcrumbs=this.breadcrumbs.slice(0),this._session&&(this._session.trackError(f),f.session=this._session),t.severity!==undefined&&(f.severity=t.severity,f._handledState.severityReason={type:"userSpecifiedSeverity"}),se(this.config.notifyReleaseStages)&&!ae(this.config.notifyReleaseStages,i))return this._logger.warn("Report not sent due to releaseStage/notifyReleaseStages configuration"),!1;var l,d,p,g,h,v,m,y,b=f.severity,w=[].concat(t.beforeSend).concat(this.config.beforeSend),S=function(e){r._logger.error("Error occurred in beforeSend callback, continuing anyway…"),r._logger.error(e)};m=f,y=S,d=function(e,n){if("function"!=typeof e)return n(null,!1);try{if(2!==e.length){var t=e(m);return t&&"function"==typeof t.then?t.then(function(e){return setTimeout(function(){return n(null,R(m,e))},0)},function(e){setTimeout(function(){return y(e),n(null,!1)})}):n(null,R(m,t))}e(m,function(e,t){if(e)return y(e),n(null,!1);n(null,R(m,t))})}catch(r){y(r),n(null,!1)}},p=function(e,t){if(e&&S(e),t)return r._logger.debug("Report not sent due to beforeSend callback"),!1;r.config.autoBreadcrumbs&&r.leaveBreadcrumb(f.errorClass,{errorClass:f.errorClass,errorMessage:f.errorMessage,severity:f.severity,stacktrace:f.stacktrace},"error"),b!==f.severity&&(f._handledState.severityReason={type:"userCallbackSetSeverity"}),r._delivery.sendReport(r._logger,r.config,{apiKey:f.apiKey||r.config.apiKey,notifier:r.notifier,events:[f]},function(e){return n(e,f)})},g=(l=w).length,h=0,(v=function(){if(g<=h)return p(null,!1);d(l[h],function(e,t){return e?p(e,!1):!0===t?p(null,!0):(h++,void v())})})()},r}(),le=function(e,t,n){var r,i,o=0;switch(typeof e){case"string":if("string"==typeof t){var a=ge("string/string");n.warn(ue+" "+a),r=new Error(ce+" "+a),i={metaData:{notifier:{notifyArgs:[e,t]}}}}else r=new Error(String(e)),o+=2;break;case"number":case"boolean":r=new Error(String(e));break;case"function":var s=ge("function");n.warn(ue+" "+s),r=new Error(ce+" "+s);break;case"object":if(null!==e&&(x(e)||e.__isBugsnagReport))r=e;else if(null!==e&&de(e))(r=new Error(e.message||e.errorMessage)).name=e.name||e.errorClass,o+=2;else{var u=ge("unsupported object");n.warn(ue+" "+u),r=new Error(ce+" "+u)}}return{err:r,errorFramesToSkip:o,_opts:i}},de=function(e){return!("string"!=typeof e.name&&"string"!=typeof e.errorClass||"string"!=typeof e.message&&"string"!=typeof e.errorMessage)},pe=function(e){return"Bugsnag configuration error\n"+oe(e,function(e){return'"'+e.key+'" '+e.message+" \n    got "+he(e.value)}).join("\n\n")},ge=function(e){return"notify() expected error/opts parameters, got "+e},he=function(e){return"object"==typeof e?JSON.stringify(e):String(e)},ve=fe,me=function(e,t,n,r){var i=r&&r.filterKeys?r.filterKeys:[],o=r&&r.filterPaths?r.filterPaths:[];return JSON.stringify(function a(e,d,p){var g=[],h=0;return function v(e,t){function n(){return t.length>we&&beye)return Se;if(n())return Se;if(null===e||"object"!=typeof e)return e;if(Ne(g,e))return"[Circular]";g.push(e);if("function"==typeof e.toJSON)try{h--;var r=v(e.toJSON(),t);return g.pop(),r}catch(f){return Oe(f)}if(s=e,"[object Array]"===Object.prototype.toString.call(s)){for(var i=[],o=0,a=e.length;o/,nt=/<\/script>.*$/,rt=(Qe={init:function(e,t,n){void 0===t&&(t=document),void 0===n&&(n=window);var s="",u=!1,c=function(){return t.documentElement.outerHTML},f=n.location.href;s=c();var r=t.onreadystatechange;t.onreadystatechange=function(){"interactive"===t.readyState&&(s=c(),u=!0),"function"==typeof r&&r.apply(this,arguments)},e.config.beforeSend.unshift(function(e){var r=e.stacktrace[0];if(!r||!r.file||!r.lineNumber)return r;if(r.file.replace(/#.*$/,"")!==f.replace(/#.*$/,""))return r;u&&s||(s=c());var t=["\x3c!-- DOC START --\x3e"].concat(s.split("\n")),n=rt(t,r.lineNumber-1),i=n.script,o=n.start,a=et(i,function(e,t,n){return 10 "+n.join("");return n.join("")}(e.target,a)}catch(r){n=t="[hidden]",i._logger.error("Cross domain error when tracking click event. See docs: https://tinyurl.com/y94fq5zm")}i.leaveBreadcrumb("UI click",{targetText:t,targetSelector:n},"user")},!0)},configSchema:{interactionBreadcrumbsEnabled:{defaultValue:function(){return undefined},validate:function(e){return!0===e||!1===e||e===undefined},message:"should be true|false"}}},ot=function(e){var t=e.textContent||e.innerText||"";return t||"submit"!==e.type&&"button"!==e.type||(t=e.value),function n(e,t){return e&&e.length<=t?e:e.slice(0,t-"(...)".length)+"(...)"}(t=t.replace(/^\s+|\s+$/g,""),140)};var at={init:function(n,r){if(void 0===r&&(r=window),"addEventListener"in r){var e=function(e){return function(){return n.leaveBreadcrumb(e,{},"navigation")}};r.addEventListener("pagehide",e("Page hidden"),!0),r.addEventListener("pageshow",e("Page shown"),!0),r.addEventListener("load",e("Page loaded"),!0),r.document.addEventListener("DOMContentLoaded",e("DOMContentLoaded"),!0),r.addEventListener("load",function(){return r.addEventListener("popstate",e("Navigated back"),!0)}),r.addEventListener("hashchange",function(e){var t=e.oldURL?{from:ct(e.oldURL,r),to:ct(e.newURL,r),state:lt(r)}:{to:ct(r.location.href,r)};n.leaveBreadcrumb("Hash changed",t,"navigation")},!0),r.history.replaceState&&ft(n,r.history,"replaceState",r),r.history.pushState&&ft(n,r.history,"pushState",r),n.leaveBreadcrumb("Bugsnag loaded",{},"navigation")}}};at.configSchema={navigationBreadcrumbsEnabled:{defaultValue:function(){return undefined},validate:function(e){return!0===e||!1===e||e===undefined},message:"should be true|false"}};var st,ut,ct=function(e,t){var n=t.document.createElement("A");return n.href=e,""+n.pathname+n.search+n.hash},ft=function(u,c,f,l){var d=c[f];c[f]=function(e,t,n){var r,i,o,a,s;u.leaveBreadcrumb("History "+f,(i=e,o=t,a=n,s=ct((r=l).location.href,r),{title:o,state:i,prevState:lt(r),to:a||s,from:s}),"navigation"),"function"==typeof u.refresh&&u.refresh(),u.session&&u.startSession(),d.apply(c,[e,t].concat(n!==undefined?n:[]))},c[f]._restore=function(){c[f]=d}},lt=function(e){try{return e.history.state}catch(t){}},dt={},pt="request",gt="BS~~U",ht="BS~~M",vt=s,mt=function(){return[st.config.endpoints.notify,st.config.endpoints.sessions]};dt.init=function(e,t){void 0===t&&(t=window),st=e,ut=t,yt(),St()},dt.configSchema={networkBreadcrumbsEnabled:{defaultValue:function(){return undefined},validate:function(e){return!0===e||!1===e||e===undefined},message:"should be true|false"}};var yt=function(){if("addEventListener"in ut.XMLHttpRequest.prototype){var n=ut.XMLHttpRequest.prototype.open;ut.XMLHttpRequest.prototype.open=function(e,t){this[gt]=t,this[ht]=e,this["BS~~S"]&&(this.removeEventListener("load",bt),this.removeEventListener("error",wt)),this.addEventListener("load",bt),this.addEventListener("error",wt),this["BS~~S"]=!0,n.apply(this,arguments)}}};function bt(){if(!vt(mt(),this[gt])){var e={status:this.status,request:this[ht]+" "+this[gt]};400<=this.status?st.leaveBreadcrumb("XMLHttpRequest failed",e,pt):st.leaveBreadcrumb("XMLHttpRequest succeeded",e,pt)}}function wt(){vt(mt(),this[gt])||st.leaveBreadcrumb("XMLHttpRequest error",{request:this[ht]+" "+this[gt]},pt)}var St=function(){if("fetch"in ut){var a=ut.fetch;ut.fetch=function(){for(var e=arguments.length,r=new Array(e),t=0;t=t.config.maxEvents)return e.ignore();n++}),t.refresh=function(){n=0}},configSchema:{maxEvents:{defaultValue:function(){return 10},message:"should be a positive integer ≤100",validate:function(e){return jt(1,100)(e)}}}},kt={};function Rt(){return(Rt=Object.assign||function(e){for(var t=1;t"].indexOf(n[0])?undefined:n[0];return new s({functionName:r,fileName:i,lineNumber:n[1],columnNumber:n[2],source:e})},this)},parseFFOrSafari:function(e){return e.stack.split("\n").filter(function(e){return!e.match(r)},this).map(function(e){if(-1 eval")&&(e=e.replace(/ line (\d+)(?: > eval line \d+)* > eval\:\d+\:\d+/g,":$1")),-1===e.indexOf("@")&&-1===e.indexOf(":"))return new s({functionName:e});var t=/((.*".+"[^@]*)?[^@]*)(?:@)/,n=e.match(t),r=n&&n[1]?n[1]:undefined,i=this.extractLocation(e.replace(t,""));return new s({functionName:r,fileName:i[0],lineNumber:i[1],columnNumber:i[2],source:e})},this)},parseOpera:function(e){return!e.stacktrace||-1e.stacktrace.split("\n").length?this.parseOpera9(e):e.stack?this.parseOpera11(e):this.parseOpera10(e)},parseOpera9:function(e){for(var t=/Line (\d+).*script (?:in )?(\S+)/i,n=e.message.split("\n"),r=[],i=2,o=n.length;i/,"$2").replace(/\([^\)]*\)/g,"")||undefined;i.match(/\(([^\)]*)\)/)&&(t=i.replace(/^[^\(]+\(([^\)]*)\)$/,"$1"));var a=t===undefined||"[arguments not available]"===t?undefined:t.split(",");return new s({functionName:o,args:a,fileName:r[0],lineNumber:r[1],columnNumber:r[2],source:e})},this)}}});var qt=function Kt(e){switch(Object.prototype.toString.call(e)){case"[object Error]":case"[object Exception]":case"[object DOMException]":return!0;default:return e instanceof Error}};var Tt={},At=r;Tt.init=function(o,e){void 0===e&&(e=window);var n=function(e){var t=e.reason,n=!1;e.detail&&e.detail.reason&&(t=e.detail.reason,n=!0);var r,i={severity:"error",unhandled:!0,severityReason:{type:"unhandledPromiseRejection"}};if(t&&_(t))r=new o.BugsnagReport(t.name,t.message,Ct.parse(t),i),n&&(r.stacktrace=At(r.stacktrace,Vt(t),[]));else{(r=new o.BugsnagReport(t&&t.name?t.name:"UnhandledRejection",t&&t.message?t.message:'Rejection reason was not an Error. See "Promise" tab for more detail.',[],i)).updateMetaData("promise","rejection reason",Pt(t))}o.notify(r)};"addEventListener"in e?e.addEventListener("unhandledrejection",n):e.onunhandledrejection=function(e,t){n({detail:{reason:e,promise:t}})},n};var Mt,Pt=function(e){return null===e||e===undefined?"undefined (or null)":qt(e)?((t={})[Object.prototype.toString.call(e)]={name:e.name,message:e.message,code:e.code,stack:e.stack},t):e;var t},Vt=function(n){return function(e,t){return t.file===n.toString()?e:(t.method&&(t.method=t.method.replace(/^\s+/,"")),e.concat(t))}};function Ft(){return(Ft=Object.assign||function(e){for(var t=1;t

…allback

The inline script plugin waits for the document to be "ready" before it scrapes the content of the
<html> element. This listens to the document.onreadystatechange event, which may already have a
handler attached. This change stores a reference to any previous handler and calls it if it is a
function.
@bengourley bengourley requested a review from a team November 23, 2018 15:58
Copy link
Contributor

@Cawllec Cawllec left a comment

Choose a reason for hiding this comment

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

LGTM - Tested and works as stated

@bengourley bengourley merged commit 2d1b997 into universal Nov 27, 2018
@bengourley bengourley deleted the u/document-onreadystatechange-prev-handler branch November 27, 2018 17:32
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.

None yet

2 participants