@react-native/debugger-frontend
Version:
Debugger frontend for React Native based on Chrome DevTools
2 lines (1 loc) • 6.75 kB
JavaScript
import*as t from"../../../core/platform/platform.js";import*as e from"../helpers/helpers.js";import*as n from"../types/types.js";const o=new Map,s=new Map;const a=new Set(["non_blocking","potentially_blocking"]);function i(t,e){return!a.has(t.args.data.renderBlocking)&&t.args.data.frame===e}class r{#t;#e=new Map;#n=new Map;#o;constructor(t,e){this.#t=t,this.#o=e?.enableIframeRootCauses??!1}async rootCausesForEvent(e,n){const o=this.#e.get(n);if(o)return o;const s=e.LayoutShifts.clusters.flatMap((t=>t.events));s.forEach((e=>function(e,n){t.MapUtilities.getWithDefault(e,n,(()=>({unsizedMedia:[],iframes:[],fontChanges:[],renderBlockingRequests:[],scriptStackTrace:[]})))}(this.#e,e))),await this.blameShifts(s,e);const a=this.#e.get(n);return a||null}async blameShifts(t,e){await this.linkShiftsToLayoutInvalidations(t,e),this.linkShiftsToLayoutEvents(t,e)}async linkShiftsToLayoutInvalidations(e,o){const{prePaintEvents:s,layoutInvalidationEvents:a,scheduleStyleInvalidationEvents:i,backendNodeIds:r}=o.LayoutShifts,u=[...a,...i],c=await this.#t.pushNodesByBackendIdsToFrontend(r),l=new Map;for(let t=0;t<r.length;t++)l.set(r[t],c[t]);const f=d(e,s);for(const e of u){const a=t.ArrayUtilities.nearestIndexFromBeginning(s,(t=>t.ts>e.ts));if(null===a)continue;const i=s[a],r=f.get(i);if(!r)continue;const u=this.getFontChangeRootCause(e,i,o),c=this.getRenderBlockRootCause(e,i,o),d=l.get(e.args.data.nodeId);let h=null,g=null;if(void 0!==d&&n.TraceEvents.isTraceEventLayoutInvalidationTracking(e)&&(h=await this.getUnsizedMediaRootCause(e,d),g=await this.getIframeRootCause(e,d)),h||g||u||c)for(const n of r){const o=t.MapUtilities.getWithDefault(this.#e,n,(()=>({unsizedMedia:[],iframes:[],fontChanges:[],renderBlockingRequests:[],scriptStackTrace:[]})));h&&!o.unsizedMedia.some((t=>t.node.nodeId===h?.node.nodeId))&&n.args.frame===e.args.data.frame&&o.unsizedMedia.push(h),g&&!o.iframes.some((t=>t.iframe.nodeId===g?.iframe.nodeId))&&o.iframes.push(g),u&&(o.fontChanges=u),c&&(o.renderBlockingRequests=c)}}}linkShiftsToLayoutEvents(e,n){const{prePaintEvents:o}=n.LayoutShifts,s=d(e,o),a=n.Renderer.allTraceEntries.filter((({name:t})=>"Layout"===t));for(const e of a){const a=t.ArrayUtilities.nearestIndexFromBeginning(o,(t=>t.ts>e.ts+(e.dur||0)));if(null===a)continue;const i=o[a],r=s.get(i);if(!r)continue;const u=n.Renderer.entryToNode.get(e),c=u?n.Initiators.eventToInitiator.get(u.entry):null,l=c?.args?.data?.stackTrace;if(l)for(const e of r){const n=t.MapUtilities.getWithDefault(this.#e,e,(()=>({unsizedMedia:[],iframes:[],fontChanges:[],renderBlockingRequests:[],scriptStackTrace:[]})));0===n.scriptStackTrace.length&&(n.scriptStackTrace=l)}}}async getUnsizedMediaRootCause(t,e){if("Size changed"!==t.args.data.reason)return null;const n=await this.getNodeDetails(e);if(!n)return null;const o=await this.#t.getComputedStyleForNode(n.nodeId),s=new Map(o.map((t=>[t.name,t.value])));if(s&&!await async function(t,e){const n=t.localName,o=function(t){const e=/^url\("([^"]+)"\)$/,n=t.get("background-image");if(!n)return!1;return e.test(n)}(e);if("img"!==n&&"video"!==n&&!o)return!1;return!function(t){const e=t.get("position");if(!e)return!1;return"fixed"===e||"absolute"===e}(e)}(n,s))return null;const a=await this.getNodeAuthoredDimensions(n);if(function(t){const{height:e,width:n,aspectRatio:o}=t,s=Boolean(e&&c(e)),a=Boolean(n&&c(n)),i=Boolean(o&&c(o)),r=(s||a)&&i;return s&&a||r}(a))return null;return{node:n,authoredDimensions:a,computedDimensions:s?function(t){const e={};return e.height=t.get("height"),e.width=t.get("width"),e.aspectRatio=t.get("aspect-ratio"),e}(s):{}}}async getIframeRootCause(t,e){if(!this.#o)return null;if(!t.args.data.nodeName?.startsWith("IFRAME")&&"Style changed"!==t.args.data.reason&&"Added to layout"!==t.args.data.reason)return null;const n=await this.getNodeDetails(e);if(!n)return null;const o=u(n);return o?{iframe:o}:null}async getNodeDetails(t){let e=this.#n.get(t);return void 0!==e||(e=await this.#t.getNode(t),this.#n.set(t,e)),e}requestsInInvalidationWindow(o,s){const a=s.NetworkRequests.byTime.sort(((t,e)=>t.ts+t.dur-(e.ts+e.dur))),i=t.ArrayUtilities.nearestIndexFromEnd(a,(t=>t.ts+t.dur<o.ts));if(null===i)return[];const r=e.Timing.secondsToMicroseconds(n.Timing.Seconds(.5)),u=[];for(let t=i;t>-1;t--){const e=a[t],n=e.ts+e.dur;if(!(o.ts-n<r))break;{const t={request:e},n=this.#t.getInitiatorForRequest(e.args.data.url);t.initiator=n||void 0,u.push(t)}}return u}getFontChangeRootCause(t,e,n){if("Fonts changed"!==t.args.data.reason)return null;const s=o.get(e);if(void 0!==s)return s;const a=this.getFontRequestsInInvalidationWindow(this.requestsInInvalidationWindow(t,n));return o.set(e,a),a}getFontRequestsInInvalidationWindow(t){const e=[];for(let n=0;n<t.length;n++){const o=t[n];if(!o.request.args.data.mimeType.startsWith("font"))continue;const s=this.#t.fontFaceForSource(o.request.args.data.url);s&&"optional"!==s.fontDisplay&&(o.fontFace=s,e.push(o))}return e}getRenderBlockRootCause(t,e,n){const o=s.get(e);if(void 0!==o)return o;const a=function(t){const e=[];for(let n=0;n<t.length;n++){const o=t[n].request.args.data.frame;i(t[n].request,o)&&e.push(t[n])}return e}(this.requestsInInvalidationWindow(t,n));return s.set(e,a),a}async nodeMatchedStylesPropertyGetter(t){const e=await this.#t.getMatchedStylesForNode(t.nodeId);return function(t){let n=e.inlineStyle?.cssProperties.find((e=>e.name===t));if(n)return n.value;for(const{rule:n}of e.matchedCSSRules||[]){const e=n.style.cssProperties.find((e=>e.name===t));if(e)return e.value}return n=e.attributesStyle?.cssProperties.find((e=>e.name===t)),n?n.value:null}}async getNodeAuthoredDimensions(t){const e={},n=await this.nodeMatchedStylesPropertyGetter(t);if(!n)return e;const o=t.attributes||[],s=[];for(let t=0;t<o.length;t+=2)s.push({name:o[t],value:o[t+1]});const a=s.find((t=>"height"===t.name&&l(t))),i=s.find((t=>"width"===t.name&&l(t))),r=n("aspect-ratio")||void 0;if(a&&i&&r)return{height:a.value,width:i.value,aspectRatio:r};return{height:n("height")||void 0,width:n("width")||void 0,aspectRatio:r}}}function u(t){if("IFRAME"===t.nodeName)return t;const e=t.children;if(!e)return null;for(const t of e){const e=u(t);if(e)return e}return null}function c(t){return!["auto","initial","unset","inherit"].includes(t)}function l(t){return parseInt(t.value,10)>=0}function d(e,n){const o=new Map;for(const s of n){const n=t.ArrayUtilities.nearestIndexFromBeginning(e,(t=>t.ts>=s.ts));if(null!==n)for(let a=n;a<e.length;a++){const n=e[a];if(n.ts>=s.ts&&n.ts<=s.ts+s.dur){t.MapUtilities.getWithDefault(o,s,(()=>[])).push(n)}if(n.ts>s.ts+s.dur)break}}return o}var f=Object.freeze({__proto__:null,RootCauses:class{layoutShifts;constructor(t){this.layoutShifts=new r(t)}},LayoutShiftRootCauses:r});export{f as RootCauses};